summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--crates/typst-ide/src/jump.rs2
-rw-r--r--crates/typst-render/src/text.rs13
-rw-r--r--crates/typst-svg/src/text.rs20
-rw-r--r--crates/typst/src/layout/abs.rs25
-rw-r--r--crates/typst/src/text/font/color.rs5
-rw-r--r--tests/ref/gradient-presets.pngbin17311 -> 17315 bytes
-rw-r--r--tests/suite/layout/length.typ38
7 files changed, 54 insertions, 49 deletions
diff --git a/crates/typst-ide/src/jump.rs b/crates/typst-ide/src/jump.rs
index b798defa..e48db986 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 70d51642..1685e67d 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 6af93398..4a99b4b8 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<EcoString
data = &decoded;
}
- let upem = Abs::raw(font.units_per_em());
- let (width, height) = (upem.to_pt(), upem.to_pt());
- let origin_ascender = font.metrics().ascender.at(upem).to_pt();
+ let upem = font.units_per_em();
+ let width = upem;
+ let height = upem;
+ let origin_ascender = font.metrics().ascender.at(Abs::pt(upem));
// Parse XML.
let mut svg_str = std::str::from_utf8(data).ok()?.to_owned();
@@ -296,7 +297,8 @@ fn convert_svg_glyph_to_base64_url(font: &Font, id: GlyphId) -> Option<EcoString
// make sure the glyph is rendered at the correct position
svg_str.insert_str(
start_span.unwrap().range().end,
- format!(r#" viewBox="0 {} {width} {height}""#, -origin_ascender).as_str(),
+ format!(r#" viewBox="0 {} {width} {height}""#, -origin_ascender.to_pt())
+ .as_str(),
);
}
diff --git a/crates/typst/src/layout/abs.rs b/crates/typst/src/layout/abs.rs
index c3ff8cbc..981a64ff 100644
--- a/crates/typst/src/layout/abs.rs
+++ b/crates/typst/src/layout/abs.rs
@@ -7,9 +7,6 @@ use ecow::EcoString;
use crate::foundations::{cast, repr, Fold, Repr, Value};
use crate::utils::{Numeric, Scalar};
-/// The epsilon for approximate comparisons.
-const EPS: f64 = 1e-6;
-
/// An absolute length.
#[derive(Default, Copy, Clone, Eq, PartialEq, Ord, PartialOrd, Hash)]
pub struct Abs(Scalar);
@@ -113,17 +110,17 @@ impl Abs {
/// Whether the other absolute length fits into this one (i.e. is smaller).
/// Allows for a bit of slack.
pub fn fits(self, other: Self) -> 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 0e6b0c1f..e26d323c 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 de496894..7fdb235c 100644
--- a/tests/ref/gradient-presets.png
+++ b/tests/ref/gradient-presets.png
Binary files differ
diff --git a/tests/suite/layout/length.typ b/tests/suite/layout/length.typ
index c40752f7..5ba70072 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.