diff --git a/crates/typst-ide/src/jump.rs b/crates/typst-ide/src/jump.rs index b798defab..e48db9865 100644 --- a/crates/typst-ide/src/jump.rs +++ b/crates/typst-ide/src/jump.rs @@ -205,7 +205,7 @@ mod tests { macro_rules! assert_approx_eq { ($l:expr, $r:expr) => { - assert!(($l.to_raw() - $r.to_raw()).abs() < 0.1, "{:?} ≉ {:?}", $l, $r); + assert!(($l - $r).abs() < Abs::pt(0.1), "{:?} ≉ {:?}", $l, $r); }; } diff --git a/crates/typst-render/src/text.rs b/crates/typst-render/src/text.rs index 70d516426..1685e67dc 100644 --- a/crates/typst-render/src/text.rs +++ b/crates/typst-render/src/text.rs @@ -13,27 +13,26 @@ use crate::{shape, AbsExt, State}; /// Render a text run into the canvas. pub fn render_text(canvas: &mut sk::Pixmap, state: State, text: &TextItem) { - let mut x = 0.0; + let mut x = Abs::zero(); for glyph in &text.glyphs { let id = GlyphId(glyph.id); - let offset = x + glyph.x_offset.at(text.size).to_f32(); + let offset = x + glyph.x_offset.at(text.size); if should_outline(&text.font, glyph) { - let state = - state.pre_translate(Point::new(Abs::raw(offset as _), Abs::raw(0.0))); + let state = state.pre_translate(Point::with_x(offset)); render_outline_glyph(canvas, state, text, id); } else { let upem = text.font.units_per_em(); - let text_scale = Abs::raw(text.size.to_raw() / upem); + let text_scale = text.size / upem; let state = state - .pre_translate(Point::new(Abs::raw(offset as _), -text.size)) + .pre_translate(Point::new(offset, -text.size)) .pre_scale(Axes::new(text_scale, text_scale)); let (glyph_frame, _) = glyph_frame(&text.font, glyph.id); crate::render_frame(canvas, state, &glyph_frame); } - x += glyph.x_advance.at(text.size).to_f32(); + x += glyph.x_advance.at(text.size); } } diff --git a/crates/typst-svg/src/text.rs b/crates/typst-svg/src/text.rs index 6af933988..4a99b4b8e 100644 --- a/crates/typst-svg/src/text.rs +++ b/crates/typst-svg/src/text.rs @@ -55,15 +55,15 @@ impl SVGRenderer { scale: f64, ) -> Option<()> { let data_url = convert_svg_glyph_to_base64_url(&text.font, id)?; - let upem = Abs::raw(text.font.units_per_em()); - let origin_ascender = text.font.metrics().ascender.at(upem).to_pt(); + let upem = text.font.units_per_em(); + let origin_ascender = text.font.metrics().ascender.at(Abs::pt(upem)); let glyph_hash = hash128(&(&text.font, id)); let id = self.glyphs.insert_with(glyph_hash, || RenderedGlyph::Image { url: data_url, - width: upem.to_pt(), - height: upem.to_pt(), - ts: Transform::translate(Abs::zero(), Abs::pt(-origin_ascender)) + width: upem, + height: upem, + ts: Transform::translate(Abs::zero(), -origin_ascender) .post_concat(Transform::scale(Ratio::new(scale), Ratio::new(-scale))), }); @@ -260,9 +260,10 @@ fn convert_svg_glyph_to_base64_url(font: &Font, id: GlyphId) -> Option Option bool { - self.0 + EPS >= other.0 + self.0 + AbsUnit::EPS >= other.0 } /// Compares two absolute lengths for whether they are approximately equal. pub fn approx_eq(self, other: Self) -> bool { - self == other || (self - other).to_raw().abs() < EPS + self == other || (self - other).to_raw().abs() < AbsUnit::EPS } /// Whether the size is close to zero or negative. pub fn approx_empty(self) -> bool { - self.to_raw() <= EPS + self.to_raw() <= AbsUnit::EPS } /// Returns a number that represent the sign of this length @@ -254,13 +251,19 @@ pub enum AbsUnit { } impl AbsUnit { + /// The epsilon for approximate length comparisons. + const EPS: f64 = 1e-4; + /// How many raw units correspond to a value of `1.0` in this unit. - fn raw_scale(self) -> f64 { + const fn raw_scale(self) -> f64 { + // We choose a raw scale which has an integer conversion value to all + // four units of interest, so that whole numbers in all units can be + // represented accurately. match self { - AbsUnit::Pt => 1.0, - AbsUnit::Mm => 2.83465, - AbsUnit::Cm => 28.3465, - AbsUnit::In => 72.0, + AbsUnit::Pt => 127.0, + AbsUnit::Mm => 360.0, + AbsUnit::Cm => 3600.0, + AbsUnit::In => 9144.0, } } } diff --git a/crates/typst/src/text/font/color.rs b/crates/typst/src/text/font/color.rs index 0e6b0c1fa..e26d323cf 100644 --- a/crates/typst/src/text/font/color.rs +++ b/crates/typst/src/text/font/color.rs @@ -186,9 +186,8 @@ fn draw_colr_glyph( ) .ok()?; - let y_shift = Abs::raw(upem.to_raw() - y_max); - - let position = Point::new(Abs::raw(x_min), y_shift); + let y_shift = Abs::pt(upem.to_pt() - y_max); + let position = Point::new(Abs::pt(x_min), y_shift); let size = Size::new(Abs::pt(width), Abs::pt(height)); frame.push(position, FrameItem::Image(image, size, Span::detached())); diff --git a/tests/ref/gradient-presets.png b/tests/ref/gradient-presets.png index de4968944..7fdb235c2 100644 Binary files a/tests/ref/gradient-presets.png and b/tests/ref/gradient-presets.png differ diff --git a/tests/suite/layout/length.typ b/tests/suite/layout/length.typ index c40752f78..5ba70072d 100644 --- a/tests/suite/layout/length.typ +++ b/tests/suite/layout/length.typ @@ -9,24 +9,26 @@ --- length-to-unit --- // Test length unit conversions. -#test((500.934pt).pt(), 500.934) -#test((3.3453cm).cm(), 3.3453) -#test((4.3452mm).mm(), 4.3452) -#test((5.345in).inches(), 5.345) -#test((500.333666999pt).pt(), 500.333666999) -#test((3.5234354cm).cm(), 3.5234354) -#test((4.12345678mm).mm(), 4.12345678) -#test((5.333666999in).inches(), 5.333666999) -#test((4.123456789123456mm).mm(), 4.123456789123456) -#test((254cm).mm(), 2540.0) -#test(calc.round((254cm).inches(), digits: 2), 100.0) -#test((2540mm).cm(), 254.0) -#test(calc.round((2540mm).inches(), digits: 2), 100.0) -#test((100in).pt(), 7200.0) -#test(calc.round((100in).cm(), digits: 2), 254.0) -#test(calc.round((100in).mm(), digits: 2), 2540.0) -#test(5em.abs.cm(), 0.0) -#test((5em + 6in).abs.inches(), 6.0) +#let t(a, b) = assert(calc.abs(a - b) < 1e-6) + +#t((500.934pt).pt(), 500.934) +#t((3.3453cm).cm(), 3.3453) +#t((4.3452mm).mm(), 4.3452) +#t((5.345in).inches(), 5.345) +#t((500.333666999pt).pt(), 500.333666999) +#t((3.523435cm).cm(), 3.523435) +#t((4.12345678mm).mm(), 4.12345678) +#t((5.333666999in).inches(), 5.333666999) +#t((4.123456789123456mm).mm(), 4.123456789123456) +#t((254cm).mm(), 2540.0) +#t((254cm).inches(), 100.0) +#t((2540mm).cm(), 254.0) +#t((2540mm).inches(), 100.0) +#t((100in).pt(), 7200.0) +#t((100in).cm(), 254.0) +#t((100in).mm(), 2540.0) +#t(5em.abs.cm(), 0.0) +#t((5em + 6in).abs.inches(), 6.0) --- length-to-absolute --- // Test length `to-absolute` method.