From 67fce0f63c13974a9f1d73e9cafa3e208bacc8ef Mon Sep 17 00:00:00 2001 From: Nigel Ihza Firdausy <106657905+Ni-zav@users.noreply.github.com> Date: Sat, 10 Oct 2026 15:54:14 +0700 Subject: [PATCH] fix(geom): carry rounded pica and cicero fractions Apply the displayed precision before testing for a 12-point carry, so measurements near a pica/cicero boundary do not display as 0p12 or 0c12. Cover positive, negative, coarse, and subunit rounding. --- crates/geom/src/units.rs | 18 +++++++++++++++++- 1 file changed, 17 insertions(+), 1 deletion(-) diff --git a/crates/geom/src/units.rs b/crates/geom/src/units.rs index 7b5aae77..0e0c9b4b 100644 --- a/crates/geom/src/units.rs +++ b/crates/geom/src/units.rs @@ -270,7 +270,12 @@ pub fn format_measure_prec(pt: f64, unit: Unit, decimals: usize) -> String { let a = pt.abs(); let mut whole = (a / big).floor(); let mut rest = (a - whole * big) / small; - if (rest - 12.0).abs() < 1e-6 || rest > 12.0 - 1e-6 { + // Carry when the displayed fractional points round up to a full pica/cicero. + // Checking unrounded rest misses values such as 11.9999 at 3 decimals, + // which would otherwise render as the misleading "0p12". + let scale = 10.0_f64.powi(decimals.min(12) as i32); + rest = (rest * scale).round() / scale; + if rest >= 12.0 { whole += 1.0; rest = 0.0; } @@ -335,6 +340,17 @@ mod tests { assert!(parse_measure("50%", Unit::Points).is_err()); } + #[test] + fn pica_and_cicero_rounding_carries_into_the_major_unit() { + assert_eq!(format_measure_prec(11.9999, Unit::Picas, 3), "1p0"); + assert_eq!(format_measure_prec(-11.9999, Unit::Picas, 3), "-1p0"); + assert_eq!(format_measure_prec(11.9994, Unit::Picas, 3), "0p11.999"); + assert_eq!(format_measure_prec(11.6, Unit::Picas, 0), "1p0"); + let almost_cicero = PT_PER_CICERO - 0.0001 * PT_PER_DIDOT; + assert_eq!(format_measure_prec(almost_cicero, Unit::Ciceros, 3), "1c0"); + assert!(close(p(&format_measure_prec(11.9999, Unit::Picas, 3)), 12.0)); + } + #[test] fn formatting() { assert_eq!(format_measure(18.0, Unit::Picas), "1p6");