diff --git a/Cairo/Perspex.Cairo/CairoExtensions.cs b/Cairo/Perspex.Cairo/CairoExtensions.cs index f6f8502cac..963d2fe980 100644 --- a/Cairo/Perspex.Cairo/CairoExtensions.cs +++ b/Cairo/Perspex.Cairo/CairoExtensions.cs @@ -24,5 +24,14 @@ namespace Perspex.Cairo { return new Cairo.Rectangle(rect.X, rect.Y, rect.Width, rect.Height); } + + public static Rect ToPerspex(this Pango.Rectangle rect) + { + return new Rect( + Pango.Units.ToDouble(rect.X), + Pango.Units.ToDouble(rect.Y), + Pango.Units.ToDouble(rect.Width), + Pango.Units.ToDouble(rect.Height)); + } } } \ No newline at end of file diff --git a/Cairo/Perspex.Cairo/CairoPlatform.cs b/Cairo/Perspex.Cairo/CairoPlatform.cs index 2b1016a2e6..cb5e10019e 100644 --- a/Cairo/Perspex.Cairo/CairoPlatform.cs +++ b/Cairo/Perspex.Cairo/CairoPlatform.cs @@ -10,6 +10,7 @@ namespace Perspex.Cairo using global::Cairo; using Perspex.Cairo.Media; using Perspex.Cairo.Media.Imaging; + using Perspex.Media; using Perspex.Platform; using Perspex.Threading; using Splat; @@ -30,8 +31,18 @@ namespace Perspex.Cairo ////return new BitmapImpl(imagingFactory, width, height); } + public IFormattedTextImpl CreateFormattedText( + string text, + string fontFamily, + double fontSize, + FontStyle fontStyle) + { + return new FormattedTextImpl(text, fontFamily, fontSize, fontStyle); + } + public IRenderer CreateRenderer(IPlatformHandle handle, double width, double height) { + Locator.CurrentMutable.RegisterConstant(this.GetPangoContext(handle), typeof(Pango.Context)); return new Renderer(handle, width, height); } diff --git a/Cairo/Perspex.Cairo/Media/DrawingContext.cs b/Cairo/Perspex.Cairo/Media/DrawingContext.cs index 830d2b2f29..5b79613e21 100644 --- a/Cairo/Perspex.Cairo/Media/DrawingContext.cs +++ b/Cairo/Perspex.Cairo/Media/DrawingContext.cs @@ -133,14 +133,14 @@ namespace Perspex.Cairo.Media /// Draws text. /// /// The foreground brush. - /// The output rectangle. + /// The upper-left corner of the text. /// The text. - public void DrawText(Perspex.Media.Brush foreground, Rect rect, FormattedText text) + public void DrawText(Brush foreground, Point origin, FormattedText text) { - ////var layout = this.textService.CreateLayout(text); - ////this.SetBrush(foreground); - ////this.context.MoveTo(rect.X, rect.Y); - ////Pango.CairoHelper.ShowLayout(this.context, layout); + var layout = ((FormattedTextImpl)text.PlatformImpl).Layout; + this.SetBrush(foreground); + this.context.MoveTo(origin.X, origin.Y); + Pango.CairoHelper.ShowLayout(this.context, layout); } /// diff --git a/Cairo/Perspex.Cairo/Media/FormattedTextImpl.cs b/Cairo/Perspex.Cairo/Media/FormattedTextImpl.cs new file mode 100644 index 0000000000..7dc670b37a --- /dev/null +++ b/Cairo/Perspex.Cairo/Media/FormattedTextImpl.cs @@ -0,0 +1,97 @@ +// ----------------------------------------------------------------------- +// +// Copyright 2014 MIT Licence. See licence.md for more information. +// +// ----------------------------------------------------------------------- + +namespace Perspex.Cairo.Media +{ + using System; + using System.Collections.Generic; + using System.Linq; + using Perspex.Media; + using Perspex.Platform; + using Splat; + + public class FormattedTextImpl : IFormattedTextImpl + { + public FormattedTextImpl( + string text, + string fontFamily, + double fontSize, + FontStyle fontStyle) + { + var context = Locator.Current.GetService(); + this.Layout = new Pango.Layout(context); + this.Layout.SetText(text); + this.Layout.FontDescription = new Pango.FontDescription + { + Family = fontFamily, + Size = Pango.Units.FromDouble(fontSize), + Style = (Pango.Style)fontStyle, + }; + } + + public Size Constraint + { + get + { + return new Size(this.Layout.Width, double.PositiveInfinity); + } + + set + { + this.Layout.Width = Pango.Units.FromDouble(value.Width); + } + } + + public Pango.Layout Layout + { + get; + private set; + } + + public void Dispose() + { + this.Layout.Dispose(); + } + + public TextHitTestResult HitTestPoint(Point point) + { + int textPosition; + int trailing; + + var isInside = this.Layout.XyToIndex( + Pango.Units.FromDouble(point.X), + Pango.Units.FromDouble(point.Y), + out textPosition, + out trailing); + + return new TextHitTestResult + { + IsInside = isInside, + TextPosition = textPosition, + IsTrailing = trailing == 0, + }; + } + + public Rect HitTestTextPosition(int index) + { + return this.Layout.IndexToPos(index).ToPerspex(); + } + + public IEnumerable HitTestTextRange(int index, int length, Point origin) + { + // TODO: Implement. + return new Rect[0]; + } + + public Size Measure() + { + int width; + int height; + this.Layout.GetPixelSize(out width, out height); + return new Size(width, height); + } + } +} diff --git a/Cairo/Perspex.Cairo/Perspex.Cairo.csproj b/Cairo/Perspex.Cairo/Perspex.Cairo.csproj index a9e2222701..12985d10b8 100644 --- a/Cairo/Perspex.Cairo/Perspex.Cairo.csproj +++ b/Cairo/Perspex.Cairo/Perspex.Cairo.csproj @@ -67,6 +67,7 @@ + diff --git a/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs b/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs index 1ce6cfb357..c01c8b03d0 100644 --- a/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs +++ b/Gtk/Perspex.Gtk/Input/GtkKeyboardDevice.cs @@ -29,7 +29,11 @@ namespace Perspex.Gtk public override ModifierKeys Modifiers { - get { throw new System.NotImplementedException(); } + get + { + // TODO: Implement. + return ModifierKeys.None; + } } public static Perspex.Input.Key ConvertKey(Gdk.Key key) diff --git a/Perspex.SceneGraph/Media/TextHitTestResult.cs b/Perspex.SceneGraph/Media/TextHitTestResult.cs index 64ee08a55d..fee1d1abc4 100644 --- a/Perspex.SceneGraph/Media/TextHitTestResult.cs +++ b/Perspex.SceneGraph/Media/TextHitTestResult.cs @@ -8,6 +8,8 @@ namespace Perspex.Media { public class TextHitTestResult { + public bool IsInside { get; set; } + public int TextPosition { get; set; } public bool IsTrailing { get; set; } diff --git a/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs b/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs index edf9888a24..fbd166cb7e 100644 --- a/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs +++ b/Windows/Perspex.Direct2D1/Media/FormattedTextImpl.cs @@ -70,6 +70,7 @@ namespace Perspex.Direct2D1.Media return new TextHitTestResult { + IsInside = isInside, TextPosition = result.TextPosition, IsTrailing = isTrailingHit, };