public float GetTypographicWidth(TFont font, AttributedGlyphRun <TFont, TGlyph> run) { var aString = run.ToNsAttributedString(); using (var ctLine = new CTLine(aString)) return((float)ctLine.GetTypographicBounds()); }
// Public method to create a rect for a given range in the text contents // Called by our EditableTextRange to implement the required // UITextInput:firstRectForRange method public CGRect FirstRect(NSRange range) { int index = (int)range.Location; // Iterate over our CTLines, looking for the line that encompasses the given range var lines = frame.GetLines(); for (int i = 0; i < lines.Length; i++) { CTLine line = lines [i]; NSRange lineRange = line.StringRange; int localIndex = index - (int)lineRange.Location; if (localIndex >= 0 && localIndex < lineRange.Length) { // For this sample, we use just the first line that intersects range int finalIndex = (int)Math.Min(lineRange.Location + lineRange.Length, range.Location + range.Length); // Create a rect for the given range within this line nfloat xStart = line.GetOffsetForStringIndex(index); nfloat xEnd = line.GetOffsetForStringIndex(finalIndex); var origins = new CGPoint [lines.Length]; frame.GetLineOrigins(new NSRange(i, 0), origins); nfloat ascent, descent, leading; line.GetTypographicBounds(out ascent, out descent, out leading); return(new CGRect(xStart, origins [0].Y - descent, xEnd - xStart, ascent + descent)); } } return(CGRect.Empty); }
public static TextMetrics GlobalMeasureText(string text, Font font) { if (string.IsNullOrEmpty(text)) { return(new TextMetrics()); } if (font == null) { throw new ArgumentNullException("font"); } using (var atext = new NSMutableAttributedString(text)) { atext.AddAttributes(new CTStringAttributes { ForegroundColorFromContext = true, Font = font.GetCTFont(), }.Dictionary, new NSRange(0, text.Length)); using (var l = new CTLine(atext)) { nfloat asc, desc, lead; var len = l.GetTypographicBounds(out asc, out desc, out lead); return(new TextMetrics { Width = len, Ascent = asc, Descent = desc, }); } } }
static void PrepareGlyphArcInfo (CTLine line, long glyphCount, GlyphArcInfo[] glyphArcInfo) { var runArray = line.GetGlyphRuns (); // Examine each run in the line, updating glyphOffset to track how far along the run is // in terms of glyphCount. long glyphOffset = 0; nfloat ascent = 0; nfloat descent = 0; nfloat leading = 0; foreach (var run in runArray) { var runGlyphCount = run.GlyphCount; // Ask for the width of each glyph in turn. var runGlyphIndex = 0; for (; runGlyphIndex < runGlyphCount; runGlyphIndex++) { glyphArcInfo [runGlyphIndex + glyphOffset].width = (float)run.GetTypographicBounds (new NSRange (runGlyphIndex, 1), out ascent, out descent, out leading); } glyphOffset += runGlyphCount; } var lineLength = line.GetTypographicBounds (out ascent, out descent, out leading); var prevHalfWidth = glyphArcInfo [0].width / 2.0; glyphArcInfo [0].angle = (float)((prevHalfWidth / lineLength) * Math.PI); var lineGlyphIndex = 1; for (; lineGlyphIndex < glyphCount; lineGlyphIndex++) { var halfWidth = glyphArcInfo [lineGlyphIndex].width / 2.0; var prevCenterToCenter = prevHalfWidth + halfWidth; glyphArcInfo [lineGlyphIndex].angle = (float)((prevCenterToCenter / lineLength) * Math.PI); prevHalfWidth = halfWidth; } }
public double GetBaseLine() { using (var line = new CTLine(TextStorage)) { nfloat ascent, descent, leading; line.GetTypographicBounds(out ascent, out descent, out leading); return(ascent); } }
public override double GetBaseline(object backend) { LayoutInfo li = (LayoutInfo)backend; using (var line = new CTLine(CreateAttributedString(li))) { nfloat ascent, descent, leading; line.GetTypographicBounds(out ascent, out descent, out leading); return((double)ascent); } }
public void DrawText(string text, Rect frame, Font font, TextAlignment alignment = TextAlignment.Left, Pen pen = null, Brush brush = null) { if (string.IsNullOrEmpty(text)) { return; } if (font == null) { throw new ArgumentNullException("font"); } SetBrush(brush); using (var atext = new NSMutableAttributedString(text)) { atext.AddAttributes(new CTStringAttributes { ForegroundColorFromContext = true, Font = font.GetCTFont(), }, new NSRange(0, text.Length)); using (var l = new CTLine(atext)) { nfloat asc, desc, lead; var len = l.GetTypographicBounds(out asc, out desc, out lead); var pt = frame.TopLeft; switch (alignment) { case TextAlignment.Left: pt.X = frame.X; break; case TextAlignment.Center: pt.X = frame.X + (frame.Width - len) / 2; break; case TextAlignment.Right: pt.X = frame.Right - len; break; } context.SaveState(); context.TranslateCTM((nfloat)(pt.X), (nfloat)(pt.Y)); context.TextPosition = CGPoint.Empty; l.Draw(context); context.RestoreState(); } } }
// This only handles one character for right now internal static void GetCharABCWidthsFloat(char characters, CTFont font, out ABCFloat[] abc) { var atts = buildAttributedString(characters.ToString(), font); // for now just a line not sure if this is going to work CTLine line = new CTLine(atts); float ascent; float descent; float leading; abc = new ABCFloat[1]; abc[0].abcfB = (float)line.GetTypographicBounds(out ascent, out descent, out leading); abc [0].abcfB += leading; }
// Public method to determine the CGRect for the insertion point or selection, used // when creating or updating our SimpleCaretView instance public CGRect CaretRect(int index) { var lines = frame.GetLines(); // Special case, no text if (text.Length == 0) { CGPoint origin = new CGPoint(Bounds.GetMinX(), Bounds.GetMinY() - font.Leading); // Note: using fabs() for typically negative descender from fonts return(new CGRect(origin.X, origin.Y - (nfloat)Math.Abs(font.Descender), 3, font.Ascender + (nfloat)Math.Abs(font.Descender))); } // Special case, insertion point at final position in text after newline if (index == text.Length && text.EndsWith("\n")) { CTLine line = lines [lines.Length - 1]; NSRange range = line.StringRange; nfloat xPos = line.GetOffsetForStringIndex(range.Location); var origins = new CGPoint [lines.Length]; nfloat ascent, descent, leading; line.GetTypographicBounds(out ascent, out descent, out leading); frame.GetLineOrigins(new NSRange(lines.Length - 1, 0), origins); // Place point after last line, including any font leading spacing if applicable origins[0].Y -= font.Leading; return(new CGRect(xPos, origins [0].Y - descent, 3, ascent + descent)); } // Regular case, caret somewhere within our text content range for (int i = 0; i < lines.Length; i++) { CTLine line = lines [i]; NSRange range = line.StringRange; int localIndex = index - (int)range.Location; if (localIndex >= 0 && localIndex <= range.Length) { // index is in the range for this line nfloat xPos = line.GetOffsetForStringIndex(index); var origins = new CGPoint [lines.Length]; nfloat ascent, descent, leading; line.GetTypographicBounds(out ascent, out descent, out leading); frame.GetLineOrigins(new NSRange(i, 0), origins); // Make a small "caret" rect at the index position return(new CGRect(xPos, origins [0].Y - descent, 3, ascent + descent)); } } return(CGRect.Empty); }
public static ABC GetCharWidthABC(char ch, Font font, System.Drawing.Graphics gr) { ABC[] _temp = new ABC[1]; var nativFont = CreateFont(font.Name, font.Size, font.Style, font.GdiCharSet, font.GdiVerticalFont); var atts = buildAttributedString(ch.ToString(), nativFont); // for now just a line not sure if this is going to work CTLine line = new CTLine(atts); float ascent; float descent; float leading; _temp[0].abcB = (uint)line.GetTypographicBounds(out ascent, out descent, out leading); return(_temp[0]); }
internal static CCSize MeasureString(string textg, CTFont font, CCRect rect) { var atts = buildAttributedString(textg, font); // for now just a line not sure if this is going to work CTLine line = new CTLine(atts); // Create and initialize some values from the bounds. float ascent; float descent; float leading; double lineWidth = line.GetTypographicBounds(out ascent, out descent, out leading); var measure = new CCSize((float)lineWidth + leading, ascent + descent); return(measure); }
public void DrawText(string text, float x, float y, float width, float height, Xamarin.Forms.TextAlignment hAlignment, Xamarin.Forms.TextAlignment vAlignment) { if (font == null || font.NativeFont == null) { return; } var attributedString = new NSAttributedString(text, new CTStringAttributes() { Font = font.NativeFont, ForegroundColorFromContext = true }); CTLine ctLine = new CTLine(attributedString); CGSize size = new CGSize((float)ctLine.GetTypographicBounds(), font.NativeFont.CapHeightMetric + font.NativeFont.DescentMetric); if ((hAlignment & Xamarin.Forms.TextAlignment.Center) != 0) { x += (width - (float)size.Width) / 2; } else if ((hAlignment & Xamarin.Forms.TextAlignment.End) != 0) { x += width - (float)size.Width; } if ((vAlignment & Xamarin.Forms.TextAlignment.Center) != 0) { y += (height - (float)size.Height) / 2; } else if ((vAlignment & Xamarin.Forms.TextAlignment.End) != 0) { y += height - (float)size.Height; } context.SaveState(); context.ScaleCTM(1f, -1f); context.TextPosition = new CGPoint(x, -y - font.NativeFont.CapHeightMetric); ctLine.Draw(context); context.RestoreState(); ctLine.Dispose(); attributedString.Dispose(); }
// Helper method for drawing the current selection range (as a simple filled rect) void DrawRangeAsSelection(NSRange selectionRange) { // If not in editing mode, we do not draw selection rects if (!IsEditing) { return; } // If selection range empty, do not draw if (selectionRange.Length == 0 || selectionRange.Location == NSRange.NotFound) { return; } // set the fill color to the selection color SelectionColor.SetFill(); // Iterate over the lines in our CTFrame, looking for lines that intersect // with the given selection range, and draw a selection rect for each intersection var lines = frame.GetLines(); for (int i = 0; i < lines.Length; i++) { CTLine line = lines [i]; NSRange lineRange = line.StringRange; NSRange range = new NSRange(lineRange.Location, lineRange.Length); NSRange intersection = RangeIntersection(range, selectionRange); if (intersection.Location != NSRange.NotFound && intersection.Length > 0) { // The text range for this line intersects our selection range nfloat xStart = line.GetOffsetForStringIndex(intersection.Location); nfloat xEnd = line.GetOffsetForStringIndex(intersection.Location + intersection.Length); var origin = new CGPoint [lines.Length]; // Get coordinate and bounds information for the intersection text range frame.GetLineOrigins(new NSRange(i, 0), origin); nfloat ascent, descent, leading; line.GetTypographicBounds(out ascent, out descent, out leading); // Create a rect for the intersection and draw it with selection color CGRect selectionRect = new CGRect(xStart, origin [0].Y - descent, xEnd - xStart, ascent + descent); UIGraphics.RectFill(selectionRect); } } }
static void PrepareGlyphArcInfo(CTLine line, long glyphCount, GlyphArcInfo[] glyphArcInfo) { var runArray = line.GetGlyphRuns(); // Examine each run in the line, updating glyphOffset to track how far along the run is // in terms of glyphCount. long glyphOffset = 0; nfloat ascent = 0; nfloat descent = 0; nfloat leading = 0; foreach (var run in runArray) { var runGlyphCount = run.GlyphCount; // Ask for the width of each glyph in turn. var runGlyphIndex = 0; for (; runGlyphIndex < runGlyphCount; runGlyphIndex++) { glyphArcInfo[runGlyphIndex + glyphOffset].width = (float)run.GetTypographicBounds(new NSRange(runGlyphIndex, 1), out ascent, out descent, out leading); } glyphOffset += runGlyphCount; } var lineLength = line.GetTypographicBounds(out ascent, out descent, out leading); var prevHalfWidth = glyphArcInfo[0].width / 2.0; glyphArcInfo[0].angle = (float)((prevHalfWidth / lineLength) * Math.PI); var lineGlyphIndex = 1; for (; lineGlyphIndex < glyphCount; lineGlyphIndex++) { var halfWidth = glyphArcInfo[lineGlyphIndex].width / 2.0; var prevCenterToCenter = prevHalfWidth + halfWidth; glyphArcInfo[lineGlyphIndex].angle = (float)((prevCenterToCenter / lineLength) * Math.PI); prevHalfWidth = halfWidth; } }
public Xamarin.Forms.Size MeasureText(string text) { if (font == null || font.NativeFont == null) { return(Xamarin.Forms.Size.Zero); } var attributedString = new NSAttributedString(text, new CTStringAttributes() { Font = font.NativeFont, ForegroundColorFromContext = true }); CTLine ctLine = new CTLine(attributedString); Xamarin.Forms.Size size = new Xamarin.Forms.Size((float)ctLine.GetTypographicBounds(), font.NativeFont.CapHeightMetric + font.NativeFont.DescentMetric); ctLine.Dispose(); attributedString.Dispose(); return(size); }
public SizeF MeasureString(string textg, Font font, RectangleF rect) { // As per documentation // https://developer.apple.com/library/mac/#documentation/GraphicsImaging/Conceptual/drawingwithquartz2d/dq_text/dq_text.html#//apple_ref/doc/uid/TP30001066-CH213-TPXREF101 // // * Note * Not sure if we should save off the graphic state, set context transform to identity // and restore state to do the measurement. Something to be looked into. // context.TextPosition = rect.Location; // var startPos = context.TextPosition; // context.SelectFont ( font.nativeFont.PostScriptName, // font.SizeInPoints, // CGTextEncoding.MacRoman); // context.SetTextDrawingMode(CGTextDrawingMode.Invisible); // // context.SetCharacterSpacing(1); // var textMatrix = CGAffineTransform.MakeScale(1f,-1f); // context.TextMatrix = textMatrix; // // context.ShowTextAtPoint(rect.X, rect.Y, textg, textg.Length); // var endPos = context.TextPosition; // // var measure = new SizeF(endPos.X - startPos.X, font.nativeFont.CapHeightMetric); var atts = buildAttributedString(textg, font); // for now just a line not sure if this is going to work CTLine line = new CTLine(atts); var lineBounds = line.GetImageBounds(context); // Create and initialize some values from the bounds. float ascent; float descent; float leading; double lineWidth = line.GetTypographicBounds(out ascent, out descent, out leading); var measure = new SizeF((float)lineWidth, ascent + descent); return(measure); }
public void DrawText(string text, Rect frame, Font font, TextAlignment alignment = TextAlignment.Left, Pen pen = null, Brush brush = null) { if (string.IsNullOrEmpty(text)) { return; } if (font == null) { throw new ArgumentNullException("font"); } SetBrush(brush); // string fontName = font.Name; // context.SelectFont (font.Name, (nfloat)font.Size, CGTextEncoding.MacRoman); // // context.ShowTextAtPoint ((nfloat)frame.X, (nfloat)frame.Y, text); var pt = frame.TopLeft; using (var atext = new NSMutableAttributedString(text)) { atext.AddAttributes(new CTStringAttributes { ForegroundColorFromContext = true, Font = font.GetCTFont(), }, new NSRange(0, text.Length)); using (var l = new CTLine(atext)) { nfloat asc, desc, lead; var width = l.GetTypographicBounds(out asc, out desc, out lead); context.SaveState(); context.TranslateCTM((nfloat)(pt.X - width / 2), (nfloat)(pt.Y + desc)); context.TextPosition = CGPoint.Empty; l.Draw(context); context.RestoreState(); } } }
public void DrawText(string text, Rect frame, Font font, TextAlignment alignment = TextAlignment.Left, Pen pen = null, Brush brush = null) { if (string.IsNullOrEmpty (text)) return; if (font == null) throw new ArgumentNullException ("font"); SetBrush (brush); // string fontName = font.Name; // context.SelectFont (font.Name, (nfloat)font.Size, CGTextEncoding.MacRoman); // // context.ShowTextAtPoint ((nfloat)frame.X, (nfloat)frame.Y, text); var pt = frame.TopLeft; using (var atext = new NSMutableAttributedString (text)) { atext.AddAttributes (new CTStringAttributes { ForegroundColorFromContext = true, Font = font.GetCTFont (), }, new NSRange (0, text.Length)); using (var l = new CTLine (atext)) { nfloat asc, desc, lead; var width = l.GetTypographicBounds (out asc, out desc, out lead); context.SaveState (); context.TranslateCTM ((nfloat)(pt.X - width / 2), (nfloat)(pt.Y + desc)); context.TextPosition = CGPoint.Empty; l.Draw (context); context.RestoreState (); } } }
public void DrawText (string text, Rect frame, Font font, TextAlignment alignment = TextAlignment.Left, Pen pen = null, Brush brush = null) { if (string.IsNullOrEmpty (text)) return; if (font == null) throw new ArgumentNullException ("font"); SetBrush (brush); using (var atext = new NSMutableAttributedString (text)) { atext.AddAttributes (new CTStringAttributes { ForegroundColorFromContext = true, StrokeColor = pen != null ? pen.Color.GetCGColor () : null, Font = font.GetCTFont (), }, new NSRange (0, text.Length)); using (var l = new CTLine (atext)) { nfloat asc, desc, lead; var len = l.GetTypographicBounds (out asc, out desc, out lead); var pt = frame.TopLeft; switch (alignment) { case TextAlignment.Left: pt.X = frame.X; break; case TextAlignment.Center: pt.X = frame.X + (frame.Width - len) / 2; break; case TextAlignment.Right: pt.X = frame.Right - len; break; } context.SaveState (); context.TranslateCTM ((nfloat)(pt.X), (nfloat)(pt.Y)); context.TextPosition = CGPoint.Empty; l.Draw (context); context.RestoreState (); } } }
public static TextMetrics GlobalMeasureText (string text, Font font) { if (string.IsNullOrEmpty(text)) return new TextMetrics (); if (font == null) throw new ArgumentNullException("font"); using (var atext = new NSMutableAttributedString (text)) { atext.AddAttributes (new CTStringAttributes { ForegroundColorFromContext = true, Font = font.GetCTFont (), }, new NSRange (0, text.Length)); using (var l = new CTLine (atext)) { nfloat asc, desc, lead; var len = l.GetTypographicBounds (out asc, out desc, out lead); return new TextMetrics { Width = len, Ascent = asc, Descent = desc, }; } } }
static double GetLineWidth(CTLine l) { // Pango does not consider trailing whitespace in its size return(l.GetTypographicBounds() - l.TrailingWhitespaceWidth); }
private static void DrawText(this CGContext context, string source, float x, float y, string fontName, float fontSize, bool isCenter) { var stringAttributes = new CTStringAttributes { ForegroundColorFromContext = true, Font = new CTFont(fontName, fontSize) }; var attributedString = new NSAttributedString(source, stringAttributes); context.TextPosition = new PointF(x, y); using (var textLine = new CTLine(attributedString)) { if (isCenter) context.TextPosition = new PointF((float)(x - (textLine.GetTypographicBounds() / 2)), y); textLine.Draw(context); } }