84 lines
1.8 KiB
Plaintext
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]
|
|
])
|
|
)
|
|
]
|
|
}
|
|
} |