Skip to content

Commit 090c68e

Browse files
committed
fixes #175 - Text gets chopped when rotated >60 degrees.
The glyph size is not rendered with enough space when rotated, this fixes the issue at all rotation angles
1 parent 0ccea4d commit 090c68e

5 files changed

Lines changed: 92 additions & 3 deletions

File tree

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

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@ protected override void BeforeImageApply()
3535
this.textRenderer = new CachingGlyphRenderer(
3636
this.Configuration.MemoryAllocator,
3737
this.definition.Text.Length,
38+
this.definition.TextOptions,
3839
this.definition.Pen,
3940
this.definition.Brush != null,
4041
this.definition.DrawingOptions.Transform)
@@ -173,22 +174,21 @@ private class CachingGlyphRenderer : IColorGlyphRenderer, IDisposable
173174
private readonly bool renderFill;
174175
private bool rasterizationRequired;
175176

176-
public CachingGlyphRenderer(MemoryAllocator memoryAllocator, int size, IPen pen, bool renderFill, Matrix3x2 transform)
177+
public CachingGlyphRenderer(MemoryAllocator memoryAllocator, int size, TextOptions textOptions, IPen pen, bool renderFill, Matrix3x2 transform)
177178
{
178179
this.MemoryAllocator = memoryAllocator;
179180
this.currentRenderPosition = default;
180181
this.Pen = pen;
181182
this.renderFill = renderFill;
182183
this.renderOutline = pen != null;
183-
this.offset = 2;
184+
this.offset = (int)textOptions.Font.Size;
184185
if (this.renderFill)
185186
{
186187
this.FillOperations = new List<DrawingOperation>(size);
187188
}
188189

189190
if (this.renderOutline)
190191
{
191-
this.offset = (int)MathF.Ceiling((pen.StrokeWidth * 2) + 2);
192192
this.OutlineOperations = new List<DrawingOperation>(size);
193193
}
194194

Lines changed: 79 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,79 @@
1+
// Copyright (c) Six Labors.
2+
// Licensed under the Apache License, Version 2.0.
3+
4+
using System.Collections.Generic;
5+
using System.Linq;
6+
using SixLabors.ImageSharp.Drawing.Processing;
7+
using SixLabors.ImageSharp.Drawing.Tests.TestUtilities.ImageComparison;
8+
using SixLabors.ImageSharp.PixelFormats;
9+
using SixLabors.ImageSharp.Processing;
10+
using Xunit;
11+
12+
namespace SixLabors.ImageSharp.Drawing.Tests.Issues
13+
{
14+
public class Issue_175
15+
{
16+
[Fact]
17+
public void CanRotateFilledFont()
18+
{
19+
if (!TestEnvironment.IsWindows)
20+
{
21+
return;
22+
}
23+
24+
using (var image = new Image<Rgba32>(300, 200))
25+
{
26+
string text = "QuickTYZ";
27+
int rotationAngle = 90;
28+
Fonts.Font font = Fonts.SystemFonts.CreateFont("Arial", 40, Fonts.FontStyle.Regular);
29+
30+
AffineTransformBuilder builder = new AffineTransformBuilder()
31+
.AppendRotationDegrees(rotationAngle)
32+
.AppendTranslation(new PointF(0, 0));
33+
var drawingOptions = new DrawingOptions
34+
{
35+
Transform = builder.BuildMatrix(image.Bounds())
36+
};
37+
38+
image.Mutate(c => c.DrawText(drawingOptions, text, font, Brushes.Solid(Color.Red), new PointF(0, 0)));
39+
40+
// ensure the font renders the same as the test image
41+
IEnumerable<ImageSimilarityReport> reports = ExactImageComparer.Instance.CompareImages(Image.Load<Rgba32>(TestFile.GetInputFileFullPath(TestImages.Png.Issue175Filled)), image);
42+
Assert.False(reports.Any());
43+
44+
// image.SaveAsPng(@"./issue175_filled.png");
45+
}
46+
}
47+
48+
[Fact]
49+
public void CanRotateOutlineFont()
50+
{
51+
if (!TestEnvironment.IsWindows)
52+
{
53+
return;
54+
}
55+
56+
using (var image = new Image<Rgba32>(300, 200))
57+
{
58+
string text = "QuickTYZ";
59+
int rotationAngle = 90;
60+
Fonts.Font font = Fonts.SystemFonts.CreateFont("Arial", 40, Fonts.FontStyle.Regular);
61+
62+
AffineTransformBuilder builder = new AffineTransformBuilder()
63+
.AppendRotationDegrees(rotationAngle)
64+
.AppendTranslation(new PointF(0, 0));
65+
var drawingOptions = new DrawingOptions
66+
{
67+
Transform = builder.BuildMatrix(image.Bounds())
68+
};
69+
image.Mutate(c => c.DrawText(drawingOptions, text, font, Pens.Solid(Color.Blue, 1), new PointF(0, 0)));
70+
71+
// ensure the font renders the same as the test image
72+
IEnumerable<ImageSimilarityReport> reports = ExactImageComparer.Instance.CompareImages(Image.Load<Rgba32>(TestFile.GetInputFileFullPath(TestImages.Png.Issue175Outlined)), image);
73+
Assert.False(reports.Any());
74+
75+
// image.SaveAsPng(@"./issue175_outlined.png");
76+
}
77+
}
78+
}
79+
}

tests/ImageSharp.Drawing.Tests/TestImages.cs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -90,6 +90,10 @@ public static class Png
9090
public const string Issue1014_5 = "Png/issues/Issue_1014_5.png";
9191
public const string Issue1014_6 = "Png/issues/Issue_1014_6.png";
9292

93+
// Issue 175: https://github.com/SixLabors/ImageSharp.Drawing/issues/175
94+
public const string Issue175Filled = "Png/issues/issue175_filled.png";
95+
public const string Issue175Outlined = "Png/issues/issue175_outlined.png";
96+
9397
public static class Bad
9498
{
9599
// Odd chunk lengths
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading

0 commit comments

Comments
 (0)