Skip to content

Commit 00b054f

Browse files
Update ref and fix line rendering
1 parent 9fc9b65 commit 00b054f

8 files changed

Lines changed: 81 additions & 42 deletions

File tree

nuget.config

Lines changed: 0 additions & 10 deletions
This file was deleted.

src/ImageSharp.Drawing/ImageSharp.Drawing.csproj

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@
1818
<None Include="..\..\shared-infrastructure\branding\icons\imagesharp.drawing\sixlabors.imagesharp.drawing.128.png" Pack="true" PackagePath="" />
1919
</ItemGroup>
2020
<ItemGroup>
21-
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta19.9" />
21+
<PackageReference Include="SixLabors.Fonts" Version="1.0.0-beta19.10" />
2222
<PackageReference Include="SixLabors.ImageSharp" Version="2.1.3" />
2323
</ItemGroup>
2424
<Import Project="..\..\shared-infrastructure\src\SharedInfrastructure\SharedInfrastructure.projitems" Label="Shared" />

src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor{TPixel}.cs

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -123,7 +123,8 @@ private static RichTextOptions ConfigureOptions(RichTextOptions options)
123123
{
124124
return new(options)
125125
{
126-
Origin = Vector2.Zero
126+
Origin = Vector2.Zero,
127+
Path = options.Path.Translate(options.Origin)
127128
};
128129
}
129130

src/ImageSharp.Drawing/Processing/Processors/Text/RichTextGlyphRenderer.cs

Lines changed: 40 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,9 @@
1515

1616
namespace SixLabors.ImageSharp.Drawing.Processing.Processors.Text
1717
{
18-
// TODO: Add caching.
18+
/// <summary>
19+
/// Allows the rendering of rich text configured via <see cref="RichTextOptions"/>.
20+
/// </summary>
1921
internal sealed class RichTextGlyphRenderer : BaseGlyphBuilder, IColorGlyphRenderer, IDisposable
2022
{
2123
private const byte RenderOrderFill = 0;
@@ -230,20 +232,42 @@ public override void SetDecoration(TextDecorations textDecorations, Vector2 star
230232
}
231233

232234
// Clamp the line to whole pixels
233-
Vector2 thicknessOffset = new(0, thickness * .5F);
234-
Vector2 tl = start - thicknessOffset;
235-
Vector2 bl = start + thicknessOffset;
236-
Vector2 tr = end - thicknessOffset;
237-
tl.Y = MathF.Floor(tl.Y);
238-
tr.Y = MathF.Floor(tr.Y);
239-
bl.Y = MathF.Ceiling(bl.Y);
240-
tl.X = MathF.Floor(tl.X);
241-
tr.X = MathF.Floor(tr.X);
242-
float newThickness = bl.Y - tl.Y;
243-
Vector2 offsetNew = new(0, newThickness * .5f);
244-
245-
pen ??= new SolidPen(this.currentBrush ?? this.defaultBrush);
246-
this.AppendDecoration(ref targetDecoration, tl + offsetNew, tr + offsetNew, pen, newThickness);
235+
Vector2 pad = new(0, thickness * .5F);
236+
Vector2 tl = start - pad;
237+
Vector2 bl = start + pad;
238+
Vector2 tr = end - pad;
239+
240+
tl.Y = MathF.Round(tl.Y, MidpointRounding.AwayFromZero);
241+
tr.Y = MathF.Round(tr.Y, MidpointRounding.AwayFromZero);
242+
bl.Y = MathF.Round(bl.Y, MidpointRounding.AwayFromZero);
243+
tl.X = MathF.Round(tl.X, MidpointRounding.AwayFromZero);
244+
tr.X = MathF.Round(tr.X, MidpointRounding.AwayFromZero);
245+
246+
// Always respect the pen stroke width if explicitly set.
247+
if (pen is null)
248+
{
249+
thickness = bl.Y - tl.Y;
250+
pen = new SolidPen(this.currentBrush ?? this.defaultBrush, thickness);
251+
}
252+
else
253+
{
254+
thickness = pen.StrokeWidth;
255+
}
256+
257+
// Drawing is always centered around the point so we need to offset by half.
258+
Vector2 offset = Vector2.Zero;
259+
if (textDecorations == TextDecorations.Overline)
260+
{
261+
// CSS overline is drawn above the position, so we need to move it up.
262+
offset = new Vector2(0, -(thickness * .5F));
263+
}
264+
else if (textDecorations == TextDecorations.Underline)
265+
{
266+
// CSS underline is drawn below the position, so we need to move it down.
267+
offset = new Vector2(0, thickness * .5F);
268+
}
269+
270+
this.AppendDecoration(ref targetDecoration, tl + offset, tr + offset, pen, thickness);
247271
}
248272

249273
protected override void EndGlyph()
@@ -357,7 +381,7 @@ private void FinalizeDecoration(ref TextDecorationDetails? decoration)
357381
if (decoration != null)
358382
{
359383
// TODO: If the path is curved a line segment does not work well.
360-
// What would be great would be if we could take a slice of a path given an offset and length.
384+
// What would be great would be if we could take a slice of a path given start and end positions.
361385
IPath path = new Path(new LinearLineSegment(decoration.Value.Start, decoration.Value.End));
362386
IPath outline = decoration.Value.Pen.GeneratePath(path, decoration.Value.Thickness);
363387

src/ImageSharp.Drawing/Processing/RichTextOptions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ public RichTextOptions(RichTextOptions options)
4343
/// </summary>
4444
/// <remarks>
4545
/// When this property is not <see langword="null"/> the <see cref="TextOptions.Origin"/>
46-
/// property is ignored. The text will be drawn along the path starting at the origin of the path.
46+
/// property is automatically applied as a translation to a copy of the path for processing.
4747
/// </remarks>
4848
public IPath Path { get; set; }
4949
}

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

Lines changed: 17 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -147,11 +147,24 @@ public virtual void SetDecoration(TextDecorations textDecorations, Vector2 start
147147
Vector2 bl = start + height;
148148
Vector2 br = end + height;
149149

150+
// Drawing is always centered around the point so we need to offset by half.
151+
Vector2 offset = Vector2.Zero;
152+
if (textDecorations == TextDecorations.Overline)
153+
{
154+
// CSS overline is drawn above the position, so we need to move it up.
155+
offset = new(0, -(thickness * .5F));
156+
}
157+
else if (textDecorations == TextDecorations.Underline)
158+
{
159+
// CSS underline is drawn below the position, so we need to move it down.
160+
offset = new Vector2(0, thickness * .5F);
161+
}
162+
150163
// MoveTo calls StartFigure();
151-
renderer.MoveTo(tl);
152-
renderer.LineTo(bl);
153-
renderer.LineTo(br);
154-
renderer.LineTo(tr);
164+
renderer.MoveTo(tl + offset);
165+
renderer.LineTo(bl + offset);
166+
renderer.LineTo(br + offset);
167+
renderer.LineTo(tr + offset);
155168
renderer.EndFigure();
156169
}
157170
}

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

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -37,29 +37,30 @@ public static IPathCollection GenerateGlyphs(string text, TextOptions textOption
3737
/// <returns>The <see cref="IPathCollection"/></returns>
3838
public static IPathCollection GenerateGlyphs(string text, IPath path, TextOptions textOptions)
3939
{
40-
TextOptions options = ConfigureOptions(textOptions, path);
41-
42-
PathGlyphBuilder glyphBuilder = new(path, options);
40+
(IPath Path, TextOptions TextOptions) transformed = ConfigureOptions(textOptions, path);
41+
PathGlyphBuilder glyphBuilder = new(transformed.Path, transformed.TextOptions);
4342
TextRenderer renderer = new(glyphBuilder);
4443

45-
renderer.RenderText(text, options);
44+
renderer.RenderText(text, transformed.TextOptions);
4645

4746
return glyphBuilder.Paths;
4847
}
4948

50-
private static TextOptions ConfigureOptions(TextOptions options, IPath path)
49+
private static (IPath Path, TextOptions TextOptions) ConfigureOptions(TextOptions options, IPath path)
5150
{
5251
// When a path is specified we should explicitly follow that path
5352
// and not adjust the origin. Any translation should be applied to the path.
5453
if (path is not null && options.Origin != Vector2.Zero)
5554
{
56-
return new(options)
55+
TextOptions clone = new(options)
5756
{
5857
Origin = Vector2.Zero
5958
};
59+
60+
return (path.Translate(options.Origin), clone);
6061
}
6162

62-
return options;
63+
return (path, options);
6364
}
6465
}
6566
}

tests/ImageSharp.Drawing.Tests/Drawing/Text/DrawTextOnImageTests.cs

Lines changed: 12 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -514,12 +514,21 @@ public void DrawRichText<TPixel>(
514514
WrappingLength = 400,
515515
TextRuns = new[]
516516
{
517+
new RichTextRun
518+
{
519+
Start = 0,
520+
End = 3,
521+
OverlinePen = Pens.Solid(Color.Yellow, 1),
522+
StrikeoutPen = Pens.Solid(Color.HotPink, 5),
523+
},
524+
517525
new RichTextRun
518526
{
519527
Start = 4,
520528
End = 10,
521529
TextDecorations = TextDecorations.Strikeout,
522530
StrikeoutPen = Pens.Solid(Color.Red),
531+
OverlinePen = Pens.Solid(Color.Green, 9),
523532
Brush = Brushes.Solid(Color.Red),
524533
},
525534

@@ -529,15 +538,16 @@ public void DrawRichText<TPixel>(
529538
End = 13,
530539
Font = font2,
531540
TextDecorations = TextDecorations.Strikeout,
532-
StrikeoutPen = Pens.Solid(Color.White),
541+
StrikeoutPen = Pens.Solid(Color.White, 6),
542+
OverlinePen = Pens.Solid(Color.Orange, 2),
533543
},
534544

535545
new RichTextRun
536546
{
537547
Start = 19,
538548
End = 23,
539549
TextDecorations = TextDecorations.Underline,
540-
UnderlinePen = Pens.Dot(Color.Fuchsia, 2),
550+
UnderlinePen = Pens.Dot(Color.Fuchsia, 5),
541551
Brush = Brushes.Solid(Color.Blue),
542552
},
543553

0 commit comments

Comments
 (0)