Skip to content

Commit eb22180

Browse files
Merge pull request #191 from replaysMike/bugs/mbrown/issue175-text-gets-chopped-when-rotated
fixes #175 - Text gets chopped when rotated >60 degrees.
2 parents 0ccea4d + 3468b8c commit eb22180

7 files changed

Lines changed: 71 additions & 5 deletions

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

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

Lines changed: 54 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -439,6 +439,60 @@ public void CanDrawTextWithEmptyPath()
439439
Vector2.Zero));
440440
}
441441

442+
[Theory]
443+
[WithSolidFilledImages(300, 200, nameof(Color.White), PixelTypes.Rgba32, TestFonts.OpenSans, 32, 75F)]
444+
[WithSolidFilledImages(300, 200, nameof(Color.White), PixelTypes.Rgba32, TestFonts.OpenSans, 40, 90F)]
445+
public void CanRotateFilledFont_Issue175<TPixel>(
446+
TestImageProvider<TPixel> provider,
447+
string fontName,
448+
int fontSize,
449+
float angle)
450+
where TPixel : unmanaged, IPixel<TPixel>
451+
{
452+
Font font = CreateFont(fontName, fontSize);
453+
const string text = "QuickTYZ";
454+
AffineTransformBuilder builder = new AffineTransformBuilder().AppendRotationDegrees(angle);
455+
456+
TextOptions textOptions = new(font);
457+
FontRectangle bounds = TextMeasurer.Measure(text, textOptions);
458+
Matrix3x2 transform = builder.BuildMatrix(Rectangle.Round(new RectangleF(bounds.X, bounds.Y, bounds.Width, bounds.Height)));
459+
460+
provider.RunValidatingProcessorTest(
461+
x => x.SetDrawingTransform(transform).DrawText(textOptions, text, Color.Black),
462+
$"F({fontName})-S({fontSize})-A({angle})-{ToTestOutputDisplayText(text)})",
463+
TextDrawingComparer,
464+
appendPixelTypeToFileName: false,
465+
appendSourceFileOrDescription: true);
466+
}
467+
468+
[Theory]
469+
[WithSolidFilledImages(300, 200, nameof(Color.White), PixelTypes.Rgba32, TestFonts.OpenSans, 32, 75F, 1)]
470+
[WithSolidFilledImages(300, 200, nameof(Color.White), PixelTypes.Rgba32, TestFonts.OpenSans, 40, 90F, 2)]
471+
public void CanRotateOutlineFont_Issue175<TPixel>(
472+
TestImageProvider<TPixel> provider,
473+
string fontName,
474+
int fontSize,
475+
float angle,
476+
int strokeWidth)
477+
where TPixel : unmanaged, IPixel<TPixel>
478+
{
479+
Font font = CreateFont(fontName, fontSize);
480+
const string text = "QuickTYZ";
481+
AffineTransformBuilder builder = new AffineTransformBuilder().AppendRotationDegrees(angle);
482+
483+
TextOptions textOptions = new(font);
484+
FontRectangle bounds = TextMeasurer.Measure(text, textOptions);
485+
Matrix3x2 transform = builder.BuildMatrix(Rectangle.Round(new RectangleF(bounds.X, bounds.Y, bounds.Width, bounds.Height)));
486+
487+
provider.RunValidatingProcessorTest(
488+
x => x.SetDrawingTransform(transform)
489+
.DrawText(textOptions, text, Pens.Solid(Color.Black, strokeWidth)),
490+
$"F({fontName})-S({fontSize})-A({angle})-STR({strokeWidth})-{ToTestOutputDisplayText(text)})",
491+
TextDrawingComparer,
492+
appendPixelTypeToFileName: false,
493+
appendSourceFileOrDescription: true);
494+
}
495+
442496
private static string Repeat(string str, int times) => string.Concat(Enumerable.Repeat(str, times));
443497

444498
private static string ToTestOutputDisplayText(string text)
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 3 additions & 0 deletions
Loading
Lines changed: 2 additions & 2 deletions
Loading

0 commit comments

Comments
 (0)