-
Notifications
You must be signed in to change notification settings - Fork 546
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support loading animations with BOM #2167
Changes from 1 commit
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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; | ||
Comment on lines
+22
to
+29
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. BOM detection. Right now just the basic UTF-7/8/16/32 |
||
else | ||
return 0; | ||
} | ||
|
||
internal static Span<byte> AsSpan (this IntPtr ptr, int size) => | ||
new Span<byte> ((void*)ptr, size); | ||
|
||
|
@@ -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, | ||
|
@@ -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, | ||
|
@@ -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), | ||
|
@@ -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), | ||
|
@@ -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), | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -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 | ||
|
@@ -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 | ||
|
@@ -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); | ||
Comment on lines
-59
to
+64
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. All animations are now created through the SKData overload, which we then use to detect the BOM. We could use the stream, but then we have to use buffering and all other manner of complex mechanisms. This way we load the full data, and then optionally skip 4 bytes before passing it to C++. |
||
} | ||
|
||
public static Animation? Create (SKData data) => | ||
|
@@ -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) => | ||
|
@@ -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); | ||
|
||
|
@@ -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)); | ||
|
||
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This was a bug I found when you pass a stream that was not at 0. This can be used to create a data object from a section of a stream.