Skip to content

Commit d14797a

Browse files
committed
canvas: Support custom coordinate systems
1 parent 57a73be commit d14797a

File tree

8 files changed

+46
-47
lines changed

8 files changed

+46
-47
lines changed

src/canvas.typ

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,9 @@
5757
marks: (
5858
mnemonics: (:),
5959
marks: (:),
60-
)
60+
),
61+
// coordinate resolver
62+
resolve-coordinate: none,
6163
)
6264

6365
let (ctx, bounds, drawables) = process.many(ctx, body)

src/coordinate.typ

Lines changed: 13 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -251,7 +251,7 @@
251251
/// Figures out what system a coordinate belongs to and returns the corresponding string.
252252
/// - c (coordinate): The coordinate to find the system of.
253253
/// -> str
254-
#let resolve-system(c) = {
254+
#let resolve-system(ctx, c) = {
255255
let t = if type(c) == dictionary {
256256
let keys = c.keys()
257257
let len = c.len()
@@ -294,6 +294,9 @@
294294
} else {
295295
"element"
296296
}
297+
} else if ctx.at("resolve-system", default: none) != none {
298+
ctx.resolve-system = none
299+
resolve-system(ctx, c)
297300
}
298301

299302
if t == none {
@@ -319,9 +322,16 @@
319322
/// - update (bool): Update the context's last position
320323
/// -> array
321324
#let resolve(ctx, ..coordinates, update: true) = {
325+
let ctx-resolver = ctx.at("resolve-coordinate", default: none)
326+
let coordinates = if ctx-resolver != none {
327+
coordinates.pos().map(ctx-resolver.with(ctx))
328+
} else {
329+
coordinates.pos()
330+
}
331+
322332
let result = ()
323-
for c in coordinates.pos() {
324-
let t = resolve-system(c)
333+
for c in coordinates {
334+
let t = resolve-system(ctx, c)
325335
let out = if t == "xyz" {
326336
resolve-xyz(c)
327337
} else if t == "previous" {

src/draw/grouping.typ

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -368,7 +368,6 @@
368368
assert(name != none and name != "" and not name.starts-with("."),
369369
message: "Anchors must not be none, \"\" or start with \".\"!")
370370

371-
coordinate.resolve-system(position)
372371
return (ctx => {
373372
let (ctx, position) = coordinate.resolve(ctx, position)
374373
position = util.apply-transform(ctx.transform, position)

src/draw/shapes.typ

Lines changed: 1 addition & 32 deletions
Original file line numberDiff line numberDiff line change
@@ -116,8 +116,6 @@
116116
assert.eq(style.pos(), (), message: "Unexpected positional arguments: " + repr(style.pos()))
117117
style = style.named()
118118

119-
(a, b, c).map(coordinate.resolve-system)
120-
121119
return (ctx => {
122120
let (ctx, a, b, c) = coordinate.resolve(ctx, a, b, c)
123121

@@ -220,9 +218,6 @@
220218
)
221219
let style = style.named()
222220

223-
// Coordinate check
224-
let t = coordinate.resolve-system(position)
225-
226221
let start-angle = if start == auto { stop - delta } else { start }
227222
let stop-angle = if stop == auto { start + delta } else { stop }
228223
// Border angles can break if the angle is 0.
@@ -445,8 +440,6 @@
445440
to = ((rel: (to, 1), to: from))
446441
}
447442

448-
(from, to).map(coordinate.resolve-system)
449-
450443
return (ctx => {
451444
let (ctx, ..pts) = coordinate.resolve(ctx, from, to)
452445
let style = styles.resolve(ctx.style, merge: style, root: "mark")
@@ -506,9 +499,6 @@
506499

507500
assert(pts.len() >= 2, message: "Line must have a minimum of two points")
508501

509-
// Coordinate check
510-
let pts-system = pts.map(coordinate.resolve-system)
511-
512502
// Find the intersection between line a-b next to b
513503
// if no intersection could be found, return a.
514504
let element-line-intersection(ctx, elem, a, b) = {
@@ -534,6 +524,7 @@
534524
return (ctx => {
535525
let first-elem = pts.first()
536526
let last-elem = pts.last()
527+
let pts-system = pts.map(coordinate.resolve-system.with(ctx))
537528
let (ctx, ..pts) = coordinate.resolve(ctx, ..pts)
538529

539530
// If the first/last element, test for intersection
@@ -610,8 +601,6 @@
610601
/// ## Anchors
611602
/// Supports border anchors.
612603
#let grid(from, to, name: none, ..style) = {
613-
(from, to).map(coordinate.resolve-system)
614-
615604
assert.eq(style.pos(), (), message: "Unexpected positional arguments: " + repr(style.pos()))
616605
style = style.named()
617606

@@ -770,16 +759,6 @@
770759
panic("Expected 2 or 3 positional arguments, got " + str(args.len()))
771760
}
772761

773-
coordinate.resolve-system(a)
774-
775-
if b != auto {
776-
coordinate.resolve-system(b)
777-
}
778-
779-
if type(angle) != typst-angle {
780-
coordinate.resolve-system(angle)
781-
}
782-
783762
return (ctx => {
784763
let style = styles.resolve(ctx.style, merge: style, root: "content")
785764
let padding = util.as-padding-dict(style.padding)
@@ -1016,9 +995,6 @@
1016995
/// Supports border and path anchors. It's default is the `"center"` anchor.
1017996
///
1018997
#let rect(a, b, name: none, anchor: none, ..style) = {
1019-
// Coordinate check
1020-
let t = (a, b).map(coordinate.resolve-system)
1021-
1022998
// No extra positional arguments from the style sink
1023999
assert.eq(
10241000
style.pos(),
@@ -1208,9 +1184,6 @@
12081184
)
12091185
let coordinates = (start, ..ctrl, end)
12101186

1211-
// Coordinates check
1212-
let t = coordinates.map(coordinate.resolve-system)
1213-
12141187
return (
12151188
ctx => {
12161189
let (ctx, start, ..ctrl, end) = coordinate.resolve(ctx, ..coordinates)
@@ -1310,8 +1283,6 @@
13101283

13111284
assert(pts.len() >= 2, message: "Catmull-rom curve requires at least two points. Got " + repr(pts.len()) + "instead.")
13121285

1313-
pts.map(coordinate.resolve-system)
1314-
13151286
return (ctx => {
13161287
let (ctx, ..pts) = coordinate.resolve(ctx, ..pts)
13171288
let style = styles.resolve(ctx.style, merge: style, root: "catmull")
@@ -1385,8 +1356,6 @@
13851356

13861357
assert(pts.len() >= 2, message: "Hobby curve requires at least two points. Got " + repr(pts.len()) + "instead.")
13871358

1388-
pts.map(coordinate.resolve-system)
1389-
13901359
return (ctx => {
13911360
let (ctx, ..pts) = coordinate.resolve(ctx, ..pts)
13921361
let style = styles.resolve(ctx.style, merge: style, root: "hobby")

src/draw/transformations.typ

Lines changed: 0 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -223,8 +223,6 @@
223223
///
224224
/// - pt (coordinate): The coordinate to move to.
225225
#let move-to(pt) = {
226-
let t = coordinate.resolve-system(pt)
227-
228226
return (ctx => {
229227
let (ctx, pt) = coordinate.resolve(ctx, pt)
230228
return (ctx: ctx)
@@ -244,8 +242,6 @@
244242
/// - bounds (vector): Viewport bounds vector that describes the inner width,
245243
/// height and depth of the viewport
246244
#let set-viewport(from, to, bounds: (1, 1, 1)) = {
247-
(from, to).map(coordinate.resolve-system)
248-
249245
return (ctx => {
250246
let bounds = vector.as-vec(bounds, init: (1, 1, 1))
251247

src/lib/decorations/brace.typ

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -62,9 +62,6 @@
6262
assert.eq(style.pos().len(), 0,
6363
message: "Brace takes no additional positional arugments.")
6464

65-
// Validate coordinates
66-
let _ = (start, end).map(coordinate.resolve-system)
67-
6865
group(name: name, ctx => {
6966
// Resolve all coordinates
7067
let (ctx, start, end) = coordinate.resolve(ctx, start, end)
@@ -195,9 +192,6 @@
195192
name: none,
196193
..style,
197194
) = {
198-
// Validate coordinates
199-
let _ = (start, end).map(coordinate.resolve-system)
200-
201195
group(name: name, ctx => {
202196
// Get styles and validate their types and values
203197
let style = styles.resolve(ctx.style, merge: style.named(),

tests/coordinate/custom/ref/1.png

6 KB
Loading

tests/coordinate/custom/test.typ

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
#set page(width: auto, height: auto)
2+
#import "/src/lib.typ": *
3+
#import "/tests/helper.typ": *
4+
5+
#test-case({
6+
import draw: *
7+
grid((-2,-1), (7,1), stroke: gray)
8+
9+
let log-resolver(ctx, coordinate) = {
10+
if type(coordinate) == dictionary and "log" in coordinate {
11+
coordinate = coordinate.log
12+
coordinate = coordinate.map(n => calc.log(calc.max(n, util.float-epsilon), base: 10))
13+
}
14+
15+
return coordinate
16+
}
17+
18+
set-ctx(ctx => {
19+
ctx.resolve-coordinate = log-resolver
20+
return ctx
21+
})
22+
23+
set-style(circle: (radius: .1))
24+
for i in (.1, 1, 10, 100, 1000, 10000) {
25+
let pt = (log: (i * 1, 1))
26+
circle(pt)
27+
content(pt, repr(i), anchor: "north", padding: (top: .5))
28+
}
29+
})

0 commit comments

Comments
 (0)