// // TextLayoutBackendHandler.cs // // Author: // Lluis Sanchez // Lytico (http://limada.sourceforge.net) // // Copyright (c) 2011 Xamarin Inc // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in // all copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN // THE SOFTWARE. using System; using Xwt.Backends; using Xwt.Drawing; using Xwt.CairoBackend; using System.Collections.Generic; using System.Runtime.InteropServices; namespace Xwt.GtkBackend { public class GtkTextLayoutBackendHandler: TextLayoutBackendHandler { static Cairo.Context SharedContext; public double Heigth = -1; internal class PangoBackend : IDisposable { Pango.Layout layout; public Pango.Layout Layout { get { if (hasUnassignedAttributes) { attributes.AssignTo (layout); hasUnassignedAttributes = false; } return layout; } set { layout = value; } } FastPangoAttrList attributes; bool hasUnassignedAttributes = false; public FastPangoAttrList Attributes { get { if (attributes == null) attributes = new FastPangoAttrList (); hasUnassignedAttributes = true; return attributes; } private set { attributes = value; } } string text = String.Empty; public string Text { get { return text; } set { text = value ?? String.Empty;; indexer = null; ClearAttributes (); } } TextIndexer indexer; public TextIndexer TextIndexer { get { if (indexer == null) indexer = new TextIndexer (Text); return indexer; } } public void ClearAttributes () { if (attributes != null) { attributes.Dispose (); attributes = new FastPangoAttrList (); hasUnassignedAttributes = true; } } public void Dispose () { if (layout != null) { layout.Dispose (); layout = null; } if (attributes != null) { attributes.Dispose (); attributes = null; } } } static GtkTextLayoutBackendHandler () { using (Cairo.Surface sf = new Cairo.ImageSurface (Cairo.Format.ARGB32, 1, 1)) { SharedContext = new Cairo.Context (sf); } } public static void DisposeResources () { ((IDisposable)SharedContext).Dispose (); } public override object Create () { return new PangoBackend { Layout = Pango.CairoHelper.CreateLayout (SharedContext) }; } public override void SetText (object backend, string text) { var tl = (PangoBackend) backend; text = text ?? String.Empty; tl.Layout.SetText (text); tl.Text = text; } public override void SetFont (object backend, Xwt.Drawing.Font font) { var tl = (PangoBackend)backend; tl.Layout.FontDescription = (Pango.FontDescription)ApplicationContext.Toolkit.GetSafeBackend (font); } public override void SetWidth (object backend, double value) { var tl = (PangoBackend) backend; tl.Layout.Width = (int) (value * Pango.Scale.PangoScale); } public override void SetHeight (object backend, double value) { this.Heigth = value; } public override void SetAlignment (object backend, Alignment alignment) { var tl = (PangoBackend)backend; tl.Layout.Alignment = alignment.ToPangoAlignment (); } public override void SetTrimming (object backend, TextTrimming textTrimming) { var tl = (PangoBackend)backend; if (textTrimming == TextTrimming.WordElipsis) tl.Layout.Ellipsize = Pango.EllipsizeMode.End; if (textTrimming == TextTrimming.Word) tl.Layout.Ellipsize = Pango.EllipsizeMode.None; } public override Size GetSize (object backend) { var tl = (PangoBackend)backend; int w, h; tl.Layout.GetPixelSize (out w, out h); return new Size ((double)w, (double)h); } public override void AddAttribute (object backend, TextAttribute attribute) { var tl = (PangoBackend) backend; tl.Attributes.AddAttribute (tl.TextIndexer, attribute); } public override void ClearAttributes (object backend) { var tl = (PangoBackend) backend; tl.ClearAttributes (); } public override int GetIndexFromCoordinates (object backend, double x, double y) { var tl = (PangoBackend) backend; int index, trailing; tl.Layout.XyToIndex ((int)x, (int)y, out index, out trailing); return tl.TextIndexer.ByteIndexToIndex (index); } public override Point GetCoordinateFromIndex (object backend, int index) { var tl = (PangoBackend) backend; var pos = tl.Layout.IndexToPos (tl.TextIndexer.IndexToByteIndex (index)); return new Point (pos.X / Pango.Scale.PangoScale, pos.Y / Pango.Scale.PangoScale); } public override double GetBaseline (object backend) { var tl = (PangoBackend) backend; // Just get the first line using (var iter = tl.Layout.Iter) return Pango.Units.ToPixels (iter.Baseline); } public override double GetMeanline (object backend) { var tl = (PangoBackend)backend; var baseline = 0; using (var iter = tl.Layout.Iter) baseline = iter.Baseline; var font = tl.Layout.Context.LoadFont (tl.Layout.FontDescription); return Pango.Units.ToPixels (baseline - font.GetMetrics (Pango.Language.Default).StrikethroughPosition); } public override void Dispose (object backend) { var tl = (IDisposable) backend; tl.Dispose (); } } }