|
|
@@ -21,7 +21,9 @@ namespace Avalonia.Skia
|
|
|
IDrawingContextImplWithEffects
|
|
|
{
|
|
|
private IDisposable?[]? _disposables;
|
|
|
- private readonly Vector _dpi;
|
|
|
+ // TODO: Get rid of this value, it's currently used to calculate intermediate sizes for tile brushes
|
|
|
+ // but does so ignoring the current transform
|
|
|
+ private readonly Vector _intermediateSurfaceDpi;
|
|
|
private readonly Stack<PaintWrapper> _maskStack = new();
|
|
|
private readonly Stack<double> _opacityStack = new();
|
|
|
private readonly Stack<RenderOptions> _renderOptionsStack = new();
|
|
|
@@ -57,7 +59,12 @@ namespace Avalonia.Skia
|
|
|
public SKSurface? Surface;
|
|
|
|
|
|
/// <summary>
|
|
|
- /// Dpi of drawings.
|
|
|
+ /// Makes DPI to be applied as a hidden matrix transform
|
|
|
+ /// </summary>
|
|
|
+ public bool ScaleDrawingToDpi;
|
|
|
+
|
|
|
+ /// <summary>
|
|
|
+ /// Dpi for intermediate surfaces
|
|
|
/// </summary>
|
|
|
public Vector Dpi;
|
|
|
|
|
|
@@ -180,7 +187,7 @@ namespace Avalonia.Skia
|
|
|
Canvas = createInfo.Canvas ?? createInfo.Surface?.Canvas
|
|
|
?? throw new ArgumentException("Invalid create info - no Canvas provided", nameof(createInfo));
|
|
|
|
|
|
- _dpi = createInfo.Dpi;
|
|
|
+ _intermediateSurfaceDpi = createInfo.Dpi;
|
|
|
_disposables = disposables;
|
|
|
_disableSubpixelTextRendering = createInfo.DisableSubpixelTextRendering;
|
|
|
_grContext = createInfo.GrContext;
|
|
|
@@ -191,10 +198,12 @@ namespace Avalonia.Skia
|
|
|
|
|
|
_session = createInfo.CurrentSession;
|
|
|
|
|
|
- if (!_dpi.NearlyEquals(SkiaPlatform.DefaultDpi))
|
|
|
+
|
|
|
+ if (createInfo.ScaleDrawingToDpi && !createInfo.Dpi.NearlyEquals(SkiaPlatform.DefaultDpi))
|
|
|
{
|
|
|
_postTransform =
|
|
|
- Matrix.CreateScale(_dpi.X / SkiaPlatform.DefaultDpi.X, _dpi.Y / SkiaPlatform.DefaultDpi.Y);
|
|
|
+ Matrix.CreateScale(createInfo.Dpi.X / SkiaPlatform.DefaultDpi.X,
|
|
|
+ createInfo.Dpi.Y / SkiaPlatform.DefaultDpi.Y);
|
|
|
}
|
|
|
|
|
|
Transform = Matrix.Identity;
|
|
|
@@ -526,6 +535,32 @@ namespace Avalonia.Skia
|
|
|
SKRoundRectCache.Shared.Return(skRoundRect);
|
|
|
}
|
|
|
|
|
|
+ /// <inheritdoc />
|
|
|
+ public void DrawRegion(IBrush? brush, IPen? pen, IPlatformRenderInterfaceRegion region)
|
|
|
+ {
|
|
|
+ var r = (SkiaRegionImpl)region;
|
|
|
+ if(r.IsEmpty)
|
|
|
+ return;
|
|
|
+ CheckLease();
|
|
|
+
|
|
|
+ if (brush != null)
|
|
|
+ {
|
|
|
+ using (var fill = CreatePaint(_fillPaint, brush, r.Bounds.ToRect(1)))
|
|
|
+ {
|
|
|
+ Canvas.DrawRegion(r.Region, fill.Paint);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ if (pen is not null
|
|
|
+ && TryCreatePaint(_strokePaint, pen, r.Bounds.ToRect(1).Inflate(new Thickness(pen.Thickness / 2))) is { } stroke)
|
|
|
+ {
|
|
|
+ using (stroke)
|
|
|
+ {
|
|
|
+ Canvas.DrawRegion(r.Region, stroke.Paint);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
/// <inheritdoc />
|
|
|
public void DrawEllipse(IBrush? brush, IPen? pen, Rect rect)
|
|
|
{
|
|
|
@@ -591,7 +626,7 @@ namespace Avalonia.Skia
|
|
|
}
|
|
|
|
|
|
/// <inheritdoc />
|
|
|
- public IDrawingContextLayerImpl CreateLayer(Size size)
|
|
|
+ public IDrawingContextLayerImpl CreateLayer(PixelSize size)
|
|
|
{
|
|
|
CheckLease();
|
|
|
return CreateRenderTarget(size, true);
|
|
|
@@ -629,6 +664,14 @@ namespace Avalonia.Skia
|
|
|
SKRoundRectCache.Shared.Return(roundRect);
|
|
|
}
|
|
|
|
|
|
+ public void PushClip(IPlatformRenderInterfaceRegion region)
|
|
|
+ {
|
|
|
+ var r = ((SkiaRegionImpl)region).Region;
|
|
|
+ CheckLease();
|
|
|
+ Canvas.Save();
|
|
|
+ Canvas.ClipRegion(r);
|
|
|
+ }
|
|
|
+
|
|
|
/// <inheritdoc />
|
|
|
public void PopClip()
|
|
|
{
|
|
|
@@ -636,6 +679,18 @@ namespace Avalonia.Skia
|
|
|
Canvas.Restore();
|
|
|
}
|
|
|
|
|
|
+ public void PushLayer(Rect bounds)
|
|
|
+ {
|
|
|
+ CheckLease();
|
|
|
+ Canvas.SaveLayer(bounds.ToSKRect(), null!);
|
|
|
+ }
|
|
|
+
|
|
|
+ public void PopLayer()
|
|
|
+ {
|
|
|
+ CheckLease();
|
|
|
+ Canvas.Restore();
|
|
|
+ }
|
|
|
+
|
|
|
/// <inheritdoc />
|
|
|
public void PushOpacity(double opacity, Rect? bounds)
|
|
|
{
|
|
|
@@ -976,15 +1031,16 @@ namespace Avalonia.Skia
|
|
|
/// <param name="tileBrushImage">Tile brush image.</param>
|
|
|
private void ConfigureTileBrush(ref PaintWrapper paintWrapper, Rect targetBox, ITileBrush tileBrush, IDrawableBitmapImpl tileBrushImage)
|
|
|
{
|
|
|
- var calc = new TileBrushCalculator(tileBrush, tileBrushImage.PixelSize.ToSizeWithDpi(_dpi), targetBox.Size);
|
|
|
- var intermediate = CreateRenderTarget(calc.IntermediateSize, false);
|
|
|
+ var calc = new TileBrushCalculator(tileBrush, tileBrushImage.PixelSize.ToSizeWithDpi(_intermediateSurfaceDpi), targetBox.Size);
|
|
|
+ var intermediate = CreateRenderTarget(
|
|
|
+ PixelSize.FromSizeWithDpi(calc.IntermediateSize, _intermediateSurfaceDpi), false);
|
|
|
|
|
|
paintWrapper.AddDisposable(intermediate);
|
|
|
|
|
|
- using (var context = intermediate.CreateDrawingContext())
|
|
|
+ using (var context = intermediate.CreateDrawingContext(true))
|
|
|
{
|
|
|
var sourceRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(96));
|
|
|
- var targetRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(_dpi));
|
|
|
+ var targetRect = new Rect(tileBrushImage.PixelSize.ToSizeWithDpi(_intermediateSurfaceDpi));
|
|
|
|
|
|
context.Clear(Colors.Transparent);
|
|
|
context.PushClip(calc.IntermediateClip);
|
|
|
@@ -1028,7 +1084,7 @@ namespace Avalonia.Skia
|
|
|
SKMatrix.Concat(
|
|
|
ref paintTransform,
|
|
|
tileTransform,
|
|
|
- SKMatrix.CreateScale((float)(96.0 / _dpi.X), (float)(96.0 / _dpi.Y)));
|
|
|
+ SKMatrix.CreateScale((float)(96.0 / _intermediateSurfaceDpi.X), (float)(96.0 / _intermediateSurfaceDpi.Y)));
|
|
|
|
|
|
if (tileBrush.Transform is { })
|
|
|
{
|
|
|
@@ -1066,9 +1122,10 @@ namespace Avalonia.Skia
|
|
|
|
|
|
if (intermediateSize.Width >= 1 && intermediateSize.Height >= 1)
|
|
|
{
|
|
|
- using var intermediate = CreateRenderTarget(intermediateSize, false);
|
|
|
+ using var intermediate = CreateRenderTarget(
|
|
|
+ PixelSize.FromSizeWithDpi(intermediateSize, _intermediateSurfaceDpi), false);
|
|
|
|
|
|
- using (var ctx = intermediate.CreateDrawingContext())
|
|
|
+ using (var ctx = intermediate.CreateDrawingContext(true))
|
|
|
{
|
|
|
ctx.RenderOptions = RenderOptions;
|
|
|
ctx.Clear(Colors.Transparent);
|
|
|
@@ -1096,7 +1153,7 @@ namespace Avalonia.Skia
|
|
|
var calc = new TileBrushCalculator(tileBrush, contentSize, targetRect.Size);
|
|
|
transform *= calc.IntermediateTransform;
|
|
|
|
|
|
- using var pictureTarget = new PictureRenderTarget(_gpu, _grContext, _dpi);
|
|
|
+ using var pictureTarget = new PictureRenderTarget(_gpu, _grContext, _intermediateSurfaceDpi);
|
|
|
using (var ctx = pictureTarget.CreateDrawingContext(calc.IntermediateSize))
|
|
|
{
|
|
|
ctx.RenderOptions = RenderOptions;
|
|
|
@@ -1127,7 +1184,7 @@ namespace Avalonia.Skia
|
|
|
: SKShaderTileMode.Repeat;
|
|
|
|
|
|
paintTransform = SKMatrix.Concat(paintTransform,
|
|
|
- SKMatrix.CreateScale((float)(96.0 / _dpi.X), (float)(96.0 / _dpi.Y)));
|
|
|
+ SKMatrix.CreateScale((float)(96.0 / _intermediateSurfaceDpi.X), (float)(96.0 / _intermediateSurfaceDpi.Y)));
|
|
|
|
|
|
if (tileBrush.Transform is { })
|
|
|
{
|
|
|
@@ -1339,18 +1396,18 @@ namespace Avalonia.Skia
|
|
|
/// <summary>
|
|
|
/// Create new render target compatible with this drawing context.
|
|
|
/// </summary>
|
|
|
- /// <param name="size">The size of the render target in DIPs.</param>
|
|
|
+ /// <param name="pixelSize">The size of the render target.</param>
|
|
|
+ /// <param name="dpi">The DPI of the render target.</param>
|
|
|
/// <param name="isLayer">Whether the render target is being created for a layer.</param>
|
|
|
/// <param name="format">Pixel format.</param>
|
|
|
/// <returns></returns>
|
|
|
- private SurfaceRenderTarget CreateRenderTarget(Size size, bool isLayer, PixelFormat? format = null)
|
|
|
+ private SurfaceRenderTarget CreateRenderTarget(PixelSize pixelSize, bool isLayer, PixelFormat? format = null)
|
|
|
{
|
|
|
- var pixelSize = PixelSize.FromSizeWithDpi(size, _dpi);
|
|
|
var createInfo = new SurfaceRenderTarget.CreateInfo
|
|
|
{
|
|
|
Width = pixelSize.Width,
|
|
|
Height = pixelSize.Height,
|
|
|
- Dpi = _dpi,
|
|
|
+ Dpi = _intermediateSurfaceDpi,
|
|
|
Format = format,
|
|
|
DisableTextLcdRendering = isLayer ? _disableSubpixelTextRendering : true,
|
|
|
GrContext = _grContext,
|