From 2aeed6ff9f618d96c83497710d7547bff9fedd8a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Javier=20Su=C3=A1rez?= Date: Tue, 16 Dec 2025 17:12:31 +0100 Subject: [PATCH] [Feature] Add FillRule property for Polyline/Polygon (#20159) * Implement FillRuleProperty on Polyline * Implement FillRule Property on Polygon * Add tests * Added comments to new public APIs * Added more comments * More tests * More tests * Updated API * Added render tests * More render tests * Reintroducing the original PolylineGeometry constructor * Updated API file --------- Co-authored-by: Julien Lebosquain --- src/Avalonia.Base/Media/PolylineGeometry.cs | 25 ++++++- src/Avalonia.Controls/Shapes/Polygon.cs | 16 +++- src/Avalonia.Controls/Shapes/Polyline.cs | 18 ++++- .../Shapes/PolygonTests.cs | 48 ++++++++++++ .../Shapes/PolylineTests.cs | 63 ++++++++++++++++ .../Shapes/PolygonTests.cs | 33 +++++++++ .../Shapes/PolylineTests.cs | 69 ++++++++++++++++++ .../Polygon_FillRule_EvenOdd.expected.png | Bin 0 -> 7530 bytes .../Polygon_FillRule_NonZero.expected.png | Bin 0 -> 7665 bytes .../Polyline_FillRule_EvenOdd.expected.png | Bin 0 -> 7579 bytes .../Polyline_FillRule_NoFill.expected.png | Bin 0 -> 4934 bytes .../Polyline_FillRule_NonZero.expected.png | Bin 0 -> 7591 bytes 12 files changed, 267 insertions(+), 5 deletions(-) create mode 100644 tests/TestFiles/Skia/Shapes/Polygon/Polygon_FillRule_EvenOdd.expected.png create mode 100644 tests/TestFiles/Skia/Shapes/Polygon/Polygon_FillRule_NonZero.expected.png create mode 100644 tests/TestFiles/Skia/Shapes/Polyline/Polyline_FillRule_EvenOdd.expected.png create mode 100644 tests/TestFiles/Skia/Shapes/Polyline/Polyline_FillRule_NoFill.expected.png create mode 100644 tests/TestFiles/Skia/Shapes/Polyline/Polyline_FillRule_NonZero.expected.png diff --git a/src/Avalonia.Base/Media/PolylineGeometry.cs b/src/Avalonia.Base/Media/PolylineGeometry.cs index 13b11d8444..f9b9c24be9 100644 --- a/src/Avalonia.Base/Media/PolylineGeometry.cs +++ b/src/Avalonia.Base/Media/PolylineGeometry.cs @@ -27,6 +27,7 @@ namespace Avalonia.Media private IList _points; private IDisposable? _pointsObserver; + private readonly FillRule _fillRule; static PolylineGeometry() { @@ -40,8 +41,10 @@ namespace Avalonia.Media public PolylineGeometry() { _points = new Points(); + _fillRule = FillRule.EvenOdd; } + /// /// /// Initializes a new instance of the class. /// @@ -49,6 +52,17 @@ namespace Avalonia.Media { _points = new Points(points); IsFilled = isFilled; + _fillRule = FillRule.EvenOdd; + } + + /// + /// Initializes a new instance of the class. + /// + public PolylineGeometry(IEnumerable points, bool isFilled, FillRule fillRule) + { + _points = new Points(points); + IsFilled = isFilled; + _fillRule = fillRule; } /// @@ -70,10 +84,18 @@ namespace Avalonia.Media set => SetValue(IsFilledProperty, value); } + /// + /// Gets how the intersecting areas of the polyline are combined. + /// + public FillRule FillRule => _fillRule; + /// public override Geometry Clone() { - return new PolylineGeometry(Points, IsFilled); + return new PolylineGeometry(Points, IsFilled, _fillRule) + { + Transform = Transform + }; } private protected sealed override IGeometryImpl? CreateDefiningGeometry() @@ -83,6 +105,7 @@ namespace Avalonia.Media using (var context = geometry.Open()) { + context.SetFillRule(_fillRule); var points = Points; var isFilled = IsFilled; if (points.Count > 0) diff --git a/src/Avalonia.Controls/Shapes/Polygon.cs b/src/Avalonia.Controls/Shapes/Polygon.cs index 48530432f0..d6fdcafa56 100644 --- a/src/Avalonia.Controls/Shapes/Polygon.cs +++ b/src/Avalonia.Controls/Shapes/Polygon.cs @@ -9,9 +9,12 @@ namespace Avalonia.Controls.Shapes public static readonly StyledProperty> PointsProperty = AvaloniaProperty.Register>("Points"); + public static readonly StyledProperty FillRuleProperty = + AvaloniaProperty.Register(nameof(FillRule)); + static Polygon() { - AffectsGeometry(PointsProperty); + AffectsGeometry(PointsProperty, FillRuleProperty); } public Polygon() @@ -25,9 +28,18 @@ namespace Avalonia.Controls.Shapes set => SetValue(PointsProperty, value); } + /// + /// Gets or sets how the interior of the polygon is determined when a is applied. + /// + public FillRule FillRule + { + get => GetValue(FillRuleProperty); + set => SetValue(FillRuleProperty, value); + } + protected override Geometry CreateDefiningGeometry() { - return new PolylineGeometry { Points = Points, IsFilled = true }; + return new PolylineGeometry(Points, isFilled: true, fillRule: FillRule); } } } diff --git a/src/Avalonia.Controls/Shapes/Polyline.cs b/src/Avalonia.Controls/Shapes/Polyline.cs index 628fc70e1d..a067520273 100644 --- a/src/Avalonia.Controls/Shapes/Polyline.cs +++ b/src/Avalonia.Controls/Shapes/Polyline.cs @@ -1,5 +1,6 @@ using System; using System.Collections.Generic; +using Avalonia; using Avalonia.Media; using Avalonia.Data; @@ -10,10 +11,13 @@ namespace Avalonia.Controls.Shapes public static readonly StyledProperty> PointsProperty = AvaloniaProperty.Register>("Points"); + public static readonly StyledProperty FillRuleProperty = + AvaloniaProperty.Register(nameof(FillRule)); + static Polyline() { StrokeThicknessProperty.OverrideDefaultValue(1); - AffectsGeometry(PointsProperty); + AffectsGeometry(PointsProperty, FillRuleProperty); } public Polyline() @@ -27,9 +31,19 @@ namespace Avalonia.Controls.Shapes set => SetValue(PointsProperty, value); } + /// + /// Gets or sets how the interior of the polyline is determined when a is applied. + /// + public FillRule FillRule + { + get => GetValue(FillRuleProperty); + set => SetValue(FillRuleProperty, value); + } + protected override Geometry CreateDefiningGeometry() { - return new PolylineGeometry { Points = Points, IsFilled = false }; + var isFilled = Fill != null; + return new PolylineGeometry(Points, isFilled, FillRule); } } } diff --git a/tests/Avalonia.Controls.UnitTests/Shapes/PolygonTests.cs b/tests/Avalonia.Controls.UnitTests/Shapes/PolygonTests.cs index 1584e836e8..c273aef013 100644 --- a/tests/Avalonia.Controls.UnitTests/Shapes/PolygonTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Shapes/PolygonTests.cs @@ -1,5 +1,6 @@ using System.Collections.ObjectModel; using Avalonia.Controls.Shapes; +using Avalonia.Media; using Avalonia.UnitTests; using Xunit; @@ -25,4 +26,51 @@ public class PolygonTests root.Child = null; } + + [Fact] + public void FillRule_On_Polygon_Is_Applied_To_DefiningGeometry() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var target = new Polygon + { + Points = new Points { new Point(0, 0), new Point(10, 10), new Point(20, 0) }, + FillRule = FillRule.NonZero + }; + + target.Measure(Size.Infinity); + + var geometry = Assert.IsType(target.DefiningGeometry); + Assert.Equal(FillRule.NonZero, geometry.FillRule); + } + + [Fact] + public void Polygon_Equals_Closed_Polyline_Bounds() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var polyline = new Polyline + { + Points = new Points + { + new Point(0, 0), + new Point(10, 0), + new Point(10, 10), + new Point(0, 10), + new Point(0, 0) + }, + FillRule = FillRule.NonZero + }; + + var polygon = new Polygon + { + Points = new Points { new Point(0, 0), new Point(10, 0), new Point(10, 10), new Point(0, 10) }, + FillRule = FillRule.NonZero + }; + + polyline.Measure(Size.Infinity); + polygon.Measure(Size.Infinity); + + Assert.Equal(polygon.DefiningGeometry!.Bounds, polyline.DefiningGeometry!.Bounds); + } } diff --git a/tests/Avalonia.Controls.UnitTests/Shapes/PolylineTests.cs b/tests/Avalonia.Controls.UnitTests/Shapes/PolylineTests.cs index a68dc9d4b4..078311f9d1 100644 --- a/tests/Avalonia.Controls.UnitTests/Shapes/PolylineTests.cs +++ b/tests/Avalonia.Controls.UnitTests/Shapes/PolylineTests.cs @@ -1,5 +1,6 @@ using System.Collections.ObjectModel; using Avalonia.Controls.Shapes; +using Avalonia.Media; using Avalonia.UnitTests; using Xunit; @@ -25,4 +26,66 @@ public class PolylineTests root.Child = null; } + + [Fact] + public void FillRule_On_Polyline_Is_Applied_To_DefiningGeometry() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var target = new Polyline + { + Points = new Points { new Point(0, 0), new Point(10, 10), new Point(20, 0) }, + Fill = Brushes.Red, + FillRule = FillRule.NonZero + }; + + target.Measure(Size.Infinity); + + var geometry = Assert.IsType(target.DefiningGeometry); + Assert.Equal(FillRule.NonZero, geometry.FillRule); + Assert.True(geometry.IsFilled); + } + + [Fact] + public void FillRule_Differs_Between_EvenOdd_And_NonZero() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var evenOdd = new Polyline + { + Points = new Points { new Point(0, 0), new Point(10, 10), new Point(20, 0) }, + Fill = Brushes.Red, + FillRule = FillRule.EvenOdd + }; + + var nonZero = new Polyline + { + Points = new Points { new Point(0, 0), new Point(10, 10), new Point(20, 0) }, + Fill = Brushes.Red, + FillRule = FillRule.NonZero + }; + + evenOdd.Measure(Size.Infinity); + nonZero.Measure(Size.Infinity); + + Assert.Equal(FillRule.EvenOdd, Assert.IsType(evenOdd.DefiningGeometry).FillRule); + Assert.Equal(FillRule.NonZero, Assert.IsType(nonZero.DefiningGeometry).FillRule); + } + + [Fact] + public void When_Fill_Is_Null_Polyline_Geometry_Is_Not_Filled() + { + using var app = UnitTestApplication.Start(TestServices.MockPlatformRenderInterface); + + var target = new Polyline + { + Points = new Points { new Point(0, 0), new Point(10, 10), new Point(20, 0) }, + FillRule = FillRule.NonZero, + Fill = null + }; + + target.Measure(Size.Infinity); + var geometry = Assert.IsType(target.DefiningGeometry); + Assert.False(geometry.IsFilled); + } } diff --git a/tests/Avalonia.RenderTests/Shapes/PolygonTests.cs b/tests/Avalonia.RenderTests/Shapes/PolygonTests.cs index b918f7180a..268a290df6 100644 --- a/tests/Avalonia.RenderTests/Shapes/PolygonTests.cs +++ b/tests/Avalonia.RenderTests/Shapes/PolygonTests.cs @@ -17,6 +17,39 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes { } + [Theory] + [InlineData(FillRule.EvenOdd)] + [InlineData(FillRule.NonZero)] + public async Task Polygon_FillRule(FillRule fillRule) + { + var target = new Decorator + { + Padding = new Thickness(8), + Width = 220, + Height = 220, + Child = new Polygon + { + Stroke = Brushes.Black, + StrokeThickness = 2, + Fill = Brushes.Gold, + Points = new Points + { + new Point(50, 0), + new Point(21, 90), + new Point(98, 35), + new Point(2, 35), + new Point(79, 90) + }, + Stretch = Stretch.Uniform, + FillRule = fillRule + } + }; + + var testName = $"{nameof(Polygon_FillRule)}_{fillRule}"; + await RenderToFile(target, testName); + CompareImages(testName); + } + [Fact] public async Task Polygon_1px_Stroke() { diff --git a/tests/Avalonia.RenderTests/Shapes/PolylineTests.cs b/tests/Avalonia.RenderTests/Shapes/PolylineTests.cs index 12420b524a..d964736eeb 100644 --- a/tests/Avalonia.RenderTests/Shapes/PolylineTests.cs +++ b/tests/Avalonia.RenderTests/Shapes/PolylineTests.cs @@ -17,6 +17,75 @@ namespace Avalonia.Direct2D1.RenderTests.Shapes { } + [Theory] + [InlineData(FillRule.EvenOdd)] + [InlineData(FillRule.NonZero)] + public async Task Polyline_FillRule(FillRule fillRule) + { + var target = new Decorator + { + Padding = new Thickness(8), + Width = 260, + Height = 180, + Child = new Polyline + { + Stroke = Brushes.Black, + StrokeThickness = 2, + Fill = Brushes.OrangeRed, + Points = new Points + { + new Point(10, 170), + new Point(60, 20), + new Point(110, 170), + new Point(20, 70), + new Point(240, 70), + new Point(130, 170), + new Point(190, 20), + new Point(10, 170), + }, + Stretch = Stretch.Uniform, + FillRule = fillRule + } + }; + + var testName = $"{nameof(Polyline_FillRule)}_{fillRule}"; + await RenderToFile(target, testName); + CompareImages(testName); + } + + [Fact] + public async Task Polyline_FillRule_NoFill() + { + var target = new Decorator + { + Padding = new Thickness(8), + Width = 260, + Height = 180, + Child = new Polyline + { + Stroke = Brushes.Black, + StrokeThickness = 2, + Fill = null, + Points = new Points + { + new Point(10, 170), + new Point(60, 20), + new Point(110, 170), + new Point(20, 70), + new Point(240, 70), + new Point(130, 170), + new Point(190, 20), + new Point(10, 170), + }, + Stretch = Stretch.Uniform, + FillRule = FillRule.EvenOdd + } + }; + + await RenderToFile(target); + CompareImages(); + } + [Fact] public async Task Polyline_1px_Stroke() { diff --git a/tests/TestFiles/Skia/Shapes/Polygon/Polygon_FillRule_EvenOdd.expected.png b/tests/TestFiles/Skia/Shapes/Polygon/Polygon_FillRule_EvenOdd.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..db832be43b358b0493fc6740f6cf151edf3f5c84 GIT binary patch literal 7530 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 literal 0 HcmV?d00001 diff --git a/tests/TestFiles/Skia/Shapes/Polygon/Polygon_FillRule_NonZero.expected.png b/tests/TestFiles/Skia/Shapes/Polygon/Polygon_FillRule_NonZero.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..152f959fd94a4da5c8a3afdaf9d0dd8717f3d295 GIT binary patch literal 7665 zcmZ{Jby!qS^!F}Z%Sv}HAq@-2lF}tDA>A(BNH-EvONy|BNSD;oQY#_SO4lMKNT~=? z^6vM2-{<$d|Gf9P_s-n=%$#%P%sDgXd?wjIPXk24NCE%=Kw6rrM%Z%gzlVqb`)0D3 zj=>gq{>oa$MA$2w$SDZ`V5!zpRWc4n9v6j#o6Ms|`#C6+lSZN?2C77QExsBM7(T}@ zwvbhLBT9c|Y8>(s5#=X{I(MID z1WteY@aA;#&GdDo!j+=ei9Echb-Fw3bkinG$beeS@PF={Xi=`~cYjmSYmXGQUj0-Q zz(6`chB=~VQHq(X>JPQ)VZ=$QQP)+*jPWt5Dsrbhz-b?e@qn z!^`qu&kB*q9FO{>zc*X?#kt3$a84&c^MH*9kjh3}Q}fGzO7pk(e)sd-tOtia{|1r$ z3?FYFFZ#Mua}PKH=Z{w?rQ3=%ow9G4E%eK+E&ZRp*=WOwoa-=K39Rc}Md7c1#>% zmTg=h3BVF9FT7MOL3O;?q%%wc_MV1R~9n&%KDiIbK<~ul#U>$p;#ksL}Y4H7zPJ<>Fx_TTKPdsgt=aEi3+eF=7WW zit%S|*3lvfgn2)OH}`NDH=GkmY^B$$BqlbM5k%T zx`6ks)o~Bd*OJE`?57O;#B_7ft)3_yEyh6D=^Vx(D2}Z<_ukJy2e!*B>tww zjj7-684~H{jzX}mv-gOzhaC`D+UGlfu#%JwW0lMYA7*>{lK}hafb(qIM<(Mp54Qdm zj3`=X&}%NWP~2oi%mWcz%~fr;Nv~+Ij1tS~dYHbgiEn2#bY{pPgIq2)I`%021t$Z) zQ5Zun2u5*j;jEw@g&67-3vS97@;JNcC;*>3YPJ9(@Tp85DV0wo>e?1KMc`MT{BFY5 zq~RQZ<){etH-{l5u!FJuj+l#RiD@`q8OkWpHenX1sm)5Y3A+T&&^&CpAk*f=&XdC4 zO5r?~!UX+K)gR!_R2k&Wvp!~neY}E)3*y-R)-BPVSli>flIVk`=jOat83EL&00MB@ zSN(Y^_}UWvUt6&|ANkxMK|4#1ZZAd-3Xmz)=&ls!!ExPUO{(Eg92TQ)4W1_P2FV)k z`|5ry5f^g-?^1bW7!tQUoz<G2yxJ51mtu5rfE4qU2LN6<>B*jcgGmUjcN&^rRQ;tQltq!H+`{e00 z*@1di{(4v*#->!b;*40fdH3`Jd_{x@fH$JjZoO3-pBe2vPx^{WdLSkWV7K} znhf&yv%XeYLkB;bT8jfwneu?V@^J%mT^;kf4@nj^&JE1UVK6uYu zwIn%H5AX^YV@+c@JGJ@EP1p3&XZ{t;#Qi;bJ2n+jZ6`-Z!@-0@f}% zS1Y+j`U(Vd#SujqZ9i(<>G{a!w;a2M1HZo)q?U1^1qK32+b-A&3edW^#efx@TQhj4 zOYiOo{;Q0~i9wHJvi*vANZ!0Ne~qF?|!_VG~s(1V;Li@=r(%MzR%;XUTKV z{FKo2|oxT6%EC2t(NwW<4xg z&g5w*jMHT}S!gHXKl5~8Togv1NhkypwMTsS;`bL=`iC39O5jOO_*iITb?}P_I`Hyy z4$zPl4iMq-ug?<<7a0dW*3SH=gMmeKuh@;3CrEo4#R)aCuHp>7Of{c zSUsJYABWpy!UN-+{Q1<1w|-~BSD;60#b5A)K@4ut=P&ik$zyPF zD{zOIcM-M!*snp!!81lK+Ynx-8Y`P%m)#n3ce7QCK)fDQoV~E7eCzimZZO$EjJC%g z*Q#?-liJ;?ZnLHu0Y5u;ZHk~{9~!g6=#{Qa`O8Wx!YIuj_5(`yf1X`$pS70AxWs@0 z7&+5S^F?IwVl}taVbc0WWl{HrUrsNfg&oQpl6zJlF2#F(!Qwi}_-xs}&xm7%%F;Q1 zX1R_bB~rn?FMqyyEEmQ7@Bl<~f0p#xTXw?HSLl#Xsv^w7s)djhy3`{lUoP*}ilaou)7Cow;Ai>E9ryhDT$^ z>%2epE4>nSCE8|8bH5->5N)}}RgBN#%Fh3|W znRL1{GicM@lf(_fI{zJ+j8-GcrO>Kpv8Fou&Cj7R+8y&Aroxw*BWKDBjmo9GO>Nzb zCsC}|`msWrU7n`fABA5KdV1C>IQ#$yTQ{uzDpF0Iuys;T6;vv2RyG5nnaBy7*gBJ{ zON}~-LyK@zOuIcyAo*dNIP}(Y54seVAeXn=Auk-_Gn)s7$Hez!Y;L_yaC%?WrvyWl zcMBVQhFp^SmacqZv7t(_ZL-COlhp-TMxAzf(q_1Y5cRBK0eLIIgi+GTyh#aTqYe`(Di-A z-QAtBZ}M2aifjn$S?vfXq-u;A(%pNK5?%Lm%&LK-cLhD%!q$oR<~EN$cKn;k3BBV{ zB&)bwI5x_dgqH~4M_q}WEHwq^%HbNq1(b@@p8Ui{WRIDr>?9Gm_3ItBl)33ez>0MI zU7{g##r6FLGRe~UblbPudUB%XMsxU(M#ip5QOh~ zVDuBkMLCU&-!~?Nm7pFgbEjgL(Jj@oC815N!i^h2%yWB8N3wMv{`zW~vpGgP zD~@Dp3^@94DW}xk95|y&vs(ii7_B#9mMS+{WyoCv6%%AEB4(ii9X?Bo2zzoW32+OoNF)zC4Rp4<)&K zEu#%?=iBispbE+}f zSSb6nj0^H(BiL433iP9DiuTEK0Wrg$O))n1m0^OL zop)gS^_UDT!FgWTxv99(cZMO&ugl{xKZx^1=jiQyVTkJZ#OS_(y>Bd{=i!~Z6q)Tz z%8tB+Bbu?R`4;Bp#QtoVNtxeRqKP08G5CK)9k|Sg{!<*29S795)K>plbCcI@VQJpm zmV(N03mO{q-_2pqiV%{{binjHBc~45Jqcq35L(wKv7oG+7t2gPy+bdleA_p8Yg;AN zU(kIIj9sg{{KtCV;p{#3Ax&o0Yo~acJ${N{D-agfkr`ildc02f<@vBiHC`84?)+C_ zcM}VqOTQICUsa6!j?F6b$&u&Ki4Q)COR9=EU13zWUsC;J>hp7jw{F7h+ngj)wggm9?&m;Zy-627Kf{U7 zfvi$CE`{Wl@~>|`g?R`iKr)iT4#akBYFmd(<*m>j_$^9bJ9zg8zc!yR?wI^LBd`jo z!Y)cR9Sif4adN2_K7YQjjhzGtrZRJZ=dQ%JdYMW+Y_m&1pbBTv-B7K8?w}Hn#RINE z;PMz_p%H0d=k+K2d_UTHb29LB0{RQ4;_(x?=Su8oH>!7baYPW2d$p5Eh(D%CO*EwK zDvwyWVBh@f*5SStVqzSyXvI#W=bxT^C>B>a;F%%C`j*nTwidH6y2DC+iU>2x2b-0M zL}et8NiT9!$)`1d zOxw755Q^`jnup*A7|%!8Y|F~}7l0?N(K3NwNcUGoZx8(nd@OF!v0iE}a&_{T6!(?e zAi?(~o0GwJQj6;>h%8Doibsp~;_?|XR@Q!Re-58e#My0^>}fC731<;ldu?#WP?0B9};yauv(H!$rBNRwYIKkz@H7oiKsoIllxzX zxEG?gVwkpSHzn@6mP);yLQ2O>RU+cClcxi`O7QYxsNK|kIc+vf%HQ#L%Uh|UR=d%D zhPtZ~xxK?!xb4AysW+T`ZJ3zC3#Qz>$@6Cpr!YCJty3G6FqZ2#G`4y-WNMb8e4}Rk zRyRIBtonB+eSoI93hh}0XAREb_6L1TFO&Vgm)2I(4(q*#&7>`4_Rjf6js9vIHw|m| zkVlgEGs%df?_MOwTW&BqI}g&&1`K6G)f|$R#=`jro=O#hj9S@2DA;N>hb}2ZH#3ii z`$L&d%fN(UDY=;n>$BF&h6sY*KZ0_RDO`(J=)#RO1F^hEdHsCt3ce{z8ym3!(PG+I z@W3!Ylg|mKXU-yfE-SwBPjiSsY7fby2!Ujm{mJM;kvLP~sCg5U!S(3@7X9)2FjjCK zYmAq5gKT1^Vn=T*(F}0OaeekK`NC(2i{1I$;Kyf!z#sf&Xw;XT!Qx97D^3=(hZ`J2 zV+|R}qJGB`e?2Nt*bPiX0|eYjv33+NOcWo(zxkNfCh<&^bU~0(tjx3)rXlvCjfn!{ zPMhr6V7cnwXT@SV@>WILh441NK)aU3`L$bXk7}9GM*5yluN`utFum=n*ZIb7gaulH zcMy^{-SNC}fnMFbu9m+x+A;dWMe*#a3z+wVnM_8F#rc3+T0qqb^y7UHw`^tlr0lj_C< z*^(?rI?rtXhA5D55bQ#QZqS|R1_5PxsHMd**#I@Bp%D$^5PZgOX-RMyV@9X^x}@!> zb6D1H4h6N<(Te#Y93S=`<^6xe{J)4#FUx`_u#Q&~woC2HF z4U!v*5c5jucNpChY$*Lf{*My?iv_JW4>85BZ)LqIYKwb&XZNLK8)7VsEP58Ny{vGR znmO@e!bf^is&~23aZh{J3&E>r+aZ0*TFa7vAmK+);NWArhA<&^-r6& zZJ>0`#Fwph-HAB0sV$~sK2Y2mB$dq28aj<&?&i;VUMtY*kvZ*WkW$6HQ_VMvl2QlL z;36wXYIx?U5FEE_G$ITD_5O$IS?JWrXVH7{BCO3zv7?dl&Uc%e@~u(bS1R^d0Aj5jBC`|WAxR-TXt@5%|Ml1ov;9`&?747I5WCPap^uKjulm>-B3 z82CPYr}$?Q{5k9vp;EC(-0~H8iwB#uc1QB2lD{VOl|GaIdSY`QF3kVFK+X0y2n%IT zTR|6@LqoIjtF!rp3${q?pYq+{mOKxPK7H)Bnsd#!Mnn|}w(P?#CF>-3wl;^lw@p@blLYoG68E3u!TXJvnc^ zG&MGo4~t4%iYbsY)hd3;%nf~@{cg06=%Hns_LOz!Y=StqCjDoN z5KPYo1*NcxGhrstge_i&91cw`HZ0lpZA5;Vj?PsqSx6kTUK}IG?FhXU%|nqq0ZZXy zkQ670$M^K6P!%S{(0SOzN5mIxP$sv5jKb&(ja);;^o`KLNcEPQFxIjT8dLo zwa8OM6m%1x=_H1i>pHNpZ<;hYd*_yp*dUl$ zj1dEc3u?Y{PD;bK?2GH8!o;Zg3F$rHK|#N(Xs?bN%#U8ManUFTG@9bCf!1Q8jEKu| zI&l1>zrKy&4vbsZ%DXtpRyz~TL6L-lr6@G7=4&owR}aDL`+``kBwA?<{eupU+Z@R1 z&_l!zUlyrub0>w95tQQ+wFOfKB(}=W{uopdjj)k$P(2*lfxOkmzbKl2L4wT#F2+&T zFY2u7tmC=cp<`HCJ{x%cRc~ST&dY5xvLiSv`vdpOtr?&iFkEl3pMQ68l(YF1hee+> z(!7rS(x*%D@Zhc?s9h6})k^T2@>eW)CvcUt)ACAJzBJ%whc+ycxL1F%-) z29_ewWLg_#gv$mK3HO84^`(kDrT@{XXH@{YF6f?IjLUa@d*P0kTkmK;qZJ))U%dPa z5}HvegLFRJN$}>fJQIHpkj!M*hpf5{X)|zE?f{+j`t@Iv6Z(;_mc0}Hn{<^-|-8fz=S{rQXQ7mCr%nOvui>Tbio87XY zmc6>r$TE=Rac~m#;r;iD-nW3CE8bJopzWf>54@=drLosp#n)>fTlr72KYuKJ!WZ|V z&M+LE7Yf1G&c7?12Xf=X8uQ3BI7xTu09Io7SV-(qqSQU0u#YBD&4FK*vQ(s}^p6iD z`o(%waenLnPBZ@D1^%%q~GmAs{e3iKOVXb%282g37@2pDxu;t|>@KHS_cL|zv-achJ%YMkKE-)n^e6u`t0;Lsx7io>-paDPs$?_mPOS#h%?oEwY845=$nZg}5{~zlS`KqOL&?s`%`(P_i`l;6+!A>Fq1uOp?mK)QlgW zTj!o5Fx!|7j@L%akF%f2KQO;Ey4%cSx>qf?Y`;poVr!#V=c03s)9mnYExcYi+J0Pc zjG8xb&y_jH9FwW}1% zMOe~J^jPk`B!6lSWL_msBK1PH0ddO*BHw(XCDq>>)vFcoDr8>Rz z*NHToIVgHLh=n!Ei;%oZZ@EcuU9q9Il&16Ohlc2620r`etQO3N?Xx%Syb zf9!7{R};+d0PjusJ~RB$RK{2zY}htcX+=28AK7-G*7dw_qes32MfNEnE9jGr{m( zE#DQr4_ZX}{0=IoC{}%$$^L~ln9=n|f0xG-mru$sGn>Q+mLacq+d1sZ*=CkKA=IM> rsbu0b|IZQV|D1*Xe=FR;e{2ssUOfr48f?a%;R3YO^i&&_?PC8I&&7_u literal 0 HcmV?d00001 diff --git a/tests/TestFiles/Skia/Shapes/Polyline/Polyline_FillRule_EvenOdd.expected.png b/tests/TestFiles/Skia/Shapes/Polyline/Polyline_FillRule_EvenOdd.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..4b1348f5b636d9cdc08034acdfae391d90eea519 GIT binary patch literal 7579 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 literal 0 HcmV?d00001 diff --git a/tests/TestFiles/Skia/Shapes/Polyline/Polyline_FillRule_NoFill.expected.png b/tests/TestFiles/Skia/Shapes/Polyline/Polyline_FillRule_NoFill.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..5837133ef4b0d12c9a11cab5ac6c15f46ceaa1c8 GIT binary patch literal 4934 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 SufU5j5hr_RyLwyCxc>sKQ(aO3 literal 0 HcmV?d00001 diff --git a/tests/TestFiles/Skia/Shapes/Polyline/Polyline_FillRule_NonZero.expected.png b/tests/TestFiles/Skia/Shapes/Polyline/Polyline_FillRule_NonZero.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..b697dc8035503cedd337e74b3a9909a32f1882ee GIT binary patch literal 7591 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 M19Sc7dYIV%1;;-issI20 literal 0 HcmV?d00001