diff --git a/Cargo.toml b/Cargo.toml index 47c0ff7..71ad2a4 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -10,12 +10,16 @@ license = "MIT OR Apache-2.0" [lib] crate-type = ["cdylib", "rlib"] +[package.metadata.component] +package = "alibaba:fontkit" + [dependencies] +wit-bindgen-rt = "0.24.0" ab_glyph_rasterizer = { version = "0.1.5", optional = true } arc-swap = "1.6.0" brotli-decompressor = { version = "2.3.2", optional = true } byteorder = { version = "1.4.3", optional = true } -dashmap = { version = "5.3.4", optional = true } +dashmap = "5.3.4" flate2 = { version = "1.0.22", optional = true } log = "0.4.17" ordered-float = "3.9.1" @@ -41,16 +45,8 @@ unicode-script = { version = "0.5.4", optional = true } # wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", tag = "v0.2.0", optional = true } woff2 = { git = "https://github.com/zimond/woff2-rs", rev = "0e25872", optional = true, version = "0.3.0" } -[target.'cfg(not(all(target_os = "unknown", target_arch = "wasm32")))'.dependencies] -walkdir = "2.3.1" - -[target.'cfg(all(target_os = "unknown", target_arch = "wasm32"))'.dependencies] -wasm-bindgen = "0.2.79" -js-sys = "0.3.56" -console_error_panic_hook = "0.1.7" - [features] -default = ["woff", "woff2", "metrics", "ras", "dashmap"] +default = ["woff", "woff2", "metrics", "ras"] woff = ["byteorder", "flate2"] metrics = [ "unicode-bidi", @@ -66,6 +62,3 @@ ras = [ ] optimize_stroke_broken = [] # wit = ["wit-bindgen-rust", "dashmap"] - -[build-dependencies] -cfg_aliases = "0.1.1" diff --git a/build.rs b/build.rs deleted file mode 100644 index bed8261..0000000 --- a/build.rs +++ /dev/null @@ -1,12 +0,0 @@ -use cfg_aliases::cfg_aliases; - -fn main() { - // Setup cfg aliases - cfg_aliases! { - // Platforms - wasm: { all(target_arch = "wasm32", target_os = "unknown") }, - wasi: { all(target_arch = "wasm32", target_os = "wasi") }, - wit: { all(target_arch = "wasm32", target_os = "unknown", feature = "wit") }, - dashmap: { feature = "dashmap" } - } -} diff --git a/examples/node.mjs b/examples/node.mjs index a9f4f7f..65aa415 100644 --- a/examples/node.mjs +++ b/examples/node.mjs @@ -2,14 +2,17 @@ import { homedir } from 'os'; import { dirname } from 'path'; import { fileURLToPath } from 'url'; -import { FontKitIndex } from '../node.js'; +import { fontkitInterface as fi } from '../pkg/fontkit.js'; const __dirname = dirname(fileURLToPath(import.meta.url)); -const fontkit = new FontKitIndex(); -await fontkit.initiate(); +const fontkit = new fi.FontKit(); +fontkit.addSearchPath(__dirname + '/OpenSans-Italic.ttf'); fontkit.addSearchPath(homedir() + '/Library/Fonts'); -const font = fontkit.font('Open Sans'); +const font = fontkit.query({ family: 'Open Sans' }); -fontkit.free(); +// eslint-disable-next-line no-console +console.log(font.hasGlyph('c')); +// eslint-disable-next-line no-console +console.log(fontkit.fontsInfo()); diff --git a/index.d.ts b/index.d.ts new file mode 100644 index 0000000..fc72e13 --- /dev/null +++ b/index.d.ts @@ -0,0 +1 @@ +export { FontKit, Font, FontInfo, FontKey } from './pkg/interfaces/alibaba-fontkit-fontkit-interface'; diff --git a/index.js b/index.js new file mode 100644 index 0000000..99b4233 --- /dev/null +++ b/index.js @@ -0,0 +1,7 @@ +import { fontkitInterface } from './pkg/fontkit.js'; + +export const Font = fontkitInterface.Font; +export const FontKit = fontkitInterface.FontKit; +export const TextMetrics = fontkitInterface.TextMetrics; +export const numberWidthToStr = fontkitInterface.numberWidthToStr; +export const strWidthToNumber = fontkitInterface.strWidthToNumber; diff --git a/package.json b/package.json index 2146627..21db051 100644 --- a/package.json +++ b/package.json @@ -1,15 +1,15 @@ { "name": "fontkit-rs", - "version": "0.0.7-beta.1", + "version": "0.0.9-beta.3", "description": "Toolkit used to load, match, measure, and render texts", - "main": "pkg/bundler/index.js", + "main": "index.js", "directories": { "example": "examples", "test": "tests" }, "files": [ "pkg/**/*", - "node.js", + "index.js", "Readme.md" ], "author": "Zimon Dai ", @@ -66,6 +66,7 @@ }, "type": "module", "dependencies": { + "@bytecodealliance/preview2-shim": "^0.16.1", "walkdir": "^0.4.1" } } \ No newline at end of file diff --git a/src/bindings.rs b/src/bindings.rs new file mode 100644 index 0000000..d3a9838 --- /dev/null +++ b/src/bindings.rs @@ -0,0 +1,1953 @@ +// Generated by `wit-bindgen` 0.21.0. DO NOT EDIT! +// Options used: +pub mod exports { + pub mod alibaba { + pub mod fontkit { + #[allow(clippy::all)] + pub mod fontkit_interface { + #[used] + #[doc(hidden)] + #[cfg(target_arch = "wasm32")] + static __FORCE_SECTION_REF: fn() = + super::super::super::super::__link_custom_section_describing_imports; + use super::super::super::super::_rt; + #[derive(Clone)] + pub struct FontKey { + pub weight: Option, + pub italic: Option, + pub stretch: Option, + pub family: _rt::String, + } + impl ::core::fmt::Debug for FontKey { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_struct("FontKey") + .field("weight", &self.weight) + .field("italic", &self.italic) + .field("stretch", &self.stretch) + .field("family", &self.family) + .finish() + } + } + #[derive(Clone)] + pub struct Name { + pub id: u16, + pub name: _rt::String, + pub language_id: u16, + } + impl ::core::fmt::Debug for Name { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_struct("Name") + .field("id", &self.id) + .field("name", &self.name) + .field("language-id", &self.language_id) + .finish() + } + } + #[derive(Clone)] + pub struct FontInfo { + pub style_names: _rt::Vec, + pub names: _rt::Vec, + pub path: Option<_rt::String>, + pub key: FontKey, + } + impl ::core::fmt::Debug for FontInfo { + fn fmt(&self, f: &mut ::core::fmt::Formatter<'_>) -> ::core::fmt::Result { + f.debug_struct("FontInfo") + .field("style-names", &self.style_names) + .field("names", &self.names) + .field("path", &self.path) + .field("key", &self.key) + .finish() + } + } + + #[derive(Debug)] + #[repr(transparent)] + pub struct TextMetrics { + handle: _rt::Resource, + } + + type _TextMetricsRep = Option; + + impl TextMetrics { + /// Creates a new resource from the specified + /// representation. + /// + /// This function will create a new resource handle by + /// moving `val` onto the heap and then + /// passing that heap pointer to the component model to + /// create a handle. The owned handle is then returned as + /// `TextMetrics`. + pub fn new(val: T) -> Self { + Self::type_guard::(); + let val: _TextMetricsRep = Some(val); + let ptr: *mut _TextMetricsRep = _rt::Box::into_raw(_rt::Box::new(val)); + unsafe { Self::from_handle(T::_resource_new(ptr.cast())) } + } + + /// Gets access to the underlying `T` which represents this + /// resource. + pub fn get(&self) -> &T { + let ptr = unsafe { &*self.as_ptr::() }; + ptr.as_ref().unwrap() + } + + /// Gets mutable access to the underlying `T` which + /// represents this resource. + pub fn get_mut(&mut self) -> &mut T { + let ptr = unsafe { &mut *self.as_ptr::() }; + ptr.as_mut().unwrap() + } + + /// Consumes this resource and returns the underlying `T`. + pub fn into_inner(self) -> T { + let ptr = unsafe { &mut *self.as_ptr::() }; + ptr.take().unwrap() + } + + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: _rt::Resource::from_handle(handle), + } + } + + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + + // It's theoretically possible to implement the `GuestTextMetrics` trait twice + // so guard against using it with two different types here. + #[doc(hidden)] + fn type_guard() { + use core::any::TypeId; + static mut LAST_TYPE: Option = None; + unsafe { + assert!(!cfg!(target_feature = "threads")); + let id = TypeId::of::(); + match LAST_TYPE { + Some(ty) => assert!( + ty == id, + "cannot use two types with this resource type" + ), + None => LAST_TYPE = Some(id), + } + } + } + + fn as_ptr(&self) -> *mut _TextMetricsRep { + TextMetrics::type_guard::(); + unsafe { T::_resource_rep(self.handle()).cast() } + } + } + + /// A borrowed version of [`TextMetrics`] which represents a + /// borrowed value with the lifetime `'a`. + #[derive(Debug)] + #[repr(transparent)] + pub struct TextMetricsBorrow<'a> { + rep: *mut u8, + _marker: core::marker::PhantomData<&'a TextMetrics>, + } + + impl<'a> TextMetricsBorrow<'a> { + #[doc(hidden)] + pub unsafe fn lift(rep: usize) -> Self { + Self { + rep: rep as *mut u8, + _marker: core::marker::PhantomData, + } + } + + /// Gets access to the underlying `T` in this resource. + pub fn get(&self) -> &T { + let ptr = unsafe { &mut *self.as_ptr::() }; + ptr.as_ref().unwrap() + } + + // NB: mutable access is not allowed due to the component model allowing + // multiple borrows of the same resource. + + fn as_ptr(&self) -> *mut _TextMetricsRep { + TextMetrics::type_guard::(); + self.rep.cast() + } + } + + unsafe impl _rt::WasmResource for TextMetrics { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link( + wasm_import_module = "[export]alibaba:fontkit/fontkit-interface" + )] + extern "C" { + #[link_name = "[resource-drop]text-metrics"] + fn drop(_: u32); + } + + drop(_handle); + } + } + } + + /// Instance of a single font + + #[derive(Debug)] + #[repr(transparent)] + pub struct Font { + handle: _rt::Resource, + } + + type _FontRep = Option; + + impl Font { + /// Creates a new resource from the specified + /// representation. + /// + /// This function will create a new resource handle by + /// moving `val` onto the heap and then + /// passing that heap pointer to the component model to + /// create a handle. The owned handle is then returned as + /// `Font`. + pub fn new(val: T) -> Self { + Self::type_guard::(); + let val: _FontRep = Some(val); + let ptr: *mut _FontRep = _rt::Box::into_raw(_rt::Box::new(val)); + unsafe { Self::from_handle(T::_resource_new(ptr.cast())) } + } + + /// Gets access to the underlying `T` which represents this + /// resource. + pub fn get(&self) -> &T { + let ptr = unsafe { &*self.as_ptr::() }; + ptr.as_ref().unwrap() + } + + /// Gets mutable access to the underlying `T` which + /// represents this resource. + pub fn get_mut(&mut self) -> &mut T { + let ptr = unsafe { &mut *self.as_ptr::() }; + ptr.as_mut().unwrap() + } + + /// Consumes this resource and returns the underlying `T`. + pub fn into_inner(self) -> T { + let ptr = unsafe { &mut *self.as_ptr::() }; + ptr.take().unwrap() + } + + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: _rt::Resource::from_handle(handle), + } + } + + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + + // It's theoretically possible to implement the `GuestFont` trait twice + // so guard against using it with two different types here. + #[doc(hidden)] + fn type_guard() { + use core::any::TypeId; + static mut LAST_TYPE: Option = None; + unsafe { + assert!(!cfg!(target_feature = "threads")); + let id = TypeId::of::(); + match LAST_TYPE { + Some(ty) => assert!( + ty == id, + "cannot use two types with this resource type" + ), + None => LAST_TYPE = Some(id), + } + } + } + + fn as_ptr(&self) -> *mut _FontRep { + Font::type_guard::(); + unsafe { T::_resource_rep(self.handle()).cast() } + } + } + + /// A borrowed version of [`Font`] which represents a borrowed + /// value with the lifetime `'a`. + #[derive(Debug)] + #[repr(transparent)] + pub struct FontBorrow<'a> { + rep: *mut u8, + _marker: core::marker::PhantomData<&'a Font>, + } + + impl<'a> FontBorrow<'a> { + #[doc(hidden)] + pub unsafe fn lift(rep: usize) -> Self { + Self { + rep: rep as *mut u8, + _marker: core::marker::PhantomData, + } + } + + /// Gets access to the underlying `T` in this resource. + pub fn get(&self) -> &T { + let ptr = unsafe { &mut *self.as_ptr::() }; + ptr.as_ref().unwrap() + } + + // NB: mutable access is not allowed due to the component model allowing + // multiple borrows of the same resource. + + fn as_ptr(&self) -> *mut _FontRep { + Font::type_guard::(); + self.rep.cast() + } + } + + unsafe impl _rt::WasmResource for Font { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link( + wasm_import_module = "[export]alibaba:fontkit/fontkit-interface" + )] + extern "C" { + #[link_name = "[resource-drop]font"] + fn drop(_: u32); + } + + drop(_handle); + } + } + } + + /// Stores font buffer and provides font-querying APIs + + #[derive(Debug)] + #[repr(transparent)] + pub struct FontKit { + handle: _rt::Resource, + } + + type _FontKitRep = Option; + + impl FontKit { + /// Creates a new resource from the specified + /// representation. + /// + /// This function will create a new resource handle by + /// moving `val` onto the heap and then + /// passing that heap pointer to the component model to + /// create a handle. The owned handle is then returned as + /// `FontKit`. + pub fn new(val: T) -> Self { + Self::type_guard::(); + let val: _FontKitRep = Some(val); + let ptr: *mut _FontKitRep = _rt::Box::into_raw(_rt::Box::new(val)); + unsafe { Self::from_handle(T::_resource_new(ptr.cast())) } + } + + /// Gets access to the underlying `T` which represents this + /// resource. + pub fn get(&self) -> &T { + let ptr = unsafe { &*self.as_ptr::() }; + ptr.as_ref().unwrap() + } + + /// Gets mutable access to the underlying `T` which + /// represents this resource. + pub fn get_mut(&mut self) -> &mut T { + let ptr = unsafe { &mut *self.as_ptr::() }; + ptr.as_mut().unwrap() + } + + /// Consumes this resource and returns the underlying `T`. + pub fn into_inner(self) -> T { + let ptr = unsafe { &mut *self.as_ptr::() }; + ptr.take().unwrap() + } + + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + Self { + handle: _rt::Resource::from_handle(handle), + } + } + + #[doc(hidden)] + pub fn take_handle(&self) -> u32 { + _rt::Resource::take_handle(&self.handle) + } + + #[doc(hidden)] + pub fn handle(&self) -> u32 { + _rt::Resource::handle(&self.handle) + } + + // It's theoretically possible to implement the `GuestFontKit` trait twice + // so guard against using it with two different types here. + #[doc(hidden)] + fn type_guard() { + use core::any::TypeId; + static mut LAST_TYPE: Option = None; + unsafe { + assert!(!cfg!(target_feature = "threads")); + let id = TypeId::of::(); + match LAST_TYPE { + Some(ty) => assert!( + ty == id, + "cannot use two types with this resource type" + ), + None => LAST_TYPE = Some(id), + } + } + } + + fn as_ptr(&self) -> *mut _FontKitRep { + FontKit::type_guard::(); + unsafe { T::_resource_rep(self.handle()).cast() } + } + } + + /// A borrowed version of [`FontKit`] which represents a + /// borrowed value with the lifetime `'a`. + #[derive(Debug)] + #[repr(transparent)] + pub struct FontKitBorrow<'a> { + rep: *mut u8, + _marker: core::marker::PhantomData<&'a FontKit>, + } + + impl<'a> FontKitBorrow<'a> { + #[doc(hidden)] + pub unsafe fn lift(rep: usize) -> Self { + Self { + rep: rep as *mut u8, + _marker: core::marker::PhantomData, + } + } + + /// Gets access to the underlying `T` in this resource. + pub fn get(&self) -> &T { + let ptr = unsafe { &mut *self.as_ptr::() }; + ptr.as_ref().unwrap() + } + + // NB: mutable access is not allowed due to the component model allowing + // multiple borrows of the same resource. + + fn as_ptr(&self) -> *mut _FontKitRep { + FontKit::type_guard::(); + self.rep.cast() + } + } + + unsafe impl _rt::WasmResource for FontKit { + #[inline] + unsafe fn drop(_handle: u32) { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link( + wasm_import_module = "[export]alibaba:fontkit/fontkit-interface" + )] + extern "C" { + #[link_name = "[resource-drop]font-kit"] + fn drop(_: u32); + } + + drop(_handle); + } + } + } + + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_text_metrics_width_cabi( + arg0: i32, + arg1: f32, + arg2: f32, + ) -> f32 { + let result0 = T::width( + TextMetricsBorrow::lift(arg0 as u32 as usize).get(), + arg1, + arg2, + ); + _rt::as_f32(result0) + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_text_metrics_height_cabi( + arg0: i32, + arg1: f32, + arg2: i32, + arg3: f32, + ) -> f32 { + let result0 = T::height( + TextMetricsBorrow::lift(arg0 as u32 as usize).get(), + arg1, + match arg2 { + 0 => None, + 1 => { + let e = arg3; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + ); + _rt::as_f32(result0) + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_text_metrics_ascender_cabi( + arg0: i32, + arg1: f32, + ) -> f32 { + let result0 = + T::ascender(TextMetricsBorrow::lift(arg0 as u32 as usize).get(), arg1); + _rt::as_f32(result0) + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_has_glyph_cabi( + arg0: i32, + arg1: i32, + ) -> i32 { + let result0 = T::has_glyph( + FontBorrow::lift(arg0 as u32 as usize).get(), + _rt::char_lift(arg1 as u32), + ); + match result0 { + true => 1, + false => 0, + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_buffer_cabi(arg0: i32) -> *mut u8 { + let result0 = T::buffer(FontBorrow::lift(arg0 as u32 as usize).get()); + let ptr1 = _RET_AREA.0.as_mut_ptr().cast::(); + let vec2 = (result0).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *ptr1.add(4).cast::() = len2; + *ptr1.add(0).cast::<*mut u8>() = ptr2.cast_mut(); + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_method_font_buffer(arg0: *mut u8) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0.add(4).cast::(); + let base2 = l0; + let len2 = l1; + _rt::cabi_dealloc(base2, len2 * 1, 1); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_path_cabi(arg0: i32) -> *mut u8 { + let result0 = T::path(FontBorrow::lift(arg0 as u32 as usize).get()); + let ptr1 = _RET_AREA.0.as_mut_ptr().cast::(); + let vec2 = (result0.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *ptr1.add(4).cast::() = len2; + *ptr1.add(0).cast::<*mut u8>() = ptr2.cast_mut(); + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_method_font_path(arg0: *mut u8) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0.add(4).cast::(); + _rt::cabi_dealloc(l0, l1, 1); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_key_cabi(arg0: i32) -> *mut u8 { + let result0 = T::key(FontBorrow::lift(arg0 as u32 as usize).get()); + let ptr1 = _RET_AREA.0.as_mut_ptr().cast::(); + let FontKey { + weight: weight2, + italic: italic2, + stretch: stretch2, + family: family2, + } = result0; + match weight2 { + Some(e) => { + *ptr1.add(0).cast::() = (1i32) as u8; + *ptr1.add(2).cast::() = (_rt::as_i32(e)) as u16; + } + None => { + *ptr1.add(0).cast::() = (0i32) as u8; + } + }; + match italic2 { + Some(e) => { + *ptr1.add(4).cast::() = (1i32) as u8; + *ptr1.add(5).cast::() = (match e { + true => 1, + false => 0, + }) as u8; + } + None => { + *ptr1.add(4).cast::() = (0i32) as u8; + } + }; + match stretch2 { + Some(e) => { + *ptr1.add(6).cast::() = (1i32) as u8; + *ptr1.add(8).cast::() = (_rt::as_i32(e)) as u16; + } + None => { + *ptr1.add(6).cast::() = (0i32) as u8; + } + }; + let vec3 = (family2.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr1.add(16).cast::() = len3; + *ptr1.add(12).cast::<*mut u8>() = ptr3.cast_mut(); + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_method_font_key(arg0: *mut u8) { + let l0 = *arg0.add(12).cast::<*mut u8>(); + let l1 = *arg0.add(16).cast::(); + _rt::cabi_dealloc(l0, l1, 1); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_measure_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + ) -> *mut u8 { + let len0 = arg2; + let bytes0 = _rt::Vec::from_raw_parts(arg1.cast(), len0, len0); + let result1 = T::measure( + FontBorrow::lift(arg0 as u32 as usize).get(), + _rt::string_lift(bytes0), + ); + let ptr2 = _RET_AREA.0.as_mut_ptr().cast::(); + match result1 { + Ok(e) => { + *ptr2.add(0).cast::() = (0i32) as u8; + *ptr2.add(4).cast::() = (e).take_handle() as i32; + } + Err(e) => { + *ptr2.add(0).cast::() = (1i32) as u8; + let vec3 = (e.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *ptr2.add(8).cast::() = len3; + *ptr2.add(4).cast::<*mut u8>() = ptr3.cast_mut(); + } + }; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_method_font_measure(arg0: *mut u8) { + let l0 = i32::from(*arg0.add(0).cast::()); + match l0 { + 0 => (), + _ => { + let l1 = *arg0.add(4).cast::<*mut u8>(); + let l2 = *arg0.add(8).cast::(); + _rt::cabi_dealloc(l1, l2, 1); + } + } + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_ascender_cabi(arg0: i32) -> i32 { + let result0 = T::ascender(FontBorrow::lift(arg0 as u32 as usize).get()); + _rt::as_i32(result0) + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_descender_cabi(arg0: i32) -> i32 { + let result0 = T::descender(FontBorrow::lift(arg0 as u32 as usize).get()); + _rt::as_i32(result0) + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_units_per_em_cabi( + arg0: i32, + ) -> i32 { + let result0 = T::units_per_em(FontBorrow::lift(arg0 as u32 as usize).get()); + _rt::as_i32(result0) + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_constructor_font_kit_cabi() -> i32 { + let result0 = FontKit::new(T::new()); + (result0).take_handle() as i32 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_kit_add_font_from_buffer_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + ) -> *mut u8 { + let len0 = arg2; + let result1 = T::add_font_from_buffer( + FontKitBorrow::lift(arg0 as u32 as usize).get(), + _rt::Vec::from_raw_parts(arg1.cast(), len0, len0), + ); + let ptr2 = _RET_AREA.0.as_mut_ptr().cast::(); + let vec5 = result1; + let len5 = vec5.len(); + let layout5 = _rt::alloc::Layout::from_size_align_unchecked(vec5.len() * 20, 4); + let result5 = if layout5.size() != 0 { + let ptr = _rt::alloc::alloc(layout5).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout5); + } + ptr + } else { + { + ::core::ptr::null_mut() + } + }; + for (i, e) in vec5.into_iter().enumerate() { + let base = result5.add(i * 20); + { + let FontKey { + weight: weight3, + italic: italic3, + stretch: stretch3, + family: family3, + } = e; + match weight3 { + Some(e) => { + *base.add(0).cast::() = (1i32) as u8; + *base.add(2).cast::() = (_rt::as_i32(e)) as u16; + } + None => { + *base.add(0).cast::() = (0i32) as u8; + } + }; + match italic3 { + Some(e) => { + *base.add(4).cast::() = (1i32) as u8; + *base.add(5).cast::() = (match e { + true => 1, + false => 0, + }) + as u8; + } + None => { + *base.add(4).cast::() = (0i32) as u8; + } + }; + match stretch3 { + Some(e) => { + *base.add(6).cast::() = (1i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u16; + } + None => { + *base.add(6).cast::() = (0i32) as u8; + } + }; + let vec4 = (family3.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *base.add(16).cast::() = len4; + *base.add(12).cast::<*mut u8>() = ptr4.cast_mut(); + } + } + *ptr2.add(4).cast::() = len5; + *ptr2.add(0).cast::<*mut u8>() = result5; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_method_font_kit_add_font_from_buffer< + T: GuestFontKit, + >( + arg0: *mut u8, + ) { + let l2 = *arg0.add(0).cast::<*mut u8>(); + let l3 = *arg0.add(4).cast::(); + let base4 = l2; + let len4 = l3; + for i in 0..len4 { + let base = base4.add(i * 20); + { + let l0 = *base.add(12).cast::<*mut u8>(); + let l1 = *base.add(16).cast::(); + _rt::cabi_dealloc(l0, l1, 1); + } + } + _rt::cabi_dealloc(base4, len4 * 20, 4); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_kit_add_search_path_cabi( + arg0: i32, + arg1: *mut u8, + arg2: usize, + ) { + let len0 = arg2; + let bytes0 = _rt::Vec::from_raw_parts(arg1.cast(), len0, len0); + T::add_search_path( + FontKitBorrow::lift(arg0 as u32 as usize).get(), + _rt::string_lift(bytes0), + ); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_kit_query_cabi( + arg0: i32, + arg1: i32, + arg2: i32, + arg3: i32, + arg4: i32, + arg5: i32, + arg6: i32, + arg7: *mut u8, + arg8: usize, + ) -> *mut u8 { + let len0 = arg8; + let bytes0 = _rt::Vec::from_raw_parts(arg7.cast(), len0, len0); + let result1 = T::query( + FontKitBorrow::lift(arg0 as u32 as usize).get(), + FontKey { + weight: match arg1 { + 0 => None, + 1 => { + let e = arg2 as u16; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + italic: match arg3 { + 0 => None, + 1 => { + let e = _rt::bool_lift(arg4 as u8); + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + stretch: match arg5 { + 0 => None, + 1 => { + let e = arg6 as u16; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + family: _rt::string_lift(bytes0), + }, + ); + let ptr2 = _RET_AREA.0.as_mut_ptr().cast::(); + match result1 { + Some(e) => { + *ptr2.add(0).cast::() = (1i32) as u8; + *ptr2.add(4).cast::() = (e).take_handle() as i32; + } + None => { + *ptr2.add(0).cast::() = (0i32) as u8; + } + }; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_kit_exact_match_cabi( + arg0: i32, + arg1: i32, + arg2: i32, + arg3: i32, + arg4: i32, + arg5: i32, + arg6: i32, + arg7: *mut u8, + arg8: usize, + ) -> *mut u8 { + let len0 = arg8; + let bytes0 = _rt::Vec::from_raw_parts(arg7.cast(), len0, len0); + let result1 = T::exact_match( + FontKitBorrow::lift(arg0 as u32 as usize).get(), + FontKey { + weight: match arg1 { + 0 => None, + 1 => { + let e = arg2 as u16; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + italic: match arg3 { + 0 => None, + 1 => { + let e = _rt::bool_lift(arg4 as u8); + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + stretch: match arg5 { + 0 => None, + 1 => { + let e = arg6 as u16; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + family: _rt::string_lift(bytes0), + }, + ); + let ptr2 = _RET_AREA.0.as_mut_ptr().cast::(); + match result1 { + Some(e) => { + *ptr2.add(0).cast::() = (1i32) as u8; + *ptr2.add(4).cast::() = (e).take_handle() as i32; + } + None => { + *ptr2.add(0).cast::() = (0i32) as u8; + } + }; + ptr2 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_kit_font_keys_cabi( + arg0: i32, + ) -> *mut u8 { + let result0 = T::font_keys(FontKitBorrow::lift(arg0 as u32 as usize).get()); + let ptr1 = _RET_AREA.0.as_mut_ptr().cast::(); + let vec4 = result0; + let len4 = vec4.len(); + let layout4 = _rt::alloc::Layout::from_size_align_unchecked(vec4.len() * 20, 4); + let result4 = if layout4.size() != 0 { + let ptr = _rt::alloc::alloc(layout4).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout4); + } + ptr + } else { + { + ::core::ptr::null_mut() + } + }; + for (i, e) in vec4.into_iter().enumerate() { + let base = result4.add(i * 20); + { + let FontKey { + weight: weight2, + italic: italic2, + stretch: stretch2, + family: family2, + } = e; + match weight2 { + Some(e) => { + *base.add(0).cast::() = (1i32) as u8; + *base.add(2).cast::() = (_rt::as_i32(e)) as u16; + } + None => { + *base.add(0).cast::() = (0i32) as u8; + } + }; + match italic2 { + Some(e) => { + *base.add(4).cast::() = (1i32) as u8; + *base.add(5).cast::() = (match e { + true => 1, + false => 0, + }) + as u8; + } + None => { + *base.add(4).cast::() = (0i32) as u8; + } + }; + match stretch2 { + Some(e) => { + *base.add(6).cast::() = (1i32) as u8; + *base.add(8).cast::() = (_rt::as_i32(e)) as u16; + } + None => { + *base.add(6).cast::() = (0i32) as u8; + } + }; + let vec3 = (family2.into_bytes()).into_boxed_slice(); + let ptr3 = vec3.as_ptr().cast::(); + let len3 = vec3.len(); + ::core::mem::forget(vec3); + *base.add(16).cast::() = len3; + *base.add(12).cast::<*mut u8>() = ptr3.cast_mut(); + } + } + *ptr1.add(4).cast::() = len4; + *ptr1.add(0).cast::<*mut u8>() = result4; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_method_font_kit_font_keys( + arg0: *mut u8, + ) { + let l2 = *arg0.add(0).cast::<*mut u8>(); + let l3 = *arg0.add(4).cast::(); + let base4 = l2; + let len4 = l3; + for i in 0..len4 { + let base = base4.add(i * 20); + { + let l0 = *base.add(12).cast::<*mut u8>(); + let l1 = *base.add(16).cast::(); + _rt::cabi_dealloc(l0, l1, 1); + } + } + _rt::cabi_dealloc(base4, len4 * 20, 4); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_kit_fonts_info_cabi( + arg0: i32, + ) -> *mut u8 { + let result0 = T::fonts_info(FontKitBorrow::lift(arg0 as u32 as usize).get()); + let ptr1 = _RET_AREA.0.as_mut_ptr().cast::(); + let vec12 = result0; + let len12 = vec12.len(); + let layout12 = + _rt::alloc::Layout::from_size_align_unchecked(vec12.len() * 48, 4); + let result12 = if layout12.size() != 0 { + let ptr = _rt::alloc::alloc(layout12).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout12); + } + ptr + } else { + { + ::core::ptr::null_mut() + } + }; + for (i, e) in vec12.into_iter().enumerate() { + let base = result12.add(i * 48); + { + let FontInfo { + style_names: style_names2, + names: names2, + path: path2, + key: key2, + } = e; + let vec5 = style_names2; + let len5 = vec5.len(); + let layout5 = + _rt::alloc::Layout::from_size_align_unchecked(vec5.len() * 16, 4); + let result5 = if layout5.size() != 0 { + let ptr = _rt::alloc::alloc(layout5).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout5); + } + ptr + } else { + { + ::core::ptr::null_mut() + } + }; + for (i, e) in vec5.into_iter().enumerate() { + let base = result5.add(i * 16); + { + let Name { + id: id3, + name: name3, + language_id: language_id3, + } = e; + *base.add(0).cast::() = (_rt::as_i32(id3)) as u16; + let vec4 = (name3.into_bytes()).into_boxed_slice(); + let ptr4 = vec4.as_ptr().cast::(); + let len4 = vec4.len(); + ::core::mem::forget(vec4); + *base.add(8).cast::() = len4; + *base.add(4).cast::<*mut u8>() = ptr4.cast_mut(); + *base.add(12).cast::() = + (_rt::as_i32(language_id3)) as u16; + } + } + *base.add(4).cast::() = len5; + *base.add(0).cast::<*mut u8>() = result5; + let vec8 = names2; + let len8 = vec8.len(); + let layout8 = + _rt::alloc::Layout::from_size_align_unchecked(vec8.len() * 16, 4); + let result8 = if layout8.size() != 0 { + let ptr = _rt::alloc::alloc(layout8).cast::(); + if ptr.is_null() { + _rt::alloc::handle_alloc_error(layout8); + } + ptr + } else { + { + ::core::ptr::null_mut() + } + }; + for (i, e) in vec8.into_iter().enumerate() { + let base = result8.add(i * 16); + { + let Name { + id: id6, + name: name6, + language_id: language_id6, + } = e; + *base.add(0).cast::() = (_rt::as_i32(id6)) as u16; + let vec7 = (name6.into_bytes()).into_boxed_slice(); + let ptr7 = vec7.as_ptr().cast::(); + let len7 = vec7.len(); + ::core::mem::forget(vec7); + *base.add(8).cast::() = len7; + *base.add(4).cast::<*mut u8>() = ptr7.cast_mut(); + *base.add(12).cast::() = + (_rt::as_i32(language_id6)) as u16; + } + } + *base.add(12).cast::() = len8; + *base.add(8).cast::<*mut u8>() = result8; + match path2 { + Some(e) => { + *base.add(16).cast::() = (1i32) as u8; + let vec9 = (e.into_bytes()).into_boxed_slice(); + let ptr9 = vec9.as_ptr().cast::(); + let len9 = vec9.len(); + ::core::mem::forget(vec9); + *base.add(24).cast::() = len9; + *base.add(20).cast::<*mut u8>() = ptr9.cast_mut(); + } + None => { + *base.add(16).cast::() = (0i32) as u8; + } + }; + let FontKey { + weight: weight10, + italic: italic10, + stretch: stretch10, + family: family10, + } = key2; + match weight10 { + Some(e) => { + *base.add(28).cast::() = (1i32) as u8; + *base.add(30).cast::() = (_rt::as_i32(e)) as u16; + } + None => { + *base.add(28).cast::() = (0i32) as u8; + } + }; + match italic10 { + Some(e) => { + *base.add(32).cast::() = (1i32) as u8; + *base.add(33).cast::() = (match e { + true => 1, + false => 0, + }) + as u8; + } + None => { + *base.add(32).cast::() = (0i32) as u8; + } + }; + match stretch10 { + Some(e) => { + *base.add(34).cast::() = (1i32) as u8; + *base.add(36).cast::() = (_rt::as_i32(e)) as u16; + } + None => { + *base.add(34).cast::() = (0i32) as u8; + } + }; + let vec11 = (family10.into_bytes()).into_boxed_slice(); + let ptr11 = vec11.as_ptr().cast::(); + let len11 = vec11.len(); + ::core::mem::forget(vec11); + *base.add(44).cast::() = len11; + *base.add(40).cast::<*mut u8>() = ptr11.cast_mut(); + } + } + *ptr1.add(4).cast::() = len12; + *ptr1.add(0).cast::<*mut u8>() = result12; + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_method_font_kit_fonts_info( + arg0: *mut u8, + ) { + let l15 = *arg0.add(0).cast::<*mut u8>(); + let l16 = *arg0.add(4).cast::(); + let base17 = l15; + let len17 = l16; + for i in 0..len17 { + let base = base17.add(i * 48); + { + let l2 = *base.add(0).cast::<*mut u8>(); + let l3 = *base.add(4).cast::(); + let base4 = l2; + let len4 = l3; + for i in 0..len4 { + let base = base4.add(i * 16); + { + let l0 = *base.add(4).cast::<*mut u8>(); + let l1 = *base.add(8).cast::(); + _rt::cabi_dealloc(l0, l1, 1); + } + } + _rt::cabi_dealloc(base4, len4 * 16, 4); + let l7 = *base.add(8).cast::<*mut u8>(); + let l8 = *base.add(12).cast::(); + let base9 = l7; + let len9 = l8; + for i in 0..len9 { + let base = base9.add(i * 16); + { + let l5 = *base.add(4).cast::<*mut u8>(); + let l6 = *base.add(8).cast::(); + _rt::cabi_dealloc(l5, l6, 1); + } + } + _rt::cabi_dealloc(base9, len9 * 16, 4); + let l10 = i32::from(*base.add(16).cast::()); + match l10 { + 0 => (), + _ => { + let l11 = *base.add(20).cast::<*mut u8>(); + let l12 = *base.add(24).cast::(); + _rt::cabi_dealloc(l11, l12, 1); + } + } + let l13 = *base.add(40).cast::<*mut u8>(); + let l14 = *base.add(44).cast::(); + _rt::cabi_dealloc(l13, l14, 1); + } + } + _rt::cabi_dealloc(base17, len17 * 48, 4); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_kit_len_cabi(arg0: i32) -> i32 { + let result0 = T::len(FontKitBorrow::lift(arg0 as u32 as usize).get()); + _rt::as_i32(result0) + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_method_font_kit_remove_cabi( + arg0: i32, + arg1: i32, + arg2: i32, + arg3: i32, + arg4: i32, + arg5: i32, + arg6: i32, + arg7: *mut u8, + arg8: usize, + ) { + let len0 = arg8; + let bytes0 = _rt::Vec::from_raw_parts(arg7.cast(), len0, len0); + T::remove( + FontKitBorrow::lift(arg0 as u32 as usize).get(), + FontKey { + weight: match arg1 { + 0 => None, + 1 => { + let e = arg2 as u16; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + italic: match arg3 { + 0 => None, + 1 => { + let e = _rt::bool_lift(arg4 as u8); + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + stretch: match arg5 { + 0 => None, + 1 => { + let e = arg6 as u16; + Some(e) + } + _ => _rt::invalid_enum_discriminant(), + }, + family: _rt::string_lift(bytes0), + }, + ); + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_str_width_to_number_cabi( + arg0: *mut u8, + arg1: usize, + ) -> i32 { + let len0 = arg1; + let bytes0 = _rt::Vec::from_raw_parts(arg0.cast(), len0, len0); + let result1 = T::str_width_to_number(_rt::string_lift(bytes0)); + _rt::as_i32(result1) + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn _export_number_width_to_str_cabi(arg0: i32) -> *mut u8 { + let result0 = T::number_width_to_str(arg0 as u16); + let ptr1 = _RET_AREA.0.as_mut_ptr().cast::(); + let vec2 = (result0.into_bytes()).into_boxed_slice(); + let ptr2 = vec2.as_ptr().cast::(); + let len2 = vec2.len(); + ::core::mem::forget(vec2); + *ptr1.add(4).cast::() = len2; + *ptr1.add(0).cast::<*mut u8>() = ptr2.cast_mut(); + ptr1 + } + #[doc(hidden)] + #[allow(non_snake_case)] + pub unsafe fn __post_return_number_width_to_str(arg0: *mut u8) { + let l0 = *arg0.add(0).cast::<*mut u8>(); + let l1 = *arg0.add(4).cast::(); + _rt::cabi_dealloc(l0, l1, 1); + } + pub trait Guest { + type TextMetrics: GuestTextMetrics; + type Font: GuestFont; + type FontKit: GuestFontKit; + fn str_width_to_number(width: _rt::String) -> u16; + fn number_width_to_str(width: u16) -> _rt::String; + } + pub trait GuestTextMetrics: 'static { + #[doc(hidden)] + unsafe fn _resource_new(val: *mut u8) -> u32 + where + Self: Sized, + { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link( + wasm_import_module = "[export]alibaba:fontkit/fontkit-interface" + )] + extern "C" { + #[link_name = "[resource-new]text-metrics"] + fn new(_: *mut u8) -> u32; + } + new(val) + } + } + + #[doc(hidden)] + fn _resource_rep(handle: u32) -> *mut u8 + where + Self: Sized, + { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link( + wasm_import_module = "[export]alibaba:fontkit/fontkit-interface" + )] + extern "C" { + #[link_name = "[resource-rep]text-metrics"] + fn rep(_: u32) -> *mut u8; + } + unsafe { rep(handle) } + } + } + + fn width(&self, font_size: f32, letter_spacing: f32) -> f32; + fn height(&self, font_size: f32, line_height: Option) -> f32; + fn ascender(&self, font_size: f32) -> f32; + } + pub trait GuestFont: 'static { + #[doc(hidden)] + unsafe fn _resource_new(val: *mut u8) -> u32 + where + Self: Sized, + { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link( + wasm_import_module = "[export]alibaba:fontkit/fontkit-interface" + )] + extern "C" { + #[link_name = "[resource-new]font"] + fn new(_: *mut u8) -> u32; + } + new(val) + } + } + + #[doc(hidden)] + fn _resource_rep(handle: u32) -> *mut u8 + where + Self: Sized, + { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link( + wasm_import_module = "[export]alibaba:fontkit/fontkit-interface" + )] + extern "C" { + #[link_name = "[resource-rep]font"] + fn rep(_: u32) -> *mut u8; + } + unsafe { rep(handle) } + } + } + + /// Check if the font has valid data for a character + fn has_glyph(&self, c: char) -> bool; + /// Return the font buffer + fn buffer(&self) -> _rt::Vec; + /// Return the path if this font is added from searching a + /// path + fn path(&self) -> _rt::String; + /// Return the key of this font + fn key(&self) -> FontKey; + /// Measure text using this font + fn measure(&self, text: _rt::String) -> Result; + fn ascender(&self) -> i16; + fn descender(&self) -> i16; + fn units_per_em(&self) -> u16; + } + pub trait GuestFontKit: 'static { + #[doc(hidden)] + unsafe fn _resource_new(val: *mut u8) -> u32 + where + Self: Sized, + { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link( + wasm_import_module = "[export]alibaba:fontkit/fontkit-interface" + )] + extern "C" { + #[link_name = "[resource-new]font-kit"] + fn new(_: *mut u8) -> u32; + } + new(val) + } + } + + #[doc(hidden)] + fn _resource_rep(handle: u32) -> *mut u8 + where + Self: Sized, + { + #[cfg(not(target_arch = "wasm32"))] + unreachable!(); + + #[cfg(target_arch = "wasm32")] + { + #[link( + wasm_import_module = "[export]alibaba:fontkit/fontkit-interface" + )] + extern "C" { + #[link_name = "[resource-rep]font-kit"] + fn rep(_: u32) -> *mut u8; + } + unsafe { rep(handle) } + } + } + + fn new() -> Self; + /// Register a font (or several fonts in case of ttc), + /// return the keys of added fonts. + /// The file type is extracted from the buffer by checking + /// magic numbers + fn add_font_from_buffer(&self, buffer: _rt::Vec) -> _rt::Vec; + /// Search and add fonts from a path + fn add_search_path(&self, path: _rt::String); + /// Query font using a key, this API returns valid result + /// only if a single result is found + fn query(&self, key: FontKey) -> Option; + /// Using exact-match method to directly obtain a font, + /// skipping the querying logic + fn exact_match(&self, key: FontKey) -> Option; + /// Get all registered fonts' keys + fn font_keys(&self) -> _rt::Vec; + /// Get detailed info of all fonts registered + fn fonts_info(&self) -> _rt::Vec; + /// Get number of registered fonts + fn len(&self) -> u32; + /// Remove a font matching the given key + fn remove(&self, key: FontKey); + } + #[doc(hidden)] + + macro_rules! __export_alibaba_fontkit_fontkit_interface_cabi{ + ($ty:ident with_types_in $($path_to_types:tt)*) => (const _: () = { + + #[export_name = "alibaba:fontkit/fontkit-interface#[method]text-metrics.width"] + unsafe extern "C" fn export_method_text_metrics_width(arg0: i32,arg1: f32,arg2: f32,) -> f32 { + $($path_to_types)*::_export_method_text_metrics_width_cabi::<<$ty as $($path_to_types)*::Guest>::TextMetrics>(arg0, arg1, arg2) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]text-metrics.height"] + unsafe extern "C" fn export_method_text_metrics_height(arg0: i32,arg1: f32,arg2: i32,arg3: f32,) -> f32 { + $($path_to_types)*::_export_method_text_metrics_height_cabi::<<$ty as $($path_to_types)*::Guest>::TextMetrics>(arg0, arg1, arg2, arg3) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]text-metrics.ascender"] + unsafe extern "C" fn export_method_text_metrics_ascender(arg0: i32,arg1: f32,) -> f32 { + $($path_to_types)*::_export_method_text_metrics_ascender_cabi::<<$ty as $($path_to_types)*::Guest>::TextMetrics>(arg0, arg1) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font.has-glyph"] + unsafe extern "C" fn export_method_font_has_glyph(arg0: i32,arg1: i32,) -> i32 { + $($path_to_types)*::_export_method_font_has_glyph_cabi::<<$ty as $($path_to_types)*::Guest>::Font>(arg0, arg1) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font.buffer"] + unsafe extern "C" fn export_method_font_buffer(arg0: i32,) -> *mut u8 { + $($path_to_types)*::_export_method_font_buffer_cabi::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "cabi_post_alibaba:fontkit/fontkit-interface#[method]font.buffer"] + unsafe extern "C" fn _post_return_method_font_buffer(arg0: *mut u8,) { + $($path_to_types)*::__post_return_method_font_buffer::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font.path"] + unsafe extern "C" fn export_method_font_path(arg0: i32,) -> *mut u8 { + $($path_to_types)*::_export_method_font_path_cabi::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "cabi_post_alibaba:fontkit/fontkit-interface#[method]font.path"] + unsafe extern "C" fn _post_return_method_font_path(arg0: *mut u8,) { + $($path_to_types)*::__post_return_method_font_path::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font.key"] + unsafe extern "C" fn export_method_font_key(arg0: i32,) -> *mut u8 { + $($path_to_types)*::_export_method_font_key_cabi::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "cabi_post_alibaba:fontkit/fontkit-interface#[method]font.key"] + unsafe extern "C" fn _post_return_method_font_key(arg0: *mut u8,) { + $($path_to_types)*::__post_return_method_font_key::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font.measure"] + unsafe extern "C" fn export_method_font_measure(arg0: i32,arg1: *mut u8,arg2: usize,) -> *mut u8 { + $($path_to_types)*::_export_method_font_measure_cabi::<<$ty as $($path_to_types)*::Guest>::Font>(arg0, arg1, arg2) + } + #[export_name = "cabi_post_alibaba:fontkit/fontkit-interface#[method]font.measure"] + unsafe extern "C" fn _post_return_method_font_measure(arg0: *mut u8,) { + $($path_to_types)*::__post_return_method_font_measure::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font.ascender"] + unsafe extern "C" fn export_method_font_ascender(arg0: i32,) -> i32 { + $($path_to_types)*::_export_method_font_ascender_cabi::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font.descender"] + unsafe extern "C" fn export_method_font_descender(arg0: i32,) -> i32 { + $($path_to_types)*::_export_method_font_descender_cabi::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font.units-per-em"] + unsafe extern "C" fn export_method_font_units_per_em(arg0: i32,) -> i32 { + $($path_to_types)*::_export_method_font_units_per_em_cabi::<<$ty as $($path_to_types)*::Guest>::Font>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[constructor]font-kit"] + unsafe extern "C" fn export_constructor_font_kit() -> i32 { + $($path_to_types)*::_export_constructor_font_kit_cabi::<<$ty as $($path_to_types)*::Guest>::FontKit>() + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font-kit.add-font-from-buffer"] + unsafe extern "C" fn export_method_font_kit_add_font_from_buffer(arg0: i32,arg1: *mut u8,arg2: usize,) -> *mut u8 { + $($path_to_types)*::_export_method_font_kit_add_font_from_buffer_cabi::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0, arg1, arg2) + } + #[export_name = "cabi_post_alibaba:fontkit/fontkit-interface#[method]font-kit.add-font-from-buffer"] + unsafe extern "C" fn _post_return_method_font_kit_add_font_from_buffer(arg0: *mut u8,) { + $($path_to_types)*::__post_return_method_font_kit_add_font_from_buffer::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font-kit.add-search-path"] + unsafe extern "C" fn export_method_font_kit_add_search_path(arg0: i32,arg1: *mut u8,arg2: usize,) { + $($path_to_types)*::_export_method_font_kit_add_search_path_cabi::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0, arg1, arg2) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font-kit.query"] + unsafe extern "C" fn export_method_font_kit_query(arg0: i32,arg1: i32,arg2: i32,arg3: i32,arg4: i32,arg5: i32,arg6: i32,arg7: *mut u8,arg8: usize,) -> *mut u8 { + $($path_to_types)*::_export_method_font_kit_query_cabi::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font-kit.exact-match"] + unsafe extern "C" fn export_method_font_kit_exact_match(arg0: i32,arg1: i32,arg2: i32,arg3: i32,arg4: i32,arg5: i32,arg6: i32,arg7: *mut u8,arg8: usize,) -> *mut u8 { + $($path_to_types)*::_export_method_font_kit_exact_match_cabi::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font-kit.font-keys"] + unsafe extern "C" fn export_method_font_kit_font_keys(arg0: i32,) -> *mut u8 { + $($path_to_types)*::_export_method_font_kit_font_keys_cabi::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0) + } + #[export_name = "cabi_post_alibaba:fontkit/fontkit-interface#[method]font-kit.font-keys"] + unsafe extern "C" fn _post_return_method_font_kit_font_keys(arg0: *mut u8,) { + $($path_to_types)*::__post_return_method_font_kit_font_keys::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font-kit.fonts-info"] + unsafe extern "C" fn export_method_font_kit_fonts_info(arg0: i32,) -> *mut u8 { + $($path_to_types)*::_export_method_font_kit_fonts_info_cabi::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0) + } + #[export_name = "cabi_post_alibaba:fontkit/fontkit-interface#[method]font-kit.fonts-info"] + unsafe extern "C" fn _post_return_method_font_kit_fonts_info(arg0: *mut u8,) { + $($path_to_types)*::__post_return_method_font_kit_fonts_info::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font-kit.len"] + unsafe extern "C" fn export_method_font_kit_len(arg0: i32,) -> i32 { + $($path_to_types)*::_export_method_font_kit_len_cabi::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0) + } + #[export_name = "alibaba:fontkit/fontkit-interface#[method]font-kit.remove"] + unsafe extern "C" fn export_method_font_kit_remove(arg0: i32,arg1: i32,arg2: i32,arg3: i32,arg4: i32,arg5: i32,arg6: i32,arg7: *mut u8,arg8: usize,) { + $($path_to_types)*::_export_method_font_kit_remove_cabi::<<$ty as $($path_to_types)*::Guest>::FontKit>(arg0, arg1, arg2, arg3, arg4, arg5, arg6, arg7, arg8) + } + #[export_name = "alibaba:fontkit/fontkit-interface#str-width-to-number"] + unsafe extern "C" fn export_str_width_to_number(arg0: *mut u8,arg1: usize,) -> i32 { + $($path_to_types)*::_export_str_width_to_number_cabi::<$ty>(arg0, arg1) + } + #[export_name = "alibaba:fontkit/fontkit-interface#number-width-to-str"] + unsafe extern "C" fn export_number_width_to_str(arg0: i32,) -> *mut u8 { + $($path_to_types)*::_export_number_width_to_str_cabi::<$ty>(arg0) + } + #[export_name = "cabi_post_alibaba:fontkit/fontkit-interface#number-width-to-str"] + unsafe extern "C" fn _post_return_number_width_to_str(arg0: *mut u8,) { + $($path_to_types)*::__post_return_number_width_to_str::<$ty>(arg0) + } + };); +} + #[doc(hidden)] + pub(crate) use __export_alibaba_fontkit_fontkit_interface_cabi; + #[repr(align(4))] + struct _RetArea([::core::mem::MaybeUninit; 20]); + static mut _RET_AREA: _RetArea = _RetArea([::core::mem::MaybeUninit::uninit(); 20]); + } + } + } +} +mod _rt { + pub use alloc_crate::string::String; + pub use alloc_crate::vec::Vec; + + use core::sync::atomic::AtomicU32; + use core::sync::atomic::Ordering::Relaxed; + use core::{fmt, marker}; + + /// A type which represents a component model resource, either imported or + /// exported into this component. + /// + /// This is a low-level wrapper which handles the lifetime of the resource + /// (namely this has a destructor). The `T` provided defines the component + /// model intrinsics that this wrapper uses. + /// + /// One of the chief purposes of this type is to provide `Deref` + /// implementations to access the underlying data when it is owned. + /// + /// This type is primarily used in generated code for exported and imported + /// resources. + #[repr(transparent)] + pub struct Resource { + // NB: This would ideally be `u32` but it is not. The fact that this has + // interior mutability is not exposed in the API of this type except for the + // `take_handle` method which is supposed to in theory be private. + // + // This represents, almost all the time, a valid handle value. When it's + // invalid it's stored as `u32::MAX`. + handle: AtomicU32, + _marker: marker::PhantomData, + } + + /// A trait which all wasm resources implement, namely providing the ability + /// to drop a resource. + /// + /// This generally is implemented by generated code, not user-facing code. + pub unsafe trait WasmResource { + /// Invokes the `[resource-drop]...` intrinsic. + unsafe fn drop(handle: u32); + } + + impl Resource { + #[doc(hidden)] + pub unsafe fn from_handle(handle: u32) -> Self { + debug_assert!(handle != u32::MAX); + Self { + handle: AtomicU32::new(handle), + _marker: marker::PhantomData, + } + } + + /// Takes ownership of the handle owned by `resource`. + /// + /// Note that this ideally would be `into_handle` taking `Resource` + /// by ownership. The code generator does not enable that in all + /// situations, unfortunately, so this is provided instead. + /// + /// Also note that `take_handle` is in theory only ever called on values + /// owned by a generated function. For example a generated function + /// might take `Resource` as an argument but then call + /// `take_handle` on a reference to that argument. In that sense + /// the dynamic nature of `take_handle` should only be exposed + /// internally to generated code, not to user code. + #[doc(hidden)] + pub fn take_handle(resource: &Resource) -> u32 { + resource.handle.swap(u32::MAX, Relaxed) + } + + #[doc(hidden)] + pub fn handle(resource: &Resource) -> u32 { + resource.handle.load(Relaxed) + } + } + + impl fmt::Debug for Resource { + fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result { + f.debug_struct("Resource") + .field("handle", &self.handle) + .finish() + } + } + + impl Drop for Resource { + fn drop(&mut self) { + unsafe { + match self.handle.load(Relaxed) { + // If this handle was "taken" then don't do anything in the + // destructor. + u32::MAX => {} + + // ... but otherwise do actually destroy it with the imported + // component model intrinsic as defined through `T`. + other => T::drop(other), + } + } + } + } + pub use alloc_crate::boxed::Box; + + pub fn as_f32(t: T) -> f32 { + t.as_f32() + } + + pub trait AsF32 { + fn as_f32(self) -> f32; + } + + impl<'a, T: Copy + AsF32> AsF32 for &'a T { + fn as_f32(self) -> f32 { + (*self).as_f32() + } + } + + impl AsF32 for f32 { + #[inline] + fn as_f32(self) -> f32 { + self as f32 + } + } + pub unsafe fn invalid_enum_discriminant() -> T { + if cfg!(debug_assertions) { + panic!("invalid enum discriminant") + } else { + core::hint::unreachable_unchecked() + } + } + pub unsafe fn char_lift(val: u32) -> char { + if cfg!(debug_assertions) { + core::char::from_u32(val).unwrap() + } else { + core::char::from_u32_unchecked(val) + } + } + pub unsafe fn cabi_dealloc(ptr: *mut u8, size: usize, align: usize) { + if size == 0 { + return; + } + let layout = alloc::Layout::from_size_align_unchecked(size, align); + alloc::dealloc(ptr as *mut u8, layout); + } + + pub fn as_i32(t: T) -> i32 { + t.as_i32() + } + + pub trait AsI32 { + fn as_i32(self) -> i32; + } + + impl<'a, T: Copy + AsI32> AsI32 for &'a T { + fn as_i32(self) -> i32 { + (*self).as_i32() + } + } + + impl AsI32 for i32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for u32 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for i16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for u16 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for i8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for u8 { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for char { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + + impl AsI32 for usize { + #[inline] + fn as_i32(self) -> i32 { + self as i32 + } + } + pub unsafe fn string_lift(bytes: Vec) -> String { + if cfg!(debug_assertions) { + String::from_utf8(bytes).unwrap() + } else { + String::from_utf8_unchecked(bytes) + } + } + pub use alloc_crate::alloc; + pub unsafe fn bool_lift(val: u8) -> bool { + if cfg!(debug_assertions) { + match val { + 0 => false, + 1 => true, + _ => panic!("invalid bool discriminant"), + } + } else { + ::core::mem::transmute::(val) + } + } + extern crate alloc as alloc_crate; +} + +/// Generates `#[no_mangle]` functions to export the specified type as the +/// root implementation of all generated traits. +/// +/// For more information see the documentation of `wit_bindgen::generate!`. +/// +/// ```rust +/// # macro_rules! export{ ($($t:tt)*) => (); } +/// # trait Guest {} +/// struct MyType; +/// +/// impl Guest for MyType { +/// // ... +/// } +/// +/// export!(MyType); +/// ``` +#[allow(unused_macros)] +#[doc(hidden)] + +macro_rules! __export_fontkit_impl { + ($ty:ident) => (self::export!($ty with_types_in self);); + ($ty:ident with_types_in $($path_to_types_root:tt)*) => ( + $($path_to_types_root)*::exports::alibaba::fontkit::fontkit_interface::__export_alibaba_fontkit_fontkit_interface_cabi!($ty with_types_in $($path_to_types_root)*::exports::alibaba::fontkit::fontkit_interface); + ) +} +#[doc(inline)] +pub(crate) use __export_fontkit_impl as export; + +#[cfg(target_arch = "wasm32")] +#[link_section = "component-type:wit-bindgen:0.21.0:fontkit:encoded world"] +#[doc(hidden)] +pub static __WIT_BINDGEN_COMPONENT_TYPE: [u8; 1365] = *b"\ +\0asm\x0d\0\x01\0\0\x19\x16wit-component-encoding\x04\0\x07\xd7\x09\x01A\x02\x01\ +A\x02\x01BC\x01k{\x01k\x7f\x01r\x04\x06weight\0\x06italic\x01\x07stretch\0\x06fa\ +milys\x04\0\x08font-key\x03\0\x02\x01r\x03\x02id{\x04names\x0blanguage-id{\x04\0\ +\x04name\x03\0\x04\x01p\x05\x01ks\x01r\x04\x0bstyle-names\x06\x05names\x06\x04pa\ +th\x07\x03key\x03\x04\0\x09font-info\x03\0\x08\x04\0\x0ctext-metrics\x03\x01\x04\ +\0\x04font\x03\x01\x04\0\x08font-kit\x03\x01\x01h\x0a\x01@\x03\x04self\x0d\x09fo\ +nt-sizev\x0eletter-spacingv\0v\x04\0\x1a[method]text-metrics.width\x01\x0e\x01kv\ +\x01@\x03\x04self\x0d\x09font-sizev\x0bline-height\x0f\0v\x04\0\x1b[method]text-\ +metrics.height\x01\x10\x01@\x02\x04self\x0d\x09font-sizev\0v\x04\0\x1d[method]te\ +xt-metrics.ascender\x01\x11\x01h\x0b\x01@\x02\x04self\x12\x01ct\0\x7f\x04\0\x16[\ +method]font.has-glyph\x01\x13\x01p}\x01@\x01\x04self\x12\0\x14\x04\0\x13[method]\ +font.buffer\x01\x15\x01@\x01\x04self\x12\0s\x04\0\x11[method]font.path\x01\x16\x01\ +@\x01\x04self\x12\0\x03\x04\0\x10[method]font.key\x01\x17\x01i\x0a\x01j\x01\x18\x01\ +s\x01@\x02\x04self\x12\x04texts\0\x19\x04\0\x14[method]font.measure\x01\x1a\x01@\ +\x01\x04self\x12\0|\x04\0\x15[method]font.ascender\x01\x1b\x04\0\x16[method]font\ +.descender\x01\x1b\x01@\x01\x04self\x12\0{\x04\0\x19[method]font.units-per-em\x01\ +\x1c\x01i\x0c\x01@\0\0\x1d\x04\0\x15[constructor]font-kit\x01\x1e\x01h\x0c\x01p\x03\ +\x01@\x02\x04self\x1f\x06buffer\x14\0\x20\x04\0%[method]font-kit.add-font-from-b\ +uffer\x01!\x01@\x02\x04self\x1f\x04paths\x01\0\x04\0\x20[method]font-kit.add-sea\ +rch-path\x01\"\x01i\x0b\x01k#\x01@\x02\x04self\x1f\x03key\x03\0$\x04\0\x16[metho\ +d]font-kit.query\x01%\x04\0\x1c[method]font-kit.exact-match\x01%\x01@\x01\x04sel\ +f\x1f\0\x20\x04\0\x1a[method]font-kit.font-keys\x01&\x01p\x09\x01@\x01\x04self\x1f\ +\0'\x04\0\x1b[method]font-kit.fonts-info\x01(\x01@\x01\x04self\x1f\0y\x04\0\x14[\ +method]font-kit.len\x01)\x01@\x02\x04self\x1f\x03key\x03\x01\0\x04\0\x17[method]\ +font-kit.remove\x01*\x01@\x01\x05widths\0{\x04\0\x13str-width-to-number\x01+\x01\ +@\x01\x05width{\0s\x04\0\x13number-width-to-str\x01,\x04\x01!alibaba:fontkit/fon\ +tkit-interface\x05\0\x04\x01\x17alibaba:fontkit/fontkit\x04\0\x0b\x0d\x01\0\x07f\ +ontkit\x03\0\0\0G\x09producers\x01\x0cprocessed-by\x02\x0dwit-component\x070.201\ +.0\x10wit-bindgen-rust\x060.21.0"; + +#[inline(never)] +#[doc(hidden)] +#[cfg(target_arch = "wasm32")] +pub fn __link_custom_section_describing_imports() { + wit_bindgen_rt::maybe_link_cabi_realloc(); +} diff --git a/src/conv/woff.rs b/src/conv/woff.rs index ce7b2a9..86c8a6a 100644 --- a/src/conv/woff.rs +++ b/src/conv/woff.rs @@ -194,15 +194,3 @@ where Ok(()) } - -// #[cfg(test)] -// #[wasm_bindgen_test::wasm_bindgen_test] -// fn dump_woff() { -// let result: &[u8] = -// include_bytes!("../../tests/HelveticaLTStd-Black.woff"); let read = -// std::io::Cursor::new(&result); let mut out = -// std::io::Cursor::new(vec![]); convert_woff_to_otf(read, &mut -// out).unwrap(); let out = out.into_inner(); -// let font = ttf_parser::Font::from_data(&out, 0).unwrap(); -// println!("{:?} {:?}", font.family_name(), font.post_script_name()); -// } diff --git a/src/error.rs b/src/error.rs index d2bf012..f87e8c0 100644 --- a/src/error.rs +++ b/src/error.rs @@ -14,9 +14,6 @@ pub enum Error { Parser(#[from] ttf_parser::FaceParsingError), #[error(transparent)] Io(#[from] std::io::Error), - #[cfg(not(all(target_os = "unknown", target_arch = "wasm32")))] - #[error(transparent)] - WalkDir(#[from] walkdir::Error), #[error("Glyph {c} not found in font")] GlyphNotFound { c: char }, #[cfg(feature = "woff2")] @@ -28,17 +25,3 @@ pub enum Error { metrics: Vec, }, } - -#[cfg(node)] -impl From for napi::Error { - fn from(e: Error) -> Self { - napi::Error::from_reason(format!("{}", e)) - } -} - -#[cfg(wasm)] -impl From for js_sys::Error { - fn from(e: Error) -> Self { - js_sys::Error::new(&format!("{}", e)).into() - } -} diff --git a/src/font.rs b/src/font.rs index ef50817..ccf61e5 100644 --- a/src/font.rs +++ b/src/font.rs @@ -3,8 +3,6 @@ use byteorder::{BigEndian, ReadBytesExt}; use ordered_float::OrderedFloat; use ouroboros::self_referencing; use serde::{Deserialize, Serialize}; -#[cfg(not(dashmap))] -use std::collections::HashMap; use std::collections::HashMap; use std::fmt; use std::io::Read; @@ -12,16 +10,9 @@ use std::path::PathBuf; use std::sync::Arc; pub use ttf_parser::LineMetrics; use ttf_parser::{Face, Fixed, Tag, VariationAxis, Width as ParserWidth}; -// #[cfg(not(wasm))] -// use walkdir::WalkDir; -#[cfg(wasm)] -use tsify::Tsify; -#[cfg(wasm)] -use wasm_bindgen::prelude::*; use crate::Error; -#[cfg_attr(wasm, wasm_bindgen)] pub fn str_width_to_number(width: &str) -> u16 { match width { "ultra-condensed" => ParserWidth::UltraCondensed, @@ -38,7 +29,6 @@ pub fn str_width_to_number(width: &str) -> u16 { .to_number() } -#[cfg_attr(wasm, wasm_bindgen)] pub fn number_width_to_str(width: u16) -> String { match width { 1 => "ultra-condensed", @@ -440,7 +430,6 @@ impl Font { self.face.swap(Arc::new(None)); } - #[cfg(not(wasm))] pub fn load(&self) -> Result<(), Error> { if self.face.load().is_some() { return Ok(()); @@ -459,6 +448,7 @@ impl Font { } pub fn has_glyph(&self, c: char) -> bool { + self.load().unwrap(); let f = self.face.load(); let f = f.as_ref().as_ref().unwrap(); let f = f.borrow_face(); diff --git a/src/lib.rs b/src/lib.rs index f0b216b..bfc1937 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,15 +1,10 @@ -#[cfg(not(wasm))] -use std::cell::RefCell; -#[cfg(not(dashmap))] -use std::collections::HashMap; use std::collections::HashSet; use std::ops::Deref; -#[cfg(not(wasm))] use std::path::Path; pub use ttf_parser::LineMetrics; -#[cfg(wasm)] -use wasm_bindgen::prelude::*; +#[cfg(target_arch = "wasm32")] +mod bindings; mod conv; mod error; mod font; @@ -17,8 +12,8 @@ mod font; mod metrics; #[cfg(feature = "ras")] mod ras; -#[cfg(wasm)] -mod wasm; +#[cfg(target_arch = "wasm32")] +mod wit; pub use error::Error; pub use font::*; @@ -28,79 +23,26 @@ pub use metrics::*; pub use ras::*; pub use tiny_skia_path::{self, PathSegment}; -#[cfg_attr(wasm, wasm_bindgen)] pub struct FontKit { - #[cfg(not(dashmap))] - fonts: HashMap, - #[cfg(dashmap)] fonts: dashmap::DashMap, fallback_font_key: Option FontKey + Send + Sync>>, } -#[cfg_attr(wasm, wasm_bindgen)] impl FontKit { /// Create a font registry - #[cfg_attr(wasm, wasm_bindgen(constructor))] pub fn new() -> Self { - #[cfg(wasm)] - console_error_panic_hook::set_once(); FontKit { - #[cfg(not(dashmap))] - fonts: HashMap::new(), - #[cfg(dashmap)] fonts: dashmap::DashMap::new(), fallback_font_key: None, } } - /// Add fonts from a buffer. This will load the fonts and store the buffer - /// in FontKit. Type information is inferred from the magic number using - /// `infer` crate. - /// - /// If the given buffer is a font collection (ttc), multiple keys will be - /// returned. - #[cfg(wasm)] - #[wasm_bindgen(js_name = "add_font_from_buffer")] - pub fn add_font_from_buffer_wasm( - &mut self, - buffer: Vec, - ) -> Result { - Ok(FontKeyArray(self.add_font_from_buffer(buffer)?)) - } - - #[cfg(wasm)] - #[wasm_bindgen(js_name = "query")] - pub fn query_wasm(&self, key: FontKey) -> Option { - let font = self.query(&key)?; - let font = font.deref(); - Some(wasm::FontWasm { - ptr: font as *const _, - }) - } - - #[cfg(wasm)] - #[wasm_bindgen(js_name = "exact_match")] - pub fn exact_match_wasm(&self, key: FontKey) -> Option { - let font = self.exact_match(&key)?; - let font = font.deref(); - Some(wasm::FontWasm { - ptr: font as *const _, - }) - } - - #[cfg(wasm)] - #[wasm_bindgen(js_name = "font_keys")] - pub fn font_keys_wasm(&self) -> FontKeyArray { - FontKeyArray(self.font_keys().collect()) - } - pub fn len(&self) -> usize { self.fonts.len() } /// Setup a font as fallback. When measure fails, FontKit will use this /// fallback to measure, if possible - #[cfg(not(wasm))] pub fn set_fallback( &mut self, font_key: Option FontKey + Send + Sync + 'static>, @@ -151,34 +93,13 @@ impl FontKit { pub fn remove(&self, key: FontKey) { self.fonts.remove(&key); } -} -impl FontKit { /// Add fonts from a buffer. This will load the fonts and store the buffer /// in FontKit. Type information is inferred from the magic number using /// `infer` crate. /// /// If the given buffer is a font collection (ttc), multiple keys will be /// returned. - #[cfg(not(dashmap))] - pub fn add_font_from_buffer(&mut self, buffer: Vec) -> Result, Error> { - Ok(Font::from_buffer(&buffer)? - .into_iter() - .map(|font| { - let key = font.key().clone(); - self.fonts.insert(key.clone(), font); - key - }) - .collect::>()) - } - - /// Add fonts from a buffer. This will load the fonts and store the buffer - /// in FontKit. Type information is inferred from the magic number using - /// `infer` crate. - /// - /// If the given buffer is a font collection (ttc), multiple keys will be - /// returned. - #[cfg(dashmap)] pub fn add_font_from_buffer(&self, buffer: Vec) -> Result, Error> { Ok(Font::from_buffer(&buffer)? .into_iter() @@ -191,47 +112,26 @@ impl FontKit { } pub fn font_keys(&self) -> impl Iterator + '_ { - #[cfg(dashmap)] return self.fonts.iter().map(|i| { - log::info!("{:?}", i.names); + log::debug!("{:?}", i.names); i.key().clone() }); - #[cfg(not(dashmap))] - self.fonts.keys() } /// Recursively scan a local path for fonts, this method will not store the /// font buffer to reduce memory consumption - #[cfg(not(wasm))] - pub fn search_fonts_from_path(&mut self, path: impl AsRef) -> Result<(), Error> { - #[cfg(not(any(wasm, wasi)))] - for entry in walkdir::WalkDir::new(path) { - let entry = entry?; - log::trace!("new entry {:?}", entry); - let path = entry.path(); - if path.is_dir() { - continue; - } - if let Some(fonts) = load_font_from_path(&path) { - for font in fonts { - self.fonts.insert(font.key(), font); - } - } - } - #[cfg(wasi)] - if let Some(fonts) = load_font_from_path(path.as_ref()) { + pub fn search_fonts_from_path(&self, path: impl AsRef) -> Result<(), Error> { + if let Some(fonts) = load_font_from_path(&path) { for font in fonts { self.fonts.insert(font.key(), font); } } + // } Ok(()) } pub fn exact_match(&self, key: &FontKey) -> Option + '_> { - #[cfg(dashmap)] return self.fonts.iter().find(|font| *font.key() == *key); - #[cfg(not(dashmap))] - self.fonts.values().find(|font| font.key == *key) } pub fn query(&self, key: &FontKey) -> Option + '_> { @@ -246,12 +146,7 @@ impl FontKit { let mut search_results = self .fonts .iter() - .map(|item| { - #[cfg(dashmap)] - return item.key().clone(); - #[cfg(not(dashmap))] - item.0.clone() - }) + .map(|item| item.key().clone()) .collect::>(); for filter in filters { let mut s = search_results.clone(); @@ -285,10 +180,22 @@ impl FontKit { } } -#[cfg(not(wasm))] fn load_font_from_path(path: impl AsRef) -> Option> { use std::io::Read; + // if path.as_ref().is_dir() { + // let mut result = vec![]; + // if let Ok(data) = fs::read_dir(path) { + // for entry in data { + // if let Ok(entry) = entry { + // + // result.extend(load_font_from_path(&entry.path()).into_iter().flatten()); + // } + // } + // } + // return Some(result); + // } + let mut buffer = Vec::new(); let path = path.as_ref(); let ext = path @@ -329,167 +236,3 @@ enum Filter<'a> { Weight(u32), Stretch(u32), } - -#[cfg(not(wasm))] -std::thread_local! { - static ALLOCS: RefCell> = RefCell::new(std::collections::HashMap::new()); -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub unsafe extern "C" fn build_font_kit() -> *const u8 { - let fontkit = FontKit::new(); - Box::into_raw(Box::new(fontkit)) as _ -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub unsafe extern "C" fn add_search_path(fontkit: *mut u8, custom_path: *const u8, len: usize) { - let fontkit = &mut *(fontkit as *mut FontKit); - let custom_path = std::slice::from_raw_parts(custom_path, len); - match std::str::from_utf8(custom_path) { - Ok("") => {} - Ok(path) => { - if let Err(e) = fontkit.search_fonts_from_path(path) { - eprintln!("{:?}", e); - } - } - Err(e) => { - eprintln!("{:?}", e) - } - } -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub unsafe extern "C" fn font_for_face( - fontkit: *mut FontKit, - font_face: *const u8, - len: usize, - weight: u32, - italic: bool, - stretch: u16, -) -> *const u8 { - let fontkit = &mut *fontkit; - let font_face = std::slice::from_raw_parts(font_face, len); - let font_face = std::str::from_utf8_unchecked(font_face); - let key = FontKey { - family: font_face.to_string(), - weight, - italic, - stretch: stretch as u32, - }; - let font = fontkit.query(&key); - match font { - Some(font) => font.deref() as *const _ as *const u8, - None => { - eprintln!("{:?} not found in {} fonts", key, fontkit.len()); - std::ptr::null() - } - } -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub unsafe extern "C" fn path_for_font(font: *const u8) -> *const u8 { - let font = &*(font as *const Font); - let path = match font.path().and_then(|p| p.to_str()).map(|p| p.to_string()) { - Some(p) => p, - None => return 0 as _, - }; - let buffer = path.as_bytes().to_vec(); - let (ptr, len) = into_raw(buffer); - ALLOCS.with(|map| map.borrow_mut().insert(ptr as u64, len)); - ptr -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub fn fontkit_alloc() -> *mut u8 { - let v = vec![0_u8; 1024]; - let (ptr, _) = into_raw(v); - ptr -} - -#[cfg(not(wasm))] -fn into_raw(mut v: Vec) -> (*mut T, usize) { - let ptr = v.as_mut_ptr(); - let len = v.len(); - v.shrink_to_fit(); - std::mem::forget(v); - (ptr, len) -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub unsafe fn fontkit_mfree(ptr: *mut u8) { - let _ = Vec::from_raw_parts(ptr, 1024, 1024); -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub unsafe fn free_fontkit(ptr: *mut FontKit) { - let _ = Box::from_raw(ptr); -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub unsafe fn free_fontkit_str(ptr: *mut u8) { - if let Some(len) = ALLOCS.with(|map| map.borrow_mut().remove(&(ptr as u64))) { - let _ = Vec::from_raw_parts(ptr, len, len); - } -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub fn fontkit_str_length(ptr: *const u8) -> u32 { - ALLOCS.with(|map| { - map.borrow() - .get(&(ptr as u64)) - .map(|l| *l as u32) - .unwrap_or_default() - }) -} - -#[cfg(not(wasm))] -#[doc(hidden)] -#[no_mangle] -pub unsafe extern "C" fn list_all_font(fontkit: *mut FontKit) -> *const u8 { - let kit = &*fontkit; - let fonts = kit - .fonts - .iter() - .map(|font| { - #[cfg(not(dashmap))] - let font = font.1; - let key = font.key(); - let path = match font.path().and_then(|p| p.to_str()).map(|p| p.to_string()) { - Some(p) => p, - None => "".to_string(), - }; - serde_json::json!({ - "names": font.names, - "stretch": key.stretch, - "italic": key.italic, - "weight": key.weight, - "family": key.family, - "styleNames": font.style_names.clone(), - "path": path, - }) - }) - .collect::>(); - let data = serde_json::to_string(&fonts).unwrap(); - let buffer = data.as_bytes().to_vec(); - let (ptr, len) = into_raw(buffer); - ALLOCS.with(|map| map.borrow_mut().insert(ptr as u64, len)); - ptr -} diff --git a/src/metrics.rs b/src/metrics.rs index 896d99a..f0f27ba 100644 --- a/src/metrics.rs +++ b/src/metrics.rs @@ -5,8 +5,6 @@ use ttf_parser::{GlyphId, Rect}; use unicode_bidi::{BidiInfo, Level}; use unicode_normalization::UnicodeNormalization; use unicode_script::{Script, ScriptExtension}; -#[cfg(wasm)] -use wasm_bindgen::prelude::*; mod arabic; mod compose; @@ -15,7 +13,6 @@ impl Font { /// Measure a string slice. If certain character is missing, the related /// [`CharMetrics`] 's `missing` field will be `true` pub fn measure(&self, text: &str) -> Result { - #[cfg(not(wasm))] self.load()?; let f = self.face.load(); let f = f.as_ref().as_ref().unwrap(); @@ -157,7 +154,6 @@ impl Font { } } -#[cfg_attr(wasm, wasm_bindgen)] #[derive(Debug, Clone, Default)] pub struct TextMetrics { value: String, @@ -168,7 +164,6 @@ pub struct TextMetrics { units: u16, } -#[cfg_attr(wasm, wasm_bindgen)] impl TextMetrics { pub fn width(&self, font_size: f32, letter_spacing: f32) -> f32 { let factor = font_size / self.units as f32; @@ -258,7 +253,6 @@ impl TextMetrics { } } -#[cfg_attr(wasm, wasm_bindgen)] #[derive(Debug, Clone)] pub struct PositionedChar { /// Various metrics data of current character @@ -269,7 +263,6 @@ pub struct PositionedChar { } /// Metrics for a single unicode charactor in a certain font -#[cfg_attr(wasm, wasm_bindgen)] #[derive(Debug, Clone, Copy)] pub struct CharMetrics { pub(crate) bbox: Rect, diff --git a/src/ras.rs b/src/ras.rs index de9b2fd..9696095 100644 --- a/src/ras.rs +++ b/src/ras.rs @@ -14,7 +14,6 @@ use ttf_parser::{OutlineBuilder, Rect}; impl Font { /// Output the outline instructions of a glyph pub fn outline(&self, c: char) -> Option<(Glyph, Outline)> { - #[cfg(not(wasm))] self.load().ok()?; let mut builder = PathBuilder::new(); let f = self.face.load(); @@ -44,7 +43,6 @@ impl Font { if !self.has_glyph(c) { return None; } - #[cfg(not(wasm))] self.load().ok()?; let f = self.face.load(); diff --git a/src/wasm.rs b/src/wasm.rs deleted file mode 100644 index 413b964..0000000 --- a/src/wasm.rs +++ /dev/null @@ -1,89 +0,0 @@ -use crate::*; -use pathfinder_content::outline::Outline; -use pathfinder_geometry::transform2d::Transform2F; -use pathfinder_geometry::vector::Vector2F; - -/// Interface for querying data in a Font -#[wasm_bindgen(js_name = "Font")] -pub struct FontWasm { - pub(super) ptr: *const Font, -} - -#[wasm_bindgen(js_class = "Font")] -impl FontWasm { - fn font(&self) -> &Font { - unsafe { &*self.ptr } - } - - /// Check if font contains a certain char - pub fn has_glyph(&self, c: char) -> bool { - self.font().has_glyph(c) - } - - /// Output the glyph's path in SVG path `d` style - #[cfg(feature = "ras")] - pub fn glyph_path(&self, c: char) -> Option { - let font = self.font(); - let (_, mut outline) = font.outline(c)?; - let height = font.ascender() as f32 - font.descender() as f32; - outline.transform(&Transform2F::from_scale(Vector2F::new(1.0, -1.0))); - outline.transform(&Transform2F::from_translation(Vector2F::new(0.0, height))); - Some(GlyphPath { outline }) - } - - #[wasm_bindgen(getter)] - pub fn key(&self) -> FontKey { - self.font().key() - } - - #[wasm_bindgen(getter)] - pub fn ascender(&self) -> i16 { - self.font().ascender() - } - - #[wasm_bindgen(getter)] - pub fn descender(&self) -> i16 { - self.font().descender() - } - - #[wasm_bindgen(getter)] - pub fn units_per_em(&self) -> u16 { - self.font().units_per_em() - } - - pub fn buffer(&self) -> Vec { - let f = self.font().face.load(); - let f = f.as_ref().as_ref().unwrap(); - f.borrow_buffer().clone() - } - - pub fn advanced_x(&self, c: char) -> Option { - let font = self.font(); - let (glyph, _) = font.outline(c)?; - Some(glyph.advanced_x) - } -} - -#[wasm_bindgen] -pub struct GlyphPath { - outline: Outline, -} - -#[wasm_bindgen] -impl GlyphPath { - /// Scale the path - pub fn scale(&mut self, scale: f32) { - self.outline.transform(&Transform2F::from_scale(scale)); - } - - /// Translate the path - pub fn translate(&mut self, x: f32, y: f32) { - self.outline - .transform(&Transform2F::from_translation(Vector2F::new(x, y))); - } - - /// Output the path following SVG `d` style - pub fn to_string(&mut self) -> String { - format!("{:?}", self.outline) - } -} diff --git a/src/wit.rs b/src/wit.rs new file mode 100644 index 0000000..1a9d439 --- /dev/null +++ b/src/wit.rs @@ -0,0 +1,169 @@ +use crate::bindings::exports::alibaba::fontkit::fontkit_interface as fi; +use crate::*; + +use self::bindings::exports::alibaba::fontkit::fontkit_interface::GuestTextMetrics; + +impl fi::GuestFont for Font { + fn has_glyph(&self, c: char) -> bool { + self.has_glyph(c) + } + + fn buffer(&self) -> Vec { + self.load().unwrap(); + let f = self.face.load(); + let f = f.as_ref().as_ref().unwrap(); + f.borrow_buffer().clone() + } + + fn path(&self) -> String { + self.path() + .and_then(|p| p.to_str()) + .unwrap_or_default() + .to_string() + } + + fn key(&self) -> fi::FontKey { + self.key().into() + } + + fn measure(&self, text: String) -> Result { + Ok(fi::TextMetrics::new( + self.measure(&text).map_err(|e| e.to_string())?, + )) + } + + fn ascender(&self) -> i16 { + self.ascender() + } + + fn descender(&self) -> i16 { + self.descender() + } + + fn units_per_em(&self) -> u16 { + self.units_per_em() + } +} + +impl From for FontKey { + fn from(value: fi::FontKey) -> Self { + FontKey { + weight: value.weight.unwrap_or(400) as u32, + italic: value.italic.unwrap_or(false), + stretch: value.stretch.unwrap_or(5) as u32, + family: value.family, + } + } +} + +impl From for fi::FontKey { + fn from(value: FontKey) -> Self { + fi::FontKey { + weight: Some(value.weight as u16), + italic: Some(value.italic), + stretch: Some(value.stretch as u16), + family: value.family, + } + } +} + +impl fi::GuestFontKit for FontKit { + fn new() -> Self { + FontKit::new() + } + + fn add_font_from_buffer(&self, buffer: Vec) -> Vec { + self.add_font_from_buffer(buffer) + .into_iter() + .flatten() + .map(fi::FontKey::from) + .collect() + } + + fn query(&self, key: fi::FontKey) -> Option { + self.query(&FontKey::from(key)) + .map(|f| fi::Font::new(f.clone())) + } + + fn exact_match(&self, key: fi::FontKey) -> Option { + self.exact_match(&FontKey::from(key)) + .map(|f| fi::Font::new(f.clone())) + } + + fn font_keys(&self) -> Vec { + self.font_keys().map(fi::FontKey::from).collect() + } + + fn len(&self) -> u32 { + self.len() as u32 + } + + fn remove(&self, key: fi::FontKey) { + self.remove(FontKey::from(key)) + } + + fn add_search_path(&self, path: String) { + self.search_fonts_from_path(path).unwrap() + } + + fn fonts_info(&self) -> Vec { + self.fonts + .iter() + .map(|i| fi::FontInfo { + style_names: i + .style_names + .iter() + .map(|n| fi::Name { + id: n.id, + name: n.name.clone(), + language_id: n.language_id, + }) + .collect(), + key: fi::FontKey::from(i.key().clone()), + names: i + .names + .iter() + .map(|n| fi::Name { + id: n.id, + name: n.name.clone(), + language_id: n.language_id, + }) + .collect(), + path: i.path().and_then(|p| Some(p.to_str()?.to_string())), + }) + .collect() + } +} + +impl GuestTextMetrics for TextMetrics { + fn width(&self, font_size: f32, letter_spacing: f32) -> f32 { + self.width(font_size, letter_spacing) + } + + fn height(&self, font_size: f32, line_height: Option) -> f32 { + self.height(font_size, line_height) + } + + fn ascender(&self, font_size: f32) -> f32 { + let factor = font_size / self.units() as f32; + (self.ascender() as f32 + self.line_gap() as f32 / 2.0) * factor + } +} + +struct Component; + +impl fi::Guest for Component { + type Font = Font; + type FontKit = FontKit; + type TextMetrics = TextMetrics; + + fn str_width_to_number(width: String) -> u16 { + crate::str_width_to_number(&width) + } + + fn number_width_to_str(width: u16) -> String { + crate::number_width_to_str(width).to_string() + } +} + +bindings::export!(Component with_types_in bindings); diff --git a/wit/world.wit b/wit/world.wit new file mode 100644 index 0000000..79e04ca --- /dev/null +++ b/wit/world.wit @@ -0,0 +1,69 @@ +package alibaba:fontkit; + +interface fontkit-interface { + record font-key { + weight: option, + italic: option, + stretch: option, + family: string, + } + record name { + id: u16, + name: string, + language-id: u16 + } + record font-info { + style-names: list, + names: list, + path: option, + key: font-key + } + resource text-metrics { + width: func(font-size: f32, letter-spacing: f32) -> f32; + height: func(font-size: f32, line-height: option) -> f32; + ascender: func(font-size: f32) -> f32; + } + /// Instance of a single font + resource font { + /// Check if the font has valid data for a character + has-glyph: func(c: char) -> bool; + /// Return the font buffer + buffer: func() -> list; + /// Return the path if this font is added from searching a path + path: func() -> string; + /// Return the key of this font + key: func() -> font-key; + /// Measure text using this font + measure: func(text: string) -> result; + ascender: func() -> s16; + descender: func() -> s16; + units-per-em: func() -> u16; + } + /// Stores font buffer and provides font-querying APIs + resource font-kit { + constructor(); + /// Register a font (or several fonts in case of ttc), return the keys of added fonts. + /// The file type is extracted from the buffer by checking magic numbers + add-font-from-buffer: func(buffer: list) -> list; + /// Search and add fonts from a path + add-search-path: func(path: string); + /// Query font using a key, this API returns valid result only if a single result is found + query: func(key: font-key) -> option; + /// Using exact-match method to directly obtain a font, skipping the querying logic + exact-match: func(key: font-key) -> option; + /// Get all registered fonts' keys + font-keys: func() -> list; + /// Get detailed info of all fonts registered + fonts-info: func() -> list; + /// Get number of registered fonts + len: func() -> u32; + /// Remove a font matching the given key + remove: func(key: font-key); + } + str-width-to-number: func(width: string) -> u16; + number-width-to-str: func(width: u16) -> string; +} + +world fontkit { + export fontkit-interface; +}