Skip to content

LabelStyle: Add underline support#4893

Merged
swharden merged 5 commits intoScottPlot:mainfrom
manaruto:underline-text
Aug 8, 2025
Merged

LabelStyle: Add underline support#4893
swharden merged 5 commits intoScottPlot:mainfrom
manaruto:underline-text

Conversation

@manaruto
Copy link
Contributor

@manaruto manaruto commented Apr 1, 2025

This pull request adds support for underlining text in labels, with complete compatibility for right-to-left (RTL) scripts using SKShaper from SkiaSharp.HarfBuzz. The enhancement works seamlessly with multi-line text.

✅ Solves:

  • Previously LabelStyle does not support underline property.

Changes Made

LabelStyle.cs

  • Added Underline property to enable underline rendering.
  • Added UnderlineStrokeWidth and UnderlineOffset for full customization.
  • Underlines render beneath shaped text using accurate width (with HarfBuzz).
public bool Underline { get; set; } = false;
public float UnderlineStrokeWidth { get; set; } = 1;
public float UnderlineOffset { get; set; } = 2f;
if (LabelStyle.RTLSupport)
{
    using (var shaper = new SKShaper(paint.Typeface))
    {
        float shapedWidth = shaper.Shape(lines[i], paint).Width;
        canvas.DrawShapedText(shaper, lines[i], xPx, yPx, paint);

        if (Underline)
        {
            float underlineY = yPx + UnderlineOffset;

            using var underlinePaint = new SKPaint
            {
                Color = paint.Color,
                StrokeWidth = UnderlineStrokeWidth,
                IsStroke = true,
                IsAntialias = paint.IsAntialias
            };

            canvas.DrawLine(xPx, underlineY, xPx + shapedWidth, underlineY, underlinePaint);
        }
    }
}
else
{
    canvas.DrawText(lines[i], xPx, yPx, paint);

    if (Underline)
    {
        float underlineY = yPx + UnderlineOffset;
        float textWidth = paint.MeasureText(lines[i]);

        using var underlinePaint = new SKPaint
        {
            Color = paint.Color,
            StrokeWidth = UnderlineStrokeWidth,
            IsStroke = true,
            IsAntialias = paint.IsAntialias
        };
        canvas.DrawLine(xPx, underlineY, xPx + textWidth, underlineY, underlinePaint);
    }
}

LabelStyleProperties.cs

  • Added public shortcuts for new underline properties to be access by Text class
public bool LabelUnderline { get => LabelStyle.Underline; set => LabelStyle.Underline = value; }
public float LabelUnderlineStrokeWidth { get => LabelStyle.UnderlineStrokeWidth; set => LabelStyle.UnderlineStrokeWidth = value; }
public float LabelUnderlineOffset { get => LabelStyle.UnderlineOffset; set => LabelStyle.UnderlineOffset = value; }

underline

@swharden swharden added the defer Action is required, so Scott will focus on closing simpler issues and PRs then return to this label Jun 16, 2025
@swharden
Copy link
Member

This is awesome, thanks @manaruto! This is related to #4873 so I'll work on both at the same time, but I'll leave this here for a bit while I focus first on clearing out some high priority PRs.

Thanks again!
Scott

@swharden swharden changed the title Feature: Underline Text Rendering LabelStyle: Add underline support Jun 16, 2025
@swharden swharden removed the defer Action is required, so Scott will focus on closing simpler issues and PRs then return to this label Jul 29, 2025
@swharden
Copy link
Member

swharden commented Aug 8, 2025

This is so great @manaruto, thanks so much! Merging now 🚀

@swharden swharden enabled auto-merge (squash) August 8, 2025 00:16
@swharden swharden merged commit 0bf3f3b into ScottPlot:main Aug 8, 2025
3 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Underline Text

2 participants