From e0de203749937918eb1c92569d0541c025bbffe7 Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Mon, 18 Sep 2023 21:21:00 +0200 Subject: [PATCH 01/24] Use spans instead of arrays --- binding/SkiaSharp/SKData.cs | 11 ++--------- binding/SkiaSharp/SKImage.cs | 24 ------------------------ binding/SkiaSharp/SKPathEffect.cs | 2 +- binding/SkiaSharp/SKRoundRect.cs | 2 +- 4 files changed, 4 insertions(+), 35 deletions(-) diff --git a/binding/SkiaSharp/SKData.cs b/binding/SkiaSharp/SKData.cs index 6be1ee9846..698926c61d 100644 --- a/binding/SkiaSharp/SKData.cs +++ b/binding/SkiaSharp/SKData.cs @@ -62,23 +62,16 @@ public static SKData CreateCopy (IntPtr bytes, ulong length) return GetObject (SkiaApi.sk_data_new_with_copy ((void*)bytes, (IntPtr)length)); } - public static SKData CreateCopy (byte[] bytes) => + public static SKData CreateCopy (ReadOnlySpan bytes) => CreateCopy (bytes, (ulong)bytes.Length); - public static SKData CreateCopy (byte[] bytes, ulong length) + public static SKData CreateCopy (ReadOnlySpan bytes, ulong length) { fixed (byte* b = bytes) { return GetObject (SkiaApi.sk_data_new_with_copy (b, (IntPtr)length)); } } - public static SKData CreateCopy (ReadOnlySpan bytes) - { - fixed (byte* b = bytes) { - return CreateCopy ((IntPtr)b, (ulong)bytes.Length); - } - } - // Create public static SKData Create (int size) => diff --git a/binding/SkiaSharp/SKImage.cs b/binding/SkiaSharp/SKImage.cs index 3e3cfef8e6..b23093f229 100644 --- a/binding/SkiaSharp/SKImage.cs +++ b/binding/SkiaSharp/SKImage.cs @@ -60,18 +60,6 @@ public static SKImage FromPixelCopy (SKImageInfo info, Stream pixels, int rowByt } } - public static SKImage FromPixelCopy (SKImageInfo info, byte[] pixels) => - FromPixelCopy (info, pixels, info.RowBytes); - - public static SKImage FromPixelCopy (SKImageInfo info, byte[] pixels, int rowBytes) - { - if (pixels == null) - throw new ArgumentNullException (nameof (pixels)); - using (var data = SKData.CreateCopy (pixels)) { - return FromPixels (info, data, rowBytes); - } - } - public static SKImage FromPixelCopy (SKImageInfo info, IntPtr pixels) => FromPixelCopy (info, pixels, info.RowBytes); @@ -184,18 +172,6 @@ public static SKImage FromEncodedData (ReadOnlySpan data) } } - public static SKImage FromEncodedData (byte[] data) - { - if (data == null) - throw new ArgumentNullException (nameof (data)); - if (data.Length == 0) - throw new ArgumentException ("The data buffer was empty."); - - using (var skdata = SKData.CreateCopy (data)) { - return FromEncodedData (skdata); - } - } - public static SKImage FromEncodedData (SKStream data) { if (data == null) diff --git a/binding/SkiaSharp/SKPathEffect.cs b/binding/SkiaSharp/SKPathEffect.cs index d21d3d7cc4..d668dba370 100644 --- a/binding/SkiaSharp/SKPathEffect.cs +++ b/binding/SkiaSharp/SKPathEffect.cs @@ -61,7 +61,7 @@ public static SKPathEffect Create2DPath(SKMatrix matrix, SKPath path) return GetObject(SkiaApi.sk_path_effect_create_2d_path(&matrix, path.Handle)); } - public static SKPathEffect CreateDash(float[] intervals, float phase) + public static SKPathEffect CreateDash(ReadOnlySpan intervals, float phase) { if (intervals == null) throw new ArgumentNullException(nameof(intervals)); diff --git a/binding/SkiaSharp/SKRoundRect.cs b/binding/SkiaSharp/SKRoundRect.cs index 67f8794da4..bee09fe7f0 100644 --- a/binding/SkiaSharp/SKRoundRect.cs +++ b/binding/SkiaSharp/SKRoundRect.cs @@ -118,7 +118,7 @@ public void SetNinePatch (SKRect rect, float leftRadius, float topRadius, float SkiaApi.sk_rrect_set_nine_patch (Handle, &rect, leftRadius, topRadius, rightRadius, bottomRadius); } - public void SetRectRadii (SKRect rect, SKPoint[] radii) + public void SetRectRadii (SKRect rect, ReadOnlySpan radii) { if (radii == null) throw new ArgumentNullException (nameof (radii)); From 3a77f16e740bcc352efd8fbf45cf9e4afb34eead Mon Sep 17 00:00:00 2001 From: Matthew Leibowitz Date: Mon, 18 Sep 2023 20:19:26 +0000 Subject: [PATCH 02/24] Add some tests --- tests/Tests/SkiaSharp/SKDataTest.cs | 9 +++++++ tests/Tests/SkiaSharp/SKImageTest.cs | 30 ++++++++++++++++++++++ tests/Tests/SkiaSharp/SKRoundRectTest.cs | 32 +++++++++++++++++++++++- 3 files changed, 70 insertions(+), 1 deletion(-) diff --git a/tests/Tests/SkiaSharp/SKDataTest.cs b/tests/Tests/SkiaSharp/SKDataTest.cs index b064bd3497..16b5fb7dd3 100644 --- a/tests/Tests/SkiaSharp/SKDataTest.cs +++ b/tests/Tests/SkiaSharp/SKDataTest.cs @@ -37,6 +37,15 @@ public void ValidDataProperties() Assert.Equal(OddData, data.ToArray()); } + [SkippableFact] + public void ValidDataPropertiesWithSpan() + { + var data = SKData.CreateCopy(new ReadOnlySpan(OddData)); + + Assert.Equal(OddData.Length, data.Size); + Assert.Equal(OddData, data.ToArray()); + } + [SkippableFact] public void AsStreamReturnsCorrectStreamData() { diff --git a/tests/Tests/SkiaSharp/SKImageTest.cs b/tests/Tests/SkiaSharp/SKImageTest.cs index e8942b5ef2..597a309051 100644 --- a/tests/Tests/SkiaSharp/SKImageTest.cs +++ b/tests/Tests/SkiaSharp/SKImageTest.cs @@ -8,6 +8,22 @@ namespace SkiaSharp.Tests { public class SKImageTest : SKTest { + [SkippableFact] + public void TestDecodeByteArray() + { + var data = SKData.Create(Path.Combine(PathToImages, "baboon.jpg")); + var image = SKImage.FromEncodedData(data.ToArray()); + Assert.NotNull(image); + } + + [SkippableFact] + public void TestDecodeSpan() + { + var data = SKData.Create(Path.Combine(PathToImages, "baboon.jpg")); + var image = SKImage.FromEncodedData(data.AsSpan()); + Assert.NotNull(image); + } + [SkippableFact] public void TestLazyImage() { @@ -208,6 +224,20 @@ public void TestFromPixelCopyByteArray() } } + [SkippableFact] + public unsafe void TestFromPixelCopySpan() + { + using (var bmp = CreateTestBitmap()) + { + var px = bmp.GetPixels(out var length); + var dst = new Span((void*)px, (int)length); + using (var image = SKImage.FromPixelCopy(bmp.Info, dst)) + { + ValidateTestPixmap(image.PeekPixels()); + } + } + } + [SkippableFact] public void TestFromPixelCopyStream() { diff --git a/tests/Tests/SkiaSharp/SKRoundRectTest.cs b/tests/Tests/SkiaSharp/SKRoundRectTest.cs index 5a2e9f4944..64e537465b 100644 --- a/tests/Tests/SkiaSharp/SKRoundRectTest.cs +++ b/tests/Tests/SkiaSharp/SKRoundRectTest.cs @@ -107,7 +107,7 @@ public void CanNotConstructRectWithInvalidRadii() } [SkippableFact] - public void CanConstructRectWithRadii() + public void CanConstructRectWithRadiiArray() { var rect = SKRect.Create(10, 10, 100, 100); var radii = new[] @@ -136,6 +136,36 @@ public void CanConstructRectWithRadii() Assert.Equal(radii[3], rrect.GetRadii(SKRoundRectCorner.LowerLeft)); } + [SkippableFact] + public void CanConstructRectWithRadiiSpan() + { + var rect = SKRect.Create(10, 10, 100, 100); + Span radii = stackalloc[] + { + new SKPoint(1, 2), + new SKPoint(3, 4), + new SKPoint(5, 6), + new SKPoint(7, 8) + }; + + var rrect = new SKRoundRect(); + rrect.SetRectRadii(rect, radii); + + Assert.NotNull(rrect); + Assert.True(rrect.IsValid); + + Assert.Equal(SKRoundRectType.Complex, rrect.Type); + + Assert.Equal(100f, rrect.Width); + Assert.Equal(100f, rrect.Height); + Assert.Equal(rect, rrect.Rect); + + Assert.Equal(radii[0], rrect.GetRadii(SKRoundRectCorner.UpperLeft)); + Assert.Equal(radii[1], rrect.GetRadii(SKRoundRectCorner.UpperRight)); + Assert.Equal(radii[2], rrect.GetRadii(SKRoundRectCorner.LowerRight)); + Assert.Equal(radii[3], rrect.GetRadii(SKRoundRectCorner.LowerLeft)); + } + [SkippableFact] public void CanCopy() { From 7741e7852d315f04823174415dfaf3abe7dc322d Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Fri, 10 Nov 2023 03:44:49 -0500 Subject: [PATCH 03/24] Convert many arrays to spans, or add span overloads where array overloads are still useful. Some null checks have been removed as they are immediately followed by minimum length checks, which effectively accomplish the same goal. --- binding/SkiaSharp/SKCanvas.cs | 49 ++++++--- binding/SkiaSharp/SKCodec.cs | 10 ++ binding/SkiaSharp/SKColorFilter.cs | 2 +- binding/SkiaSharp/SKColorSpace.cs | 5 +- binding/SkiaSharp/SKColorSpaceStructs.cs | 120 ++++++++++++++++++----- binding/SkiaSharp/SKData.cs | 6 ++ binding/SkiaSharp/SKFont.cs | 5 +- binding/SkiaSharp/SKMaskFilter.cs | 4 +- binding/SkiaSharp/SKMatrix.cs | 51 +++++----- binding/SkiaSharp/SKPMColor.cs | 24 ++++- binding/SkiaSharp/SKPath.cs | 31 ++++-- binding/SkiaSharp/SKRuntimeEffect.cs | 8 +- binding/SkiaSharp/SKShader.cs | 60 ++++++------ binding/SkiaSharp/SKStream.cs | 20 +++- binding/SkiaSharp/SKString.cs | 31 ++++-- binding/SkiaSharp/SKVertices.cs | 8 +- 16 files changed, 304 insertions(+), 130 deletions(-) diff --git a/binding/SkiaSharp/SKCanvas.cs b/binding/SkiaSharp/SKCanvas.cs index 81966b9a45..efc6a3a673 100644 --- a/binding/SkiaSharp/SKCanvas.cs +++ b/binding/SkiaSharp/SKCanvas.cs @@ -409,7 +409,7 @@ public void DrawPath (SKPath path, SKPaint paint) // DrawPoints - public void DrawPoints (SKPointMode mode, SKPoint[] points, SKPaint paint) + public void DrawPoints (SKPointMode mode, ReadOnlySpan points, SKPaint paint) { if (paint == null) throw new ArgumentNullException (nameof (paint)); @@ -754,6 +754,13 @@ public SKData DrawUrlAnnotation (SKRect rect, string value) return data; } + public SKData DrawUrlAnnotation (SKRect rect, ReadOnlySpan value) + { + var data = SKData.FromCString (value); + DrawUrlAnnotation (rect, data); + return data; + } + public void DrawNamedDestinationAnnotation (SKPoint point, SKData value) { SkiaApi.sk_canvas_draw_named_destination_annotation (Handle, &point, value == null ? IntPtr.Zero : value.Handle); @@ -766,6 +773,13 @@ public SKData DrawNamedDestinationAnnotation (SKPoint point, string value) return data; } + public SKData DrawNamedDestinationAnnotation (SKPoint point, ReadOnlySpan value) + { + var data = SKData.FromCString (value); + DrawNamedDestinationAnnotation (point, data); + return data; + } + public void DrawLinkDestinationAnnotation (SKRect rect, SKData value) { SkiaApi.sk_canvas_draw_link_destination_annotation (Handle, &rect, value == null ? IntPtr.Zero : value.Handle); @@ -778,6 +792,13 @@ public SKData DrawLinkDestinationAnnotation (SKRect rect, string value) return data; } + public SKData DrawLinkDestinationAnnotation (SKRect rect, ReadOnlySpan value) + { + var data = SKData.FromCString (value); + DrawLinkDestinationAnnotation (rect, data); + return data; + } + // Draw*NinePatch public void DrawBitmapNinePatch (SKBitmap bitmap, SKRectI center, SKRect dst, SKPaint paint = null) => @@ -905,25 +926,25 @@ public SKMatrix44 TotalMatrix44 { // DrawVertices - public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKColor[] colors, SKPaint paint) + public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan colors, SKPaint paint) { var vert = SKVertices.CreateCopy (vmode, vertices, colors); DrawVertices (vert, SKBlendMode.Modulate, paint); } - public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKPaint paint) + public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, SKPaint paint) { var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors); DrawVertices (vert, SKBlendMode.Modulate, paint); } - public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, UInt16[] indices, SKPaint paint) + public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, ReadOnlySpan indices, SKPaint paint) { var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices); DrawVertices (vert, SKBlendMode.Modulate, paint); } - public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKBlendMode mode, UInt16[] indices, SKPaint paint) + public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, SKBlendMode mode, ReadOnlySpan indices, SKPaint paint) { var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices); DrawVertices (vert, mode, paint); @@ -963,31 +984,31 @@ public void DrawRoundRectDifference (SKRoundRect outer, SKRoundRect inner, SKPai // DrawAtlas - public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKPaint paint = null) => + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, SKPaint paint = null) => #pragma warning disable CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' DrawAtlas (atlas, sprites, transforms, null, SKBlendMode.Dst, paint?.FilterQuality.ToSamplingOptions() ?? SKSamplingOptions.Default, null, paint); #pragma warning restore CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' - public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKSamplingOptions sampling, SKPaint paint = null) => + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, SKSamplingOptions sampling, SKPaint paint = null) => DrawAtlas (atlas, sprites, transforms, null, SKBlendMode.Dst, sampling, null, paint); - public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKPaint paint = null) => + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKPaint paint = null) => #pragma warning disable CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' DrawAtlas (atlas, sprites, transforms, colors, mode, paint?.FilterQuality.ToSamplingOptions() ?? SKSamplingOptions.Default, null, paint); #pragma warning restore CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' - public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKSamplingOptions sampling, SKPaint paint = null) => + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKSamplingOptions sampling, SKPaint paint = null) => DrawAtlas (atlas, sprites, transforms, colors, mode, sampling, null, paint); - public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKRect cullRect, SKPaint paint = null) => + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKRect cullRect, SKPaint paint = null) => #pragma warning disable CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' DrawAtlas (atlas, sprites, transforms, colors, mode, paint?.FilterQuality.ToSamplingOptions() ?? SKSamplingOptions.Default, &cullRect, paint); #pragma warning restore CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' - public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKSamplingOptions sampling, SKRect cullRect, SKPaint paint = null) => + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKSamplingOptions sampling, SKRect cullRect, SKPaint paint = null) => DrawAtlas (atlas, sprites, transforms, colors, mode, sampling, &cullRect, paint); - private void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKSamplingOptions sampling, SKRect* cullRect, SKPaint paint = null) + private void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKSamplingOptions sampling, SKRect* cullRect, SKPaint paint = null) { if (atlas == null) throw new ArgumentNullException (nameof (atlas)); @@ -1010,10 +1031,10 @@ private void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] // DrawPatch - public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKPoint[] texCoords, SKPaint paint) => + public void DrawPatch (ReadOnlySpan cubics, ReadOnlySpan colors, ReadOnlySpan texCoords, SKPaint paint) => DrawPatch (cubics, colors, texCoords, SKBlendMode.Modulate, paint); - public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKPoint[] texCoords, SKBlendMode mode, SKPaint paint) + public void DrawPatch (ReadOnlySpan cubics, ReadOnlySpan colors, ReadOnlySpan texCoords, SKBlendMode mode, SKPaint paint) { if (cubics == null) throw new ArgumentNullException (nameof (cubics)); diff --git a/binding/SkiaSharp/SKCodec.cs b/binding/SkiaSharp/SKCodec.cs index 859f8b7825..9065a017e1 100644 --- a/binding/SkiaSharp/SKCodec.cs +++ b/binding/SkiaSharp/SKCodec.cs @@ -110,6 +110,16 @@ public SKCodecResult GetPixels (SKImageInfo info, byte[] pixels) } } + public SKCodecResult GetPixels (SKImageInfo info, Span pixels) + { + if (pixels == null) + throw new ArgumentNullException (nameof (pixels)); + + fixed (byte* p = pixels) { + return GetPixels (info, (IntPtr)p, info.RowBytes, SKCodecOptions.Default); + } + } + public SKCodecResult GetPixels (SKImageInfo info, IntPtr pixels) => GetPixels (info, pixels, info.RowBytes, SKCodecOptions.Default); diff --git a/binding/SkiaSharp/SKColorFilter.cs b/binding/SkiaSharp/SKColorFilter.cs index c17062d975..3c279a9829 100644 --- a/binding/SkiaSharp/SKColorFilter.cs +++ b/binding/SkiaSharp/SKColorFilter.cs @@ -36,7 +36,7 @@ public static SKColorFilter CreateCompose(SKColorFilter outer, SKColorFilter inn return GetObject (SkiaApi.sk_colorfilter_new_compose(outer.Handle, inner.Handle)); } - public static SKColorFilter CreateColorMatrix(float[] matrix) + public static SKColorFilter CreateColorMatrix (float[] matrix) { if (matrix == null) throw new ArgumentNullException(nameof(matrix)); diff --git a/binding/SkiaSharp/SKColorSpace.cs b/binding/SkiaSharp/SKColorSpace.cs index a639dac46f..a9f3da5626 100644 --- a/binding/SkiaSharp/SKColorSpace.cs +++ b/binding/SkiaSharp/SKColorSpace.cs @@ -78,7 +78,10 @@ public static bool Equal (SKColorSpace left, SKColorSpace right) public static SKColorSpace CreateIcc (IntPtr input, long length) => CreateIcc (SKColorSpaceIccProfile.Create (input, length)); - public static SKColorSpace CreateIcc (byte[] input, long length) + public static SKColorSpace CreateIcc (byte[] input, long length) => + CreateIcc (input.AsSpan (), length); + + public static SKColorSpace CreateIcc (ReadOnlySpan input, long length) { if (input == null) throw new ArgumentNullException (nameof (input)); diff --git a/binding/SkiaSharp/SKColorSpaceStructs.cs b/binding/SkiaSharp/SKColorSpaceStructs.cs index 35c51a1193..4c0d63f1e1 100644 --- a/binding/SkiaSharp/SKColorSpaceStructs.cs +++ b/binding/SkiaSharp/SKColorSpaceStructs.cs @@ -9,10 +9,8 @@ public unsafe partial struct SKColorSpacePrimaries { public static readonly SKColorSpacePrimaries Empty; - public SKColorSpacePrimaries (float[] values) + public SKColorSpacePrimaries (ReadOnlySpan values) { - if (values == null) - throw new ArgumentNullException (nameof (values)); if (values.Length != 8) throw new ArgumentException ("The values must have exactly 8 items, one for each of [RX, RY, GX, GY, BX, BY, WX, WY].", nameof (values)); @@ -41,6 +39,36 @@ public SKColorSpacePrimaries (float rx, float ry, float gx, float gy, float bx, public readonly float[] Values => new[] { fRX, fRY, fGX, fGY, fBX, fBY, fWX, fWY }; + public readonly void GetValues (Span values) + { + if (values.Length != 8) + throw new ArgumentException ("The values must have exactly 8 items, one for each of [RX, RY, GX, GY, BX, BY, WX, WY].", nameof (values)); + + values[0] = fRX; + values[1] = fRY; + values[2] = fGX; + values[3] = fGY; + values[4] = fBX; + values[5] = fBY; + values[6] = fWX; + values[7] = fWY; + } + + public void SetValues (ReadOnlySpan values) + { + if (values.Length != 8) + throw new ArgumentException ("The values must have exactly 8 items, one for each of [RX, RY, GX, GY, BX, BY, WX, WY].", nameof (values)); + + fRX = values[0]; + fRY = values[1]; + fGX = values[2]; + fGY = values[3]; + fBX = values[4]; + fBY = values[5]; + fWX = values[6]; + fWY = values[7]; + } + public readonly bool ToColorSpaceXyz (out SKColorSpaceXyz toXyzD50) { fixed (SKColorSpacePrimaries* t = &this) @@ -105,10 +133,8 @@ public static SKColorSpaceTransferFn Hlg { public static readonly SKColorSpaceTransferFn Empty; - public SKColorSpaceTransferFn (float[] values) + public SKColorSpaceTransferFn (ReadOnlySpan values) { - if (values == null) - throw new ArgumentNullException (nameof (values)); if (values.Length != 7) throw new ArgumentException ("The values must have exactly 7 items, one for each of [G, A, B, C, D, E, F].", nameof (values)); @@ -135,6 +161,35 @@ public SKColorSpaceTransferFn (float g, float a, float b, float c, float d, floa public readonly float[] Values => new[] { fG, fA, fB, fC, fD, fE, fF }; + + public readonly void GetValues (Span values) + { + if (values.Length != 7) + throw new ArgumentException ("The values must have exactly 7 items, one for each of [G, A, B, C, D, E, F].", nameof (values)); + + values[0] = fG; + values[1] = fA; + values[2] = fB; + values[3] = fC; + values[4] = fD; + values[5] = fE; + values[6] = fF; + } + + public void SetValues (ReadOnlySpan values) + { + if (values.Length != 8) + throw new ArgumentException ("The values must have exactly 7 items, one for each of [G, A, B, C, D, E, F].", nameof (values)); + + fG = values[0]; + fA = values[1]; + fB = values[2]; + fC = values[3]; + fD = values[4]; + fE = values[5]; + fF = values[6]; + } + public readonly SKColorSpaceTransferFn Invert () { SKColorSpaceTransferFn inverted; @@ -217,12 +272,10 @@ public SKColorSpaceXyz (float value) fM22 = value; } - public SKColorSpaceXyz (float[] values) + public SKColorSpaceXyz (ReadOnlySpan values) { - if (values == null) - throw new ArgumentNullException (nameof (values)); if (values.Length != 9) - throw new ArgumentException ("The matrix array must have a length of 9.", nameof (values)); + throw new ArgumentException ("The values must have a length of 9.", nameof (values)); fM00 = values[0]; fM01 = values[1]; @@ -261,22 +314,43 @@ public float[] Values { fM10, fM11, fM12, fM20, fM21, fM22, }; - set { - if (value.Length != 9) - throw new ArgumentException ("The matrix array must have a length of 9.", nameof (value)); + set => SetValues (new ReadOnlySpan (value)); + } - fM00 = value[0]; - fM01 = value[1]; - fM02 = value[2]; + public readonly void GetValues (Span values) + { + if (values.Length != 9) + throw new ArgumentException ("The values must have a length of 9.", nameof(values)); - fM10 = value[3]; - fM11 = value[4]; - fM12 = value[5]; + values[0] = fM00; + values[1] = fM01; + values[2] = fM02; - fM20 = value[6]; - fM21 = value[7]; - fM22 = value[8]; - } + values[3] = fM10; + values[4] = fM11; + values[5] = fM12; + + values[6] = fM20; + values[7] = fM21; + values[8] = fM22; + } + + public void SetValues (ReadOnlySpan values) + { + if (values.Length != 9) + throw new ArgumentException ("The values must have a length of 9.", nameof(values)); + + fM00 = values[0]; + fM01 = values[1]; + fM02 = values[2]; + + fM10 = values[3]; + fM11 = values[4]; + fM12 = values[5]; + + fM20 = values[6]; + fM21 = values[7]; + fM22 = values[8]; } public readonly float this[int x, int y] { diff --git a/binding/SkiaSharp/SKData.cs b/binding/SkiaSharp/SKData.cs index 698926c61d..58ff869c2c 100644 --- a/binding/SkiaSharp/SKData.cs +++ b/binding/SkiaSharp/SKData.cs @@ -211,6 +211,12 @@ internal static SKData FromCString (string str) return SKData.CreateCopy (bytes, (ulong)(bytes.Length + 1)); // + 1 for the terminating char } + internal static SKData FromCString (ReadOnlySpan str) + { + var bytes = Encoding.ASCII.GetBytes (str); + return SKData.CreateCopy (bytes, (ulong)(bytes.Length + 1)); // + 1 for the terminating char + } + // Subset public SKData Subset (ulong offset, ulong length) diff --git a/binding/SkiaSharp/SKFont.cs b/binding/SkiaSharp/SKFont.cs index fb49e85f4e..204407b336 100644 --- a/binding/SkiaSharp/SKFont.cs +++ b/binding/SkiaSharp/SKFont.cs @@ -232,7 +232,10 @@ public bool ContainsGlyphs (IntPtr text, int length, SKTextEncoding encoding) => ContainsGlyphs (GetGlyphs (text, length, encoding)); private bool ContainsGlyphs (ushort[] glyphs) => - Array.IndexOf (glyphs, (ushort)0) == -1; + ContainsGlyphs (new ReadOnlySpan (glyphs)); + + private bool ContainsGlyphs (ReadOnlySpan glyphs) => + glyphs.IndexOf ((ushort)0) == -1; // CountGlyphs diff --git a/binding/SkiaSharp/SKMaskFilter.cs b/binding/SkiaSharp/SKMaskFilter.cs index 012dad4c8d..1504996634 100644 --- a/binding/SkiaSharp/SKMaskFilter.cs +++ b/binding/SkiaSharp/SKMaskFilter.cs @@ -41,10 +41,8 @@ public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma, bool return GetObject (SkiaApi.sk_maskfilter_new_blur_with_flags (blurStyle, sigma, respectCTM)); } - public static SKMaskFilter CreateTable (byte[] table) + public static SKMaskFilter CreateTable (ReadOnlySpan table) { - if (table == null) - throw new ArgumentNullException (nameof (table)); if (table.Length != TableMaxLength) throw new ArgumentException ("Table must have a length of {SKColorTable.MaxLength}.", nameof (table)); fixed (byte* t = table) { diff --git a/binding/SkiaSharp/SKMatrix.cs b/binding/SkiaSharp/SKMatrix.cs index 836b58a15e..3be6598986 100644 --- a/binding/SkiaSharp/SKMatrix.cs +++ b/binding/SkiaSharp/SKMatrix.cs @@ -27,12 +27,10 @@ private class Indices public const int Count = 9; } - public SKMatrix (float[] values) + public SKMatrix (ReadOnlySpan values) { - if (values == null) - throw new ArgumentNullException (nameof (values)); if (values.Length != Indices.Count) - throw new ArgumentException ($"The matrix array must have a length of {Indices.Count}.", nameof (values)); + throw new ArgumentException ($"The values must have a length of {Indices.Count}.", nameof (values)); scaleX = values[Indices.ScaleX]; skewX = values[Indices.SkewX]; @@ -74,32 +72,13 @@ public float[] Values { skewY, scaleY, transY, persp0, persp1, persp2 }; - set { - if (value == null) - throw new ArgumentNullException (nameof (Values)); - if (value.Length != Indices.Count) - throw new ArgumentException ($"The matrix array must have a length of {Indices.Count}.", nameof (Values)); - - scaleX = value[Indices.ScaleX]; - skewX = value[Indices.SkewX]; - transX = value[Indices.TransX]; - - skewY = value[Indices.SkewY]; - scaleY = value[Indices.ScaleY]; - transY = value[Indices.TransY]; - - persp0 = value[Indices.Persp0]; - persp1 = value[Indices.Persp1]; - persp2 = value[Indices.Persp2]; - } + set => SetValues (new ReadOnlySpan (value)); } - public readonly void GetValues (float[] values) + public readonly void GetValues (Span values) { - if (values == null) - throw new ArgumentNullException (nameof (values)); if (values.Length != Indices.Count) - throw new ArgumentException ($"The matrix array must have a length of {Indices.Count}.", nameof (values)); + throw new ArgumentException ($"The values must have a length of {Indices.Count}.", nameof (values)); values[Indices.ScaleX] = scaleX; values[Indices.SkewX] = skewX; @@ -114,6 +93,24 @@ public readonly void GetValues (float[] values) values[Indices.Persp2] = persp2; } + public void SetValues (ReadOnlySpan values) + { + if (values.Length != Indices.Count) + throw new ArgumentException ($"The values must have a length of {Indices.Count}.", nameof(values)); + + scaleX = values[Indices.ScaleX]; + skewX = values[Indices.SkewX]; + transX = values[Indices.TransX]; + + skewY = values[Indices.SkewY]; + scaleY = values[Indices.ScaleY]; + transY = values[Indices.TransY]; + + persp0 = values[Indices.Persp0]; + persp1 = values[Indices.Persp1]; + persp2 = values[Indices.Persp2]; + } + // Create* public static SKMatrix CreateIdentity () => @@ -399,7 +396,7 @@ public readonly void MapVectors (SKPoint[] result, SKPoint[] vectors) } } - public readonly SKPoint[] MapVectors (SKPoint[] vectors) + public readonly SKPoint[] MapVectors (ReadOnlySpan vectors) { if (vectors == null) throw new ArgumentNullException (nameof (vectors)); diff --git a/binding/SkiaSharp/SKPMColor.cs b/binding/SkiaSharp/SKPMColor.cs index 4be0398ae4..a137f841b3 100644 --- a/binding/SkiaSharp/SKPMColor.cs +++ b/binding/SkiaSharp/SKPMColor.cs @@ -23,7 +23,7 @@ public SKPMColor (uint value) public static SKPMColor PreMultiply (SKColor color) => SkiaApi.sk_color_premultiply ((uint)color); - public static SKPMColor[] PreMultiply (SKColor[] colors) + public static SKPMColor[] PreMultiply (ReadOnlySpan colors) { var pmcolors = new SKPMColor[colors.Length]; fixed (SKColor* c = colors) @@ -33,12 +33,22 @@ public static SKPMColor[] PreMultiply (SKColor[] colors) return pmcolors; } + public static void PreMultiply (Span pmcolors, ReadOnlySpan colors) + { + if (pmcolors.Length != colors.Length) + throw new ArgumentException ("The length of pmcolors must be the same as the length of colors.", nameof (pmcolors)); + fixed (SKColor* c = colors) + fixed (SKPMColor* pm = pmcolors) { + SkiaApi.sk_color_premultiply_array ((uint*)c, colors.Length, (uint*)pm); + } + } + // UnPreMultiply public static SKColor UnPreMultiply (SKPMColor pmcolor) => SkiaApi.sk_color_unpremultiply ((uint)pmcolor); - public static SKColor[] UnPreMultiply (SKPMColor[] pmcolors) + public static SKColor[] UnPreMultiply (ReadOnlySpan pmcolors) { var colors = new SKColor[pmcolors.Length]; fixed (SKColor* c = colors) @@ -48,6 +58,16 @@ public static SKColor[] UnPreMultiply (SKPMColor[] pmcolors) return colors; } + public static void UnPreMultiply (Span colors, ReadOnlySpan pmcolors) + { + if (colors.Length != pmcolors.Length) + throw new ArgumentException ("The length of colors must be the same as the length of pmcolors.", nameof (colors)); + fixed (SKColor* c = colors) + fixed (SKPMColor* pm = pmcolors) { + SkiaApi.sk_color_unpremultiply_array ((uint*)pm, pmcolors.Length, (uint*)c); + } + } + public static explicit operator SKPMColor (SKColor color) => SKPMColor.PreMultiply (color); diff --git a/binding/SkiaSharp/SKPath.cs b/binding/SkiaSharp/SKPath.cs index a551595f6a..823c5741b4 100644 --- a/binding/SkiaSharp/SKPath.cs +++ b/binding/SkiaSharp/SKPath.cs @@ -122,13 +122,26 @@ public SKRoundRect GetRoundRect () public SKPoint[] GetLine () { - var temp = new SKPoint[2]; - fixed (SKPoint* t = temp) { - var result = SkiaApi.sk_path_is_line (Handle, t); + Span temp = stackalloc SKPoint[2]; + if (TryGetLine (temp)) { + return temp.ToArray (); + } else { + return null; + } + } + + public bool TryGetLine (Span points) + { + if (points.Length != 2) + return false; + + fixed (SKPoint* p = points) { + var result = SkiaApi.sk_path_is_line (Handle, p); if (result) { - return temp; + return true; } else { - return null; + points.Clear (); + return false; } } } @@ -168,8 +181,10 @@ public SKPoint[] GetPoints (int max) return points; } - public int GetPoints (SKPoint[] points, int max) + public int GetPoints (Span points, int max) { + if (points == null) + throw new ArgumentNullException (nameof (points)); fixed (SKPoint* p = points) { return SkiaApi.sk_path_get_points (Handle, p, max); } @@ -509,10 +524,10 @@ public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float var quadCount = 1 << pow2; var ptCount = 2 * quadCount + 1; pts = new SKPoint[ptCount]; - return ConvertConicToQuads (p0, p1, p2, w, pts, pow2); + return ConvertConicToQuads (p0, p1, p2, w, new Span (pts), pow2); } - public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, SKPoint[] pts, int pow2) + public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, Span pts, int pow2) { if (pts == null) throw new ArgumentNullException (nameof (pts)); diff --git a/binding/SkiaSharp/SKRuntimeEffect.cs b/binding/SkiaSharp/SKRuntimeEffect.cs index 9a26537938..71e9c0251a 100644 --- a/binding/SkiaSharp/SKRuntimeEffect.cs +++ b/binding/SkiaSharp/SKRuntimeEffect.cs @@ -19,7 +19,7 @@ internal SKRuntimeEffect (IntPtr handle, bool owns) // Create* - public static SKRuntimeEffect CreateShader (string sksl, out string errors) + public static SKRuntimeEffect CreateShader (ReadOnlySpan sksl, out string errors) { using var s = new SKString (sksl); using var errorString = new SKString (); @@ -30,7 +30,7 @@ public static SKRuntimeEffect CreateShader (string sksl, out string errors) return effect; } - public static SKRuntimeEffect CreateColorFilter (string sksl, out string errors) + public static SKRuntimeEffect CreateColorFilter (ReadOnlySpan sksl, out string errors) { using var s = new SKString (sksl); using var errorString = new SKString (); @@ -54,14 +54,14 @@ public static SKRuntimeEffect CreateBlender (string sksl, out string errors) // Build* - public static SKRuntimeShaderBuilder BuildShader (string sksl) + public static SKRuntimeShaderBuilder BuildShader (ReadOnlySpan sksl) { var effect = CreateShader (sksl, out var errors); ValidateResult (effect, errors); return new SKRuntimeShaderBuilder (effect); } - public static SKRuntimeColorFilterBuilder BuildColorFilter (string sksl) + public static SKRuntimeColorFilterBuilder BuildColorFilter (ReadOnlySpan sksl) { var effect = CreateColorFilter (sksl, out var errors); ValidateResult (effect, errors); diff --git a/binding/SkiaSharp/SKShader.cs b/binding/SkiaSharp/SKShader.cs index 8f1e9cb6cb..d6a9da35e9 100644 --- a/binding/SkiaSharp/SKShader.cs +++ b/binding/SkiaSharp/SKShader.cs @@ -119,10 +119,10 @@ public static SKShader CreatePicture (SKPicture src, SKShaderTileMode tmx, SKSha // CreateLinearGradient - public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor[] colors, SKShaderTileMode mode) => + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, SKShaderTileMode mode) => CreateLinearGradient (start, end, colors, null, mode); - public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor[] colors, float[] colorPos, SKShaderTileMode mode) + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -136,7 +136,7 @@ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor } } - public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor[] colors, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -150,10 +150,10 @@ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor } } - public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode mode) => + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, SKColorSpace colorspace, SKShaderTileMode mode) => CreateLinearGradient (start, end, colors, colorspace, null, mode); - public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode) + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -167,7 +167,7 @@ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor } } - public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -183,10 +183,10 @@ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor // CreateRadialGradient - public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, SKShaderTileMode mode) => + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, SKShaderTileMode mode) => CreateRadialGradient (center, radius, colors, null, mode); - public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode) + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -199,7 +199,7 @@ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKCol } } - public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -212,10 +212,10 @@ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKCol } } - public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode mode) => + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, SKColorSpace colorspace, SKShaderTileMode mode) => CreateRadialGradient (center, radius, colors, colorspace, null, mode); - public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode) + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -228,7 +228,7 @@ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKCol } } - public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -243,19 +243,19 @@ public static SKShader CreateRadialGradient (SKPoint center, float radius, SKCol // CreateSweepGradient - public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors) => + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors) => CreateSweepGradient (center, colors, null, SKShaderTileMode.Clamp, 0, 360); - public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos) => + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, ReadOnlySpan colorPos) => CreateSweepGradient (center, colors, colorPos, SKShaderTileMode.Clamp, 0, 360); - public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos, SKMatrix localMatrix) => + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, ReadOnlySpan colorPos, SKMatrix localMatrix) => CreateSweepGradient (center, colors, colorPos, SKShaderTileMode.Clamp, 0, 360, localMatrix); - public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, SKShaderTileMode tileMode, float startAngle, float endAngle) => + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKShaderTileMode tileMode, float startAngle, float endAngle) => CreateSweepGradient (center, colors, null, tileMode, startAngle, endAngle); - public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle) + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -268,7 +268,7 @@ public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, fl } } - public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle, SKMatrix localMatrix) + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle, SKMatrix localMatrix) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -281,19 +281,19 @@ public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, fl } } - public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace) => + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace) => CreateSweepGradient (center, colors, colorspace, null, SKShaderTileMode.Clamp, 0, 360); - public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos) => + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos) => CreateSweepGradient (center, colors, colorspace, colorPos, SKShaderTileMode.Clamp, 0, 360); - public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKMatrix localMatrix) => + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKMatrix localMatrix) => CreateSweepGradient (center, colors, colorspace, colorPos, SKShaderTileMode.Clamp, 0, 360, localMatrix); - public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode tileMode, float startAngle, float endAngle) => + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, SKShaderTileMode tileMode, float startAngle, float endAngle) => CreateSweepGradient (center, colors, colorspace, null, tileMode, startAngle, endAngle); - public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle) + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -306,7 +306,7 @@ public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, S } } - public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle, SKMatrix localMatrix) + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle, SKMatrix localMatrix) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -321,10 +321,10 @@ public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, S // CreateTwoPointConicalGradient - public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColor[] colors, SKShaderTileMode mode) => + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, SKShaderTileMode mode) => CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors, null, mode); - public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode) + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -337,7 +337,7 @@ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float start } } - public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -350,10 +350,10 @@ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float start } } - public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode mode) => + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, SKColorSpace colorspace, SKShaderTileMode mode) => CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors, colorspace, null, mode); - public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode) + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) throw new ArgumentNullException (nameof (colors)); @@ -366,7 +366,7 @@ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float start } } - public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) throw new ArgumentNullException (nameof (colors)); diff --git a/binding/SkiaSharp/SKStream.cs b/binding/SkiaSharp/SKStream.cs index af0191695e..3912d90492 100644 --- a/binding/SkiaSharp/SKStream.cs +++ b/binding/SkiaSharp/SKStream.cs @@ -11,7 +11,7 @@ internal SKStream (IntPtr handle, bool owns) : base (handle, owns) { } - + public bool IsAtEnd { get { return SkiaApi.sk_stream_is_at_end (Handle); @@ -124,6 +124,13 @@ public int Read (byte[] buffer, int size) } } + public int Read (Span buffer) + { + fixed (byte* b = buffer) { + return Read ((IntPtr)b, buffer.Length); + } + } + public int Read (IntPtr buffer, int size) { return (int)SkiaApi.sk_stream_read (Handle, (void*)buffer, (IntPtr)size); @@ -175,7 +182,7 @@ public int Position { get { return (int)SkiaApi.sk_stream_get_position (Handle); } - set { + set { Seek (value); } } @@ -378,7 +385,7 @@ internal SKWStream (IntPtr handle, bool owns) : base (handle, owns) { } - + public virtual int BytesWritten { get { return (int)SkiaApi.sk_wstream_bytes_written (Handle); @@ -392,6 +399,13 @@ public virtual bool Write (byte[] buffer, int size) } } + public virtual bool Write (ReadOnlySpan buffer) + { + fixed (byte* b = buffer) { + return SkiaApi.sk_wstream_write (Handle, (void*)b, (IntPtr)buffer.Length); + } + } + public bool NewLine () { return SkiaApi.sk_wstream_newline (Handle); diff --git a/binding/SkiaSharp/SKString.cs b/binding/SkiaSharp/SKString.cs index b48a84f23f..5c23a46e8b 100644 --- a/binding/SkiaSharp/SKString.cs +++ b/binding/SkiaSharp/SKString.cs @@ -19,32 +19,37 @@ public SKString () throw new InvalidOperationException ("Unable to create a new SKString instance."); } } - - public SKString (byte [] src, long length) + + public SKString (ReadOnlySpan src, long length) : base (CreateCopy (src, length), true) { if (Handle == IntPtr.Zero) { throw new InvalidOperationException ("Unable to copy the SKString instance."); } } - - private static IntPtr CreateCopy (byte [] src, long length) + + private static IntPtr CreateCopy (ReadOnlySpan src, long length) { fixed (byte* s = src) { return SkiaApi.sk_string_new_with_copy (s, (IntPtr)length); } } - public SKString (byte [] src) + public SKString (ReadOnlySpan src) : this (src, src.Length) { } - + public SKString (string str) - : this (StringUtilities.GetEncodedText (str, SKTextEncoding.Utf8)) + : this (StringUtilities.GetEncodedText (str, SKTextEncoding.Utf8).AsSpan ()) + { + } + + public SKString (ReadOnlySpan str) + : this (StringUtilities.GetEncodedText (str, SKTextEncoding.Utf16).AsSpan ()) { } - + public override string ToString () { var cstr = SkiaApi.sk_string_get_c_str (Handle); @@ -56,7 +61,7 @@ public static explicit operator string (SKString skString) { return skString.ToString (); } - + internal static SKString Create (string str) { if (str == null) { @@ -65,6 +70,14 @@ internal static SKString Create (string str) return new SKString (str); } + internal static SKString Create (ReadOnlySpan str) + { + if (str == null) { + return null; + } + return new SKString (str); + } + protected override void Dispose (bool disposing) => base.Dispose (disposing); diff --git a/binding/SkiaSharp/SKVertices.cs b/binding/SkiaSharp/SKVertices.cs index c50d33d919..75f6325b2e 100644 --- a/binding/SkiaSharp/SKVertices.cs +++ b/binding/SkiaSharp/SKVertices.cs @@ -22,17 +22,17 @@ protected override void Dispose (bool disposing) => void ISKNonVirtualReferenceCounted.UnreferenceNative () => SkiaApi.sk_vertices_unref (Handle); - public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SKColor[] colors) + public static SKVertices CreateCopy (SKVertexMode vmode, ReadOnlySpan positions, ReadOnlySpan colors) { return CreateCopy (vmode, positions, null, colors, null); } - public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SKPoint[] texs, SKColor[] colors) + public static SKVertices CreateCopy (SKVertexMode vmode, ReadOnlySpan positions, ReadOnlySpan texs, ReadOnlySpan colors) { return CreateCopy (vmode, positions, texs, colors, null); } - public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SKPoint[] texs, SKColor[] colors, UInt16[] indices) + public static SKVertices CreateCopy (SKVertexMode vmode, ReadOnlySpan positions, ReadOnlySpan texs, ReadOnlySpan colors, ReadOnlySpan indices) { if (positions == null) throw new ArgumentNullException (nameof (positions)); @@ -43,7 +43,7 @@ public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SK throw new ArgumentException ("The number of colors must match the number of vertices.", nameof (colors)); var vertexCount = positions.Length; - var indexCount = indices?.Length ?? 0; + var indexCount = indices.Length; fixed (SKPoint* p = positions) fixed (SKPoint* t = texs) From c87b9fa313b664c94a87ca61cab0c9eaf766f984 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Fri, 10 Nov 2023 03:49:17 -0500 Subject: [PATCH 04/24] Remove some unnecessary null checks. The length checks immediately following the null checks accomplish the same goal. --- binding/SkiaSharp/SKMatrix44.cs | 6 ------ 1 file changed, 6 deletions(-) diff --git a/binding/SkiaSharp/SKMatrix44.cs b/binding/SkiaSharp/SKMatrix44.cs index 8c44538d4a..8bdebfb46a 100644 --- a/binding/SkiaSharp/SKMatrix44.cs +++ b/binding/SkiaSharp/SKMatrix44.cs @@ -268,8 +268,6 @@ internal float[] MapScalars (float x, float y, float z, float w) internal float[] MapScalars (ReadOnlySpan srcVector4) { - if (srcVector4 == null) - throw new ArgumentNullException (nameof (srcVector4)); if (srcVector4.Length != 4) throw new ArgumentException ("The source vector array must be 4 entries.", nameof (srcVector4)); @@ -280,12 +278,8 @@ internal float[] MapScalars (ReadOnlySpan srcVector4) internal void MapScalars (ReadOnlySpan srcVector4, Span dstVector4) { - if (srcVector4 == null) - throw new ArgumentNullException (nameof (srcVector4)); if (srcVector4.Length != 4) throw new ArgumentException ("The source vector array must be 4 entries.", nameof (srcVector4)); - if (dstVector4 == null) - throw new ArgumentNullException (nameof (dstVector4)); if (dstVector4.Length != 4) throw new ArgumentException ("The destination vector array must be 4 entries.", nameof (dstVector4)); From 8d4bf7fcf09b44a4999445f73a937dc06755ab47 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Wed, 6 Nov 2024 17:49:45 -0500 Subject: [PATCH 05/24] Fix duplicate SetRectRadii overloads --- binding/SkiaSharp/SKRoundRect.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding/SkiaSharp/SKRoundRect.cs b/binding/SkiaSharp/SKRoundRect.cs index bee09fe7f0..67f8794da4 100644 --- a/binding/SkiaSharp/SKRoundRect.cs +++ b/binding/SkiaSharp/SKRoundRect.cs @@ -118,7 +118,7 @@ public void SetNinePatch (SKRect rect, float leftRadius, float topRadius, float SkiaApi.sk_rrect_set_nine_patch (Handle, &rect, leftRadius, topRadius, rightRadius, bottomRadius); } - public void SetRectRadii (SKRect rect, ReadOnlySpan radii) + public void SetRectRadii (SKRect rect, SKPoint[] radii) { if (radii == null) throw new ArgumentNullException (nameof (radii)); From 8f77fcc8d9fffa16225347bf45e5b20dc7204aa9 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Fri, 10 Nov 2023 03:52:34 -0500 Subject: [PATCH 06/24] Swap out `new T[0]` for `Array.Empty ()` --- binding/SkiaSharp/SKFont.cs | 24 +++++++++---------- binding/SkiaSharp/Util.cs | 4 ++-- .../SkiaSharp.HarfBuzz/SKShaper.cs | 6 ++--- 3 files changed, 17 insertions(+), 17 deletions(-) diff --git a/binding/SkiaSharp/SKFont.cs b/binding/SkiaSharp/SKFont.cs index 204407b336..73b3250c88 100644 --- a/binding/SkiaSharp/SKFont.cs +++ b/binding/SkiaSharp/SKFont.cs @@ -188,11 +188,11 @@ public void GetGlyphs (IntPtr text, int length, SKTextEncoding encoding, Span (); var n = CountGlyphs (text, length, encoding); if (n <= 0) - return new ushort[0]; + return Array.Empty (); var glyphs = new ushort[n]; GetGlyphs (text, length, encoding, glyphs); @@ -436,11 +436,11 @@ public void GetGlyphPositions (IntPtr text, int length, SKTextEncoding encoding, internal SKPoint[] GetGlyphPositions (void* text, int length, SKTextEncoding encoding, SKPoint origin) { if (!ValidateTextArgs (text, length, encoding)) - return new SKPoint[0]; + return Array.Empty (); var n = CountGlyphs (text, length, encoding); if (n <= 0) - return new SKPoint[0]; + return Array.Empty (); var positions = new SKPoint[n]; GetGlyphPositions (text, length, encoding, positions, origin); @@ -526,11 +526,11 @@ public void GetGlyphOffsets (IntPtr text, int length, SKTextEncoding encoding, S internal float[] GetGlyphOffsets (void* text, int length, SKTextEncoding encoding, float origin) { if (!ValidateTextArgs (text, length, encoding)) - return new float[0]; + return Array.Empty (); var n = CountGlyphs (text, length, encoding); if (n <= 0) - return new float[0]; + return Array.Empty (); var offsets = new float[n]; GetGlyphOffsets (text, length, encoding, offsets, origin); @@ -636,11 +636,11 @@ public void GetGlyphWidths (IntPtr text, int length, SKTextEncoding encoding, Sp internal float[] GetGlyphWidths (void* text, int length, SKTextEncoding encoding, SKPaint paint) { if (!ValidateTextArgs (text, length, encoding)) - return new float[0]; + return Array.Empty (); var n = CountGlyphs (text, length, encoding); if (n <= 0) - return new float[0]; + return Array.Empty (); var widths = new float[n]; GetGlyphWidths (text, length, encoding, widths, Span.Empty, paint); @@ -650,14 +650,14 @@ internal float[] GetGlyphWidths (void* text, int length, SKTextEncoding encoding internal float[] GetGlyphWidths (void* text, int length, SKTextEncoding encoding, out SKRect[] bounds, SKPaint paint) { if (!ValidateTextArgs (text, length, encoding)) { - bounds = new SKRect[0]; - return new float[0]; + bounds = Array.Empty (); + return Array.Empty (); } var n = CountGlyphs (text, length, encoding); if (n <= 0) { - bounds = new SKRect[0]; - return new float[0]; + bounds = Array.Empty (); + return Array.Empty (); } bounds = new SKRect[n]; diff --git a/binding/SkiaSharp/Util.cs b/binding/SkiaSharp/Util.cs index 3846d58dcb..67a1a9597f 100644 --- a/binding/SkiaSharp/Util.cs +++ b/binding/SkiaSharp/Util.cs @@ -45,12 +45,12 @@ internal static bool NearlyEqual (float a, float b, float tolerance) => internal static byte[] GetBytes (this Encoding encoding, ReadOnlySpan text) { if (text.Length == 0) - return new byte[0]; + return Array.Empty (); fixed (char* t = text) { var byteCount = encoding.GetByteCount (t, text.Length); if (byteCount == 0) - return new byte[0]; + return Array.Empty (); var bytes = new byte[byteCount]; fixed (byte* b = bytes) { diff --git a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/SKShaper.cs b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/SKShaper.cs index ae6998dd78..b318bbced3 100644 --- a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/SKShaper.cs +++ b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/SKShaper.cs @@ -156,9 +156,9 @@ public class Result { public Result() { - Codepoints = new uint[0]; - Clusters = new uint[0]; - Points = new SKPoint[0]; + Codepoints = Array.Empty(); + Clusters = Array.Empty(); + Points = Array.Empty(); Width = 0f; } From 8428942fd0ebc64190a6a12a6187a1db72691c7b Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Fri, 10 Nov 2023 03:53:36 -0500 Subject: [PATCH 07/24] Fix apparent memory leak when drawing vertices --- binding/SkiaSharp/SKCanvas.cs | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/binding/SkiaSharp/SKCanvas.cs b/binding/SkiaSharp/SKCanvas.cs index efc6a3a673..5160addc6a 100644 --- a/binding/SkiaSharp/SKCanvas.cs +++ b/binding/SkiaSharp/SKCanvas.cs @@ -928,25 +928,25 @@ public SKMatrix44 TotalMatrix44 { public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan colors, SKPaint paint) { - var vert = SKVertices.CreateCopy (vmode, vertices, colors); + using var vert = SKVertices.CreateCopy (vmode, vertices, colors); DrawVertices (vert, SKBlendMode.Modulate, paint); } public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, SKPaint paint) { - var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors); + using var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors); DrawVertices (vert, SKBlendMode.Modulate, paint); } public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, ReadOnlySpan indices, SKPaint paint) { - var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices); + using var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices); DrawVertices (vert, SKBlendMode.Modulate, paint); } public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, SKBlendMode mode, ReadOnlySpan indices, SKPaint paint) { - var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices); + using var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices); DrawVertices (vert, mode, paint); } From 9f6f9ce42f66081f71a878fa32d0aa0a5defbf45 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Fri, 10 Nov 2023 03:53:55 -0500 Subject: [PATCH 08/24] Minor memory improvements --- binding/SkiaSharp/SKRuntimeEffect.cs | 14 ++++++++++---- binding/SkiaSharp/SKTypeface.cs | 21 ++++++--------------- 2 files changed, 16 insertions(+), 19 deletions(-) diff --git a/binding/SkiaSharp/SKRuntimeEffect.cs b/binding/SkiaSharp/SKRuntimeEffect.cs index 71e9c0251a..6f0451e72d 100644 --- a/binding/SkiaSharp/SKRuntimeEffect.cs +++ b/binding/SkiaSharp/SKRuntimeEffect.cs @@ -518,11 +518,17 @@ public static implicit operator SKRuntimeEffectUniform (SKColorF value) => public static implicit operator SKRuntimeEffectUniform (float[][] value) { - var floats = new List (); - foreach (var array in value) { - floats.AddRange (array); + var totalLength = value.Sum (static f => f.Length); + var floats = new float[totalLength]; + + var offset = 0; + foreach (var f in value) + { + Array.Copy (f, 0, floats, offset, f.Length); + offset += f.Length; } - return floats.ToArray (); + + return floats; } public static implicit operator SKRuntimeEffectUniform (SKMatrix value) => value.Values; diff --git a/binding/SkiaSharp/SKTypeface.cs b/binding/SkiaSharp/SKTypeface.cs index 098628cb21..3d28806e02 100644 --- a/binding/SkiaSharp/SKTypeface.cs +++ b/binding/SkiaSharp/SKTypeface.cs @@ -232,23 +232,14 @@ public ushort[] GetGlyphs (ReadOnlySpan codepoints) => public ushort[] GetGlyphs (string text) => GetGlyphs (text.AsSpan ()); - public ushort[] GetGlyphs (ReadOnlySpan text) - { - using var font = ToFont (); - return font.GetGlyphs (text); - } + public ushort[] GetGlyphs (ReadOnlySpan text) => + GetFont ().GetGlyphs (text); - public ushort[] GetGlyphs (ReadOnlySpan text, SKTextEncoding encoding) - { - using var font = ToFont (); - return font.GetGlyphs (text, encoding); - } + public ushort[] GetGlyphs (ReadOnlySpan text, SKTextEncoding encoding) => + GetFont ().GetGlyphs (text, encoding); - public ushort[] GetGlyphs (IntPtr text, int length, SKTextEncoding encoding) - { - using var font = ToFont (); - return font.GetGlyphs (text, length * encoding.GetCharacterByteSize (), encoding); - } + public ushort[] GetGlyphs (IntPtr text, int length, SKTextEncoding encoding) => + GetFont ().GetGlyphs (text, length * encoding.GetCharacterByteSize (), encoding); // ContainsGlyph From a70e287fd277b80cfb13afaddd018861a84fab40 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Mon, 13 Nov 2023 09:30:11 -0500 Subject: [PATCH 09/24] Fix typo --- binding/SkiaSharp/SKString.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding/SkiaSharp/SKString.cs b/binding/SkiaSharp/SKString.cs index 5c23a46e8b..5e50615f1b 100644 --- a/binding/SkiaSharp/SKString.cs +++ b/binding/SkiaSharp/SKString.cs @@ -46,7 +46,7 @@ public SKString (string str) } public SKString (ReadOnlySpan str) - : this (StringUtilities.GetEncodedText (str, SKTextEncoding.Utf16).AsSpan ()) + : this (StringUtilities.GetEncodedText (str, SKTextEncoding.Utf8).AsSpan ()) { } From cc3fe2fcf369bd5b7c22f751dbe1be86df495637 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Mon, 13 Nov 2023 23:59:28 -0500 Subject: [PATCH 10/24] Add ReadOnlySpan overloads to SKShaper.Shape and convert DrawShapedText to use ReadOnlySpan --- .../SkiaSharp.HarfBuzz/CanvasExtensions.cs | 36 +++++++++---------- .../SkiaSharp.HarfBuzz/SKShaper.cs | 18 ++++++++++ 2 files changed, 36 insertions(+), 18 deletions(-) diff --git a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs index 8b39ae75d9..d8d694b651 100644 --- a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs +++ b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs @@ -4,60 +4,60 @@ namespace SkiaSharp.HarfBuzz { public static class CanvasExtensions { - [Obsolete("Use DrawShapedText(string text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] + [Obsolete("Use DrawShapedText(ReadOnlySpan text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] public static void DrawShapedText(this SKCanvas canvas, string text, SKPoint p, SKPaint paint) => - canvas.DrawShapedText(text, p.X, p.Y, paint.TextAlign, paint.GetFont(), paint); + canvas.DrawShapedText(text.AsSpan(), p.X, p.Y, paint.TextAlign, paint.GetFont(), paint); - public static void DrawShapedText(this SKCanvas canvas, string text, SKPoint p, SKFont font, SKPaint paint) => + public static void DrawShapedText(this SKCanvas canvas, ReadOnlySpan text, SKPoint p, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) canvas.DrawShapedText(text, p.X, p.Y, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete - public static void DrawShapedText(this SKCanvas canvas, string text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => + public static void DrawShapedText(this SKCanvas canvas, ReadOnlySpan text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => canvas.DrawShapedText(text, p.X, p.Y, textAlign, font, paint); - [Obsolete("Use DrawShapedText(string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] + [Obsolete("Use DrawShapedText(ReadOnlySpan text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] public static void DrawShapedText(this SKCanvas canvas, string text, float x, float y, SKPaint paint) => - canvas.DrawShapedText(text, x, y, paint.TextAlign, paint.GetFont(), paint); + canvas.DrawShapedText(text.AsSpan(), x, y, paint.TextAlign, paint.GetFont(), paint); - public static void DrawShapedText(this SKCanvas canvas, string text, float x, float y, SKFont font, SKPaint paint) => + public static void DrawShapedText(this SKCanvas canvas, ReadOnlySpan text, float x, float y, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) canvas.DrawShapedText(text, x, y, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete - public static void DrawShapedText(this SKCanvas canvas, string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) + public static void DrawShapedText(this SKCanvas canvas, ReadOnlySpan text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) { - if (string.IsNullOrEmpty(text)) + if (text.IsEmpty) return; using var shaper = new SKShaper(font.Typeface); canvas.DrawShapedText(shaper, text, x, y, textAlign, font, paint); } - [Obsolete("Use DrawShapedText(SKShaper shaper, string text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] + [Obsolete("Use DrawShapedText(SKShaper shaper, ReadOnlySpan text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, SKPoint p, SKPaint paint) => - canvas.DrawShapedText(shaper, text, p.X, p.Y, paint.TextAlign, paint.GetFont(), paint); + canvas.DrawShapedText(shaper, text.AsSpan(), p.X, p.Y, paint.TextAlign, paint.GetFont(), paint); - public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, SKPoint p, SKFont font, SKPaint paint) => + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, ReadOnlySpan text, SKPoint p, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) canvas.DrawShapedText(shaper, text, p.X, p.Y, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete - public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, ReadOnlySpan text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => canvas.DrawShapedText(shaper, text, p.X, p.Y, textAlign, font, paint); - [Obsolete("Use DrawShapedText(SKShaper shaper, string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] + [Obsolete("Use DrawShapedText(SKShaper shaper, ReadOnlySpan text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, float x, float y, SKPaint paint) => - canvas.DrawShapedText(shaper, text, x, y, paint.TextAlign, paint.GetFont(), paint); + canvas.DrawShapedText(shaper, text.AsSpan(), x, y, paint.TextAlign, paint.GetFont(), paint); - public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, float x, float y, SKFont font, SKPaint paint) => + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, ReadOnlySpan text, float x, float y, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) canvas.DrawShapedText(shaper, text, x, y, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete - public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, ReadOnlySpan text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) { - if (string.IsNullOrEmpty(text)) + if (text.IsEmpty) return; if (canvas == null) diff --git a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/SKShaper.cs b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/SKShaper.cs index b318bbced3..6db9f2ddf9 100644 --- a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/SKShaper.cs +++ b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/SKShaper.cs @@ -152,6 +152,24 @@ public Result Shape(string text, float xOffset, float yOffset, SKFont font) return Shape(buffer, xOffset, yOffset, font); } + public Result Shape(ReadOnlySpan text, SKFont font) => + Shape(text, 0, 0, font); + + public Result Shape(ReadOnlySpan text, float xOffset, float yOffset, SKFont font) + { + if (text.IsEmpty) + { + return new Result(); + } + + using var buffer = new Buffer(); + buffer.AddUtf16(text); + + buffer.GuessSegmentProperties(); + + return Shape(buffer, xOffset, yOffset, font); + } + public class Result { public Result() From d4985d3c1b200144b8886502caf25e5448ac832c Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Tue, 14 Nov 2023 00:00:35 -0500 Subject: [PATCH 11/24] Add tests for SKShaper.Shape with ReadOnlySpan --- tests/Tests/SkiaSharp/SKShaperTest.cs | 41 ++++++++++++++++++++++++++- 1 file changed, 40 insertions(+), 1 deletion(-) diff --git a/tests/Tests/SkiaSharp/SKShaperTest.cs b/tests/Tests/SkiaSharp/SKShaperTest.cs index 7f14de8a27..2ad0d2bb5b 100644 --- a/tests/Tests/SkiaSharp/SKShaperTest.cs +++ b/tests/Tests/SkiaSharp/SKShaperTest.cs @@ -1,4 +1,5 @@ -using System.IO; +using System; +using System.IO; using System.Linq; using System.Runtime.InteropServices; using HarfBuzzSharp; @@ -54,6 +55,25 @@ public void CorrectlyShapesArabicScriptAtAnOffset() } } + [SkippableFact] + public void CorrectlyShapesArabicScriptAtAnOffsetWithSpan() + { + var clusters = new uint[] { 2, 1, 0 }; + var codepoints = new uint[] { 629, 668, 891 }; + var points = new SKPoint[] { new SKPoint(100, 200), new SKPoint(128.375f, 200), new SKPoint(142.125f, 200) }; + + using (var tf = SKTypeface.FromFile(Path.Combine(PathToFonts, "content-font.ttf"))) + using (var shaper = new SKShaper(tf)) + using (var font = new SKFont { Size = 64, Typeface = tf }) + { + var result = shaper.Shape("متن".AsSpan(), 100, 200, font); + + Assert.Equal(clusters, result.Clusters); + Assert.Equal(codepoints, result.Codepoints); + Assert.Equal(points, result.Points); + } + } + [SkippableFact] public void CorrectlyShapesArabicScript() { @@ -73,6 +93,25 @@ public void CorrectlyShapesArabicScript() } } + [SkippableFact] + public void CorrectlyShapesArabicScriptWithSpan() + { + var clusters = new uint[] { 2, 1, 0 }; + var codepoints = new uint[] { 629, 668, 891 }; + var points = new SKPoint[] { new SKPoint(0, 0), new SKPoint(28.375f, 0), new SKPoint(42.125f, 0) }; + + using (var tf = SKTypeface.FromFile(Path.Combine(PathToFonts, "content-font.ttf"))) + using (var shaper = new SKShaper(tf)) + using (var font = new SKFont { Size = 64, Typeface = tf }) + { + var result = shaper.Shape("متن".AsSpan(), font); + + Assert.Equal(clusters, result.Clusters); + Assert.Equal(codepoints, result.Codepoints); + Assert.Equal(points, result.Points); + } + } + [SkippableFact] public void CanCreateFaceShaperFromTypeface() { From 47926c859eeb74a8aa1b3bad3f4850a3f4e542a9 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Tue, 14 Nov 2023 01:41:52 -0500 Subject: [PATCH 12/24] Minor adjustments --- binding/SkiaSharp/SKCodec.cs | 4 +--- binding/SkiaSharp/SKPath.cs | 2 +- 2 files changed, 2 insertions(+), 4 deletions(-) diff --git a/binding/SkiaSharp/SKCodec.cs b/binding/SkiaSharp/SKCodec.cs index 9065a017e1..51c3ad324b 100644 --- a/binding/SkiaSharp/SKCodec.cs +++ b/binding/SkiaSharp/SKCodec.cs @@ -105,9 +105,7 @@ public SKCodecResult GetPixels (SKImageInfo info, byte[] pixels) if (pixels == null) throw new ArgumentNullException (nameof (pixels)); - fixed (byte* p = pixels) { - return GetPixels (info, (IntPtr)p, info.RowBytes, SKCodecOptions.Default); - } + return GetPixels (info, pixels.AsSpan ()); } public SKCodecResult GetPixels (SKImageInfo info, Span pixels) diff --git a/binding/SkiaSharp/SKPath.cs b/binding/SkiaSharp/SKPath.cs index 823c5741b4..700219b370 100644 --- a/binding/SkiaSharp/SKPath.cs +++ b/binding/SkiaSharp/SKPath.cs @@ -133,7 +133,7 @@ public SKPoint[] GetLine () public bool TryGetLine (Span points) { if (points.Length != 2) - return false; + throw new ArgumentException ("Points must have a length of 2."); fixed (SKPoint* p = points) { var result = SkiaApi.sk_path_is_line (Handle, p); From 535d4e3ba6d45541bb64c1e9150f04645bc7a065 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Tue, 14 Nov 2023 01:42:38 -0500 Subject: [PATCH 13/24] Add some span-array overload comparison tests --- tests/Tests/SkiaSharp/SKColorTest.cs | 24 ++++++++++++++++++++++++ tests/Tests/SkiaSharp/SKPathTest.cs | 15 +++++++++++++++ tests/Tests/SkiaSharp/SKTypefaceTest.cs | 16 +++++++++++++++- 3 files changed, 54 insertions(+), 1 deletion(-) diff --git a/tests/Tests/SkiaSharp/SKColorTest.cs b/tests/Tests/SkiaSharp/SKColorTest.cs index e738a3161f..40b1f6b3f5 100644 --- a/tests/Tests/SkiaSharp/SKColorTest.cs +++ b/tests/Tests/SkiaSharp/SKColorTest.cs @@ -268,5 +268,29 @@ public void CanUnPreultiplyArrays() Assert.Equal(colors, upm); } + + [SkippableFact] + public void PreMultiplySpanMatchesArray() + { + var colors = new SKColor[] { 0x33008200, 0x33008200, 0x33008200, 0x33008200, 0x33008200 }; + + var pm1 = SKPMColor.PreMultiply(colors); + var pm2 = new SKPMColor[colors.Length]; + SKPMColor.PreMultiply(pm2, colors); + + Assert.Equal(pm1, pm2); + } + + [SkippableFact] + public void UnPreMultiplySpanMatchesArray() + { + var pmcolors = new SKPMColor[] { 0x33001A00, 0x33001A00, 0x33001A00, 0x33001A00, 0x33001A00 }; + + var upm1 = SKPMColor.UnPreMultiply(pmcolors); + var upm2 = new SKColor[pmcolors.Length]; + SKPMColor.UnPreMultiply(upm2, pmcolors); + + Assert.Equal(upm1, upm2); + } } } diff --git a/tests/Tests/SkiaSharp/SKPathTest.cs b/tests/Tests/SkiaSharp/SKPathTest.cs index 8b0fee109c..5dbcea47b1 100644 --- a/tests/Tests/SkiaSharp/SKPathTest.cs +++ b/tests/Tests/SkiaSharp/SKPathTest.cs @@ -397,6 +397,21 @@ public void OvalPathIsOval() } } + [SkippableFact] + public void TryGetLineMatchesGetLine() + { + using (var path = new SKPath()) + { + path.LineTo(new SKPoint(100, 100)); + + var getLine = path.GetLine(); + var tryGetLine = new SKPoint[2]; + path.TryGetLine(tryGetLine); + + Assert.Equal(getLine, tryGetLine); + } + } + [SkippableFact] public void TrimPathEffectWorksInverted() { diff --git a/tests/Tests/SkiaSharp/SKTypefaceTest.cs b/tests/Tests/SkiaSharp/SKTypefaceTest.cs index 18978e0a10..b322e6511e 100644 --- a/tests/Tests/SkiaSharp/SKTypefaceTest.cs +++ b/tests/Tests/SkiaSharp/SKTypefaceTest.cs @@ -495,7 +495,7 @@ public unsafe void FromFamilyReturnsSameObject() public unsafe void FontStyleIsNotTheSame() { var tf = SKTypeface.FromFamilyName(DefaultFontFamily); - + var fs1 = tf.FontStyle; var fs2 = tf.FontStyle; @@ -556,5 +556,19 @@ static IntPtr DoWork() return tf1.Handle; } } + + [SkippableFact] + public void GetKerningPairAdjustmentsSpanMatchesArray() + { + using var tf = SKTypeface.FromFamilyName(DefaultFontFamily); + + var glyphs = new ushort[] { 54, 78, 76, 68, 54, 75, 68, 85, 83 }; + + var adjustments1 = tf.GetKerningPairAdjustments(glyphs); + var adjustments2 = new int[glyphs.Length]; + tf.GetKerningPairAdjustments(adjustments2, glyphs); + + Assert.Equal(adjustments1, adjustments2); + } } } From 175fa0005681eed46c38629609a60e39308cebaf Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Wed, 6 Nov 2024 19:15:06 -0500 Subject: [PATCH 14/24] Convert LINQ to code --- binding/SkiaSharp/SKRuntimeEffect.cs | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/binding/SkiaSharp/SKRuntimeEffect.cs b/binding/SkiaSharp/SKRuntimeEffect.cs index 6f0451e72d..95b1fadff9 100644 --- a/binding/SkiaSharp/SKRuntimeEffect.cs +++ b/binding/SkiaSharp/SKRuntimeEffect.cs @@ -518,7 +518,11 @@ public static implicit operator SKRuntimeEffectUniform (SKColorF value) => public static implicit operator SKRuntimeEffectUniform (float[][] value) { - var totalLength = value.Sum (static f => f.Length); + var totalLength = 0; + foreach (var f in value) { + totalLength += f.Length; + } + var floats = new float[totalLength]; var offset = 0; From 2b32428e3c623b88271f33803957d1d076290bc9 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Wed, 6 Nov 2024 19:52:49 -0500 Subject: [PATCH 15/24] Restore some array overloads & reduce duplicate code between span and array overloads --- binding/SkiaSharp/SKCanvas.cs | 59 ++++++++++++++++++++---- binding/SkiaSharp/SKColorSpaceStructs.cs | 15 ++++++ binding/SkiaSharp/SKData.cs | 6 --- binding/SkiaSharp/SKImage.cs | 6 +++ binding/SkiaSharp/SKMaskFilter.cs | 3 ++ 5 files changed, 74 insertions(+), 15 deletions(-) diff --git a/binding/SkiaSharp/SKCanvas.cs b/binding/SkiaSharp/SKCanvas.cs index 5160addc6a..03fbb35dba 100644 --- a/binding/SkiaSharp/SKCanvas.cs +++ b/binding/SkiaSharp/SKCanvas.cs @@ -749,9 +749,7 @@ public void DrawUrlAnnotation (SKRect rect, SKData value) public SKData DrawUrlAnnotation (SKRect rect, string value) { - var data = SKData.FromCString (value); - DrawUrlAnnotation (rect, data); - return data; + return DrawUrlAnnotation (rect, value.AsSpan ()); } public SKData DrawUrlAnnotation (SKRect rect, ReadOnlySpan value) @@ -768,9 +766,7 @@ public void DrawNamedDestinationAnnotation (SKPoint point, SKData value) public SKData DrawNamedDestinationAnnotation (SKPoint point, string value) { - var data = SKData.FromCString (value); - DrawNamedDestinationAnnotation (point, data); - return data; + return DrawNamedDestinationAnnotation (point, value.AsSpan ()); } public SKData DrawNamedDestinationAnnotation (SKPoint point, ReadOnlySpan value) @@ -787,9 +783,7 @@ public void DrawLinkDestinationAnnotation (SKRect rect, SKData value) public SKData DrawLinkDestinationAnnotation (SKRect rect, string value) { - var data = SKData.FromCString (value); - DrawLinkDestinationAnnotation (rect, data); - return data; + return DrawLinkDestinationAnnotation (rect, value.AsSpan ()); } public SKData DrawLinkDestinationAnnotation (SKRect rect, ReadOnlySpan value) @@ -926,24 +920,44 @@ public SKMatrix44 TotalMatrix44 { // DrawVertices + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKColor[] colors, SKPaint paint) + { + DrawVertices (vmode, vertices.AsSpan (), colors.AsSpan (), paint); + } + public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan colors, SKPaint paint) { using var vert = SKVertices.CreateCopy (vmode, vertices, colors); DrawVertices (vert, SKBlendMode.Modulate, paint); } + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKPaint paint) + { + DrawVertices (vmode, vertices.AsSpan (), texs.AsSpan (), colors.AsSpan (), paint); + } + public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, SKPaint paint) { using var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors); DrawVertices (vert, SKBlendMode.Modulate, paint); } + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, UInt16[] indices, SKPaint paint) + { + DrawVertices (vmode, vertices.AsSpan (), texs.AsSpan (), colors.AsSpan (), indices.AsSpan (), paint); + } + public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, ReadOnlySpan indices, SKPaint paint) { using var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices); DrawVertices (vert, SKBlendMode.Modulate, paint); } + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKBlendMode mode, UInt16[] indices, SKPaint paint) + { + DrawVertices (vmode, vertices.AsSpan (), texs.AsSpan (), colors.AsSpan (), mode, indices.AsSpan (), paint); + } + public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, SKBlendMode mode, ReadOnlySpan indices, SKPaint paint) { using var vert = SKVertices.CreateCopy (vmode, vertices, texs, colors, indices); @@ -984,30 +998,51 @@ public void DrawRoundRectDifference (SKRoundRect outer, SKRoundRect inner, SKPai // DrawAtlas + public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKPaint paint = null) => + DrawAtlas (atlas, sprites.AsSpan (), transforms.AsSpan (), paint); + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, SKPaint paint = null) => #pragma warning disable CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' DrawAtlas (atlas, sprites, transforms, null, SKBlendMode.Dst, paint?.FilterQuality.ToSamplingOptions() ?? SKSamplingOptions.Default, null, paint); #pragma warning restore CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' + public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKSamplingOptions sampling, SKPaint paint = null) => + DrawAtlas (atlas, sprites.AsSpan (), transforms.AsSpan (), sampling, paint); + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, SKSamplingOptions sampling, SKPaint paint = null) => DrawAtlas (atlas, sprites, transforms, null, SKBlendMode.Dst, sampling, null, paint); + public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKPaint paint = null) => + DrawAtlas (atlas, sprites.AsSpan (), transforms.AsSpan (), colors.AsSpan (), mode, paint); + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKPaint paint = null) => #pragma warning disable CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' DrawAtlas (atlas, sprites, transforms, colors, mode, paint?.FilterQuality.ToSamplingOptions() ?? SKSamplingOptions.Default, null, paint); #pragma warning restore CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' + public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKSamplingOptions sampling, SKPaint paint = null) => + DrawAtlas (atlas, sprites.AsSpan (), transforms.AsSpan (), colors.AsSpan (), mode, sampling, paint); + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKSamplingOptions sampling, SKPaint paint = null) => DrawAtlas (atlas, sprites, transforms, colors, mode, sampling, null, paint); + public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKRect cullRect, SKPaint paint = null) => + DrawAtlas (atlas, sprites.AsSpan (), transforms.AsSpan (), colors.AsSpan (), mode, cullRect, paint); + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKRect cullRect, SKPaint paint = null) => #pragma warning disable CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' DrawAtlas (atlas, sprites, transforms, colors, mode, paint?.FilterQuality.ToSamplingOptions() ?? SKSamplingOptions.Default, &cullRect, paint); #pragma warning restore CS0618 // 'SKPaint.FilterQuality' is obsolete: 'Use SKSamplingOptions instead.' + public void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKSamplingOptions sampling, SKRect cullRect, SKPaint paint = null) => + DrawAtlas (atlas, sprites.AsSpan (), transforms.AsSpan (), colors.AsSpan (), mode, sampling, paint); + public void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKSamplingOptions sampling, SKRect cullRect, SKPaint paint = null) => DrawAtlas (atlas, sprites, transforms, colors, mode, sampling, &cullRect, paint); + private void DrawAtlas (SKImage atlas, SKRect[] sprites, SKRotationScaleMatrix[] transforms, SKColor[] colors, SKBlendMode mode, SKSamplingOptions sampling, SKRect* cullRect, SKPaint paint = null) => + DrawAtlas (atlas, sprites.AsSpan (), transforms.AsSpan (), colors.AsSpan (), mode, sampling, cullRect, paint); + private void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpan transforms, ReadOnlySpan colors, SKBlendMode mode, SKSamplingOptions sampling, SKRect* cullRect, SKPaint paint = null) { if (atlas == null) @@ -1031,9 +1066,15 @@ private void DrawAtlas (SKImage atlas, ReadOnlySpan sprites, ReadOnlySpa // DrawPatch + public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKPoint[] texCoords, SKPaint paint) => + DrawPatch (cubics.AsSpan (), colors.AsSpan (), texCoords.AsSpan (), paint); + public void DrawPatch (ReadOnlySpan cubics, ReadOnlySpan colors, ReadOnlySpan texCoords, SKPaint paint) => DrawPatch (cubics, colors, texCoords, SKBlendMode.Modulate, paint); + public void DrawPatch (SKPoint[] cubics, SKColor[] colors, SKPoint[] texCoords, SKBlendMode mode, SKPaint paint) => + DrawPatch (cubics.AsSpan (), colors.AsSpan (), texCoords.AsSpan (), mode, paint); + public void DrawPatch (ReadOnlySpan cubics, ReadOnlySpan colors, ReadOnlySpan texCoords, SKBlendMode mode, SKPaint paint) { if (cubics == null) diff --git a/binding/SkiaSharp/SKColorSpaceStructs.cs b/binding/SkiaSharp/SKColorSpaceStructs.cs index 4c0d63f1e1..945fad28e8 100644 --- a/binding/SkiaSharp/SKColorSpaceStructs.cs +++ b/binding/SkiaSharp/SKColorSpaceStructs.cs @@ -9,6 +9,11 @@ public unsafe partial struct SKColorSpacePrimaries { public static readonly SKColorSpacePrimaries Empty; + public SKColorSpacePrimaries (float[] values) + : this (new ReadOnlySpan (values)) + { + } + public SKColorSpacePrimaries (ReadOnlySpan values) { if (values.Length != 8) @@ -133,6 +138,11 @@ public static SKColorSpaceTransferFn Hlg { public static readonly SKColorSpaceTransferFn Empty; + public SKColorSpaceTransferFn (float[] values) + : this (new ReadOnlySpan (values)) + { + } + public SKColorSpaceTransferFn (ReadOnlySpan values) { if (values.Length != 7) @@ -272,6 +282,11 @@ public SKColorSpaceXyz (float value) fM22 = value; } + public SKColorSpaceXyz (float[] values) + : this (new ReadOnlySpan (values)) + { + } + public SKColorSpaceXyz (ReadOnlySpan values) { if (values.Length != 9) diff --git a/binding/SkiaSharp/SKData.cs b/binding/SkiaSharp/SKData.cs index 58ff869c2c..c1658719fe 100644 --- a/binding/SkiaSharp/SKData.cs +++ b/binding/SkiaSharp/SKData.cs @@ -205,12 +205,6 @@ public static SKData Create (IntPtr address, int length, SKDataReleaseDelegate r return GetObject (SkiaApi.sk_data_new_with_proc ((void*)address, (IntPtr)length, proxy, (void*)ctx)); } - internal static SKData FromCString (string str) - { - var bytes = Encoding.ASCII.GetBytes (str ?? string.Empty); - return SKData.CreateCopy (bytes, (ulong)(bytes.Length + 1)); // + 1 for the terminating char - } - internal static SKData FromCString (ReadOnlySpan str) { var bytes = Encoding.ASCII.GetBytes (str); diff --git a/binding/SkiaSharp/SKImage.cs b/binding/SkiaSharp/SKImage.cs index b23093f229..4a1df885c0 100644 --- a/binding/SkiaSharp/SKImage.cs +++ b/binding/SkiaSharp/SKImage.cs @@ -60,6 +60,12 @@ public static SKImage FromPixelCopy (SKImageInfo info, Stream pixels, int rowByt } } + public static SKImage FromPixelCopy (SKImageInfo info, byte[] pixels) => + FromPixelCopy (info, pixels.AsSpan ()); + + public static SKImage FromPixelCopy (SKImageInfo info, byte[] pixels, int rowBytes) => + FromPixelCopy (info, pixels.AsSpan (), rowBytes); + public static SKImage FromPixelCopy (SKImageInfo info, IntPtr pixels) => FromPixelCopy (info, pixels, info.RowBytes); diff --git a/binding/SkiaSharp/SKMaskFilter.cs b/binding/SkiaSharp/SKMaskFilter.cs index 1504996634..1edcc849b2 100644 --- a/binding/SkiaSharp/SKMaskFilter.cs +++ b/binding/SkiaSharp/SKMaskFilter.cs @@ -41,6 +41,9 @@ public static SKMaskFilter CreateBlur (SKBlurStyle blurStyle, float sigma, bool return GetObject (SkiaApi.sk_maskfilter_new_blur_with_flags (blurStyle, sigma, respectCTM)); } + public static SKMaskFilter CreateTable (byte[] table) => + CreateTable (table.AsSpan ()); + public static SKMaskFilter CreateTable (ReadOnlySpan table) { if (table.Length != TableMaxLength) From 53d4f74dc9b21686e9384e7335486571dfb1a991 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Wed, 6 Nov 2024 22:40:45 -0500 Subject: [PATCH 16/24] Restore more array overloads & add some missing span overloads --- binding/SkiaSharp/SKCanvas.cs | 3 ++ binding/SkiaSharp/SKData.cs | 6 ++++ binding/SkiaSharp/SKMatrix.cs | 52 +++++++++++++++------------- binding/SkiaSharp/SKPathEffect.cs | 3 ++ binding/SkiaSharp/SKRuntimeEffect.cs | 22 ++++++++++-- binding/SkiaSharp/SKString.cs | 10 +----- binding/SkiaSharp/SKVertices.cs | 21 ++++++----- 7 files changed, 73 insertions(+), 44 deletions(-) diff --git a/binding/SkiaSharp/SKCanvas.cs b/binding/SkiaSharp/SKCanvas.cs index 03fbb35dba..bb55b70b38 100644 --- a/binding/SkiaSharp/SKCanvas.cs +++ b/binding/SkiaSharp/SKCanvas.cs @@ -409,6 +409,9 @@ public void DrawPath (SKPath path, SKPaint paint) // DrawPoints + public void DrawPoints (SKPointMode mode, SKPoint[] points, SKPaint paint) => + DrawPoints (mode, points.AsSpan (), paint); + public void DrawPoints (SKPointMode mode, ReadOnlySpan points, SKPaint paint) { if (paint == null) diff --git a/binding/SkiaSharp/SKData.cs b/binding/SkiaSharp/SKData.cs index c1658719fe..eced66a2f5 100644 --- a/binding/SkiaSharp/SKData.cs +++ b/binding/SkiaSharp/SKData.cs @@ -62,9 +62,15 @@ public static SKData CreateCopy (IntPtr bytes, ulong length) return GetObject (SkiaApi.sk_data_new_with_copy ((void*)bytes, (IntPtr)length)); } + public static SKData CreateCopy (byte[] bytes) => + CreateCopy (bytes.AsSpan ()); + public static SKData CreateCopy (ReadOnlySpan bytes) => CreateCopy (bytes, (ulong)bytes.Length); + public static SKData CreateCopy (byte[] bytes, ulong length) => + CreateCopy (bytes.AsSpan (), length); + public static SKData CreateCopy (ReadOnlySpan bytes, ulong length) { fixed (byte* b = bytes) { diff --git a/binding/SkiaSharp/SKMatrix.cs b/binding/SkiaSharp/SKMatrix.cs index 3be6598986..7f9c78ec77 100644 --- a/binding/SkiaSharp/SKMatrix.cs +++ b/binding/SkiaSharp/SKMatrix.cs @@ -27,6 +27,11 @@ private class Indices public const int Count = 9; } + public SKMatrix (float[] values) + : this (new ReadOnlySpan (values)) + { + } + public SKMatrix (ReadOnlySpan values) { if (values.Length != Indices.Count) @@ -75,6 +80,9 @@ public float[] Values { set => SetValues (new ReadOnlySpan (value)); } + public readonly void GetValues (float[] values) => + GetValues (values.AsSpan ()); + public readonly void GetValues (Span values) { if (values.Length != Indices.Count) @@ -316,24 +324,18 @@ public readonly SKPoint MapPoint (float x, float y) return result; } - public readonly void MapPoints (Span result, ReadOnlySpan points) - { - if (result.Length != points.Length) - throw new ArgumentException ("Buffers must be the same size."); - - fixed (SKMatrix* t = &this) - fixed (SKPoint* rp = result) - fixed (SKPoint* pp = points) { - SkiaApi.sk_matrix_map_points (t, rp, pp, result.Length); - } - } - public readonly void MapPoints (SKPoint[] result, SKPoint[] points) { if (result == null) throw new ArgumentNullException (nameof (result)); if (points == null) throw new ArgumentNullException (nameof (points)); + + MapPoints (result.AsSpan (), points.AsSpan ()); + } + + public readonly void MapPoints (Span result, ReadOnlySpan points) + { if (result.Length != points.Length) throw new ArgumentException ("Buffers must be the same size."); @@ -344,7 +346,10 @@ public readonly void MapPoints (SKPoint[] result, SKPoint[] points) } } - public readonly SKPoint[] MapPoints (SKPoint[] points) + public readonly SKPoint[] MapPoints (SKPoint[] points) => + MapPoints (points.AsSpan ()); + + public readonly SKPoint[] MapPoints (ReadOnlySpan points) { if (points == null) throw new ArgumentNullException (nameof (points)); @@ -368,24 +373,18 @@ public readonly SKPoint MapVector (float x, float y) return result; } - public readonly void MapVectors (Span result, ReadOnlySpan vectors) - { - if (result.Length != vectors.Length) - throw new ArgumentException ("Buffers must be the same size."); - - fixed (SKMatrix* t = &this) - fixed (SKPoint* rp = result) - fixed (SKPoint* pp = vectors) { - SkiaApi.sk_matrix_map_vectors (t, rp, pp, result.Length); - } - } - public readonly void MapVectors (SKPoint[] result, SKPoint[] vectors) { if (result == null) throw new ArgumentNullException (nameof (result)); if (vectors == null) throw new ArgumentNullException (nameof (vectors)); + + MapVectors (result.AsSpan (), vectors.AsSpan ()); + } + + public readonly void MapVectors (Span result, ReadOnlySpan vectors) + { if (result.Length != vectors.Length) throw new ArgumentException ("Buffers must be the same size."); @@ -396,6 +395,9 @@ public readonly void MapVectors (SKPoint[] result, SKPoint[] vectors) } } + public readonly SKPoint[] MapVectors (SKPoint[] vectors) => + MapVectors (vectors.AsSpan ()); + public readonly SKPoint[] MapVectors (ReadOnlySpan vectors) { if (vectors == null) diff --git a/binding/SkiaSharp/SKPathEffect.cs b/binding/SkiaSharp/SKPathEffect.cs index d668dba370..277ff656ed 100644 --- a/binding/SkiaSharp/SKPathEffect.cs +++ b/binding/SkiaSharp/SKPathEffect.cs @@ -61,6 +61,9 @@ public static SKPathEffect Create2DPath(SKMatrix matrix, SKPath path) return GetObject(SkiaApi.sk_path_effect_create_2d_path(&matrix, path.Handle)); } + public static SKPathEffect CreateDash (float[] intervals, float phase) => + CreateDash (intervals.AsSpan (), phase); + public static SKPathEffect CreateDash(ReadOnlySpan intervals, float phase) { if (intervals == null) diff --git a/binding/SkiaSharp/SKRuntimeEffect.cs b/binding/SkiaSharp/SKRuntimeEffect.cs index 95b1fadff9..24e2f20286 100644 --- a/binding/SkiaSharp/SKRuntimeEffect.cs +++ b/binding/SkiaSharp/SKRuntimeEffect.cs @@ -19,6 +19,9 @@ internal SKRuntimeEffect (IntPtr handle, bool owns) // Create* + public static SKRuntimeEffect CreateShader (string sksl, out string errors) => + CreateShader (sksl.AsSpan (), out errors); + public static SKRuntimeEffect CreateShader (ReadOnlySpan sksl, out string errors) { using var s = new SKString (sksl); @@ -30,6 +33,9 @@ public static SKRuntimeEffect CreateShader (ReadOnlySpan sksl, out string return effect; } + public static SKRuntimeEffect CreateColorFilter (string sksl, out string errors) => + CreateColorFilter (sksl.AsSpan (), out errors); + public static SKRuntimeEffect CreateColorFilter (ReadOnlySpan sksl, out string errors) { using var s = new SKString (sksl); @@ -41,7 +47,10 @@ public static SKRuntimeEffect CreateColorFilter (ReadOnlySpan sksl, out st return effect; } - public static SKRuntimeEffect CreateBlender (string sksl, out string errors) + public static SKRuntimeEffect CreateBlender (string sksl, out string errors) => + CreateBlender (sksl.AsSpan (), out errors); + + public static SKRuntimeEffect CreateBlender (ReadOnlySpan sksl, out string errors) { using var s = new SKString (sksl); using var errorString = new SKString (); @@ -54,6 +63,9 @@ public static SKRuntimeEffect CreateBlender (string sksl, out string errors) // Build* + public static SKRuntimeShaderBuilder BuildShader (string sksl) => + BuildShader (sksl.AsSpan ()); + public static SKRuntimeShaderBuilder BuildShader (ReadOnlySpan sksl) { var effect = CreateShader (sksl, out var errors); @@ -61,6 +73,9 @@ public static SKRuntimeShaderBuilder BuildShader (ReadOnlySpan sksl) return new SKRuntimeShaderBuilder (effect); } + public static SKRuntimeColorFilterBuilder BuildColorFilter (string sksl) => + BuildColorFilter (sksl.AsSpan ()); + public static SKRuntimeColorFilterBuilder BuildColorFilter (ReadOnlySpan sksl) { var effect = CreateColorFilter (sksl, out var errors); @@ -68,7 +83,10 @@ public static SKRuntimeColorFilterBuilder BuildColorFilter (ReadOnlySpan s return new SKRuntimeColorFilterBuilder (effect); } - public static SKRuntimeBlenderBuilder BuildBlender (string sksl) + public static SKRuntimeBlenderBuilder BuildBlender (string sksl) => + BuildBlender (sksl.AsSpan ()); + + public static SKRuntimeBlenderBuilder BuildBlender (ReadOnlySpan sksl) { var effect = CreateBlender (sksl, out var errors); ValidateResult (effect, errors); diff --git a/binding/SkiaSharp/SKString.cs b/binding/SkiaSharp/SKString.cs index 5e50615f1b..0f7701168f 100644 --- a/binding/SkiaSharp/SKString.cs +++ b/binding/SkiaSharp/SKString.cs @@ -40,11 +40,6 @@ public SKString (ReadOnlySpan src) { } - public SKString (string str) - : this (StringUtilities.GetEncodedText (str, SKTextEncoding.Utf8).AsSpan ()) - { - } - public SKString (ReadOnlySpan str) : this (StringUtilities.GetEncodedText (str, SKTextEncoding.Utf8).AsSpan ()) { @@ -64,10 +59,7 @@ public static explicit operator string (SKString skString) internal static SKString Create (string str) { - if (str == null) { - return null; - } - return new SKString (str); + return Create (str.AsSpan ()); } internal static SKString Create (ReadOnlySpan str) diff --git a/binding/SkiaSharp/SKVertices.cs b/binding/SkiaSharp/SKVertices.cs index 75f6325b2e..648cad71ac 100644 --- a/binding/SkiaSharp/SKVertices.cs +++ b/binding/SkiaSharp/SKVertices.cs @@ -22,15 +22,20 @@ protected override void Dispose (bool disposing) => void ISKNonVirtualReferenceCounted.UnreferenceNative () => SkiaApi.sk_vertices_unref (Handle); - public static SKVertices CreateCopy (SKVertexMode vmode, ReadOnlySpan positions, ReadOnlySpan colors) - { - return CreateCopy (vmode, positions, null, colors, null); - } + public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SKColor[] colors) => + CreateCopy (vmode, positions.AsSpan (), colors.AsSpan ()); - public static SKVertices CreateCopy (SKVertexMode vmode, ReadOnlySpan positions, ReadOnlySpan texs, ReadOnlySpan colors) - { - return CreateCopy (vmode, positions, texs, colors, null); - } + public static SKVertices CreateCopy (SKVertexMode vmode, ReadOnlySpan positions, ReadOnlySpan colors) => + CreateCopy (vmode, positions, null, colors, null); + + public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SKPoint[] texs, SKColor[] colors) => + CreateCopy (vmode, positions.AsSpan (), texs.AsSpan (), colors.AsSpan ()); + + public static SKVertices CreateCopy (SKVertexMode vmode, ReadOnlySpan positions, ReadOnlySpan texs, ReadOnlySpan colors) => + CreateCopy (vmode, positions, texs, colors, null); + + public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SKPoint[] texs, SKColor[] colors, UInt16[] indices) => + CreateCopy (vmode, positions.AsSpan (), texs.AsSpan (), colors.AsSpan (), indices.AsSpan ()); public static SKVertices CreateCopy (SKVertexMode vmode, ReadOnlySpan positions, ReadOnlySpan texs, ReadOnlySpan colors, ReadOnlySpan indices) { From 8bb55f1c5ede1f4b1e285002f363ebd52fea1894 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Wed, 6 Nov 2024 22:47:06 -0500 Subject: [PATCH 17/24] Fix method order to preserve blame --- binding/SkiaSharp/SKMatrix.cs | 40 +++++++++++++++++------------------ 1 file changed, 20 insertions(+), 20 deletions(-) diff --git a/binding/SkiaSharp/SKMatrix.cs b/binding/SkiaSharp/SKMatrix.cs index 7f9c78ec77..6f7842a0a0 100644 --- a/binding/SkiaSharp/SKMatrix.cs +++ b/binding/SkiaSharp/SKMatrix.cs @@ -324,16 +324,6 @@ public readonly SKPoint MapPoint (float x, float y) return result; } - public readonly void MapPoints (SKPoint[] result, SKPoint[] points) - { - if (result == null) - throw new ArgumentNullException (nameof (result)); - if (points == null) - throw new ArgumentNullException (nameof (points)); - - MapPoints (result.AsSpan (), points.AsSpan ()); - } - public readonly void MapPoints (Span result, ReadOnlySpan points) { if (result.Length != points.Length) @@ -346,6 +336,16 @@ public readonly void MapPoints (Span result, ReadOnlySpan poin } } + public readonly void MapPoints (SKPoint[] result, SKPoint[] points) + { + if (result == null) + throw new ArgumentNullException (nameof (result)); + if (points == null) + throw new ArgumentNullException (nameof (points)); + + MapPoints (result.AsSpan (), points.AsSpan ()); + } + public readonly SKPoint[] MapPoints (SKPoint[] points) => MapPoints (points.AsSpan ()); @@ -373,16 +373,6 @@ public readonly SKPoint MapVector (float x, float y) return result; } - public readonly void MapVectors (SKPoint[] result, SKPoint[] vectors) - { - if (result == null) - throw new ArgumentNullException (nameof (result)); - if (vectors == null) - throw new ArgumentNullException (nameof (vectors)); - - MapVectors (result.AsSpan (), vectors.AsSpan ()); - } - public readonly void MapVectors (Span result, ReadOnlySpan vectors) { if (result.Length != vectors.Length) @@ -395,6 +385,16 @@ public readonly void MapVectors (Span result, ReadOnlySpan vec } } + public readonly void MapVectors (SKPoint[] result, SKPoint[] vectors) + { + if (result == null) + throw new ArgumentNullException (nameof (result)); + if (vectors == null) + throw new ArgumentNullException (nameof (vectors)); + + MapVectors (result.AsSpan (), vectors.AsSpan ()); + } + public readonly SKPoint[] MapVectors (SKPoint[] vectors) => MapVectors (vectors.AsSpan ()); From 1ae486a3a8ac468f5034a36548465d5aad7a1e58 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Wed, 6 Nov 2024 23:02:00 -0500 Subject: [PATCH 18/24] Almost done restoring array methods --- binding/SkiaSharp/SKData.cs | 2 +- binding/SkiaSharp/SKImage.cs | 12 +++++++++--- binding/SkiaSharp/SKPMColor.cs | 22 ++++++++++++++-------- binding/SkiaSharp/SKPath.cs | 8 +++++++- 4 files changed, 31 insertions(+), 13 deletions(-) diff --git a/binding/SkiaSharp/SKData.cs b/binding/SkiaSharp/SKData.cs index eced66a2f5..76987ea76b 100644 --- a/binding/SkiaSharp/SKData.cs +++ b/binding/SkiaSharp/SKData.cs @@ -74,7 +74,7 @@ public static SKData CreateCopy (byte[] bytes, ulong length) => public static SKData CreateCopy (ReadOnlySpan bytes, ulong length) { fixed (byte* b = bytes) { - return GetObject (SkiaApi.sk_data_new_with_copy (b, (IntPtr)length)); + return CreateCopy ((IntPtr)b, (ulong)bytes.Length); } } diff --git a/binding/SkiaSharp/SKImage.cs b/binding/SkiaSharp/SKImage.cs index 4a1df885c0..aeeecb26b0 100644 --- a/binding/SkiaSharp/SKImage.cs +++ b/binding/SkiaSharp/SKImage.cs @@ -168,9 +168,7 @@ public static SKImage FromEncodedData (SKData data) public static SKImage FromEncodedData (ReadOnlySpan data) { - if (data == null) - throw new ArgumentNullException (nameof (data)); - if (data.Length == 0) + if (data.IsEmpty) throw new ArgumentException ("The data buffer was empty."); using (var skdata = SKData.CreateCopy (data)) { @@ -178,6 +176,14 @@ public static SKImage FromEncodedData (ReadOnlySpan data) } } + public static SKImage FromEncodedData (byte[] data) + { + if (data == null) + throw new ArgumentNullException (nameof (data)); + + return FromEncodedData (data.AsSpan ()); + } + public static SKImage FromEncodedData (SKStream data) { if (data == null) diff --git a/binding/SkiaSharp/SKPMColor.cs b/binding/SkiaSharp/SKPMColor.cs index a137f841b3..21902d9c4a 100644 --- a/binding/SkiaSharp/SKPMColor.cs +++ b/binding/SkiaSharp/SKPMColor.cs @@ -23,16 +23,19 @@ public SKPMColor (uint value) public static SKPMColor PreMultiply (SKColor color) => SkiaApi.sk_color_premultiply ((uint)color); + public static SKPMColor[] PreMultiply (SKColor[] colors) => + PreMultiply (colors.AsSpan ()); + public static SKPMColor[] PreMultiply (ReadOnlySpan colors) { var pmcolors = new SKPMColor[colors.Length]; - fixed (SKColor* c = colors) - fixed (SKPMColor* pm = pmcolors) { - SkiaApi.sk_color_premultiply_array ((uint*)c, colors.Length, (uint*)pm); - } + PreMultiply (pmcolors.AsSpan (), colors); return pmcolors; } + public static void PreMultiply (SKPMColor[] pmcolors, SKColor[] colors) => + PreMultiply (pmcolors.AsSpan (), colors.AsSpan ()); + public static void PreMultiply (Span pmcolors, ReadOnlySpan colors) { if (pmcolors.Length != colors.Length) @@ -48,16 +51,19 @@ public static void PreMultiply (Span pmcolors, ReadOnlySpan public static SKColor UnPreMultiply (SKPMColor pmcolor) => SkiaApi.sk_color_unpremultiply ((uint)pmcolor); + public static SKColor[] UnPreMultiply (SKPMColor[] pmcolors) => + UnPreMultiply (pmcolors.AsSpan ()); + public static SKColor[] UnPreMultiply (ReadOnlySpan pmcolors) { var colors = new SKColor[pmcolors.Length]; - fixed (SKColor* c = colors) - fixed (SKPMColor* pm = pmcolors) { - SkiaApi.sk_color_unpremultiply_array ((uint*)pm, pmcolors.Length, (uint*)c); - } + UnPreMultiply (colors.AsSpan (), pmcolors); return colors; } + public static void UnPreMultiply (SKColor[] colors, SKPMColor[] pmcolors) => + UnPreMultiply (colors.AsSpan (), pmcolors.AsSpan ()); + public static void UnPreMultiply (Span colors, ReadOnlySpan pmcolors) { if (colors.Length != pmcolors.Length) diff --git a/binding/SkiaSharp/SKPath.cs b/binding/SkiaSharp/SKPath.cs index 700219b370..85de9d02cc 100644 --- a/binding/SkiaSharp/SKPath.cs +++ b/binding/SkiaSharp/SKPath.cs @@ -181,6 +181,9 @@ public SKPoint[] GetPoints (int max) return points; } + public int GetPoints (SKPoint[] points, int max) => + GetPoints (points.AsSpan (), max); + public int GetPoints (Span points, int max) { if (points == null) @@ -524,9 +527,12 @@ public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float var quadCount = 1 << pow2; var ptCount = 2 * quadCount + 1; pts = new SKPoint[ptCount]; - return ConvertConicToQuads (p0, p1, p2, w, new Span (pts), pow2); + return ConvertConicToQuads (p0, p1, p2, w, pts.AsSpan (), pow2); } + public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, SKPoint[] pts, int pow2) => + ConvertConicToQuads (p0, p1, p2, w, pts.AsSpan (), pow2); + public static int ConvertConicToQuads (SKPoint p0, SKPoint p1, SKPoint p2, float w, Span pts, int pow2) { if (pts == null) From f1336f0e1c80331f752abc18dee6b2de14575455 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Wed, 6 Nov 2024 23:06:37 -0500 Subject: [PATCH 19/24] Fix recursive method --- binding/SkiaSharp/SKTypeface.cs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/binding/SkiaSharp/SKTypeface.cs b/binding/SkiaSharp/SKTypeface.cs index 3d28806e02..218bf047b4 100644 --- a/binding/SkiaSharp/SKTypeface.cs +++ b/binding/SkiaSharp/SKTypeface.cs @@ -258,7 +258,7 @@ public bool ContainsGlyphs (ReadOnlySpan text) => GetFont ().ContainsGlyphs (text); public bool ContainsGlyphs (ReadOnlySpan text, SKTextEncoding encoding) => - ContainsGlyphs (text, encoding); + GetFont ().ContainsGlyphs (text, encoding); public bool ContainsGlyphs (IntPtr text, int length, SKTextEncoding encoding) => GetFont ().ContainsGlyphs (text, length * encoding.GetCharacterByteSize (), encoding); From 34b0dd69778d36b96669d339c254c90b02cbaf80 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Wed, 6 Nov 2024 23:16:24 -0500 Subject: [PATCH 20/24] Fix build --- binding/SkiaSharp.Resources/ResourceProvider.cs | 5 ++++- tests/Tests/SkiaSharp/SKTypefaceTest.cs | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/binding/SkiaSharp.Resources/ResourceProvider.cs b/binding/SkiaSharp.Resources/ResourceProvider.cs index 5b22bc5c7d..0b5dac9a45 100644 --- a/binding/SkiaSharp.Resources/ResourceProvider.cs +++ b/binding/SkiaSharp.Resources/ResourceProvider.cs @@ -57,7 +57,10 @@ public FileResourceProvider (string baseDirectory, bool preDecode = false) private static IntPtr Create (string baseDirectory, bool preDecode) { - using var baseDir = new SKString(baseDirectory ?? throw new ArgumentNullException (nameof (baseDirectory))); + if (baseDirectory == null) + throw new ArgumentNullException (nameof (baseDirectory)); + + using var baseDir = new SKString (baseDirectory.AsSpan ()); return ResourcesApi.skresources_file_resource_provider_make (baseDir.Handle, preDecode); } } diff --git a/tests/Tests/SkiaSharp/SKTypefaceTest.cs b/tests/Tests/SkiaSharp/SKTypefaceTest.cs index b322e6511e..1cce5c4e9b 100644 --- a/tests/Tests/SkiaSharp/SKTypefaceTest.cs +++ b/tests/Tests/SkiaSharp/SKTypefaceTest.cs @@ -566,7 +566,7 @@ public void GetKerningPairAdjustmentsSpanMatchesArray() var adjustments1 = tf.GetKerningPairAdjustments(glyphs); var adjustments2 = new int[glyphs.Length]; - tf.GetKerningPairAdjustments(adjustments2, glyphs); + tf.GetKerningPairAdjustments(glyphs, adjustments2); Assert.Equal(adjustments1, adjustments2); } From 3d355e382820f69926850ec227c8fbb77dbf0126 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Thu, 7 Nov 2024 00:45:38 -0500 Subject: [PATCH 21/24] Revert changes to SKStream --- binding/SkiaSharp/SKStream.cs | 14 -------------- 1 file changed, 14 deletions(-) diff --git a/binding/SkiaSharp/SKStream.cs b/binding/SkiaSharp/SKStream.cs index 3912d90492..43f408193e 100644 --- a/binding/SkiaSharp/SKStream.cs +++ b/binding/SkiaSharp/SKStream.cs @@ -124,13 +124,6 @@ public int Read (byte[] buffer, int size) } } - public int Read (Span buffer) - { - fixed (byte* b = buffer) { - return Read ((IntPtr)b, buffer.Length); - } - } - public int Read (IntPtr buffer, int size) { return (int)SkiaApi.sk_stream_read (Handle, (void*)buffer, (IntPtr)size); @@ -399,13 +392,6 @@ public virtual bool Write (byte[] buffer, int size) } } - public virtual bool Write (ReadOnlySpan buffer) - { - fixed (byte* b = buffer) { - return SkiaApi.sk_wstream_write (Handle, (void*)b, (IntPtr)buffer.Length); - } - } - public bool NewLine () { return SkiaApi.sk_wstream_newline (Handle); From 590f43d335e55e82502f09f84f85d026b5976ec6 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Thu, 7 Nov 2024 08:34:58 -0500 Subject: [PATCH 22/24] Restore even more array/string overloads --- binding/SkiaSharp/SKShader.cs | 90 +++++++++++++++++++ .../SkiaSharp.HarfBuzz/CanvasExtensions.cs | 32 ++++++- 2 files changed, 118 insertions(+), 4 deletions(-) diff --git a/binding/SkiaSharp/SKShader.cs b/binding/SkiaSharp/SKShader.cs index d6a9da35e9..c86b85e63f 100644 --- a/binding/SkiaSharp/SKShader.cs +++ b/binding/SkiaSharp/SKShader.cs @@ -119,9 +119,15 @@ public static SKShader CreatePicture (SKPicture src, SKShaderTileMode tmx, SKSha // CreateLinearGradient + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor[] colors, SKShaderTileMode mode) => + CreateLinearGradient (start, end, colors.AsSpan (), mode); + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, SKShaderTileMode mode) => CreateLinearGradient (start, end, colors, null, mode); + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor[] colors, float[] colorPos, SKShaderTileMode mode) => + CreateLinearGradient (start, end, colors.AsSpan (), colorPos.AsSpan (), mode); + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) @@ -136,6 +142,9 @@ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnl } } + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColor[] colors, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) => + CreateLinearGradient (start, end, colors.AsSpan (), colorPos.AsSpan (), mode, localMatrix); + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) @@ -150,9 +159,15 @@ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnl } } + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode mode) => + CreateLinearGradient (start, end, colors.AsSpan (), colorspace, mode); + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, SKColorSpace colorspace, SKShaderTileMode mode) => CreateLinearGradient (start, end, colors, colorspace, null, mode); + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode) => + CreateLinearGradient (start, end, colors.AsSpan (), colorspace, colorPos.AsSpan (), mode); + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) @@ -167,6 +182,9 @@ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnl } } + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) => + CreateLinearGradient (start, end, colors.AsSpan (), colorspace, colorPos.AsSpan (), mode, localMatrix); + public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) @@ -183,9 +201,15 @@ public static SKShader CreateLinearGradient (SKPoint start, SKPoint end, ReadOnl // CreateRadialGradient + public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, SKShaderTileMode mode) => + CreateRadialGradient (center, radius, colors.AsSpan (), mode); + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, SKShaderTileMode mode) => CreateRadialGradient (center, radius, colors, null, mode); + public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode) => + CreateRadialGradient (center, radius, colors.AsSpan (), colorPos.AsSpan(), mode); + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) @@ -199,6 +223,9 @@ public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadO } } + public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) => + CreateRadialGradient (center, radius, colors.AsSpan (), colorPos.AsSpan (), mode, localMatrix); + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) @@ -212,9 +239,15 @@ public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadO } } + public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode mode) => + CreateRadialGradient (center, radius, colors.AsSpan (), colorspace, mode); + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, SKColorSpace colorspace, SKShaderTileMode mode) => CreateRadialGradient (center, radius, colors, colorspace, null, mode); + public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode) => + CreateRadialGradient (center, radius, colors.AsSpan (), colorspace, colorPos.AsSpan (), mode); + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) @@ -228,6 +261,9 @@ public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadO } } + public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) => + CreateRadialGradient (center, radius, colors.AsSpan (), colorspace, colorPos.AsSpan (), mode, localMatrix); + public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) @@ -243,18 +279,33 @@ public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadO // CreateSweepGradient + public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors) => + CreateSweepGradient (center, colors.AsSpan ()); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors) => CreateSweepGradient (center, colors, null, SKShaderTileMode.Clamp, 0, 360); + public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos) => + CreateSweepGradient (center, colors.AsSpan (), colorPos.AsSpan ()); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, ReadOnlySpan colorPos) => CreateSweepGradient (center, colors, colorPos, SKShaderTileMode.Clamp, 0, 360); + public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos, SKMatrix localMatrix) => + CreateSweepGradient (center, colors.AsSpan (), colorPos.AsSpan (), localMatrix); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, ReadOnlySpan colorPos, SKMatrix localMatrix) => CreateSweepGradient (center, colors, colorPos, SKShaderTileMode.Clamp, 0, 360, localMatrix); + public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, SKShaderTileMode tileMode, float startAngle, float endAngle) => + CreateSweepGradient (center, colors.AsSpan (), tileMode, startAngle, endAngle); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKShaderTileMode tileMode, float startAngle, float endAngle) => CreateSweepGradient (center, colors, null, tileMode, startAngle, endAngle); + public static SKShader CreateSweepGradient (SKPoint center, SKColor[] colors, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle) => + CreateSweepGradient (center, colors.AsSpan (), colorPos.AsSpan (), tileMode, startAngle, endAngle); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle) { if (colors == null) @@ -268,6 +319,9 @@ public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan + CreateSweepGradient (center, colors.AsSpan (), colorPos.AsSpan (), tileMode, startAngle, endAngle, localMatrix); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle, SKMatrix localMatrix) { if (colors == null) @@ -281,18 +335,33 @@ public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan + CreateSweepGradient (center, colors.AsSpan (), colorspace); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace) => CreateSweepGradient (center, colors, colorspace, null, SKShaderTileMode.Clamp, 0, 360); + public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos) => + CreateSweepGradient (center, colors.AsSpan (), colorspace, colorPos.AsSpan ()); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos) => CreateSweepGradient (center, colors, colorspace, colorPos, SKShaderTileMode.Clamp, 0, 360); + public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKMatrix localMatrix) => + CreateSweepGradient (center, colors.AsSpan (), colorspace, colorPos.AsSpan (), localMatrix); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKMatrix localMatrix) => CreateSweepGradient (center, colors, colorspace, colorPos, SKShaderTileMode.Clamp, 0, 360, localMatrix); + public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode tileMode, float startAngle, float endAngle) => + CreateSweepGradient (center, colors.AsSpan (), colorspace, tileMode, startAngle, endAngle); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, SKShaderTileMode tileMode, float startAngle, float endAngle) => CreateSweepGradient (center, colors, colorspace, null, tileMode, startAngle, endAngle); + public static SKShader CreateSweepGradient (SKPoint center, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle) => + CreateSweepGradient (center, colors.AsSpan (), colorspace, colorPos.AsSpan (), tileMode, startAngle, endAngle); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle) { if (colors == null) @@ -306,6 +375,9 @@ public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan + CreateSweepGradient (center, colors.AsSpan (), colorspace, colorPos.AsSpan (), tileMode, startAngle, endAngle, localMatrix); + public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode tileMode, float startAngle, float endAngle, SKMatrix localMatrix) { if (colors == null) @@ -321,9 +393,15 @@ public static SKShader CreateSweepGradient (SKPoint center, ReadOnlySpan + CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors.AsSpan (), mode); + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, SKShaderTileMode mode) => CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors, null, mode); + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode) => + CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors.AsSpan (), colorPos.AsSpan (), mode); + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) @@ -337,6 +415,9 @@ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float start } } + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) => + CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors.AsSpan (), colorPos.AsSpan (), mode, localMatrix); + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) @@ -350,9 +431,15 @@ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float start } } + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColorF[] colors, SKColorSpace colorspace, SKShaderTileMode mode) => + CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors.AsSpan (), colorspace, mode); + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, SKColorSpace colorspace, SKShaderTileMode mode) => CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors, colorspace, null, mode); + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode) => + CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors.AsSpan (), colorspace, colorPos.AsSpan (), mode); + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode) { if (colors == null) @@ -366,6 +453,9 @@ public static SKShader CreateTwoPointConicalGradient (SKPoint start, float start } } + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, SKColorF[] colors, SKColorSpace colorspace, float[] colorPos, SKShaderTileMode mode, SKMatrix localMatrix) => + CreateTwoPointConicalGradient (start, startRadius, end, endRadius, colors.AsSpan (), colorspace, colorPos.AsSpan (), mode, localMatrix); + public static SKShader CreateTwoPointConicalGradient (SKPoint start, float startRadius, SKPoint end, float endRadius, ReadOnlySpan colors, SKColorSpace colorspace, ReadOnlySpan colorPos, SKShaderTileMode mode, SKMatrix localMatrix) { if (colors == null) diff --git a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs index d8d694b651..6b44e524ee 100644 --- a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs +++ b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs @@ -4,27 +4,39 @@ namespace SkiaSharp.HarfBuzz { public static class CanvasExtensions { - [Obsolete("Use DrawShapedText(ReadOnlySpan text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] + [Obsolete("Use DrawShapedText(string text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] public static void DrawShapedText(this SKCanvas canvas, string text, SKPoint p, SKPaint paint) => canvas.DrawShapedText(text.AsSpan(), p.X, p.Y, paint.TextAlign, paint.GetFont(), paint); + public static void DrawShapedText(this SKCanvas canvas, string text, SKPoint p, SKFont font, SKPaint paint) => + DrawShapedText(canvas, text.AsSpan(), p, font, paint); + public static void DrawShapedText(this SKCanvas canvas, ReadOnlySpan text, SKPoint p, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) canvas.DrawShapedText(text, p.X, p.Y, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete + public static void DrawShapedText(this SKCanvas canvas, string text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => + DrawShapedText(canvas, text.AsSpan(), p, textAlign, font, paint); + public static void DrawShapedText(this SKCanvas canvas, ReadOnlySpan text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => canvas.DrawShapedText(text, p.X, p.Y, textAlign, font, paint); - [Obsolete("Use DrawShapedText(ReadOnlySpan text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] + [Obsolete("Use DrawShapedText(string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] public static void DrawShapedText(this SKCanvas canvas, string text, float x, float y, SKPaint paint) => canvas.DrawShapedText(text.AsSpan(), x, y, paint.TextAlign, paint.GetFont(), paint); + public static void DrawShapedText(this SKCanvas canvas, string text, float x, float y, SKFont font, SKPaint paint) => + DrawShapedText(canvas, text.AsSpan(), x, y, font, paint); + public static void DrawShapedText(this SKCanvas canvas, ReadOnlySpan text, float x, float y, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) canvas.DrawShapedText(text, x, y, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete + public static void DrawShapedText(this SKCanvas canvas, string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) => + DrawShapedText(canvas, text.AsSpan(), x, y, textAlign, font, paint); + public static void DrawShapedText(this SKCanvas canvas, ReadOnlySpan text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) { if (text.IsEmpty) @@ -34,27 +46,39 @@ public static void DrawShapedText(this SKCanvas canvas, ReadOnlySpan text, canvas.DrawShapedText(shaper, text, x, y, textAlign, font, paint); } - [Obsolete("Use DrawShapedText(SKShaper shaper, ReadOnlySpan text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] + [Obsolete("Use DrawShapedText(SKShaper shaper, string text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, SKPoint p, SKPaint paint) => canvas.DrawShapedText(shaper, text.AsSpan(), p.X, p.Y, paint.TextAlign, paint.GetFont(), paint); + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, SKPoint p, SKFont font, SKPaint paint) => + DrawShapedText(canvas, shaper, text.AsSpan(), p, font, paint); + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, ReadOnlySpan text, SKPoint p, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) canvas.DrawShapedText(shaper, text, p.X, p.Y, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => + DrawShapedText(canvas, shaper, text.AsSpan(), p, textAlign, font, paint); + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, ReadOnlySpan text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => canvas.DrawShapedText(shaper, text, p.X, p.Y, textAlign, font, paint); - [Obsolete("Use DrawShapedText(SKShaper shaper, ReadOnlySpan text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] + [Obsolete("Use DrawShapedText(SKShaper shaper, string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) instead.")] public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, float x, float y, SKPaint paint) => canvas.DrawShapedText(shaper, text.AsSpan(), x, y, paint.TextAlign, paint.GetFont(), paint); + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, float x, float y, SKFont font, SKPaint paint) => + DrawShapedText(canvas, shaper, text.AsSpan(), x, y, font, paint); + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, ReadOnlySpan text, float x, float y, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) canvas.DrawShapedText(shaper, text, x, y, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) => + DrawShapedText(canvas, shaper, text.AsSpan(), x, y, textAlign, font, paint); + public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, ReadOnlySpan text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) { if (text.IsEmpty) From 27bd94de1f8bc505c511cec5bad32103cfd9fb0a Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:02:27 -0500 Subject: [PATCH 23/24] Add missing DrawText* span overloads --- binding/SkiaSharp/SKCanvas.cs | 34 ++++++++++++++++++++++++++++++++-- 1 file changed, 32 insertions(+), 2 deletions(-) diff --git a/binding/SkiaSharp/SKCanvas.cs b/binding/SkiaSharp/SKCanvas.cs index bb55b70b38..a23a7d97b4 100644 --- a/binding/SkiaSharp/SKCanvas.cs +++ b/binding/SkiaSharp/SKCanvas.cs @@ -623,19 +623,31 @@ public void DrawText (string text, float x, float y, SKPaint paint) => DrawText (text, x, y, paint.TextAlign, paint.GetFont (), paint); public void DrawText (string text, SKPoint p, SKFont font, SKPaint paint) => + DrawText (text.AsSpan (), p, font, paint); + + public void DrawText (ReadOnlySpan text, SKPoint p, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) DrawText (text, p, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete public void DrawText (string text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => + DrawText (text.AsSpan (), p, textAlign, font, paint); + + public void DrawText (ReadOnlySpan text, SKPoint p, SKTextAlign textAlign, SKFont font, SKPaint paint) => DrawText (text, p.X, p.Y, textAlign, font, paint); public void DrawText (string text, float x, float y, SKFont font, SKPaint paint) => + DrawText (text.AsSpan (), x, y, font, paint); + + public void DrawText (ReadOnlySpan text, float x, float y, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) DrawText (text, x, y, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete - public void DrawText (string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) + public void DrawText (string text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) => + DrawText (text.AsSpan (), x, y, textAlign, font, paint); + + public void DrawText (ReadOnlySpan text, float x, float y, SKTextAlign textAlign, SKFont font, SKPaint paint) { if (text == null) throw new ArgumentNullException (nameof (text)); @@ -673,27 +685,45 @@ public void DrawTextOnPath (string text, SKPath path, SKPoint offset, bool warpG DrawTextOnPath (text, path, offset, warpGlyphs, paint.GetFont (), paint); public void DrawTextOnPath (string text, SKPath path, SKPoint offset, SKFont font, SKPaint paint) => + DrawTextOnPath (text.AsSpan (), path, offset, font, paint); + + public void DrawTextOnPath (ReadOnlySpan text, SKPath path, SKPoint offset, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) DrawTextOnPath (text, path, offset, true, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete public void DrawTextOnPath (string text, SKPath path, SKPoint offset, SKTextAlign textAlign, SKFont font, SKPaint paint) => + DrawTextOnPath (text.AsSpan (), path, offset, textAlign, font, paint); + + public void DrawTextOnPath (ReadOnlySpan text, SKPath path, SKPoint offset, SKTextAlign textAlign, SKFont font, SKPaint paint) => DrawTextOnPath (text, path, offset, true, textAlign, font, paint); public void DrawTextOnPath (string text, SKPath path, float hOffset, float vOffset, SKFont font, SKPaint paint) => + DrawTextOnPath (text.AsSpan (), path, hOffset, vOffset, font, paint); + + public void DrawTextOnPath (ReadOnlySpan text, SKPath path, float hOffset, float vOffset, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) DrawTextOnPath (text, path, new SKPoint (hOffset, vOffset), true, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete public void DrawTextOnPath (string text, SKPath path, float hOffset, float vOffset, SKTextAlign textAlign, SKFont font, SKPaint paint) => + DrawTextOnPath (text.AsSpan (), path, hOffset, vOffset, textAlign, font, paint); + + public void DrawTextOnPath (ReadOnlySpan text, SKPath path, float hOffset, float vOffset, SKTextAlign textAlign, SKFont font, SKPaint paint) => DrawTextOnPath (text, path, new SKPoint (hOffset, vOffset), true, textAlign, font, paint); public void DrawTextOnPath (string text, SKPath path, SKPoint offset, bool warpGlyphs, SKFont font, SKPaint paint) => + DrawTextOnPath (text.AsSpan (), path, offset, warpGlyphs, font, paint); + + public void DrawTextOnPath (ReadOnlySpan text, SKPath path, SKPoint offset, bool warpGlyphs, SKFont font, SKPaint paint) => #pragma warning disable CS0618 // Type or member is obsolete (TODO: replace paint.TextAlign with SKTextAlign.Left) DrawTextOnPath (text, path, offset, warpGlyphs, paint.TextAlign, font, paint); #pragma warning restore CS0618 // Type or member is obsolete - public void DrawTextOnPath (string text, SKPath path, SKPoint offset, bool warpGlyphs, SKTextAlign textAlign, SKFont font, SKPaint paint) + public void DrawTextOnPath (string text, SKPath path, SKPoint offset, bool warpGlyphs, SKTextAlign textAlign, SKFont font, SKPaint paint) => + DrawTextOnPath (text.AsSpan (), path, offset, warpGlyphs, textAlign, font, paint); + + public void DrawTextOnPath (ReadOnlySpan text, SKPath path, SKPoint offset, bool warpGlyphs, SKTextAlign textAlign, SKFont font, SKPaint paint) { if (text == null) throw new ArgumentNullException (nameof (text)); From 47479bfbc49dbfdcc175347ce23894113073d1d2 Mon Sep 17 00:00:00 2001 From: ScrubN <72096833+ScrubN@users.noreply.github.com> Date: Thu, 7 Nov 2024 10:03:47 -0500 Subject: [PATCH 24/24] Cleanup --- binding/SkiaSharp/SKCanvas.cs | 34 +++++++++--------------------- binding/SkiaSharp/SKColorFilter.cs | 30 ++++++-------------------- binding/SkiaSharp/SKDocument.cs | 12 +++++------ binding/SkiaSharp/SKFont.cs | 2 +- binding/SkiaSharp/SKImage.cs | 9 ++------ binding/SkiaSharp/SKMatrix.cs | 18 ++-------------- binding/SkiaSharp/SKPath.cs | 10 ++------- binding/SkiaSharp/SKRoundRect.cs | 9 ++------ binding/SkiaSharp/SKShader.cs | 2 +- binding/SkiaSharp/SKString.cs | 14 ++---------- binding/SkiaSharp/SKVertices.cs | 3 --- 11 files changed, 34 insertions(+), 109 deletions(-) diff --git a/binding/SkiaSharp/SKCanvas.cs b/binding/SkiaSharp/SKCanvas.cs index a23a7d97b4..4fb9667418 100644 --- a/binding/SkiaSharp/SKCanvas.cs +++ b/binding/SkiaSharp/SKCanvas.cs @@ -780,10 +780,8 @@ public void DrawUrlAnnotation (SKRect rect, SKData value) SkiaApi.sk_canvas_draw_url_annotation (Handle, &rect, value == null ? IntPtr.Zero : value.Handle); } - public SKData DrawUrlAnnotation (SKRect rect, string value) - { - return DrawUrlAnnotation (rect, value.AsSpan ()); - } + public SKData DrawUrlAnnotation (SKRect rect, string value) => + DrawUrlAnnotation (rect, value.AsSpan ()); public SKData DrawUrlAnnotation (SKRect rect, ReadOnlySpan value) { @@ -797,10 +795,8 @@ public void DrawNamedDestinationAnnotation (SKPoint point, SKData value) SkiaApi.sk_canvas_draw_named_destination_annotation (Handle, &point, value == null ? IntPtr.Zero : value.Handle); } - public SKData DrawNamedDestinationAnnotation (SKPoint point, string value) - { - return DrawNamedDestinationAnnotation (point, value.AsSpan ()); - } + public SKData DrawNamedDestinationAnnotation (SKPoint point, string value) => + DrawNamedDestinationAnnotation (point, value.AsSpan ()); public SKData DrawNamedDestinationAnnotation (SKPoint point, ReadOnlySpan value) { @@ -814,10 +810,8 @@ public void DrawLinkDestinationAnnotation (SKRect rect, SKData value) SkiaApi.sk_canvas_draw_link_destination_annotation (Handle, &rect, value == null ? IntPtr.Zero : value.Handle); } - public SKData DrawLinkDestinationAnnotation (SKRect rect, string value) - { - return DrawLinkDestinationAnnotation (rect, value.AsSpan ()); - } + public SKData DrawLinkDestinationAnnotation (SKRect rect, string value) => + DrawLinkDestinationAnnotation (rect, value.AsSpan ()); public SKData DrawLinkDestinationAnnotation (SKRect rect, ReadOnlySpan value) { @@ -953,10 +947,8 @@ public SKMatrix44 TotalMatrix44 { // DrawVertices - public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKColor[] colors, SKPaint paint) - { + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKColor[] colors, SKPaint paint) => DrawVertices (vmode, vertices.AsSpan (), colors.AsSpan (), paint); - } public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan colors, SKPaint paint) { @@ -964,10 +956,8 @@ public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, Re DrawVertices (vert, SKBlendMode.Modulate, paint); } - public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKPaint paint) - { + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKPaint paint) => DrawVertices (vmode, vertices.AsSpan (), texs.AsSpan (), colors.AsSpan (), paint); - } public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, SKPaint paint) { @@ -975,10 +965,8 @@ public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, Re DrawVertices (vert, SKBlendMode.Modulate, paint); } - public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, UInt16[] indices, SKPaint paint) - { + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, UInt16[] indices, SKPaint paint) => DrawVertices (vmode, vertices.AsSpan (), texs.AsSpan (), colors.AsSpan (), indices.AsSpan (), paint); - } public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, ReadOnlySpan indices, SKPaint paint) { @@ -986,10 +974,8 @@ public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, Re DrawVertices (vert, SKBlendMode.Modulate, paint); } - public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKBlendMode mode, UInt16[] indices, SKPaint paint) - { + public void DrawVertices (SKVertexMode vmode, SKPoint[] vertices, SKPoint[] texs, SKColor[] colors, SKBlendMode mode, UInt16[] indices, SKPaint paint) => DrawVertices (vmode, vertices.AsSpan (), texs.AsSpan (), colors.AsSpan (), mode, indices.AsSpan (), paint); - } public void DrawVertices (SKVertexMode vmode, ReadOnlySpan vertices, ReadOnlySpan texs, ReadOnlySpan colors, SKBlendMode mode, ReadOnlySpan indices, SKPaint paint) { diff --git a/binding/SkiaSharp/SKColorFilter.cs b/binding/SkiaSharp/SKColorFilter.cs index 3c279a9829..46340eec62 100644 --- a/binding/SkiaSharp/SKColorFilter.cs +++ b/binding/SkiaSharp/SKColorFilter.cs @@ -36,12 +36,8 @@ public static SKColorFilter CreateCompose(SKColorFilter outer, SKColorFilter inn return GetObject (SkiaApi.sk_colorfilter_new_compose(outer.Handle, inner.Handle)); } - public static SKColorFilter CreateColorMatrix (float[] matrix) - { - if (matrix == null) - throw new ArgumentNullException(nameof(matrix)); - return CreateColorMatrix(matrix.AsSpan()); - } + public static SKColorFilter CreateColorMatrix (float[] matrix) => + CreateColorMatrix (matrix.AsSpan ()); public static SKColorFilter CreateColorMatrix(ReadOnlySpan matrix) { @@ -57,12 +53,8 @@ public static SKColorFilter CreateLumaColor() return GetObject (SkiaApi.sk_colorfilter_new_luma_color()); } - public static SKColorFilter CreateTable(byte[] table) - { - if (table == null) - throw new ArgumentNullException(nameof(table)); - return CreateTable(table.AsSpan()); - } + public static SKColorFilter CreateTable (byte[] table) => + CreateTable (table.AsSpan ()); public static SKColorFilter CreateTable(ReadOnlySpan table) { @@ -73,18 +65,8 @@ public static SKColorFilter CreateTable(ReadOnlySpan table) } } - public static SKColorFilter CreateTable(byte[] tableA, byte[] tableR, byte[] tableG, byte[] tableB) - { - if (tableA == null) - throw new ArgumentNullException(nameof(tableA)); - if (tableR == null) - throw new ArgumentNullException(nameof(tableR)); - if (tableG == null) - throw new ArgumentNullException(nameof(tableG)); - if (tableB == null) - throw new ArgumentNullException(nameof(tableB)); - return CreateTable(tableA.AsSpan(), tableR.AsSpan(), tableG.AsSpan(), tableB.AsSpan()); - } + public static SKColorFilter CreateTable(byte[] tableA, byte[] tableR, byte[] tableG, byte[] tableB) => + CreateTable(tableA.AsSpan(), tableR.AsSpan(), tableG.AsSpan(), tableB.AsSpan()); public static SKColorFilter CreateTable(ReadOnlySpan tableA, ReadOnlySpan tableR, ReadOnlySpan tableG, ReadOnlySpan tableB) { diff --git a/binding/SkiaSharp/SKDocument.cs b/binding/SkiaSharp/SKDocument.cs index 2330964be8..6eee6e87f8 100644 --- a/binding/SkiaSharp/SKDocument.cs +++ b/binding/SkiaSharp/SKDocument.cs @@ -139,12 +139,12 @@ public static SKDocument CreatePdf (SKWStream stream, SKDocumentPdfMetadata meta throw new ArgumentNullException (nameof (stream)); } - using var title = SKString.Create (metadata.Title); - using var author = SKString.Create (metadata.Author); - using var subject = SKString.Create (metadata.Subject); - using var keywords = SKString.Create (metadata.Keywords); - using var creator = SKString.Create (metadata.Creator); - using var producer = SKString.Create (metadata.Producer); + using var title = SKString.Create (metadata.Title.AsSpan ()); + using var author = SKString.Create (metadata.Author.AsSpan ()); + using var subject = SKString.Create (metadata.Subject.AsSpan ()); + using var keywords = SKString.Create (metadata.Keywords.AsSpan ()); + using var creator = SKString.Create (metadata.Creator.AsSpan ()); + using var producer = SKString.Create (metadata.Producer.AsSpan ()); var cmetadata = new SKDocumentPdfMetadataInternal { fTitle = title?.Handle ?? IntPtr.Zero, diff --git a/binding/SkiaSharp/SKFont.cs b/binding/SkiaSharp/SKFont.cs index 73b3250c88..d69a557008 100644 --- a/binding/SkiaSharp/SKFont.cs +++ b/binding/SkiaSharp/SKFont.cs @@ -232,7 +232,7 @@ public bool ContainsGlyphs (IntPtr text, int length, SKTextEncoding encoding) => ContainsGlyphs (GetGlyphs (text, length, encoding)); private bool ContainsGlyphs (ushort[] glyphs) => - ContainsGlyphs (new ReadOnlySpan (glyphs)); + ContainsGlyphs (glyphs.AsSpan ()); private bool ContainsGlyphs (ReadOnlySpan glyphs) => glyphs.IndexOf ((ushort)0) == -1; diff --git a/binding/SkiaSharp/SKImage.cs b/binding/SkiaSharp/SKImage.cs index aeeecb26b0..7f182abf87 100644 --- a/binding/SkiaSharp/SKImage.cs +++ b/binding/SkiaSharp/SKImage.cs @@ -176,13 +176,8 @@ public static SKImage FromEncodedData (ReadOnlySpan data) } } - public static SKImage FromEncodedData (byte[] data) - { - if (data == null) - throw new ArgumentNullException (nameof (data)); - - return FromEncodedData (data.AsSpan ()); - } + public static SKImage FromEncodedData (byte[] data) => + FromEncodedData (data.AsSpan ()); public static SKImage FromEncodedData (SKStream data) { diff --git a/binding/SkiaSharp/SKMatrix.cs b/binding/SkiaSharp/SKMatrix.cs index 6f7842a0a0..01cf0e5266 100644 --- a/binding/SkiaSharp/SKMatrix.cs +++ b/binding/SkiaSharp/SKMatrix.cs @@ -336,15 +336,8 @@ public readonly void MapPoints (Span result, ReadOnlySpan poin } } - public readonly void MapPoints (SKPoint[] result, SKPoint[] points) - { - if (result == null) - throw new ArgumentNullException (nameof (result)); - if (points == null) - throw new ArgumentNullException (nameof (points)); - + public readonly void MapPoints (SKPoint[] result, SKPoint[] points) => MapPoints (result.AsSpan (), points.AsSpan ()); - } public readonly SKPoint[] MapPoints (SKPoint[] points) => MapPoints (points.AsSpan ()); @@ -385,15 +378,8 @@ public readonly void MapVectors (Span result, ReadOnlySpan vec } } - public readonly void MapVectors (SKPoint[] result, SKPoint[] vectors) - { - if (result == null) - throw new ArgumentNullException (nameof (result)); - if (vectors == null) - throw new ArgumentNullException (nameof (vectors)); - + public readonly void MapVectors (SKPoint[] result, SKPoint[] vectors) => MapVectors (result.AsSpan (), vectors.AsSpan ()); - } public readonly SKPoint[] MapVectors (SKPoint[] vectors) => MapVectors (vectors.AsSpan ()); diff --git a/binding/SkiaSharp/SKPath.cs b/binding/SkiaSharp/SKPath.cs index 85de9d02cc..15f4403a47 100644 --- a/binding/SkiaSharp/SKPath.cs +++ b/binding/SkiaSharp/SKPath.cs @@ -417,14 +417,8 @@ public void AddPoly (ReadOnlySpan points, bool close = true) } } - public void AddPoly (SKPoint[] points, bool close = true) - { - if (points == null) - throw new ArgumentNullException (nameof (points)); - fixed (SKPoint* p = points) { - SkiaApi.sk_path_add_poly (Handle, p, points.Length, close); - } - } + public void AddPoly (SKPoint[] points, bool close = true) => + AddPoly (points.AsSpan (), close); public Iterator CreateIterator (bool forceClose) => new Iterator (this, forceClose); diff --git a/binding/SkiaSharp/SKRoundRect.cs b/binding/SkiaSharp/SKRoundRect.cs index 67f8794da4..4a17a9e5db 100644 --- a/binding/SkiaSharp/SKRoundRect.cs +++ b/binding/SkiaSharp/SKRoundRect.cs @@ -118,13 +118,8 @@ public void SetNinePatch (SKRect rect, float leftRadius, float topRadius, float SkiaApi.sk_rrect_set_nine_patch (Handle, &rect, leftRadius, topRadius, rightRadius, bottomRadius); } - public void SetRectRadii (SKRect rect, SKPoint[] radii) - { - if (radii == null) - throw new ArgumentNullException (nameof (radii)); - - SetRectRadii(rect, radii.AsSpan()); - } + public void SetRectRadii (SKRect rect, SKPoint[] radii) => + SetRectRadii (rect, radii.AsSpan ()); public void SetRectRadii (SKRect rect, ReadOnlySpan radii) { diff --git a/binding/SkiaSharp/SKShader.cs b/binding/SkiaSharp/SKShader.cs index c86b85e63f..1750e7ed40 100644 --- a/binding/SkiaSharp/SKShader.cs +++ b/binding/SkiaSharp/SKShader.cs @@ -208,7 +208,7 @@ public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadO CreateRadialGradient (center, radius, colors, null, mode); public static SKShader CreateRadialGradient (SKPoint center, float radius, SKColor[] colors, float[] colorPos, SKShaderTileMode mode) => - CreateRadialGradient (center, radius, colors.AsSpan (), colorPos.AsSpan(), mode); + CreateRadialGradient (center, radius, colors.AsSpan (), colorPos.AsSpan (), mode); public static SKShader CreateRadialGradient (SKPoint center, float radius, ReadOnlySpan colors, ReadOnlySpan colorPos, SKShaderTileMode mode) { diff --git a/binding/SkiaSharp/SKString.cs b/binding/SkiaSharp/SKString.cs index 0f7701168f..ce32cc0fc9 100644 --- a/binding/SkiaSharp/SKString.cs +++ b/binding/SkiaSharp/SKString.cs @@ -57,18 +57,8 @@ public static explicit operator string (SKString skString) return skString.ToString (); } - internal static SKString Create (string str) - { - return Create (str.AsSpan ()); - } - - internal static SKString Create (ReadOnlySpan str) - { - if (str == null) { - return null; - } - return new SKString (str); - } + internal static SKString Create (ReadOnlySpan str) => + new SKString (str); protected override void Dispose (bool disposing) => base.Dispose (disposing); diff --git a/binding/SkiaSharp/SKVertices.cs b/binding/SkiaSharp/SKVertices.cs index 648cad71ac..525b268f6a 100644 --- a/binding/SkiaSharp/SKVertices.cs +++ b/binding/SkiaSharp/SKVertices.cs @@ -39,9 +39,6 @@ public static SKVertices CreateCopy (SKVertexMode vmode, SKPoint[] positions, SK public static SKVertices CreateCopy (SKVertexMode vmode, ReadOnlySpan positions, ReadOnlySpan texs, ReadOnlySpan colors, ReadOnlySpan indices) { - if (positions == null) - throw new ArgumentNullException (nameof (positions)); - if (texs != null && positions.Length != texs.Length) throw new ArgumentException ("The number of texture coordinates must match the number of vertices.", nameof (texs)); if (colors != null && positions.Length != colors.Length)