Browse Source

Make a bunch of skia render tests pass.

scenegraph-after-breakage
Steven Kirk 10 years ago
parent
commit
8f4ef7fab0
  1. 12
      src/Shared/RenderHelpers/TileBrushImplHelper.cs
  2. 14
      src/Skia/Avalonia.Skia/BitmapImpl.cs
  3. 72
      src/Skia/Avalonia.Skia/DrawingContextImpl.cs
  4. 3
      src/Skia/Avalonia.Skia/FramebufferRenderTarget.cs
  5. BIN
      tests/TestFiles/Skia/GeometryClipping/Geometry_Clip_Clips_Path.expected.png

12
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)

14
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)

72
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

3
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

Binary file not shown.

Before

Width:  |  Height:  |  Size: 373 B

After

Width:  |  Height:  |  Size: 728 B

Loading…
Cancel
Save