From 8e7a3aa31b76f3e16e561eead4c938a8fbbd520f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=B4me=20Laban?= Date: Tue, 31 May 2022 14:20:40 -0400 Subject: [PATCH] feat: Add basic Skottie C binding (#84) --- BUILD.gn | 1 + gn/core.gni | 2 + include/c/sk_types.h | 17 +++++ include/c/skottie_animation.h | 48 +++++++++++++ include/c/sksg_invalidation_controller.h | 28 ++++++++ src/c/sk_enums.cpp | 4 ++ src/c/sk_types_priv.h | 71 +++++++++++-------- src/c/skottie_animation.cpp | 89 ++++++++++++++++++++++++ src/c/sksg_invalidation_controller.cpp | 35 ++++++++++ src/xamarin/SkiaKeeper.c | 10 +++ 10 files changed, 276 insertions(+), 29 deletions(-) create mode 100644 include/c/skottie_animation.h create mode 100644 include/c/sksg_invalidation_controller.h create mode 100644 src/c/skottie_animation.cpp create mode 100644 src/c/sksg_invalidation_controller.cpp diff --git a/BUILD.gn b/BUILD.gn index f5bd897bd18f..ab3e49302dcc 100644 --- a/BUILD.gn +++ b/BUILD.gn @@ -3084,6 +3084,7 @@ skiasharp_build("SkiaSharp") { deps = [ ":skia", + "modules/skottie", ] # clear the sources and add explicitly diff --git a/gn/core.gni b/gn/core.gni index 7b62922f8e92..cc3db1a8843d 100644 --- a/gn/core.gni +++ b/gn/core.gni @@ -173,6 +173,8 @@ skia_core_sources = [ "$_src/c/sk_vertices.cpp", "$_src/c/sk_xml.cpp", "$_src/c/gr_context.cpp", + "$_src/c/skottie_animation.cpp", + "$_src/c/sksg_invalidation_controller.cpp", "$_src/core/Sk4px.h", "$_src/core/SkAAClip.cpp", diff --git a/include/c/sk_types.h b/include/c/sk_types.h index cd1632966c51..289ecaee92ee 100644 --- a/include/c/sk_types.h +++ b/include/c/sk_types.h @@ -1011,6 +1011,23 @@ typedef struct sk_tracememorydump_t sk_tracememorydump_t; typedef struct sk_runtimeeffect_t sk_runtimeeffect_t; typedef struct sk_runtimeeffect_uniform_t sk_runtimeeffect_uniform_t; +/* + * Skottie Animation + */ +typedef struct skottie_animation_t skottie_animation_t; +typedef struct skottie_animation_builder_t skottie_animation_builder_t; +typedef struct skottie_resource_provider_t skottie_resource_provider_t; +typedef struct skottie_property_observer_t skottie_property_observer_t; +typedef struct skottie_logger_t skottie_logger_t; +typedef struct skottie_marker_observer_t skottie_marker_observer_t; + +typedef struct sksg_invalidation_controller_t sksg_invalidation_controller_t; + +typedef enum { + SKIP_TOP_LEVEL_ISOLATION = 0x01, + DISABLE_TOP_LEVEL_CLIPPING = 0x02, +} skottie_animation_renderflags_t; + SK_C_PLUS_PLUS_END_GUARD #endif diff --git a/include/c/skottie_animation.h b/include/c/skottie_animation.h new file mode 100644 index 000000000000..43bb9e2adaa1 --- /dev/null +++ b/include/c/skottie_animation.h @@ -0,0 +1,48 @@ +/* + * Copyright 2014 Google Inc. + * Copyright 2015 Xamarin Inc. + * Copyright 2017 Microsoft Corporation. All rights reserved. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef skottie_DEFINED +#define skottie_DEFINED + +#include "include/c/sk_types.h" + +SK_C_PLUS_PLUS_BEGIN_GUARD + +/* + * skottie::Animation + */ +SK_C_API void skottie_animation_keepalive(); + +SK_C_API skottie_animation_t* skottie_animation_make_from_string(const char* data, size_t length); +SK_C_API skottie_animation_t* skottie_animation_make_from_stream(sk_stream_t* stream); +SK_C_API skottie_animation_t* skottie_animation_make_from_file(const char* path); + +SK_C_API void skottie_animation_ref(skottie_animation_t* instance); +SK_C_API void skottie_animation_unref(skottie_animation_t* instance); + +SK_C_API void skottie_animation_delete(skottie_animation_t *instance); + +SK_C_API void skottie_animation_render(skottie_animation_t *instance, sk_canvas_t *canvas, sk_rect_t *dst); +SK_C_API void skottie_animation_render_with_flags(skottie_animation_t *instance, sk_canvas_t *canvas, sk_rect_t *dst, skottie_animation_renderflags_t flags); + +SK_C_API void skottie_animation_seek(skottie_animation_t *instance, float t, sksg_invalidation_controller_t *ic); +SK_C_API void skottie_animation_seek_frame(skottie_animation_t *instance, float t, sksg_invalidation_controller_t *ic); +SK_C_API void skottie_animation_seek_frame_time(skottie_animation_t *instance, float t, sksg_invalidation_controller_t *ic); + +SK_C_API double skottie_animation_get_duration(skottie_animation_t *instance); +SK_C_API double skottie_animation_get_fps(skottie_animation_t *instance); +SK_C_API double skottie_animation_get_in_point(skottie_animation_t *instance); +SK_C_API double skottie_animation_get_out_point(skottie_animation_t *instance); + +SK_C_API void skottie_animation_get_version(skottie_animation_t *instance, sk_string_t* version); +SK_C_API void skottie_animation_get_size(skottie_animation_t *instance, sk_size_t* size); + +SK_C_PLUS_PLUS_END_GUARD + +#endif diff --git a/include/c/sksg_invalidation_controller.h b/include/c/sksg_invalidation_controller.h new file mode 100644 index 000000000000..cc2a3c601760 --- /dev/null +++ b/include/c/sksg_invalidation_controller.h @@ -0,0 +1,28 @@ +/* + * Copyright 2014 Google Inc. + * Copyright 2015 Xamarin Inc. + * Copyright 2017 Microsoft Corporation. All rights reserved. + * + * Use of this source code is governed by a BSD-style license that can be + * found in the LICENSE file. + */ + +#ifndef sksg_invalidationcontroller_DEFINED +#define sksg_invalidationcontroller_DEFINED + +#include "include/c/sk_types.h" + +SK_C_PLUS_PLUS_BEGIN_GUARD + +SK_C_API sksg_invalidation_controller_t* sksg_invalidation_controller_new(); +SK_C_API void sksg_invalidation_controller_delete(sksg_invalidation_controller_t* instance); + +SK_C_API void sksg_invalidation_controller_inval(sksg_invalidation_controller_t* instance, sk_rect_t* rect, sk_matrix_t* matrix); +SK_C_API void sksg_invalidation_controller_get_bounds(sksg_invalidation_controller_t* instance, sk_rect_t* bounds); +SK_C_API void sksg_invalidation_controller_begin(sksg_invalidation_controller_t* instance); +SK_C_API void sksg_invalidation_controller_end(sksg_invalidation_controller_t* instance); +SK_C_API void sksg_invalidation_controller_reset(sksg_invalidation_controller_t* instance); + +SK_C_PLUS_PLUS_END_GUARD + +#endif diff --git a/src/c/sk_enums.cpp b/src/c/sk_enums.cpp index cd308ea60885..4505ac8a8dcb 100644 --- a/src/c/sk_enums.cpp +++ b/src/c/sk_enums.cpp @@ -371,6 +371,10 @@ static_assert ((int)SkRRect::Corner::kUpperRight_Corner == (int)UPPER_RIGHT_SK static_assert ((int)SkRRect::Corner::kLowerRight_Corner == (int)LOWER_RIGHT_SK_RRECT_CORNER, ASSERT_MSG(SkRRect::Corner, sk_rrect_corner_t)); static_assert ((int)SkRRect::Corner::kLowerLeft_Corner == (int)LOWER_LEFT_SK_RRECT_CORNER, ASSERT_MSG(SkRRect::Corner, sk_rrect_corner_t)); +// skottie_animation_renderflags_t +static_assert ((int)skottie::Animation::kSkipTopLevelIsolation == (int)SKIP_TOP_LEVEL_ISOLATION, ASSERT_MSG(skottie::Animation, skottie_animation_renderflags_t)); +static_assert ((int)skottie::Animation::kDisableTopLevelClipping == (int)DISABLE_TOP_LEVEL_CLIPPING, ASSERT_MSG(skottie::Animation, skottie_animation_renderflags_t)); + #if SK_SUPPORT_GPU // gr_surfaceorigin_t diff --git a/src/c/sk_types_priv.h b/src/c/sk_types_priv.h index 20649843b5e1..af460d8994d0 100644 --- a/src/c/sk_types_priv.h +++ b/src/c/sk_types_priv.h @@ -55,42 +55,44 @@ // - C | sk_type | sk_some_type_t // - Map | Name | ToSomeType / AsSomeType // -#define DEF_MAP_DECL(SkType, sk_type, Name, Declaration) \ - Declaration; \ - static inline const SkType& As##Name(const sk_type& t) { \ - return reinterpret_cast(t); \ - } \ - static inline const SkType* As##Name(const sk_type* t) { \ - return reinterpret_cast(t); \ - } \ - static inline SkType& As##Name(sk_type& t) { \ - return reinterpret_cast(t); \ - } \ - static inline SkType* As##Name(sk_type* t) { \ - return reinterpret_cast(t); \ - } \ - static inline const sk_type& To##Name(const SkType& t) { \ - return reinterpret_cast(t); \ - } \ - static inline const sk_type* To##Name(const SkType* t) { \ - return reinterpret_cast(t); \ - } \ - static inline sk_type& To##Name(SkType& t) { \ - return reinterpret_cast(t); \ - } \ - static inline sk_type* To##Name(SkType* t) { \ - return reinterpret_cast(t); \ +#define DEF_MAP_DECL(SkType, sk_type, Name, Declaration, Ns) \ + Declaration; \ + static inline const Ns::SkType& As##Name(const sk_type& t) { \ + return reinterpret_cast(t); \ + } \ + static inline const Ns::SkType* As##Name(const sk_type* t) { \ + return reinterpret_cast(t); \ + } \ + static inline Ns::SkType& As##Name(sk_type& t) { \ + return reinterpret_cast(t); \ + } \ + static inline Ns::SkType* As##Name(sk_type* t) { \ + return reinterpret_cast(t); \ + } \ + static inline const sk_type& To##Name(const Ns::SkType& t) { \ + return reinterpret_cast(t); \ + } \ + static inline const sk_type* To##Name(const Ns::SkType* t) { \ + return reinterpret_cast(t); \ + } \ + static inline sk_type& To##Name(Ns::SkType& t) { \ + return reinterpret_cast(t); \ + } \ + static inline sk_type* To##Name(Ns::SkType* t) { \ + return reinterpret_cast(t); \ } #define DEF_CLASS_MAP(SkType, sk_type, Name) \ - DEF_MAP_DECL(SkType, sk_type, Name, class SkType) + DEF_MAP_DECL(SkType, sk_type, Name, class SkType, ) + +#define DEF_CLASS_MAP_WITH_NS(Ns, SkType, sk_type, Name) \ + DEF_MAP_DECL(SkType, sk_type, Name, class SkType, Ns) #define DEF_STRUCT_MAP(SkType, sk_type, Name) \ - DEF_MAP_DECL(SkType, sk_type, Name, struct SkType) + DEF_MAP_DECL(SkType, sk_type, Name, struct SkType, ) #define DEF_MAP(SkType, sk_type, Name) \ - DEF_MAP_DECL(SkType, sk_type, Name, ) - + DEF_MAP_DECL(SkType, sk_type, Name, ,) DEF_CLASS_MAP(Sk3DView, sk_3dview_t, 3DView) DEF_CLASS_MAP(SkBitmap, sk_bitmap_t, Bitmap) @@ -321,6 +323,17 @@ static inline SkPDF::Metadata AsDocumentPDFMetadata(const sk_document_pdf_metada return md; } +#include "modules/skottie/include/Skottie.h" +DEF_CLASS_MAP_WITH_NS(skottie, Animation, skottie_animation_t, SkottieAnimation) + +DEF_CLASS_MAP_WITH_NS(skottie, ResourceProvider, skottie_resource_provider_t, SkottieResourceProvider) +DEF_CLASS_MAP_WITH_NS(skottie, PropertyObserver, skottie_property_observer_t, SkottiePropertyObserver) +DEF_CLASS_MAP_WITH_NS(skottie, Logger, skottie_logger_t, SkottieLogger) +DEF_CLASS_MAP_WITH_NS(skottie, MarkerObserver, skottie_marker_observer_t, SkottieMarkerObserver) + +#include "modules/sksg/include/SkSGInvalidationController.h" +DEF_CLASS_MAP_WITH_NS(sksg, InvalidationController, sksg_invalidation_controller_t, SksgInvalidationController) + #if SK_SUPPORT_GPU // GPU specific diff --git a/src/c/skottie_animation.cpp b/src/c/skottie_animation.cpp new file mode 100644 index 000000000000..d8b2d8da0e18 --- /dev/null +++ b/src/c/skottie_animation.cpp @@ -0,0 +1,89 @@ +#include "modules/skottie/include/Skottie.h" +#include "modules/skresources/include/SkResources.h" +#include "modules/sksg/include/SkSGInvalidationController.h" +#include "include/c/skottie_animation.h" + +#include "src/c/sk_types_priv.h" + +#include "src/utils/SkJSON.h" +#include "include/core/SkCubicMap.h" + +void skottie_animation_keepalive() { + // This function is needed on Tizen to ensure required types are kept alive + // It is not meant to be executed. + + skjson::ObjectValue* a; + auto r = (*a)["tmp"]; + + SkCubicMap* b; + (*b).computeYFromX(.0f); +} + +void skottie_animation_ref(skottie_animation_t* instance) { + SkSafeRef(AsSkottieAnimation(instance)); +} + +void skottie_animation_unref(skottie_animation_t* instance) { + SkSafeUnref(AsSkottieAnimation(instance)); +} + +skottie_animation_t* skottie_animation_make_from_string(const char* data, size_t length) { + auto animation = skottie::Animation::Make(data, length); + return ToSkottieAnimation(animation.release()); +} + +skottie_animation_t* skottie_animation_make_from_stream(sk_stream_t* stream) { + return ToSkottieAnimation(skottie::Animation::Make(AsStream(stream)).release()); +} + +skottie_animation_t* skottie_animation_make_from_file(const char* path) { + return ToSkottieAnimation(skottie::Animation::MakeFromFile(path).release()); +} + +void skottie_animation_delete(skottie_animation_t* instance) { + delete AsSkottieAnimation(instance); +} + +void skottie_animation_render(skottie_animation_t *instance, sk_canvas_t *canvas, sk_rect_t *dst) { + AsSkottieAnimation(instance)->render(AsCanvas(canvas), AsRect(dst)); +} + +void skottie_animation_render_with_flags(skottie_animation_t *instance, sk_canvas_t *canvas, sk_rect_t *dst, skottie_animation_renderflags_t flags) { + AsSkottieAnimation(instance)->render(AsCanvas(canvas), AsRect(dst), (skottie::Animation::RenderFlags)(flags)); +} + +void skottie_animation_seek(skottie_animation_t *instance, float t, sksg_invalidation_controller_t *ic) { + AsSkottieAnimation(instance)->seek(t, AsSksgInvalidationController(ic)); +} + +void skottie_animation_seek_frame(skottie_animation_t *instance, float t, sksg_invalidation_controller_t *ic) { + AsSkottieAnimation(instance)->seekFrame(t, AsSksgInvalidationController(ic)); +} + +void skottie_animation_seek_frame_time(skottie_animation_t *instance, float t, sksg_invalidation_controller_t *ic) { + AsSkottieAnimation(instance)->seekFrameTime(t, AsSksgInvalidationController(ic)); +} + +double skottie_animation_get_duration(skottie_animation_t *instance) { + return AsSkottieAnimation(instance)->duration(); +} + +double skottie_animation_get_fps(skottie_animation_t *instance) { + return AsSkottieAnimation(instance)->fps(); +} + +double skottie_animation_get_in_point(skottie_animation_t *instance) { + return AsSkottieAnimation(instance)->inPoint(); +} + +double skottie_animation_get_out_point(skottie_animation_t *instance) { + return AsSkottieAnimation(instance)->outPoint(); +} + +void skottie_animation_get_version(skottie_animation_t *instance, sk_string_t* version) { + AsString(version)->set(AsSkottieAnimation(instance)->version()); +} + +void skottie_animation_get_size(skottie_animation_t *instance, sk_size_t* size) { + *size = ToSize(AsSkottieAnimation(instance)->size()); +} \ No newline at end of file diff --git a/src/c/sksg_invalidation_controller.cpp b/src/c/sksg_invalidation_controller.cpp new file mode 100644 index 000000000000..c6a6bc403f75 --- /dev/null +++ b/src/c/sksg_invalidation_controller.cpp @@ -0,0 +1,35 @@ +#include "modules/skottie/include/Skottie.h" +#include "modules/skresources/include/SkResources.h" +#include "modules/sksg/include/SkSGInvalidationController.h" +#include "include/c/skottie_animation.h" +#include "include/c/sksg_invalidation_controller.h" + +#include "src/c/sk_types_priv.h" + +sksg_invalidation_controller_t* sksg_invalidation_controller_new() { + return ToSksgInvalidationController(new sksg::InvalidationController()); +} + +void sksg_invalidation_controller_delete(sksg_invalidation_controller_t* instance) { + delete AsSksgInvalidationController(instance); +} + +void sksg_invalidation_controller_inval(sksg_invalidation_controller_t* instance, sk_rect_t* rect, sk_matrix_t* matrix) { + AsSksgInvalidationController(instance)->inval(*AsRect(rect), AsMatrix(matrix)); +} + +void sksg_invalidation_controller_get_bounds(sksg_invalidation_controller_t* instance, sk_rect_t* bounds) { + *bounds = ToRect(AsSksgInvalidationController(instance)->bounds()); +} + +void sksg_invalidation_controller_begin(sksg_invalidation_controller_t* instance) { + AsSksgInvalidationController(instance)->begin(); +} + +void sksg_invalidation_controller_end(sksg_invalidation_controller_t* instance) { + AsSksgInvalidationController(instance)->end(); +} + +void sksg_invalidation_controller_reset(sksg_invalidation_controller_t* instance) { + AsSksgInvalidationController(instance)->reset(); +} \ No newline at end of file diff --git a/src/xamarin/SkiaKeeper.c b/src/xamarin/SkiaKeeper.c index ae5599073bfa..67f482881e68 100644 --- a/src/xamarin/SkiaKeeper.c +++ b/src/xamarin/SkiaKeeper.c @@ -45,6 +45,11 @@ #include "include/c/sk_vertices.h" #include "include/c/sk_xml.h" +// Skottie +#include "include/c/skottie_animation.h" +#include "include/c/sksg_invalidation_controller.h" + + // Xamarin #include "include/xamarin/sk_managedstream.h" #include "include/xamarin/sk_manageddrawable.h" @@ -94,6 +99,11 @@ void** KeepSkiaCSymbols (void) (void*)sk_vertices_unref, (void*)sk_graphics_init, + // Animation + (void*)skottie_animation_make_from_stream, + (void*)sksg_invalidation_controller_new, + (void*)skottie_animation_keepalive, + // Xamarin (void*)sk_compatpaint_new, (void*)sk_managedstream_new,