From ec010a1c4d3f16023fe1f636a99bc1b5bff38ab9 Mon Sep 17 00:00:00 2001 From: Steven Kirk Date: Fri, 4 Sep 2015 10:25:20 +0200 Subject: [PATCH] Implemented VisualBrush.SourceRect. --- src/Perspex.SceneGraph/Point.cs | 10 +++ .../Rendering/RendererBase.cs | 8 +- .../Media/VisualBrushImpl.cs | 30 ++++--- .../Media/VisualBrushTests.cs | 76 ++++++++---------- ...sualBrush_SourceRect_Absolute.expected.png | Bin 0 -> 3321 bytes 5 files changed, 67 insertions(+), 57 deletions(-) create mode 100644 tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png diff --git a/src/Perspex.SceneGraph/Point.cs b/src/Perspex.SceneGraph/Point.cs index 917ebc749a..62daee8870 100644 --- a/src/Perspex.SceneGraph/Point.cs +++ b/src/Perspex.SceneGraph/Point.cs @@ -59,6 +59,16 @@ namespace Perspex return new Vector(p.x, p.y); } + /// + /// Negates a point. + /// + /// The point. + /// The negated point. + public static Point operator -(Point a) + { + return new Point(-a.x, -a.y); + } + /// /// Checks for equality between two s. /// diff --git a/src/Perspex.SceneGraph/Rendering/RendererBase.cs b/src/Perspex.SceneGraph/Rendering/RendererBase.cs index 43e193dfd3..2dce69e3d0 100644 --- a/src/Perspex.SceneGraph/Rendering/RendererBase.cs +++ b/src/Perspex.SceneGraph/Rendering/RendererBase.cs @@ -34,7 +34,7 @@ namespace Perspex.Rendering /// An optional platform-specific handle. public virtual void Render(IVisual visual, IPlatformHandle handle) { - this.Render(visual, handle, Matrix.Identity, Matrix.Identity); + this.Render(visual, handle, Matrix.Identity); } /// @@ -42,14 +42,12 @@ namespace Perspex.Rendering /// /// The visual to render. /// An optional platform-specific handle. - /// The translation. /// The transform. - public virtual void Render(IVisual visual, IPlatformHandle handle, Matrix translation, Matrix transform) + public virtual void Render(IVisual visual, IPlatformHandle handle, Matrix transform) { using (var context = this.CreateDrawingContext(handle)) { - //context.PushTransform(translation * transform); - this.Render(visual, context, translation, transform); + this.Render(visual, context, Matrix.Identity, transform); } ++this.RenderCount; diff --git a/src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs b/src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs index 2d98e367f8..a17106b6b5 100644 --- a/src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs +++ b/src/Windows/Perspex.Direct2D1/Media/VisualBrushImpl.cs @@ -28,10 +28,10 @@ namespace Perspex.Direct2D1.Media layoutable.Arrange(new Rect(layoutable.DesiredSize)); } - var sourceSize = layoutable.Bounds.Size; + var sourceRect = brush.SourceRect.ToPixels(layoutable.Bounds.Size); var destinationRect = brush.DestinationRect.ToPixels(destinationSize); - var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceSize); - var translate = CalculateTranslate(brush, destinationRect.Size, sourceSize * scale); + var scale = brush.Stretch.CalculateScaling(destinationRect.Size, sourceRect.Size); + var translate = CalculateTranslate(brush, sourceRect, destinationRect, scale); using (var brt = new BitmapRenderTarget( target, @@ -39,33 +39,41 @@ namespace Perspex.Direct2D1.Media destinationRect.Size.ToSharpDX())) { var renderer = new Renderer(brt); - renderer.Render(visual, null, Matrix.CreateTranslation(translate), Matrix.CreateScale(scale)); + var transform = Matrix.CreateTranslation(-sourceRect.Position) * + Matrix.CreateScale(scale) * + Matrix.CreateTranslation(translate); + renderer.Render(visual, null, transform); this.PlatformBrush = new BitmapBrush(brt, brt.Bitmap); } } - private static Vector CalculateTranslate(VisualBrush brush, Size destinationSize, Size sourceSize) + private static Vector CalculateTranslate( + VisualBrush brush, + Rect sourceRect, + Rect destinationRect, + Vector scale) { - double x = 0; - double y = 0; + var x = 0.0; + var y = 0.0; + var size = sourceRect.Size * scale; switch (brush.AlignmentX) { case AlignmentX.Center: - x = (destinationSize.Width - sourceSize.Width) / 2; + x += (destinationRect.Width - size.Width) / 2; break; case AlignmentX.Right: - x = destinationSize.Width - sourceSize.Width; + x += destinationRect.Width - size.Width; break; } switch (brush.AlignmentY) { case AlignmentY.Center: - y = (destinationSize.Height - sourceSize.Height) / 2; + y += (destinationRect.Height - size.Height) / 2; break; case AlignmentY.Bottom: - y = destinationSize.Height - sourceSize.Height; + y += destinationRect.Height - size.Height; break; } diff --git a/tests/Perspex.RenderTests/Media/VisualBrushTests.cs b/tests/Perspex.RenderTests/Media/VisualBrushTests.cs index 9b7fb7fbdd..fc74160e74 100644 --- a/tests/Perspex.RenderTests/Media/VisualBrushTests.cs +++ b/tests/Perspex.RenderTests/Media/VisualBrushTests.cs @@ -247,47 +247,41 @@ namespace Perspex.Direct2D1.RenderTests.Media this.CompareImages(); } - ////[Fact] - ////public void VisualBrush_Line_Fill() - ////{ - //// Decorator target = new Decorator - //// { - //// Padding = new Thickness(8), - //// Width = 200, - //// Height = 200, - //// Child = new Line - //// { - //// X1 = 16, - //// Y1 = 16, - //// X2 = 184, - //// Y2 = 184, - //// StrokeThickness = 40, - //// StrokeStartLineCap = "Triangle", - //// StrokeEndLineCap = "Triangle", - //// Fill = new VisualBrush - //// { - //// Visual = new Border - //// { - //// Width = 92, - //// Height = 92, - //// Background = Brushes.Red, - //// BorderBrush = Brushes.Black, - //// BorderThickness = 2, - //// Child = new TextBlock - //// { - //// Text = "Perspex", - //// FontSize = 12, - //// FontFamily = "Arial", - //// HorizontalAlignment = HorizontalAlignment.Center, - //// VerticalAlignment = VerticalAlignment.Center, - //// } - //// } - //// } - //// } - //// }; + [Fact] + public void VisualBrush_SourceRect_Absolute() + { + Decorator target = new Decorator + { + Padding = new Thickness(8), + Width = 200, + Height = 200, + Child = new Rectangle + { + Fill = new VisualBrush + { + SourceRect = new RelativeRect(40, 40, 100, 100, OriginUnit.Pixels), + Visual = new Border + { + Width = 180, + Height = 180, + Background = Brushes.Red, + BorderBrush = Brushes.Black, + BorderThickness = 2, + Child = new Ellipse + { + Width = 100, + Height = 100, + Fill = Brushes.Yellow, + VerticalAlignment = VerticalAlignment.Center, + HorizontalAlignment = HorizontalAlignment.Center, + } + } + } + } + }; - //// this.RenderToFile(target); - //// this.CompareImages(); - ////} + this.RenderToFile(target); + this.CompareImages(); + } } } diff --git a/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png b/tests/TestFiles/Direct2D1/Media/VisualBrush/VisualBrush_SourceRect_Absolute.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..e1fcdbc1a6697a32ce517e6457612c1ecf1bb68f GIT binary patch literal 3321 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∓YWw7mj5JWIy=?S7D384 zNCW1$UAjl|x~_g;jK?H4H5C$>ZIG>;CEX$2E7>Sv5G4*u?AItPWwk-h1e>w;OBlt) z{Ps|MACjJwM!ckEPHd16Xg2PXm>y;s%aUOO(-G;gG~+&vsjxx1K>Br~gjpDuvgMa0 zAXFY=ZR#RD zV*4ukNMiPh^l71KQx|NIIict$9m6o_9I5HOU>+s`Xka3q8$