diff --git a/Cargo.toml b/Cargo.toml index e342d67a..9175573d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -22,7 +22,7 @@ codegen-units = 1 inherits = "release" [workspace.dependencies] -read-fonts = { version = "0.40.2", default-features = false, features = ["experimental_font_api"] } +read-fonts = { version = "0.41.0", default-features = false, features = ["experimental_font_api"] } harfrust = { version = "0.11.0", path = "./harfrust", default-features = false } [workspace.lints.rust] diff --git a/harfrust/src/hb/face.rs b/harfrust/src/hb/face.rs index 485bf98c..2cd1cb0b 100644 --- a/harfrust/src/hb/face.rs +++ b/harfrust/src/hb/face.rs @@ -381,6 +381,18 @@ impl Scale { Self::scale_by_mult(y, self.y_mult) } + /// Scales a fractional (font-unit) value, matching HarfBuzz's `em_scalef` + /// (`roundf(v * scale / upem)`). + #[inline(always)] + pub(crate) fn scale_x_f(&self, x: f32) -> i32 { + (x * self.x_multf).round() as i32 + } + + #[inline(always)] + pub(crate) fn scale_y_f(&self, y: f32) -> i32 { + (y * self.y_multf).round() as i32 + } + /// Scales glyph extents using HarfBuzz's corner-based float arithmetic: /// floor the origin corners and ceil the far corners before deriving the /// final width/height. diff --git a/harfrust/src/hb/ot/gpos/mod.rs b/harfrust/src/hb/ot/gpos/mod.rs index 9b0425e3..210b435c 100644 --- a/harfrust/src/hb/ot/gpos/mod.rs +++ b/harfrust/src/hb/ot/gpos/mod.rs @@ -60,7 +60,10 @@ fn apply_value( () => {{ let rec_offset = data.read_at::(offset).ok()? as usize; offset += 2; - let mut value = 0; + // Keep the delta fractional; scale_x_f rounds once, matching + // HarfBuzz's em_scalef (rounding whole font units first would + // lose up to half a unit). + let mut value = 0.0f32; // Offset is nullable if rec_offset != 0 { let format = data.read_at::(rec_offset + 4).ok()?; @@ -71,30 +74,31 @@ fn apply_value( let outer = data.read_at::(rec_offset).ok()?; let inner = data.read_at::(rec_offset + 2).ok()?; value = vs - .compute_delta(DeltaSetIndex { outer, inner }, coords) - .unwrap_or_default(); - worked |= value != 0; + .compute_float_delta(DeltaSetIndex { outer, inner }, coords) + .unwrap_or_default() + .to_f64() as f32; + worked |= value != 0.0; } } value }}; } if format.contains(ValueFormat::X_PLACEMENT_DEVICE) { - pos.x_offset += scale.scale_x(read_delta!()); + pos.x_offset += scale.scale_x_f(read_delta!()); } if format.contains(ValueFormat::Y_PLACEMENT_DEVICE) { - pos.y_offset += scale.scale_y(read_delta!()); + pos.y_offset += scale.scale_y_f(read_delta!()); } if format.contains(ValueFormat::X_ADVANCE_DEVICE) { if is_horizontal { - pos.x_advance += scale.scale_x(read_delta!()); + pos.x_advance += scale.scale_x_f(read_delta!()); } else { offset += 2; } } if format.contains(ValueFormat::Y_ADVANCE_DEVICE) { if !is_horizontal { - pos.y_advance -= scale.scale_y(read_delta!()); + pos.y_advance -= scale.scale_y_f(read_delta!()); } else { offset += 2; } diff --git a/harfrust/src/hb/ot/mod.rs b/harfrust/src/hb/ot/mod.rs index 4d0a29d3..4b5783ba 100644 --- a/harfrust/src/hb/ot/mod.rs +++ b/harfrust/src/hb/ot/mod.rs @@ -336,21 +336,25 @@ impl<'a> OtTables<'a> { } } - pub(super) fn resolve_anchor(&self, anchor: &AnchorTable) -> (i32, i32) { - let mut x = anchor.x_coordinate() as i32; - let mut y = anchor.y_coordinate() as i32; + pub(super) fn resolve_anchor(&self, anchor: &AnchorTable) -> (f32, f32) { + let mut x = anchor.x_coordinate() as f32; + let mut y = anchor.y_coordinate() as f32; if let Some(vs) = self.var_store.as_ref() { + // Keep the delta fractional; the caller rounds once when scaling, + // matching HarfBuzz's Anchor::get_anchor. let delta = |val: Option, ReadError>>| match val { - Some(Ok(DeviceOrVariationIndex::VariationIndex(varix))) => vs - .compute_delta( + Some(Ok(DeviceOrVariationIndex::VariationIndex(varix))) => { + vs.compute_float_delta( DeltaSetIndex { outer: varix.delta_set_outer_index(), inner: varix.delta_set_inner_index(), }, self.coords, ) - .unwrap_or_default(), - _ => 0, + .unwrap_or_default() + .to_f64() as f32 + } + _ => 0.0, }; x += delta(anchor.x_device()); y += delta(anchor.y_device()); diff --git a/harfrust/src/hb/ot_layout_gsubgpos.rs b/harfrust/src/hb/ot_layout_gsubgpos.rs index 5354ec63..a8771281 100644 --- a/harfrust/src/hb/ot_layout_gsubgpos.rs +++ b/harfrust/src/hb/ot_layout_gsubgpos.rs @@ -906,13 +906,13 @@ pub mod OT { } #[inline(always)] - pub fn scale_x(&self, value: i32) -> i32 { - self.scale.scale_x(value) + pub fn scale_x(&self, value: f32) -> i32 { + self.scale.scale_x_f(value) } #[inline(always)] - pub fn scale_y(&self, value: i32) -> i32 { - self.scale.scale_y(value) + pub fn scale_y(&self, value: f32) -> i32 { + self.scale.scale_y_f(value) } pub fn random_number(&mut self) -> u32 {