When cetz v0.4.2 calculates border anchors for cetz.draw.content, it changes text.bottom-edge and increases the effective line spacing, resulting in an additional bottom padding if the content is multi-line.
|
// Compute the baseline offset |
|
let (_, line-baseline-height) = util.measure(ctx, text(top-edge: "cap-height", bottom-edge: "baseline", |
|
[ #show linebreak: [ ]; #body])) |
|
let (_, line-bounds-height) = util.measure(ctx, text(top-edge: "cap-height", bottom-edge: "bounds", |
|
[ #show linebreak: [ ]; #body])) |
|
let baseline-offset = line-bounds-height - line-baseline-height |
|
|
|
// Size of the bounding box |
|
let (content-width, content-height, ..) = if auto-size { |
|
util.measure(ctx, text(top-edge: "cap-height", bottom-edge: "baseline", body)) |
|
} else { |
|
vector.sub(b, a) |
|
} |
Minimal example
In the following example, the height of the green border line is expected to equal to the height of the aqua block, but it isn't.
#import "@preview/cetz:0.4.2"
#cetz.canvas({
import cetz.draw: *
content((0, 0), name: "a", block(
width: 6em,
fill: aqua.lighten(50%),
lorem(10),
))
line(
"a.north-west",
"a.north-east",
"a.south-east",
"a.south-west",
close: true,
stroke: green,
)
})
Links and comparisons
#894 is a similar issue. #956 (first appeared in v0.4.2) has fixed that issue, but not this one.
The difference is that linebreaks in #894 are inserted manually, but here they're inserted automatically (by putting contents in a fixed-width block).
Therefore, the #show linebreak: [ ] hack used by #956 is not helpful.
In the minimal example above, changing a.south-{west,east} to a.base-{west,east} would draw the correct border line.
However, there exist certain cases that base-{west,east} are not applicable.
For instance, when drawing a chat bubble, you may want the lower-left corner of the whole group, including a triangle and a cetz.draw.content. This point locates at (x: group.triangle.west.x, y: group.content.base-west.y). If cetz had measured correctly, then this can be simplified as group.south-west.
Workaround
Set text.{top,bottom}-edge explicitly and control spacing on your own.
#import "@preview/cetz:0.4.2"
#cetz.canvas({
import cetz.draw: *
content((0, 0), name: "a", block(
width: 6em,
fill: aqua.lighten(50%),
{
// 👇 Edit here
set text(top-edge: "cap-height", bottom-edge: "baseline")
v(0.5em) // or use `block.inset`
lorem(10)
v(0.5em)
},
))
line(
"a.north-west",
"a.north-east",
"a.base-east",
"a.base-west",
close: true,
stroke: green,
)
})

When cetz v0.4.2 calculates border anchors for
cetz.draw.content, it changestext.bottom-edgeand increases the effective line spacing, resulting in an additional bottom padding if the content is multi-line.cetz/src/draw/shapes.typ
Lines 1143 to 1155 in 0459295
Minimal example
In the following example, the height of the green border
lineis expected to equal to the height of the aquablock, but it isn't.Links and comparisons
#894 is a similar issue. #956 (first appeared in v0.4.2) has fixed that issue, but not this one.
The difference is that linebreaks in #894 are inserted manually, but here they're inserted automatically (by putting contents in a fixed-width
block).Therefore, the
#show linebreak: [ ]hack used by #956 is not helpful.In the minimal example above, changing
a.south-{west,east}toa.base-{west,east}would draw the correct borderline.However, there exist certain cases that
base-{west,east}are not applicable.For instance, when drawing a chat bubble, you may want the lower-left corner of the whole group, including a triangle and a
cetz.draw.content. This point locates at(x: group.triangle.west.x, y: group.content.base-west.y). If cetz had measured correctly, then this can be simplified asgroup.south-west.Workaround
Set
text.{top,bottom}-edgeexplicitly and control spacing on your own.