diff --git a/src/Avalonia.Base/Media/TextDecoration.cs b/src/Avalonia.Base/Media/TextDecoration.cs index 8661959aa6..beac28da4a 100644 --- a/src/Avalonia.Base/Media/TextDecoration.cs +++ b/src/Avalonia.Base/Media/TextDecoration.cs @@ -182,18 +182,18 @@ namespace Avalonia.Media break; } - var origin = new Point(); + var origin = baselineOrigin; switch (Location) { - case TextDecorationLocation.Baseline: - origin += glyphRun.BaselineOrigin; + case TextDecorationLocation.Overline: + origin += new Point(0, textMetrics.Ascent); break; case TextDecorationLocation.Strikethrough: - origin += new Point(baselineOrigin.X, baselineOrigin.Y + textMetrics.StrikethroughPosition); + origin += new Point(0, textMetrics.StrikethroughPosition); break; case TextDecorationLocation.Underline: - origin += new Point(baselineOrigin.X, baselineOrigin.Y + textMetrics.UnderlinePosition); + origin += new Point(0, textMetrics.UnderlinePosition); break; } @@ -255,7 +255,10 @@ namespace Avalonia.Media } } - drawingContext.DrawLine(pen, origin, origin + new Point(glyphRun.Metrics.Width, 0)); + var p1 = origin; + var p2 = p1 + new Point(glyphRun.Metrics.Width, 0); + + drawingContext.DrawLine(pen, p1, p2); } } } diff --git a/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs b/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs index a1dc0827e8..5bb8ad5b95 100644 --- a/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs +++ b/src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs @@ -64,7 +64,7 @@ namespace Avalonia.Media.TextFormatting if (Properties.BackgroundBrush != null) { - drawingContext.DrawRectangle(Properties.BackgroundBrush, null, GlyphRun.Bounds); + drawingContext.DrawRectangle(Properties.BackgroundBrush, null, GlyphRun.Bounds.Translate(new Vector(0, -Baseline))); } drawingContext.DrawGlyphRun(Properties.ForegroundBrush, GlyphRun); @@ -204,7 +204,8 @@ namespace Avalonia.Media.TextFormatting ShapedBuffer.FontRenderingEmSize, Text, ShapedBuffer, - biDiLevel: BidiLevel); + biDiLevel: BidiLevel, + baselineOrigin: new Point()); } public void Dispose() diff --git a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs index 954a9b2deb..cbed2cea27 100644 --- a/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs +++ b/src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs @@ -115,18 +115,19 @@ namespace Avalonia.Media.TextFormatting switch (baselineAlignment) { + case BaselineAlignment.Baseline: + return textLine.Baseline; case BaselineAlignment.Top: - return 0; + case BaselineAlignment.TextTop: + return textLine.Baseline - textLine.Extent + textRun.Size.Height / 2; case BaselineAlignment.Center: - return textLine.Height / 2 - textRun.Size.Height / 2; + return textLine.Height / 2 + baseline - textRun.Size.Height / 2; + case BaselineAlignment.Subscript: case BaselineAlignment.Bottom: - return textLine.Height - textRun.Size.Height; - case BaselineAlignment.Baseline: - case BaselineAlignment.TextTop: case BaselineAlignment.TextBottom: - case BaselineAlignment.Subscript: + return textLine.Height - textRun.Size.Height + baseline; case BaselineAlignment.Superscript: - return textLine.Baseline - baseline; + return baseline; default: throw new ArgumentOutOfRangeException(nameof(baselineAlignment), baselineAlignment, null); } @@ -1143,7 +1144,6 @@ namespace Avalonia.Media.TextFormatting } TextRun? currentRun = null; - TextRun? previousRun = null; while (runIndex < _indexedTextRuns.Count) { @@ -1182,7 +1182,7 @@ namespace Avalonia.Media.TextFormatting break; } - case TextRun: + case not null: { if(direction == LogicalDirection.Forward) { @@ -1212,8 +1212,6 @@ namespace Avalonia.Media.TextFormatting } runIndex++; - - previousRun = currentRun; } return currentRun; @@ -1242,61 +1240,57 @@ namespace Avalonia.Media.TextFormatting switch (_textRuns[index]) { case ShapedTextRun textRun: - { - var textMetrics = textRun.TextMetrics; - var glyphRun = textRun.GlyphRun; - var runBounds = glyphRun.InkBounds.WithX(widthIncludingWhitespace + glyphRun.InkBounds.X); + { + var textMetrics = textRun.TextMetrics; + var glyphRun = textRun.GlyphRun; + var runBounds = glyphRun.InkBounds.WithX(widthIncludingWhitespace + glyphRun.InkBounds.X); - bounds = bounds.Union(runBounds); + bounds = bounds.Union(runBounds); - if (fontRenderingEmSize < textMetrics.FontRenderingEmSize) - { - fontRenderingEmSize = textMetrics.FontRenderingEmSize; + if (ascent > textMetrics.Ascent) + { + ascent = textMetrics.Ascent; + } - if (ascent > textMetrics.Ascent) - { - ascent = textMetrics.Ascent; - } + if (descent < textMetrics.Descent) + { + descent = textMetrics.Descent; + } - if (descent < textMetrics.Descent) - { - descent = textMetrics.Descent; - } + if (lineGap < textMetrics.LineGap) + { + lineGap = textMetrics.LineGap; + } - if (lineGap < textMetrics.LineGap) - { - lineGap = textMetrics.LineGap; - } + if (descent - ascent + lineGap > height) + { + height = descent - ascent + lineGap; + } - if (descent - ascent + lineGap > height) - { - height = descent - ascent + lineGap; - } - } - widthIncludingWhitespace += textRun.Size.Width; + widthIncludingWhitespace += textRun.Size.Width; - break; - } + break; + } case DrawableTextRun drawableTextRun: + { + widthIncludingWhitespace += drawableTextRun.Size.Width; + + if (drawableTextRun.Size.Height > height) { - widthIncludingWhitespace += drawableTextRun.Size.Width; + height = drawableTextRun.Size.Height; + } - if (drawableTextRun.Size.Height > height) - { - height = drawableTextRun.Size.Height; - } - - //Adjust current ascent so drawables and text align at the bottom edge of the line. - var offset = Math.Max(0, drawableTextRun.Baseline + ascent - descent); + //Adjust current ascent so drawables and text align at the bottom edge of the line. + var offset = Math.Max(0, drawableTextRun.Baseline + ascent - descent); - ascent -= offset; + ascent -= offset; - bounds = bounds.Union(new Rect(new Point(bounds.Right, 0), drawableTextRun.Size)); + bounds = bounds.Union(new Rect(new Point(bounds.Right, 0), drawableTextRun.Size)); - break; - } + break; + } } } diff --git a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs index cb9b378986..3d19efeae9 100644 --- a/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs +++ b/tests/Avalonia.Skia.UnitTests/Media/TextFormatting/TextLayoutTests.cs @@ -1123,7 +1123,7 @@ namespace Avalonia.Skia.UnitTests.Media.TextFormatting var rect = textLayout.HitTestTextPosition(text.Length); - Assert.Equal(14.0625, rect.Top); + Assert.Equal(16.32, rect.Top); } }