From 416ef6b601462f2eca229cfec1dd3481a8098aaa Mon Sep 17 00:00:00 2001 From: DJGosnell Date: Fri, 10 Feb 2023 18:45:20 -0500 Subject: [PATCH] Added two GetAndSetRadii methods. Added documentaiton. --- src/Skia/Avalonia.Skia/DrawingContextImpl.cs | 16 +---- src/Skia/Avalonia.Skia/SKRoundRectCache.cs | 76 +++++++++++++++++++- 2 files changed, 77 insertions(+), 15 deletions(-) diff --git a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs index 2bb6f1dc7e..eededb2836 100644 --- a/src/Skia/Avalonia.Skia/DrawingContextImpl.cs +++ b/src/Skia/Avalonia.Skia/DrawingContextImpl.cs @@ -365,15 +365,7 @@ namespace Avalonia.Skia SKRoundRect skRoundRect = null; if (needRoundRect) { - skRoundRect = SKRoundRectCache.Shared.Get(); - skRoundRect.SetRectRadii(rc, - new[] - { - rect.RadiiTopLeft.ToSKPoint(), - rect.RadiiTopRight.ToSKPoint(), - rect.RadiiBottomRight.ToSKPoint(), - rect.RadiiBottomLeft.ToSKPoint(), - }); + skRoundRect = SKRoundRectCache.Shared.GetAndSetRadii(rc, rect); } foreach (var boxShadow in boxShadows) @@ -389,8 +381,7 @@ namespace Avalonia.Skia Canvas.Save(); if (isRounded) { - var shadowRect = SKRoundRectCache.Shared.Get(); - shadowRect.SetRectRadii(skRoundRect!.Rect, skRoundRect.Radii); + var shadowRect = SKRoundRectCache.Shared.GetAndSetRadii(skRoundRect!.Rect, skRoundRect.Radii); if (spread != 0) shadowRect.Inflate(spread, spread); Canvas.ClipRoundRect(skRoundRect, @@ -446,8 +437,7 @@ namespace Avalonia.Skia var outerRect = AreaCastingShadowInHole(rc, (float)boxShadow.Blur, spread, offsetX, offsetY); Canvas.Save(); - var shadowRect = SKRoundRectCache.Shared.Get(); - shadowRect.SetRectRadii(skRoundRect!.Rect, skRoundRect.Radii); + var shadowRect = SKRoundRectCache.Shared.GetAndSetRadii(skRoundRect!.Rect, skRoundRect.Radii); if (spread != 0) shadowRect.Deflate(spread, spread); Canvas.ClipRoundRect(skRoundRect, diff --git a/src/Skia/Avalonia.Skia/SKRoundRectCache.cs b/src/Skia/Avalonia.Skia/SKRoundRectCache.cs index e164f97d6a..8de9e65553 100644 --- a/src/Skia/Avalonia.Skia/SKRoundRectCache.cs +++ b/src/Skia/Avalonia.Skia/SKRoundRectCache.cs @@ -1,13 +1,73 @@ -using System.Collections.Concurrent; +using System.Buffers; +using System.Collections.Concurrent; +using System.Collections.Generic; using SkiaSharp; namespace Avalonia.Skia { /// - /// Cache for SKPaints. + /// Cache for SKRoundRectCache. /// internal class SKRoundRectCache : SKCacheBase { + /// + /// Cache for points to use for setting the radii. + /// + private readonly ConcurrentBag _radiiCache = new(); + + /// + /// Gets a cached SKRoundRect and sets it with the passed rectangle and Radii. + /// + /// Rectangle size to set the cached rectangle to. + /// Rounded rectangle to copy the radii from. + /// Configured rounded rectangle + public SKRoundRect GetAndSetRadii(in SKRect rectangle, in RoundedRect roundedRect) + { + if (!Cache.TryTake(out var item)) + { + item = new SKRoundRect(); + } + + // Try and acquire a cached point array. + if (!_radiiCache.TryTake(out var skArray)) + { + skArray = new SKPoint[4]; + } + + skArray[0].X = (float)roundedRect.RadiiTopLeft.X; + skArray[0].Y = (float)roundedRect.RadiiTopLeft.Y; + skArray[1].X = (float)roundedRect.RadiiTopRight.X; + skArray[1].Y = (float)roundedRect.RadiiTopRight.Y; + skArray[2].X = (float)roundedRect.RadiiBottomRight.X; + skArray[2].Y = (float)roundedRect.RadiiBottomRight.Y; + skArray[3].X = (float)roundedRect.RadiiBottomLeft.X; + skArray[3].Y = (float)roundedRect.RadiiBottomLeft.Y; + + item.SetRectRadii(rectangle, skArray); + + // Add the array back to the cache. + _radiiCache.Add(skArray); + + return item; + } + + /// + /// Gets a cached SKRoundRect and sets it with the passed rectangle and Radii. + /// + /// Rectangle size to set the cached rectangle to. + /// point array of radii. + /// Configured rounded rectangle + public SKRoundRect GetAndSetRadii(in SKRect rectangle, in SKPoint[] radii) + { + if (!Cache.TryTake(out var item)) + { + item = new SKRoundRect(); + } + + item.SetRectRadii(rectangle, radii); + + return item; + } /// /// Returns a SKPaint and resets it for reuse later. /// @@ -22,5 +82,17 @@ namespace Avalonia.Skia rect.SetEmpty(); Cache.Add(rect); } + + /// + /// Clears and disposes all cached items. + /// + public new void Clear() + { + base.Clear(); + + // Clear out the cache of SKPoint arrays. + _radiiCache.Clear(); + } + } }