diff --git a/binding/SkiaSharp/SKRunBuffer.cs b/binding/SkiaSharp/SKRunBuffer.cs index 8f4916104e..65831136ef 100644 --- a/binding/SkiaSharp/SKRunBuffer.cs +++ b/binding/SkiaSharp/SKRunBuffer.cs @@ -1,10 +1,11 @@ #nullable disable using System; -using System.ComponentModel; namespace SkiaSharp { + // Base + public unsafe class SKRunBuffer { internal readonly SKRunBufferInternal internalBuffer; @@ -17,103 +18,142 @@ internal SKRunBuffer (SKRunBufferInternal buffer, int size) public int Size { get; } - public Span GetGlyphSpan () => - new Span (internalBuffer.glyphs, internalBuffer.glyphs == null ? 0 : Size); + public Span Glyphs => new (internalBuffer.glyphs, Size); + + public void SetGlyphs (ReadOnlySpan glyphs) => glyphs.CopyTo (Glyphs); - public void SetGlyphs (ReadOnlySpan glyphs) => - glyphs.CopyTo (GetGlyphSpan ()); + [Obsolete ("Use Glyphs instead.")] + public Span GetGlyphSpan () => Glyphs; } public sealed unsafe class SKHorizontalRunBuffer : SKRunBuffer { - internal SKHorizontalRunBuffer (SKRunBufferInternal buffer, int count) - : base (buffer, count) + internal SKHorizontalRunBuffer (SKRunBufferInternal buffer, int size) + : base (buffer, size) { } - public Span GetPositionSpan () => - new Span (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size); + public Span Positions => new (internalBuffer.pos, Size); - public void SetPositions (ReadOnlySpan positions) => - positions.CopyTo (GetPositionSpan ()); + public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions); + + [Obsolete ("Use Positions instead.")] + public Span GetPositionSpan () => Positions; } public sealed unsafe class SKPositionedRunBuffer : SKRunBuffer { - internal SKPositionedRunBuffer (SKRunBufferInternal buffer, int count) - : base (buffer, count) + internal SKPositionedRunBuffer (SKRunBufferInternal buffer, int size) + : base (buffer, size) { } - public Span GetPositionSpan () => - new Span (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size); + public Span Positions => new (internalBuffer.pos, Size); + + public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions); - public void SetPositions (ReadOnlySpan positions) => - positions.CopyTo (GetPositionSpan ()); + [Obsolete ("Use Positions instead.")] + public Span GetPositionSpan () => Positions; } public sealed unsafe class SKRotationScaleRunBuffer : SKRunBuffer { - internal SKRotationScaleRunBuffer (SKRunBufferInternal buffer, int count) - : base (buffer, count) + internal SKRotationScaleRunBuffer (SKRunBufferInternal buffer, int size) + : base (buffer, size) { } - public Span GetRotationScaleSpan () => - new Span (internalBuffer.pos, Size); + public Span Positions => new (internalBuffer.pos, Size); - public void SetRotationScale (ReadOnlySpan positions) => - positions.CopyTo (GetRotationScaleSpan ()); + public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions); + + [Obsolete ("Use Positions instead.")] + public Span GetRotationScaleSpan () => Positions; + + [Obsolete ("Use SetPositions instead.")] + public void SetRotationScale (ReadOnlySpan positions) => SetPositions (positions); } + // Text + public unsafe class SKTextRunBuffer : SKRunBuffer { - internal SKTextRunBuffer (SKRunBufferInternal buffer, int count, int textSize) - : base (buffer, count) + internal SKTextRunBuffer (SKRunBufferInternal buffer, int size, int textSize) + : base (buffer, size) { TextSize = textSize; } public int TextSize { get; } - public Span GetTextSpan () => - new Span (internalBuffer.utf8text, internalBuffer.utf8text == null ? 0 : TextSize); + public Span Text => new (internalBuffer.utf8text, TextSize); - public Span GetClusterSpan () => - new Span (internalBuffer.clusters, internalBuffer.clusters == null ? 0 : Size); + public Span Clusters => new (internalBuffer.clusters, Size); - public void SetText (ReadOnlySpan text) => - text.CopyTo (GetTextSpan ()); + public void SetText (ReadOnlySpan text) => text.CopyTo (Text); - public void SetClusters (ReadOnlySpan clusters) => - clusters.CopyTo (GetClusterSpan ()); + public void SetClusters (ReadOnlySpan clusters) => clusters.CopyTo (Clusters); } public sealed unsafe class SKHorizontalTextRunBuffer : SKTextRunBuffer { - internal SKHorizontalTextRunBuffer (SKRunBufferInternal buffer, int count, int textSize) - : base (buffer, count, textSize) + internal SKHorizontalTextRunBuffer (SKRunBufferInternal buffer, int size, int textSize) + : base (buffer, size, textSize) { } - public Span GetPositionSpan () => - new Span (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size); + public Span Positions => new (internalBuffer.pos, Size); - public void SetPositions (ReadOnlySpan positions) => - positions.CopyTo (GetPositionSpan ()); + public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions); } public sealed unsafe class SKPositionedTextRunBuffer : SKTextRunBuffer { - internal SKPositionedTextRunBuffer (SKRunBufferInternal buffer, int count, int textSize) - : base (buffer, count, textSize) + internal SKPositionedTextRunBuffer (SKRunBufferInternal buffer, int size, int textSize) + : base (buffer, size, textSize) { } - public Span GetPositionSpan () => - new Span (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size); + public Span Positions => new (internalBuffer.pos, Size); + + public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions); + } + + public sealed unsafe class SKRotationScaleTextRunBuffer : SKTextRunBuffer + { + internal SKRotationScaleTextRunBuffer (SKRunBufferInternal buffer, int size, int textSize) + : base (buffer, size, textSize) + { + } + + public Span Positions => new (internalBuffer.pos, Size); + + public void SetPositions (ReadOnlySpan positions) => positions.CopyTo (Positions); + } + + // Raw / Struct + + public unsafe readonly struct SKRawRunBuffer + { + internal readonly SKRunBufferInternal buffer; + private readonly int size; + private readonly int posSize; + private readonly int textSize; + + internal SKRawRunBuffer (SKRunBufferInternal buffer, int size, int posSize, int textSize) + { + this.buffer = buffer; + this.size = size; + this.posSize = posSize; + this.textSize = textSize; + } + + public Span Glyphs => new (buffer.glyphs, size); + + public Span Positions => new (buffer.pos, posSize); + + public Span Text => new (buffer.utf8text, textSize); - public void SetPositions (ReadOnlySpan positions) => - positions.CopyTo (GetPositionSpan ()); + public Span Clusters => new (buffer.clusters, size); } } diff --git a/binding/SkiaSharp/SKTextBlob.cs b/binding/SkiaSharp/SKTextBlob.cs index 704b3e95b8..10193d25a0 100644 --- a/binding/SkiaSharp/SKTextBlob.cs +++ b/binding/SkiaSharp/SKTextBlob.cs @@ -1,7 +1,4 @@ -#nullable disable - -using System; -using System.ComponentModel; +using System; namespace SkiaSharp { @@ -31,27 +28,27 @@ public SKRect Bounds { // Create - public static SKTextBlob Create (string text, SKFont font, SKPoint origin = default) => + public static SKTextBlob? Create (string text, SKFont font, SKPoint origin = default) => Create (text.AsSpan (), font, origin); - public static SKTextBlob Create (ReadOnlySpan text, SKFont font, SKPoint origin = default) + public static SKTextBlob? Create (ReadOnlySpan text, SKFont font, SKPoint origin = default) { fixed (void* t = text) { return Create (t, text.Length * 2, SKTextEncoding.Utf16, font, origin); } } - public static SKTextBlob Create (IntPtr text, int length, SKTextEncoding encoding, SKFont font, SKPoint origin = default) => + public static SKTextBlob? Create (IntPtr text, int length, SKTextEncoding encoding, SKFont font, SKPoint origin = default) => Create (text.AsReadOnlySpan (length), encoding, font, origin); - public static SKTextBlob Create (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, SKPoint origin = default) + public static SKTextBlob? Create (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, SKPoint origin = default) { fixed (void* t = text) { return Create (t, text.Length, encoding, font, origin); } } - internal static SKTextBlob Create (void* text, int length, SKTextEncoding encoding, SKFont font, SKPoint origin) + internal static SKTextBlob? Create (void* text, int length, SKTextEncoding encoding, SKFont font, SKPoint origin) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -61,35 +58,35 @@ internal static SKTextBlob Create (void* text, int length, SKTextEncoding encodi return null; using var builder = new SKTextBlobBuilder (); - var buffer = builder.AllocatePositionedRun (font, count); - font.GetGlyphs (text, length, encoding, buffer.GetGlyphSpan ()); - font.GetGlyphPositions (buffer.GetGlyphSpan (), buffer.GetPositionSpan (), origin); + var buffer = builder.AllocateRawPositionedRun (font, count); + font.GetGlyphs (text, length, encoding, buffer.Glyphs); + font.GetGlyphPositions (buffer.Glyphs, buffer.Positions, origin); return builder.Build (); } // CreateHorizontal - public static SKTextBlob CreateHorizontal (string text, SKFont font, ReadOnlySpan positions, float y) => + public static SKTextBlob? CreateHorizontal (string text, SKFont font, ReadOnlySpan positions, float y) => CreateHorizontal (text.AsSpan (), font, positions, y); - public static SKTextBlob CreateHorizontal (ReadOnlySpan text, SKFont font, ReadOnlySpan positions, float y) + public static SKTextBlob? CreateHorizontal (ReadOnlySpan text, SKFont font, ReadOnlySpan positions, float y) { fixed (void* t = text) { return CreateHorizontal (t, text.Length * 2, SKTextEncoding.Utf16, font, positions, y); } } - public static SKTextBlob CreateHorizontal (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y) => + public static SKTextBlob? CreateHorizontal (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y) => CreateHorizontal (text.AsReadOnlySpan (length), encoding, font, positions, y); - public static SKTextBlob CreateHorizontal (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y) + public static SKTextBlob? CreateHorizontal (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y) { fixed (void* t = text) { return CreateHorizontal (t, text.Length, encoding, font, positions, y); } } - internal static SKTextBlob CreateHorizontal (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y) + internal static SKTextBlob? CreateHorizontal (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions, float y) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -99,35 +96,35 @@ internal static SKTextBlob CreateHorizontal (void* text, int length, SKTextEncod return null; using var builder = new SKTextBlobBuilder (); - var buffer = builder.AllocateHorizontalRun (font, count, y); - font.GetGlyphs (text, length, encoding, buffer.GetGlyphSpan ()); - positions.CopyTo (buffer.GetPositionSpan ()); + var buffer = builder.AllocateRawHorizontalRun (font, count, y); + font.GetGlyphs (text, length, encoding, buffer.Glyphs); + positions.CopyTo (buffer.Positions); return builder.Build (); } // CreatePositioned - public static SKTextBlob CreatePositioned (string text, SKFont font, ReadOnlySpan positions) => + public static SKTextBlob? CreatePositioned (string text, SKFont font, ReadOnlySpan positions) => CreatePositioned (text.AsSpan (), font, positions); - public static SKTextBlob CreatePositioned (ReadOnlySpan text, SKFont font, ReadOnlySpan positions) + public static SKTextBlob? CreatePositioned (ReadOnlySpan text, SKFont font, ReadOnlySpan positions) { fixed (void* t = text) { return CreatePositioned (t, text.Length * 2, SKTextEncoding.Utf16, font, positions); } } - public static SKTextBlob CreatePositioned (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) => + public static SKTextBlob? CreatePositioned (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) => CreatePositioned (text.AsReadOnlySpan (length), encoding, font, positions); - public static SKTextBlob CreatePositioned (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) + public static SKTextBlob? CreatePositioned (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) { fixed (void* t = text) { return CreatePositioned (t, text.Length, encoding, font, positions); } } - internal static SKTextBlob CreatePositioned (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) + internal static SKTextBlob? CreatePositioned (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -137,35 +134,35 @@ internal static SKTextBlob CreatePositioned (void* text, int length, SKTextEncod return null; using var builder = new SKTextBlobBuilder (); - var buffer = builder.AllocatePositionedRun (font, count); - font.GetGlyphs (text, length, encoding, buffer.GetGlyphSpan ()); - positions.CopyTo (buffer.GetPositionSpan ()); + var buffer = builder.AllocateRawPositionedRun (font, count); + font.GetGlyphs (text, length, encoding, buffer.Glyphs); + positions.CopyTo (buffer.Positions); return builder.Build (); } // CreateRotationScale - public static SKTextBlob CreateRotationScale (string text, SKFont font, ReadOnlySpan positions) => + public static SKTextBlob? CreateRotationScale (string text, SKFont font, ReadOnlySpan positions) => CreateRotationScale (text.AsSpan (), font, positions); - public static SKTextBlob CreateRotationScale (ReadOnlySpan text, SKFont font, ReadOnlySpan positions) + public static SKTextBlob? CreateRotationScale (ReadOnlySpan text, SKFont font, ReadOnlySpan positions) { fixed (void* t = text) { return CreateRotationScale (t, text.Length * 2, SKTextEncoding.Utf16, font, positions); } } - public static SKTextBlob CreateRotationScale (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) => + public static SKTextBlob? CreateRotationScale (IntPtr text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) => CreateRotationScale (text.AsReadOnlySpan (length), encoding, font, positions); - public static SKTextBlob CreateRotationScale (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) + public static SKTextBlob? CreateRotationScale (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) { fixed (void* t = text) { return CreateRotationScale (t, text.Length, encoding, font, positions); } } - internal static SKTextBlob CreateRotationScale (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) + internal static SKTextBlob? CreateRotationScale (void* text, int length, SKTextEncoding encoding, SKFont font, ReadOnlySpan positions) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -176,34 +173,34 @@ internal static SKTextBlob CreateRotationScale (void* text, int length, SKTextEn using var builder = new SKTextBlobBuilder (); var buffer = builder.AllocateRotationScaleRun (font, count); - font.GetGlyphs (text, length, encoding, buffer.GetGlyphSpan ()); - positions.CopyTo (buffer.GetRotationScaleSpan ()); + font.GetGlyphs (text, length, encoding, buffer.Glyphs); + positions.CopyTo (buffer.Positions); return builder.Build (); } // CreatePathPositioned - public static SKTextBlob CreatePathPositioned (string text, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) => + public static SKTextBlob? CreatePathPositioned (string text, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) => CreatePathPositioned (text.AsSpan (), font, path, textAlign, origin); - public static SKTextBlob CreatePathPositioned (ReadOnlySpan text, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) + public static SKTextBlob? CreatePathPositioned (ReadOnlySpan text, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) { fixed (void* t = text) { return CreatePathPositioned (t, text.Length * 2, SKTextEncoding.Utf16, font, path, textAlign, origin); } } - public static SKTextBlob CreatePathPositioned (IntPtr text, int length, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) => + public static SKTextBlob? CreatePathPositioned (IntPtr text, int length, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) => CreatePathPositioned (text.AsReadOnlySpan (length), encoding, font, path, textAlign, origin); - public static SKTextBlob CreatePathPositioned (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) + public static SKTextBlob? CreatePathPositioned (ReadOnlySpan text, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) { fixed (void* t = text) { return CreatePathPositioned (t, text.Length, encoding, font, path, textAlign, origin); } } - internal static SKTextBlob CreatePathPositioned (void* text, int length, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) + internal static SKTextBlob? CreatePathPositioned (void* text, int length, SKTextEncoding encoding, SKFont font, SKPath path, SKTextAlign textAlign = SKTextAlign.Left, SKPoint origin = default) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -228,7 +225,7 @@ internal static SKTextBlob CreatePathPositioned (void* text, int length, SKTextE // GetIntercepts - public float[] GetIntercepts (float upperBounds, float lowerBounds, SKPaint paint = null) + public float[] GetIntercepts (float upperBounds, float lowerBounds, SKPaint? paint = null) { var n = CountIntercepts (upperBounds, lowerBounds, paint); var intervals = new float[n]; @@ -236,7 +233,7 @@ public float[] GetIntercepts (float upperBounds, float lowerBounds, SKPaint pain return intervals; } - public void GetIntercepts (float upperBounds, float lowerBounds, Span intervals, SKPaint paint = null) + public void GetIntercepts (float upperBounds, float lowerBounds, Span intervals, SKPaint? paint = null) { var bounds = stackalloc float[2]; bounds[0] = upperBounds; @@ -248,7 +245,7 @@ public void GetIntercepts (float upperBounds, float lowerBounds, Span int // CountIntercepts - public int CountIntercepts (float upperBounds, float lowerBounds, SKPaint paint = null) + public int CountIntercepts (float upperBounds, float lowerBounds, SKPaint? paint = null) { var bounds = stackalloc float[2]; bounds[0] = upperBounds; @@ -258,7 +255,7 @@ public int CountIntercepts (float upperBounds, float lowerBounds, SKPaint paint // - internal static SKTextBlob GetObject (IntPtr handle) => + internal static SKTextBlob? GetObject (IntPtr handle) => handle == IntPtr.Zero ? null : new SKTextBlob (handle, true); } @@ -282,7 +279,7 @@ protected override void DisposeNative () => // Build - public SKTextBlob Build () + public SKTextBlob? Build () { var blob = SKTextBlob.GetObject (SkiaApi.sk_textblob_builder_make (Handle)); GC.KeepAlive (this); @@ -293,48 +290,36 @@ public SKTextBlob Build () public void AddRun (ReadOnlySpan glyphs, SKFont font, SKPoint origin = default) { - if (font == null) - throw new ArgumentNullException (nameof (font)); - - var buffer = AllocatePositionedRun (font, glyphs.Length); - glyphs.CopyTo (buffer.GetGlyphSpan ()); - font.GetGlyphPositions (buffer.GetGlyphSpan (), buffer.GetPositionSpan (), origin); + var buffer = AllocateRawPositionedRun (font, glyphs.Length); + glyphs.CopyTo (buffer.Glyphs); + font.GetGlyphPositions (buffer.Glyphs, buffer.Positions, origin); } // AddHorizontalRun public void AddHorizontalRun (ReadOnlySpan glyphs, SKFont font, ReadOnlySpan positions, float y) { - if (font == null) - throw new ArgumentNullException (nameof (font)); - - var buffer = AllocateHorizontalRun (font, glyphs.Length, y); - glyphs.CopyTo (buffer.GetGlyphSpan ()); - positions.CopyTo (buffer.GetPositionSpan ()); + var buffer = AllocateRawHorizontalRun (font, glyphs.Length, y); + glyphs.CopyTo (buffer.Glyphs); + positions.CopyTo (buffer.Positions); } // AddPositionedRun public void AddPositionedRun (ReadOnlySpan glyphs, SKFont font, ReadOnlySpan positions) { - if (font == null) - throw new ArgumentNullException (nameof (font)); - - var buffer = AllocatePositionedRun (font, glyphs.Length); - glyphs.CopyTo (buffer.GetGlyphSpan ()); - positions.CopyTo (buffer.GetPositionSpan ()); + var buffer = AllocateRawPositionedRun (font, glyphs.Length); + glyphs.CopyTo (buffer.Glyphs); + positions.CopyTo (buffer.Positions); } // AddRotationScaleRun public void AddRotationScaleRun (ReadOnlySpan glyphs, SKFont font, ReadOnlySpan positions) { - if (font == null) - throw new ArgumentNullException (nameof (font)); - - var buffer = AllocateRotationScaleRun (font, glyphs.Length); - glyphs.CopyTo (buffer.GetGlyphSpan ()); - positions.CopyTo (buffer.GetRotationScaleSpan ()); + var buffer = AllocateRawRotationScaleRun (font, glyphs.Length); + glyphs.CopyTo (buffer.Glyphs); + positions.CopyTo (buffer.Positions); } // AddPathPositionedRun @@ -390,9 +375,17 @@ public void AddPathPositionedRun (ReadOnlySpan glyphs, SKFont font, Read AddRotationScaleRun (glyphSubset, font, positions); } - // AllocateRun + // Allocate* + + // Allocate*Run public SKRunBuffer AllocateRun (SKFont font, int count, float x, float y, SKRect? bounds = null) + { + var buffer = AllocateRawRun (font, count, x, y, bounds); + return new SKRunBuffer (buffer.buffer, count); + } + + public SKRawRunBuffer AllocateRawRun (SKFont font, int count, float x, float y, SKRect? bounds = null) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -403,10 +396,16 @@ public SKRunBuffer AllocateRun (SKFont font, int count, float x, float y, SKRect else SkiaApi.sk_textblob_builder_alloc_run (Handle, font.Handle, count, x, y, null, &runbuffer); - return new SKRunBuffer (runbuffer, count); + return new SKRawRunBuffer (runbuffer, count, 0, 0); } public SKTextRunBuffer AllocateTextRun (SKFont font, int count, float x, float y, int textByteCount, SKRect? bounds = null) + { + var buffer = AllocateRawTextRun (font, count, x, y, textByteCount, bounds); + return new SKTextRunBuffer (buffer.buffer, count, textByteCount); + } + + public SKRawRunBuffer AllocateRawTextRun (SKFont font, int count, float x, float y, int textByteCount, SKRect? bounds = null) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -417,12 +416,18 @@ public SKTextRunBuffer AllocateTextRun (SKFont font, int count, float x, float y else SkiaApi.sk_textblob_builder_alloc_run_text (Handle, font.Handle, count, x, y, textByteCount, null, &runbuffer); - return new SKTextRunBuffer (runbuffer, count, textByteCount); + return new SKRawRunBuffer (runbuffer, count, 0, textByteCount); } - // AllocateHorizontalRun + // Allocate*HorizontalRun public SKHorizontalRunBuffer AllocateHorizontalRun (SKFont font, int count, float y, SKRect? bounds = null) + { + var buffer = AllocateRawHorizontalRun (font, count, y, bounds); + return new SKHorizontalRunBuffer (buffer.buffer, count); + } + + public SKRawRunBuffer AllocateRawHorizontalRun (SKFont font, int count, float y, SKRect? bounds = null) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -433,10 +438,16 @@ public SKHorizontalRunBuffer AllocateHorizontalRun (SKFont font, int count, floa else SkiaApi.sk_textblob_builder_alloc_run_pos_h (Handle, font.Handle, count, y, null, &runbuffer); - return new SKHorizontalRunBuffer (runbuffer, count); + return new SKRawRunBuffer (runbuffer, count, count, 0); } public SKHorizontalTextRunBuffer AllocateHorizontalTextRun (SKFont font, int count, float y, int textByteCount, SKRect? bounds = null) + { + var buffer = AllocateRawHorizontalTextRun (font, count, y, textByteCount, bounds); + return new SKHorizontalTextRunBuffer (buffer.buffer, count, textByteCount); + } + + public SKRawRunBuffer AllocateRawHorizontalTextRun (SKFont font, int count, float y, int textByteCount, SKRect? bounds = null) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -447,12 +458,19 @@ public SKHorizontalTextRunBuffer AllocateHorizontalTextRun (SKFont font, int cou else SkiaApi.sk_textblob_builder_alloc_run_text_pos_h (Handle, font.Handle, count, y, textByteCount, null, &runbuffer); - return new SKHorizontalTextRunBuffer (runbuffer, count, textByteCount); + return new SKRawRunBuffer (runbuffer, count, count, textByteCount); + } // AllocatePositionedRun public SKPositionedRunBuffer AllocatePositionedRun (SKFont font, int count, SKRect? bounds = null) + { + var buffer = AllocateRawPositionedRun (font, count, bounds); + return new SKPositionedRunBuffer (buffer.buffer, count); + } + + public SKRawRunBuffer AllocateRawPositionedRun (SKFont font, int count, SKRect? bounds = null) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -463,10 +481,16 @@ public SKPositionedRunBuffer AllocatePositionedRun (SKFont font, int count, SKRe else SkiaApi.sk_textblob_builder_alloc_run_pos (Handle, font.Handle, count, null, &runbuffer); - return new SKPositionedRunBuffer (runbuffer, count); + return new SKRawRunBuffer (runbuffer, count, count, 0); } public SKPositionedTextRunBuffer AllocatePositionedTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null) + { + var buffer = AllocateRawPositionedTextRun (font, count, textByteCount, bounds); + return new SKPositionedTextRunBuffer (buffer.buffer, count, textByteCount); + } + + public SKRawRunBuffer AllocateRawPositionedTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -477,12 +501,18 @@ public SKPositionedTextRunBuffer AllocatePositionedTextRun (SKFont font, int cou else SkiaApi.sk_textblob_builder_alloc_run_text_pos (Handle, font.Handle, count, textByteCount, null, &runbuffer); - return new SKPositionedTextRunBuffer (runbuffer, count, textByteCount); + return new SKRawRunBuffer (runbuffer, count, count, textByteCount); } // AllocateRotationScaleRun public SKRotationScaleRunBuffer AllocateRotationScaleRun (SKFont font, int count, SKRect? bounds = null) + { + var buffer = AllocateRawRotationScaleRun (font, count, bounds); + return new SKRotationScaleRunBuffer (buffer.buffer, count); + } + + public SKRawRunBuffer AllocateRawRotationScaleRun (SKFont font, int count, SKRect? bounds = null) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -493,10 +523,16 @@ public SKRotationScaleRunBuffer AllocateRotationScaleRun (SKFont font, int count else SkiaApi.sk_textblob_builder_alloc_run_rsxform (Handle, font.Handle, count, null, &runbuffer); - return new SKRotationScaleRunBuffer (runbuffer, count); + return new SKRawRunBuffer (runbuffer, count, count, 0); + } + + public SKRotationScaleTextRunBuffer AllocateRotationScaleTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null) + { + var buffer = AllocateRawRotationScaleTextRun (font, count, textByteCount, bounds); + return new SKRotationScaleTextRunBuffer (buffer.buffer, count, textByteCount); } - public SKRotationScaleRunBuffer AllocateRotationScaleTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null) + public SKRawRunBuffer AllocateRawRotationScaleTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null) { if (font == null) throw new ArgumentNullException (nameof (font)); @@ -507,7 +543,7 @@ public SKRotationScaleRunBuffer AllocateRotationScaleTextRun (SKFont font, int c else SkiaApi.sk_textblob_builder_alloc_run_text_rsxform (Handle, font.Handle, count, textByteCount, null, &runbuffer); - return new SKRotationScaleRunBuffer (runbuffer, count); + return new SKRawRunBuffer (runbuffer, count, count, textByteCount); } } } diff --git a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs index d03462caf8..8b39ae75d9 100644 --- a/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs +++ b/source/SkiaSharp.HarfBuzz/SkiaSharp.HarfBuzz/CanvasExtensions.cs @@ -74,11 +74,11 @@ public static void DrawShapedText(this SKCanvas canvas, SKShaper shaper, string // create the text blob using var builder = new SKTextBlobBuilder(); - var run = builder.AllocatePositionedRun(font, result.Codepoints.Length); + var run = builder.AllocateRawPositionedRun(font, result.Codepoints.Length, null); // copy the glyphs - var g = run.GetGlyphSpan(); - var p = run.GetPositionSpan(); + var g = run.Glyphs; + var p = run.Positions; for (var i = 0; i < result.Codepoints.Length; i++) { g[i] = (ushort)result.Codepoints[i]; diff --git a/tests/Tests/SkiaSharp/SKTextBlobTest.cs b/tests/Tests/SkiaSharp/SKTextBlobTest.cs index 32cb3e35cd..58785b35c7 100644 --- a/tests/Tests/SkiaSharp/SKTextBlobTest.cs +++ b/tests/Tests/SkiaSharp/SKTextBlobTest.cs @@ -16,6 +16,36 @@ public void TestEmptyBuilderReturnsNull() Assert.Null(blob); } + [SkippableFact] + public void RunsAllocateNoPositions() + { + var font = new SKFont(); + + using var builder = new SKTextBlobBuilder(); + + var run = builder.AllocateRun(font, 100, 0, 0); + Assert.Equal(100, run.Glyphs.Length); + + using var blob = builder.Build(); + Assert.NotNull(blob); + } + + [SkippableFact] + public void RawRunsAllocateNoPositions() + { + var font = new SKFont(); + + using var builder = new SKTextBlobBuilder(); + + var run = builder.AllocateRawRun(font, 100, 0, 0); + Assert.Equal(100, run.Glyphs.Length); + Assert.Equal(0, run.Positions.Length); + Assert.Equal(0, run.Text.Length); + + using var blob = builder.Build(); + Assert.NotNull(blob); + } + [SkippableFact] public void TextRunsAllocateTextSpan() { @@ -24,8 +54,23 @@ public void TextRunsAllocateTextSpan() using var builder = new SKTextBlobBuilder(); var run = builder.AllocateTextRun(font, 100, 0, 0, 50); - Assert.Equal(100, run.GetGlyphSpan().Length); - Assert.Equal(50, run.GetTextSpan().Length); + Assert.Equal(100, run.Glyphs.Length); + Assert.Equal(50, run.Text.Length); + + using var blob = builder.Build(); + Assert.NotNull(blob); + } + + [SkippableFact] + public void RawTextRunsAllocateTextSpan() + { + var font = new SKFont(); + + using var builder = new SKTextBlobBuilder(); + + var run = builder.AllocateRawTextRun(font, 100, 0, 0, 50); + Assert.Equal(100, run.Glyphs.Length); + Assert.Equal(50, run.Text.Length); using var blob = builder.Build(); Assert.NotNull(blob); @@ -112,7 +157,7 @@ public unsafe void TestPositionedRunIsBothPointsAndFloats() run.SetPositions(positions); - var span = run.GetPositionSpan(); + var span = run.Positions; Assert.Equal(positions, span.ToArray()); var floats = new float[6];