Beispiel #1
0
 /// <summary>
 /// Paint this line
 /// </summary>
 /// <param name="ctx">The paint context</param>
 internal void Paint(PaintTextContext ctx)
 {
     foreach (var r in Runs)
     {
         r.Paint(ctx);
     }
 }
Beispiel #2
0
 /// <summary>
 /// Paint background of this font run
 /// </summary>
 /// <param name="ctx"></param>
 internal void PaintBackground(PaintTextContext ctx)
 {
     if (Style.BackgroundColor != SKColor.Empty && RunKind == FontRunKind.Normal)
     {
         var rect = new SKRect(XCoord, Line.YCoord,
                               XCoord + Width, Line.YCoord + Line.Height);
         using (var skPaint = new SKPaint {
             Style = SKPaintStyle.Fill, Color = Style.BackgroundColor
         })
         {
             ctx.Canvas.DrawRect(rect, skPaint);
         }
     }
 }
Beispiel #3
0
        /// <summary>
        /// Paint this font run
        /// </summary>
        /// <param name="ctx"></param>
        internal void Paint(PaintTextContext ctx)
        {
            // Paint selection?
            if (ctx.PaintSelectionBackground != null && RunKind != FontRunKind.Ellipsis)
            {
                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 tl = new SKPoint(selStartXCoord + this.XCoord, Line.YCoord);
                    var br = new SKPoint(selEndXCoord + this.XCoord, Line.YCoord + Line.Height);

                    // Align coords to pixel boundaries
                    // Not needed - disabled antialias on SKPaint instead

                    /*
                     * if (ctx.Canvas.TotalMatrix.TryInvert(out var inverse))
                     * {
                     *  tl = ctx.Canvas.TotalMatrix.MapPoint(tl);
                     *  br = ctx.Canvas.TotalMatrix.MapPoint(br);
                     *  tl = new SKPoint((float)Math.Round(tl.X), (float)Math.Round(tl.Y));
                     *  br = new SKPoint((float)Math.Round(br.X), (float)Math.Round(br.Y));
                     *  tl = inverse.MapPoint(tl);
                     *  br = inverse.MapPoint(br);
                     * }
                     */

                    var rect = new SKRect(tl.X, tl.Y, br.X, br.Y);
                    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.IsAntialias   = ctx.Options.IsAntialias;
                paint.LcdRenderText = ctx.Options.LcdRenderText;

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

                        // Create the font
                        if (_font == null)
                        {
                            _font          = new SKFont(this.Typeface, this.Style.FontSize * glyphScale);
                            _font.Subpixel = true;
                        }

                        // Create the SKTextBlob (if necessary)
                        if (_textBlob == null)
                        {
                            _textBlob = SKTextBlob.CreatePositioned(
                                (IntPtr)(pGlyphs + Glyphs.Start),
                                Glyphs.Length * sizeof(ushort),
                                SKTextEncoding.GlyphId,
                                _font,
                                GlyphPositions.AsSpan());
                        }

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

                            if (Style.Underline == UnderlineStyle.Gapped)
                            {
                                // Get intercept positions
                                var interceptPositions = _textBlob.GetIntercepts(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
                            {
                                switch (Style.Underline)
                                {
                                case UnderlineStyle.ImeInput:
                                    paint.PathEffect = SKPathEffect.CreateDash(new float[] { paint.StrokeWidth, paint.StrokeWidth }, paint.StrokeWidth);
                                    break;

                                case UnderlineStyle.ImeConverted:
                                    paint.PathEffect = SKPathEffect.CreateDash(new float[] { paint.StrokeWidth, paint.StrokeWidth }, paint.StrokeWidth);
                                    break;

                                case UnderlineStyle.ImeTargetConverted:
                                    paint.StrokeWidth *= 2;
                                    break;

                                case UnderlineStyle.ImeTargetNonConverted:
                                    break;
                                }
                                // Paint solid underline
                                ctx.Canvas.DrawLine(new SKPoint(XCoord, underlineYPos), new SKPoint(XCoord + Width, underlineYPos), paint);
                                paint.PathEffect = null;
                            }
                        }


                        ctx.Canvas.DrawText(_textBlob, 0, 0, paint);
                    }
                }

                // Paint strikethrough
                if (Style.StrikeThrough != StrikeThroughStyle.None && RunKind == FontRunKind.Normal)
                {
                    paint.StrokeWidth = _font.Metrics.StrikeoutThickness ?? 0;
                    float strikeYPos = Line.YCoord + Line.BaseLine + (_font.Metrics.StrikeoutPosition ?? 0) + glyphVOffset;
                    ctx.Canvas.DrawLine(new SKPoint(XCoord, strikeYPos), new SKPoint(XCoord + Width, strikeYPos), paint);
                }
            }
        }
Beispiel #4
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);
                }
            }
        }