Skip to content

Commit 9c8d9df

Browse files
Cleanup and document. Vert still buggy.
1 parent 4f10bcd commit 9c8d9df

1 file changed

Lines changed: 24 additions & 9 deletions

File tree

src/ImageSharp.Drawing/Shapes/Text/PathGlyphBuilder.cs

Lines changed: 24 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,29 +41,37 @@ public PathGlyphBuilder(IPath path, LayoutMode layoutMode)
4141
/// <inheritdoc/>
4242
protected override void BeginText(FontRectangle rect)
4343
{
44+
// TODO: This uses the baseline of the text, should it be the bottom?
4445
this.yOffset = rect.Height;
4546
this.xOffset = rect.Left;
4647
}
4748

4849
/// <inheritdoc/>
4950
protected override void BeginGlyph(FontRectangle rect)
5051
{
51-
if (!this.isVerticalLayout)
52+
// https://svgwg.org/svg2-draft/text.html#TextpathLayoutRules
53+
if (this.isVerticalLayout)
5254
{
53-
this.TransformGlyphHorizontal(rect);
55+
this.TransformGlyphVertical(rect);
5456
}
5557
else
5658
{
57-
this.TransformGlyphVertical(rect);
59+
this.TransformGlyphHorizontal(rect);
5860
}
5961
}
6062

6163
[MethodImpl(MethodImplOptions.AggressiveInlining)]
6264
private void TransformGlyphHorizontal(FontRectangle rect)
6365
{
66+
// Find the intersection point. Bottom-centre for horizontal text.
6467
float halfWidth = rect.Width * .5F;
65-
SegmentInfo point = this.path.PointAlongPath(rect.Left + halfWidth - this.xOffset);
66-
Vector2 targetPoint = point.Point + new PointF(-halfWidth, rect.Top - this.yOffset);
68+
Vector2 intersectionPoint = new(rect.Left + halfWidth, rect.Bottom);
69+
70+
// Find the point of this intersection along the given path. This ensures the correct rotation.
71+
SegmentInfo point = this.path.PointAlongPath(intersectionPoint.X - this.xOffset);
72+
73+
// Now offset our target point since we're aligning top-left.
74+
Vector2 targetPoint = point.Point + new PointF(-halfWidth, intersectionPoint.Y - rect.Height - this.yOffset);
6775

6876
// Due to how matrix combining works you have to combine this in the reverse order of operation
6977
// this one rotates the glype then moves it.
@@ -74,12 +82,19 @@ private void TransformGlyphHorizontal(FontRectangle rect)
7482
[MethodImpl(MethodImplOptions.AggressiveInlining)]
7583
private void TransformGlyphVertical(FontRectangle rect)
7684
{
77-
// TODO: Fix this. Vertical text should be rotated at the centre along a different axis.
78-
// https://svgwg.org/svg2-draft/text.html#TextpathLayoutRules
85+
// TODO: Fix this.
86+
// Find the intersection point. Centre-centre for vertical text.
7987
float halfWidth = rect.Width * .5F;
80-
SegmentInfo point = this.path.PointAlongPath(rect.Left + halfWidth - this.xOffset);
81-
Vector2 targetPoint = point.Point + new PointF(-halfWidth, rect.Top - this.yOffset);
88+
float halfHeight = rect.Height * .5F;
89+
Vector2 intersectionPoint = new(rect.Left + halfWidth, rect.Top + halfHeight);
90+
91+
SegmentInfo point = this.path.PointAlongPath(intersectionPoint.X - this.xOffset);
8292

93+
// Now offset our target point since we're aligning top-left.
94+
Vector2 targetPoint = point.Point + new PointF(-halfWidth, intersectionPoint.Y - halfHeight - this.yOffset);
95+
96+
// Due to how matrix combining works you have to combine this in the reverse order of operation
97+
// this one rotates the glype then moves it.
8398
Matrix3x2 matrix = Matrix3x2.CreateTranslation(targetPoint - rect.Location) * Matrix3x2.CreateRotation(point.Angle - Pi, point.Point);
8499
this.builder.SetTransform(matrix);
85100
}

0 commit comments

Comments
 (0)