Skip to content
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

feat: support load external image in svg #869

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .taplo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -5,3 +5,4 @@ exclude = ["node_modules/**/*.toml", "skia/**/*.toml"]
align_entries = true
indent_tables = true
reorder_keys = true
column_width = 180
39 changes: 17 additions & 22 deletions Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -41,6 +36,6 @@ cc = "1"
napi-build = "2"

[profile.release]
lto = true
codegen-units = 1
strip = "symbols"
lto = true
strip = "symbols"
11 changes: 11 additions & 0 deletions skia-c/skia_c.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1620,6 +1620,7 @@ extern "C"
delete reinterpret_cast<SkString *>(c_sk_string);
}

// FontCollection
skiac_font_collection *skiac_font_collection_create()
{
return new skiac_font_collection();
Expand Down Expand Up @@ -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<skiac_resource_provider *>(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)
{
Expand Down
42 changes: 38 additions & 4 deletions skia-c/skia_c.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand Down Expand Up @@ -129,6 +133,29 @@ class TypefaceFontProviderCustom : public TypefaceFontProvider
sk_sp<SkFontMgr> font_mgr;
};

class ResourceProviderCustom: public skresources::ResourceProvider {
public:
static sk_sp<ResourceProviderCustom> Make(void *skiac_on_load_image_rust, skiac_on_load_image on_load_image) {
return sk_sp<ResourceProviderCustom>(new ResourceProviderCustom(skiac_on_load_image_rust, on_load_image));
}

sk_sp<skresources::ImageAsset> 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;
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);

Expand Down
39 changes: 39 additions & 0 deletions src/sk.rs
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down Expand Up @@ -222,6 +228,9 @@ pub mod ffi {
pub type SkiacFontCollectionGetFamily =
Option<unsafe extern "C" fn(width: i32, weight: i32, slant: i32, raw_cb: *mut c_void)>;

pub type SkiacResourceProviderLoadImage =
Option<unsafe extern "C" fn(resource_path: *const c_char, on_load_image: *mut c_void)>;

#[allow(clippy::duplicated_attributes)]
// https://github.com/rust-lang/rust/issues/96192
#[link(
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -3688,6 +3704,24 @@ pub struct FontStyleSet {
pub styles: Vec<FontStyles>,
}

#[derive(Debug, Clone)]
pub struct ResourceProvider {
pub(crate) inner: *mut ffi::skiac_resource_provider,
}

impl ResourceProvider {
pub fn new<F: FnOnce(String)>() -> 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);

Expand Down Expand Up @@ -3774,6 +3808,11 @@ pub fn sk_svg_text_to_path(svg: &[u8], fc: &FontCollection) -> Option<SkiaDataRe
Some(SkiaDataRef(output_data))
}

unsafe extern "C" fn skiac_on_load_image(resource: *const c_char, raw_cb: *mut c_void) {
let cb = Box::leak(Box::from_raw(raw_cb as *mut Box<dyn FnMut(*const c_char)>));
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<dyn FnMut(i32, i32, i32)>));
cb(width, weight, slant);
Expand Down
Loading