diff --git a/font-types/src/fixed.rs b/font-types/src/fixed.rs index 93d726195..884792caa 100644 --- a/font-types/src/fixed.rs +++ b/font-types/src/fixed.rs @@ -239,10 +239,10 @@ macro_rules! float_conv { /// representable value. #[inline(always)] pub fn $from(x: $ty) -> Self { - Self( - (x * Self::ONE.0 as $ty + (0.5 * (-1.0 * x.is_sign_negative() as u8 as $ty))) - as _, - ) + // When x is positive: 1.0 - 0.5 = 0.5 + // When x is negative: 0.0 - 0.5 = -0.5 + let frac = (x.is_sign_positive() as u8 as $ty) - 0.5; + Self((x * Self::ONE.0 as $ty + frac) as _) } #[doc = concat!("Returns the value as an ", stringify!($ty), ".")] @@ -420,6 +420,23 @@ mod tests { assert_eq!(Fixed(0x7fff_ffff), Fixed::from_f64(32768.0)); } + // We lost the f64::round() intrinsic when dropping std and the + // alternative implementation was very slightly incorrect, throwing + // off some tests. This makes sure we match. + #[test] + fn fixed_floats_rounding() { + fn with_round_intrinsic(x: f64) -> Fixed { + Fixed((x * 65536.0).round() as i32) + } + // These particular values were tripping up tests + let inputs = [0.05, 0.6, 0.2, 0.4, 0.67755]; + for input in inputs { + assert_eq!(Fixed::from_f64(input), with_round_intrinsic(input)); + // Test negated values as well for good measure + assert_eq!(Fixed::from_f64(-input), with_round_intrinsic(-input)); + } + } + #[test] fn fixed_to_int() { assert_eq!(Fixed::from_f64(1.0).to_i32(), 1); diff --git a/read-fonts/src/tables/avar.rs b/read-fonts/src/tables/avar.rs index 77b9c0131..9f2debf8d 100644 --- a/read-fonts/src/tables/avar.rs +++ b/read-fonts/src/tables/avar.rs @@ -82,9 +82,9 @@ mod tests { value_map(-0.6667, -0.5), value_map(-0.3333, -0.25), value_map(0.0, 0.0), - value_map(0.2000122, 0.3674), - value_map(0.4000244, 0.52246094), - value_map(0.6, 0.67755127), + value_map(0.2, 0.3674), + value_map(0.4, 0.52246), + value_map(0.6, 0.67755), value_map(0.8, 0.83875), value_map(1.0, 1.0), ]]; diff --git a/read-fonts/src/tables/postscript/dict.rs b/read-fonts/src/tables/postscript/dict.rs index b1fb1f958..2354ad60b 100644 --- a/read-fonts/src/tables/postscript/dict.rs +++ b/read-fonts/src/tables/postscript/dict.rs @@ -655,7 +655,7 @@ mod tests { -20.0, 0.0, 473.0, 491.0, 525.0, 540.0, 644.0, 659.0, 669.0, 689.0, 729.0, 749.0, ])), FamilyOtherBlues(make_blues(&[-249.0, -239.0])), - BlueScale(Fixed::from_f64(0.0374908447265625)), + BlueScale(Fixed::from_f64(0.037506103515625)), BlueFuzz(Fixed::ZERO), StdHw(Fixed::from_f64(55.0)), StdVw(Fixed::from_f64(80.0)), diff --git a/skrifa/src/outline/cff/hint.rs b/skrifa/src/outline/cff/hint.rs index d73bef156..002910b41 100644 --- a/skrifa/src/outline/cff/hint.rs +++ b/skrifa/src/outline/cff/hint.rs @@ -1136,7 +1136,7 @@ mod tests { let state = make_hint_state(); assert!(!state.do_em_box_hints); assert_eq!(state.zone_count, 6); - assert_eq!(state.boost, Fixed::from_f64(0.412445068359375)); + assert_eq!(state.boost, Fixed::from_bits(27035)); assert!(state.supress_overshoot); // FreeType generates the following zones: let expected_zones = &[