diff --git a/src/Uno.UI.Composition/Composition/CompositionMaskBrush.skia.cs b/src/Uno.UI.Composition/Composition/CompositionMaskBrush.skia.cs index 30698ebfd878..bcf515f88687 100644 --- a/src/Uno.UI.Composition/Composition/CompositionMaskBrush.skia.cs +++ b/src/Uno.UI.Composition/Composition/CompositionMaskBrush.skia.cs @@ -35,7 +35,7 @@ internal override void UpdatePaint(SKPaint paint, SKRect bounds) void IOnlineBrush.Paint(in Visual.PaintingSession session, SKRect bounds) { - var resultPaint = SkiaExtensions.GetTempSKPaint(); + var resultPaint = SkiaHelper.GetTempSKPaint(); resultPaint.IsAntialias = true; UpdatePaint(resultPaint, bounds); diff --git a/src/Uno.UI.Composition/Composition/CompositionSpriteShape.skia.cs b/src/Uno.UI.Composition/Composition/CompositionSpriteShape.skia.cs index fb46c1784002..06eac02c398b 100644 --- a/src/Uno.UI.Composition/Composition/CompositionSpriteShape.skia.cs +++ b/src/Uno.UI.Composition/Composition/CompositionSpriteShape.skia.cs @@ -76,7 +76,7 @@ internal override void Paint(in Visual.PaintingSession session) // On Windows, the stroke is simply 1px, it doesn't scale with the height. // So, to get a correct stroke geometry, we must apply the transformations first. - var strokeFillPath = SkiaExtensions.GetTempSKPath(); + var strokeFillPath = SkiaHelper.GetTempSKPath(); // Get the stroke geometry, after scaling has been applied. strokePaint.GetFillPath(geometryWithTransformations, strokeFillPath); @@ -95,7 +95,7 @@ private SKPaint GetTempFillPaint(SKColorFilter? colorFilter) private static SKPaint GetTempPaint(bool isStroke, SKColorFilter? colorFilter, bool isHighQuality = false) { - var paint = SkiaExtensions.GetTempSKPaint(); + var paint = isStroke ? SkiaHelper.GetTempSKPaint() : SkiaHelper.GetAnotherTempSKPaint(); paint.IsAntialias = true; paint.ColorFilter = colorFilter; @@ -162,7 +162,7 @@ internal override bool HitTest(Point point) var strokePaint = GetTempStrokePaint(null); strokePaint.StrokeWidth = StrokeThickness; - var hitTestStrokeFillPath = SkiaExtensions.GetTempSKPath(); + var hitTestStrokeFillPath = SkiaHelper.GetTempSKPath(); strokePaint.GetFillPath(geometryWithTransformations, hitTestStrokeFillPath); if (hitTestStrokeFillPath.Contains((float)point.X, (float)point.Y)) { diff --git a/src/Uno.UI.Composition/Composition/SkiaExtensions.skia.cs b/src/Uno.UI.Composition/Composition/SkiaExtensions.skia.cs index 7ad0eaa9b17d..ef771645640b 100644 --- a/src/Uno.UI.Composition/Composition/SkiaExtensions.skia.cs +++ b/src/Uno.UI.Composition/Composition/SkiaExtensions.skia.cs @@ -12,9 +12,6 @@ namespace Microsoft.UI.Composition { public static class SkiaExtensions { - [ThreadStatic] private static readonly SKPath _tempPath = new SKPath(); - [ThreadStatic] private static readonly SKPaint _tempPaint = new SKPaint(); - public static SKRect ToSKRect(this Rect rect) => new SKRect((float)rect.Left, (float)rect.Top, (float)rect.Right, (float)rect.Bottom); @@ -144,21 +141,5 @@ public static SKBitmap ToSKBitmap(this SKImage image) return bmp!; } - - public static SKPath GetTempSKPath() - { - // Note the difference between Rewind and Reset - // https://api.skia.org/classSkPath.html#a8dc858ee4c95a59b3dd4bdd3f7b85fdc : "Use rewind() instead of reset() if SkPath storage will be reused and performance is critical." - _tempPath.Rewind(); - return _tempPath; - } - - public static SKPaint GetTempSKPaint() - { - // https://api.skia.org/classSkPaint.html#a6c7118c97a0e8819d75aa757afbc4c49 - // "This is equivalent to replacing SkPaint with the result of SkPaint()." - _tempPaint.Reset(); - return _tempPaint; - } } } diff --git a/src/Uno.UI.Composition/Composition/SkiaHelper.skia.cs b/src/Uno.UI.Composition/Composition/SkiaHelper.skia.cs new file mode 100644 index 000000000000..a74f63bad0aa --- /dev/null +++ b/src/Uno.UI.Composition/Composition/SkiaHelper.skia.cs @@ -0,0 +1,43 @@ +#nullable enable + +using SkiaSharp; +using System; +using System.Collections.Generic; +using System.Numerics; +using System.Text; +using Windows.Foundation; +using Windows.UI; + +namespace Microsoft.UI.Composition +{ + public static class SkiaHelper + { + [ThreadStatic] private static readonly SKPath _tempPath = new SKPath(); + [ThreadStatic] private static readonly SKPaint _tempPaint = new SKPaint(); + [ThreadStatic] private static readonly SKPaint _tempPaint2 = new SKPaint(); + + public static SKPath GetTempSKPath() + { + // Note the difference between Rewind and Reset + // https://api.skia.org/classSkPath.html#a8dc858ee4c95a59b3dd4bdd3f7b85fdc : "Use rewind() instead of reset() if SkPath storage will be reused and performance is critical." + _tempPath.Rewind(); + return _tempPath; + } + + public static SKPaint GetTempSKPaint() + { + // https://api.skia.org/classSkPaint.html#a6c7118c97a0e8819d75aa757afbc4c49 + // "This is equivalent to replacing SkPaint with the result of SkPaint()." + _tempPaint.Reset(); + return _tempPaint; + } + + public static SKPaint GetAnotherTempSKPaint() + { + // https://api.skia.org/classSkPaint.html#a6c7118c97a0e8819d75aa757afbc4c49 + // "This is equivalent to replacing SkPaint with the result of SkPaint()." + _tempPaint2.Reset(); + return _tempPaint2; + } + } +} diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.skia.cs b/src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.skia.cs index c49b0413c628..f1b23279f2b0 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.skia.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBlock/TextBlock.skia.cs @@ -190,7 +190,7 @@ partial void SetupInlines() var canvas = t.canvas; var rect = t.rect; - var paint = SkiaExtensions.GetTempSKPaint(); + var paint = SkiaHelper.GetTempSKPaint(); paint.Color = SelectionHighlightColor.Color.ToSKColor(); paint.Style = SKPaintStyle.Fill; canvas.DrawRect(new SKRect((float)rect.Left, (float)rect.Top, (float)rect.Right, (float)rect.Bottom), paint); diff --git a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs index 1670dcbdfa02..7d35bd15b7ef 100644 --- a/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs +++ b/src/Uno.UI/UI/Xaml/Controls/TextBox/TextBox.skia.cs @@ -239,7 +239,7 @@ private void UpdateTextBoxView() var caretRect = args.rect; var compositor = _visual.Compositor; var brush = DefaultBrushes.TextForegroundBrush.GetOrCreateCompositionBrush(compositor); - var caretPaint = Microsoft.UI.Composition.SkiaExtensions.GetTempSKPaint(); + var caretPaint = SkiaHelper.GetTempSKPaint(); brush.UpdatePaint(caretPaint, caretRect.ToSKRect()); args.canvas.DrawRect( new SKRect((float)caretRect.Left, (float)caretRect.Top, (float)caretRect.Right, diff --git a/src/Uno.UI/UI/Xaml/Documents/InlineCollection.skia.cs b/src/Uno.UI/UI/Xaml/Documents/InlineCollection.skia.cs index 1096239376b8..c4fdafe5ccf1 100644 --- a/src/Uno.UI/UI/Xaml/Documents/InlineCollection.skia.cs +++ b/src/Uno.UI/UI/Xaml/Documents/InlineCollection.skia.cs @@ -501,7 +501,7 @@ internal void Draw(in Visual.PaintingSession session) var inline = segment.Inline; var fontInfo = segment.FallbackFont ?? inline.FontInfo; - var paint = SkiaExtensions.GetTempSKPaint(); + var paint = SkiaHelper.GetTempSKPaint(); paint.TextEncoding = SKTextEncoding.Utf16; paint.IsStroke = false; paint.IsAntialias = true;