Browse Source

Make a bunch of skia render tests pass.

Steven Kirk 8 years ago
parent
commit
8f4ef7fab0

+ 6 - 6
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
         /// <returns>A vector with the X and Y _translate.</returns>
 
         public static Vector CalculateTranslate(
-            TileBrush brush,
+            ITileBrush brush,
             Rect sourceRect,
             Rect destinationRect,
             Vector scale)

+ 10 - 4
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)

+ 61 - 11
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<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

+ 1 - 2
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);
         }
     }
 }

BIN
tests/TestFiles/Skia/GeometryClipping/Geometry_Clip_Clips_Path.expected.png