|
1 | 1 | #import "/src/path-util.typ"
|
2 | 2 |
|
3 | 3 | /// A path modifier is a function that accepts a contex, style and
|
4 |
| -/// a single drawable and returns a single (modified) drawable. |
| 4 | +/// a single drawable and returns either a single replacement drawable, |
| 5 | +/// or an dictionary with the keys `replacement` (single drawable) and `decoration` (list of drawables) |
| 6 | +/// that contain a replacement and/or additional drawable to render. |
| 7 | +/// |
| 8 | +/// Arguments: |
| 9 | +/// - ctx (context): |
| 10 | +/// - style (styles): |
| 11 | +/// - drawable (drawable): Single drawable to modify/decorate |
| 12 | +/// - close (bool): Boolean if the drawable is closed |
5 | 13 | ///
|
6 | 14 | /// Example:
|
7 | 15 | /// ```typ
|
8 |
| -/// (ctx, style, drawable) => { |
| 16 | +/// (ctx, style, drawable, close) => { |
9 | 17 | /// // ... modify the drawable ...
|
10 |
| -/// return drawable |
| 18 | +/// return (replacement: ..., decoration: ...) |
11 | 19 | /// }
|
12 | 20 | /// ```
|
13 | 21 |
|
|
48 | 56 | assert(type(fn) == function,
|
49 | 57 | message: "Path modifier must be of type function.")
|
50 | 58 |
|
| 59 | + let new-elements = () |
51 | 60 | if "segments" in elem {
|
52 | 61 | let begin = style.at("begin", default: 0%)
|
53 | 62 | let end = style.at("end", default: 0%)
|
54 | 63 |
|
55 | 64 | let (head, mid, tail) = slice-segments(elem.segments, begin, end)
|
56 | 65 | let close = close and head == () and tail == ()
|
57 |
| - elem.segments = head + (fn)(ctx, style, mid, close) + tail |
| 66 | + let result = (fn)(ctx, style, mid, close) |
| 67 | + if type(result) != dictionary { |
| 68 | + result = (replace: result) |
| 69 | + } else { |
| 70 | + new-elements += result.at("decoration", default: ()) |
| 71 | + } |
| 72 | + |
| 73 | + let replace = result.at("replacement", default: none) |
| 74 | + if replace != none { |
| 75 | + let replacement-elem = elem |
| 76 | + replacement-elem.segments = head + replace + tail |
| 77 | + |
| 78 | + new-elements.insert(0, replacement-elem) |
| 79 | + } else { |
| 80 | + let head-elem = elem |
| 81 | + head-elem.segments = head |
| 82 | + |
| 83 | + let tail-elem = elem |
| 84 | + tail-elem.segments = tail |
| 85 | + |
| 86 | + new-elements.insert(0, head-elem) |
| 87 | + new-elements.push(tail-elem) |
| 88 | + } |
58 | 89 | }
|
59 | 90 |
|
60 |
| - return elem |
| 91 | + return new-elements |
61 | 92 | }
|
62 | 93 |
|
63 | 94 | /// Apply a path modifier to a list of drawables
|
|
98 | 129 | style.modifier = ()
|
99 | 130 |
|
100 | 131 | // Apply function on all drawables
|
101 |
| - return drawables.map(d => { |
| 132 | + let new = () |
| 133 | + for i in range(0, drawables.len()) { |
102 | 134 | for fn in fns.filter(v => v.fn != none) {
|
103 |
| - d = apply-modifier-fn(ctx, fn.style, d, fn.fn, close) |
| 135 | + new += apply-modifier-fn(ctx, fn.style, drawables.at(i), fn.fn, close) |
104 | 136 | }
|
105 |
| - return d |
106 |
| - }) |
| 137 | + } |
| 138 | + |
| 139 | + return new |
107 | 140 | }
|
0 commit comments