|
46 | 46 | transform: |
47 | 47 | ((1, 0,-.5, 0), |
48 | 48 | (0,-1,+.5, 0), |
49 | | - (0, 0, .0, 0), |
| 49 | + (0, 0, 0, 0), // FIXME: This should not be zero for Z! Changing it destroys mark & decorations in 3D space. |
50 | 50 | (0, 0, .0, 1)), |
51 | 51 | // Nodes, stores anchors and paths |
52 | 52 | nodes: (:), |
|
76 | 76 | let padding = util.as-padding-dict(padding) |
77 | 77 | bounds = aabb.padded(bounds, padding) |
78 | 78 |
|
| 79 | + let (offset-x, offset-y, ..) = bounds.low |
| 80 | + |
79 | 81 | // Final canvas size |
80 | 82 | let (width, height, ..) = vector.scale(aabb.size(bounds), length) |
81 | 83 |
|
|
87 | 89 | for drawable in drawables { |
88 | 90 | // Typst path elements have strange bounding boxes. We need to |
89 | 91 | // offset all paths to start at (0, 0) to make gradients work. |
90 | | - let (x, y, _) = if drawable.type == "path" { |
| 92 | + let (segment-x, segment-y, _) = if drawable.type == "path" { |
91 | 93 | vector.sub( |
92 | 94 | aabb.aabb(path-util.bounds(drawable.segments)).low, |
93 | 95 | bounds.low) |
|
97 | 99 |
|
98 | 100 | place(top + left, float: false, if drawable.type == "path" { |
99 | 101 | let vertices = () |
100 | | - for ((kind, ..pts)) in drawable.segments { |
101 | | - pts = pts.map(c => { |
102 | | - ((c.at(0) - bounds.low.at(0) - x) * length, |
103 | | - (c.at(1) - bounds.low.at(1) - y) * length) |
104 | | - }) |
105 | | - assert( |
106 | | - kind in ("line", "cubic"), |
107 | | - message: "Path segments must be of type line, cubic") |
108 | | - |
109 | | - if kind == "cubic" { |
110 | | - let a = pts.at(0) |
111 | | - let b = pts.at(1) |
112 | | - let ctrla = relative(a, pts.at(2)) |
113 | | - let ctrlb = relative(b, pts.at(3)) |
114 | | - |
115 | | - vertices.push((a, (0pt, 0pt), ctrla)) |
116 | | - vertices.push((b, ctrlb, (0pt, 0pt))) |
| 102 | + |
| 103 | + let transform-point((x, y, _)) = { |
| 104 | + ((x - offset-x - segment-x) * length, |
| 105 | + (y - offset-y - segment-y) * length) |
| 106 | + } |
| 107 | + |
| 108 | + for ((kind, ..rest)) in drawable.segments { |
| 109 | + if kind == "sub" { |
| 110 | + // TODO: Support sub-paths by converting |
| 111 | + // Also support move commands. |
| 112 | + // Refactor path arrays to typst style curves. |
| 113 | + } else if kind == "cubic" { |
| 114 | + let pts = rest.map(transform-point) |
| 115 | + |
| 116 | + vertices.push(curve.move(pts.at(0))) |
| 117 | + vertices.push(curve.cubic(pts.at(2), pts.at(3), pts.at(1))) |
117 | 118 | } else { |
118 | | - vertices += pts |
| 119 | + let pts = rest.map(transform-point) |
| 120 | + |
| 121 | + vertices.push(curve.move(pts.at(0))) |
| 122 | + for i in range(1, pts.len()) { |
| 123 | + vertices.push(curve.line(pts.at(i))) |
| 124 | + } |
119 | 125 | } |
120 | 126 | } |
| 127 | + |
| 128 | + if (drawable.at("close", default: false)) { |
| 129 | + vertices.push(curve.close(mode: "straight")) |
| 130 | + } |
| 131 | + |
121 | 132 | if type(drawable.stroke) == dictionary and "thickness" in drawable.stroke and type(drawable.stroke.thickness) != std.length { |
122 | 133 | drawable.stroke.thickness *= length |
123 | 134 | } |
124 | | - path( |
| 135 | + std.curve( |
125 | 136 | stroke: drawable.stroke, |
126 | 137 | fill: drawable.fill, |
127 | 138 | fill-rule: drawable.at("fill-rule", default: "non-zero"), |
128 | | - closed: drawable.at("close", default: false), |
129 | 139 | ..vertices, |
130 | 140 | ) |
131 | 141 | } else if drawable.type == "content" { |
132 | 142 | let (width, height) = std.measure(drawable.body) |
133 | 143 | move( |
134 | | - dx: (drawable.pos.at(0) - bounds.low.at(0)) * length - width / 2, |
135 | | - dy: (drawable.pos.at(1) - bounds.low.at(1)) * length - height / 2, |
| 144 | + dx: (drawable.pos.at(0) - offset-x) * length - width / 2, |
| 145 | + dy: (drawable.pos.at(1) - offset-y) * length - height / 2, |
136 | 146 | drawable.body, |
137 | 147 | ) |
138 | | - }, dx: x * length, dy: y * length) |
| 148 | + }, dx: segment-x * length, dy: segment-y * length) |
139 | 149 | } |
140 | 150 | })) |
141 | 151 | })} |
0 commit comments