|
|
@@ -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<PaintWrapper> maskStack = new Stack<PaintWrapper>();
|
|
|
|
|
|
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
|