From f8f7a0655c38f8423969fefed2cd138815af87b9 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Sat, 27 Oct 2018 15:32:48 +0100 Subject: [PATCH 1/8] prevent text wandering from baseline --- .../Processors/Text/DrawTextProcessor.cs | 21 +++++++++++++------ .../Drawing/Text/DrawTextOnImageTests.cs | 4 ++-- tests/Images/External | 2 +- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs index 1095de325f..49a6530633 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs @@ -97,7 +97,8 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text this.textRenderer = new CachingGlyphRenderer(source.GetMemoryAllocator(), this.Text.Length, this.Pen, this.Brush != null); this.textRenderer.Options = (GraphicsOptions)this.Options; - TextRenderer.RenderTextTo(this.textRenderer, this.Text, style); + var renderer = new TextRenderer(this.textRenderer); + renderer.RenderText(this.Text, style); } protected override void AfterImageApply(Image source, Rectangle sourceRectangle) @@ -164,14 +165,18 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text private class CachingGlyphRenderer : IGlyphRenderer, IDisposable { + // just enough accuracy to allow for half pixel differences which + // later are componded into full pixel offsets while rendering. + private const float AcuracyMultiple = 2; + private PathBuilder builder; private Point currentRenderPosition = default; - private GlyphRendererParameters currentGlyphRenderParams = default; + private (GlyphRendererParameters glyph, PointF subPixelOffset) currentGlyphRenderParams = default; private int offset = 0; private PointF currentPoint = default(PointF); - private readonly Dictionary glyphData = new Dictionary(); + private readonly Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> glyphData = new Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData>(); private bool renderOutline = false; private bool renderFill = false; @@ -216,11 +221,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text public bool BeginGlyph(RectangleF bounds, GlyphRendererParameters paramters) { this.currentRenderPosition = Point.Truncate(bounds.Location); + PointF dif = bounds.Location - this.currentRenderPosition; + + dif.X = ((int)(dif.X * AcuracyMultiple)) / AcuracyMultiple; + dif.Y = ((int)(dif.Y * AcuracyMultiple)) / AcuracyMultiple; // we have offset our rendering origion a little bit down to prevent edge cropping, move the draw origin up to compensate this.currentRenderPosition = new Point(this.currentRenderPosition.X - this.offset, this.currentRenderPosition.Y - this.offset); - this.currentGlyphRenderParams = paramters; - if (this.glyphData.ContainsKey(paramters)) + this.currentGlyphRenderParams = (paramters, dif); + if (this.glyphData.ContainsKey(this.currentGlyphRenderParams)) { // we have already drawn the glyph vectors skip trying again this.raterizationRequired = false; @@ -252,7 +261,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text public void Dispose() { - foreach (KeyValuePair kv in this.glyphData) + foreach (KeyValuePair<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> kv in this.glyphData) { kv.Value.Dispose(); } diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs index 44bb160ce3..6d7c86409c 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -22,8 +22,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text private const string TestText = "Sphinx of black quartz, judge my vow\n0123456789"; - public static ImageComparer TextDrawingComparer = ImageComparer.TolerantPercentage(0.01f); - public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.TolerantPercentage(0.5f, 3); + public static ImageComparer TextDrawingComparer = ImageComparer.Exact;//.TolerantPercentage(0.01f); + public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.Exact;// TolerantPercentage(0.5f, 3); [Theory] [WithSolidFilledImages(200, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "SixLaborsSampleAB.woff", AB)] diff --git a/tests/Images/External b/tests/Images/External index c6980db777..5634b8b2af 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit c6980db777e49d5e526b56cb986001d1a191acdf +Subproject commit 5634b8b2affa1158cec31ccbb67f9583e9137234 From a51c6b4af5e57431cb5b3b80f78f8986b5b31550 Mon Sep 17 00:00:00 2001 From: Scott Williams Date: Sat, 27 Oct 2018 15:42:10 +0100 Subject: [PATCH 2/8] remove commented out tolerances --- tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs index 6d7c86409c..a02b65ef08 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -22,8 +22,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text private const string TestText = "Sphinx of black quartz, judge my vow\n0123456789"; - public static ImageComparer TextDrawingComparer = ImageComparer.Exact;//.TolerantPercentage(0.01f); - public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.Exact;// TolerantPercentage(0.5f, 3); + public static ImageComparer TextDrawingComparer = ImageComparer.Exact; + public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.Exact; [Theory] [WithSolidFilledImages(200, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "SixLaborsSampleAB.woff", AB)] From 190d133b2c92368737b2cc3f7d6def60acd90b4c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sat, 27 Oct 2018 17:22:52 +0200 Subject: [PATCH 3/8] fix typos & cleanup --- .../Processors/Text/DrawTextProcessor.cs | 29 ++++++++++--------- 1 file changed, 15 insertions(+), 14 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs index 49a6530633..478358191d 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs @@ -167,20 +167,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text { // just enough accuracy to allow for half pixel differences which // later are componded into full pixel offsets while rendering. - private const float AcuracyMultiple = 2; + private const float AccuracyMultiple = 2; - private PathBuilder builder; + private readonly PathBuilder builder; private Point currentRenderPosition = default; private (GlyphRendererParameters glyph, PointF subPixelOffset) currentGlyphRenderParams = default; - private int offset = 0; + private readonly int offset = 0; private PointF currentPoint = default(PointF); - private readonly Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> glyphData = new Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData>(); + private readonly Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData> + glyphData = new Dictionary<(GlyphRendererParameters glyph, PointF subPixelOffset), GlyphRenderData>(); - private bool renderOutline = false; - private bool renderFill = false; - private bool raterizationRequired = false; + private readonly bool renderOutline = false; + private readonly bool renderFill = false; + private bool rasterizationRequired = false; public CachingGlyphRenderer(MemoryAllocator memoryAllocator, int size, IPen pen, bool renderFill) { @@ -218,21 +219,21 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text this.builder.StartFigure(); } - public bool BeginGlyph(RectangleF bounds, GlyphRendererParameters paramters) + public bool BeginGlyph(RectangleF bounds, GlyphRendererParameters parameters) { this.currentRenderPosition = Point.Truncate(bounds.Location); PointF dif = bounds.Location - this.currentRenderPosition; - dif.X = ((int)(dif.X * AcuracyMultiple)) / AcuracyMultiple; - dif.Y = ((int)(dif.Y * AcuracyMultiple)) / AcuracyMultiple; + dif.X = ((int)(dif.X * AccuracyMultiple)) / AccuracyMultiple; + dif.Y = ((int)(dif.Y * AccuracyMultiple)) / AccuracyMultiple; // we have offset our rendering origion a little bit down to prevent edge cropping, move the draw origin up to compensate this.currentRenderPosition = new Point(this.currentRenderPosition.X - this.offset, this.currentRenderPosition.Y - this.offset); - this.currentGlyphRenderParams = (paramters, dif); + this.currentGlyphRenderParams = (parameters, dif); if (this.glyphData.ContainsKey(this.currentGlyphRenderParams)) { // we have already drawn the glyph vectors skip trying again - this.raterizationRequired = false; + this.rasterizationRequired = false; return false; } @@ -242,7 +243,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text // ensure all glyphs render around [zero, zero] so offset negative root positions so when we draw the glyph we can offet it back this.builder.SetOrigin(new PointF(-(int)bounds.X + this.offset, -(int)bounds.Y + this.offset)); - this.raterizationRequired = true; + this.rasterizationRequired = true; return true; } @@ -279,7 +280,7 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text GlyphRenderData renderData = default; // has the glyoh been rendedered already???? - if (this.raterizationRequired) + if (this.rasterizationRequired) { IPath path = this.builder.Build(); From 96042fd12657d58fa05575f5c6e3e6f46ef501d6 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 28 Oct 2018 15:51:11 +0100 Subject: [PATCH 4/8] use strict - but not exact - comparison in DrawTextOnImageTests --- tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs index a02b65ef08..2acb3d5e31 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -22,8 +22,8 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text private const string TestText = "Sphinx of black quartz, judge my vow\n0123456789"; - public static ImageComparer TextDrawingComparer = ImageComparer.Exact; - public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.Exact; + public static ImageComparer TextDrawingComparer = ImageComparer.TolerantPercentage(1e-5f); + public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.TolerantPercentage(1e-4f); [Theory] [WithSolidFilledImages(200, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "SixLaborsSampleAB.woff", AB)] From 6aa8f0ac4099e1f741a2903321aad9da3045365c Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 28 Oct 2018 16:41:22 +0100 Subject: [PATCH 5/8] Failing test case based on #685 --- .../Drawing/Text/DrawTextOnImageTests.cs | 23 +++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs index 2acb3d5e31..09aeef35ce 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -151,6 +151,27 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text appendSourceFileOrDescription: true); } + [Theory] + [WithSolidFilledImages(1000, 1500, "White", PixelTypes.Rgba32)] + public static void TextPositioningIsRobust(TestImageProvider provider) + where TPixel : struct, IPixel + { + if (!TestEnvironment.IsWindows) + { + // Does the system font "Baskerville Old Face" exist on most Linux/MAC machines? + return; + } + + Font font = SystemFonts.CreateFont("Baskerville Old Face", 30, FontStyle.Regular); + + string text = Repeat("Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Beware the Jubjub bird, and shun The frumious Bandersnatch!\n", + 20); + var textOptions = new TextGraphicsOptions(true) { WrapTextWidth = 1000 }; + + provider.RunValidatingProcessorTest( + x => x.DrawText(textOptions, text, font, NamedColors.Black, new PointF(10, 50)), appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); + } + private static string Repeat(string str, int times) => string.Concat(Enumerable.Repeat(str, times)); private static string ToTestOutputDisplayText(string text) @@ -167,5 +188,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text Font font = fontCollection.Install(fontPath).CreateFont(size); return font; } + + } } From 381f83d5438da496f30e5f37c5d7e15cfaff3045 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 28 Oct 2018 18:06:28 +0100 Subject: [PATCH 6/8] Improve text rendering accuracy --- .../Processors/Text/DrawTextProcessor.cs | 18 ++++++---- .../Drawing/Text/DrawTextOnImageTests.cs | 34 ++++++++++++++++--- tests/Images/External | 2 +- 3 files changed, 41 insertions(+), 13 deletions(-) diff --git a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs index 478358191d..f9a1d87393 100644 --- a/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs +++ b/src/ImageSharp.Drawing/Processing/Processors/Text/DrawTextProcessor.cs @@ -165,9 +165,12 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text private class CachingGlyphRenderer : IGlyphRenderer, IDisposable { - // just enough accuracy to allow for half pixel differences which - // later are componded into full pixel offsets while rendering. - private const float AccuracyMultiple = 2; + // just enough accuracy to allow for 1/8 pixel differences which + // later are accumulated while rendering, but do not grow into full pixel offsets + // The value 8 is benchmarked to: + // - Provide a good accuracy (smaller than 0.2% image difference compared to the non-caching variant) + // - Cache hit ratio above 60% + private const float AccuracyMultiple = 8; private readonly PathBuilder builder; @@ -222,14 +225,15 @@ namespace SixLabors.ImageSharp.Processing.Processors.Text public bool BeginGlyph(RectangleF bounds, GlyphRendererParameters parameters) { this.currentRenderPosition = Point.Truncate(bounds.Location); - PointF dif = bounds.Location - this.currentRenderPosition; + PointF subPixelOffset = bounds.Location - this.currentRenderPosition; - dif.X = ((int)(dif.X * AccuracyMultiple)) / AccuracyMultiple; - dif.Y = ((int)(dif.Y * AccuracyMultiple)) / AccuracyMultiple; + subPixelOffset.X = MathF.Round(subPixelOffset.X * AccuracyMultiple) / AccuracyMultiple; + subPixelOffset.Y = MathF.Round(subPixelOffset.Y * AccuracyMultiple) / AccuracyMultiple; // we have offset our rendering origion a little bit down to prevent edge cropping, move the draw origin up to compensate this.currentRenderPosition = new Point(this.currentRenderPosition.X - this.offset, this.currentRenderPosition.Y - this.offset); - this.currentGlyphRenderParams = (parameters, dif); + this.currentGlyphRenderParams = (parameters, subPixelOffset); + if (this.glyphData.ContainsKey(this.currentGlyphRenderParams)) { // we have already drawn the glyph vectors skip trying again diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs index 09aeef35ce..c1aeebed80 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -11,6 +11,8 @@ using SixLabors.ImageSharp.Tests.TestUtilities.ImageComparison; using SixLabors.Primitives; using Xunit; +using Xunit.Abstractions; + // ReSharper disable InconsistentNaming namespace SixLabors.ImageSharp.Tests.Drawing.Text @@ -25,6 +27,13 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text public static ImageComparer TextDrawingComparer = ImageComparer.TolerantPercentage(1e-5f); public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.TolerantPercentage(1e-4f); + public DrawTextOnImageTests(ITestOutputHelper output) + { + this.Output = output; + } + + private ITestOutputHelper Output { get; } + [Theory] [WithSolidFilledImages(200, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "SixLaborsSampleAB.woff", AB)] [WithSolidFilledImages(900, 100, "White", PixelTypes.Rgba32, 50, 0, 0, "OpenSans-Regular.ttf", TestText)] @@ -87,8 +96,12 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text TPixel color = NamedColors.Black; + // Based on the reported 0.0270% difference with AccuracyMultiple = 8 + // We should avoid quality regressions leading to higher difference! + var comparer = ImageComparer.TolerantPercentage(0.03f); + provider.VerifyOperation( - TextDrawingComparer, + comparer, img => { img.Mutate(c => c.DrawText(textOptions, sb.ToString(), font, color, new PointF(10, 5))); @@ -152,8 +165,9 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text } [Theory] - [WithSolidFilledImages(1000, 1500, "White", PixelTypes.Rgba32)] - public static void TextPositioningIsRobust(TestImageProvider provider) + [WithSolidFilledImages(1000, 1500, "White", PixelTypes.Rgba32, "Baskerville Old Face")] + [WithSolidFilledImages(1000, 1500, "White", PixelTypes.Rgba32, "Arial")] + public void TextPositioningIsRobust(TestImageProvider provider, string fontName) where TPixel : struct, IPixel { if (!TestEnvironment.IsWindows) @@ -162,14 +176,24 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text return; } - Font font = SystemFonts.CreateFont("Baskerville Old Face", 30, FontStyle.Regular); + Font font = SystemFonts.CreateFont(fontName, 30, FontStyle.Regular); string text = Repeat("Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Beware the Jubjub bird, and shun The frumious Bandersnatch!\n", 20); var textOptions = new TextGraphicsOptions(true) { WrapTextWidth = 1000 }; + string details = fontName.Replace(" ", ""); + + // Based on the reported 0.1755% difference with AccuracyMultiple = 8 + // We should avoid quality regressions leading to higher difference! + var comparer = ImageComparer.TolerantPercentage(0.2f); + provider.RunValidatingProcessorTest( - x => x.DrawText(textOptions, text, font, NamedColors.Black, new PointF(10, 50)), appendPixelTypeToFileName: false, appendSourceFileOrDescription: false); + x => x.DrawText(textOptions, text, font, NamedColors.Black, new PointF(10, 50)), + details, + comparer, + appendPixelTypeToFileName: false, + appendSourceFileOrDescription: false); } private static string Repeat(string str, int times) => string.Concat(Enumerable.Repeat(str, times)); diff --git a/tests/Images/External b/tests/Images/External index 5634b8b2af..b7a7eacc04 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit 5634b8b2affa1158cec31ccbb67f9583e9137234 +Subproject commit b7a7eacc0446a1acc266f30ddadbda40fccde231 From ef32f68391cc0e59e99480182acdb5d4043c94bf Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 28 Oct 2018 19:14:02 +0100 Subject: [PATCH 7/8] use OpenSans-Regular.ttf in tests --- .../Drawing/Text/DrawTextOnImageTests.cs | 11 ++--------- tests/Images/External | 2 +- 2 files changed, 3 insertions(+), 10 deletions(-) diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs index c1aeebed80..46251cdcfd 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -165,18 +165,11 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text } [Theory] - [WithSolidFilledImages(1000, 1500, "White", PixelTypes.Rgba32, "Baskerville Old Face")] - [WithSolidFilledImages(1000, 1500, "White", PixelTypes.Rgba32, "Arial")] + [WithSolidFilledImages(1000, 1500, "White", PixelTypes.Rgba32, "OpenSans-Regular.ttf")] public void TextPositioningIsRobust(TestImageProvider provider, string fontName) where TPixel : struct, IPixel { - if (!TestEnvironment.IsWindows) - { - // Does the system font "Baskerville Old Face" exist on most Linux/MAC machines? - return; - } - - Font font = SystemFonts.CreateFont(fontName, 30, FontStyle.Regular); + Font font = CreateFont(fontName, 30); string text = Repeat("Beware the Jabberwock, my son! The jaws that bite, the claws that catch! Beware the Jubjub bird, and shun The frumious Bandersnatch!\n", 20); diff --git a/tests/Images/External b/tests/Images/External index b7a7eacc04..f41ae0327a 160000 --- a/tests/Images/External +++ b/tests/Images/External @@ -1 +1 @@ -Subproject commit b7a7eacc0446a1acc266f30ddadbda40fccde231 +Subproject commit f41ae0327a3ab21ab2388c32160bda67debcc082 From 1bd8a9cb92d94b9f1a56fcabac79f32a1196ecd3 Mon Sep 17 00:00:00 2001 From: Anton Firszov Date: Sun, 28 Oct 2018 20:21:29 +0100 Subject: [PATCH 8/8] increase tolerance to tolerate inaccuracies on legacy JIT --- tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs index 46251cdcfd..71fddafa9d 100644 --- a/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs +++ b/tests/ImageSharp.Tests/Drawing/Text/DrawTextOnImageTests.cs @@ -25,7 +25,7 @@ namespace SixLabors.ImageSharp.Tests.Drawing.Text private const string TestText = "Sphinx of black quartz, judge my vow\n0123456789"; public static ImageComparer TextDrawingComparer = ImageComparer.TolerantPercentage(1e-5f); - public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.TolerantPercentage(1e-4f); + public static ImageComparer OutlinedTextDrawingComparer = ImageComparer.TolerantPercentage(5e-4f); public DrawTextOnImageTests(ITestOutputHelper output) {