From fbf9b48cdc8bf3e2822615733bba2c4c88685e0f Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 10 Jan 2025 21:54:46 +1000 Subject: [PATCH 1/3] Fix calculation of wrapping advance --- src/SixLabors.Fonts/TextLayout.cs | 48 +++++++++-------- .../CountLinesWrappingLength_100-3.png | 3 ++ .../CountLinesWrappingLength_100-4.png | 3 -- .../CountLinesWrappingLength_50-4.png | 3 ++ .../CountLinesWrappingLength_50-5.png | 3 -- ...zontalBottomTop-wordBreaking_BreakAll_.png | 4 +- ...zontalTopBottom-wordBreaking_BreakAll_.png | 4 +- ...zontalBottomTop-wordBreaking_BreakAll_.png | 4 +- ...zontalTopBottom-wordBreaking_BreakAll_.png | 4 +- ...omTop_350-_height_62.625-width_318.86_.png | 4 +- ...ottom_350-_height_62.625-width_318.86_.png | 4 +- ...ight_350-_height_318.563-width_62.813_.png | 4 +- ...ight_350-_height_318.563-width_62.813_.png | 4 +- ...Left_350-_height_318.563-width_62.813_.png | 4 +- ...ExtraLineBreaks_2__WrappingLength_400_.png | 3 ++ .../Issues/Issues_431.cs | 24 +++++++++ .../SixLabors.Fonts.Tests/TextLayoutTests.cs | 53 +++++++++++-------- 17 files changed, 109 insertions(+), 67 deletions(-) create mode 100644 tests/Images/ReferenceOutput/CountLinesWrappingLength_100-3.png delete mode 100644 tests/Images/ReferenceOutput/CountLinesWrappingLength_100-4.png create mode 100644 tests/Images/ReferenceOutput/CountLinesWrappingLength_50-4.png delete mode 100644 tests/Images/ReferenceOutput/CountLinesWrappingLength_50-5.png create mode 100644 tests/Images/ReferenceOutput/ShouldNotInsertExtraLineBreaks_2__WrappingLength_400_.png diff --git a/src/SixLabors.Fonts/TextLayout.cs b/src/SixLabors.Fonts/TextLayout.cs index f137cd81..fdd1402d 100644 --- a/src/SixLabors.Fonts/TextLayout.cs +++ b/src/SixLabors.Fonts/TextLayout.cs @@ -894,6 +894,8 @@ private static TextBox BreakLines( LayoutMode layoutMode) { bool shouldWrap = options.WrappingLength > 0; + + // Wrapping length is always provided in pixels. Convert to inches for comparison. float wrappingLength = shouldWrap ? options.WrappingLength / options.Dpi : float.MaxValue; bool breakAll = options.WordBreaking == WordBreaking.BreakAll; bool keepAll = options.WordBreaking == WordBreaking.KeepAll; @@ -904,7 +906,6 @@ private static TextBox BreakLines( int graphemeIndex; int codePointIndex = 0; - float lineAdvance = 0; List textLines = new(); TextLine textLine = new(); int stringIndex = 0; @@ -1073,7 +1074,7 @@ VerticalOrientationType.Rotate or } } - // Now scale the advance. + // Now scale the advance. We use inches for comparison. if (isHorizontalLayout || shouldRotate) { float scaleAX = pointSize / glyph.ScaleFactor.X; @@ -1115,7 +1116,6 @@ VerticalOrientationType.Rotate or descender -= delta; // Add our metrics to the line. - lineAdvance += decomposedAdvance; textLine.Add( isDecomposed ? new GlyphMetrics[] { metric } : metrics, pointSize, @@ -1153,45 +1153,47 @@ VerticalOrientationType.Rotate or int maxLineBreakIndex = lineBreaks.Count - 1; LineBreak lastLineBreak = lineBreaks[lineBreakIndex]; LineBreak currentLineBreak = lineBreaks[lineBreakIndex]; + float lineAdvance = 0; - lineAdvance = 0; for (int i = 0; i < textLine.Count; i++) { int max = textLine.Count - 1; TextLine.GlyphLayoutData glyph = textLine[i]; codePointIndex = glyph.CodePointIndex; int graphemeCodePointIndex = glyph.GraphemeCodePointIndex; - float glyphAdvance = glyph.ScaledAdvance; - lineAdvance += glyphAdvance; if (graphemeCodePointIndex == 0 && textLine.Count > 0) { + lineAdvance += glyph.ScaledAdvance; + if (codePointIndex == currentLineBreak.PositionWrap && currentLineBreak.Required) { // Mandatory line break at index. TextLine remaining = textLine.SplitAt(i); textLines.Add(textLine.Finalize(options)); textLine = remaining; - i = 0; + i = -1; lineAdvance = 0; } else if (shouldWrap) { - float currentAdvance = lineAdvance + glyphAdvance; - if (currentAdvance >= wrappingLength) + if (lineAdvance >= wrappingLength) { if (breakAll) { - // Insert a forced break at this index. + // Insert a forced break. TextLine remaining = textLine.SplitAt(i); - textLines.Add(textLine.Finalize(options)); - textLine = remaining; - i = 0; - lineAdvance = 0; + if (remaining != textLine) + { + textLines.Add(textLine.Finalize(options)); + textLine = remaining; + i = -1; + lineAdvance = 0; + } } else if (codePointIndex == currentLineBreak.PositionWrap || i == max) { - LineBreak lineBreak = currentAdvance == wrappingLength + LineBreak lineBreak = lineAdvance == wrappingLength ? currentLineBreak : lastLineBreak; @@ -1199,12 +1201,12 @@ VerticalOrientationType.Rotate or { // If the current break is a space, and the line minus the space // is less than the wrapping length, we can break using the current break. - float positionAdvance = lineAdvance; + float previousAdvance = lineAdvance - (float)glyph.ScaledAdvance; TextLine.GlyphLayoutData lastGlyph = textLine[i - 1]; if (CodePoint.IsWhiteSpace(lastGlyph.CodePoint)) { - positionAdvance -= lastGlyph.ScaledAdvance; - if (positionAdvance <= wrappingLength) + previousAdvance -= lastGlyph.ScaledAdvance; + if (previousAdvance <= wrappingLength) { lineBreak = currentLineBreak; } @@ -1220,7 +1222,7 @@ VerticalOrientationType.Rotate or { if (breakWord) { - // If the line is too long, insert a forced line break. + // If the line is too long, insert a forced break. if (textLine.ScaledLineAdvance > wrappingLength) { TextLine overflow = textLine.SplitAt(wrappingLength); @@ -1233,7 +1235,7 @@ VerticalOrientationType.Rotate or textLines.Add(textLine.Finalize(options)); textLine = remaining; - i = 0; + i = -1; lineAdvance = 0; } } @@ -1326,7 +1328,11 @@ public void Add( { // Reset metrics. // We track the maximum metrics for each line to ensure glyphs can be aligned. - this.ScaledLineAdvance += scaledAdvance; + if (graphemeIndex == 0) + { + this.ScaledLineAdvance += scaledAdvance; + } + this.ScaledMaxLineHeight = MathF.Max(this.ScaledMaxLineHeight, scaledLineHeight); this.ScaledMaxAscender = MathF.Max(this.ScaledMaxAscender, scaledAscender); this.ScaledMaxDescender = MathF.Max(this.ScaledMaxDescender, scaledDescender); diff --git a/tests/Images/ReferenceOutput/CountLinesWrappingLength_100-3.png b/tests/Images/ReferenceOutput/CountLinesWrappingLength_100-3.png new file mode 100644 index 00000000..67440973 --- /dev/null +++ b/tests/Images/ReferenceOutput/CountLinesWrappingLength_100-3.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:9c28b19171f3bf75e7eb259492b213dac0132f3664bd29a217bacb08a93c5b6a +size 2929 diff --git a/tests/Images/ReferenceOutput/CountLinesWrappingLength_100-4.png b/tests/Images/ReferenceOutput/CountLinesWrappingLength_100-4.png deleted file mode 100644 index aef12a47..00000000 --- a/tests/Images/ReferenceOutput/CountLinesWrappingLength_100-4.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:071789cee1ac03354e5727bda21321e8bb875ae417adfe5e745877023d62c6d7 -size 2963 diff --git a/tests/Images/ReferenceOutput/CountLinesWrappingLength_50-4.png b/tests/Images/ReferenceOutput/CountLinesWrappingLength_50-4.png new file mode 100644 index 00000000..2c2a6b35 --- /dev/null +++ b/tests/Images/ReferenceOutput/CountLinesWrappingLength_50-4.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:08378706fcf31fa5efaea158bde3b6350f9e96c5721364f7a1b88ac138f4aaca +size 3021 diff --git a/tests/Images/ReferenceOutput/CountLinesWrappingLength_50-5.png b/tests/Images/ReferenceOutput/CountLinesWrappingLength_50-5.png deleted file mode 100644 index 4ee0e7d2..00000000 --- a/tests/Images/ReferenceOutput/CountLinesWrappingLength_50-5.png +++ /dev/null @@ -1,3 +0,0 @@ -version https://git-lfs.github.com/spec/v1 -oid sha256:907dcca95723f6b21aa3791e047476e31b2d8b13f88f3c5e6604696ce5b469f5 -size 3022 diff --git a/tests/Images/ReferenceOutput/MeasureTextWordBreakMatchesMDN_238-_layoutMode_HorizontalBottomTop-wordBreaking_BreakAll_.png b/tests/Images/ReferenceOutput/MeasureTextWordBreakMatchesMDN_238-_layoutMode_HorizontalBottomTop-wordBreaking_BreakAll_.png index 67114c86..cc0dc5c5 100644 --- a/tests/Images/ReferenceOutput/MeasureTextWordBreakMatchesMDN_238-_layoutMode_HorizontalBottomTop-wordBreaking_BreakAll_.png +++ b/tests/Images/ReferenceOutput/MeasureTextWordBreakMatchesMDN_238-_layoutMode_HorizontalBottomTop-wordBreaking_BreakAll_.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:e13708fcaf702a91540b1f68803cc2cff14de1a97cef771ca0bcc69e414a706e -size 13446 +oid sha256:2a23777abd77520f78d269148cee286e23941fea273a7f7a73fcd3a16a724c19 +size 13365 diff --git a/tests/Images/ReferenceOutput/MeasureTextWordBreakMatchesMDN_238-_layoutMode_HorizontalTopBottom-wordBreaking_BreakAll_.png b/tests/Images/ReferenceOutput/MeasureTextWordBreakMatchesMDN_238-_layoutMode_HorizontalTopBottom-wordBreaking_BreakAll_.png index 2c0ae06c..adf303ce 100644 --- a/tests/Images/ReferenceOutput/MeasureTextWordBreakMatchesMDN_238-_layoutMode_HorizontalTopBottom-wordBreaking_BreakAll_.png +++ b/tests/Images/ReferenceOutput/MeasureTextWordBreakMatchesMDN_238-_layoutMode_HorizontalTopBottom-wordBreaking_BreakAll_.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:1896cd5f5d0521261c4b9e366ae56baa89f48cfd21b7d1a5d4a4e4c50b3f8542 -size 13485 +oid sha256:f0ba4662e9b8a24d4bd852d712d5a2a5f34b9aeadf332f12fdff172d3536b4e8 +size 13396 diff --git a/tests/Images/ReferenceOutput/MeasureTextWordBreak_500-_layoutMode_HorizontalBottomTop-wordBreaking_BreakAll_.png b/tests/Images/ReferenceOutput/MeasureTextWordBreak_500-_layoutMode_HorizontalBottomTop-wordBreaking_BreakAll_.png index 44196676..64e39223 100644 --- a/tests/Images/ReferenceOutput/MeasureTextWordBreak_500-_layoutMode_HorizontalBottomTop-wordBreaking_BreakAll_.png +++ b/tests/Images/ReferenceOutput/MeasureTextWordBreak_500-_layoutMode_HorizontalBottomTop-wordBreaking_BreakAll_.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:66b5c1046ab68824efdd3af54c7753a18d7bb12b7a2960c956395b0d20bf19e2 -size 17444 +oid sha256:6d7e8d7d4d63cfe3082b571d7bb156497dd738af448126f319f7be6870317050 +size 17604 diff --git a/tests/Images/ReferenceOutput/MeasureTextWordBreak_500-_layoutMode_HorizontalTopBottom-wordBreaking_BreakAll_.png b/tests/Images/ReferenceOutput/MeasureTextWordBreak_500-_layoutMode_HorizontalTopBottom-wordBreaking_BreakAll_.png index 71ac3151..86a2ff91 100644 --- a/tests/Images/ReferenceOutput/MeasureTextWordBreak_500-_layoutMode_HorizontalTopBottom-wordBreaking_BreakAll_.png +++ b/tests/Images/ReferenceOutput/MeasureTextWordBreak_500-_layoutMode_HorizontalTopBottom-wordBreaking_BreakAll_.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:a99e819c0a8d7380e7afbdd289ebe0a2ee6f8c62b51ab7d10b06cfddf0729c55 -size 17437 +oid sha256:1fc37c69f57e01534abac8d6ae2c441f88dca4f7111f6b3209f8769ba2a3ac37 +size 17502 diff --git a/tests/Images/ReferenceOutput/MeasureTextWordWrappingHorizontalBottomTop_350-_height_62.625-width_318.86_.png b/tests/Images/ReferenceOutput/MeasureTextWordWrappingHorizontalBottomTop_350-_height_62.625-width_318.86_.png index 02bc02c6..290d860e 100644 --- a/tests/Images/ReferenceOutput/MeasureTextWordWrappingHorizontalBottomTop_350-_height_62.625-width_318.86_.png +++ b/tests/Images/ReferenceOutput/MeasureTextWordWrappingHorizontalBottomTop_350-_height_62.625-width_318.86_.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:bcf9ccad091fde6016070afcaa24e9040d6a81672f04350e56aa446802675bff -size 9272 +oid sha256:e272b2bd807c9137d620115fe9f656cb5c810f967a8b2e85d43a0c87c6f62f56 +size 9240 diff --git a/tests/Images/ReferenceOutput/MeasureTextWordWrappingHorizontalTopBottom_350-_height_62.625-width_318.86_.png b/tests/Images/ReferenceOutput/MeasureTextWordWrappingHorizontalTopBottom_350-_height_62.625-width_318.86_.png index ed9c7eee..b231125f 100644 --- a/tests/Images/ReferenceOutput/MeasureTextWordWrappingHorizontalTopBottom_350-_height_62.625-width_318.86_.png +++ b/tests/Images/ReferenceOutput/MeasureTextWordWrappingHorizontalTopBottom_350-_height_62.625-width_318.86_.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:afd34328b9e945944d90f8e56c33cff7d796a5ab22a55a4b1be5eeb629fb2f5a -size 9268 +oid sha256:c6a65e60c84cb26ad6cdf4241be47cf00ebdc5ad425da1278a683c7dd709f785 +size 9256 diff --git a/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalLeftRight_350-_height_318.563-width_62.813_.png b/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalLeftRight_350-_height_318.563-width_62.813_.png index df8cb7f9..712c58af 100644 --- a/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalLeftRight_350-_height_318.563-width_62.813_.png +++ b/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalLeftRight_350-_height_318.563-width_62.813_.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57b1755082a3e82879b28ff20f2e4e2cd017aa8b0b236678a8dbf5cc6ddab17d -size 10317 +oid sha256:6eb2b3a67d130574b75e917cd37f161a07b74fe7ce79e5b2c42abdf9de96e1c0 +size 10300 diff --git a/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalMixedLeftRight_350-_height_318.563-width_62.813_.png b/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalMixedLeftRight_350-_height_318.563-width_62.813_.png index df8cb7f9..712c58af 100644 --- a/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalMixedLeftRight_350-_height_318.563-width_62.813_.png +++ b/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalMixedLeftRight_350-_height_318.563-width_62.813_.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:57b1755082a3e82879b28ff20f2e4e2cd017aa8b0b236678a8dbf5cc6ddab17d -size 10317 +oid sha256:6eb2b3a67d130574b75e917cd37f161a07b74fe7ce79e5b2c42abdf9de96e1c0 +size 10300 diff --git a/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalRightLeft_350-_height_318.563-width_62.813_.png b/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalRightLeft_350-_height_318.563-width_62.813_.png index 0aa163cb..cdbb5951 100644 --- a/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalRightLeft_350-_height_318.563-width_62.813_.png +++ b/tests/Images/ReferenceOutput/MeasureTextWordWrappingVerticalRightLeft_350-_height_318.563-width_62.813_.png @@ -1,3 +1,3 @@ version https://git-lfs.github.com/spec/v1 -oid sha256:b4b0bc75fa8b2ff464b38401741a58ce0fd7095767883d8fcd227e336a8f9c08 -size 10241 +oid sha256:7161d913d93c3e50cb67dcb57d42afcee5a117b10aa65ff7b8d03ec8a9f9bc93 +size 10313 diff --git a/tests/Images/ReferenceOutput/ShouldNotInsertExtraLineBreaks_2__WrappingLength_400_.png b/tests/Images/ReferenceOutput/ShouldNotInsertExtraLineBreaks_2__WrappingLength_400_.png new file mode 100644 index 00000000..4796c6bd --- /dev/null +++ b/tests/Images/ReferenceOutput/ShouldNotInsertExtraLineBreaks_2__WrappingLength_400_.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:18b14563c798925aaeee959bbeb12bd392af681ab620fb15a0264f7f2904f2a6 +size 14829 diff --git a/tests/SixLabors.Fonts.Tests/Issues/Issues_431.cs b/tests/SixLabors.Fonts.Tests/Issues/Issues_431.cs index f19d8f9e..95c55d35 100644 --- a/tests/SixLabors.Fonts.Tests/Issues/Issues_431.cs +++ b/tests/SixLabors.Fonts.Tests/Issues/Issues_431.cs @@ -30,4 +30,28 @@ public void ShouldNotInsertExtraLineBreaks() TextLayoutTestUtilities.TestLayout(text, options); } } + + [Fact] + public void ShouldNotInsertExtraLineBreaks_2() + { + if (SystemFonts.TryGet("Arial", out FontFamily family)) + { + Font font = family.CreateFont(60); + const string text = "- Lorem ipsullll dolor sit amet\n-consectetur elit"; + + TextOptions options = new(font) + { + Origin = new Vector2(50, 20), + WrappingLength = 400, + }; + + int lineCount = TextMeasurer.CountLines(text, options); + //Assert.Equal(4, lineCount); + + IReadOnlyList layout = TextLayout.GenerateLayout(text, options); + // Assert.Equal(46, layout.Count); + + TextLayoutTestUtilities.TestLayout(text, options); + } + } } diff --git a/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs b/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs index 4e4d9cff..9743fd0b 100644 --- a/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs +++ b/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs @@ -3,6 +3,7 @@ using System.Globalization; using System.Numerics; +using System.Text; using SixLabors.Fonts.Tests.Fakes; using SixLabors.Fonts.Unicode; using SixLabors.ImageSharp.Drawing.Processing; @@ -289,11 +290,11 @@ public void MeasureTextWordWrappingHorizontalTopBottom(string text, float height LayoutMode = LayoutMode.HorizontalTopBottom }; - FontRectangle size = TextMeasurer.MeasureBounds(text, options); + TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); + FontRectangle size = TextMeasurer.MeasureBounds(text, options); Assert.Equal(width, size.Width, 4F); Assert.Equal(height, size.Height, 4F); - TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); } } @@ -315,11 +316,12 @@ public void MeasureTextWordWrappingHorizontalBottomTop(string text, float height LayoutMode = LayoutMode.HorizontalBottomTop }; - FontRectangle size = TextMeasurer.MeasureBounds(text, options); + TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); + + FontRectangle size = TextMeasurer.MeasureBounds(text, options); Assert.Equal(width, size.Width, 4F); Assert.Equal(height, size.Height, 4F); - TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); } } @@ -338,11 +340,11 @@ public void MeasureTextWordWrappingVerticalLeftRight(string text, float height, LayoutMode = LayoutMode.VerticalLeftRight }; - FontRectangle size = TextMeasurer.MeasureBounds(text, options); + TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); + FontRectangle size = TextMeasurer.MeasureBounds(text, options); Assert.Equal(width, size.Width, 4F); Assert.Equal(height, size.Height, 4F); - TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); } } @@ -361,11 +363,11 @@ public void MeasureTextWordWrappingVerticalRightLeft(string text, float height, LayoutMode = LayoutMode.VerticalRightLeft }; - FontRectangle size = TextMeasurer.MeasureBounds(text, options); + TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); + FontRectangle size = TextMeasurer.MeasureBounds(text, options); Assert.Equal(width, size.Width, 4F); Assert.Equal(height, size.Height, 4F); - TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); } } @@ -384,11 +386,11 @@ public void MeasureTextWordWrappingVerticalMixedLeftRight(string text, float hei LayoutMode = LayoutMode.VerticalMixedLeftRight }; - FontRectangle size = TextMeasurer.MeasureBounds(text, options); + TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); + FontRectangle size = TextMeasurer.MeasureBounds(text, options); Assert.Equal(width, size.Width, 4F); Assert.Equal(height, size.Height, 4F); - TextLayoutTestUtilities.TestLayout(text, options, properties: new { height, width }); } } @@ -416,14 +418,11 @@ public void MeasureTextWordBreakMatchesMDN(string text, LayoutMode layoutMode, W FallbackFontFamilies = new[] { jhengHei } }; - FontRectangle size = TextMeasurer.MeasureAdvance( - text, - options); + TextLayoutTestUtilities.TestLayout(text, options, properties: new { layoutMode, wordBreaking }); + FontRectangle size = TextMeasurer.MeasureAdvance(text, options); Assert.Equal(width, size.Width, 4F); Assert.Equal(height, size.Height, 4F); - - TextLayoutTestUtilities.TestLayout(text, options, properties: new { layoutMode, wordBreaking }); } } @@ -455,10 +454,10 @@ public void MeasureTextWordBreak(string text, LayoutMode layoutMode, WordBreakin text, options); + TextLayoutTestUtilities.TestLayout(text, options, properties: new { layoutMode, wordBreaking }); + Assert.Equal(width, size.Width, 4F); Assert.Equal(height, size.Height, 4F); - - TextLayoutTestUtilities.TestLayout(text, options, properties: new { layoutMode, wordBreaking }); } } @@ -550,8 +549,8 @@ public void CountLinesWithSpan() [Theory] [InlineData("This is a long and Honorificabilitudinitatibus califragilisticexpialidocious", 25, 6)] - [InlineData("This is a long and Honorificabilitudinitatibus califragilisticexpialidocious", 50, 5)] - [InlineData("This is a long and Honorificabilitudinitatibus califragilisticexpialidocious", 100, 4)] + [InlineData("This is a long and Honorificabilitudinitatibus califragilisticexpialidocious", 50, 4)] + [InlineData("This is a long and Honorificabilitudinitatibus califragilisticexpialidocious", 100, 3)] [InlineData("This is a long and Honorificabilitudinitatibus califragilisticexpialidocious", 200, 3)] public void CountLinesWrappingLength(string text, int wrappingLength, int usedLines) { @@ -561,9 +560,10 @@ public void CountLinesWrappingLength(string text, int wrappingLength, int usedLi WrappingLength = wrappingLength }; + TextLayoutTestUtilities.TestLayout(text, options, properties: usedLines); + int count = TextMeasurer.CountLines(text, options); Assert.Equal(usedLines, count); - TextLayoutTestUtilities.TestLayout(text, options, properties: usedLines); } [Fact] @@ -668,6 +668,14 @@ public void BuildTextRuns_PreventsOverlappingRun() [InlineData(TextDirection.RightToLeft)] public void TextJustification_InterCharacter_Horizontal(TextDirection direction) { + //const string textI = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ornare maximus vehicula. Duis nisi velit, dictum id mauris vitae, lobortis pretium quam. Quisque sed nisi pulvinar, consequat justo id, feugiat leo. Cras eu elementum dui."; + //StringBuilder sb = new(); + //for (int i = 0; i < textI.Length; i++) + //{ + // sb.Append(textI[i] == ' ' ? ' ' : 'x'); + //} + //string text = sb.ToString(); + const string text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ornare maximus vehicula. Duis nisi velit, dictum id mauris vitae, lobortis pretium quam. Quisque sed nisi pulvinar, consequat justo id, feugiat leo. Cras eu elementum dui."; const float wrappingLength = 400; const float pointSize = 12; @@ -1217,10 +1225,11 @@ public void BreakWordEnsuresSingleCharacterPerLine() }; const string text = "Hello World!"; - int lineCount = TextMeasurer.CountLines(text, options); - Assert.Equal(text.Length - 1, lineCount); TextLayoutTestUtilities.TestLayout(text, options); + + int lineCount = TextMeasurer.CountLines(text, options); + Assert.Equal(text.Length - 1, lineCount); } private class CaptureGlyphBoundBuilder : IGlyphRenderer From 27d5cc54f2c798f9d2d4347f19a8bfb8fc6ec05a Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 10 Jan 2025 22:00:12 +1000 Subject: [PATCH 2/3] Uncomment test asserts --- tests/SixLabors.Fonts.Tests/Issues/Issues_431.cs | 12 ++++++------ 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/tests/SixLabors.Fonts.Tests/Issues/Issues_431.cs b/tests/SixLabors.Fonts.Tests/Issues/Issues_431.cs index 95c55d35..a5db104e 100644 --- a/tests/SixLabors.Fonts.Tests/Issues/Issues_431.cs +++ b/tests/SixLabors.Fonts.Tests/Issues/Issues_431.cs @@ -21,13 +21,13 @@ public void ShouldNotInsertExtraLineBreaks() WrappingLength = 400, }; + TextLayoutTestUtilities.TestLayout(text, options); + int lineCount = TextMeasurer.CountLines(text, options); Assert.Equal(4, lineCount); IReadOnlyList layout = TextLayout.GenerateLayout(text, options); Assert.Equal(46, layout.Count); - - TextLayoutTestUtilities.TestLayout(text, options); } } @@ -45,13 +45,13 @@ public void ShouldNotInsertExtraLineBreaks_2() WrappingLength = 400, }; + TextLayoutTestUtilities.TestLayout(text, options); + int lineCount = TextMeasurer.CountLines(text, options); - //Assert.Equal(4, lineCount); + Assert.Equal(4, lineCount); IReadOnlyList layout = TextLayout.GenerateLayout(text, options); - // Assert.Equal(46, layout.Count); - - TextLayoutTestUtilities.TestLayout(text, options); + Assert.Equal(46, layout.Count); } } } From 371e95a497a7aa8f8742d5223df3099071dbffea Mon Sep 17 00:00:00 2001 From: James Jackson-South Date: Fri, 10 Jan 2025 22:44:38 +1000 Subject: [PATCH 3/3] Remove debugging code --- tests/SixLabors.Fonts.Tests/TextLayoutTests.cs | 8 -------- 1 file changed, 8 deletions(-) diff --git a/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs b/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs index 9743fd0b..7b3ff0ca 100644 --- a/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs +++ b/tests/SixLabors.Fonts.Tests/TextLayoutTests.cs @@ -668,14 +668,6 @@ public void BuildTextRuns_PreventsOverlappingRun() [InlineData(TextDirection.RightToLeft)] public void TextJustification_InterCharacter_Horizontal(TextDirection direction) { - //const string textI = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ornare maximus vehicula. Duis nisi velit, dictum id mauris vitae, lobortis pretium quam. Quisque sed nisi pulvinar, consequat justo id, feugiat leo. Cras eu elementum dui."; - //StringBuilder sb = new(); - //for (int i = 0; i < textI.Length; i++) - //{ - // sb.Append(textI[i] == ' ' ? ' ' : 'x'); - //} - //string text = sb.ToString(); - const string text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Nunc ornare maximus vehicula. Duis nisi velit, dictum id mauris vitae, lobortis pretium quam. Quisque sed nisi pulvinar, consequat justo id, feugiat leo. Cras eu elementum dui."; const float wrappingLength = 400; const float pointSize = 12;