예제 #1
0
        /// <summary>
        /// Populates text measures. If you use a shared textShaper, call this before GetSpans, or GetLines.
        /// </summary>
        public void LoadMeasures(TextShaper textShaper = null)
        {
            if (textShaper == null)
            {
                textShaper = new TextShaper(false);
            }

            if (GlyphSpan == null)
            {
                GlyphSpan = textShaper.GetGlyphSpan(Font, Text);

                var fontMetrics = GlyphSpan.Paints[0].FontMetrics;
                FontHeight = fontMetrics.CapHeight;
                if (Font.LineHeight.HasValue)
                {
                    LineHeight = Font.LineHeight.Value;
                }
                else
                {
                    LineHeight = (fontMetrics.Descent - fontMetrics.Ascent + fontMetrics.Leading) * LineSpacing;
                }
                MarginY = (LineHeight - FontHeight) / 2;
            }

            if (LineBreakMode == LineBreakMode.MiddleTruncation)
            {
                if (EllipsisGlyphSpan == null)
                {
                    EllipsisGlyphSpan = textShaper.GetGlyphSpan(Font, " … ");
                }
            }
        }
예제 #2
0
        /// <summary>
        /// Measure this text block, given supplied maximum width
        /// </summary>
        /// <param name="textShaper">Text Shaper (measurement cache) to use, or null if measurements shouldn't be cached in memory</param>
        public SKSize Measure(float maxwidth, TextShaper textShaper = null)
        {
            float width = 0;

            LoadMeasures(textShaper);
            if (LineBreakMode == LineBreakMode.MiddleTruncation)
            {
                var spans = GetSpans(maxwidth);
                foreach (var span in spans)
                {
                    width += span.width;
                }
                return(new SKSize(width, LineHeight));
            }
            else
            {
                var lines = GetLines(maxwidth);
                foreach (var line in lines)
                {
                    if (width < line.width)
                    {
                        width = line.width;
                    }
                }
                return(new SKSize(width, lines.Count * LineHeight));
            }
        }
        private SKRect Layout(SKCanvas canvas, SKRect rect, FlowDirection flowDirection, TextShaper textShaper)
        {
            var width = rect.Width;

            var line      = new List <(RichTextSpan span, MeasuredSpan wordspan)>();
            var linewidth = 0.0f;

            var linefontheight = 0f;
            var linemarginy    = 0f;

            var maxlinewidth = 0.0f;
            var y            = rect.Top;

            if (Spans != null)
            {
                // calculate maximum font dimensions
                foreach (var span in Spans)
                {
                    if (span != null)
                    {
                        var(fontheight, marginy) = span.GetMeasures(textShaper);
                        if (linefontheight < fontheight)
                        {
                            linefontheight = fontheight;
                        }
                        if (linemarginy < marginy)
                        {
                            linemarginy = marginy;
                        }
                    }
                }

                y += linefontheight + linemarginy;

                // draw all text blocks in succession
                foreach (var span in Spans)
                {
                    if (span != null)
                    {
                        var childlines = span.GetLines(width, linewidth, false);

                        if (childlines != null)
                        {
                            var childlinecount = childlines.Count;
                            for (var i = 0; i < childlinecount; i++)
                            {
                                var wordspan = childlines[i];
                                line.Add((span, wordspan));

                                linewidth += wordspan.width;
                                if (maxlinewidth < linewidth)
                                {
                                    maxlinewidth = linewidth;
                                }

                                if (i != childlinecount - 1)
                                {
                                    LayoutLine();
                                }
                            }
                        }
                    }
                }

                if (line.Count > 0)
                {
                    LayoutLine();
                }

                y -= linefontheight + linemarginy;
            }

            if (flowDirection == FlowDirection.Unknown || flowDirection == FlowDirection.LeftToRight)
            {
                return(new SKRect(rect.Left, rect.Top, rect.Left + maxlinewidth + floatroundingmargin, y));
            }
            else
            {
                return(new SKRect(rect.Right - maxlinewidth - floatroundingmargin, rect.Top, rect.Right, y));
            }

            void LayoutLine()
            {
                if (canvas != null)
                {
                    if (flowDirection == FlowDirection.LeftToRight)
                    {
                        var x = rect.Left;
                        foreach (var chunk in line)
                        {
                            if (PixelRounding)
                            {
                                x = (float)Math.Round(x);
                            }

                            var span      = chunk.span;
                            var spanwidth = chunk.wordspan.width;

                            // draw the span
                            span.DrawMeasuredSpan(canvas, x, y, linefontheight, linemarginy, chunk.wordspan, false);

#if DEBUGCONTAINER
                            var paintrect = new SKRect(x + t.X, y - text.FontHeight - text.MarginY + t.Y, x + spanwidth + t.X, y + text.MarginY + t.Y);
                            using (var borderpaint = new SKPaint()
                            {
                                Color = SKColors.Orange.WithAlpha(64), IsStroke = true
                            })
                                canvas.DrawRect(paintrect, borderpaint);
#endif

                            x += spanwidth;
                        }
                    }
                    else
                    {
                        var x = rect.Right;
                        foreach (var chunk in line)
                        {
                            var span      = chunk.span;
                            var spanwidth = chunk.wordspan.width;

                            if (PixelRounding)
                            {
                                x = (float)Math.Round(x);
                            }

                            x -= spanwidth;

                            // draw the span
                            span.DrawMeasuredSpan(canvas, x, y, linefontheight, linemarginy, chunk.wordspan, true);

#if DEBUGCONTAINER
                            var paintrect = new SKRect(x - t.X, y - text.FontHeight - text.MarginY + t.Y, x + spanwidth - t.X, y + text.MarginY + t.Y);
                            using (var borderpaint = new SKPaint()
                            {
                                Color = SKColors.Orange.WithAlpha(64), IsStroke = true
                            })
                                canvas.DrawRect(paintrect, borderpaint);
#endif
                        }
                    }
                }

                linewidth = 0;
                y        += linefontheight + linemarginy * 2;

                line.Clear();
            }
        }
 /// <summary>
 /// Paint's the rich text in the provided rectangle
 /// </summary>
 /// <returns>a rect containing the actual bottom of painted text</returns>
 public SKRect Paint(SKCanvas canvas, SKRect rect, FlowDirection flowDirection = FlowDirection.LeftToRight, TextShaper textShaper = null)
 {
     return(Layout(canvas, rect, flowDirection, textShaper));
 }
        /// <summary>
        /// Measures the Rich Text, given the maximum width
        /// </summary>
        /// <param name="maxWidth"></param>
        /// <param name="textShaper"></param>
        /// <returns></returns>
        public SKSize Measure(float maxWidth, TextShaper textShaper = null)
        {
            var calculated = Layout(null, new SKRect(0, 0, maxWidth, float.MaxValue), FlowDirection.LeftToRight, textShaper ?? new TextShaper(false));

            return(new SKSize(calculated.Width, calculated.Height));
        }
예제 #6
0
        public SKRect Draw(SKCanvas canvas, SKRect rect, TextShaper textShaper = null, FlowDirection flowDirection = FlowDirection.LeftToRight)
        {
            LoadMeasures(textShaper);

            var y = rect.Top + FontHeight + MarginY;

            if (LineBreakMode == LineBreakMode.MiddleTruncation)
            {
                var spans = GetSpans(rect.Width);
                if (flowDirection == FlowDirection.LeftToRight)
                {
                    var x = rect.Left;
                    if (spans.Count > 0)
                    {
                        canvas.DrawGlyphSpan(GlyphSpan, x, y, Color, spans[0]);
                        x += spans[0].width;
                    }
                    if (spans.Count > 1)
                    {
                        canvas.DrawGlyphSpan(EllipsisGlyphSpan, x, y, Color, spans[1]);
                        x += spans[1].width;
                    }
                    if (spans.Count > 2)
                    {
                        canvas.DrawGlyphSpan(GlyphSpan, x, y, Color, spans[2]);
                    }
                }
                else
                {
                    var x = rect.Right;
                    if (spans.Count > 0)
                    {
                        x -= spans[0].width;
                        canvas.DrawGlyphSpan(GlyphSpan, x, y, Color, spans[0]);
                    }
                    if (spans.Count > 1)
                    {
                        x -= spans[1].width;
                        canvas.DrawGlyphSpan(EllipsisGlyphSpan, x, y, Color, spans[1]);
                    }
                    if (spans.Count > 2)
                    {
                        x -= spans[2].width;
                        canvas.DrawGlyphSpan(GlyphSpan, x, y, Color, spans[2]);
                    }
                }
                y += LineHeight;
            }
            else
            {
                var lines = GetLines(rect.Width);
                var i     = 0;
                foreach (var line in lines)
                {
                    if (GetLineColor != null)
                    {
                        Color = GetLineColor(i++, lines.Count);
                    }
                    if (LineBreakMode == LineBreakMode.WordWrap)
                    {
                        float x;
                        if (flowDirection == FlowDirection.LeftToRight)
                        {
                            x = rect.Left;
                        }
                        else
                        {
                            x = rect.Right - line.width;
                        }
                        canvas.DrawGlyphSpan(GlyphSpan, x, y, Color, line, GlyphAnimation);
                    }
                    else if (LineBreakMode == LineBreakMode.Center)
                    {
                        var x = rect.Left + (rect.Width - line.width) / 2;
                        canvas.DrawGlyphSpan(GlyphSpan, x, y, Color, line, GlyphAnimation);
                    }
                    y += LineHeight;
                }
            }

            var paintrect = new SKRect(rect.Left, rect.Top, rect.Right, y - LineHeight + MarginY);

#if DEBUGCONTAINER
            if (canvas != null)
            {
                using (var borderpaint = new SKPaint()
                {
                    Color = SKColors.Red.WithAlpha(64), IsStroke = true
                })
                    canvas.DrawRect(paintrect, borderpaint);
            }
#endif

            return(paintrect);
        }
예제 #7
0
 /// <summary>
 /// Draw a block of text on the canvas.
 /// </summary>
 /// <returns>The bounds of the painted text. Note that the returned rectangle's Width is equal to the input (IE only bottom is calculated). Use TextBlock.Measure to get text bounds</returns>
 public static SKRect DrawRichTextBlock(this SKCanvas canvas, RichTextBlock text, SKRect rect, TextShaper textShaper = null, FlowDirection flowDirection = FlowDirection.LeftToRight)
 {
     return(text.Paint(canvas, rect, flowDirection, textShaper));
 }
예제 #8
0
 /// <summary>
 /// Draw a block of text on the canvas.
 /// </summary>
 /// <returns>The bounds of the painted text. Note that the returned rectangle's Width is equal to the input (IE only bottom is calculated). Use TextBlock.Measure to get text bounds</returns>
 public static SKRect DrawTextBlock(this SKCanvas canvas, TextBlock text, SKRect rect, TextShaper textShaper = null, FlowDirection flowDirection = FlowDirection.LeftToRight)
 {
     return(text.Draw(canvas, rect, textShaper, flowDirection));
 }
예제 #9
0
        /// <summary>
        /// Draw a text block
        /// </summary>
        public static SKRect DrawTextBlock(this SKCanvas canvas, string text, SKRect rect, Font font, SKColor color, TextShaper textShaper = null)
        {
            var textblock = new TextBlock(font, color, text);

            return(DrawTextBlock(canvas, textblock, rect, textShaper));
        }