Skip to content

Commit

Permalink
Fix BaselineAlignment (#16276)
Browse files Browse the repository at this point in the history
* Implement remaining BaselineAlignment variants

* Adjust BaselineOffset calculation

* Draw all shaped runs at the baseline

* Random change please revert

* Revert change
  • Loading branch information
Gillibald committed Jul 15, 2024
1 parent 6dde3f5 commit 376a841
Show file tree
Hide file tree
Showing 4 changed files with 58 additions and 60 deletions.
15 changes: 9 additions & 6 deletions src/Avalonia.Base/Media/TextDecoration.cs
Original file line number Diff line number Diff line change
Expand Up @@ -182,18 +182,18 @@ internal void Draw(DrawingContext drawingContext, GlyphRun glyphRun, TextMetrics
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;
}

Expand Down Expand Up @@ -255,7 +255,10 @@ internal void Draw(DrawingContext drawingContext, GlyphRun glyphRun, TextMetrics
}
}

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);
}
}
}
5 changes: 3 additions & 2 deletions src/Avalonia.Base/Media/TextFormatting/ShapedTextRun.cs
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ public override void Draw(DrawingContext drawingContext, Point origin)

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);
Expand Down Expand Up @@ -204,7 +204,8 @@ internal GlyphRun CreateGlyphRun()
ShapedBuffer.FontRenderingEmSize,
Text,
ShapedBuffer,
biDiLevel: BidiLevel);
biDiLevel: BidiLevel,
baselineOrigin: new Point());
}

public void Dispose()
Expand Down
96 changes: 45 additions & 51 deletions src/Avalonia.Base/Media/TextFormatting/TextLineImpl.cs
Original file line number Diff line number Diff line change
Expand Up @@ -115,18 +115,19 @@ private static double GetBaselineOffset(TextLine textLine, DrawableTextRun textR

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);
}
Expand Down Expand Up @@ -1143,7 +1144,6 @@ public void FinalizeLine()
}

TextRun? currentRun = null;
TextRun? previousRun = null;

while (runIndex < _indexedTextRuns.Count)
{
Expand Down Expand Up @@ -1182,7 +1182,7 @@ public void FinalizeLine()

break;
}
case TextRun:
case not null:
{
if(direction == LogicalDirection.Forward)
{
Expand Down Expand Up @@ -1212,8 +1212,6 @@ public void FinalizeLine()
}

runIndex++;

previousRun = currentRun;
}

return currentRun;
Expand Down Expand Up @@ -1242,61 +1240,57 @@ private TextLineMetrics CreateLineMetrics()
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;
}
}
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1123,7 +1123,7 @@ public void Should_HitTestTextPosition_EndOfLine_RTL()

var rect = textLayout.HitTestTextPosition(text.Length);

Assert.Equal(14.0625, rect.Top);
Assert.Equal(16.32, rect.Top);
}
}

Expand Down

0 comments on commit 376a841

Please sign in to comment.