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

Content Baseline Anchors #684

Merged
merged 6 commits into from
Sep 6, 2024
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
2 changes: 2 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,8 @@ package called `cetz-plot`.
- **BREAKING** The winding order of _all_ elements has been changed to CCW.
- You can now add custom marks via `register-mark`.
- Mark anchor (tip, base, center) calcuation got fixed.
- Content border anchors for `text` now default to the texts bounds.
- Content emit new anchors for accessing the baseline of the content.

## Draw
- Added `floating` function for drawing elements without affecting bounding boxes.
Expand Down
99 changes: 70 additions & 29 deletions src/draw/shapes.typ
Original file line number Diff line number Diff line change
Expand Up @@ -735,7 +735,14 @@
/// - frame (str, none) = none: Sets the frame style. Can be `none`, "rect" or "circle" and inherits the `stroke` and `fill` style.
///
/// ## Anchors
/// Supports border anchors.
/// Supports border anchors, the default anchor is set to **center**.
/// - **mid**: Content center, from baseline to top bounds
/// - **mid-east**: Content center extended to the east
/// - **mid-west**: Content center extended to the west
/// - **base**: Horizontally centered baseline of the content
/// - **base-east**: Baseline height extended to the east
/// - **base-west**: Baseline height extended to the west
/// - **text**: Position at the content start on the baseline of the content
fenjalien marked this conversation as resolved.
Show resolved Hide resolved
#let content(
..args-style,
angle: 0deg,
Expand Down Expand Up @@ -788,47 +795,84 @@
// Typst's `rotate` function is clockwise relative to x-axis, which is backwards from us
angle = angle * -1

// Height from the baseline to content-north
let (content-width, baseline-height) = util.measure(ctx, text(top-edge: "bounds", bottom-edge: "baseline", body))

// Size of the bounding box
let (width, height, ..) = if auto-size {
util.measure(ctx, body)
util.measure(ctx, text(top-edge: "bounds", bottom-edge: "bounds", body))
} else {
vector.sub(b, a)
}

width = (calc.abs(width)
+ padding.at("left", default: 0)
+ padding.at("right", default: 0))
height = (calc.abs(height)
+ padding.at("top", default: 0)
+ padding.at("bottom", default: 0))
let bounds-width = calc.abs(width)
let bounds-height = calc.abs(height)
baseline-height = bounds-height - baseline-height

width = bounds-width + padding.left + padding.right
height = bounds-height + padding.top + padding.bottom

let anchors = {
let w = width/2
let h = height/2
let center = if auto-size {
let w = width / 2
let h = height / 2
let bh = (baseline-height - padding.top - padding.bottom) / 2

let bounds-center = if auto-size {
a
} else {
vector.lerp(a, b, .5)
}

// Only the center anchor gets transformed. All other anchors
// must be calculated relative to the transformed center!
center = matrix.mul4x4-vec3(ctx.transform,
vector.as-vec(center, init: (0,0,0)))
bounds-center = matrix.mul4x4-vec3(ctx.transform,
vector.as-vec(bounds-center, init: (0,0,0)))

let east-dir = vector.rotate-z((1, 0, 0), angle)
let north-dir = vector.rotate-z((-1, 0, 0), angle + 90deg)
let east-scaled = vector.scale(east-dir, +w)
let west-scaled = vector.scale(east-dir, -w)
let north-scaled = vector.scale(north-dir, +h)
let south-scaled = vector.scale(north-dir, -h)

let north = vector.add(bounds-center, north-scaled)
let south = vector.add(bounds-center, south-scaled)
let east = vector.add(bounds-center, east-scaled)
let west = vector.add(bounds-center, west-scaled)
let north-east = vector.add(bounds-center, vector.add(north-scaled, east-scaled))
let north-west = vector.sub(bounds-center, vector.add(south-scaled, east-scaled))
let south-east = vector.add(bounds-center, vector.add(south-scaled, east-scaled))
let south-west = vector.sub(bounds-center, vector.add(north-scaled, east-scaled))

let base = vector.add(south,
vector.scale(north-dir, padding.bottom + baseline-height))
let mid = vector.lerp(
vector.sub(north, vector.scale(north-dir, padding.top)),
base,
0.5)
let base-east = vector.add(base, east-scaled)
let base-west = vector.add(base, west-scaled)
let text = vector.add(base, vector.scale(east-dir, -content-width / 2))
let mid-east = vector.add(mid, east-scaled)
let mid-west = vector.add(mid, west-scaled)

let north = (calc.sin(angle)*h, -calc.cos(angle)*h,0)
let east = (calc.cos(-angle)*w, -calc.sin(-angle)*w,0)
let south = vector.scale(north, -1)
let west = vector.scale(east, -1)
(
center: center,
north: vector.add(center, north),
north-east: vector.add(center, vector.add(north, east)),
east: vector.add(center, east),
south-east: vector.add(center, vector.add(south, east)),
south: vector.add(center, south),
south-west: vector.add(center, vector.add(south, west)),
west: vector.add(center, west),
north-west: vector.add(center, vector.add(north, west)),
center: bounds-center,
mid: mid,
mid-east: mid-east,
mid-west: mid-west,
base: base,
base-east: base-east,
base-west: base-west,
text: text,
north: north,
north-east: north-east,
north-west: north-west,
south: south,
south-east: south-east,
south-west: south-west,
east: east,
west: west,
)
}

Expand Down Expand Up @@ -858,9 +902,6 @@
(anchors.north-west, anchors.north-east,
anchors.south-west, anchors.south-east)))

let corners = (anchors.north-east, anchors.north-west,
anchors.south-west, anchors.south-east)

let drawables = ()
if style.frame != none {
drawables.push(border)
Expand Down
Binary file modified tests/anchor/element-anchors/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/angle/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/angle/right-angle/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/bezier/shorten/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/content/anchor/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
13 changes: 11 additions & 2 deletions tests/content/anchor/test.typ
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,17 @@
#import "/tests/helper.typ": *
#import draw: content, rotate, scale, translate

#for a in ("center", "north", "south", "east", "west", "north-east", "north-west", "south-east", "south-west") {
#test-case({
import draw: *
content((0, 0), text(size: 40pt)[Yogurt], padding: (rest: 1, top: 2), frame: "rect", name: "content")
line("content.base-west", "content.base-east", stroke: green)
for-each-anchor("content", name => {
content((), text(size: 6pt)[#name], frame: "rect",
fill: white, stroke: none)
})
})

#for a in ("center", "north", "south", "east", "west", "north-east", "north-west", "south-east", "south-west", "mid", "base") {
test-case({
cross((0,0))
content((0,0), [#a], anchor: a)
Expand All @@ -28,5 +38,4 @@
cross((0,0))
content((0,0), [#a (scale)], anchor: a)
})
[\ ]
}
Binary file modified tests/content/intersection/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/content/padding/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/content/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/content/rotate/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/content/rtl/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/content/transform/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/floating/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/group/nested-anchor/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/group/transform/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/group/translate/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/hide/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/image/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/intersection/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/layer/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/line/element-element/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/projection/ortho/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/relative-length/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/set-get-ctx/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/translation/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/tree/ref/1.png
Loading
Sorry, something went wrong. Reload?
Sorry, we cannot display this file.
Sorry, this file is invalid so it cannot be displayed.
Binary file modified tests/viewport/ref/1.png
Loading