We get weird result because
- there’s no enough space to put
sq
— the height ofsq
is 15 mm, but only 10 mm is available in the row (expect the first row) - the scale factor is specified as an absolute
length
, instead ofratio
.
According to the rust code, I think the relation between these heights is the following:
#let calc-result-height(
available-height,
content-height,
scale-abs,
) = {
let scale-ratio = (
scale-abs / calc.min(available-height, content-height)
)
content-height * scale-ratio
}
Code
#let calc-result-height(available: 0pt, content: 0pt, scale-abs: 0pt) = {
// Here `0pt` are only placeholders. This function only expects positive lengths.
let scale-ratio = scale-abs / calc.min(available, content)
content * scale-ratio
}
#let scale-abs = 10pt
#let content-height = 10pt
#let available-heights = (20pt, 15pt, 10pt, 8pt, 4pt, 2pt, 1pt, 0.5pt)
#assert.eq(type(scale-abs), length)
#let it = scale(scale-abs, box(
fill: orange.transparentize(50%),
width: 10pt,
height: content-height,
))
#set page(width: auto, height: auto, margin: 1em)
A #content-height square: #box(width: 10pt, height: content-height, fill: purple, baseline: 20%)
#let raw-repr(it) = raw(repr(it), lang: "typc")
#table(
columns: 2 + available-heights.len(),
align: (x, _) => if x > 0 { center } else { start } + horizon,
stroke: (x, y) => if y > 0 { (top: 0.5pt) } + if x > 0 { (left: 0.5pt) },
[*Height of \ available space*],
$+oo$,
..available-heights.map(raw-repr),
[
*Height of* \
#raw(
lang: "typc",
```typc
scale(
{scale-abs},
box(height: {content-height})
)```
.text
.replace("{scale-abs}", repr(scale-abs))
.replace("{content-height}", repr(content-height)),
)
],
grid(
align: horizon,
columns: 4,
column-gutter: 2pt,
raw-repr(content-height),
box(width: 0.5pt, height: content-height, fill: black),
it,
),
..available-heights.map(h => {
let result = calc-result-height(
available: h,
content: content-height,
scale-abs: scale-abs,
)
grid(
align: horizon,
columns: 4,
column-gutter: 2pt,
raw-repr(result),
box(width: 0.5pt, height: result, fill: black),
box(height: h, stroke: gray, it),
)
}),
)
My conclusions
(for typst 0.13.1)
Short answers to specific questions
Why is the “square” in row 2 rectangular and not square?
row 2:scale(sz, sq)
-
width: 5 mm, as specified.
-
height: there’s no enough space to put the original 15 mm
sq
, and the result height is determined by:let scale-ratio = scale-abs / calc.min(available-height, content-height) // = 5mm / calc.min(10mm, 15mm) // = 50% let result-height = content-height * scale-ratio // = 15mm * 50% // = 7.5mm
Why is the square in row 3 not 5mm x 5mm?
row 3:scale(sz, x: auto, sq)
auto
means to preserve the aspect ratio.
- height: 7.5 mm, the same as row 2.
- width: 15 mm * 50% = 7.5 mm, as implied by
x: auto
, which means the same ratio in y axis.
Why is the
factor
in row 7 ignored and width and height are different?
row 7:scale(sz, x: 100%, sq)
The precedence of factor, x, y
is:
- Resolved
x
= first value that is notnone
in the list(x, factor, 100%)
. - Resolved
y
= first value that is notnone
in the list(y, factor, 100%)
.
Therefore,
- width: 15 mm * 100% = 15 mm, as specified by
x: 100%
— it’s relative to the original size of the content. - height: 7.5 mm, the same as row 2.
What is going on in row 8?
row 8:scale(sz, x:1.5 * sz, y: 1.1 * sz, sq)
As explained in row 7, the resolved x
is 1.5 * sz
, and resolved y
is 1.1 * sz
.
- width: 1.5 * 5 mm = 7.5 mm, as specified by
x: 1.5 * sz
. - height:
15mm * ((1.1 * 5mm) / 10mm)
, as specified byy: 1.1 * sz
and similar to row 2.
Why is the square height in row 10 and 12 larger than the row height even though the
y
parameter is 100%?
row 10:scale(sz, y: 100%, sq)
row 12:scale(sz, x: 100%, y: 100%, sq)
ratio
s are relative to the original size of the content, not available region.
Row 10:
- width: 5 mm, as specified.
- height: 15 mm * 100% = 15 mm, as specified.
Row 12:
- width: 15 mm * 100% = 15 mm, as specified.
- height: 15 mm * 100% = 15 mm, as specified.
Answer to general questions
-
Resolve
(factor, x, y)
into(x, y)
.- Resolved
x
= first value that is notnone
in the list(x, factor, 100%)
. - Resolved
y
= first value that is notnone
in the list(y, factor, 100%)
.
Here
factor, x, y
can beauto | length | ratio
. - Resolved
-
Convert
auto | length | ratio
toratio
.length
→ratio
: As explained in row 2,length ↦ length / min(available-size, content-size)
.auto
→ratio
: Use the ratio in the other axis, keeping the aspect ratio.ratio
is relative tocontent-size
.