From 60aad5ef0612308bb7ea71f2e899138b29aff74e Mon Sep 17 00:00:00 2001 From: Jumar Macato <16554748+jmacato@users.noreply.github.com> Date: Thu, 17 Jun 2021 16:07:26 +0800 Subject: [PATCH] Merge pull request #6066 from AvaloniaUI/fixes/5947-gradient-drawingcontext Fixed gradient brush target rectangles. --- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 47 +++++++++--------- src/Skia/Avalonia.Skia/FormattedTextImpl.cs | 4 +- .../Media/AvaloniaTextRenderer.cs | 4 +- .../Media/DrawingContextImpl.cs | 32 ++++++------ .../Media/LinearGradientBrushImpl.cs | 7 +-- .../Media/RadialGradientBrushImpl.cs | 11 ++-- .../Media/ConicGradientBrushTests.cs | 40 +++++++++++++++ .../Media/LinearGradientBrushTests.cs | 36 ++++++++++++++ .../Media/RadialGradientBrushTests.cs | 34 +++++++++++++ ...cGradientBrush_DrawingContext.expected.png | Bin 0 -> 631 bytes ...rGradientBrush_DrawingContext.expected.png | Bin 0 -> 2997 bytes ...lGradientBrush_DrawingContext.expected.png | Bin 0 -> 9127 bytes ...cGradientBrush_DrawingContext.expected.png | Bin 0 -> 10037 bytes ...rGradientBrush_DrawingContext.expected.png | Bin 0 -> 1908 bytes ...lGradientBrush_DrawingContext.expected.png | Bin 0 -> 5904 bytes 15 files changed, 163 insertions(+), 52 deletions(-) create mode 100644 tests/TestFiles/Direct2D1/Media/ConicGradientBrush/ConicGradientBrush_DrawingContext.expected.png create mode 100644 tests/TestFiles/Direct2D1/Media/LinearGradientBrush/LinearGradientBrush_DrawingContext.expected.png create mode 100644 tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_DrawingContext.expected.png create mode 100644 tests/TestFiles/Skia/Media/ConicGradientBrush/ConicGradientBrush_DrawingContext.expected.png create mode 100644 tests/TestFiles/Skia/Media/LinearGradientBrush/LinearGradientBrush_DrawingContext.expected.png create mode 100644 tests/TestFiles/Skia/Media/RadialGradientBrush/RadialGradientBrush_DrawingContext.expected.png diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 2c5c2acd52..d8bd0607d1 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -164,7 +164,7 @@ namespace Avalonia.Skia /// public void DrawLine(IPen pen, Point p1, Point p2) { - using (var paint = CreatePaint(_strokePaint, pen, new Size(Math.Abs(p2.X - p1.X), Math.Abs(p2.Y - p1.Y)))) + using (var paint = CreatePaint(_strokePaint, pen, new Rect(p1, p2).Normalize())) { if (paint.Paint is object) { @@ -177,10 +177,10 @@ namespace Avalonia.Skia public void DrawGeometry(IBrush brush, IPen pen, IGeometryImpl geometry) { var impl = (GeometryImpl) geometry; - var size = geometry.Bounds.Size; + var rect = geometry.Bounds; - using (var fill = brush != null ? CreatePaint(_fillPaint, brush, size) : default(PaintWrapper)) - using (var stroke = pen?.Brush != null ? CreatePaint(_strokePaint, pen, size) : default(PaintWrapper)) + using (var fill = brush != null ? CreatePaint(_fillPaint, brush, rect) : default(PaintWrapper)) + using (var stroke = pen?.Brush != null ? CreatePaint(_strokePaint, pen, rect) : default(PaintWrapper)) { if (fill.Paint != null) { @@ -354,7 +354,7 @@ namespace Avalonia.Skia if (brush != null) { - using (var paint = CreatePaint(_fillPaint, brush, rect.Rect.Size)) + using (var paint = CreatePaint(_fillPaint, brush, rect.Rect)) { if (isRounded) { @@ -397,7 +397,7 @@ namespace Avalonia.Skia if (pen?.Brush != null) { - using (var paint = CreatePaint(_strokePaint, pen, rect.Rect.Size)) + using (var paint = CreatePaint(_strokePaint, pen, rect.Rect)) { if (paint.Paint is object) { @@ -417,7 +417,7 @@ namespace Avalonia.Skia /// public void DrawText(IBrush foreground, Point origin, IFormattedTextImpl text) { - using (var paint = CreatePaint(_fillPaint, foreground, text.Bounds.Size)) + using (var paint = CreatePaint(_fillPaint, foreground, text.Bounds)) { var textImpl = (FormattedTextImpl) text; textImpl.Draw(this, Canvas, origin.ToSKPoint(), paint, _canTextUseLcdRendering); @@ -427,7 +427,7 @@ namespace Avalonia.Skia /// public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun) { - using (var paintWrapper = CreatePaint(_fillPaint, foreground, glyphRun.Size)) + using (var paintWrapper = CreatePaint(_fillPaint, foreground, new Rect(glyphRun.Size))) { var glyphRunImpl = (GlyphRunImpl)glyphRun.GlyphRunImpl; @@ -537,7 +537,7 @@ namespace Avalonia.Skia var paint = new SKPaint(); Canvas.SaveLayer(paint); - _maskStack.Push(CreatePaint(paint, mask, bounds.Size, true)); + _maskStack.Push(CreatePaint(paint, mask, bounds, true)); } /// @@ -593,18 +593,19 @@ namespace Avalonia.Skia /// Paint wrapper. /// Target size. /// Gradient brush. - private void ConfigureGradientBrush(ref PaintWrapper paintWrapper, Size targetSize, IGradientBrush gradientBrush) + private void ConfigureGradientBrush(ref PaintWrapper paintWrapper, Rect targetRect, IGradientBrush gradientBrush) { var tileMode = gradientBrush.SpreadMethod.ToSKShaderTileMode(); var stopColors = gradientBrush.GradientStops.Select(s => s.Color.ToSKColor()).ToArray(); var stopOffsets = gradientBrush.GradientStops.Select(s => (float)s.Offset).ToArray(); + var position = targetRect.Position.ToSKPoint(); switch (gradientBrush) { case ILinearGradientBrush linearGradient: { - var start = linearGradient.StartPoint.ToPixels(targetSize).ToSKPoint(); - var end = linearGradient.EndPoint.ToPixels(targetSize).ToSKPoint(); + var start = position + linearGradient.StartPoint.ToPixels(targetRect.Size).ToSKPoint(); + var end = position + linearGradient.EndPoint.ToPixels(targetRect.Size).ToSKPoint(); // would be nice to cache these shaders possibly? using (var shader = @@ -617,10 +618,10 @@ namespace Avalonia.Skia } case IRadialGradientBrush radialGradient: { - var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint(); - var radius = (float)(radialGradient.Radius * targetSize.Width); + var center = position + radialGradient.Center.ToPixels(targetRect.Size).ToSKPoint(); + var radius = (float)(radialGradient.Radius * targetRect.Width); - var origin = radialGradient.GradientOrigin.ToPixels(targetSize).ToSKPoint(); + var origin = position + radialGradient.GradientOrigin.ToPixels(targetRect.Size).ToSKPoint(); if (origin.Equals(center)) { @@ -665,7 +666,7 @@ namespace Avalonia.Skia } case IConicGradientBrush conicGradient: { - var center = conicGradient.Center.ToPixels(targetSize).ToSKPoint(); + var center = position + conicGradient.Center.ToPixels(targetRect.Size).ToSKPoint(); // Skia's default is that angle 0 is from the right hand side of the center point // but we are matching CSS where the vertical point above the center is 0. @@ -867,10 +868,10 @@ namespace Avalonia.Skia /// /// The paint to wrap. /// Source brush. - /// Target size. + /// Target rect. /// Optional dispose of the supplied paint. /// Paint wrapper for given brush. - internal PaintWrapper CreatePaint(SKPaint paint, IBrush brush, Size targetSize, bool disposePaint = false) + internal PaintWrapper CreatePaint(SKPaint paint, IBrush brush, Rect targetRect, bool disposePaint = false) { var paintWrapper = new PaintWrapper(paint, disposePaint); @@ -889,7 +890,7 @@ namespace Avalonia.Skia if (brush is IGradientBrush gradient) { - ConfigureGradientBrush(ref paintWrapper, targetSize, gradient); + ConfigureGradientBrush(ref paintWrapper, targetRect, gradient); return paintWrapper; } @@ -909,7 +910,7 @@ namespace Avalonia.Skia if (tileBrush != null && tileBrushImage != null) { - ConfigureTileBrush(ref paintWrapper, targetSize, tileBrush, tileBrushImage); + ConfigureTileBrush(ref paintWrapper, targetRect.Size, tileBrush, tileBrushImage); } else { @@ -924,10 +925,10 @@ namespace Avalonia.Skia /// /// The paint to wrap. /// Source pen. - /// Target size. + /// Target rect. /// Optional dispose of the supplied paint. /// - private PaintWrapper CreatePaint(SKPaint paint, IPen pen, Size targetSize, bool disposePaint = false) + private PaintWrapper CreatePaint(SKPaint paint, IPen pen, Rect targetRect, bool disposePaint = false) { // In Skia 0 thickness means - use hairline rendering // and for us it means - there is nothing rendered. @@ -936,7 +937,7 @@ namespace Avalonia.Skia return default; } - var rv = CreatePaint(paint, pen.Brush, targetSize, disposePaint); + var rv = CreatePaint(paint, pen.Brush, targetRect, disposePaint); paint.IsStroke = true; paint.StrokeWidth = (float) pen.Thickness; diff --git a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs index 5f4980e461..3eca42faa9 100644 --- a/src/Skia/Avalonia.Skia/FormattedTextImpl.cs +++ b/src/Skia/Avalonia.Skia/FormattedTextImpl.cs @@ -278,9 +278,9 @@ namespace Avalonia.Skia if (fb != null) { - //TODO: figure out how to get the brush size + //TODO: figure out how to get the brush rect currentWrapper = context.CreatePaint(new SKPaint { IsAntialias = true }, fb, - new Size()); + default); } else { diff --git a/src/Windows/Avalonia.Direct2D1/Media/AvaloniaTextRenderer.cs b/src/Windows/Avalonia.Direct2D1/Media/AvaloniaTextRenderer.cs index 22c998df93..e4b2405290 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/AvaloniaTextRenderer.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/AvaloniaTextRenderer.cs @@ -34,10 +34,10 @@ namespace Avalonia.Direct2D1.Media { var wrapper = clientDrawingEffect as BrushWrapper; - // TODO: Work out how to get the size below rather than passing new Size(). + // TODO: Work out how to get the rect below rather than passing default. var brush = (wrapper == null) ? _foreground : - _context.CreateBrush(wrapper.Brush, new Size()).PlatformBrush; + _context.CreateBrush(wrapper.Brush, default).PlatformBrush; _renderTarget.DrawGlyphRun( new RawVector2 { X = baselineOriginX, Y = baselineOriginY }, diff --git a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs index af35934785..9336c9a7bb 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/DrawingContextImpl.cs @@ -192,7 +192,7 @@ namespace Avalonia.Direct2D1.Media { using (var d2dSource = ((BitmapImpl)source.Item).GetDirect2DBitmap(_deviceContext)) using (var sourceBrush = new BitmapBrush(_deviceContext, d2dSource.Value)) - using (var d2dOpacityMask = CreateBrush(opacityMask, opacityMaskRect.Size)) + using (var d2dOpacityMask = CreateBrush(opacityMask, opacityMaskRect)) using (var geometry = new SharpDX.Direct2D1.RectangleGeometry(Direct2D1Platform.Direct2D1Factory, destRect.ToDirect2D())) { if (d2dOpacityMask.PlatformBrush != null) @@ -217,9 +217,7 @@ namespace Avalonia.Direct2D1.Media { if (pen != null) { - var size = new Rect(p1, p2).Size; - - using (var d2dBrush = CreateBrush(pen.Brush, size)) + using (var d2dBrush = CreateBrush(pen.Brush, new Rect(p1, p2).Normalize())) using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext)) { if (d2dBrush.PlatformBrush != null) @@ -245,7 +243,7 @@ namespace Avalonia.Direct2D1.Media { if (brush != null) { - using (var d2dBrush = CreateBrush(brush, geometry.Bounds.Size)) + using (var d2dBrush = CreateBrush(brush, geometry.Bounds)) { if (d2dBrush.PlatformBrush != null) { @@ -257,7 +255,7 @@ namespace Avalonia.Direct2D1.Media if (pen != null) { - using (var d2dBrush = CreateBrush(pen.Brush, geometry.GetRenderBounds(pen).Size)) + using (var d2dBrush = CreateBrush(pen.Brush, geometry.GetRenderBounds(pen))) using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext)) { if (d2dBrush.PlatformBrush != null) @@ -282,7 +280,7 @@ namespace Avalonia.Direct2D1.Media if (brush != null) { - using (var b = CreateBrush(brush, rect.Size)) + using (var b = CreateBrush(brush, rect)) { if (b.PlatformBrush != null) { @@ -311,7 +309,7 @@ namespace Avalonia.Direct2D1.Media if (pen?.Brush != null) { - using (var wrapper = CreateBrush(pen.Brush, rect.Size)) + using (var wrapper = CreateBrush(pen.Brush, rect)) using (var d2dStroke = pen.ToDirect2DStrokeStyle(_deviceContext)) { if (wrapper.PlatformBrush != null) @@ -349,7 +347,7 @@ namespace Avalonia.Direct2D1.Media { var impl = (FormattedTextImpl)text; - using (var brush = CreateBrush(foreground, impl.Bounds.Size)) + using (var brush = CreateBrush(foreground, impl.Bounds)) using (var renderer = new AvaloniaTextRenderer(this, _deviceContext, brush.PlatformBrush)) { if (brush.PlatformBrush != null) @@ -367,7 +365,7 @@ namespace Avalonia.Direct2D1.Media /// The glyph run. public void DrawGlyphRun(IBrush foreground, GlyphRun glyphRun) { - using (var brush = CreateBrush(foreground, glyphRun.Size)) + using (var brush = CreateBrush(foreground, new Rect(glyphRun.Size))) { var glyphRunImpl = (GlyphRunImpl)glyphRun.GlyphRunImpl; @@ -458,9 +456,9 @@ namespace Avalonia.Direct2D1.Media /// Creates a Direct2D brush wrapper for a Avalonia brush. /// /// The avalonia brush. - /// The size of the brush's target area. + /// The brush's target area. /// The Direct2D brush wrapper. - public BrushImpl CreateBrush(IBrush brush, Size destinationSize) + public BrushImpl CreateBrush(IBrush brush, Rect destinationRect) { var solidColorBrush = brush as ISolidColorBrush; var linearGradientBrush = brush as ILinearGradientBrush; @@ -475,11 +473,11 @@ namespace Avalonia.Direct2D1.Media } else if (linearGradientBrush != null) { - return new LinearGradientBrushImpl(linearGradientBrush, _deviceContext, destinationSize); + return new LinearGradientBrushImpl(linearGradientBrush, _deviceContext, destinationRect); } else if (radialGradientBrush != null) { - return new RadialGradientBrushImpl(radialGradientBrush, _deviceContext, destinationSize); + return new RadialGradientBrushImpl(radialGradientBrush, _deviceContext, destinationRect); } else if (conicGradientBrush != null) { @@ -492,7 +490,7 @@ namespace Avalonia.Direct2D1.Media imageBrush, _deviceContext, (BitmapImpl)imageBrush.Source.PlatformImpl.Item, - destinationSize); + destinationRect.Size); } else if (visualBrush != null) { @@ -523,7 +521,7 @@ namespace Avalonia.Direct2D1.Media visualBrush, _deviceContext, new D2DBitmapImpl(intermediate.Bitmap), - destinationSize); + destinationRect.Size); } } } @@ -574,7 +572,7 @@ namespace Avalonia.Direct2D1.Media ContentBounds = PrimitiveExtensions.RectangleInfinite, MaskTransform = PrimitiveExtensions.Matrix3x2Identity, Opacity = 1, - OpacityBrush = CreateBrush(mask, bounds.Size).PlatformBrush + OpacityBrush = CreateBrush(mask, bounds).PlatformBrush }; var layer = _layerPool.Count != 0 ? _layerPool.Pop() : new Layer(_deviceContext); _deviceContext.PushLayer(ref parameters, layer); diff --git a/src/Windows/Avalonia.Direct2D1/Media/LinearGradientBrushImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/LinearGradientBrushImpl.cs index 0e63d4cc03..69b45455ac 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/LinearGradientBrushImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/LinearGradientBrushImpl.cs @@ -8,7 +8,7 @@ namespace Avalonia.Direct2D1.Media public LinearGradientBrushImpl( ILinearGradientBrush brush, SharpDX.Direct2D1.RenderTarget target, - Size destinationSize) + Rect destinationRect) { if (brush.GradientStops.Count == 0) { @@ -21,8 +21,9 @@ namespace Avalonia.Direct2D1.Media Position = (float)s.Offset }).ToArray(); - var startPoint = brush.StartPoint.ToPixels(destinationSize); - var endPoint = brush.EndPoint.ToPixels(destinationSize); + var position = destinationRect.Position; + var startPoint = position + brush.StartPoint.ToPixels(destinationRect.Size); + var endPoint = position + brush.EndPoint.ToPixels(destinationRect.Size); using (var stops = new SharpDX.Direct2D1.GradientStopCollection( target, diff --git a/src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs b/src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs index 1fca6d4e33..7dcfd7e1e0 100644 --- a/src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs +++ b/src/Windows/Avalonia.Direct2D1/Media/RadialGradientBrushImpl.cs @@ -8,7 +8,7 @@ namespace Avalonia.Direct2D1.Media public RadialGradientBrushImpl( IRadialGradientBrush brush, SharpDX.Direct2D1.RenderTarget target, - Size destinationSize) + Rect destinationRect) { if (brush.GradientStops.Count == 0) { @@ -21,12 +21,13 @@ namespace Avalonia.Direct2D1.Media Position = (float)s.Offset }).ToArray(); - var centerPoint = brush.Center.ToPixels(destinationSize); - var gradientOrigin = brush.GradientOrigin.ToPixels(destinationSize) - centerPoint; + var position = destinationRect.Position; + var centerPoint = position + brush.Center.ToPixels(destinationRect.Size); + var gradientOrigin = position + brush.GradientOrigin.ToPixels(destinationRect.Size) - centerPoint; // Note: Direct2D supports RadiusX and RadiusY but Cairo backend supports only Radius property - var radiusX = brush.Radius * destinationSize.Width; - var radiusY = brush.Radius * destinationSize.Height; + var radiusX = brush.Radius * destinationRect.Width; + var radiusY = brush.Radius * destinationRect.Height; using (var stops = new SharpDX.Direct2D1.GradientStopCollection( target, diff --git a/tests/Avalonia.RenderTests/Media/ConicGradientBrushTests.cs b/tests/Avalonia.RenderTests/Media/ConicGradientBrushTests.cs index db69a0a028..3d2f09e2a8 100644 --- a/tests/Avalonia.RenderTests/Media/ConicGradientBrushTests.cs +++ b/tests/Avalonia.RenderTests/Media/ConicGradientBrushTests.cs @@ -1,5 +1,6 @@ using Avalonia.Controls; using Avalonia.Media; +using System; using System.Threading.Tasks; using Xunit; @@ -174,5 +175,44 @@ namespace Avalonia.Direct2D1.RenderTests.Media await RenderToFile(target); CompareImages(); } + + [Fact] + public async Task ConicGradientBrush_DrawingContext() + { + var brush = new ConicGradientBrush + { + GradientStops = + { + new GradientStop { Color = Colors.Red, Offset = 0 }, + new GradientStop { Color = Colors.Yellow, Offset = 0.1667 }, + new GradientStop { Color = Colors.Lime, Offset = 0.3333 }, + new GradientStop { Color = Colors.Aqua, Offset = 0.5000 }, + new GradientStop { Color = Colors.Blue, Offset = 0.6667 }, + new GradientStop { Color = Colors.Magenta, Offset = 0.8333 }, + new GradientStop { Color = Colors.Red, Offset = 1 }, + } + }; + + Decorator target = new Decorator + { + Width = 200, + Height = 200, + Child = new DrawnControl(c => + { + c.DrawRectangle(brush, null, new Rect(0, 0, 100, 100)); + c.DrawRectangle(brush, null, new Rect(100, 100, 100, 100)); + }), + }; + + await RenderToFile(target); + CompareImages(); + } + + private class DrawnControl : Control + { + private readonly Action _render; + public DrawnControl(Action render) => _render = render; + public override void Render(DrawingContext context) => _render(context); + } } } diff --git a/tests/Avalonia.RenderTests/Media/LinearGradientBrushTests.cs b/tests/Avalonia.RenderTests/Media/LinearGradientBrushTests.cs index af7b4f130f..28701f2f97 100644 --- a/tests/Avalonia.RenderTests/Media/LinearGradientBrushTests.cs +++ b/tests/Avalonia.RenderTests/Media/LinearGradientBrushTests.cs @@ -72,5 +72,41 @@ namespace Avalonia.Direct2D1.RenderTests.Media await RenderToFile(target); CompareImages(); } + + [Fact] + public async Task LinearGradientBrush_DrawingContext() + { + var brush = new LinearGradientBrush + { + StartPoint = new RelativePoint(0, 0, RelativeUnit.Relative), + EndPoint = new RelativePoint(1, 1, RelativeUnit.Relative), + GradientStops = + { + new GradientStop { Color = Colors.Red, Offset = 0 }, + new GradientStop { Color = Colors.Blue, Offset = 1 } + } + }; + + Decorator target = new Decorator + { + Width = 200, + Height = 200, + Child = new DrawnControl(c => + { + c.DrawRectangle(brush, null, new Rect(0, 0, 100, 100)); + c.DrawRectangle(brush, null, new Rect(100, 100, 100, 100)); + }), + }; + + await RenderToFile(target); + CompareImages(); + } + + private class DrawnControl : Control + { + private readonly Action _render; + public DrawnControl(Action render) => _render = render; + public override void Render(DrawingContext context) => _render(context); + } } } diff --git a/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs index 2941b8dc34..95fae7f2fa 100644 --- a/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs +++ b/tests/Avalonia.RenderTests/Media/RadialGradientBrushTests.cs @@ -165,5 +165,39 @@ namespace Avalonia.Direct2D1.RenderTests.Media await RenderToFile(target); CompareImages(); } + + [Fact] + public async Task RadialGradientBrush_DrawingContext() + { + var brush = new RadialGradientBrush + { + GradientStops = + { + new GradientStop { Color = Colors.Red, Offset = 0 }, + new GradientStop { Color = Colors.Blue, Offset = 1 } + } + }; + + Decorator target = new Decorator + { + Width = 200, + Height = 200, + Child = new DrawnControl(c => + { + c.DrawRectangle(brush, null, new Rect(0, 0, 100, 100)); + c.DrawRectangle(brush, null, new Rect(100, 100, 100, 100)); + }), + }; + + await RenderToFile(target); + CompareImages(); + } + + private class DrawnControl : Control + { + private readonly Action _render; + public DrawnControl(Action render) => _render = render; + public override void Render(DrawingContext context) => _render(context); + } } } diff --git a/tests/TestFiles/Direct2D1/Media/ConicGradientBrush/ConicGradientBrush_DrawingContext.expected.png b/tests/TestFiles/Direct2D1/Media/ConicGradientBrush/ConicGradientBrush_DrawingContext.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..3a2241b53f92cc878ba874d1af5fb67efd875848 GIT binary patch literal 631 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 HoGAW30rASt literal 0 HcmV?d00001 diff --git a/tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_DrawingContext.expected.png b/tests/TestFiles/Direct2D1/Media/RadialGradientBrush/RadialGradientBrush_DrawingContext.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..85d11f2c2bb1cb02ee1f4b84770ef83fac040e93 GIT binary patch literal 9127 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 literal 0 HcmV?d00001 diff --git a/tests/TestFiles/Skia/Media/ConicGradientBrush/ConicGradientBrush_DrawingContext.expected.png b/tests/TestFiles/Skia/Media/ConicGradientBrush/ConicGradientBrush_DrawingContext.expected.png new file mode 100644 index 0000000000000000000000000000000000000000..3906d5a181a2fdb7ee70e1ce1f01820608d1a4de GIT binary patch literal 10037 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

GN zs%8y3`btfqL}~Ev;9ACrX51TdI`uCt&T)(#gx@+9bNmfmTI8#gqC+enPP=QR*KK89 zQRl9NE)L>t7K>>a7OB!>KX_?l$*4|WDUo}FQQjcx0lh3;GPo8ZT;=lOOmB-7pfIfe z+hDedqm>RFzrl>$n@a&;d1Nb=5C&w^=1~Rs{DGs1*1E!s)T*U$$~VcS#KW9f^CjVj zOEeH@!PG%Lq`T6UY@;DHq+8&8_*K3;7BF6#Bb4M@%9vF2>s39>*=zMRzjl;pVruK}y=Fbdop+2P zq8TPZs$%wWCl7!d-VlynCyfex5i-~ZYO5qeJF2pcV(-~-MNy??1ThhDj&gnY4=Bv^ z+tKczzcEC1c*oT{jrChimh~9&w%K6q;19mXzgWV-Sg>uU(&yME+itr&B(e3?&sui!0$WcTJJebK~PV;z_Ft~t0+nM$L9-^gM8)fZA5KGUO#W$nJM z^e`+d{NwR4E!iHl5=yVYYrG%B%cXcvTN|LD9b0-#;p7Cdc42StH~rlxO-j&aN3u$%2ce+P&4`!0rxnZ2B8RSDz1 z*U&B~Vo-1)InIV%j$@uL-M63K%516iDPwG?fbgfq7mdh1C8m~$rrA$L&DjQG$XHU2GJG2N8^TNb5C z;Oia4+MVEE`osbp1Y%Eq48&kfNzykygl;we)0EM;@&vG9&+jcdB7@rZn0}=R06? zN3OqWbMk{mo!RmVXs+M0)tU0qUK%7KC2m*N3o@9N+i;Ng=TH0v0a`U(fZ@6(|4qbx zn}l+%S201XB;fF8mu6Yiu`Eau6o1-AW7j*~4a-Uw$8UBc!X@mXzuj#J`h6O>LKy7_ z$V##t%^>38bOo63(VLdkVwtS8-p_l^l^Gi-|Ls3t1E;4VbcK@&p-A?;Lckg*ZRd9M zZi9MF2;gL{U~}cNq+?+BO2QuWy3y$B*e<%io6Bfp^_hTC2N{%Hj`QyNK*p5R_-a+~ z5FV?%Y8N>7d6hBx8#+u2hRA#W`6ewDL? z$MTn#X3}DT;pP|J+6wzQMCNl<^Q;P2z@Jhz*Vy9bNdX4#CupCB^4i-XZdNZt)=t=T zKR5ianfVaO^|p%n*m&1Qumjt=K|k#GB=mhtoeh-{0phOJRbSuec}|A%l9*8s7zNSI zV^p-Gl>iS(s~DsGPhHufijr&s#U1aeuER$oI+ZB6NxF1=f}2KSF`zacJ?aIt1izH- z*IiPPLKguCM(R9P`gIarOw<)U7pQW)8iq7V4k><56HSB;uxP7L4R+DgnaQfn{U0=x z-YhN!O}LKITFjS_f)D}&!bo&dzjs3HkN|Xl$kdPkmufJ1x|#+H4lHFT56V2#@Vy|U z^FZ!Ieub;MYb;-ZSM?zN5%AHHz?K3%7}}o9aZ!8mR-k1-Y`*Qc)xadE$AW3lxB{;s z(A+EmB5{)m$aVKv;gQQk)n(CSaUcyyO_0*SGao8^x3}UrKTeTG?MfYy4+@BHn+@~f z$kw<5j8Gpv&OsMPY8|65B()l)ue)&O!zis?j>ayIUzetSY&_kQyB!n85^iec+> zf~@qiJ^`pxQ5i-m$HfnDWFPHY43_Pxbm2z$G)tDqI-)WTZN7KBPoSK@n18g= ztwC1L-3O0WQWoGK)M*_-A6j& zLoFe_yE73IV;LZC$3=Fyki1v{k)(;|G(*dwiK7~2pZ)nNprptXoG%?2M@BdxZwsH( zzVBkLl>47Kr17E#(2`KggehiX24Y0zNavD@0l5w%`g*aIMVB0`CqHFalXspX8{U-J!>u`q>f`I_o@T|)l>D083zu>M)i;nb;nq- z@Z1>gblQwnVH8ju``Ee9HUxU3F+DMwd~&9459)nw*7g|Hk|h-jbfCDOP&r+FtbqJm zq*N`dm%;x692GG@r299@i$ThQ0Z?A#;Hf*+Z!((%=?O~w1mR5@fN8u%Ev%Z;f23hV z$yDIX)+^1!c`FRMJyu;2cB0Mh76)e1@k|iASP6mZCSKxG!sCNZ#IBZ~Zs0wi1 zkG&x2cWS0?U~S)`YfQQfmOwAb-VG@dA`8Jq(q(dbBaGG#ZGFnQDt|?^{)@Yy0E>jM z+Q{W`OhA6Zt7*D_IT!SN7z!x>=4wE*Z8<16Z&XhweUHHx~YRU}tCDr2Xm22;$z%zg`^THTQ!Oy^GPZ_TH5-;Zw2ELaNTOV&vLx_9en_B`awP%7nEHdexo{6FHO)I6!%DsU z00^fCWSitl;ss}AP|}5rOV5-k6DoUWa`>~I2L=LJd%c{2Iwd+-Zw+V?RXkWsv_3D~ z03GY&Bh%<9Ek(96wkNm73CaIEN%_EFLJJi-+0PP|f#Rq|P^4-3LHSJM&*qc8CDBa< zaC))~RN2wQ06FlnS=eB!fsobk8&DBU)O&H9&UKcYfA1)R+NF`FWqe!}cup*^?rP_w zJhrl; zl$IY3WN1pRO(3RAQb_a#j8v%_IjqlFf&%&~71+6(xYCbK3KSFX^ss7egc=K51@2gf zp6n!R+X}Q6=T_vPF(u}qMSnYgwRyFy)0%a2xp8@`=qTb*1d=&ns{Cl-rwj{FOCyKh zVB%4CCuk#VBDP+W;d%(3!k_w$8gLe5?f*n!`Qw6CllXt5aGN7A{D>8Yzzi%<4#WK* zAW-?eT^55`HpYTh`WD_@#t($HvXu0$_Zw!YqX55lB@I?<-Y<^gDxWg}r^xn{!0Ct- zH!U%EFWIWq@J-(Fv!sm#@aHLHr|%WI|GekH7eNFx1N4>g=f)Gb6`KC`8~Iy`3q5$d zVD#(g+i=?OYBpezBYSh|pCdm6zC@hn`js+)DP`Zi3x;dErX_;@I@~Wl`Nx$)B5Htz zvB2Xj+cA!o{BxS*^m*8vfnNS3UDApJ-2ptiv0zLN$Bx+EPp z{g0ju>X_8Zd*VOC)P(9Nw;wV$+n&d09qpzjf(OZl_E27LVs0BaQ7E!Ufeba=Meq3t z6K2YZ3*w#A(tP7HSV!mEe)Gx$0)PGklpY4i z+o%@|<4aO{o*J&r7U>^AbVl`6BhUBsM!E`hVu1tq@#s18l8M;htHXrT!N= C-k?7K literal 0 HcmV?d00001