alice-in-metamorpov/spiral.typ

84 lines
1.8 KiB
Plaintext

#let spiral-text(
input-text,
small-size,
large-size,
start-angle,
end-angle,
offset-from-center: 0,
font: "Inter",
weight: "regular",
color: black,
stroke: none,
face-inward: false,
use-variable-spacing: true,
) = context {
let num-chars = input-text.len()
let char-offset = 0.1rad
let scale = 10pt
let rot-total = end-angle - start-angle
let rot-step = rot-total / (num-chars - 1)
let points = ()
// Find the rotation and radius for each letter
for i in range(num-chars) {
let progress = i / num-chars
let rot
if (points.len() == 0) {
rot = start-angle
}
else if (use-variable-spacing) {
let rot-step-mod = calc.sqrt(progress) + 1/3
let cur-rot-step = rot-step * rot-step-mod
rot = points.last().rot + cur-rot-step
}
else {
rot = start-angle + i * rot-step
}
let rad = rot + offset-from-center
points.push((rad: rad, rot: rot))
}
// Draw a letter at each point
for i in range(num-chars) {
let point = points.at(i)
let x = point.rad * calc.cos(point.rot)
let y = point.rad * calc.sin(point.rot)
let size = small-size + ((large-size - small-size) * (i / num-chars))
// Face inwards by default
let facing = calc.pi * 0.5rad
if not face-inward {
facing = -facing
}
let text-angle = point.rot * 1rad + facing
let char = input-text.at(i)
if not face-inward {
char = input-text.at(num-chars - i - 1)
}
[
#place(
center + horizon,
dx: scale * x,
dy: scale * y,
rotate(text-angle - char-offset, move(dy: measure(char).height)[
#set text(
font: font,
weight: weight,
size: size,
fill: color,
stroke: stroke
)
#smallcaps[#char]
])
)
]
}
}