From 45f74150dd79db5a162034ab0c43e6abdb83beea Mon Sep 17 00:00:00 2001 From: jpbruyere Date: Wed, 15 Mar 2017 05:59:51 +0100 Subject: split graphic objects dir --- src/GraphicObjects/Base/TextRun.cs | 315 +++++++++++++++++++++++++++++++++++++ 1 file changed, 315 insertions(+) create mode 100644 src/GraphicObjects/Base/TextRun.cs (limited to 'src/GraphicObjects/Base/TextRun.cs') diff --git a/src/GraphicObjects/Base/TextRun.cs b/src/GraphicObjects/Base/TextRun.cs new file mode 100644 index 00000000..a312ca1e --- /dev/null +++ b/src/GraphicObjects/Base/TextRun.cs @@ -0,0 +1,315 @@ +// +// TextRun.cs +// +// Author: +// Jean-Philippe Bruyère +// +// Copyright (c) 2013-2017 Jean-Philippe Bruyère +// +// 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 System.Collections.Generic; +using System.Linq; +using System.Text; +using System.Diagnostics; +using Cairo; +using System.Text.RegularExpressions; +using System.Xml.Serialization; +using System.ComponentModel; + +namespace Crow +{ + public class TextRun : GraphicObject + { + #region CTOR + public TextRun () + { + + } + public TextRun (string _text) + : base () + { + Text = _text; + } + #endregion + + //TODO:change protected to private + + #region private and protected fields + protected string _text = "label"; + Alignment _textAlignment = Alignment.Left; + bool horizontalStretch = false; + bool verticalStretch = false; + bool _multiline; + bool wordWrap; + protected Rectangle rText; + protected float widthRatio = 1f; + protected float heightRatio = 1f; + protected FontExtents fe; + protected TextExtents te; + #endregion + + + [XmlAttributeAttribute ()] + [DefaultValue (Alignment.Left)] + public Alignment TextAlignment { + get { return _textAlignment; } + set { _textAlignment = value; } + } + [XmlAttributeAttribute ()] + [DefaultValue (false)] + public virtual bool HorizontalStretch { + get { return horizontalStretch; } + set { + if (horizontalStretch == value) + return; + horizontalStretch = value; + RegisterForRedraw (); + NotifyValueChanged ("HorizontalStretch", horizontalStretch); + } + } + [XmlAttributeAttribute ()] + [DefaultValue (false)] + public virtual bool VerticalStretch { + get { return verticalStretch; } + set { + if (verticalStretch == value) + return; + verticalStretch = value; + RegisterForRedraw (); + NotifyValueChanged ("VerticalStretch", verticalStretch); + } + } + [XmlAttributeAttribute ()] + [DefaultValue ("label")] + public string Text { + get { + return lines == null ? + _text : lines.Aggregate ((i, j) => i + Interface.LineBreak + j); + } + set { + if (_text == value) + return; + + RegisterForGraphicUpdate (); + + _text = value; + + if (string.IsNullOrEmpty (_text)) + _text = ""; + + lines = getLines; + } + } + [XmlAttributeAttribute ()] + [DefaultValue (false)] + public bool Multiline { + get { return _multiline; } + set { + _multiline = value; + RegisterForGraphicUpdate (); + } + } + [XmlAttributeAttribute ()] + [DefaultValue (false)] + public bool WordWrap { + get { + return wordWrap; + } + set { + if (wordWrap == value) + return; + wordWrap = value; + RegisterForGraphicUpdate (); + } + } + + List lines; + List getLines { + get { + return _multiline ? + Regex.Split (_text, "\r\n|\r|\n").ToList () : + new List (new string [] { _text }); + } + } + + #region GraphicObject overrides + protected override int measureRawSize (LayoutingType lt) + { + if (lines == null) + lines = getLines; + + using (ImageSurface img = new ImageSurface (Format.Argb32, 10, 10)) { + using (Context gr = new Context (img)) { + //Cairo.FontFace cf = gr.GetContextFontFace (); + + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + + + fe = gr.FontExtents; + te = new TextExtents (); + + if (lt == LayoutingType.Height) { + int lc = lines.Count; + //ensure minimal height = text line height + if (lc == 0) + lc = 1; + + return (int)(fe.Height * lc) + Margin * 2; + } + + foreach (string s in lines) { + string l = s.Replace("\t", new String (' ', Interface.TabSize)); + TextExtents tmp = gr.TextExtents (l); + if (tmp.XAdvance > te.XAdvance) + te = tmp; + } + return (int)Math.Ceiling (te.XAdvance) + Margin * 2; + } + } + } + protected override void onDraw (Context gr) + { + base.onDraw (gr); + + gr.SelectFontFace (Font.Name, Font.Slant, Font.Wheight); + gr.SetFontSize (Font.Size); + gr.FontOptions = Interface.FontRenderingOptions; + gr.Antialias = Interface.Antialias; + + rText = new Rectangle (new Size ( + measureRawSize (LayoutingType.Width), measureRawSize (LayoutingType.Height))); + rText.Width -= 2 * Margin; + rText.Height -= 2 * Margin; + + widthRatio = 1f; + heightRatio = 1f; + + Rectangle cb = ClientRectangle; + + //ignore text alignment if size to content = true + //or if text size is larger than client bounds + if (Width < 0 || Height < 0 || rText.Width > cb.Width) { + rText.X = cb.X; + rText.Y = cb.Y; + } else { + if (horizontalStretch) { + widthRatio = (float)cb.Width / rText.Width; + if (!verticalStretch) + heightRatio = widthRatio; + } + if (verticalStretch) { + heightRatio = (float)cb.Height / rText.Height; + if (!horizontalStretch) + widthRatio = heightRatio; + } + + rText.Width = (int)(widthRatio * cb.Width); + rText.Height = (int)(heightRatio * cb.Height); + + switch (TextAlignment) { + case Alignment.TopLeft: //ok + rText.X = cb.X; + rText.Y = cb.Y; + break; + case Alignment.Top: //ok + rText.Y = cb.Y; + rText.X = cb.X + cb.Width / 2 - rText.Width / 2; + break; + case Alignment.TopRight: //ok + rText.Y = cb.Y; + rText.X = cb.Right - rText.Width; + break; + case Alignment.Left://ok + rText.X = cb.X; + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + break; + case Alignment.Right://ok + rText.X = cb.X + cb.Width - rText.Width; + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + break; + case Alignment.Bottom://ok + rText.X = cb.Width / 2 - rText.Width / 2; + rText.Y = cb.Height - rText.Height; + break; + case Alignment.BottomLeft://ok + rText.X = cb.X; + rText.Y = cb.Bottom - rText.Height; + break; + case Alignment.BottomRight://ok + rText.Y = cb.Bottom - rText.Height; + rText.X = cb.Right - rText.Width; + break; + case Alignment.Center://ok + rText.X = cb.X + cb.Width / 2 - rText.Width / 2; + rText.Y = cb.Y + cb.Height / 2 - rText.Height / 2; + break; + } + } + + gr.FontMatrix = new Matrix (widthRatio * Font.Size, 0, 0, heightRatio * Font.Size, 0, 0); + + + int curLineCount = 0; + for (int i = 0; i < lines.Count; i++) { + string l = lines [i].Replace ("\t", new String (' ', Interface.TabSize)); + List wl = new List (); + int lineLength = (int)gr.TextExtents (l).XAdvance; + + if (wordWrap && lineLength > cb.Width) { + string tmpLine = ""; + int curChar = 0; + while (curChar < l.Length) { + tmpLine += l [curChar]; + if ((int)gr.TextExtents (tmpLine).XAdvance > cb.Width) { + tmpLine = tmpLine.Remove (tmpLine.Length - 1); + wl.Add (tmpLine); + tmpLine = ""; + continue; + } + curChar++; + } + wl.Add (tmpLine); + } else + wl.Add (l); + + foreach (string ll in wl) { + lineLength = (int)gr.TextExtents (ll).XAdvance; + + + if (string.IsNullOrWhiteSpace (ll)) { + curLineCount++; + continue; + } + + Foreground.SetAsSource (gr); + gr.MoveTo (rText.X, rText.Y + fe.Ascent + fe.Height * curLineCount); + + gr.ShowText (ll); + gr.Fill (); + + curLineCount++; + } + } + } + #endregion + } +} -- cgit v1.3.1-4-g156e