From f2f644d3de8dee9a71c90e0376fd44531e5c2eec Mon Sep 17 00:00:00 2001 From: Cristian Brinza Date: Sat, 17 Aug 2024 15:49:06 +0300 Subject: [PATCH] Add glyph pair kerning bindings (#55) * Add kerning pair bindings Signed-off-by: crbrz * Use cached IDWriteFontFace1 Signed-off-by: crbrz * Fixed build warnings Signed-off-by: crbrz --------- Signed-off-by: crbrz --- src/com_helpers.rs | 2 +- src/font_face.rs | 53 +++++++++++++++++++++++++++++++++--- src/font_file_loader_impl.rs | 2 +- src/helpers.rs | 6 +--- 4 files changed, 52 insertions(+), 11 deletions(-) diff --git a/src/com_helpers.rs b/src/com_helpers.rs index b4bcf16..aa28b2d 100644 --- a/src/com_helpers.rs +++ b/src/com_helpers.rs @@ -122,6 +122,6 @@ where } unsafe fn destroy(thing: *mut Interface) { - Box::from_raw(thing as *mut ComRepr); + let _ = Box::from_raw(thing as *mut ComRepr); } } diff --git a/src/font_face.rs b/src/font_face.rs index be0091e..2e3d149 100644 --- a/src/font_face.rs +++ b/src/font_face.rs @@ -21,6 +21,7 @@ use winapi::um::dwrite::{DWRITE_GLYPH_OFFSET, DWRITE_MATRIX, DWRITE_RENDERING_MO use winapi::um::dwrite::{DWRITE_RENDERING_MODE_DEFAULT, DWRITE_RENDERING_MODE_NATURAL_SYMMETRIC}; use winapi::um::dwrite_1::IDWriteFontFace1; use winapi::um::dwrite_3::{IDWriteFontFace5, IDWriteFontResource, DWRITE_FONT_AXIS_VALUE}; +use winapi::Interface; use wio::com::ComPtr; use super::{DWriteFactory, DefaultDWriteRenderParams, FontFile, FontMetrics}; @@ -30,6 +31,7 @@ use crate::outline_builder::OutlineBuilder; pub struct FontFace { native: UnsafeCell>, + face1: UnsafeCell>>, face5: UnsafeCell>>, } @@ -38,6 +40,7 @@ impl FontFace { let cell = UnsafeCell::new(native); FontFace { native: cell, + face1: UnsafeCell::new(None), face5: UnsafeCell::new(None), } } @@ -99,7 +102,7 @@ impl FontFace { pub fn metrics(&self) -> FontMetrics { unsafe { - let font_1: Option> = (*self.native.get()).cast().ok(); + let font_1 = self.get_face1(); match font_1 { None => { let mut metrics = mem::zeroed(); @@ -286,6 +289,34 @@ impl FontFace { } } + pub fn has_kerning_pairs(&self) -> bool { + unsafe { + match self.get_face1() { + Some(face1) => face1.HasKerningPairs() == TRUE, + None => false, + } + } + } + + pub fn get_glyph_pair_kerning_adjustment(&self, first_glyph: u16, second_glyph: u16) -> i32 { + unsafe { + match self.get_face1() { + Some(face1) => { + let mut adjustments = [0; 2]; + let hr = face1.GetKerningPairAdjustments( + 2, + [first_glyph, second_glyph].as_ptr(), + adjustments.as_mut_ptr(), + ); + assert_eq!(hr, S_OK); + + adjustments[0] + } + None => 0, + } + } + } + #[inline] pub fn get_type(&self) -> FontFaceType { unsafe { @@ -307,12 +338,25 @@ impl FontFace { unsafe { (*self.native.get()).GetIndex() } } + #[inline] + unsafe fn get_face1(&self) -> Option> { + self.get_interface(&self.face1) + } + #[inline] unsafe fn get_face5(&self) -> Option> { - if (*self.face5.get()).is_none() { - *self.face5.get() = (*self.native.get()).cast().ok() + self.get_interface(&self.face5) + } + + #[inline] + unsafe fn get_interface( + &self, + interface: &UnsafeCell>>, + ) -> Option> { + if (*interface.get()).is_none() { + *interface.get() = (*self.native.get()).cast().ok() } - (*self.face5.get()).clone() + (*interface.get()).clone() } pub fn has_variations(&self) -> bool { @@ -358,6 +402,7 @@ impl Clone for FontFace { unsafe { FontFace { native: UnsafeCell::new((*self.native.get()).clone()), + face1: UnsafeCell::new(None), face5: UnsafeCell::new(None), } } diff --git a/src/font_file_loader_impl.rs b/src/font_file_loader_impl.rs index 30230d0..6a3f22d 100644 --- a/src/font_file_loader_impl.rs +++ b/src/font_file_loader_impl.rs @@ -178,7 +178,7 @@ unsafe impl Sync for FontFileLoaderWrapper {} lazy_static! { static ref FONT_FILE_STREAM_MAP: Mutex> = - { Mutex::new(HashMap::new()) }; + Mutex::new(HashMap::new()); static ref FONT_FILE_LOADER: Mutex = { unsafe { let ffl_native = FontFileLoader::new(); diff --git a/src/helpers.rs b/src/helpers.rs index 804ff9e..45bf005 100644 --- a/src/helpers.rs +++ b/src/helpers.rs @@ -19,7 +19,7 @@ lazy_static! { locale } }; - static ref EN_US_LOCALE: Vec = { OsStr::new("en-us").to_wide_null() }; + static ref EN_US_LOCALE: Vec = OsStr::new("en-us").to_wide_null(); } pub fn get_locale_string(strings: &mut ComPtr) -> String { @@ -51,7 +51,6 @@ pub fn get_locale_string(strings: &mut ComPtr) -> Strin // ToWide from https://github.com/retep998/wio-rs/blob/master/src/wide.rs pub trait ToWide { - fn to_wide(&self) -> Vec; fn to_wide_null(&self) -> Vec; } @@ -59,9 +58,6 @@ impl ToWide for T where T: AsRef, { - fn to_wide(&self) -> Vec { - self.as_ref().encode_wide().collect() - } fn to_wide_null(&self) -> Vec { self.as_ref().encode_wide().chain(Some(0)).collect() }