From f158c3e3993c913ba423ba3253ac2acd94abf2ad Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Wed, 17 Dec 2014 18:40:31 +0100 Subject: [PATCH] Fixed scaling for Paths. Will no doubt need revisiting as mentioned in the comments in Shape.MeasureOverride. --- Perspex.Controls/Shapes/Shape.cs | 36 +++++++++++------- .../Path_100px_Triangle_Centered.expected.png | Bin 1242 -> 1213 bytes .../Path_Expander_With_Border.expected.png | Bin 0 -> 1311 bytes .../Shapes/PathTests.cs | 28 ++++++++++++++ .../Perspex.Direct2D1/Media/GeometryImpl.cs | 12 +++++- .../Media/StreamGeometryImpl.cs | 5 --- 6 files changed, 62 insertions(+), 19 deletions(-) create mode 100644 TestFiles/Direct2D1/Shapes/Path/Path_Expander_With_Border.expected.png diff --git a/Perspex.Controls/Shapes/Shape.cs b/Perspex.Controls/Shapes/Shape.cs index 271e575682..7a03cafcba 100644 --- a/Perspex.Controls/Shapes/Shape.cs +++ b/Perspex.Controls/Shapes/Shape.cs @@ -26,6 +26,8 @@ namespace Perspex.Controls.Shapes private Matrix transform = Matrix.Identity; + private Geometry renderedGeometry; + public abstract Geometry DefiningGeometry { get; @@ -41,15 +43,17 @@ namespace Perspex.Controls.Shapes { get { - var result = this.DefiningGeometry; - - if (result != null) + if (this.renderedGeometry == null) { - result = result.Clone(); - result.Transform = new MatrixTransform(this.transform); + if (this.DefiningGeometry != null) + { + this.renderedGeometry = this.DefiningGeometry.Clone(); + this.renderedGeometry.Transform = new MatrixTransform(this.transform); + } + } - return result; + return this.renderedGeometry; } } @@ -83,7 +87,9 @@ namespace Perspex.Controls.Shapes protected override Size MeasureOverride(Size availableSize) { - Rect shapeBounds = this.DefiningGeometry.GetRenderBounds(this.StrokeThickness); + // This should probably use GetRenderBounds(strokeThickness) but then the calculations + // will multiply the stroke thickness as well, which isn't correct. + Rect shapeBounds = this.DefiningGeometry.Bounds; Size shapeSize = new Size(shapeBounds.Right, shapeBounds.Bottom); Matrix translate = Matrix.Identity; double width = this.Width; @@ -111,12 +117,12 @@ namespace Perspex.Controls.Shapes if (shapeBounds.Width > 0) { - sx = desiredX / shapeBounds.Width; + sx = desiredX / shapeSize.Width; } if (shapeBounds.Height > 0) { - sy = desiredY / shapeBounds.Height; + sy = desiredY / shapeSize.Height; } if (double.IsInfinity(availableSize.Width)) @@ -154,11 +160,15 @@ namespace Perspex.Controls.Shapes break; } - this.transform = translate * Matrix.Scaling(sx, sy); + var t = translate * Matrix.Scaling(sx, sy); + + if (this.transform != t) + { + this.transform = t; + this.renderedGeometry = null; + } - double finalX = (width > 0) ? width : shapeSize.Width * sx; - double finalY = (height > 0) ? height : shapeSize.Width * sy; - return new Size(finalX, finalY); + return new Size(shapeSize.Width * sx, shapeSize.Height * sy); } } } diff --git a/TestFiles/Direct2D1/Shapes/Path/Path_100px_Triangle_Centered.expected.png b/TestFiles/Direct2D1/Shapes/Path/Path_100px_Triangle_Centered.expected.png index 6db62e30c3c2716ba3149be4d96800f21efca49a..dab965f9885e0922ffae590303905b56125a1bb1 100644 GIT binary patch literal 1213 zcmajei%(N`6bJBPSz}m%vPjnQC=Jw26nROUFq+*0KWVKiSn8$)6h{$(jclzw&f=pvSfqU`*#KfosKxu-ej^S$?% z+>_bTOn<)+KN^kZFBWCUpxW?vJp+EP?=!bU@lne%(`e>D!k$3mTP*xkNTYQ(yt{hn z9o&jDg!0M*^OJ(|(9hX*cTaZ6zMr5XOY-`X@+{7Ed6g0O<#%2P`{gAvey+%1Oya8} zYbfO&=jznOwko?%tSDfTb>jU%A^`BWeu&^>)~}P>|B`Hf_-NU-y*icqu)90#7wf-| zE9JhozG44%#oG6Ad)Cm%?R}>Ulix(>^tYo569x~hR#j9iEqQP13AQB2yS!qpw_GeQ zmn+j(^?M%-J*%5}wPrTgJ-B}>yyp1A;pN9KN%oC1&!&%mr(ha8yIJ)Mn(8+m%Q0)~ z$jHp%qc4_cU%#qc>(x7pcol-Hnc0o=@zgHqc$CTZEn6h`&=VwAhBA${YVZ2ZJ^l>Y z&?M;_eAQ0)os%_mM0zYTeC00&*vw zVyY$p;V_yqCjc3?6Yp)o$O=b9B0%_Ybg@YZh`Wea5{!{*CciNRkfsK$F$W{h<0;=# zjBpuEJI4VL+lkNarNNG|nCJPb6Gr|_q=J8z16#terJTdhbCjvPv=uLi)B6ON{dVH;y>wu@ig^q3n3+hRIE$F^ux+Up%*-;CodRHNDn{aTEIwQg zy{*6wOwVcU?p_ZtZFb_oU3@pA#k?D3nE5+_+NQwU8m4>TGCZU*g{~2vf~CX@+JUZN zyfjEikMzOpy3Na2+|Y8*yLc zvAjFd(bI}#mbdbPe#&!`HX^ed`BTNMCeH4SRo=eLGR2(1}^ljT%>?>r6UI!Al*HdgA}pQ zJ0-{v2E9vy6kB!V21hzFgzCtav2>(>{0&YL86dyKMIr^{%N;6YfPCke3Mn98?kq(H z$alI*kpl9+Bu)h}XPKi#-53oZ0{gBR|9g{r&-vwdzH`1WUvjG> z!b7)NJ6KaFlx+fjunTS8wxL@-7@J z1i@UcAXQ?>6C#MzzOyUnEcU2EMK7oQDsqlti1ND;}=w64>!c9SMaHPs<^t; zYPa9aN>Tyad72%aI32BXeU!J9<2#r+vlBAj;(1&;@zdY_mye9)%O6av*2^yY);Pbc zG-P}^x~9s}Ox-EF-R70h5&62`aY&_7ec~#3c4{r{ufzJMvm+zZI$euOJ6!m~9U<3Y zFn6G^|ND*E$$rDFrY3{VY&Kk5%__XLdT9VvwE7Y+$LxZtCG+!@>N7J%Di@1Ae;3{S zo+vpHRW$6gSh=g2G~r+$PG!W=kV^4ZiGRSVmspI8440l9mje&8eD$% zAQi3A)(yO6OHyy`2zKhA_ z4f_za=dVMM8fBenBZEAVdx{WnIh%yp>$~748)cP$O?Fu+OHk&KHxg_|{5~MY6l_Oq z*d~c0$#Kl5yBmBLyotu~SZH&_PK%~>gH0itTBRzAl@yq+8d9c^F|#f(RI;0PFTypRobn&kSQAr3Q@bh+zAY{f~Je^KL34Qxl7 zPg|&K20NoKGHE7V!hHx06N-)ghyW)?dWy2OoSw_JwVZ6J zDO4`WltYO7!tIQ$t;|!M+Etucg*#n!$;=I~wfG<8&6sjAQ&wfo6LSV;@~Q*O0&J+s z`PkNSF@*QZu?jz+FW?Q>SK;@^3V65!p#B7Jz^)2UXn$6-=xuBHHlmjyEyhgp&|b!z z1W-`Vkm7)c0E+$ZDja$;GJm@yB7R+5j(cTUTU{T?^YbAVdCf1J z<7B=Ky`!AssZTRvJdl;Z#2`({v0dx?k(Htn`dj=4D3o8iB+GQ`tY(9_N%MlN5b(l- Jd-fhJ`ww2k2%G=_ diff --git a/TestFiles/Direct2D1/Shapes/Path/Path_Expander_With_Border.expected.png b/TestFiles/Direct2D1/Shapes/Path/Path_Expander_With_Border.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..9c72e69ea923ef1c78ed6ac289eac3c92fc1a627 GIT binary patch literal 1311 zcmWlZe@qi+9LDQQl{=((*G@OSW4qHr*7axZrq43~~h94#LY z#||&&F4?vA;V%oM-leb972T}*gzFR@m@?^P+#pA(D;vu6?LImqFuG$= z%d?%mX9l>O$v>mri+yZ~C0)(|&eBQG0iK^SU#EE?FfC-$+2{oR7Hhpi z-QW9>?(aRW`^%iN$KG!bj3%4^pxX27{o@1IoaSaCGFz##%YSqG@et*$M&A^$BI&m( ztW%D1jWWJZduOAQAQJwm3Tu=9j8&%fxR);(sRBfp87;m-7HKIBWRi5G#QsiMVf>HDUpJ10i3`Ptn zTF=*{$S;F_4~ib+Yd{tKu_$_qp9`w!&qbn}oksJFy?Y;CPkT2a(ZfzA*%YP3F1K^!12hh0h3 zKH{nac$bg;im3gK`=C?rx z9=Cm0{_N3{FSenxp<-rW5hu35UH130hWe`MgLqZyW(Mfkp>yUQo%SWbrqty+9i=*F zuF+}V2yAt2(dpc&Gi9$%j)6DK5waarv!yK+^)C?0lBqbM%tnQU1CT&lBI?LvED(zT zvFr)Y0+DWmta6!&5TF17J_}#k52?06s(H+0f=v-1>RsU?1@iYm{<+LFijUX2f_TIw znMie;*42bZoKhm87HC}}9&t#Cr22-|brO%*q!>b-q-6$ik4uUn)h$|P6YgHz8UrHKNPrr>2rEr^tHlG|@-ajtPJp_79ll`+Tw@c~Qtgwpd!|6P zIrdeOV|wLi9`na@OnxYx5;F46fw*}!qGRj*1jnRJ0q4bK5fI-k z0%s`)PWUh=p|JD{4!cXs(euoqyBVXy8A$_44_c2DJb4i<`gUIYe=#T8liIJmC>(}Q O&fs0*<1Xa9v;TjC((*R| literal 0 HcmV?d00001 diff --git a/Windows/Perspex.Direct2D1.RenderTests/Shapes/PathTests.cs b/Windows/Perspex.Direct2D1.RenderTests/Shapes/PathTests.cs index 0b1b69694e..f72b71195f 100644 --- a/Windows/Perspex.Direct2D1.RenderTests/Shapes/PathTests.cs +++ b/Windows/Perspex.Direct2D1.RenderTests/Shapes/PathTests.cs @@ -65,5 +65,33 @@ namespace Perspex.Direct2D1.RenderTests.Shapes this.RenderToFile(target); this.CompareImages(); } + + [TestMethod] + public void Path_Expander_With_Border() + { + Decorator target = new Decorator + { + Width = 200, + Height = 200, + Content = new Border + { + BorderBrush = Brushes.Red, + BorderThickness = 1, + HorizontalAlignment = HorizontalAlignment.Center, + VerticalAlignment = VerticalAlignment.Center, + Content = new Path + { + Fill = Brushes.Black, + Stroke = Brushes.Black, + StrokeThickness = 1, + Stretch = Stretch.Uniform, + Data = StreamGeometry.Parse("M 0 2 L 4 6 L 0 10 Z"), + } + } + }; + + this.RenderToFile(target); + this.CompareImages(); + } } } diff --git a/Windows/Perspex.Direct2D1/Media/GeometryImpl.cs b/Windows/Perspex.Direct2D1/Media/GeometryImpl.cs index 510b618533..4fd2584e67 100644 --- a/Windows/Perspex.Direct2D1/Media/GeometryImpl.cs +++ b/Windows/Perspex.Direct2D1/Media/GeometryImpl.cs @@ -60,6 +60,16 @@ namespace Perspex.Direct2D1.Media } } - public abstract Rect GetRenderBounds(double strokeThickness); + public Rect GetRenderBounds(double strokeThickness) + { + if (this.transformed != null) + { + return this.transformed.GetWidenedBounds((float)strokeThickness).ToPerspex(); + } + else + { + return this.DefiningGeometry.GetWidenedBounds((float)strokeThickness).ToPerspex(); + } + } } } diff --git a/Windows/Perspex.Direct2D1/Media/StreamGeometryImpl.cs b/Windows/Perspex.Direct2D1/Media/StreamGeometryImpl.cs index 41f0a91a68..2567f937c7 100644 --- a/Windows/Perspex.Direct2D1/Media/StreamGeometryImpl.cs +++ b/Windows/Perspex.Direct2D1/Media/StreamGeometryImpl.cs @@ -44,11 +44,6 @@ namespace Perspex.Direct2D1.Media return new StreamGeometryImpl(result); } - public override Rect GetRenderBounds(double strokeThickness) - { - return this.path.GetWidenedBounds((float)strokeThickness).ToPerspex(); - } - public IStreamGeometryContextImpl Open() { return new StreamGeometryContextImpl(this.path.Open());