Skip to content

Commit dfd3237

Browse files
Update TextBuilderTests.cs
1 parent c343942 commit dfd3237

1 file changed

Lines changed: 210 additions & 0 deletions

File tree

tests/ImageSharp.Drawing.Tests/Shapes/TextBuilderTests.cs

Lines changed: 210 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@
33

44
using System.Numerics;
55
using SixLabors.Fonts;
6+
using SixLabors.Fonts.Rendering;
7+
using SixLabors.ImageSharp.Drawing.Processing;
68
using SixLabors.ImageSharp.Drawing.Text;
9+
using SixLabors.ImageSharp.PixelFormats;
710

811
namespace SixLabors.ImageSharp.Drawing.Tests.Shapes;
912

@@ -66,4 +69,211 @@ public void TextBuilder_Bounds_AreCorrect_Glyphs()
6669
// is no path to include.
6770
Assert.True(measuredBounds.Height >= builderBounds.Height);
6871
}
72+
73+
[Fact]
74+
public void GlyphPathCollection_PreservesLayerMetadataAndFiltersPaths()
75+
{
76+
RectangularPolygon glyphPath = new(0, 0, 10, 12);
77+
RectangularPolygon paintedPath = new(20, 4, 6, 8);
78+
SolidPaint paint = new() { CompositeMode = CompositeMode.Multiply };
79+
80+
GlyphPathCollection.Builder builder = new();
81+
builder.AddPath(glyphPath);
82+
builder.AddLayer(0, 1, null, FillRule.NonZero, glyphPath.Bounds, GlyphLayerKind.Glyph);
83+
builder.AddPath(paintedPath);
84+
builder.AddLayer(1, 1, paint, FillRule.EvenOdd, paintedPath.Bounds, GlyphLayerKind.Painted);
85+
86+
GlyphPathCollection glyph = builder.Build();
87+
88+
Assert.Equal(2, glyph.PathList.Count);
89+
Assert.Equal(2, glyph.LayerCount);
90+
Assert.Same(glyphPath, glyph.PathList[0]);
91+
Assert.Same(paintedPath, glyph.PathList[1]);
92+
93+
GlyphLayerInfo glyphLayer = glyph.Layers[0];
94+
Assert.Equal(0, glyphLayer.StartIndex);
95+
Assert.Equal(1, glyphLayer.Count);
96+
Assert.Null(glyphLayer.Paint);
97+
Assert.Equal(IntersectionRule.NonZero, glyphLayer.IntersectionRule);
98+
Assert.Equal(PixelAlphaCompositionMode.SrcOver, glyphLayer.PixelAlphaCompositionMode);
99+
Assert.Equal(PixelColorBlendingMode.Normal, glyphLayer.PixelColorBlendingMode);
100+
Assert.Equal(GlyphLayerKind.Glyph, glyphLayer.Kind);
101+
Assert.Equal(glyphPath.Bounds, glyphLayer.Bounds);
102+
103+
GlyphLayerInfo paintedLayer = glyph.Layers[1];
104+
Assert.Equal(1, paintedLayer.StartIndex);
105+
Assert.Equal(1, paintedLayer.Count);
106+
Assert.Same(paint, paintedLayer.Paint);
107+
Assert.Equal(IntersectionRule.EvenOdd, paintedLayer.IntersectionRule);
108+
Assert.Equal(PixelAlphaCompositionMode.SrcOver, paintedLayer.PixelAlphaCompositionMode);
109+
Assert.Equal(PixelColorBlendingMode.Multiply, paintedLayer.PixelColorBlendingMode);
110+
Assert.Equal(GlyphLayerKind.Painted, paintedLayer.Kind);
111+
Assert.Equal(paintedPath.Bounds, paintedLayer.Bounds);
112+
113+
Assert.Equal(2, glyph.ToPathCollection().Count());
114+
Assert.Same(glyphPath, glyph.ToPathCollection(layer => layer.Kind == GlyphLayerKind.Glyph).Single());
115+
Assert.Same(paintedPath, glyph.GetLayerPaths(1).Single());
116+
}
117+
118+
[Fact]
119+
public void GlyphPathCollection_Transform_TransformsPathsAndLayerBounds()
120+
{
121+
RectangularPolygon path = new(2, 3, 10, 5);
122+
123+
GlyphPathCollection.Builder builder = new();
124+
builder.AddPath(path);
125+
builder.AddLayer(0, 1, null, FillRule.NonZero, path.Bounds);
126+
127+
GlyphPathCollection glyph = builder.Build();
128+
Matrix4x4 matrix = Matrix4x4.CreateTranslation(7, 11, 0);
129+
130+
GlyphPathCollection transformed = glyph.Transform(matrix);
131+
132+
Assert.NotSame(glyph, transformed);
133+
Assert.Equal(new RectangleF(9, 14, 10, 5), transformed.Bounds);
134+
Assert.Equal(new RectangleF(9, 14, 10, 5), transformed.Layers[0].Bounds);
135+
Assert.Equal(glyph.Layers[0].StartIndex, transformed.Layers[0].StartIndex);
136+
Assert.Equal(glyph.Layers[0].Count, transformed.Layers[0].Count);
137+
Assert.Equal(glyph.Layers[0].Kind, transformed.Layers[0].Kind);
138+
Assert.Equal(new RectangleF(2, 3, 10, 5), glyph.Bounds);
139+
}
140+
141+
[Fact]
142+
public void GlyphPathCollection_BuilderRejectsOutOfRangeLayerSpan()
143+
{
144+
GlyphPathCollection.Builder builder = new();
145+
builder.AddPath(new RectangularPolygon(0, 0, 10, 10));
146+
147+
ArgumentOutOfRangeException ex = Assert.Throws<ArgumentOutOfRangeException>(
148+
() => builder.AddLayer(1, 1, null, FillRule.NonZero, RectangleF.Empty));
149+
150+
Assert.Equal("count", ex.ParamName);
151+
}
152+
153+
[Theory]
154+
[InlineData(FillRule.NonZero, IntersectionRule.NonZero)]
155+
[InlineData(FillRule.EvenOdd, IntersectionRule.EvenOdd)]
156+
public void TextUtilities_MapsFillRules(FillRule fillRule, IntersectionRule intersectionRule)
157+
=> Assert.Equal(intersectionRule, TextUtilities.MapFillRule(fillRule));
158+
159+
[Theory]
160+
[InlineData(CompositeMode.Clear, PixelAlphaCompositionMode.Clear)]
161+
[InlineData(CompositeMode.Src, PixelAlphaCompositionMode.Src)]
162+
[InlineData(CompositeMode.Dest, PixelAlphaCompositionMode.Dest)]
163+
[InlineData(CompositeMode.SrcOver, PixelAlphaCompositionMode.SrcOver)]
164+
[InlineData(CompositeMode.DestOver, PixelAlphaCompositionMode.DestOver)]
165+
[InlineData(CompositeMode.SrcIn, PixelAlphaCompositionMode.SrcIn)]
166+
[InlineData(CompositeMode.DestIn, PixelAlphaCompositionMode.DestIn)]
167+
[InlineData(CompositeMode.SrcOut, PixelAlphaCompositionMode.SrcOut)]
168+
[InlineData(CompositeMode.DestOut, PixelAlphaCompositionMode.DestOut)]
169+
[InlineData(CompositeMode.SrcAtop, PixelAlphaCompositionMode.SrcAtop)]
170+
[InlineData(CompositeMode.DestAtop, PixelAlphaCompositionMode.DestAtop)]
171+
[InlineData(CompositeMode.Xor, PixelAlphaCompositionMode.Xor)]
172+
[InlineData(CompositeMode.Multiply, PixelAlphaCompositionMode.SrcOver)]
173+
public void TextUtilities_MapsAlphaCompositionModes(CompositeMode compositeMode, PixelAlphaCompositionMode alphaCompositionMode)
174+
=> Assert.Equal(alphaCompositionMode, TextUtilities.MapCompositionMode(compositeMode));
175+
176+
[Theory]
177+
[InlineData(CompositeMode.Plus, PixelColorBlendingMode.Add)]
178+
[InlineData(CompositeMode.Screen, PixelColorBlendingMode.Screen)]
179+
[InlineData(CompositeMode.Overlay, PixelColorBlendingMode.Overlay)]
180+
[InlineData(CompositeMode.Darken, PixelColorBlendingMode.Darken)]
181+
[InlineData(CompositeMode.Lighten, PixelColorBlendingMode.Lighten)]
182+
[InlineData(CompositeMode.HardLight, PixelColorBlendingMode.HardLight)]
183+
[InlineData(CompositeMode.Multiply, PixelColorBlendingMode.Multiply)]
184+
[InlineData(CompositeMode.SrcOver, PixelColorBlendingMode.Normal)]
185+
[InlineData(CompositeMode.ColorDodge, PixelColorBlendingMode.Normal)]
186+
public void TextUtilities_MapsColorBlendingModes(CompositeMode compositeMode, PixelColorBlendingMode colorBlendingMode)
187+
=> Assert.Equal(colorBlendingMode, TextUtilities.MapBlendingMode(compositeMode));
188+
189+
[Fact]
190+
public void TextUtilities_CloneOrReturnForRules_ReturnsDrawingOptionsWhenRulesMatch()
191+
{
192+
DrawingOptions options = new();
193+
194+
DrawingOptions result = options.CloneOrReturnForRules(
195+
options.ShapeOptions.IntersectionRule,
196+
options.GraphicsOptions.AlphaCompositionMode,
197+
options.GraphicsOptions.ColorBlendingMode);
198+
199+
Assert.Same(options, result);
200+
}
201+
202+
[Fact]
203+
public void TextUtilities_CloneOrReturnForRules_ClonesDrawingOptionsWhenRulesDiffer()
204+
{
205+
DrawingOptions options = new()
206+
{
207+
Transform = Matrix4x4.CreateTranslation(12, 23, 0)
208+
};
209+
210+
DrawingOptions result = options.CloneOrReturnForRules(
211+
IntersectionRule.EvenOdd,
212+
PixelAlphaCompositionMode.SrcIn,
213+
PixelColorBlendingMode.Multiply);
214+
215+
Assert.NotSame(options, result);
216+
Assert.NotSame(options.ShapeOptions, result.ShapeOptions);
217+
Assert.NotSame(options.GraphicsOptions, result.GraphicsOptions);
218+
Assert.Equal(IntersectionRule.EvenOdd, result.ShapeOptions.IntersectionRule);
219+
Assert.Equal(PixelAlphaCompositionMode.SrcIn, result.GraphicsOptions.AlphaCompositionMode);
220+
Assert.Equal(PixelColorBlendingMode.Multiply, result.GraphicsOptions.ColorBlendingMode);
221+
Assert.Equal(options.Transform, result.Transform);
222+
Assert.Equal(IntersectionRule.NonZero, options.ShapeOptions.IntersectionRule);
223+
Assert.Equal(PixelAlphaCompositionMode.SrcOver, options.GraphicsOptions.AlphaCompositionMode);
224+
Assert.Equal(PixelColorBlendingMode.Normal, options.GraphicsOptions.ColorBlendingMode);
225+
}
226+
227+
[Fact]
228+
public void TextBuilder_GenerateGlyphs_ReturnsLayerMetadataForSimpleText()
229+
{
230+
TextOptions options = new(TestFontUtilities.GetFont(TestFonts.OpenSans, 18))
231+
{
232+
Origin = new Vector2(4, 7)
233+
};
234+
235+
IReadOnlyList<GlyphPathCollection> glyphs = TextBuilder.GenerateGlyphs("Hi", options);
236+
237+
Assert.Equal(2, glyphs.Count);
238+
239+
foreach (GlyphPathCollection glyph in glyphs)
240+
{
241+
Assert.True(glyph.PathList.Count > 0);
242+
Assert.Equal(1, glyph.LayerCount);
243+
Assert.Equal(glyph.PathList.Count, glyph.Layers.Sum(layer => layer.Count));
244+
Assert.Equal(GlyphLayerKind.Glyph, glyph.Layers[0].Kind);
245+
Assert.Equal(glyph.Paths.Bounds, glyph.ToPathCollection().Bounds);
246+
}
247+
}
248+
249+
[Fact]
250+
public void TextBuilder_PathOverload_TranslatesPathWhenOptionsHaveOrigin()
251+
{
252+
Font font = TestFontUtilities.GetFont(TestFonts.OpenSans, 24);
253+
const string text = "Path";
254+
255+
TextOptions optionsWithOrigin = new(font)
256+
{
257+
Origin = new Vector2(17, 29)
258+
};
259+
260+
TextOptions optionsWithoutOrigin = new(font);
261+
Path path = new([new PointF(0, 100), new PointF(600, 100)]);
262+
263+
IPathCollection withOrigin = TextBuilder.GeneratePaths(text, path, optionsWithOrigin);
264+
IPathCollection translatedPaths = TextBuilder.GeneratePaths(text, path.Translate(optionsWithOrigin.Origin), optionsWithoutOrigin);
265+
IReadOnlyList<GlyphPathCollection> glyphs = TextBuilder.GenerateGlyphs(text, path, optionsWithOrigin);
266+
RectangleF glyphBounds = glyphs.Select(glyph => glyph.Bounds).Aggregate(RectangleF.Union);
267+
268+
AssertRectEqual(translatedPaths.Bounds, withOrigin.Bounds);
269+
AssertRectEqual(withOrigin.Bounds, glyphBounds);
270+
}
271+
272+
private static void AssertRectEqual(RectangleF expected, RectangleF actual, int precision = 3)
273+
{
274+
Assert.Equal(expected.X, actual.X, precision);
275+
Assert.Equal(expected.Y, actual.Y, precision);
276+
Assert.Equal(expected.Width, actual.Width, precision);
277+
Assert.Equal(expected.Height, actual.Height, precision);
278+
}
69279
}

0 commit comments

Comments
 (0)