diff --git a/src/Shared/RenderHelpers/TileBrushImplHelper.cs b/src/Shared/RenderHelpers/TileBrushImplHelper.cs
index fc0057f01b..d1d3073be6 100644
--- a/src/Shared/RenderHelpers/TileBrushImplHelper.cs
+++ b/src/Shared/RenderHelpers/TileBrushImplHelper.cs
@@ -17,17 +17,17 @@ namespace Avalonia.RenderHelpers
private readonly Vector _scale;
private readonly Vector _translate;
private readonly Size _imageSize;
- private readonly VisualBrush _visualBrush;
- private readonly ImageBrush _imageBrush;
+ private readonly IVisualBrush _visualBrush;
+ private readonly IImageBrush _imageBrush;
private readonly Matrix _transform;
private readonly Rect _drawRect;
public bool IsValid { get; }
- public TileBrushImplHelper(TileBrush brush, Size targetSize)
+ public TileBrushImplHelper(ITileBrush brush, Size targetSize)
{
- _imageBrush = brush as ImageBrush;
- _visualBrush = brush as VisualBrush;
+ _imageBrush = brush as IImageBrush;
+ _visualBrush = brush as IVisualBrush;
if (_imageBrush != null)
{
if (_imageBrush.Source == null)
@@ -115,7 +115,7 @@ namespace Avalonia.RenderHelpers
/// A vector with the X and Y _translate.
public static Vector CalculateTranslate(
- TileBrush brush,
+ ITileBrush brush,
Rect sourceRect,
Rect destinationRect,
Vector scale)
diff --git a/src/Skia/Avalonia.Skia/BitmapImpl.cs b/src/Skia/Avalonia.Skia/BitmapImpl.cs
index 4d6b106fc6..7926a62a50 100644
--- a/src/Skia/Avalonia.Skia/BitmapImpl.cs
+++ b/src/Skia/Avalonia.Skia/BitmapImpl.cs
@@ -30,6 +30,11 @@ namespace Avalonia.Skia
if (runtime?.IsDesktop == true && runtime?.OperatingSystem == OperatingSystemType.Linux)
colorType = SKColorType.Bgra8888;
Bitmap = new SKBitmap(width, height, colorType, SKAlphaType.Premul);
+
+ using (var context = new BitmapDrawingContext(Bitmap, null))
+ {
+ context.Clear(Colors.Transparent);
+ }
}
public void Dispose()
@@ -56,7 +61,8 @@ namespace Avalonia.Skia
{
private readonly SKSurface _surface;
- public BitmapDrawingContext(SKBitmap bitmap) : this(CreateSurface(bitmap))
+ public BitmapDrawingContext(SKBitmap bitmap, IVisualBrushRenderer visualBrushRenderer)
+ : this(CreateSurface(bitmap), visualBrushRenderer)
{
}
@@ -70,7 +76,8 @@ namespace Avalonia.Skia
return rv;
}
- public BitmapDrawingContext(SKSurface surface) : base(surface.Canvas)
+ public BitmapDrawingContext(SKSurface surface, IVisualBrushRenderer visualBrushRenderer)
+ : base(surface.Canvas, visualBrushRenderer)
{
_surface = surface;
}
@@ -84,8 +91,7 @@ namespace Avalonia.Skia
public IDrawingContextImpl CreateDrawingContext(IVisualBrushRenderer visualBrushRenderer)
{
-
- return new BitmapDrawingContext(Bitmap);
+ return new BitmapDrawingContext(Bitmap, visualBrushRenderer);
}
public void Save(Stream stream)
diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
index eacf64e550..4be8662a18 100644
--- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
+++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs
@@ -6,6 +6,8 @@ using System;
using System.Collections.Generic;
using System.Linq;
using Avalonia.Platform;
+using Avalonia.Rendering.Utilities;
+using Avalonia.Rendering;
namespace Avalonia.Skia
{
@@ -13,14 +15,20 @@ namespace Avalonia.Skia
{
private readonly Matrix? _postTransform;
private readonly IDisposable[] _disposables;
+ private readonly IVisualBrushRenderer _visualBrushRenderer;
private Stack maskStack = new Stack();
public SKCanvas Canvas { get; private set; }
- public DrawingContextImpl(SKCanvas canvas, Matrix? postTransform = null, params IDisposable[] disposables)
+ public DrawingContextImpl(
+ SKCanvas canvas,
+ IVisualBrushRenderer visualBrushRenderer,
+ Matrix? postTransform = null,
+ params IDisposable[] disposables)
{
if (postTransform.HasValue && !postTransform.Value.IsIdentity)
_postTransform = postTransform;
+ _visualBrushRenderer = visualBrushRenderer;
_disposables = disposables;
Canvas = canvas;
Transform = Matrix.Identity;
@@ -160,14 +168,14 @@ namespace Avalonia.Skia
return rv;
}
- var gradient = brush as GradientBrush;
+ var gradient = brush as IGradientBrush;
if (gradient != null)
{
var tileMode = gradient.SpreadMethod.ToSKShaderTileMode();
var stopColors = gradient.GradientStops.Select(s => s.Color.ToSKColor()).ToArray();
var stopOffsets = gradient.GradientStops.Select(s => (float)s.Offset).ToArray();
- var linearGradient = brush as LinearGradientBrush;
+ var linearGradient = brush as ILinearGradientBrush;
if (linearGradient != null)
{
var start = linearGradient.StartPoint.ToPixels(targetSize).ToSKPoint();
@@ -180,7 +188,7 @@ namespace Avalonia.Skia
}
else
{
- var radialGradient = brush as RadialGradientBrush;
+ var radialGradient = brush as IRadialGradientBrush;
if (radialGradient != null)
{
var center = radialGradient.Center.ToPixels(targetSize).ToSKPoint();
@@ -199,15 +207,57 @@ namespace Avalonia.Skia
return rv;
}
- var tileBrush = brush as TileBrush;
- if (tileBrush != null)
+ var tileBrush = brush as ITileBrush;
+ var visualBrush = brush as IVisualBrush;
+ var tileBrushImage = default(BitmapImpl);
+
+ if (visualBrush != null)
{
- var helper = new TileBrushImplHelper(tileBrush, targetSize);
- var bitmap = new BitmapImpl((int)helper.IntermediateSize.Width, (int)helper.IntermediateSize.Height);
+ if (_visualBrushRenderer != null)
+ {
+ var intermediateSize = _visualBrushRenderer.GetRenderTargetSize(visualBrush);
+
+ if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1)
+ {
+ var intermediate = new BitmapImpl((int)intermediateSize.Width, (int)intermediateSize.Height);
+
+ using (var ctx = intermediate.CreateDrawingContext(_visualBrushRenderer))
+ {
+ ctx.Clear(Colors.Transparent);
+ _visualBrushRenderer.RenderVisualBrush(ctx, visualBrush);
+ }
+
+ rv.AddDisposable(tileBrushImage);
+ tileBrushImage = intermediate;
+ }
+ }
+ else
+ {
+ throw new NotSupportedException("No IVisualBrushRenderer was supplied to DrawingContextImpl.");
+ }
+ }
+ else
+ {
+ tileBrushImage = (BitmapImpl)((tileBrush as IImageBrush)?.Source?.PlatformImpl);
+ }
+
+ if (tileBrush != null && tileBrushImage != null)
+ {
+ var calc = new TileBrushCalculator(tileBrush, new Size(tileBrushImage.PixelWidth, tileBrushImage.PixelHeight), targetSize);
+ var bitmap = new BitmapImpl((int)calc.IntermediateSize.Width, (int)calc.IntermediateSize.Height);
rv.AddDisposable(bitmap);
- using (var ctx = bitmap.CreateDrawingContext(null))
- helper.DrawIntermediate(new DrawingContext(ctx));
- SKMatrix translation = SKMatrix.MakeTranslation(-(float)helper.DestinationRect.X, -(float)helper.DestinationRect.Y);
+ using (var context = bitmap.CreateDrawingContext(null))
+ {
+ var rect = new Rect(0, 0, tileBrushImage.PixelWidth, tileBrushImage.PixelHeight);
+
+ context.Clear(Colors.Transparent);
+ context.PushClip(calc.IntermediateClip);
+ context.Transform = calc.IntermediateTransform;
+ context.DrawImage(tileBrushImage, 1, rect, rect);
+ context.PopClip();
+ }
+
+ SKMatrix translation = SKMatrix.MakeTranslation(-(float)calc.DestinationRect.X, -(float)calc.DestinationRect.Y);
SKShaderTileMode tileX =
tileBrush.TileMode == TileMode.None
? SKShaderTileMode.Clamp
diff --git a/src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs b/src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs
index 7eaa8cf172..287c056cc9 100644
--- a/src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs
+++ b/src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs
@@ -88,10 +88,9 @@ namespace Avalonia.Skia
canvas.RestoreToCount(0);
canvas.Save();
- canvas.Clear(SKColors.Red);
canvas.ResetMatrix();
var scale = Matrix.CreateScale(fb.Dpi.Width / 96, fb.Dpi.Height / 96);
- return new DrawingContextImpl(canvas, scale, canvas, surface, shim, fb);
+ return new DrawingContextImpl(canvas, visualBrushRenderer, scale, canvas, surface, shim, fb);
}
}
}
diff --git a/tests/TestFiles/Skia/GeometryClipping/Geometry_Clip_Clips_Path.expected.png b/tests/TestFiles/Skia/GeometryClipping/Geometry_Clip_Clips_Path.expected.png
index 892899507b..5993088a33 100644
Binary files a/tests/TestFiles/Skia/GeometryClipping/Geometry_Clip_Clips_Path.expected.png and b/tests/TestFiles/Skia/GeometryClipping/Geometry_Clip_Clips_Path.expected.png differ