Skip to content

Commit

Permalink
Support loading animations with BOM (#2167)
Browse files Browse the repository at this point in the history
* Support loading animations with BOM

Fixes #2166

* New .NET version that just came out
  • Loading branch information
mattleibow authored Jul 14, 2022
1 parent 0f25051 commit 8f81be2
Show file tree
Hide file tree
Showing 7 changed files with 7,529 additions and 54 deletions.
2 changes: 1 addition & 1 deletion binding/Binding/SKData.cs
Original file line number Diff line number Diff line change
Expand Up @@ -103,7 +103,7 @@ public static SKData Create (Stream stream)
if (stream == null)
throw new ArgumentNullException (nameof (stream));
if (stream.CanSeek) {
return Create (stream, stream.Length);
return Create (stream, stream.Length - stream.Position);
} else {
using var memory = new SKDynamicMemoryWStream ();
using (var managed = new SKManagedStream (stream)) {
Expand Down
34 changes: 24 additions & 10 deletions binding/Binding/Util.cs
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,25 @@ internal unsafe static class Utils
{
internal const float NearlyZero = 1.0f / (1 << 12);

internal static int GetPreambleSize (SKData data)
{
_ = data ?? throw new ArgumentNullException (nameof (data));

var buffer = data.AsSpan ();
var len = buffer.Length;

if (len >= 2 && buffer[0] == 0xfe && buffer[1] == 0xff)
return 2;
else if (len >= 3 && buffer[0] == 0xef && buffer[1] == 0xbb && buffer[2] == 0xbf)
return 3;
else if (len >= 3 && buffer[0] == 0x2b && buffer[1] == 0x2f && buffer[2] == 0x76)
return 3;
else if (len >= 4 && buffer[0] == 0 && buffer[1] == 0 && buffer[2] == 0xfe && buffer[3] == 0xff)
return 4;
else
return 0;
}

internal static Span<byte> AsSpan (this IntPtr ptr, int size) =>
new Span<byte> ((void*)ptr, size);

Expand Down Expand Up @@ -105,8 +124,7 @@ public unsafe static class StringUtilities
// GetUnicodeStringLength

private static int GetUnicodeStringLength (SKTextEncoding encoding) =>
encoding switch
{
encoding switch {
SKTextEncoding.Utf8 => 1,
SKTextEncoding.Utf16 => 1,
SKTextEncoding.Utf32 => 2,
Expand All @@ -116,8 +134,7 @@ private static int GetUnicodeStringLength (SKTextEncoding encoding) =>
// GetCharacterByteSize

internal static int GetCharacterByteSize (this SKTextEncoding encoding) =>
encoding switch
{
encoding switch {
SKTextEncoding.Utf8 => 1,
SKTextEncoding.Utf16 => 2,
SKTextEncoding.Utf32 => 4,
Expand Down Expand Up @@ -156,8 +173,7 @@ internal static byte[] GetEncodedText (string text, SKTextEncoding encoding, boo
}

public static byte[] GetEncodedText (ReadOnlySpan<char> text, SKTextEncoding encoding) =>
encoding switch
{
encoding switch {
SKTextEncoding.Utf8 => Encoding.UTF8.GetBytes (text),
SKTextEncoding.Utf16 => Encoding.Unicode.GetBytes (text),
SKTextEncoding.Utf32 => Encoding.UTF32.GetBytes (text),
Expand All @@ -177,8 +193,7 @@ public static string GetString (byte[] data, int index, int count, SKTextEncodin
if (data == null)
throw new ArgumentNullException (nameof (data));

return encoding switch
{
return encoding switch {
SKTextEncoding.Utf8 => Encoding.UTF8.GetString (data, index, count),
SKTextEncoding.Utf16 => Encoding.Unicode.GetString (data, index, count),
SKTextEncoding.Utf32 => Encoding.UTF32.GetString (data, index, count),
Expand All @@ -197,8 +212,7 @@ public static string GetString (ReadOnlySpan<byte> data, int index, int count, S
return string.Empty;

fixed (byte* bp = data) {
return encoding switch
{
return encoding switch {
SKTextEncoding.Utf8 => Encoding.UTF8.GetString (bp, data.Length),
SKTextEncoding.Utf16 => Encoding.Unicode.GetString (bp, data.Length),
SKTextEncoding.Utf32 => Encoding.UTF32.GetString (bp, data.Length),
Expand Down
27 changes: 21 additions & 6 deletions binding/SkiaSharp.Skottie/Animation.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,8 @@ void ISKNonVirtualReferenceCounted.UnreferenceNative ()
protected override void DisposeNative ()
=> SkottieApi.skottie_animation_delete (Handle);

// Parse

public static Animation? Parse (string json) =>
TryParse (json, out var animation)
? animation
Expand All @@ -34,6 +36,8 @@ public static bool TryParse (string json, [System.Diagnostics.CodeAnalysis.NotNu
return animation != null;
}

// Create

public static Animation? Create (Stream stream) =>
TryCreate (stream, out var animation)
? animation
Expand All @@ -56,8 +60,8 @@ public static bool TryCreate (SKStream stream, [System.Diagnostics.CodeAnalysis.
{
_ = stream ?? throw new ArgumentNullException (nameof (stream));

animation = GetObject (SkottieApi.skottie_animation_make_from_stream (stream.Handle));
return animation != null;
using var data = SKData.Create (stream);
return TryCreate (data, out animation);
}

public static Animation? Create (SKData data) =>
Expand All @@ -69,8 +73,13 @@ public static bool TryCreate (SKData data, [System.Diagnostics.CodeAnalysis.NotN
{
_ = data ?? throw new ArgumentNullException (nameof (data));

animation = GetObject (SkottieApi.skottie_animation_make_from_data ((void*)data.Data, (IntPtr)data.Size));
return animation != null;
var preamble = Utils.GetPreambleSize (data);
var span = data.AsSpan ().Slice (preamble);

fixed (byte* ptr = span) {
animation = GetObject (SkottieApi.skottie_animation_make_from_data (ptr, (IntPtr)span.Length));
return animation != null;
}
}

public static Animation? Create (string path) =>
Expand All @@ -82,16 +91,20 @@ public static bool TryCreate (string path, [System.Diagnostics.CodeAnalysis.NotN
{
_ = path ?? throw new ArgumentNullException (nameof (path));

animation = GetObject (SkottieApi.skottie_animation_make_from_file (path));
return animation != null;
using var data = SKData.Create (path);
return TryCreate (data, out animation);
}

// Render

public unsafe void Render (SKCanvas canvas, SKRect dst)
=> SkottieApi.skottie_animation_render (Handle, canvas.Handle, &dst);

public void Render (SKCanvas canvas, SKRect dst, AnimationRenderFlags flags)
=> SkottieApi.skottie_animation_render_with_flags (Handle, canvas.Handle, &dst, flags);

// Seek*

public void Seek (double percent, InvalidationController? ic = null)
=> SkottieApi.skottie_animation_seek (Handle, (float)percent, ic?.Handle ?? IntPtr.Zero);

Expand All @@ -104,6 +117,8 @@ public void SeekFrameTime (double seconds, InvalidationController? ic = null)
public void SeekFrameTime (TimeSpan time, InvalidationController? ic = null)
=> SeekFrameTime (time.TotalSeconds, ic);

// Properties

public TimeSpan Duration
=> TimeSpan.FromSeconds (SkottieApi.skottie_animation_get_duration (Handle));

Expand Down
2 changes: 1 addition & 1 deletion scripts/azure-pipelines-variables.yml
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ variables:
MONO_VERSION_LINUX: ''
XCODE_VERSION: 13.2.1
VISUAL_STUDIO_VERSION: '17/pre'
DOTNET_VERSION_PREVIEW: '6.0.301'
DOTNET_VERSION_PREVIEW: '6.0.302'
DOTNET_WORKLOAD_SOURCE: 'https://aka.ms/dotnet/maui/6.0.300.json'
CONFIGURATION: 'Release'
DOTNET_SKIP_FIRST_TIME_EXPERIENCE: true
Expand Down
Loading

0 comments on commit 8f81be2

Please sign in to comment.