From f1defa1fd2324ab98b35acc760d99bfc8385e0b0 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 28 Oct 2024 18:22:12 +1000 Subject: [PATCH 1/2] Don't use Ceil when measuring. --- src/SixLabors.Fonts/TextMeasurer.cs | 4 +- .../ApproximateFloatComparer.cs | 89 ++++ tests/SixLabors.Fonts.Tests/GlyphTests.cs | 5 +- .../SixLabors.Fonts.Tests/TextLayoutTests.cs | 387 +++++++++--------- 4 files changed, 289 insertions(+), 196 deletions(-) create mode 100644 tests/SixLabors.Fonts.Tests/ApproximateFloatComparer.cs diff --git a/src/SixLabors.Fonts/TextMeasurer.cs b/src/SixLabors.Fonts/TextMeasurer.cs index 12162095..ae9edda9 100644 --- a/src/SixLabors.Fonts/TextMeasurer.cs +++ b/src/SixLabors.Fonts/TextMeasurer.cs @@ -203,13 +203,13 @@ internal static FontRectangle GetAdvance(IReadOnlyList glyphLayouts Vector2 topLeft = new(left, top); Vector2 bottomRight = new(right, bottom); Vector2 size = (bottomRight - topLeft) * dpi; - return new FontRectangle(0, 0, MathF.Ceiling(size.X), MathF.Ceiling(size.Y)); + return new FontRectangle(0, 0, size.X, size.Y); } internal static FontRectangle GetSize(IReadOnlyList glyphLayouts, float dpi) { FontRectangle bounds = GetBounds(glyphLayouts, dpi); - return new FontRectangle(0, 0, MathF.Ceiling(bounds.Width), MathF.Ceiling(bounds.Height)); + return new FontRectangle(0, 0, bounds.Width, bounds.Height); } internal static FontRectangle GetBounds(IReadOnlyList glyphLayouts, float dpi) diff --git a/tests/SixLabors.Fonts.Tests/ApproximateFloatComparer.cs b/tests/SixLabors.Fonts.Tests/ApproximateFloatComparer.cs new file mode 100644 index 00000000..ac794b62 --- /dev/null +++ b/tests/SixLabors.Fonts.Tests/ApproximateFloatComparer.cs @@ -0,0 +1,89 @@ +// Copyright (c) Six Labors. +// Licensed under the Six Labors Split License. + +using System.Numerics; + +namespace SixLabors.Fonts.Tests; + +internal class ApproximateFloatComparer : + IEqualityComparer, + IEqualityComparer, + IEqualityComparer>, + IEqualityComparer +{ + private readonly float epsilon; + + /// + /// Initializes a new instance of the class. + /// + /// The comparison error difference epsilon to use. + public ApproximateFloatComparer(float epsilon = 1F) => this.epsilon = epsilon; + + public bool Equals(float x, float y) + { + float d = x - y; + return d >= -this.epsilon && d <= this.epsilon; + } + + public bool Equals(Vector2 x, Vector2 y) + => this.Equals(x.X, y.X) && this.Equals(x.Y, y.Y); + + public bool Equals(IEnumerable x, IEnumerable y) + { + if (ReferenceEquals(x, y)) + { + return true; + } + + if (x is null) + { + return y is null; + } + + if (y is null) + { + return false; + } + + if (x.Count() != y.Count()) + { + return false; + } + + using IEnumerator e1 = x.GetEnumerator(); + using IEnumerator e2 = x.GetEnumerator(); + while (e1.MoveNext()) + { + if (!(e2.MoveNext() && this.Equals(e1.Current, e2.Current))) + { + return false; + } + } + + return !e2.MoveNext(); + } + + public bool Equals(FontRectangle x, FontRectangle y) + => this.Equals(x.X, y.X) && + this.Equals(x.Y, y.Y) && + this.Equals(x.Width, y.Width) + && this.Equals(x.Height, y.Height); + + public int GetHashCode(float obj) => obj.GetHashCode(); + + public int GetHashCode(Vector2 obj) => obj.GetHashCode(); + + public int GetHashCode(IEnumerable obj) + { + int hash = 17; + foreach (Vector2 point in obj) + { + hash = (hash * 31) + point.GetHashCode(); + } + + return hash; + } + + public int GetHashCode(FontRectangle obj) + => obj.GetHashCode(); +} diff --git a/tests/SixLabors.Fonts.Tests/GlyphTests.cs b/tests/SixLabors.Fonts.Tests/GlyphTests.cs index 6671bf24..ebec89c0 100644 --- a/tests/SixLabors.Fonts.Tests/GlyphTests.cs +++ b/tests/SixLabors.Fonts.Tests/GlyphTests.cs @@ -14,6 +14,7 @@ namespace SixLabors.Fonts.Tests; public class GlyphTests { private readonly GlyphRenderer renderer = new(); + private static readonly ApproximateFloatComparer Comparer = new(.1F); [Fact] public void RenderToPointAndSingleDPI() @@ -164,8 +165,8 @@ public void EmojiWidthIsComputedCorrectlyWithSubstitutionOnZwj() FontRectangle size = TextMeasurer.MeasureSize(text, new TextOptions(font)); FontRectangle size2 = TextMeasurer.MeasureSize(text2, new TextOptions(font)); - Assert.Equal(51f, size.Width); - Assert.Equal(51f, size2.Width); + Assert.Equal(50.625F, size.Width, Comparer); + Assert.Equal(50.625F, size2.Width, Comparer); } [Theory] diff --git a/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs b/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs index 5000c4fd..dff3522a 100644 --- a/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs +++ b/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs @@ -10,6 +10,8 @@ namespace SixLabors.Fonts.Tests; public class TextLayoutTests { + private static readonly ApproximateFloatComparer Comparer = new(.1F); + [Theory] [InlineData(LayoutMode.HorizontalTopBottom, true)] [InlineData(LayoutMode.HorizontalBottomTop, true)] @@ -780,100 +782,100 @@ public void TextJustification_InterWord_Vertical(TextDirection direction) public static TheoryData OpenSans_Data = new() { - { '!', new(0, 0, 2, 8) }, - { '"', new(0, 0, 3, 3) }, - { '#', new(0, 0, 6, 8) }, - { '$', new(0, 0, 5, 9) }, - { '%', new(0, 0, 8, 8) }, - { '&', new(0, 0, 7, 8) }, - { '\'', new(0, 0, 1, 3) }, - { '(', new(0, 0, 3, 9) }, - { ')', new(0, 0, 3, 9) }, - { '*', new(0, 0, 5, 5) }, - { '+', new(0, 0, 5, 5) }, - { ',', new(0, 0, 2, 3) }, - { '-', new(0, 0, 3, 1) }, - { '.', new(0, 0, 2, 2) }, - { '/', new(0, 0, 4, 8) }, - { '0', new(0, 0, 5, 8) }, - { '1', new(0, 0, 3, 8) }, - { '2', new(0, 0, 5, 8) }, - { '3', new(0, 0, 5, 8) }, - { '4', new(0, 0, 6, 8) }, - { '5', new(0, 0, 5, 8) }, - { '6', new(0, 0, 5, 8) }, - { '7', new(0, 0, 5, 8) }, - { '8', new(0, 0, 5, 8) }, - { '9', new(0, 0, 5, 8) }, - { ':', new(0, 0, 2, 6) }, - { ';', new(0, 0, 2, 7) }, - { '<', new(0, 0, 5, 5) }, - { '=', new(0, 0, 5, 3) }, - { '>', new(0, 0, 5, 5) }, - { '?', new(0, 0, 4, 8) }, - { '@', new(0, 0, 8, 9) }, - { 'A', new(0, 0, 7, 8) }, - { 'B', new(0, 0, 5, 8) }, - { 'C', new(0, 0, 6, 8) }, - { 'D', new(0, 0, 6, 8) }, - { 'E', new(0, 0, 4, 8) }, - { 'F', new(0, 0, 4, 8) }, - { 'G', new(0, 0, 6, 8) }, - { 'H', new(0, 0, 6, 8) }, - { 'I', new(0, 0, 1, 8) }, - { 'J', new(0, 0, 3, 10) }, - { 'K', new(0, 0, 6, 8) }, - { 'L', new(0, 0, 4, 8) }, - { 'M', new(0, 0, 8, 8) }, - { 'N', new(0, 0, 6, 8) }, - { 'O', new(0, 0, 7, 8) }, - { 'P', new(0, 0, 5, 8) }, - { 'Q', new(0, 0, 7, 9) }, - { 'R', new(0, 0, 6, 8) }, - { 'S', new(0, 0, 5, 8) }, - { 'T', new(0, 0, 6, 8) }, - { 'U', new(0, 0, 6, 8) }, - { 'V', new(0, 0, 6, 8) }, - { 'W', new(0, 0, 9, 8) }, - { 'X', new(0, 0, 6, 8) }, - { 'Y', new(0, 0, 6, 8) }, - { 'Z', new(0, 0, 5, 8) }, - { '[', new(0, 0, 3, 9) }, - { '\\', new(0, 0, 4, 8) }, - { ']', new(0, 0, 3, 9) }, - { '^', new(0, 0, 5, 5) }, - { '_', new(0, 0, 5, 1) }, - { '`', new(0, 0, 2, 2) }, - { 'a', new(0, 0, 5, 6) }, - { 'b', new(0, 0, 5, 8) }, - { 'c', new(0, 0, 4, 6) }, - { 'd', new(0, 0, 5, 8) }, - { 'e', new(0, 0, 5, 6) }, - { 'f', new(0, 0, 4, 8) }, - { 'g', new(0, 0, 6, 8) }, - { 'h', new(0, 0, 5, 8) }, - { 'i', new(0, 0, 1, 8) }, - { 'j', new(0, 0, 3, 10) }, - { 'k', new(0, 0, 5, 8) }, - { 'l', new(0, 0, 1, 8) }, - { 'm', new(0, 0, 8, 6) }, - { 'n', new(0, 0, 5, 6) }, - { 'o', new(0, 0, 5, 6) }, - { 'p', new(0, 0, 5, 8) }, - { 'q', new(0, 0, 5, 8) }, - { 'r', new(0, 0, 4, 6) }, - { 's', new(0, 0, 4, 6) }, - { 't', new(0, 0, 4, 7) }, - { 'u', new(0, 0, 5, 6) }, - { 'v', new(0, 0, 5, 6) }, - { 'w', new(0, 0, 8, 6) }, - { 'x', new(0, 0, 5, 6) }, - { 'y', new(0, 0, 5, 8) }, - { 'z', new(0, 0, 4, 6) }, - { '{', new(0, 0, 4, 9) }, - { '|', new(0, 0, 1, 11) }, - { '}', new(0, 0, 4, 9) }, - { '~', new(0, 0, 5, 2) }, + { '!', new(0F, 0F, 1.1621094F, 7.2753906F) }, + { '"', new(0F, 0F, 2.6660156F, 2.578125F) }, + { '#', new(0F, 0F, 5.9472656F, 7.138672F) }, + { '$', new(0F, 0F, 4.4921875F, 8.168945F) }, + { '%', new(0F, 0F, 7.270508F, 7.338867F) }, + { '&', new(0F, 0F, 6.689453F, 7.348633F) }, + { '\'', new(0F, 0F, 0.87890625F, 2.578125F) }, + { '(', new(0F, 0F, 2.2460938F, 8.720703F) }, + { ')', new(0F, 0F, 2.2460938F, 8.720703F) }, + { '*', new(0F, 0F, 4.614258F, 4.4433594F) }, + { '+', new(0F, 0F, 4.692383F, 4.814453F) }, + { ',', new(0F, 0F, 1.4404297F, 2.4511719F) }, + { '-', new(0F, 0F, 2.421875F, 0.72265625F) }, + { '.', new(0F, 0F, 1.1621094F, 1.2744141F) }, + { '/', new(0F, 0F, 3.4570312F, 7.138672F) }, + { '0', new(0F, 0F, 4.7070312F, 7.348633F) }, + { '1', new(0F, 0F, 2.6074219F, 7.138672F) }, + { '2', new(0F, 0F, 4.6777344F, 7.241211F) }, + { '3', new(0F, 0F, 4.6777344F, 7.338867F) }, + { '4', new(0F, 0F, 5.3125F, 7.1777344F) }, + { '5', new(0F, 0F, 4.4970703F, 7.236328F) }, + { '6', new(0F, 0F, 4.6679688F, 7.338867F) }, + { '7', new(0F, 0F, 4.760742F, 7.138672F) }, + { '8', new(0F, 0F, 4.6972656F, 7.338867F) }, + { '9', new(0F, 0F, 4.6777344F, 7.34375F) }, + { ':', new(0F, 0F, 1.1621094F, 5.6152344F) }, + { ';', new(0F, 0F, 1.5576172F, 6.767578F) }, + { '<', new(0F, 0F, 4.6972656F, 4.868164F) }, + { '=', new(0F, 0F, 4.580078F, 2.65625F) }, + { '>', new(0F, 0F, 4.6972656F, 4.868164F) }, + { '?', new(0F, 0F, 3.8916016F, 7.3779297F) }, + { '@', new(0F, 0F, 7.817383F, 8.032227F) }, + { 'A', new(0F, 0F, 6.3134766F, 7.1679688F) }, + { 'B', new(0F, 0F, 4.9414062F, 7.138672F) }, + { 'C', new(0F, 0F, 5.3808594F, 7.338867F) }, + { 'D', new(0F, 0F, 5.6689453F, 7.138672F) }, + { 'E', new(0F, 0F, 3.9746094F, 7.138672F) }, + { 'F', new(0F, 0F, 3.9746094F, 7.138672F) }, + { 'G', new(0F, 0F, 5.913086F, 7.338867F) }, + { 'H', new(0F, 0F, 5.4101562F, 7.138672F) }, + { 'I', new(0F, 0F, 0.8300781F, 7.138672F) }, + { 'J', new(0F, 0F, 2.5683594F, 9.018555F) }, + { 'K', new(0F, 0F, 5.1464844F, 7.138672F) }, + { 'L', new(0F, 0F, 3.9990234F, 7.138672F) }, + { 'M', new(0F, 0F, 7.0410156F, 7.138672F) }, + { 'N', new(0F, 0F, 5.5810547F, 7.138672F) }, + { 'O', new(0F, 0F, 6.557617F, 7.348633F) }, + { 'P', new(0F, 0F, 4.5214844F, 7.138672F) }, + { 'Q', new(0F, 0F, 6.557617F, 8.950195F) }, + { 'R', new(0F, 0F, 5.029297F, 7.138672F) }, + { 'S', new(0F, 0F, 4.4921875F, 7.338867F) }, + { 'T', new(0F, 0F, 5.317383F, 7.138672F) }, + { 'U', new(0F, 0F, 5.473633F, 7.236328F) }, + { 'V', new(0F, 0F, 5.961914F, 7.138672F) }, + { 'W', new(0F, 0F, 8.94043F, 7.138672F) }, + { 'X', new(0F, 0F, 5.7128906F, 7.138672F) }, + { 'Y', new(0F, 0F, 5.5908203F, 7.138672F) }, + { 'Z', new(0F, 0F, 4.9560547F, 7.138672F) }, + { '[', new(0F, 0F, 2.211914F, 8.720703F) }, + { '\\', new(0F, 0F, 3.4667969F, 7.138672F) }, + { ']', new(0F, 0F, 2.2167969F, 8.720703F) }, + { '^', new(0F, 0F, 4.9414062F, 4.5117188F) }, + { '_', new(0F, 0F, 4.4189453F, 0.60058594F) }, + { '`', new(0F, 0F, 1.9775391F, 1.6015625F) }, + { 'a', new(0F, 0F, 4.2822266F, 5.5371094F) }, + { 'b', new(0F, 0F, 4.7070312F, 7.6953125F) }, + { 'c', new(0F, 0F, 3.90625F, 5.546875F) }, + { 'd', new(0F, 0F, 4.7021484F, 7.6953125F) }, + { 'e', new(0F, 0F, 4.536133F, 5.546875F) }, + { 'f', new(0F, 0F, 3.671875F, 7.651367F) }, + { 'g', new(0F, 0F, 5.078125F, 7.861328F) }, + { 'h', new(0F, 0F, 4.4628906F, 7.5976562F) }, + { 'i', new(0F, 0F, 0.9765625F, 7.3535156F) }, + { 'j', new(0F, 0F, 2.3046875F, 9.755859F) }, + { 'k', new(0F, 0F, 4.321289F, 7.5976562F) }, + { 'l', new(0F, 0F, 0.8154297F, 7.5976562F) }, + { 'm', new(0F, 0F, 7.5927734F, 5.4492188F) }, + { 'n', new(0F, 0F, 4.4628906F, 5.4492188F) }, + { 'o', new(0F, 0F, 4.9121094F, 5.546875F) }, + { 'p', new(0F, 0F, 4.7070312F, 7.841797F) }, + { 'q', new(0F, 0F, 4.7021484F, 7.841797F) }, + { 'r', new(0F, 0F, 3.0810547F, 5.4492188F) }, + { 's', new(0F, 0F, 3.8134766F, 5.546875F) }, + { 't', new(0F, 0F, 3.178711F, 6.689453F) }, + { 'u', new(0F, 0F, 4.477539F, 5.4492188F) }, + { 'v', new(0F, 0F, 4.995117F, 5.3515625F) }, + { 'w', new(0F, 0F, 7.5146484F, 5.3515625F) }, + { 'x', new(0F, 0F, 4.8535156F, 5.3515625F) }, + { 'y', new(0F, 0F, 5F, 7.758789F) }, + { 'z', new(0F, 0F, 3.9013672F, 5.3515625F) }, + { '{', new(0F, 0F, 3.149414F, 8.720703F) }, + { '|', new(0F, 0F, 0.67871094F, 10.024414F) }, + { '}', new(0F, 0F, 3.149414F, 8.720703F) }, + { '~', new(0F, 0F, 4.6972656F, 1.2597656F) }, }; [Theory] @@ -887,7 +889,7 @@ public void TrueTypeHinting_CanHintSmallOpenSans(char c, FontRectangle expected) }; FontRectangle actual = TextMeasurer.MeasureSize(c.ToString(), options); - Assert.Equal(expected, actual); + Assert.Equal(expected, actual, Comparer); options = new(OpenSansWoff) { @@ -896,7 +898,7 @@ public void TrueTypeHinting_CanHintSmallOpenSans(char c, FontRectangle expected) }; actual = TextMeasurer.MeasureSize(c.ToString(), options); - Assert.Equal(expected, actual); + Assert.Equal(expected, actual, Comparer); } [Fact] @@ -913,7 +915,7 @@ public void CanMeasureTextAdvance() const string text = "Hello World!"; FontRectangle first = TextMeasurer.MeasureAdvance(text, options); - Assert.Equal(new FontRectangle(0, 0, 11729, 2049), first); + Assert.Equal(new FontRectangle(0, 0, 11729, 2048), first, Comparer); options.LineSpacing = 2F; FontRectangle second = TextMeasurer.MeasureAdvance(text, options); @@ -1170,100 +1172,101 @@ public void SetDecoration(TextDecorations textDecorations, Vector2 start, Vector public static TheoryData SegoeUi_Data = new() { - { '!', new(0, 0, 2, 8) }, - { '"', new(0, 0, 3, 3) }, - { '#', new(0, 0, 6, 7) }, - { '$', new(0, 0, 4, 9) }, - { '%', new(0, 0, 8, 8) }, - { '&', new(0, 0, 8, 8) }, - { '\'', new(0, 0, 1, 3) }, - { '(', new(0, 0, 3, 9) }, - { ')', new(0, 0, 3, 9) }, - { '*', new(0, 0, 4, 4) }, - { '+', new(0, 0, 5, 5) }, - { ',', new(0, 0, 2, 3) }, - { '-', new(0, 0, 3, 1) }, - { '.', new(0, 0, 2, 2) }, - { '/', new(0, 0, 5, 9) }, - { '0', new(0, 0, 5, 8) }, - { '1', new(0, 0, 3, 8) }, - { '2', new(0, 0, 5, 8) }, - { '3', new(0, 0, 5, 8) }, - { '4', new(0, 0, 5, 8) }, - { '5', new(0, 0, 4, 8) }, - { '6', new(0, 0, 5, 8) }, - { '7', new(0, 0, 5, 8) }, - { '8', new(0, 0, 5, 8) }, - { '9', new(0, 0, 5, 8) }, - { ':', new(0, 0, 2, 6) }, - { ';', new(0, 0, 2, 7) }, - { '<', new(0, 0, 5, 5) }, - { '=', new(0, 0, 5, 3) }, - { '>', new(0, 0, 5, 5) }, - { '?', new(0, 0, 4, 8) }, - { '@', new(0, 0, 8, 9) }, - { 'A', new(0, 0, 7, 8) }, - { 'B', new(0, 0, 5, 8) }, - { 'C', new(0, 0, 6, 8) }, - { 'D', new(0, 0, 6, 8) }, - { 'E', new(0, 0, 4, 8) }, - { 'F', new(0, 0, 4, 8) }, - { 'G', new(0, 0, 6, 8) }, - { 'H', new(0, 0, 6, 8) }, - { 'I', new(0, 0, 1, 8) }, - { 'J', new(0, 0, 3, 8) }, - { 'K', new(0, 0, 5, 8) }, - { 'L', new(0, 0, 4, 8) }, - { 'M', new(0, 0, 8, 8) }, - { 'N', new(0, 0, 6, 8) }, - { 'O', new(0, 0, 7, 8) }, - { 'P', new(0, 0, 5, 8) }, - { 'Q', new(0, 0, 8, 9) }, - { 'R', new(0, 0, 6, 8) }, - { 'S', new(0, 0, 5, 8) }, - { 'T', new(0, 0, 5, 8) }, - { 'U', new(0, 0, 6, 8) }, - { 'V', new(0, 0, 7, 8) }, - { 'W', new(0, 0, 10, 8) }, - { 'X', new(0, 0, 6, 8) }, - { 'Y', new(0, 0, 6, 8) }, - { 'Z', new(0, 0, 6, 8) }, - { '[', new(0, 0, 2, 9) }, - { '\\', new(0, 0, 5, 9) }, - { ']', new(0, 0, 2, 9) }, - { '^', new(0, 0, 5, 5) }, - { '_', new(0, 0, 5, 1) }, - { '`', new(0, 0, 2, 2) }, - { 'a', new(0, 0, 4, 6) }, - { 'b', new(0, 0, 5, 8) }, - { 'c', new(0, 0, 4, 6) }, - { 'd', new(0, 0, 5, 8) }, - { 'e', new(0, 0, 5, 6) }, - { 'f', new(0, 0, 4, 8) }, - { 'g', new(0, 0, 5, 8) }, - { 'h', new(0, 0, 5, 8) }, - { 'i', new(0, 0, 2, 8) }, - { 'j', new(0, 0, 3, 10) }, - { 'k', new(0, 0, 5, 8) }, - { 'l', new(0, 0, 1, 8) }, - { 'm', new(0, 0, 8, 6) }, - { 'n', new(0, 0, 5, 6) }, - { 'o', new(0, 0, 5, 6) }, - { 'p', new(0, 0, 5, 8) }, - { 'q', new(0, 0, 5, 8) }, - { 'r', new(0, 0, 3, 6) }, - { 's', new(0, 0, 4, 6) }, - { 't', new(0, 0, 3, 7) }, - { 'u', new(0, 0, 5, 6) }, - { 'v', new(0, 0, 5, 5) }, - { 'w', new(0, 0, 7, 5) }, - { 'x', new(0, 0, 5, 5) }, - { 'y', new(0, 0, 5, 8) }, - { 'z', new(0, 0, 5, 5) }, - { '{', new(0, 0, 3, 9) }, - { '|', new(0, 0, 1, 10) }, - { '}', new(0, 0, 3, 9) }, - { '~', new(0, 0, 5, 2) } + { '!', new(0F, 0F, 1.0839844F, 7.0898438F) }, + { '"', new(0F, 0F, 2.3291016F, 2.1826172F) }, + { '#', new(0F, 0F, 5.5322266F, 6.401367F) }, + { '$', new(0F, 0F, 3.9794922F, 8.911133F) }, + { '%', new(0F, 0F, 7.421875F, 7.216797F) }, + { '&', new(0F, 0F, 7.2216797F, 7.2314453F) }, + { '\'', new(0F, 0F, 0.7080078F, 2.1826172F) }, + { '(', new(0F, 0F, 2.2363281F, 8.59375F) }, + { ')', new(0F, 0F, 2.2460938F, 8.59375F) }, + { '*', new(0F, 0F, 3.4375F, 3.4423828F) }, + { '+', new(0F, 0F, 4.5898438F, 4.5898438F) }, + { ',', new(0F, 0F, 1.3525391F, 2.4023438F) }, + { '-', new(0F, 0F, 2.6660156F, 0.6298828F) }, + { '.', new(0F, 0F, 1.09375F, 1.0986328F) }, + { '/', new(0F, 0F, 4.1064453F, 8.1640625F) }, + { '0', new(0F, 0F, 4.560547F, 7.241211F) }, + { '1', new(0F, 0F, 2.421875F, 7.158203F) }, + { '2', new(0F, 0F, 4.321289F, 7.1191406F) }, + { '3', new(0F, 0F, 4.0527344F, 7.241211F) }, + { '4', new(0F, 0F, 4.9804688F, 7.001953F) }, + { '5', new(0F, 0F, 3.930664F, 7.1240234F) }, + { '6', new(0F, 0F, 4.448242F, 7.241211F) }, + { '7', new(0F, 0F, 4.453125F, 7.001953F) }, + { '8', new(0F, 0F, 4.5410156F, 7.2314453F) }, + { '9', new(0F, 0F, 4.4433594F, 7.241211F) }, + { ':', new(0F, 0F, 1.09375F, 5.2148438F) }, + { ';', new(0F, 0F, 1.4599609F, 6.3964844F) }, + { '<', new(0F, 0F, 4.1992188F, 4.7509766F) }, + { '=', new(0F, 0F, 4.5898438F, 2.7246094F) }, + { '>', new(0F, 0F, 4.1992188F, 4.7509766F) }, + { '?', new(0F, 0F, 3.3496094F, 7.2070312F) }, + { '@', new(0F, 0F, 7.890625F, 8.017578F) }, + { 'A', new(0F, 0F, 6.2304688F, 7.001953F) }, + { 'B', new(0F, 0F, 4.3115234F, 7.001953F) }, + { 'C', new(0F, 0F, 5.2246094F, 7.236328F) }, + { 'D', new(0F, 0F, 5.6347656F, 7.001953F) }, + { 'E', new(0F, 0F, 3.7109375F, 7.001953F) }, + { 'F', new(0F, 0F, 3.5546875F, 7.001953F) }, + { 'G', new(0F, 0F, 5.6933594F, 7.236328F) }, + { 'H', new(0F, 0F, 5.263672F, 7.001953F) }, + { 'I', new(0F, 0F, 0.8203125F, 7.001953F) }, + { 'J', new(0F, 0F, 2.6123047F, 7.1191406F) }, + { 'K', new(0F, 0F, 4.873047F, 7.001953F) }, + { 'L', new(0F, 0F, 3.6328125F, 7.001953F) }, + { 'M', new(0F, 0F, 7.138672F, 7.001953F) }, + { 'N', new(0F, 0F, 5.6445312F, 7.001953F) }, + { 'O', new(0F, 0F, 6.6210938F, 7.236328F) }, + { 'P', new(0F, 0F, 4.2822266F, 7.001953F) }, + { 'Q', new(0F, 0F, 7.2216797F, 8.061523F) }, + { 'R', new(0F, 0F, 5.0195312F, 7.001953F) }, + { 'S', new(0F, 0F, 4.243164F, 7.236328F) }, + { 'T', new(0F, 0F, 4.8583984F, 7.001953F) }, + { 'U', new(0F, 0F, 5.209961F, 7.1191406F) }, + { 'V', new(0F, 0F, 6.0351562F, 7.001953F) }, + { 'W', new(0F, 0F, 9.091797F, 7.001953F) }, + { 'X', new(0F, 0F, 5.625F, 7.001953F) }, + { 'Y', new(0F, 0F, 5.3808594F, 7.001953F) }, + { 'Z', new(0F, 0F, 5.3271484F, 7.001953F) }, + { '[', new(0F, 0F, 1.796875F, 8.59375F) }, + { '\\', new(0F, 0F, 4.0234375F, 8.173828F) }, + { ']', new(0F, 0F, 1.7919922F, 8.59375F) }, + { '^', new(0F, 0F, 4.609375F, 4.0722656F) }, + { '_', new(0F, 0F, 4.1503906F, 0.5810547F) }, + { '`', new(0F, 0F, 1.8994141F, 1.6015625F) }, + { 'a', new(0F, 0F, 3.9501953F, 5.234375F) }, + { 'b', new(0F, 0F, 4.5996094F, 7.5195312F) }, + { 'c', new(0F, 0F, 3.7597656F, 5.234375F) }, + { 'd', new(0F, 0F, 4.609375F, 7.5195312F) }, + { 'e', new(0F, 0F, 4.3603516F, 5.234375F) }, + { 'f', new(0F, 0F, 3.022461F, 7.5097656F) }, + { 'g', new(0F, 0F, 4.609375F, 7.470703F) }, + { 'h', new(0F, 0F, 4.1503906F, 7.4023438F) }, + { 'i', new(0F, 0F, 1.0449219F, 7.3095703F) }, + { 'j', new(0F, 0F, 2.7148438F, 9.663086F) }, + { 'k', new(0F, 0F, 4.1503906F, 7.4023438F) }, + { 'l', new(0F, 0F, 0.80078125F, 7.4023438F) }, + { 'm', new(0F, 0F, 7.0996094F, 5.1171875F) }, + { 'n', new(0F, 0F, 4.1503906F, 5.1171875F) }, + { 'o', new(0F, 0F, 4.921875F, 5.234375F) }, + { 'p', new(0F, 0F, 4.5996094F, 7.416992F) }, + { 'q', new(0F, 0F, 4.609375F, 7.416992F) }, + { 'r', new(0F, 0F, 2.6074219F, 5.0878906F) }, + { 's', new(0F, 0F, 3.3154297F, 5.234375F) }, + { 't', new(0F, 0F, 2.9199219F, 6.586914F) }, + { 'u', new(0F, 0F, 4.1503906F, 5.1171875F) }, + { 'v', new(0F, 0F, 4.6728516F, 5F) }, + { 'w', new(0F, 0F, 6.9921875F, 5F) }, + { 'x', new(0F, 0F, 4.3359375F, 5F) }, + { 'y', new(0F, 0F, 4.7216797F, 7.3535156F) }, + { 'z', new(0F, 0F, 4.135742F, 5F) }, + { '{', new(0F, 0F, 2.2607422F, 8.59375F) }, + { '|', new(0F, 0F, 0.72265625F, 10F) }, + { '}', new(0F, 0F, 2.2558594F, 8.59375F) }, + { '~', new(0F, 0F, 4.8095703F, 1.5136719F) }, + }; [Theory] @@ -1278,7 +1281,7 @@ public void TrueTypeHinting_CanHintSmallSegoeUi(char c, FontRectangle expected) FontRectangle actual = TextMeasurer.MeasureSize(c.ToString(), options); - Assert.Equal(expected, actual); + Assert.Equal(expected, actual, Comparer); } private static readonly Font SegoeUi = SystemFonts.CreateFont("Segoe Ui", 10); From caaf9011537c940ffad9c17b74df76cd3c2852b2 Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Mon, 28 Oct 2024 18:28:47 +1000 Subject: [PATCH 2/2] Update missed tests --- tests/SixLabors.Fonts.Tests/Issues/Issues_269.cs | 6 ++++-- tests/SixLabors.Fonts.Tests/Issues/Issues_367.cs | 10 ++++++---- 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/SixLabors.Fonts.Tests/Issues/Issues_269.cs b/tests/SixLabors.Fonts.Tests/Issues/Issues_269.cs index 024fb867..a7a91585 100644 --- a/tests/SixLabors.Fonts.Tests/Issues/Issues_269.cs +++ b/tests/SixLabors.Fonts.Tests/Issues/Issues_269.cs @@ -5,6 +5,8 @@ namespace SixLabors.Fonts.Tests.Issues; public class Issues_269 { + private static readonly ApproximateFloatComparer Comparer = new(.1F); + [Fact] public void CorrectlySetsMetricsForFontsNotAdheringToSpec() { @@ -12,7 +14,7 @@ public void CorrectlySetsMetricsForFontsNotAdheringToSpec() Font font = new FontCollection().Add(TestFonts.AliceFrancesHMKRegularFile).CreateFont(25); FontRectangle size = TextMeasurer.MeasureSize("H", new TextOptions(font)); - Assert.Equal(32, size.Width, 1F); - Assert.Equal(25, size.Height, 1F); + Assert.Equal(30.6000004F, size.Width, Comparer); + Assert.Equal(24.75F, size.Height, Comparer); } } diff --git a/tests/SixLabors.Fonts.Tests/Issues/Issues_367.cs b/tests/SixLabors.Fonts.Tests/Issues/Issues_367.cs index 5a35bf6c..58b44e6f 100644 --- a/tests/SixLabors.Fonts.Tests/Issues/Issues_367.cs +++ b/tests/SixLabors.Fonts.Tests/Issues/Issues_367.cs @@ -4,6 +4,8 @@ namespace SixLabors.Fonts.Tests.Issues; public class Issues_367 { + private static readonly ApproximateFloatComparer Comparer = new(.1F); + [Fact] public void ShouldMatchBrowserBreak() { @@ -11,10 +13,10 @@ public void ShouldMatchBrowserBreak() TextOptions options = new(font) { - Dpi = 96f // 1in = 96px + Dpi = 96F // 1in = 96px }; - const float wrappingLengthInInches = 3.875f; + const float wrappingLengthInInches = 3.875F; options.WrappingLength = wrappingLengthInInches * options.Dpi; const string text = "Leer, but lonesome has fussin' change a faith. Themself seen and four trample."; @@ -23,7 +25,7 @@ public void ShouldMatchBrowserBreak() Assert.Equal(3, lineCount); FontRectangle advance = TextMeasurer.MeasureAdvance(text, options); - Assert.Equal(355, advance.Width); - Assert.Equal(48, advance.Height); + Assert.Equal(354.968658F, advance.Width, Comparer); + Assert.Equal(48, advance.Height, Comparer); } }