From 72c218145bac481f9b5eb07114764319f72e7693 Mon Sep 17 00:00:00 2001 From: LongYinan Date: Sat, 10 Aug 2024 22:48:03 +0800 Subject: [PATCH] feat: support load external image in svg --- .taplo.toml | 1 + Cargo.toml | 39 +++++++++++++++++---------------------- skia-c/skia_c.cpp | 11 +++++++++++ skia-c/skia_c.hpp | 42 ++++++++++++++++++++++++++++++++++++++---- src/sk.rs | 39 +++++++++++++++++++++++++++++++++++++++ 5 files changed, 106 insertions(+), 26 deletions(-) diff --git a/.taplo.toml b/.taplo.toml index df0b54ca..1957a688 100644 --- a/.taplo.toml +++ b/.taplo.toml @@ -5,3 +5,4 @@ exclude = ["node_modules/**/*.toml", "skia/**/*.toml"] align_entries = true indent_tables = true reorder_keys = true +column_width = 180 diff --git a/Cargo.toml b/Cargo.toml index 8b67f273..6f764a6a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -8,27 +8,22 @@ version = "0.1.0" crate-type = ["cdylib"] [dependencies] -anyhow = "1" -base64 = "0.22" -cssparser = "0.29" -infer = "0.16" -libavif = { version = "0.14", default-features = false, features = [ - "codec-aom", -] } -napi = { version = "2", default-features = false, features = [ - "napi3", - "serde-json", -] } -napi-derive = { version = "2", default-features = false } -nom = "7" -num_cpus = "1" -once_cell = "1" -regex = "1" -rgb = "0.8" -serde = "1" +anyhow = "1" +base64 = "0.22" +cssparser = "0.29" +infer = "0.16" +libavif = { version = "0.14", default-features = false, features = ["codec-aom"] } +napi = { version = "2", default-features = false, features = ["napi3", "serde-json"] } +napi-derive = { version = "2", default-features = false } +nom = "7" +num_cpus = "1" +once_cell = "1" +regex = "1" +rgb = "0.8" +serde = "1" serde_derive = "1" -serde_json = "1" -thiserror = "1" +serde_json = "1" +thiserror = "1" [target.'cfg(not(target_os = "linux"))'.dependencies] mimalloc = "0.1" @@ -41,6 +36,6 @@ cc = "1" napi-build = "2" [profile.release] -lto = true codegen-units = 1 -strip = "symbols" +lto = true +strip = "symbols" diff --git a/skia-c/skia_c.cpp b/skia-c/skia_c.cpp index 8427ea69..3b805995 100644 --- a/skia-c/skia_c.cpp +++ b/skia-c/skia_c.cpp @@ -1620,6 +1620,7 @@ extern "C" delete reinterpret_cast(c_sk_string); } + // FontCollection skiac_font_collection *skiac_font_collection_create() { return new skiac_font_collection(); @@ -1692,6 +1693,16 @@ extern "C" delete c_font_collection; } + // ResourceProvider + + skiac_resource_provider *skiac_resource_provider_create( + void *skiac_on_load_image_rust, + skiac_on_load_image on_load_image) + { + auto rp = ResourceProviderCustom::Make(skiac_on_load_image_rust, on_load_image); + return reinterpret_cast(rp.release()); + } + // SkWStream void skiac_sk_w_stream_get(skiac_w_memory_stream *c_w_memory_stream, skiac_sk_data *sk_data, int width, int height) { diff --git a/skia-c/skia_c.hpp b/skia-c/skia_c.hpp index a7c79da7..7d5744b3 100644 --- a/skia-c/skia_c.hpp +++ b/skia-c/skia_c.hpp @@ -73,6 +73,10 @@ typedef struct skiac_typeface_font_provider skiac_typeface_font_provider; typedef struct skiac_w_memory_stream skiac_w_memory_stream; typedef struct skiac_picture_recorder skiac_picture_recorder; typedef struct skiac_picture skiac_picture; +typedef struct skiac_resource_provider skiac_resource_provider; + +typedef void (*skiac_on_match_font_style)(int width, int weight, int slant, void *skiac_on_match_font_style_rust); +typedef void (*skiac_on_load_image)(const char *image_path, void *skiac_on_load_image_rust); #if defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(__NT__) #define SK_FONT_FILE_PREFIX "C:/Windows/Fonts" @@ -129,6 +133,29 @@ class TypefaceFontProviderCustom : public TypefaceFontProvider sk_sp font_mgr; }; +class ResourceProviderCustom: public skresources::ResourceProvider { + public: + static sk_sp Make(void *skiac_on_load_image_rust, skiac_on_load_image on_load_image) { + return sk_sp(new ResourceProviderCustom(skiac_on_load_image_rust, on_load_image)); + } + + sk_sp loadImageAsset(const char resource_path[], + const char resource_name[], + const char resource_id[]) const { + SkDebugf("loadImageAsset: %s %s %s\n", resource_path, resource_name, resource_id); + if (this->on_load_image) { + this->on_load_image(resource_path, this->skiac_on_load_image_rust); + } + return nullptr; + } + + private: + explicit ResourceProviderCustom(void* skiac_on_load_image_rust, skiac_on_load_image on_load_image) : skiac_on_load_image_rust(skiac_on_load_image_rust), on_load_image(on_load_image) {} + + void* skiac_on_load_image_rust; + skiac_on_load_image on_load_image; +}; + struct skiac_svg_surface { skiac_w_memory_stream *stream; @@ -207,8 +234,6 @@ struct skiac_string SkString *sk_string; }; -typedef void (*skiac_on_match_font_style)(int width, int weight, int slant, void *skiac_on_match_font_style_rust); - struct skiac_sk_data { const uint8_t *ptr; @@ -493,13 +518,22 @@ extern "C" // FontCollection skiac_font_collection *skiac_font_collection_create(); uint32_t skiac_font_collection_get_default_fonts_count(skiac_font_collection *c_font_collection); - void skiac_font_collection_get_family(skiac_font_collection *c_font_collection, uint32_t i, skiac_string *c_string, void *on_get_style_rust, skiac_on_match_font_style on_match_font_style); + void skiac_font_collection_get_family( + skiac_font_collection *c_font_collection, + uint32_t i, + skiac_string *c_string, + void *on_get_style_rust, + skiac_on_match_font_style on_match_font_style); size_t skiac_font_collection_register(skiac_font_collection *c_font_collection, const uint8_t *font, size_t length, const char *name_alias); size_t skiac_font_collection_register_from_path(skiac_font_collection *c_font_collection, const char *font_path, const char *name_alias); void skiac_font_collection_set_alias(skiac_font_collection *c_font_collection, const char *family, const char *alias); void skiac_font_collection_destroy(skiac_font_collection *c_font_collection); - // SkDynamicMemoryWStream + // ResourceProvider + + skiac_resource_provider *skiac_resource_provider_create(void *skiac_on_load_image_rust, skiac_on_load_image on_load_image); + + // SkWStream void skiac_sk_w_stream_get(skiac_w_memory_stream *c_w_memory_stream, skiac_sk_data *sk_data, int width, int height); void skiac_sk_w_stream_destroy(skiac_w_memory_stream *c_w_memory_stream); diff --git a/src/sk.rs b/src/sk.rs index 67d98757..a83db577 100644 --- a/src/sk.rs +++ b/src/sk.rs @@ -167,6 +167,12 @@ pub mod ffi { _unused: [u8; 0], } + #[repr(C)] + #[derive(Copy, Clone, Debug)] + pub struct skiac_resource_provider { + _unused: [u8; 0], + } + #[repr(C)] #[derive(Copy, Clone, Debug)] pub struct skiac_typeface_font_provider { @@ -222,6 +228,9 @@ pub mod ffi { pub type SkiacFontCollectionGetFamily = Option; + pub type SkiacResourceProviderLoadImage = + Option; + #[allow(clippy::duplicated_attributes)] // https://github.com/rust-lang/rust/issues/96192 #[link( @@ -883,6 +892,13 @@ pub mod ffi { pub fn skiac_font_collection_destroy(c_font_collection: *mut skiac_font_collection); + // ResourceProvider + + pub fn skiac_resource_provider_create( + on_load_image_rust: *mut c_void, + on_load_image: SkiacResourceProviderLoadImage, + ) -> *mut skiac_resource_provider; + // SkDynamicMemoryStream pub fn skiac_sk_w_stream_get( c_w_memory_stream: *mut skiac_w_memory_stream, @@ -3688,6 +3704,24 @@ pub struct FontStyleSet { pub styles: Vec, } +#[derive(Debug, Clone)] +pub struct ResourceProvider { + pub(crate) inner: *mut ffi::skiac_resource_provider, +} + +impl ResourceProvider { + pub fn new() -> Self { + let on_load_image = Box::new(|_resource: *const c_char| {}); + let inner = unsafe { + ffi::skiac_resource_provider_create( + Box::into_raw(on_load_image).cast(), + Some(skiac_on_load_image), + ) + }; + Self { inner } + } +} + #[derive(Debug, Clone)] pub struct SkWMemoryStream(*mut ffi::skiac_w_memory_stream); @@ -3774,6 +3808,11 @@ pub fn sk_svg_text_to_path(svg: &[u8], fc: &FontCollection) -> Option)); + cb(resource); +} + unsafe extern "C" fn skiac_on_get_style(width: i32, weight: i32, slant: i32, raw_cb: *mut c_void) { let cb = Box::leak(Box::from_raw(raw_cb as *mut Box)); cb(width, weight, slant);