From 742deba471b392f6c58a9eb0cd54fac1e89e95a0 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 31 Mar 2023 00:44:05 -0700 Subject: [PATCH 01/22] Add UnicodeFuncs --- harfbuzz/src/buffer.rs | 9 + harfbuzz/src/lib.rs | 10 + harfbuzz/src/unicode_funcs.rs | 357 ++++++++++++++++++++++++++++++++++ 3 files changed, 376 insertions(+) create mode 100644 harfbuzz/src/unicode_funcs.rs diff --git a/harfbuzz/src/buffer.rs b/harfbuzz/src/buffer.rs index 12c1965d..6debfdcc 100644 --- a/harfbuzz/src/buffer.rs +++ b/harfbuzz/src/buffer.rs @@ -10,6 +10,8 @@ use std; use sys; +use crate::UnicodeFuncs; + use {Direction, Language}; /// A series of Unicode characters. @@ -120,6 +122,13 @@ impl Buffer { b } + /// Sets a [`UnicodeFuncs`] instance to use with this buffer. + /// + /// Note: `unicode_funcs` is reference counted by HarfBuzz. + pub fn set_unicode_funcs(&mut self, unicode_funcs: &UnicodeFuncs) { + unsafe { sys::hb_buffer_set_unicode_funcs(self.raw, unicode_funcs.as_ptr()) } + } + /// Add UTF-8 encoded text to the buffer. pub fn add_str(&mut self, text: &str) { unsafe { diff --git a/harfbuzz/src/lib.rs b/harfbuzz/src/lib.rs index dc8fe678..6ada18a9 100644 --- a/harfbuzz/src/lib.rs +++ b/harfbuzz/src/lib.rs @@ -31,3 +31,13 @@ pub use self::language::Language; mod blob; pub use self::blob::Blob; + +mod unicode_funcs; +pub use self::unicode_funcs::CombiningClassFunc; +pub use self::unicode_funcs::ComposeFunc; +pub use self::unicode_funcs::DecomposeFunc; +pub use self::unicode_funcs::GeneralCategoryFunc; +pub use self::unicode_funcs::MirroringFunc; +pub use self::unicode_funcs::ScriptFunc; +pub use self::unicode_funcs::UnicodeFuncs; +pub use self::unicode_funcs::UnicodeFuncsBuilder; diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs new file mode 100644 index 00000000..0b48e02b --- /dev/null +++ b/harfbuzz/src/unicode_funcs.rs @@ -0,0 +1,357 @@ +// Copyright 2023 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +use crate::sys::*; +use std::ffi::c_void; + +/// An object to map from code points to general category properties. +pub trait GeneralCategoryFunc { + /// Given a code point, return the general category as a + /// [`hb_unicode_general_category_t`]. + fn general_category(&self, ch: u32) -> hb_unicode_general_category_t; +} + +impl GeneralCategoryFunc for () { + fn general_category(&self, ch: u32) -> hb_unicode_general_category_t { + unreachable!() + } +} + +/// An object to map from code points to combining classes. +pub trait CombiningClassFunc { + /// Given a code point, return the combining class as a + /// [`hb_unicode_combining_class_t`]. + fn combining_class(&self, ch: u32) -> hb_unicode_combining_class_t; +} + +impl CombiningClassFunc for () { + fn combining_class(&self, ch: u32) -> hb_unicode_combining_class_t { + unreachable!() + } +} + +/// An object to map from code points to mirrored code points. +pub trait MirroringFunc { + /// Given a code point, return the mirrored code point. + fn mirroring(&self, ch: u32) -> u32; +} + +impl MirroringFunc for () { + fn mirroring(&self, ch: u32) -> u32 { + unreachable!() + } +} + +/// An object to map from code points to script names. +pub trait ScriptFunc { + /// Given a code point, return the script as a 4-byte script name. + fn script(&self, ch: u32) -> [u8; 4]; +} + +impl ScriptFunc for () { + fn script(&self, ch: u32) -> [u8; 4] { + unreachable!() + } +} + +/// An object to compose two characters. +pub trait ComposeFunc { + /// Given two code points, return the composed code point. + fn compose(&self, a: u32, b: u32) -> Option; +} + +impl ComposeFunc for () { + fn compose(&self, a: u32, b: u32) -> Option { + unreachable!() + } +} + +/// An object to decompose a character. +pub trait DecomposeFunc { + /// Given a code point, return the two decomposed code points. + fn decompose(&self, ab: u32) -> Option<(u32, u32)>; +} + +impl DecomposeFunc for () { + fn decompose(&self, ab: u32) -> Option<(u32, u32)> { + unreachable!() + } +} + +/// A builder for [`UnicodeFuncs`]. +#[non_exhaustive] +pub struct UnicodeFuncsBuilder { + /// Optional implementation of [`hb_unicode_general_category_func_t`]. + pub general_category: Option>, + /// Optional implementation of [`hb_unicode_combining_class_func_t`]. + pub combining_class: Option>, + /// Optional implementation of [`hb_unicode_mirroring_func_t`]. + pub mirroring: Option>, + /// Optional implementation of [`hb_unicode_script_func_t`]. + pub script: Option>, + /// Optional implementation of [`hb_unicode_compose_func_t`]. + pub compose: Option>, + /// Optional implementation of [`hb_unicode_decompose_func_t`]. + pub decompose: Option>, +} + +impl UnicodeFuncsBuilder { + /// Creates a new, empty builder. + pub fn new() -> Self { + Self { + general_category: None, + combining_class: None, + mirroring: None, + script: None, + compose: None, + decompose: None, + } + } +} + +impl UnicodeFuncsBuilder +where + F0: GeneralCategoryFunc, + F1: CombiningClassFunc, + F2: MirroringFunc, + F3: ScriptFunc, + F4: ComposeFunc, + F5: DecomposeFunc, +{ + /// Creates a [`UnicodeFuncs`] based on the fields in this builder. + pub fn build(self) -> Result { + unsafe { self.build_unsafe() } + } + + unsafe fn build_unsafe(self) -> Result { + let empty = hb_unicode_funcs_get_empty(); + // The HarfBuzz refcounting convention is that "create" + // sets refcount to one, not zero. + // https://harfbuzz.github.io/object-model-lifecycle.html + let ufuncs = hb_unicode_funcs_create(empty); + if ufuncs == empty { + // return Err(HarfBuzzError::Alloc); + return Err(()); + } + + if let Some(general_category) = self.general_category { + let general_category_ptr: *mut F0 = Box::into_raw(general_category); + extern "C" fn impl_general_category( + _ufuncs: *mut hb_unicode_funcs_t, + unicode: hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_unicode_general_category_t { + unsafe { &*(user_data as *mut F0) }.general_category(unicode) + } + extern "C" fn destroy_general_category(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F0) }; + } + hb_unicode_funcs_set_general_category_func( + ufuncs, + Some(impl_general_category::), + general_category_ptr as *mut c_void, + Some(destroy_general_category::), + ); + } + + if let Some(combining_class) = self.combining_class { + let combining_class_ptr: *mut F1 = Box::into_raw(combining_class); + extern "C" fn impl_combining_class( + _ufuncs: *mut hb_unicode_funcs_t, + unicode: hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_unicode_combining_class_t { + unsafe { &*(user_data as *mut F1) }.combining_class(unicode) + } + extern "C" fn destroy_combining_class(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F1) }; + } + hb_unicode_funcs_set_combining_class_func( + ufuncs, + Some(impl_combining_class::), + combining_class_ptr as *mut c_void, + Some(destroy_combining_class::), + ); + } + + if let Some(mirroring) = self.mirroring { + let mirroring_ptr: *mut F2 = Box::into_raw(mirroring); + extern "C" fn impl_mirroring( + _ufuncs: *mut hb_unicode_funcs_t, + unicode: hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_codepoint_t { + unsafe { &*(user_data as *mut F2) }.mirroring(unicode) + } + extern "C" fn destroy_mirroring(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F2) }; + } + hb_unicode_funcs_set_mirroring_func( + ufuncs, + Some(impl_mirroring::), + mirroring_ptr as *mut c_void, + Some(destroy_mirroring::), + ); + } + + if let Some(script) = self.script { + let script_ptr: *mut F3 = Box::into_raw(script); + extern "C" fn impl_script( + _ufuncs: *mut hb_unicode_funcs_t, + unicode: hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_codepoint_t { + let code = unsafe { &*(user_data as *mut F3) }.script(unicode); + unsafe { hb_script_from_string(code.as_ptr() as *const i8, 4) } + } + extern "C" fn destroy_script(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F3) }; + } + hb_unicode_funcs_set_script_func( + ufuncs, + Some(impl_script::), + script_ptr as *mut c_void, + Some(destroy_script::), + ); + } + + if let Some(compose) = self.compose { + let compose_ptr: *mut F4 = Box::into_raw(compose); + extern "C" fn impl_compose( + _ufuncs: *mut hb_unicode_funcs_t, + a: hb_codepoint_t, + b: hb_codepoint_t, + ab: *mut hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_bool_t { + let result = unsafe { &*(user_data as *mut F4) }.compose(a, b); + match result { + Some(ab_x) => { + unsafe { *ab = ab_x }; + true as hb_bool_t + } + None => false as hb_bool_t, + } + } + extern "C" fn destroy_compose(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F4) }; + } + hb_unicode_funcs_set_compose_func( + ufuncs, + Some(impl_compose::), + compose_ptr as *mut c_void, + Some(destroy_compose::), + ); + } + + if let Some(decompose) = self.decompose { + let decompose_ptr: *mut F5 = Box::into_raw(decompose); + extern "C" fn impl_decompose( + _ufuncs: *mut hb_unicode_funcs_t, + ab: hb_codepoint_t, + a: *mut hb_codepoint_t, + b: *mut hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_bool_t { + let result = unsafe { &*(user_data as *mut F5) }.decompose(ab); + match result { + Some((a_x, b_x)) => { + unsafe { *a = a_x }; + unsafe { *b = b_x }; + true as hb_bool_t + } + None => false as hb_bool_t, + } + } + extern "C" fn destroy_decompose(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F5) }; + } + hb_unicode_funcs_set_decompose_func( + ufuncs, + Some(impl_decompose::), + decompose_ptr as *mut c_void, + Some(destroy_decompose::), + ); + } + + // Compatibility decomposition and East Asian Width lookups + // are deprecated, and there's no need to set up the callbacks + // for those. + + hb_unicode_funcs_make_immutable(ufuncs); + Ok(UnicodeFuncs::from_raw(ufuncs)) + } +} + +/// A collection of functions to run Unicode algorithms required by HarfBuzz. +/// +/// Create one of these using a [`UnicodeFuncsBuilder`]. +/// +/// # Example +/// +/// ``` +/// # use harfbuzz::{Buffer, Direction, UnicodeFuncsBuilder, sys}; +/// struct GeneralCategoryCalculator; +/// +/// impl harfbuzz::GeneralCategoryFunc for GeneralCategoryCalculator { +/// fn general_category(&self, ch: u32) -> harfbuzz::sys::hb_unicode_general_category_t { +/// todo!() +/// } +/// } +/// +/// let mut unicode_funcs = UnicodeFuncsBuilder::<_, (), (), (), (), ()>::new(); +/// unicode_funcs.general_category = Some(Box::new(GeneralCategoryCalculator)); +/// let unicode_funcs = unicode_funcs.build().unwrap(); +/// +/// let mut b = Buffer::with("مساء الخير"); +/// b.set_unicode_funcs(&unicode_funcs); +/// b.guess_segment_properties(); +/// assert_eq!(b.get_direction(), Direction::RTL); +/// assert_eq!(b.get_script(), sys::HB_SCRIPT_ARABIC); +/// ``` +pub struct UnicodeFuncs { + raw: *mut hb_unicode_funcs_t, +} + +impl UnicodeFuncs { + /// Takes ownership of a `*mut hb_unicode_funcs_t` without incrementing + /// the refcount. + /// + /// # Safety + /// + /// After the call, the previous owner must not call + /// `hb_unicode_funcs_destroy()`, since `UnicodeFuncs` will now + /// take care of it. + pub unsafe fn from_raw(raw: *mut hb_unicode_funcs_t) -> Self { + Self { raw } + } + + /// Transfers the ownership of the wrapped pointer to the caller. + /// The caller is responsible for calling `hb_unicode_funcs_destroy()`; + /// `UnicodeFuncs` will no longer take care of it. + pub fn into_raw(funcs: Self) -> *mut hb_unicode_funcs_t { + let ret = funcs.raw; + core::mem::forget(funcs); + ret + } + + /// Borrows the wrapped raw pointer without transferring ownership + /// and without affecting the refcount. + pub fn as_ptr(&self) -> *mut hb_unicode_funcs_t { + self.raw + } +} + +impl Drop for UnicodeFuncs { + fn drop(&mut self) { + unsafe { + hb_unicode_funcs_destroy(self.raw); + } + } +} From 992ead8e90c9aa996ca2c68d94dbf03378f98d27 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 31 Mar 2023 01:01:54 -0700 Subject: [PATCH 02/22] Add ability to set parent --- harfbuzz/src/unicode_funcs.rs | 39 +++++++++++++++++++++++++---------- 1 file changed, 28 insertions(+), 11 deletions(-) diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index 0b48e02b..ef09f308 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -19,7 +19,7 @@ pub trait GeneralCategoryFunc { impl GeneralCategoryFunc for () { fn general_category(&self, ch: u32) -> hb_unicode_general_category_t { - unreachable!() + panic!("Stub implementation of GeneralCategoryFunc") } } @@ -32,7 +32,7 @@ pub trait CombiningClassFunc { impl CombiningClassFunc for () { fn combining_class(&self, ch: u32) -> hb_unicode_combining_class_t { - unreachable!() + panic!("Stub implementation of CombiningClassFunc") } } @@ -44,7 +44,7 @@ pub trait MirroringFunc { impl MirroringFunc for () { fn mirroring(&self, ch: u32) -> u32 { - unreachable!() + panic!("Stub implementation of MirroringFunc") } } @@ -56,7 +56,7 @@ pub trait ScriptFunc { impl ScriptFunc for () { fn script(&self, ch: u32) -> [u8; 4] { - unreachable!() + panic!("Stub implementation of ScriptFunc") } } @@ -68,7 +68,7 @@ pub trait ComposeFunc { impl ComposeFunc for () { fn compose(&self, a: u32, b: u32) -> Option { - unreachable!() + panic!("Stub implementation of ComposeFunc") } } @@ -80,11 +80,13 @@ pub trait DecomposeFunc { impl DecomposeFunc for () { fn decompose(&self, ab: u32) -> Option<(u32, u32)> { - unreachable!() + panic!("Stub implementation of DecomposeFunc") } } /// A builder for [`UnicodeFuncs`]. +/// +/// If one or more of the functions is not provided, set its type parameter to `()`. #[non_exhaustive] pub struct UnicodeFuncsBuilder { /// Optional implementation of [`hb_unicode_general_category_func_t`]. @@ -99,11 +101,26 @@ pub struct UnicodeFuncsBuilder { pub compose: Option>, /// Optional implementation of [`hb_unicode_decompose_func_t`]. pub decompose: Option>, + /// Parent unicode_funcs_t instance. + pub raw_parent: *mut hb_unicode_funcs_t, } impl UnicodeFuncsBuilder { /// Creates a new, empty builder. - pub fn new() -> Self { + pub fn new_with_empty_parent() -> Self { + Self { + general_category: None, + combining_class: None, + mirroring: None, + script: None, + compose: None, + decompose: None, + raw_parent: unsafe { hb_unicode_funcs_get_empty() }, + } + } + + /// Creates a new, empty builder, with the parent set to the HarfBuzz default. + pub fn new_with_harfbuzz_default_parent() -> Self { Self { general_category: None, combining_class: None, @@ -111,6 +128,7 @@ impl UnicodeFuncsBuilder { script: None, compose: None, decompose: None, + raw_parent: unsafe { hb_unicode_funcs_get_default() }, } } } @@ -130,12 +148,11 @@ where } unsafe fn build_unsafe(self) -> Result { - let empty = hb_unicode_funcs_get_empty(); // The HarfBuzz refcounting convention is that "create" // sets refcount to one, not zero. // https://harfbuzz.github.io/object-model-lifecycle.html - let ufuncs = hb_unicode_funcs_create(empty); - if ufuncs == empty { + let ufuncs = hb_unicode_funcs_create(self.raw_parent); + if ufuncs == self.raw_parent { // return Err(HarfBuzzError::Alloc); return Err(()); } @@ -305,7 +322,7 @@ where /// } /// } /// -/// let mut unicode_funcs = UnicodeFuncsBuilder::<_, (), (), (), (), ()>::new(); +/// let mut unicode_funcs = UnicodeFuncsBuilder::<_, (), (), (), (), ()>::new_with_empty_parent(); /// unicode_funcs.general_category = Some(Box::new(GeneralCategoryCalculator)); /// let unicode_funcs = unicode_funcs.build().unwrap(); /// From 1980bc9711ffcb5b0b92a7d5a4e0b7140f1ca728 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Fri, 31 Mar 2023 01:21:33 -0700 Subject: [PATCH 03/22] Use individual functions with individual bounds --- harfbuzz/src/lib.rs | 8 + harfbuzz/src/unicode_funcs.rs | 400 ++++++++++++++++------------------ 2 files changed, 197 insertions(+), 211 deletions(-) diff --git a/harfbuzz/src/lib.rs b/harfbuzz/src/lib.rs index 6ada18a9..86c18b36 100644 --- a/harfbuzz/src/lib.rs +++ b/harfbuzz/src/lib.rs @@ -20,6 +20,14 @@ pub extern crate harfbuzz_sys as sys; +/// An error type for this crate +#[derive(Debug)] +pub enum HarfBuzzError { + /// Allocation failed within HarfBuzz itself + Alloc, +} +pub use HarfBuzzError as Error; + mod buffer; pub use self::buffer::Buffer; diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index ef09f308..31751763 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -8,6 +8,7 @@ // except according to those terms. use crate::sys::*; +use crate::Error; use std::ffi::c_void; /// An object to map from code points to general category properties. @@ -17,12 +18,6 @@ pub trait GeneralCategoryFunc { fn general_category(&self, ch: u32) -> hb_unicode_general_category_t; } -impl GeneralCategoryFunc for () { - fn general_category(&self, ch: u32) -> hb_unicode_general_category_t { - panic!("Stub implementation of GeneralCategoryFunc") - } -} - /// An object to map from code points to combining classes. pub trait CombiningClassFunc { /// Given a code point, return the combining class as a @@ -30,279 +25,262 @@ pub trait CombiningClassFunc { fn combining_class(&self, ch: u32) -> hb_unicode_combining_class_t; } -impl CombiningClassFunc for () { - fn combining_class(&self, ch: u32) -> hb_unicode_combining_class_t { - panic!("Stub implementation of CombiningClassFunc") - } -} - /// An object to map from code points to mirrored code points. pub trait MirroringFunc { /// Given a code point, return the mirrored code point. fn mirroring(&self, ch: u32) -> u32; } -impl MirroringFunc for () { - fn mirroring(&self, ch: u32) -> u32 { - panic!("Stub implementation of MirroringFunc") - } -} - /// An object to map from code points to script names. pub trait ScriptFunc { /// Given a code point, return the script as a 4-byte script name. fn script(&self, ch: u32) -> [u8; 4]; } -impl ScriptFunc for () { - fn script(&self, ch: u32) -> [u8; 4] { - panic!("Stub implementation of ScriptFunc") - } -} - /// An object to compose two characters. pub trait ComposeFunc { /// Given two code points, return the composed code point. fn compose(&self, a: u32, b: u32) -> Option; } -impl ComposeFunc for () { - fn compose(&self, a: u32, b: u32) -> Option { - panic!("Stub implementation of ComposeFunc") - } -} - /// An object to decompose a character. pub trait DecomposeFunc { /// Given a code point, return the two decomposed code points. fn decompose(&self, ab: u32) -> Option<(u32, u32)>; } -impl DecomposeFunc for () { - fn decompose(&self, ab: u32) -> Option<(u32, u32)> { - panic!("Stub implementation of DecomposeFunc") - } -} - /// A builder for [`UnicodeFuncs`]. /// /// If one or more of the functions is not provided, set its type parameter to `()`. #[non_exhaustive] -pub struct UnicodeFuncsBuilder { - /// Optional implementation of [`hb_unicode_general_category_func_t`]. - pub general_category: Option>, - /// Optional implementation of [`hb_unicode_combining_class_func_t`]. - pub combining_class: Option>, - /// Optional implementation of [`hb_unicode_mirroring_func_t`]. - pub mirroring: Option>, - /// Optional implementation of [`hb_unicode_script_func_t`]. - pub script: Option>, - /// Optional implementation of [`hb_unicode_compose_func_t`]. - pub compose: Option>, - /// Optional implementation of [`hb_unicode_decompose_func_t`]. - pub decompose: Option>, - /// Parent unicode_funcs_t instance. - pub raw_parent: *mut hb_unicode_funcs_t, +#[derive(Debug)] +pub struct UnicodeFuncsBuilder { + raw: *mut hb_unicode_funcs_t, } -impl UnicodeFuncsBuilder { +impl UnicodeFuncsBuilder { /// Creates a new, empty builder. - pub fn new_with_empty_parent() -> Self { - Self { - general_category: None, - combining_class: None, - mirroring: None, - script: None, - compose: None, - decompose: None, - raw_parent: unsafe { hb_unicode_funcs_get_empty() }, - } - } - - /// Creates a new, empty builder, with the parent set to the HarfBuzz default. - pub fn new_with_harfbuzz_default_parent() -> Self { - Self { - general_category: None, - combining_class: None, - mirroring: None, - script: None, - compose: None, - decompose: None, - raw_parent: unsafe { hb_unicode_funcs_get_default() }, + pub fn new_with_empty_parent() -> Result { + let parent = unsafe { hb_unicode_funcs_get_empty() }; + // The HarfBuzz refcounting convention is that "create" + // sets refcount to one, not zero. + // https://harfbuzz.github.io/object-model-lifecycle.html + let ufuncs = unsafe { hb_unicode_funcs_create(parent) }; + if ufuncs == parent { + return Err(Error::Alloc); } - } -} - -impl UnicodeFuncsBuilder -where - F0: GeneralCategoryFunc, - F1: CombiningClassFunc, - F2: MirroringFunc, - F3: ScriptFunc, - F4: ComposeFunc, - F5: DecomposeFunc, -{ - /// Creates a [`UnicodeFuncs`] based on the fields in this builder. - pub fn build(self) -> Result { - unsafe { self.build_unsafe() } + Ok(Self { raw: ufuncs }) } - unsafe fn build_unsafe(self) -> Result { + /// Creates a new builder with the parent set to the HarfBuzz default. + pub fn new_with_harfbuzz_default_parent() -> Result { + let parent = unsafe { hb_unicode_funcs_get_default() }; // The HarfBuzz refcounting convention is that "create" // sets refcount to one, not zero. // https://harfbuzz.github.io/object-model-lifecycle.html - let ufuncs = hb_unicode_funcs_create(self.raw_parent); - if ufuncs == self.raw_parent { - // return Err(HarfBuzzError::Alloc); - return Err(()); + let ufuncs = unsafe { hb_unicode_funcs_create(parent) }; + if ufuncs == parent { + return Err(Error::Alloc); } + Ok(Self { raw: ufuncs }) + } - if let Some(general_category) = self.general_category { - let general_category_ptr: *mut F0 = Box::into_raw(general_category); - extern "C" fn impl_general_category( - _ufuncs: *mut hb_unicode_funcs_t, - unicode: hb_codepoint_t, - user_data: *mut c_void, - ) -> hb_unicode_general_category_t { - unsafe { &*(user_data as *mut F0) }.general_category(unicode) - } - extern "C" fn destroy_general_category(user_data: *mut c_void) { - let _ = unsafe { Box::from_raw(user_data as *mut F0) }; - } + /// Sets an implementation of [`hb_unicode_general_category_func_t`]. + pub fn set_general_category_func(&mut self, f: Box) { + let general_category_ptr: *mut F = Box::into_raw(f); + extern "C" fn impl_general_category( + _ufuncs: *mut hb_unicode_funcs_t, + unicode: hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_unicode_general_category_t { + unsafe { &*(user_data as *mut F) }.general_category(unicode) + } + extern "C" fn destroy_general_category(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F) }; + } + unsafe { hb_unicode_funcs_set_general_category_func( - ufuncs, - Some(impl_general_category::), + self.raw, + Some(impl_general_category::), general_category_ptr as *mut c_void, - Some(destroy_general_category::), + Some(destroy_general_category::), ); } + } - if let Some(combining_class) = self.combining_class { - let combining_class_ptr: *mut F1 = Box::into_raw(combining_class); - extern "C" fn impl_combining_class( - _ufuncs: *mut hb_unicode_funcs_t, - unicode: hb_codepoint_t, - user_data: *mut c_void, - ) -> hb_unicode_combining_class_t { - unsafe { &*(user_data as *mut F1) }.combining_class(unicode) - } - extern "C" fn destroy_combining_class(user_data: *mut c_void) { - let _ = unsafe { Box::from_raw(user_data as *mut F1) }; - } + /// Sets an implementation of [`hb_unicode_combining_class_func_t`]. + pub fn set_combining_class_func(&mut self, f: Box) { + let combining_class_ptr: *mut F = Box::into_raw(f); + extern "C" fn impl_combining_class( + _ufuncs: *mut hb_unicode_funcs_t, + unicode: hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_unicode_combining_class_t { + unsafe { &*(user_data as *mut F) }.combining_class(unicode) + } + extern "C" fn destroy_combining_class(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F) }; + } + unsafe { hb_unicode_funcs_set_combining_class_func( - ufuncs, - Some(impl_combining_class::), + self.raw, + Some(impl_combining_class::), combining_class_ptr as *mut c_void, - Some(destroy_combining_class::), + Some(destroy_combining_class::), ); } + } - if let Some(mirroring) = self.mirroring { - let mirroring_ptr: *mut F2 = Box::into_raw(mirroring); - extern "C" fn impl_mirroring( - _ufuncs: *mut hb_unicode_funcs_t, - unicode: hb_codepoint_t, - user_data: *mut c_void, - ) -> hb_codepoint_t { - unsafe { &*(user_data as *mut F2) }.mirroring(unicode) - } - extern "C" fn destroy_mirroring(user_data: *mut c_void) { - let _ = unsafe { Box::from_raw(user_data as *mut F2) }; - } + /// Sets an implementation of [`hb_unicode_mirroring_func_t`]. + pub fn set_mirroring_func(&mut self, f: Box) { + let mirroring_ptr: *mut F = Box::into_raw(f); + extern "C" fn impl_mirroring( + _ufuncs: *mut hb_unicode_funcs_t, + unicode: hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_codepoint_t { + unsafe { &*(user_data as *mut F) }.mirroring(unicode) + } + extern "C" fn destroy_mirroring(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F) }; + } + unsafe { hb_unicode_funcs_set_mirroring_func( - ufuncs, - Some(impl_mirroring::), + self.raw, + Some(impl_mirroring::), mirroring_ptr as *mut c_void, - Some(destroy_mirroring::), + Some(destroy_mirroring::), ); } + } - if let Some(script) = self.script { - let script_ptr: *mut F3 = Box::into_raw(script); - extern "C" fn impl_script( - _ufuncs: *mut hb_unicode_funcs_t, - unicode: hb_codepoint_t, - user_data: *mut c_void, - ) -> hb_codepoint_t { - let code = unsafe { &*(user_data as *mut F3) }.script(unicode); - unsafe { hb_script_from_string(code.as_ptr() as *const i8, 4) } - } - extern "C" fn destroy_script(user_data: *mut c_void) { - let _ = unsafe { Box::from_raw(user_data as *mut F3) }; - } + /// Sets an implementation of [`hb_unicode_script_func_t`]. + pub fn set_script_func(&mut self, f: Box) { + let script_ptr: *mut F = Box::into_raw(f); + extern "C" fn impl_script( + _ufuncs: *mut hb_unicode_funcs_t, + unicode: hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_codepoint_t { + let code = unsafe { &*(user_data as *mut F) }.script(unicode); + unsafe { hb_script_from_string(code.as_ptr() as *const i8, 4) } + } + extern "C" fn destroy_script(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F) }; + } + unsafe { hb_unicode_funcs_set_script_func( - ufuncs, - Some(impl_script::), + self.raw, + Some(impl_script::), script_ptr as *mut c_void, - Some(destroy_script::), + Some(destroy_script::), ); } + } - if let Some(compose) = self.compose { - let compose_ptr: *mut F4 = Box::into_raw(compose); - extern "C" fn impl_compose( - _ufuncs: *mut hb_unicode_funcs_t, - a: hb_codepoint_t, - b: hb_codepoint_t, - ab: *mut hb_codepoint_t, - user_data: *mut c_void, - ) -> hb_bool_t { - let result = unsafe { &*(user_data as *mut F4) }.compose(a, b); - match result { - Some(ab_x) => { - unsafe { *ab = ab_x }; - true as hb_bool_t - } - None => false as hb_bool_t, + /// Sets an implementation of [`hb_unicode_compose_func_t`]. + pub fn set_compose_func(&mut self, f: Box) { + let compose_ptr: *mut F = Box::into_raw(f); + extern "C" fn impl_compose( + _ufuncs: *mut hb_unicode_funcs_t, + a: hb_codepoint_t, + b: hb_codepoint_t, + ab: *mut hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_bool_t { + let result = unsafe { &*(user_data as *mut F) }.compose(a, b); + match result { + Some(ab_x) => { + unsafe { *ab = ab_x }; + true as hb_bool_t } + None => false as hb_bool_t, } - extern "C" fn destroy_compose(user_data: *mut c_void) { - let _ = unsafe { Box::from_raw(user_data as *mut F4) }; - } + } + extern "C" fn destroy_compose(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F) }; + } + unsafe { hb_unicode_funcs_set_compose_func( - ufuncs, - Some(impl_compose::), + self.raw, + Some(impl_compose::), compose_ptr as *mut c_void, - Some(destroy_compose::), + Some(destroy_compose::), ); } + } - if let Some(decompose) = self.decompose { - let decompose_ptr: *mut F5 = Box::into_raw(decompose); - extern "C" fn impl_decompose( - _ufuncs: *mut hb_unicode_funcs_t, - ab: hb_codepoint_t, - a: *mut hb_codepoint_t, - b: *mut hb_codepoint_t, - user_data: *mut c_void, - ) -> hb_bool_t { - let result = unsafe { &*(user_data as *mut F5) }.decompose(ab); - match result { - Some((a_x, b_x)) => { - unsafe { *a = a_x }; - unsafe { *b = b_x }; - true as hb_bool_t - } - None => false as hb_bool_t, + /// Sets an implementation of [`hb_unicode_decompose_func_t`]. + pub fn set_decompose_func(&mut self, f: Box) { + let decompose_ptr: *mut F = Box::into_raw(f); + extern "C" fn impl_decompose( + _ufuncs: *mut hb_unicode_funcs_t, + ab: hb_codepoint_t, + a: *mut hb_codepoint_t, + b: *mut hb_codepoint_t, + user_data: *mut c_void, + ) -> hb_bool_t { + let result = unsafe { &*(user_data as *mut F) }.decompose(ab); + match result { + Some((a_x, b_x)) => { + unsafe { *a = a_x }; + unsafe { *b = b_x }; + true as hb_bool_t } + None => false as hb_bool_t, } - extern "C" fn destroy_decompose(user_data: *mut c_void) { - let _ = unsafe { Box::from_raw(user_data as *mut F5) }; - } + } + extern "C" fn destroy_decompose(user_data: *mut c_void) { + let _ = unsafe { Box::from_raw(user_data as *mut F) }; + } + unsafe { hb_unicode_funcs_set_decompose_func( - ufuncs, - Some(impl_decompose::), + self.raw, + Some(impl_decompose::), decompose_ptr as *mut c_void, - Some(destroy_decompose::), + Some(destroy_decompose::), ); } + } + + /// Creates a [`UnicodeFuncs`] based on this builder. + pub fn build(self) -> UnicodeFuncs { + let raw = self.raw; + unsafe { + hb_unicode_funcs_make_immutable(raw); + } + core::mem::forget(self); + // Safety: Ownership is being transferred + unsafe { UnicodeFuncs::from_raw(raw) } + } - // Compatibility decomposition and East Asian Width lookups - // are deprecated, and there's no need to set up the callbacks - // for those. + /// Takes ownership of a `*mut hb_unicode_funcs_t` without incrementing + /// the refcount. + /// + /// # Safety + /// + /// After the call, the previous owner must not call + /// `hb_unicode_funcs_destroy()`, since `UnicodeFuncs` will now + /// take care of it. + pub unsafe fn from_raw(raw: *mut hb_unicode_funcs_t) -> Self { + Self { raw } + } - hb_unicode_funcs_make_immutable(ufuncs); - Ok(UnicodeFuncs::from_raw(ufuncs)) + /// Transfers the ownership of the wrapped pointer to the caller. + /// The caller is responsible for calling `hb_unicode_funcs_destroy()`; + /// `UnicodeFuncs` will no longer take care of it. + pub fn into_raw(self) -> *mut hb_unicode_funcs_t { + let ret = self.raw; + core::mem::forget(self); + ret + } +} + +impl Drop for UnicodeFuncsBuilder { + fn drop(&mut self) { + unsafe { + hb_unicode_funcs_destroy(self.raw); + } } } @@ -322,9 +300,9 @@ where /// } /// } /// -/// let mut unicode_funcs = UnicodeFuncsBuilder::<_, (), (), (), (), ()>::new_with_empty_parent(); -/// unicode_funcs.general_category = Some(Box::new(GeneralCategoryCalculator)); -/// let unicode_funcs = unicode_funcs.build().unwrap(); +/// let mut unicode_funcs = UnicodeFuncsBuilder::new_with_empty_parent().unwrap(); +/// unicode_funcs.set_general_category_func(Box::new(GeneralCategoryCalculator)); +/// let unicode_funcs = unicode_funcs.build(); /// /// let mut b = Buffer::with("مساء الخير"); /// b.set_unicode_funcs(&unicode_funcs); @@ -352,9 +330,9 @@ impl UnicodeFuncs { /// Transfers the ownership of the wrapped pointer to the caller. /// The caller is responsible for calling `hb_unicode_funcs_destroy()`; /// `UnicodeFuncs` will no longer take care of it. - pub fn into_raw(funcs: Self) -> *mut hb_unicode_funcs_t { - let ret = funcs.raw; - core::mem::forget(funcs); + pub fn into_raw(self) -> *mut hb_unicode_funcs_t { + let ret = self.raw; + core::mem::forget(self); ret } From 2792d92537614ec2712aa1d4403a893a4b455b21 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Tue, 1 Aug 2023 16:27:16 -0700 Subject: [PATCH 04/22] Make the crate no_std and add harfbuzz-sys feature --- .github/workflows/main.yml | 5 ++++ harfbuzz/Cargo.toml | 9 ++++--- harfbuzz/src/blob.rs | 11 ++++++--- harfbuzz/src/buffer.rs | 17 ++++++------- harfbuzz/src/language.rs | 11 ++++----- harfbuzz/src/lib.rs | 34 ++++++++++++++++++++------ harfbuzz/src/traits.rs | 46 +++++++++++++++++++++++++++++++++++ harfbuzz/src/unicode_funcs.rs | 44 +++------------------------------ 8 files changed, 107 insertions(+), 70 deletions(-) create mode 100644 harfbuzz/src/traits.rs diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index e532987f..f6a38f59 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -47,6 +47,11 @@ jobs: run: cargo test --all env: RUST_BACKTRACE: 1 + + - name: Cargo check no-default-features + run: cargo check --no-default-features + env: + RUST_BACKTRACE: 1 - name: ctest tests run: cargo run --manifest-path=harfbuzz-sys-test/Cargo.toml diff --git a/harfbuzz/Cargo.toml b/harfbuzz/Cargo.toml index 255d976e..474cab72 100644 --- a/harfbuzz/Cargo.toml +++ b/harfbuzz/Cargo.toml @@ -14,8 +14,11 @@ keywords = ["opentype", "font", "text", "layout", "unicode"] path = "../harfbuzz-sys" version = "0.5.0" default-features = false +optional = true [features] -default = ["build-native-harfbuzz", "build-native-freetype"] -build-native-harfbuzz = ["harfbuzz-sys/build-native-harfbuzz"] -build-native-freetype = ["harfbuzz-sys/build-native-freetype"] +default = ["harfbuzz-sys", "std", "build-native-harfbuzz", "build-native-freetype"] +harfbuzz-sys = ["dep:harfbuzz-sys"] +std = [] +build-native-harfbuzz = ["harfbuzz-sys?/build-native-harfbuzz"] +build-native-freetype = ["harfbuzz-sys?/build-native-freetype"] diff --git a/harfbuzz/src/blob.rs b/harfbuzz/src/blob.rs index 6863930a..67f60561 100644 --- a/harfbuzz/src/blob.rs +++ b/harfbuzz/src/blob.rs @@ -7,12 +7,14 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std::marker::PhantomData; -use std::os::raw::{c_char, c_uint, c_void}; -use std::sync::Arc; -use std::{mem, ops, ptr, slice}; +use core::ffi::{c_char, c_uint}; +use core::marker::PhantomData; +use core::{mem, ops, ptr, slice}; use sys; +#[cfg(feature = "std")] +use std::{ffi::c_void, sync::Arc, vec::Vec}; + /// Blobs wrap a chunk of binary data to handle lifecycle management of data /// while it is passed between client and HarfBuzz. /// @@ -63,6 +65,7 @@ impl<'a> Blob<'a> { /// assert_eq!(blob.len(), 256); /// assert!(!blob.is_empty()); /// ``` + #[cfg(feature = "std")] pub fn new_from_arc_vec(data: Arc>) -> Blob<'static> { let len = data.len(); assert!(len <= c_uint::max_value() as usize); diff --git a/harfbuzz/src/buffer.rs b/harfbuzz/src/buffer.rs index 6debfdcc..bc0ef627 100644 --- a/harfbuzz/src/buffer.rs +++ b/harfbuzz/src/buffer.rs @@ -7,7 +7,6 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use std; use sys; use crate::UnicodeFuncs; @@ -104,7 +103,7 @@ impl Buffer { /// Gives up ownership and returns a raw pointer to the buffer. pub fn into_raw(self) -> *mut sys::hb_buffer_t { let raw = self.raw; - std::mem::forget(self); + core::mem::forget(self); raw } @@ -134,10 +133,10 @@ impl Buffer { unsafe { sys::hb_buffer_add_utf8( self.raw, - text.as_ptr() as *const std::os::raw::c_char, - text.len() as std::os::raw::c_int, + text.as_ptr() as *const core::ffi::c_char, + text.len() as core::ffi::c_int, 0, - text.len() as std::os::raw::c_int, + text.len() as core::ffi::c_int, ) }; } @@ -156,8 +155,8 @@ impl Buffer { sys::hb_buffer_append( self.raw, other.raw, - start as std::os::raw::c_uint, - end as std::os::raw::c_uint, + start as core::ffi::c_uint, + end as core::ffi::c_uint, ) }; } @@ -309,8 +308,8 @@ impl Buffer { } } -impl std::fmt::Debug for Buffer { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Debug for Buffer { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { fmt.debug_struct("Buffer") .field("direction", &self.get_direction()) .field("script", &self.get_script()) diff --git a/harfbuzz/src/language.rs b/harfbuzz/src/language.rs index 6bf93376..3fe9ea75 100644 --- a/harfbuzz/src/language.rs +++ b/harfbuzz/src/language.rs @@ -9,7 +9,6 @@ #![allow(missing_docs)] -use std; use sys; #[derive(Copy, Clone, PartialEq, PartialOrd)] @@ -27,15 +26,15 @@ impl Language { Language { raw: unsafe { sys::hb_language_from_string( - lang.as_ptr() as *const std::os::raw::c_char, - lang.len() as std::os::raw::c_int, + lang.as_ptr() as *const core::ffi::c_char, + lang.len() as core::ffi::c_int, ) }, } } pub fn to_string(&self) -> &str { - unsafe { std::ffi::CStr::from_ptr(sys::hb_language_to_string(self.raw)) } + unsafe { core::ffi::CStr::from_ptr(sys::hb_language_to_string(self.raw)) } .to_str() .unwrap() } @@ -59,8 +58,8 @@ impl Language { } } -impl std::fmt::Debug for Language { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Debug for Language { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { fmt.write_str(self.to_string()) } } diff --git a/harfbuzz/src/lib.rs b/harfbuzz/src/lib.rs index 86c18b36..db2c5b19 100644 --- a/harfbuzz/src/lib.rs +++ b/harfbuzz/src/lib.rs @@ -10,6 +10,7 @@ //! HarfBuzz is a text shaping engine. It solves the problem of selecting //! and positioning glyphs from a font given a Unicode string. +#![no_std] #![warn(missing_docs)] #![deny( trivial_numeric_casts, @@ -18,6 +19,12 @@ unused_qualifications )] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + +#[cfg(feature = "harfbuzz-sys")] pub extern crate harfbuzz_sys as sys; /// An error type for this crate @@ -28,24 +35,35 @@ pub enum HarfBuzzError { } pub use HarfBuzzError as Error; +#[cfg(feature = "harfbuzz-sys")] mod buffer; +#[cfg(feature = "harfbuzz-sys")] pub use self::buffer::Buffer; +#[cfg(feature = "harfbuzz-sys")] mod direction; +#[cfg(feature = "harfbuzz-sys")] pub use self::direction::Direction; +#[cfg(feature = "harfbuzz-sys")] mod language; +#[cfg(feature = "harfbuzz-sys")] pub use self::language::Language; +#[cfg(feature = "harfbuzz-sys")] mod blob; +#[cfg(feature = "harfbuzz-sys")] pub use self::blob::Blob; +mod traits; +pub use self::traits::CombiningClassFunc; +pub use self::traits::ComposeFunc; +pub use self::traits::DecomposeFunc; +pub use self::traits::GeneralCategoryFunc; +pub use self::traits::MirroringFunc; +pub use self::traits::ScriptFunc; + +#[cfg(feature = "harfbuzz-sys")] mod unicode_funcs; -pub use self::unicode_funcs::CombiningClassFunc; -pub use self::unicode_funcs::ComposeFunc; -pub use self::unicode_funcs::DecomposeFunc; -pub use self::unicode_funcs::GeneralCategoryFunc; -pub use self::unicode_funcs::MirroringFunc; -pub use self::unicode_funcs::ScriptFunc; -pub use self::unicode_funcs::UnicodeFuncs; -pub use self::unicode_funcs::UnicodeFuncsBuilder; +#[cfg(feature = "harfbuzz-sys")] +pub use self::unicode_funcs::{UnicodeFuncs, UnicodeFuncsBuilder}; diff --git a/harfbuzz/src/traits.rs b/harfbuzz/src/traits.rs new file mode 100644 index 00000000..882e332c --- /dev/null +++ b/harfbuzz/src/traits.rs @@ -0,0 +1,46 @@ +// Copyright 2023 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +/// An object to map from code points to general category properties. +pub trait GeneralCategoryFunc { + /// Given a code point, return the general category as a + /// [`hb_unicode_general_category_t`]. + fn general_category(&self, ch: u32) -> core::ffi::c_uint; +} + +/// An object to map from code points to combining classes. +pub trait CombiningClassFunc { + /// Given a code point, return the combining class as a + /// [`hb_unicode_combining_class_t`]. + fn combining_class(&self, ch: u32) -> core::ffi::c_uint; +} + +/// An object to map from code points to mirrored code points. +pub trait MirroringFunc { + /// Given a code point, return the mirrored code point. + fn mirroring(&self, ch: u32) -> u32; +} + +/// An object to map from code points to script names. +pub trait ScriptFunc { + /// Given a code point, return the script as a 4-byte script name. + fn script(&self, ch: u32) -> [u8; 4]; +} + +/// An object to compose two characters. +pub trait ComposeFunc { + /// Given two code points, return the composed code point. + fn compose(&self, a: u32, b: u32) -> Option; +} + +/// An object to decompose a character. +pub trait DecomposeFunc { + /// Given a code point, return the two decomposed code points. + fn decompose(&self, ab: u32) -> Option<(u32, u32)>; +} diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index 31751763..cbb71723 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -7,47 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. -use crate::sys::*; +use crate::traits::*; use crate::Error; -use std::ffi::c_void; - -/// An object to map from code points to general category properties. -pub trait GeneralCategoryFunc { - /// Given a code point, return the general category as a - /// [`hb_unicode_general_category_t`]. - fn general_category(&self, ch: u32) -> hb_unicode_general_category_t; -} - -/// An object to map from code points to combining classes. -pub trait CombiningClassFunc { - /// Given a code point, return the combining class as a - /// [`hb_unicode_combining_class_t`]. - fn combining_class(&self, ch: u32) -> hb_unicode_combining_class_t; -} - -/// An object to map from code points to mirrored code points. -pub trait MirroringFunc { - /// Given a code point, return the mirrored code point. - fn mirroring(&self, ch: u32) -> u32; -} - -/// An object to map from code points to script names. -pub trait ScriptFunc { - /// Given a code point, return the script as a 4-byte script name. - fn script(&self, ch: u32) -> [u8; 4]; -} - -/// An object to compose two characters. -pub trait ComposeFunc { - /// Given two code points, return the composed code point. - fn compose(&self, a: u32, b: u32) -> Option; -} - -/// An object to decompose a character. -pub trait DecomposeFunc { - /// Given a code point, return the two decomposed code points. - fn decompose(&self, ab: u32) -> Option<(u32, u32)>; -} +use alloc::boxed::Box; +use core::ffi::c_void; +use sys::*; /// A builder for [`UnicodeFuncs`]. /// From 4f3392b3f5c714bba75f95524e7611a451eefc70 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Tue, 1 Aug 2023 16:46:54 -0700 Subject: [PATCH 05/22] Fix docs and tests --- harfbuzz/src/unicode_funcs.rs | 67 +++++++++++++++++++++++++++++++---- 1 file changed, 61 insertions(+), 6 deletions(-) diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index cbb71723..ca618f84 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -15,7 +15,9 @@ use sys::*; /// A builder for [`UnicodeFuncs`]. /// -/// If one or more of the functions is not provided, set its type parameter to `()`. +/// Not all of the functions need to be provided. If a function is missing, +/// the one from the parent will be called, either empty (returning invalid +/// placeholder data) or default (using the built-in Harfbuzz properties). #[non_exhaustive] #[derive(Debug)] pub struct UnicodeFuncsBuilder { @@ -254,18 +256,56 @@ impl Drop for UnicodeFuncsBuilder { /// /// # Example /// +/// Implementing a custom properties provider for HarfBuzz: +/// /// ``` /// # use harfbuzz::{Buffer, Direction, UnicodeFuncsBuilder, sys}; -/// struct GeneralCategoryCalculator; +/// struct PropertyProvider; +/// +/// impl harfbuzz::GeneralCategoryFunc for PropertyProvider { +/// fn general_category(&self, ch: u32) -> core::ffi::c_uint { +/// todo!("GeneralCategoryFunc") +/// } +/// } +/// +/// impl harfbuzz::CombiningClassFunc for PropertyProvider { +/// fn combining_class(&self, ch: u32) -> core::ffi::c_uint { +/// todo!("CombiningClassFunc") +/// } +/// } +/// +/// impl harfbuzz::MirroringFunc for PropertyProvider { +/// fn mirroring(&self, ch: u32) -> u32 { +/// todo!("MirroringFunc") +/// } +/// } +/// +/// impl harfbuzz::ScriptFunc for PropertyProvider { +/// fn script(&self, ch: u32) -> [u8; 4] { +/// debug_assert!(ch >= 0x0600 && ch <= 0x06FF); // Arab code points +/// *b"Arab" +/// } +/// } +/// +/// impl harfbuzz::ComposeFunc for PropertyProvider { +/// fn compose(&self, a: u32, b:u32) -> Option { +/// todo!("ComposeFunc") +/// } +/// } /// -/// impl harfbuzz::GeneralCategoryFunc for GeneralCategoryCalculator { -/// fn general_category(&self, ch: u32) -> harfbuzz::sys::hb_unicode_general_category_t { -/// todo!() +/// impl harfbuzz::DecomposeFunc for PropertyProvider { +/// fn decompose(&self, ab: u32) -> Option<(u32, u32)> { +/// todo!("DecomposeFunc") /// } /// } /// /// let mut unicode_funcs = UnicodeFuncsBuilder::new_with_empty_parent().unwrap(); -/// unicode_funcs.set_general_category_func(Box::new(GeneralCategoryCalculator)); +/// unicode_funcs.set_general_category_func(Box::new(PropertyProvider)); +/// unicode_funcs.set_combining_class_func(Box::new(PropertyProvider)); +/// unicode_funcs.set_mirroring_func(Box::new(PropertyProvider)); +/// unicode_funcs.set_script_func(Box::new(PropertyProvider)); +/// unicode_funcs.set_compose_func(Box::new(PropertyProvider)); +/// unicode_funcs.set_decompose_func(Box::new(PropertyProvider)); /// let unicode_funcs = unicode_funcs.build(); /// /// let mut b = Buffer::with("مساء الخير"); @@ -274,6 +314,21 @@ impl Drop for UnicodeFuncsBuilder { /// assert_eq!(b.get_direction(), Direction::RTL); /// assert_eq!(b.get_script(), sys::HB_SCRIPT_ARABIC); /// ``` +/// +/// Without the provider, the results are unexpected: +/// +/// ``` +/// # use harfbuzz::{Buffer, Direction, UnicodeFuncsBuilder, sys}; +/// +/// let mut unicode_funcs = UnicodeFuncsBuilder::new_with_empty_parent().unwrap(); +/// let unicode_funcs = unicode_funcs.build(); +/// +/// let mut b = Buffer::with("مساء الخير"); +/// b.set_unicode_funcs(&unicode_funcs); +/// b.guess_segment_properties(); +/// assert_eq!(b.get_direction(), Direction::LTR); // WRONG! +/// assert_eq!(b.get_script(), sys::HB_SCRIPT_INVALID); // WRONG! +/// ``` pub struct UnicodeFuncs { raw: *mut hb_unicode_funcs_t, } From 9cf9066e5a5dfc79a0bfd93e91a86cf3217aa6b1 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 23 Aug 2023 18:25:07 -0700 Subject: [PATCH 06/22] Post-merge fixes --- harfbuzz/src/blob.rs | 2 +- harfbuzz/src/unicode_funcs.rs | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/harfbuzz/src/blob.rs b/harfbuzz/src/blob.rs index 48b91934..ef99ea38 100644 --- a/harfbuzz/src/blob.rs +++ b/harfbuzz/src/blob.rs @@ -8,8 +8,8 @@ // except according to those terms. use crate::sys; -use core::marker::PhantomData; use core::ffi::{c_char, c_uint}; +use core::marker::PhantomData; use core::{mem, ops, ptr, slice}; #[cfg(feature = "std")] diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index ca618f84..b55ff441 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -7,11 +7,11 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +use crate::sys::*; use crate::traits::*; use crate::Error; use alloc::boxed::Box; use core::ffi::c_void; -use sys::*; /// A builder for [`UnicodeFuncs`]. /// From 6868c9751e22706a78c0d0a1f4f3cad701649f59 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 23 Aug 2023 18:36:43 -0700 Subject: [PATCH 07/22] Make GeneralCategory an enum --- harfbuzz/src/lib.rs | 1 + harfbuzz/src/traits.rs | 43 ++++++++++++++++++++++++++++++++--- harfbuzz/src/unicode_funcs.rs | 3 ++- 3 files changed, 43 insertions(+), 4 deletions(-) diff --git a/harfbuzz/src/lib.rs b/harfbuzz/src/lib.rs index 3e9cccad..3a2ace6b 100644 --- a/harfbuzz/src/lib.rs +++ b/harfbuzz/src/lib.rs @@ -69,6 +69,7 @@ mod traits; pub use self::traits::CombiningClassFunc; pub use self::traits::ComposeFunc; pub use self::traits::DecomposeFunc; +pub use self::traits::GeneralCategory; pub use self::traits::GeneralCategoryFunc; pub use self::traits::MirroringFunc; pub use self::traits::ScriptFunc; diff --git a/harfbuzz/src/traits.rs b/harfbuzz/src/traits.rs index 882e332c..f2a71be3 100644 --- a/harfbuzz/src/traits.rs +++ b/harfbuzz/src/traits.rs @@ -7,11 +7,48 @@ // option. This file may not be copied, modified, or distributed // except according to those terms. +/// A general category value. Equivalent to [`hb_unicode_general_category_t`]. +#[repr(u8)] +#[derive(Debug, Copy, Clone, PartialEq, Eq)] +#[allow(non_camel_case_types)] // the names are defined by Unicode +#[allow(missing_docs)] // the categories are defined by Unicode +pub enum GeneralCategory { + Control = 0, + Format = 1, + Unassigned = 2, + Private_use = 3, + Surrogate = 4, + Lowercase_Letter = 5, + Modifier_Letter = 6, + Other_Letter = 7, + Titlecase_Letter = 8, + Uppercase_Letter = 9, + Spacing_Mark = 10, + Enclosing_Mark = 11, + Non_Spacing_Mark = 12, + Decimal_Number = 13, + Letter_Number = 14, + Other_Number = 15, + Connect_Punctuation = 16, + Dash_Punctuation = 17, + Close_Punctuation = 18, + Final_Punctuation = 19, + Initial_Punctuation = 20, + Other_Punctuation = 21, + Open_Punctuation = 22, + Currency_Symbol = 23, + Modifier_Symbol = 24, + Math_Symbol = 25, + Other_Symbol = 26, + Line_Separator = 27, + Paragraph_Separator = 28, + Space_Separator = 29, +} + /// An object to map from code points to general category properties. pub trait GeneralCategoryFunc { - /// Given a code point, return the general category as a - /// [`hb_unicode_general_category_t`]. - fn general_category(&self, ch: u32) -> core::ffi::c_uint; + /// Given a code point, return the general category as a [`GeneralCategory`]. + fn general_category(&self, ch: u32) -> GeneralCategory; } /// An object to map from code points to combining classes. diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index b55ff441..692bf2e8 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -60,6 +60,7 @@ impl UnicodeFuncsBuilder { user_data: *mut c_void, ) -> hb_unicode_general_category_t { unsafe { &*(user_data as *mut F) }.general_category(unicode) + as hb_unicode_general_category_t } extern "C" fn destroy_general_category(user_data: *mut c_void) { let _ = unsafe { Box::from_raw(user_data as *mut F) }; @@ -263,7 +264,7 @@ impl Drop for UnicodeFuncsBuilder { /// struct PropertyProvider; /// /// impl harfbuzz::GeneralCategoryFunc for PropertyProvider { -/// fn general_category(&self, ch: u32) -> core::ffi::c_uint { +/// fn general_category(&self, ch: u32) -> harfbuzz::GeneralCategory { /// todo!("GeneralCategoryFunc") /// } /// } From 39af9196351f3eaff25d93d34ff8dd6466db56be Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 23 Aug 2023 18:40:40 -0700 Subject: [PATCH 08/22] Change CombiningClassFunc to return a u8 --- harfbuzz/src/traits.rs | 8 +++++--- harfbuzz/src/unicode_funcs.rs | 3 ++- 2 files changed, 7 insertions(+), 4 deletions(-) diff --git a/harfbuzz/src/traits.rs b/harfbuzz/src/traits.rs index f2a71be3..c728610b 100644 --- a/harfbuzz/src/traits.rs +++ b/harfbuzz/src/traits.rs @@ -53,9 +53,11 @@ pub trait GeneralCategoryFunc { /// An object to map from code points to combining classes. pub trait CombiningClassFunc { - /// Given a code point, return the combining class as a - /// [`hb_unicode_combining_class_t`]. - fn combining_class(&self, ch: u32) -> core::ffi::c_uint; + /// Given a code point, return the combining class as a `u8` corresponding to a + /// [`hb_unicode_combining_class_t`]. Note that the + /// [Unicode stability policy](https://www.unicode.org/policies/stability_policy.html) + /// guarantees that Canonical Combining Class numeric values fit in a `u8`. + fn combining_class(&self, ch: u32) -> u8; } /// An object to map from code points to mirrored code points. diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index 692bf2e8..86347cb1 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -84,6 +84,7 @@ impl UnicodeFuncsBuilder { user_data: *mut c_void, ) -> hb_unicode_combining_class_t { unsafe { &*(user_data as *mut F) }.combining_class(unicode) + as hb_unicode_combining_class_t } extern "C" fn destroy_combining_class(user_data: *mut c_void) { let _ = unsafe { Box::from_raw(user_data as *mut F) }; @@ -270,7 +271,7 @@ impl Drop for UnicodeFuncsBuilder { /// } /// /// impl harfbuzz::CombiningClassFunc for PropertyProvider { -/// fn combining_class(&self, ch: u32) -> core::ffi::c_uint { +/// fn combining_class(&self, ch: u32) -> u8 { /// todo!("CombiningClassFunc") /// } /// } From ea3a6d3a3eef885aaea0fba58aa7c335270409f8 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 23 Aug 2023 18:43:10 -0700 Subject: [PATCH 09/22] Fix docs links --- harfbuzz/src/traits.rs | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/harfbuzz/src/traits.rs b/harfbuzz/src/traits.rs index c728610b..6407c9ca 100644 --- a/harfbuzz/src/traits.rs +++ b/harfbuzz/src/traits.rs @@ -8,6 +8,8 @@ // except according to those terms. /// A general category value. Equivalent to [`hb_unicode_general_category_t`]. +/// +/// [`hb_unicode_general_category_t`]: crate::sys::hb_unicode_general_category_t #[repr(u8)] #[derive(Debug, Copy, Clone, PartialEq, Eq)] #[allow(non_camel_case_types)] // the names are defined by Unicode @@ -57,6 +59,8 @@ pub trait CombiningClassFunc { /// [`hb_unicode_combining_class_t`]. Note that the /// [Unicode stability policy](https://www.unicode.org/policies/stability_policy.html) /// guarantees that Canonical Combining Class numeric values fit in a `u8`. + /// + /// [`hb_unicode_combining_class_t`]: crate::sys::hb_unicode_combining_class_t fn combining_class(&self, ch: u32) -> u8; } From 5b8a4aaafcb8b18bc590443545dac2ac393e7643 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 23 Aug 2023 18:49:53 -0700 Subject: [PATCH 10/22] Use `char` instead of `u32` for hb_codepoint_t in traits --- harfbuzz/src/traits.rs | 12 +++++------ harfbuzz/src/unicode_funcs.rs | 40 +++++++++++++++++++++-------------- 2 files changed, 30 insertions(+), 22 deletions(-) diff --git a/harfbuzz/src/traits.rs b/harfbuzz/src/traits.rs index 6407c9ca..e8442bdd 100644 --- a/harfbuzz/src/traits.rs +++ b/harfbuzz/src/traits.rs @@ -50,7 +50,7 @@ pub enum GeneralCategory { /// An object to map from code points to general category properties. pub trait GeneralCategoryFunc { /// Given a code point, return the general category as a [`GeneralCategory`]. - fn general_category(&self, ch: u32) -> GeneralCategory; + fn general_category(&self, ch: char) -> GeneralCategory; } /// An object to map from code points to combining classes. @@ -61,29 +61,29 @@ pub trait CombiningClassFunc { /// guarantees that Canonical Combining Class numeric values fit in a `u8`. /// /// [`hb_unicode_combining_class_t`]: crate::sys::hb_unicode_combining_class_t - fn combining_class(&self, ch: u32) -> u8; + fn combining_class(&self, ch: char) -> u8; } /// An object to map from code points to mirrored code points. pub trait MirroringFunc { /// Given a code point, return the mirrored code point. - fn mirroring(&self, ch: u32) -> u32; + fn mirroring(&self, ch: char) -> char; } /// An object to map from code points to script names. pub trait ScriptFunc { /// Given a code point, return the script as a 4-byte script name. - fn script(&self, ch: u32) -> [u8; 4]; + fn script(&self, ch: char) -> [u8; 4]; } /// An object to compose two characters. pub trait ComposeFunc { /// Given two code points, return the composed code point. - fn compose(&self, a: u32, b: u32) -> Option; + fn compose(&self, a: char, b: char) -> Option; } /// An object to decompose a character. pub trait DecomposeFunc { /// Given a code point, return the two decomposed code points. - fn decompose(&self, ab: u32) -> Option<(u32, u32)>; + fn decompose(&self, ab: char) -> Option<(char, char)>; } diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index 86347cb1..6b6a4b24 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -13,6 +13,12 @@ use crate::Error; use alloc::boxed::Box; use core::ffi::c_void; +/// Converts from `hb_codepoint_t`, assumed to be valid, to `char`. +#[inline] +fn hb_codepoint_t_to_char(input: hb_codepoint_t) -> char { + unsafe { char::from_u32_unchecked(input) } +} + /// A builder for [`UnicodeFuncs`]. /// /// Not all of the functions need to be provided. If a function is missing, @@ -59,7 +65,7 @@ impl UnicodeFuncsBuilder { unicode: hb_codepoint_t, user_data: *mut c_void, ) -> hb_unicode_general_category_t { - unsafe { &*(user_data as *mut F) }.general_category(unicode) + unsafe { &*(user_data as *mut F) }.general_category(hb_codepoint_t_to_char(unicode)) as hb_unicode_general_category_t } extern "C" fn destroy_general_category(user_data: *mut c_void) { @@ -83,7 +89,7 @@ impl UnicodeFuncsBuilder { unicode: hb_codepoint_t, user_data: *mut c_void, ) -> hb_unicode_combining_class_t { - unsafe { &*(user_data as *mut F) }.combining_class(unicode) + unsafe { &*(user_data as *mut F) }.combining_class(hb_codepoint_t_to_char(unicode)) as hb_unicode_combining_class_t } extern "C" fn destroy_combining_class(user_data: *mut c_void) { @@ -107,7 +113,8 @@ impl UnicodeFuncsBuilder { unicode: hb_codepoint_t, user_data: *mut c_void, ) -> hb_codepoint_t { - unsafe { &*(user_data as *mut F) }.mirroring(unicode) + unsafe { &*(user_data as *mut F) }.mirroring(hb_codepoint_t_to_char(unicode)) + as hb_codepoint_t } extern "C" fn destroy_mirroring(user_data: *mut c_void) { let _ = unsafe { Box::from_raw(user_data as *mut F) }; @@ -130,7 +137,7 @@ impl UnicodeFuncsBuilder { unicode: hb_codepoint_t, user_data: *mut c_void, ) -> hb_codepoint_t { - let code = unsafe { &*(user_data as *mut F) }.script(unicode); + let code = unsafe { &*(user_data as *mut F) }.script(hb_codepoint_t_to_char(unicode)); unsafe { hb_script_from_string(code.as_ptr() as *const i8, 4) } } extern "C" fn destroy_script(user_data: *mut c_void) { @@ -156,10 +163,11 @@ impl UnicodeFuncsBuilder { ab: *mut hb_codepoint_t, user_data: *mut c_void, ) -> hb_bool_t { - let result = unsafe { &*(user_data as *mut F) }.compose(a, b); + let result = unsafe { &*(user_data as *mut F) } + .compose(hb_codepoint_t_to_char(a), hb_codepoint_t_to_char(b)); match result { Some(ab_x) => { - unsafe { *ab = ab_x }; + unsafe { *ab = ab_x as hb_codepoint_t }; true as hb_bool_t } None => false as hb_bool_t, @@ -188,11 +196,11 @@ impl UnicodeFuncsBuilder { b: *mut hb_codepoint_t, user_data: *mut c_void, ) -> hb_bool_t { - let result = unsafe { &*(user_data as *mut F) }.decompose(ab); + let result = unsafe { &*(user_data as *mut F) }.decompose(hb_codepoint_t_to_char(ab)); match result { Some((a_x, b_x)) => { - unsafe { *a = a_x }; - unsafe { *b = b_x }; + unsafe { *a = a_x as hb_codepoint_t }; + unsafe { *b = b_x as hb_codepoint_t }; true as hb_bool_t } None => false as hb_bool_t, @@ -265,38 +273,38 @@ impl Drop for UnicodeFuncsBuilder { /// struct PropertyProvider; /// /// impl harfbuzz::GeneralCategoryFunc for PropertyProvider { -/// fn general_category(&self, ch: u32) -> harfbuzz::GeneralCategory { +/// fn general_category(&self, ch: char) -> harfbuzz::GeneralCategory { /// todo!("GeneralCategoryFunc") /// } /// } /// /// impl harfbuzz::CombiningClassFunc for PropertyProvider { -/// fn combining_class(&self, ch: u32) -> u8 { +/// fn combining_class(&self, ch: char) -> u8 { /// todo!("CombiningClassFunc") /// } /// } /// /// impl harfbuzz::MirroringFunc for PropertyProvider { -/// fn mirroring(&self, ch: u32) -> u32 { +/// fn mirroring(&self, ch: char) -> char { /// todo!("MirroringFunc") /// } /// } /// /// impl harfbuzz::ScriptFunc for PropertyProvider { -/// fn script(&self, ch: u32) -> [u8; 4] { -/// debug_assert!(ch >= 0x0600 && ch <= 0x06FF); // Arab code points +/// fn script(&self, ch: char) -> [u8; 4] { +/// debug_assert!(ch as u32 >= 0x0600 && ch as u32 <= 0x06FF); // Arab code points /// *b"Arab" /// } /// } /// /// impl harfbuzz::ComposeFunc for PropertyProvider { -/// fn compose(&self, a: u32, b:u32) -> Option { +/// fn compose(&self, a: char, b:char) -> Option { /// todo!("ComposeFunc") /// } /// } /// /// impl harfbuzz::DecomposeFunc for PropertyProvider { -/// fn decompose(&self, ab: u32) -> Option<(u32, u32)> { +/// fn decompose(&self, ab: char) -> Option<(char, char)> { /// todo!("DecomposeFunc") /// } /// } From 62e8b30de4e74fdf749260f5c6c5ca15745717c1 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Thu, 24 Aug 2023 17:22:47 -0700 Subject: [PATCH 11/22] Add std feature to harfbuzz --- .github/workflows/main.yml | 5 +++++ harfbuzz/Cargo.toml | 3 ++- harfbuzz/src/blob.rs | 13 +++++++++---- harfbuzz/src/buffer.rs | 16 ++++++++-------- harfbuzz/src/language.rs | 10 +++++----- harfbuzz/src/lib.rs | 7 +++++++ 6 files changed, 36 insertions(+), 18 deletions(-) diff --git a/.github/workflows/main.yml b/.github/workflows/main.yml index 57fc79f2..4d50b206 100644 --- a/.github/workflows/main.yml +++ b/.github/workflows/main.yml @@ -32,6 +32,11 @@ jobs: env: RUST_BACKTRACE: 1 + - name: Cargo check no-default-features + run: cargo check --no-default-features + env: + RUST_BACKTRACE: 1 + linux-ci-static: name: stable, Linux, static linking, no pkg-config runs-on: ubuntu-latest diff --git a/harfbuzz/Cargo.toml b/harfbuzz/Cargo.toml index 6e9470a0..ef52c17d 100644 --- a/harfbuzz/Cargo.toml +++ b/harfbuzz/Cargo.toml @@ -19,8 +19,9 @@ version = "0.5.0" default-features = false [features] -default = ["coretext", "directwrite", "freetype"] +default = ["coretext", "directwrite", "freetype", "std"] bundled = ["harfbuzz-sys/bundled"] coretext = ["harfbuzz-sys/coretext"] directwrite = ["harfbuzz-sys/directwrite"] freetype = ["harfbuzz-sys/freetype"] +std = [] diff --git a/harfbuzz/src/blob.rs b/harfbuzz/src/blob.rs index b8e6faf2..655320dc 100644 --- a/harfbuzz/src/blob.rs +++ b/harfbuzz/src/blob.rs @@ -8,10 +8,12 @@ // except according to those terms. use crate::sys; -use std::marker::PhantomData; -use std::os::raw::{c_char, c_uint, c_void}; -use std::sync::Arc; -use std::{mem, ops, ptr, slice}; +use core::ffi::{c_char, c_uint}; +use core::marker::PhantomData; +use core::{mem, ops, ptr, slice}; + +#[cfg(feature = "std")] +use std::{ffi::c_void, sync::Arc, vec::Vec}; /// Blobs wrap a chunk of binary data to handle lifecycle management of data /// while it is passed between client and HarfBuzz. @@ -55,6 +57,8 @@ impl<'a> Blob<'a> { /// data may be shared by Rust code and the blob. The `Vec` is freed /// when all references are dropped. /// + /// ✨ *Enabled with the `std` Cargo feature.* + /// /// ``` /// # use std::sync::Arc; /// # use harfbuzz::Blob; @@ -63,6 +67,7 @@ impl<'a> Blob<'a> { /// assert_eq!(blob.len(), 256); /// assert!(!blob.is_empty()); /// ``` + #[cfg(feature = "std")] pub fn new_from_arc_vec(data: Arc>) -> Blob<'static> { let len = data.len(); assert!(len <= c_uint::max_value() as usize); diff --git a/harfbuzz/src/buffer.rs b/harfbuzz/src/buffer.rs index 21c81e4b..6d893c11 100644 --- a/harfbuzz/src/buffer.rs +++ b/harfbuzz/src/buffer.rs @@ -99,7 +99,7 @@ impl Buffer { /// Gives up ownership and returns a raw pointer to the buffer. pub fn into_raw(self) -> *mut sys::hb_buffer_t { let raw = self.raw; - std::mem::forget(self); + core::mem::forget(self); raw } @@ -122,10 +122,10 @@ impl Buffer { unsafe { sys::hb_buffer_add_utf8( self.raw, - text.as_ptr() as *const std::os::raw::c_char, - text.len() as std::os::raw::c_int, + text.as_ptr() as *const core::ffi::c_char, + text.len() as core::ffi::c_int, 0, - text.len() as std::os::raw::c_int, + text.len() as core::ffi::c_int, ) }; } @@ -144,8 +144,8 @@ impl Buffer { sys::hb_buffer_append( self.raw, other.raw, - start as std::os::raw::c_uint, - end as std::os::raw::c_uint, + start as core::ffi::c_uint, + end as core::ffi::c_uint, ) }; } @@ -297,8 +297,8 @@ impl Buffer { } } -impl std::fmt::Debug for Buffer { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Debug for Buffer { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { fmt.debug_struct("Buffer") .field("direction", &self.get_direction()) .field("script", &self.get_script()) diff --git a/harfbuzz/src/language.rs b/harfbuzz/src/language.rs index 85456dce..4d6da60b 100644 --- a/harfbuzz/src/language.rs +++ b/harfbuzz/src/language.rs @@ -26,15 +26,15 @@ impl Language { Language { raw: unsafe { sys::hb_language_from_string( - lang.as_ptr() as *const std::os::raw::c_char, - lang.len() as std::os::raw::c_int, + lang.as_ptr() as *const core::ffi::c_char, + lang.len() as core::ffi::c_int, ) }, } } pub fn to_string(&self) -> &str { - unsafe { std::ffi::CStr::from_ptr(sys::hb_language_to_string(self.raw)) } + unsafe { core::ffi::CStr::from_ptr(sys::hb_language_to_string(self.raw)) } .to_str() .unwrap() } @@ -63,8 +63,8 @@ impl Language { } } -impl std::fmt::Debug for Language { - fn fmt(&self, fmt: &mut std::fmt::Formatter) -> std::fmt::Result { +impl core::fmt::Debug for Language { + fn fmt(&self, fmt: &mut core::fmt::Formatter) -> core::fmt::Result { fmt.write_str(self.to_string()) } } diff --git a/harfbuzz/src/lib.rs b/harfbuzz/src/lib.rs index 19645988..45285546 100644 --- a/harfbuzz/src/lib.rs +++ b/harfbuzz/src/lib.rs @@ -15,9 +15,11 @@ //! - `freetype` - Enables bindings to the FreeType font engine. (Enabled by default.) //! - `coretext` - Enables bindings to the CoreText font engine. (Apple platforms only) (Enabled by default.) //! - `directwrite` - Enables bindings to the DirectWrite font engine. (Windows only) (Enabled by default.) +//! - `std` - Enable certain functions that require the standard library. (Enabled by default.) //! //! - `bundled` - Use the bundled copy of the harfbuzz library rather than one installed on the system. +#![no_std] #![warn(missing_docs)] #![deny( trivial_numeric_casts, @@ -26,6 +28,11 @@ unused_qualifications )] +extern crate alloc; + +#[cfg(feature = "std")] +extern crate std; + pub use harfbuzz_sys as sys; mod buffer; From e66b4c4ac9598dc03ad9f98bbd9e1fffbb8000aa Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Thu, 24 Aug 2023 17:23:25 -0700 Subject: [PATCH 12/22] Mark harfbuzz-sys as no_std. --- harfbuzz-sys/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/harfbuzz-sys/src/lib.rs b/harfbuzz-sys/src/lib.rs index 0a6aa6ec..21dec8df 100644 --- a/harfbuzz-sys/src/lib.rs +++ b/harfbuzz-sys/src/lib.rs @@ -20,6 +20,8 @@ //! //! - `bundled` - Use the bundled copy of the harfbuzz library rather than one installed on the system. +#![no_std] + #[cfg(all(target_vendor = "apple", feature = "coretext"))] pub mod coretext; From 0509b8b3964c681ed2dc807d19d1742d30713f3f Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Mon, 28 Aug 2023 14:16:01 -0700 Subject: [PATCH 13/22] Move to separate crate --- Cargo.toml | 2 +- harfbuzz-traits/Cargo.toml | 16 ++ harfbuzz-traits/LICENSE-APACHE | 201 ++++++++++++++++++ harfbuzz-traits/LICENSE-MIT | 25 +++ harfbuzz-traits/README.md | 35 +++ harfbuzz-traits/src/lib.rs | 17 ++ .../src/unicode_funcs_traits.rs | 0 harfbuzz/Cargo.toml | 5 + harfbuzz/src/unicode_funcs.rs | 2 +- 9 files changed, 301 insertions(+), 2 deletions(-) create mode 100644 harfbuzz-traits/Cargo.toml create mode 100644 harfbuzz-traits/LICENSE-APACHE create mode 100644 harfbuzz-traits/LICENSE-MIT create mode 100644 harfbuzz-traits/README.md create mode 100644 harfbuzz-traits/src/lib.rs rename harfbuzz/src/traits.rs => harfbuzz-traits/src/unicode_funcs_traits.rs (100%) diff --git a/Cargo.toml b/Cargo.toml index 21ecd9b6..ea649977 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,3 +1,3 @@ [workspace] resolver = "2" -members = ["harfbuzz", "harfbuzz-sys"] +members = ["harfbuzz", "harfbuzz-sys", "harfbuzz-traits"] diff --git a/harfbuzz-traits/Cargo.toml b/harfbuzz-traits/Cargo.toml new file mode 100644 index 00000000..f7d996a9 --- /dev/null +++ b/harfbuzz-traits/Cargo.toml @@ -0,0 +1,16 @@ +[package] +name = "harfbuzz-traits" +version = "0.1.0" +edition = "2021" + +authors = ["The Servo Project Developers"] +license = "MIT OR Apache-2.0" +readme = "README.md" + +description = "Rust Traits for the HarfBuzz text shaping engine" +repository = "https://github.com/servo/rust-harfbuzz" +documentation = "https://docs.rs/harfbuzz/" +keywords = ["opentype", "font", "text", "layout", "unicode", "shaping"] +categories = ["text-processing"] + +[features] diff --git a/harfbuzz-traits/LICENSE-APACHE b/harfbuzz-traits/LICENSE-APACHE new file mode 100644 index 00000000..16fe87b0 --- /dev/null +++ b/harfbuzz-traits/LICENSE-APACHE @@ -0,0 +1,201 @@ + Apache License + Version 2.0, January 2004 + http://www.apache.org/licenses/ + +TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION + +1. Definitions. + + "License" shall mean the terms and conditions for use, reproduction, + and distribution as defined by Sections 1 through 9 of this document. + + "Licensor" shall mean the copyright owner or entity authorized by + the copyright owner that is granting the License. + + "Legal Entity" shall mean the union of the acting entity and all + other entities that control, are controlled by, or are under common + control with that entity. For the purposes of this definition, + "control" means (i) the power, direct or indirect, to cause the + direction or management of such entity, whether by contract or + otherwise, or (ii) ownership of fifty percent (50%) or more of the + outstanding shares, or (iii) beneficial ownership of such entity. + + "You" (or "Your") shall mean an individual or Legal Entity + exercising permissions granted by this License. + + "Source" form shall mean the preferred form for making modifications, + including but not limited to software source code, documentation + source, and configuration files. + + "Object" form shall mean any form resulting from mechanical + transformation or translation of a Source form, including but + not limited to compiled object code, generated documentation, + and conversions to other media types. + + "Work" shall mean the work of authorship, whether in Source or + Object form, made available under the License, as indicated by a + copyright notice that is included in or attached to the work + (an example is provided in the Appendix below). + + "Derivative Works" shall mean any work, whether in Source or Object + form, that is based on (or derived from) the Work and for which the + editorial revisions, annotations, elaborations, or other modifications + represent, as a whole, an original work of authorship. For the purposes + of this License, Derivative Works shall not include works that remain + separable from, or merely link (or bind by name) to the interfaces of, + the Work and Derivative Works thereof. + + "Contribution" shall mean any work of authorship, including + the original version of the Work and any modifications or additions + to that Work or Derivative Works thereof, that is intentionally + submitted to Licensor for inclusion in the Work by the copyright owner + or by an individual or Legal Entity authorized to submit on behalf of + the copyright owner. For the purposes of this definition, "submitted" + means any form of electronic, verbal, or written communication sent + to the Licensor or its representatives, including but not limited to + communication on electronic mailing lists, source code control systems, + and issue tracking systems that are managed by, or on behalf of, the + Licensor for the purpose of discussing and improving the Work, but + excluding communication that is conspicuously marked or otherwise + designated in writing by the copyright owner as "Not a Contribution." + + "Contributor" shall mean Licensor and any individual or Legal Entity + on behalf of whom a Contribution has been received by Licensor and + subsequently incorporated within the Work. + +2. Grant of Copyright License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + copyright license to reproduce, prepare Derivative Works of, + publicly display, publicly perform, sublicense, and distribute the + Work and such Derivative Works in Source or Object form. + +3. Grant of Patent License. Subject to the terms and conditions of + this License, each Contributor hereby grants to You a perpetual, + worldwide, non-exclusive, no-charge, royalty-free, irrevocable + (except as stated in this section) patent license to make, have made, + use, offer to sell, sell, import, and otherwise transfer the Work, + where such license applies only to those patent claims licensable + by such Contributor that are necessarily infringed by their + Contribution(s) alone or by combination of their Contribution(s) + with the Work to which such Contribution(s) was submitted. If You + institute patent litigation against any entity (including a + cross-claim or counterclaim in a lawsuit) alleging that the Work + or a Contribution incorporated within the Work constitutes direct + or contributory patent infringement, then any patent licenses + granted to You under this License for that Work shall terminate + as of the date such litigation is filed. + +4. Redistribution. You may reproduce and distribute copies of the + Work or Derivative Works thereof in any medium, with or without + modifications, and in Source or Object form, provided that You + meet the following conditions: + + (a) You must give any other recipients of the Work or + Derivative Works a copy of this License; and + + (b) You must cause any modified files to carry prominent notices + stating that You changed the files; and + + (c) You must retain, in the Source form of any Derivative Works + that You distribute, all copyright, patent, trademark, and + attribution notices from the Source form of the Work, + excluding those notices that do not pertain to any part of + the Derivative Works; and + + (d) If the Work includes a "NOTICE" text file as part of its + distribution, then any Derivative Works that You distribute must + include a readable copy of the attribution notices contained + within such NOTICE file, excluding those notices that do not + pertain to any part of the Derivative Works, in at least one + of the following places: within a NOTICE text file distributed + as part of the Derivative Works; within the Source form or + documentation, if provided along with the Derivative Works; or, + within a display generated by the Derivative Works, if and + wherever such third-party notices normally appear. The contents + of the NOTICE file are for informational purposes only and + do not modify the License. You may add Your own attribution + notices within Derivative Works that You distribute, alongside + or as an addendum to the NOTICE text from the Work, provided + that such additional attribution notices cannot be construed + as modifying the License. + + You may add Your own copyright statement to Your modifications and + may provide additional or different license terms and conditions + for use, reproduction, or distribution of Your modifications, or + for any such Derivative Works as a whole, provided Your use, + reproduction, and distribution of the Work otherwise complies with + the conditions stated in this License. + +5. Submission of Contributions. Unless You explicitly state otherwise, + any Contribution intentionally submitted for inclusion in the Work + by You to the Licensor shall be under the terms and conditions of + this License, without any additional terms or conditions. + Notwithstanding the above, nothing herein shall supersede or modify + the terms of any separate license agreement you may have executed + with Licensor regarding such Contributions. + +6. Trademarks. This License does not grant permission to use the trade + names, trademarks, service marks, or product names of the Licensor, + except as required for reasonable and customary use in describing the + origin of the Work and reproducing the content of the NOTICE file. + +7. Disclaimer of Warranty. Unless required by applicable law or + agreed to in writing, Licensor provides the Work (and each + Contributor provides its Contributions) on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or + implied, including, without limitation, any warranties or conditions + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A + PARTICULAR PURPOSE. You are solely responsible for determining the + appropriateness of using or redistributing the Work and assume any + risks associated with Your exercise of permissions under this License. + +8. Limitation of Liability. In no event and under no legal theory, + whether in tort (including negligence), contract, or otherwise, + unless required by applicable law (such as deliberate and grossly + negligent acts) or agreed to in writing, shall any Contributor be + liable to You for damages, including any direct, indirect, special, + incidental, or consequential damages of any character arising as a + result of this License or out of the use or inability to use the + Work (including but not limited to damages for loss of goodwill, + work stoppage, computer failure or malfunction, or any and all + other commercial damages or losses), even if such Contributor + has been advised of the possibility of such damages. + +9. Accepting Warranty or Additional Liability. While redistributing + the Work or Derivative Works thereof, You may choose to offer, + and charge a fee for, acceptance of support, warranty, indemnity, + or other liability obligations and/or rights consistent with this + License. However, in accepting such obligations, You may act only + on Your own behalf and on Your sole responsibility, not on behalf + of any other Contributor, and only if You agree to indemnify, + defend, and hold each Contributor harmless for any liability + incurred by, or claims asserted against, such Contributor by reason + of your accepting any such warranty or additional liability. + +END OF TERMS AND CONDITIONS + +APPENDIX: How to apply the Apache License to your work. + + To apply the Apache License to your work, attach the following + boilerplate notice, with the fields enclosed by brackets "[]" + replaced with your own identifying information. (Don't include + the brackets!) The text should be enclosed in the appropriate + comment syntax for the file format. We also recommend that a + file or class name and description of purpose be included on the + same "printed page" as the copyright notice for easier + identification within third-party archives. + +Copyright [yyyy] [name of copyright owner] + +Licensed under the Apache License, Version 2.0 (the "License"); +you may not use this file except in compliance with the License. +You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + +Unless required by applicable law or agreed to in writing, software +distributed under the License is distributed on an "AS IS" BASIS, +WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. +See the License for the specific language governing permissions and +limitations under the License. diff --git a/harfbuzz-traits/LICENSE-MIT b/harfbuzz-traits/LICENSE-MIT new file mode 100644 index 00000000..807526f5 --- /dev/null +++ b/harfbuzz-traits/LICENSE-MIT @@ -0,0 +1,25 @@ +Copyright (c) 2012-2013 Mozilla Foundation + +Permission is hereby granted, free of charge, to any +person obtaining a copy of this software and associated +documentation files (the "Software"), to deal in the +Software without restriction, including without +limitation the rights to use, copy, modify, merge, +publish, distribute, sublicense, and/or sell copies of +the Software, and to permit persons to whom the Software +is furnished to do so, subject to the following +conditions: + +The above copyright notice and this permission notice +shall be included in all copies or substantial portions +of the Software. + +THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF +ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED +TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A +PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT +SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY +CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION +OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR +IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER +DEALINGS IN THE SOFTWARE. diff --git a/harfbuzz-traits/README.md b/harfbuzz-traits/README.md new file mode 100644 index 00000000..90a5c9f6 --- /dev/null +++ b/harfbuzz-traits/README.md @@ -0,0 +1,35 @@ +
+ +# harfbuzz-traits + +[![Build Status](https://github.com/servo/rust-harfbuzz/actions/workflows/main.yml/badge.svg)](https://github.com/servo/rust-harfbuzz/actions) +[![Crates.io](https://img.shields.io/crates/v/harfbuzz-traits.svg)](https://crates.io/crates/harfbuzz-traits) +[![Docs](https://docs.rs/harfbuzz-traits/badge.svg)](https://docs.rs/harfbuzz-traits) + +
+ +[HarfBuzz](https://harfbuzz.github.io/) is a text shaping engine. It +solves the problem of selecting and positioning glyphs from a font +given a Unicode string. + +This crate provides high-level Rust traits that can be implemented without +depending on HarfBuzz itself. + +## License + +Licensed under either of + +- Apache License, Version 2.0 + ([LICENSE-APACHE](LICENSE-APACHE) or ) +- MIT license + ([LICENSE-MIT](LICENSE-MIT) or ) + +at your option. + +## Contribution + +Contributions are welcome by pull request. + +Unless you explicitly state otherwise, any contribution intentionally submitted +for inclusion in the work by you, as defined in the Apache-2.0 license, shall be +dual licensed as above, without any additional terms or conditions. \ No newline at end of file diff --git a/harfbuzz-traits/src/lib.rs b/harfbuzz-traits/src/lib.rs new file mode 100644 index 00000000..265132f5 --- /dev/null +++ b/harfbuzz-traits/src/lib.rs @@ -0,0 +1,17 @@ +// Copyright 2023 The Servo Project Developers. See the COPYRIGHT +// file at the top-level directory of this distribution. +// +// Licensed under the Apache License, Version 2.0 or the MIT license +// , at your +// option. This file may not be copied, modified, or distributed +// except according to those terms. + +//! # harfbuzz-traits +//! +//! This crate provides traits for the `harfbuzz` crate that can be implememted without +//! depending on [HarfBuzz](https://harfbuzz.github.io/) itself. + +mod unicode_funcs_traits; + +pub use unicode_funcs_traits::*; diff --git a/harfbuzz/src/traits.rs b/harfbuzz-traits/src/unicode_funcs_traits.rs similarity index 100% rename from harfbuzz/src/traits.rs rename to harfbuzz-traits/src/unicode_funcs_traits.rs diff --git a/harfbuzz/Cargo.toml b/harfbuzz/Cargo.toml index cecf1e52..0a9bdfbe 100644 --- a/harfbuzz/Cargo.toml +++ b/harfbuzz/Cargo.toml @@ -19,6 +19,11 @@ version = "0.5.0" default-features = false optional = true +[dependencies.harfbuzz-traits] +path = "../harfbuzz-traits" +version = "0.1.0" +default-features = false + [features] default = ["coretext", "directwrite", "freetype", "harfbuzz-sys", "std"] bundled = ["harfbuzz-sys?/bundled"] diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index 6b6a4b24..ebc3f9bb 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -8,7 +8,7 @@ // except according to those terms. use crate::sys::*; -use crate::traits::*; +use harfbuzz_traits::*; use crate::Error; use alloc::boxed::Box; use core::ffi::c_void; From 19b35fc993950e703d3c6faf3df0a73ab00eab42 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Mon, 28 Aug 2023 14:16:46 -0700 Subject: [PATCH 14/22] Undo sys feature --- harfbuzz/Cargo.toml | 12 +++++------- harfbuzz/src/lib.rs | 11 ----------- 2 files changed, 5 insertions(+), 18 deletions(-) diff --git a/harfbuzz/Cargo.toml b/harfbuzz/Cargo.toml index 0a9bdfbe..e2b9f129 100644 --- a/harfbuzz/Cargo.toml +++ b/harfbuzz/Cargo.toml @@ -17,7 +17,6 @@ categories = ["text-processing"] path = "../harfbuzz-sys" version = "0.5.0" default-features = false -optional = true [dependencies.harfbuzz-traits] path = "../harfbuzz-traits" @@ -25,10 +24,9 @@ version = "0.1.0" default-features = false [features] -default = ["coretext", "directwrite", "freetype", "harfbuzz-sys", "std"] -bundled = ["harfbuzz-sys?/bundled"] -coretext = ["harfbuzz-sys?/coretext"] -directwrite = ["harfbuzz-sys?/directwrite"] -freetype = ["harfbuzz-sys?/freetype"] -harfbuzz-sys = ["dep:harfbuzz-sys"] +default = ["coretext", "directwrite", "freetype", "std"] +bundled = ["harfbuzz-sys/bundled"] +coretext = ["harfbuzz-sys/coretext"] +directwrite = ["harfbuzz-sys/directwrite"] +freetype = ["harfbuzz-sys/freetype"] std = [] diff --git a/harfbuzz/src/lib.rs b/harfbuzz/src/lib.rs index 768656c4..69160b91 100644 --- a/harfbuzz/src/lib.rs +++ b/harfbuzz/src/lib.rs @@ -35,7 +35,6 @@ extern crate alloc; #[cfg(feature = "std")] extern crate std; -#[cfg(feature = "harfbuzz-sys")] pub use harfbuzz_sys as sys; /// An error type for this crate @@ -46,24 +45,16 @@ pub enum HarfBuzzError { } pub use HarfBuzzError as Error; -#[cfg(feature = "harfbuzz-sys")] mod buffer; -#[cfg(feature = "harfbuzz-sys")] pub use self::buffer::Buffer; -#[cfg(feature = "harfbuzz-sys")] mod direction; -#[cfg(feature = "harfbuzz-sys")] pub use self::direction::Direction; -#[cfg(feature = "harfbuzz-sys")] mod language; -#[cfg(feature = "harfbuzz-sys")] pub use self::language::Language; -#[cfg(feature = "harfbuzz-sys")] mod blob; -#[cfg(feature = "harfbuzz-sys")] pub use self::blob::Blob; mod traits; @@ -75,7 +66,5 @@ pub use self::traits::GeneralCategoryFunc; pub use self::traits::MirroringFunc; pub use self::traits::ScriptFunc; -#[cfg(feature = "harfbuzz-sys")] mod unicode_funcs; -#[cfg(feature = "harfbuzz-sys")] pub use self::unicode_funcs::{UnicodeFuncs, UnicodeFuncsBuilder}; From a313e89fa668d9428ecb736b812e4a16e9898179 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Mon, 28 Aug 2023 14:17:27 -0700 Subject: [PATCH 15/22] fix --- harfbuzz/src/lib.rs | 9 --------- 1 file changed, 9 deletions(-) diff --git a/harfbuzz/src/lib.rs b/harfbuzz/src/lib.rs index 69160b91..b8ef45e9 100644 --- a/harfbuzz/src/lib.rs +++ b/harfbuzz/src/lib.rs @@ -57,14 +57,5 @@ pub use self::language::Language; mod blob; pub use self::blob::Blob; -mod traits; -pub use self::traits::CombiningClassFunc; -pub use self::traits::ComposeFunc; -pub use self::traits::DecomposeFunc; -pub use self::traits::GeneralCategory; -pub use self::traits::GeneralCategoryFunc; -pub use self::traits::MirroringFunc; -pub use self::traits::ScriptFunc; - mod unicode_funcs; pub use self::unicode_funcs::{UnicodeFuncs, UnicodeFuncsBuilder}; From b54c45489898e955c9f8c48b5c39a7232e5fc4f7 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Mon, 28 Aug 2023 14:38:05 -0700 Subject: [PATCH 16/22] Add no_std marker for unicode-traits --- harfbuzz-traits/src/lib.rs | 2 ++ 1 file changed, 2 insertions(+) diff --git a/harfbuzz-traits/src/lib.rs b/harfbuzz-traits/src/lib.rs index 265132f5..1010ec13 100644 --- a/harfbuzz-traits/src/lib.rs +++ b/harfbuzz-traits/src/lib.rs @@ -12,6 +12,8 @@ //! This crate provides traits for the `harfbuzz` crate that can be implememted without //! depending on [HarfBuzz](https://harfbuzz.github.io/) itself. +#![no_std] + mod unicode_funcs_traits; pub use unicode_funcs_traits::*; From cfa6c82498028241807cbbf256c8c870e388732d Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Mon, 28 Aug 2023 19:50:40 -0500 Subject: [PATCH 17/22] Update lib.rs --- harfbuzz/src/lib.rs | 2 -- 1 file changed, 2 deletions(-) diff --git a/harfbuzz/src/lib.rs b/harfbuzz/src/lib.rs index 87bbf2b0..4554128d 100644 --- a/harfbuzz/src/lib.rs +++ b/harfbuzz/src/lib.rs @@ -18,8 +18,6 @@ //! - `std` - Enable certain functions that require the standard library. (Enabled by default.) //! //! - `bundled` - Use the bundled copy of the harfbuzz library rather than one installed on the system. -//! -//! TODO: Add more feature docs here #![no_std] #![warn(missing_docs)] From 9629d7a65c48aea2a5da9e4e95f79d5a6e40b91b Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Mon, 28 Aug 2023 19:56:13 -0500 Subject: [PATCH 18/22] Docs tests --- harfbuzz/src/unicode_funcs.rs | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index ebc3f9bb..ef2a37b8 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -272,38 +272,38 @@ impl Drop for UnicodeFuncsBuilder { /// # use harfbuzz::{Buffer, Direction, UnicodeFuncsBuilder, sys}; /// struct PropertyProvider; /// -/// impl harfbuzz::GeneralCategoryFunc for PropertyProvider { -/// fn general_category(&self, ch: char) -> harfbuzz::GeneralCategory { +/// impl harfbuzz_traits::GeneralCategoryFunc for PropertyProvider { +/// fn general_category(&self, ch: char) -> harfbuzz_traits::GeneralCategory { /// todo!("GeneralCategoryFunc") /// } /// } /// -/// impl harfbuzz::CombiningClassFunc for PropertyProvider { +/// impl harfbuzz_traits::CombiningClassFunc for PropertyProvider { /// fn combining_class(&self, ch: char) -> u8 { /// todo!("CombiningClassFunc") /// } /// } /// -/// impl harfbuzz::MirroringFunc for PropertyProvider { +/// impl harfbuzz_traits::MirroringFunc for PropertyProvider { /// fn mirroring(&self, ch: char) -> char { /// todo!("MirroringFunc") /// } /// } /// -/// impl harfbuzz::ScriptFunc for PropertyProvider { +/// impl harfbuzz_traits::ScriptFunc for PropertyProvider { /// fn script(&self, ch: char) -> [u8; 4] { /// debug_assert!(ch as u32 >= 0x0600 && ch as u32 <= 0x06FF); // Arab code points /// *b"Arab" /// } /// } /// -/// impl harfbuzz::ComposeFunc for PropertyProvider { +/// impl harfbuzz_traits::ComposeFunc for PropertyProvider { /// fn compose(&self, a: char, b:char) -> Option { /// todo!("ComposeFunc") /// } /// } /// -/// impl harfbuzz::DecomposeFunc for PropertyProvider { +/// impl harfbuzz_traits::DecomposeFunc for PropertyProvider { /// fn decompose(&self, ab: char) -> Option<(char, char)> { /// todo!("DecomposeFunc") /// } From 7e0ac7f5002cf5f3ff9337b44eaa5c7b5d2d1ee6 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Mon, 28 Aug 2023 20:04:28 -0500 Subject: [PATCH 19/22] fmt? --- harfbuzz/src/unicode_funcs.rs | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index ef2a37b8..31c9211d 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -8,10 +8,10 @@ // except according to those terms. use crate::sys::*; -use harfbuzz_traits::*; use crate::Error; use alloc::boxed::Box; use core::ffi::c_void; +use harfbuzz_traits::*; /// Converts from `hb_codepoint_t`, assumed to be valid, to `char`. #[inline] From 8aae545866ff1285ff7cfad8238d38f9a77c4760 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 30 Aug 2023 11:30:50 -0500 Subject: [PATCH 20/22] Update unicode_funcs_traits.rs --- harfbuzz-traits/src/unicode_funcs_traits.rs | 52 ++++++++++----------- 1 file changed, 26 insertions(+), 26 deletions(-) diff --git a/harfbuzz-traits/src/unicode_funcs_traits.rs b/harfbuzz-traits/src/unicode_funcs_traits.rs index e8442bdd..7f024edf 100644 --- a/harfbuzz-traits/src/unicode_funcs_traits.rs +++ b/harfbuzz-traits/src/unicode_funcs_traits.rs @@ -18,33 +18,33 @@ pub enum GeneralCategory { Control = 0, Format = 1, Unassigned = 2, - Private_use = 3, + PrivateUse = 3, Surrogate = 4, - Lowercase_Letter = 5, - Modifier_Letter = 6, - Other_Letter = 7, - Titlecase_Letter = 8, - Uppercase_Letter = 9, - Spacing_Mark = 10, - Enclosing_Mark = 11, - Non_Spacing_Mark = 12, - Decimal_Number = 13, - Letter_Number = 14, - Other_Number = 15, - Connect_Punctuation = 16, - Dash_Punctuation = 17, - Close_Punctuation = 18, - Final_Punctuation = 19, - Initial_Punctuation = 20, - Other_Punctuation = 21, - Open_Punctuation = 22, - Currency_Symbol = 23, - Modifier_Symbol = 24, - Math_Symbol = 25, - Other_Symbol = 26, - Line_Separator = 27, - Paragraph_Separator = 28, - Space_Separator = 29, + LowercaseLetter = 5, + ModifierLetter = 6, + OtherLetter = 7, + TitlecaseLetter = 8, + UppercaseLetter = 9, + SpacingMark = 10, + EnclosingMark = 11, + NonSpacingMark = 12, + DecimalNumber = 13, + LetterNumber = 14, + OtherNumber = 15, + ConnectPunctuation = 16, + DashPunctuation = 17, + ClosePunctuation = 18, + FinalPunctuation = 19, + InitialPunctuation = 20, + OtherPunctuation = 21, + OpenPunctuation = 22, + CurrencySymbol = 23, + ModifierSymbol = 24, + MathSymbol = 25, + OtherSymbol = 26, + LineSeparator = 27, + ParagraphSeparator = 28, + SpaceSeparator = 29, } /// An object to map from code points to general category properties. From cfe7ca49e43518cf88c9ae5ce01e8ee5c47613fa Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 30 Aug 2023 13:04:13 -0500 Subject: [PATCH 21/22] Update lib.rs --- harfbuzz/src/lib.rs | 1 + 1 file changed, 1 insertion(+) diff --git a/harfbuzz/src/lib.rs b/harfbuzz/src/lib.rs index 4554128d..fa1f4228 100644 --- a/harfbuzz/src/lib.rs +++ b/harfbuzz/src/lib.rs @@ -34,6 +34,7 @@ extern crate alloc; extern crate std; pub use harfbuzz_sys as sys; +pub use harfbuzz_traits as traits; /// An error type for this crate #[derive(Debug)] From cfc89acacaccb9d85af40e27b328dad5243db148 Mon Sep 17 00:00:00 2001 From: "Shane F. Carr" Date: Wed, 30 Aug 2023 13:05:20 -0500 Subject: [PATCH 22/22] Update unicode_funcs.rs --- harfbuzz/src/unicode_funcs.rs | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/harfbuzz/src/unicode_funcs.rs b/harfbuzz/src/unicode_funcs.rs index 31c9211d..558463e4 100644 --- a/harfbuzz/src/unicode_funcs.rs +++ b/harfbuzz/src/unicode_funcs.rs @@ -8,10 +8,10 @@ // except according to those terms. use crate::sys::*; +use crate::traits::*; use crate::Error; use alloc::boxed::Box; use core::ffi::c_void; -use harfbuzz_traits::*; /// Converts from `hb_codepoint_t`, assumed to be valid, to `char`. #[inline] @@ -272,38 +272,38 @@ impl Drop for UnicodeFuncsBuilder { /// # use harfbuzz::{Buffer, Direction, UnicodeFuncsBuilder, sys}; /// struct PropertyProvider; /// -/// impl harfbuzz_traits::GeneralCategoryFunc for PropertyProvider { -/// fn general_category(&self, ch: char) -> harfbuzz_traits::GeneralCategory { +/// impl harfbuzz::traits::GeneralCategoryFunc for PropertyProvider { +/// fn general_category(&self, ch: char) -> harfbuzz::traits::GeneralCategory { /// todo!("GeneralCategoryFunc") /// } /// } /// -/// impl harfbuzz_traits::CombiningClassFunc for PropertyProvider { +/// impl harfbuzz::traits::CombiningClassFunc for PropertyProvider { /// fn combining_class(&self, ch: char) -> u8 { /// todo!("CombiningClassFunc") /// } /// } /// -/// impl harfbuzz_traits::MirroringFunc for PropertyProvider { +/// impl harfbuzz::traits::MirroringFunc for PropertyProvider { /// fn mirroring(&self, ch: char) -> char { /// todo!("MirroringFunc") /// } /// } /// -/// impl harfbuzz_traits::ScriptFunc for PropertyProvider { +/// impl harfbuzz::traits::ScriptFunc for PropertyProvider { /// fn script(&self, ch: char) -> [u8; 4] { /// debug_assert!(ch as u32 >= 0x0600 && ch as u32 <= 0x06FF); // Arab code points /// *b"Arab" /// } /// } /// -/// impl harfbuzz_traits::ComposeFunc for PropertyProvider { +/// impl harfbuzz::traits::ComposeFunc for PropertyProvider { /// fn compose(&self, a: char, b:char) -> Option { /// todo!("ComposeFunc") /// } /// } /// -/// impl harfbuzz_traits::DecomposeFunc for PropertyProvider { +/// impl harfbuzz::traits::DecomposeFunc for PropertyProvider { /// fn decompose(&self, ab: char) -> Option<(char, char)> { /// todo!("DecomposeFunc") /// }