Skip to content

Commit

Permalink
Adding back text-based blobs (#2545)
Browse files Browse the repository at this point in the history
  • Loading branch information
mattleibow authored Aug 1, 2023
1 parent a140a20 commit a956fd1
Show file tree
Hide file tree
Showing 3 changed files with 110 additions and 0 deletions.
51 changes: 51 additions & 0 deletions binding/SkiaSharp/SKRunBuffer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -63,4 +63,55 @@ public Span<SKRotationScaleMatrix> GetRotationScaleSpan () =>
public void SetRotationScale (ReadOnlySpan<SKRotationScaleMatrix> positions) =>
positions.CopyTo (GetRotationScaleSpan ());
}

public unsafe class SKTextRunBuffer : SKRunBuffer
{
internal SKTextRunBuffer (SKRunBufferInternal buffer, int count, int textSize)
: base (buffer, count)
{
TextSize = textSize;
}

public int TextSize { get; }

public Span<byte> GetTextSpan () =>
new Span<byte> (internalBuffer.utf8text, internalBuffer.utf8text == null ? 0 : TextSize);

public Span<uint> GetClusterSpan () =>
new Span<uint> (internalBuffer.clusters, internalBuffer.clusters == null ? 0 : Size);

public void SetText (ReadOnlySpan<byte> text) =>
text.CopyTo (GetTextSpan ());

public void SetClusters (ReadOnlySpan<uint> clusters) =>
clusters.CopyTo (GetClusterSpan ());
}

public sealed unsafe class SKHorizontalTextRunBuffer : SKTextRunBuffer
{
internal SKHorizontalTextRunBuffer (SKRunBufferInternal buffer, int count, int textSize)
: base (buffer, count, textSize)
{
}

public Span<float> GetPositionSpan () =>
new Span<float> (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size);

public void SetPositions (ReadOnlySpan<float> positions) =>
positions.CopyTo (GetPositionSpan ());
}

public sealed unsafe class SKPositionedTextRunBuffer : SKTextRunBuffer
{
internal SKPositionedTextRunBuffer (SKRunBufferInternal buffer, int count, int textSize)
: base (buffer, count, textSize)
{
}

public Span<SKPoint> GetPositionSpan () =>
new Span<SKPoint> (internalBuffer.pos, internalBuffer.pos == null ? 0 : Size);

public void SetPositions (ReadOnlySpan<SKPoint> positions) =>
positions.CopyTo (GetPositionSpan ());
}
}
42 changes: 42 additions & 0 deletions binding/SkiaSharp/SKTextBlob.cs
Original file line number Diff line number Diff line change
Expand Up @@ -404,6 +404,20 @@ public SKRunBuffer AllocateRun (SKFont font, int count, float x, float y, SKRect
return new SKRunBuffer (runbuffer, count);
}

public SKTextRunBuffer AllocateTextRun (SKFont font, int count, float x, float y, int textByteCount, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));

SKRunBufferInternal runbuffer;
if (bounds is SKRect b)
SkiaApi.sk_textblob_builder_alloc_run_text (Handle, font.Handle, count, x, y, textByteCount, &b, &runbuffer);
else
SkiaApi.sk_textblob_builder_alloc_run_text (Handle, font.Handle, count, x, y, textByteCount, null, &runbuffer);

return new SKTextRunBuffer (runbuffer, count, textByteCount);
}

// AllocateHorizontalRun

public SKHorizontalRunBuffer AllocateHorizontalRun (SKFont font, int count, float y, SKRect? bounds = null)
Expand All @@ -420,6 +434,20 @@ public SKHorizontalRunBuffer AllocateHorizontalRun (SKFont font, int count, floa
return new SKHorizontalRunBuffer (runbuffer, count);
}

public SKHorizontalTextRunBuffer AllocateHorizontalTextRun (SKFont font, int count, float y, int textByteCount, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));

SKRunBufferInternal runbuffer;
if (bounds is SKRect b)
SkiaApi.sk_textblob_builder_alloc_run_text_pos_h (Handle, font.Handle, count, y, textByteCount, &b, &runbuffer);
else
SkiaApi.sk_textblob_builder_alloc_run_text_pos_h (Handle, font.Handle, count, y, textByteCount, null, &runbuffer);

return new SKHorizontalTextRunBuffer (runbuffer, count, textByteCount);
}

// AllocatePositionedRun

public SKPositionedRunBuffer AllocatePositionedRun (SKFont font, int count, SKRect? bounds = null)
Expand All @@ -436,6 +464,20 @@ public SKPositionedRunBuffer AllocatePositionedRun (SKFont font, int count, SKRe
return new SKPositionedRunBuffer (runbuffer, count);
}

public SKPositionedTextRunBuffer AllocatePositionedTextRun (SKFont font, int count, int textByteCount, SKRect? bounds = null)
{
if (font == null)
throw new ArgumentNullException (nameof (font));

SKRunBufferInternal runbuffer;
if (bounds is SKRect b)
SkiaApi.sk_textblob_builder_alloc_run_text_pos (Handle, font.Handle, count, textByteCount, &b, &runbuffer);
else
SkiaApi.sk_textblob_builder_alloc_run_text_pos (Handle, font.Handle, count, textByteCount, null, &runbuffer);

return new SKPositionedTextRunBuffer (runbuffer, count, textByteCount);
}

// AllocateRotationScaleRun

public SKRotationScaleRunBuffer AllocateRotationScaleRun (SKFont font, int count)
Expand Down
17 changes: 17 additions & 0 deletions tests/Tests/SkiaSharp/SKTextBlobTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,23 @@ public void TestEmptyBuilderReturnsNull()
Assert.Null(blob);
}

[SkippableFact]
public void NonGlyphTextEncodingDoesNotThrow()
{
using var paint = new SKPaint { TextEncoding = SKTextEncoding.Utf16 };

using var builder = new SKTextBlobBuilder();

var run = builder.AllocateTextRun(paint.GetFont(), 100, 0, 0, 50);
Assert.Equal(100, run.GetGlyphSpan().Length);
Assert.Equal(50, run.GetTextSpan().Length);

using var blob = builder.Build();
Assert.NotNull(blob);

Assert.Equal(SKTextEncoding.Utf16, paint.TextEncoding);
}

[SkippableFact]
public void TestExplicitBounds()
{
Expand Down

0 comments on commit a956fd1

Please sign in to comment.