示例#1
0
        public override Size GetSize(object backend)
        {
            LayoutInfo li = (LayoutInfo)backend;

            using (CTFrame frame = CreateFrame(li)) {
                if (frame == null)
                {
                    return(Size.Zero);
                }

                Size      result     = Size.Zero;
                CTLine [] lines      = frame.GetLines();
                float     lineHeight = li.Font.Ascender - li.Font.Descender + li.Font.Leading;

                // try to approximate Pango's layout
                foreach (var line in lines)
                {
                    result.Width   = Math.Max(result.Width, line.GetTypographicBounds());
                    result.Height += lineHeight;

                    // clean up after ourselves as we go
                    line.Dispose();
                }

                // CoreText throws away trailing line breaks..
                if (li.Text.EndsWith("\n"))
                {
                    result.Height += lineHeight;
                }

                result.Width  = Math.Ceiling(result.Width);
                result.Height = Math.Ceiling(result.Height);
                return(result);
            }
        }
示例#2
0
        public static RectangleF GetTextSize(CTFrame frame)
        {
            var   minY  = float.MaxValue;
            var   maxY  = float.MinValue;
            float width = 0;

            var lines   = frame.GetLines();
            var origins = new CGPoint[lines.Length];

            frame.GetLineOrigins(new NSRange(0, 0), origins);

            for (var i = 0; i < lines.Length; i++)
            {
                var line      = lines[i];
                var lineWidth = (float)line.GetTypographicBounds(out var ascent, out var descent, out var leading);

                if (lineWidth > width)
                {
                    width = lineWidth;
                }

                var origin = origins[i];

                minY = (float)Math.Min(minY, origin.Y - ascent);
                maxY = (float)Math.Max(maxY, origin.Y + descent);

                lines[i].Dispose();
            }

            return(new RectangleF(0f, minY, width, Math.Max(0, maxY - minY)));
        }
示例#3
0
        // 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);
                }
            }
        }
        public override Size GetSize(object backend)
        {
            LayoutInfo li = (LayoutInfo)backend;

            using (CTFrame frame = CreateFrame(li)) {
                if (frame == null)
                {
                    return(Size.Zero);
                }

                Size      result     = Size.Zero;
                CTLine [] lines      = frame.GetLines();
                nfloat    lineHeight = li.Font.Ascender - li.Font.Descender + li.Font.Leading;

                CTLine ellipsis  = null;
                bool   ellipsize = li.Width.HasValue && li.TextTrimming == TextTrimming.WordElipsis;
                if (ellipsize)
                {
                    ellipsis = new CTLine(CreateAttributedString(li, "..."));
                }

                // try to approximate Pango's layout
                foreach (var line in lines)
                {
                    var l = line;
                    if (ellipsize)                       // we need to create a new CTLine here because the framesetter already truncated the text for the line
                    {
                        l = new CTLine(CreateAttributedString(li, li.Text.Substring((int)line.StringRange.Location)))
                            .GetTruncatedLine(li.Width.Value, CTLineTruncation.End, ellipsis);
                        line.Dispose();
                    }

                    result.Width   = Math.Max(result.Width, l.GetTypographicBounds());
                    result.Height += lineHeight;

                    // clean up after ourselves as we go
                    l.Dispose();
                }

                // CoreText throws away trailing line breaks..
                if (li.Text.EndsWith("\n"))
                {
                    result.Height += lineHeight;
                }

                result.Width  = Math.Ceiling(result.Width);
                result.Height = Math.Ceiling(result.Height);
                return(result);
            }
        }
示例#5
0
        internal static void Draw(CGContext ctx, object layout, double x, double y)
        {
            LayoutInfo li = (LayoutInfo)layout;

            using (CTFrame frame = CreateFrame(li)) {
                if (frame == null)
                {
                    return;
                }

                CTLine ellipsis  = null;
                bool   ellipsize = li.Width.HasValue && li.TextTrimming == TextTrimming.WordElipsis;
                if (ellipsize)
                {
                    ellipsis = new CTLine(CreateAttributedString(li, "..."));
                }

                nfloat lineHeight = li.Font.Ascender - li.Font.Descender + li.Font.Leading;

                ctx.SaveState();
                ctx.TextMatrix = CGAffineTransform.MakeScale(1f, -1f);
                ctx.TranslateCTM((float)x, (float)y + li.Font.Ascender);
                foreach (var line in frame.GetLines())
                {
                    ctx.TextPosition = CGPoint.Empty;
                    // Determine final line
                    var ln = line;
                    if (ellipsize)
                    {
                        // we need to create a new CTLine here because the framesetter already truncated the text for the line
                        ln = new CTLine(CreateAttributedString(li, li.Text.Substring((int)line.StringRange.Location)))
                             .GetTruncatedLine(li.Width.Value, CTLineTruncation.End, ellipsis);
                        line.Dispose();
                    }
                    else if (li.Width.HasValue && li.TextAlignment != Alignment.Start)
                    {
                        var tx = li.Width.Value - GetLineWidth(ln);
                        if (li.TextAlignment == Alignment.Center)
                        {
                            tx /= 2d;
                        }
                        ctx.TextPosition = new CGPoint((nfloat)tx, 0);
                    }
                    ln.Draw(ctx);
                    ctx.TranslateCTM(0, lineHeight);
                    ln.Dispose();
                }
                ctx.RestoreState();
            }
        }