예제 #1
0
        /// <summary>
        /// Paint this font run
        /// </summary>
        /// <param name="ctx"></param>
        internal void Paint(PaintTextContext ctx)
        {
            // Paint selection?
            if (ctx.PaintSelectionBackground != null)
            {
                float selStartXCoord;
                if (ctx.SelectionStart < Start)
                {
                    selStartXCoord = Direction == TextDirection.LTR ? 0 : Width;
                }
                else if (ctx.SelectionStart >= End)
                {
                    selStartXCoord = Direction == TextDirection.LTR ? Width : 0;
                }
                else
                {
                    selStartXCoord = RelativeCodePointXCoords[ctx.SelectionStart - this.Start];
                }

                float selEndXCoord;
                if (ctx.SelectionEnd < Start)
                {
                    selEndXCoord = Direction == TextDirection.LTR ? 0 : Width;
                }
                else if (ctx.SelectionEnd >= End)
                {
                    selEndXCoord = Direction == TextDirection.LTR ? Width : 0;
                }
                else
                {
                    selEndXCoord = RelativeCodePointXCoords[ctx.SelectionEnd - this.Start];
                }

                if (selStartXCoord != selEndXCoord)
                {
                    var rect = new SKRect(this.XCoord + selStartXCoord, Line.YCoord,
                                          this.XCoord + selEndXCoord, Line.YCoord + Line.Height);
                    ctx.Canvas.DrawRect(rect, ctx.PaintSelectionBackground);
                }
            }

            // Don't paint trailing whitespace runs
            if (RunKind == FontRunKind.TrailingWhitespace)
            {
                return;
            }

            // Text
            using (var paint = new SKPaint())
            {
                // Work out font variant adjustments
                float glyphScale   = 1;
                float glyphVOffset = 0;
                if (Style.FontVariant == FontVariant.SuperScript)
                {
                    glyphScale   = 0.65f;
                    glyphVOffset = -Style.FontSize * 0.35f;
                }
                if (Style.FontVariant == FontVariant.SubScript)
                {
                    glyphScale   = 0.65f;
                    glyphVOffset = Style.FontSize * 0.1f;
                }

                // Setup SKPaint
                paint.Color         = Style.TextColor;
                paint.TextEncoding  = SKTextEncoding.GlyphId;
                paint.Typeface      = Typeface;
                paint.TextSize      = Style.FontSize * glyphScale;
                paint.SubpixelText  = true;
                paint.IsAntialias   = ctx.Options.IsAntialias;
                paint.LcdRenderText = ctx.Options.LcdRenderText;

                unsafe
                {
                    fixed(ushort *pGlyphs = Glyphs.Underlying)
                    {
                        // Get glyph positions
                        var glyphPositions = GlyphPositions.ToArray();

                        // Paint underline
                        if (Style.Underline != UnderlineStyle.None && RunKind == FontRunKind.Normal)
                        {
                            // Work out underline metrics
                            paint.TextSize = Style.FontSize;
                            float underlineYPos = Line.YCoord + Line.BaseLine + (paint.FontMetrics.UnderlinePosition ?? 0);
                            paint.StrokeWidth = paint.FontMetrics.UnderlineThickness ?? 0;
                            paint.TextSize    = Style.FontSize * glyphScale;

                            if (Style.Underline == UnderlineStyle.Gapped)
                            {
                                // Get intercept positions
                                var interceptPositions = paint.GetPositionedTextIntercepts(
                                    (IntPtr)(pGlyphs + Glyphs.Start),
                                    Glyphs.Length * sizeof(ushort),
                                    glyphPositions, underlineYPos - paint.StrokeWidth / 2, underlineYPos + paint.StrokeWidth);

                                // Paint gapped underlinline
                                float x = XCoord;
                                for (int i = 0; i < interceptPositions.Length; i += 2)
                                {
                                    float b = interceptPositions[i] - paint.StrokeWidth;
                                    if (x < b)
                                    {
                                        ctx.Canvas.DrawLine(new SKPoint(x, underlineYPos), new SKPoint(b, underlineYPos), paint);
                                    }
                                    x = interceptPositions[i + 1] + paint.StrokeWidth;
                                }
                                if (x < XCoord + Width)
                                {
                                    ctx.Canvas.DrawLine(new SKPoint(x, underlineYPos), new SKPoint(XCoord + Width, underlineYPos), paint);
                                }
                            }
                            else
                            {
                                // Paint solid underline
                                ctx.Canvas.DrawLine(new SKPoint(XCoord, underlineYPos), new SKPoint(XCoord + Width, underlineYPos), paint);
                            }
                        }

                        // Draw the text
                        ctx.Canvas.DrawPositionedText((IntPtr)(pGlyphs + Glyphs.Start), Glyphs.Length * sizeof(ushort), glyphPositions, paint);
                    }
                }

                // Paint strikethrough
                if (Style.StrikeThrough != StrikeThroughStyle.None && RunKind == FontRunKind.Normal)
                {
                    paint.StrokeWidth = paint.FontMetrics.StrikeoutThickness ?? 0;
                    float strikeYPos = Line.YCoord + Line.BaseLine + (paint.FontMetrics.StrikeoutPosition ?? 0) + glyphVOffset;
                    ctx.Canvas.DrawLine(new SKPoint(XCoord, strikeYPos), new SKPoint(XCoord + Width, strikeYPos), paint);
                }
            }
        }