Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Use fields from Typst 0.7.0 when possible #106

Merged
merged 2 commits into from
Dec 31, 2023
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
16 changes: 16 additions & 0 deletions src/common.typ
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,15 @@
calc.floor(a) - calc.floor(b * calc.floor(a / b))
}

// Returns the sign of the operand.
// -1 for negative, 1 for positive or zero.
#let calc-sign(x) = {
// For positive: true - false = 1 - 0 = 1
// For zero: true - false = 1 - 0 = 1
// For negative: false - true = 0 - 1 = -1
int(0 <= x) - int(x < 0)
}

// get the types of things so we can compare with them
// (0.2.0-0.7.0: they're strings; 0.8.0+: they're proper types)
#let _array-type = type(())
Expand All @@ -33,3 +42,10 @@
// but keep it like this for pre-0.8.0
#let _align-type = type(left)
#let _2d-align-type = type(top + left)

// If types aren't strings, this means we're using 0.8.0+.
#let using-typst-v080-or-later = str(type(_str-type)) == "type"

// This is true if types have fields in the current Typst version.
// This means we can use stroke.thickness, length.em, and so on.
#let typst-fields-supported = using-typst-v080-or-later
2 changes: 1 addition & 1 deletion src/type-validators.typ
Original file line number Diff line number Diff line change
Expand Up @@ -100,7 +100,7 @@

// Check if the given length has type '_length-type' and no 'em' component.
#let is-purely-pt-len(len) = {
type(len) == _length-type and "em" not in repr(len)
type(len) == _length-type and ((typst-fields-supported and len.em == 0) or (not typst-fields-supported and "em" not in repr(len)))
}

// Check if this is a valid color (color, gradient or pattern).
Expand Down
31 changes: 25 additions & 6 deletions src/utilities.typ
Original file line number Diff line number Diff line change
Expand Up @@ -129,6 +129,18 @@
//
// styles: from style()
#let measure-pt(len, styles) = {
if typst-fields-supported {
// We can use fields to separate em from pt.
let pt = len.abs
let em = len.em
// Measure with abs (and later multiply by the sign) so negative em works.
// Otherwise it would return 0pt, and we would need to measure again with abs.
let measured-em = calc-sign(em) * measure(box(width: calc.abs(em) * 1em), styles).width

return pt + measured-em
}

// Fields not supported, so we have to measure twice when em can be negative.
let measured-pt = measure(box(width: len), styles).width

// If the measured length is positive, `len` must have overall been positive.
Expand All @@ -151,7 +163,7 @@
// styles: from style()
#let convert-length-type-to-pt(len, styles: none) = {
// repr examples: "1pt", "1em", "0.5pt", "0.5em", "1pt + 1em", "-0.5pt + -0.5em"
if "em" not in repr(len) {
if is-purely-pt-len(len) {
// No need to do any conversion because it must already be in pt.
return len
}
Expand Down Expand Up @@ -217,17 +229,18 @@
// styles: from style()
// page-size: equivalent to 100% (optional because the length may not have a ratio component)
#let convert-relative-type-to-pt(len, styles, page-size: none) = {
if typst-fields-supported or eval(repr(0.00005em)) != 0.00005em {
// em repr changed in 0.11.0 => need to use fields here
// or use fields if they're supported anyway
return convert-ratio-type-to-pt(len.ratio, page-size) + convert-length-type-to-pt(len.length, styles: styles)
}

// We will need to draw a line for measurement later,
// so we need the styles.
if styles == none {
panic("Cannot convert relative length to pt ('styles' not specified).")
}

if eval(repr(0.00005em)) != 0.00005em {
// em repr changed in 0.11.0 => can safely use fields here
return convert-ratio-type-to-pt(len.ratio, page-size) + convert-length-type-to-pt(len.length, styles: styles)
}

// Note on precision: the `repr` for em components is precise, unlike
// other length components, which are rounded to a precision of 2.
// This is true up to Typst 0.9.0 and possibly later versions.
Expand Down Expand Up @@ -305,6 +318,12 @@
} else if is-color(stroke) {
1pt
} else if type(stroke) == _stroke-type {
if typst-fields-supported {
// No need for any repr() parsing, just use the thickness field.
let thickness = default-if-auto(stroke.thickness, 1pt)
return convert-length-to-pt(thickness, styles: styles)
}

// support:
// - 2pt / 2em / 2cm / 2in + color
// - 2.5pt / 2.5em / ... + color
Expand Down