https://github.com/akkartik/mu/blob/main/509bezier.mu
1
2
3
4
5
6
7
8
9
10
11
12
13
14 fn draw-monotonic-bezier screen: (addr screen), x0: int, y0: int, x1: int, y1: int, x2: int, y2: int, color: int {
15 var xx: int
16 var yy: int
17 var xy: int
18 var sx: int
19 var sy: int
20
21 var tmp/eax: int <- copy x2
22 tmp <- subtract x1
23 copy-to sx, tmp
24
25 tmp <- copy y2
26 tmp <- subtract y1
27 copy-to sy, tmp
28
29 tmp <- copy x0
30 tmp <- subtract x1
31 copy-to xx, tmp
32
33 tmp <- copy y0
34 tmp <- subtract y1
35 copy-to yy, tmp
36
37 var cur-f/xmm4: float <- convert xx
38 {
39 var sy-f/xmm1: float <- convert sy
40 cur-f <- multiply sy-f
41 var tmp2-f/xmm1: float <- convert yy
42 var sx-f/xmm2: float <- convert sx
43 tmp2-f <- multiply sx-f
44 cur-f <- subtract tmp2-f
45 }
46
47 {
48 tmp <- copy xx
49 tmp <- multiply sx
50 compare tmp, 0
51 break-if-<=
52 abort "bezier: gradient of x changes sign"
53 }
54
55 {
56 tmp <- copy yy
57 tmp <- multiply sy
58 compare tmp, 0
59 break-if-<=
60 abort "bezier: gradient of y changes sign"
61 }
62
63 {
64
65 var dist1/ecx: int <- copy sx
66 {
67 dist1 <- multiply sx
68 {
69 break-if-not-overflow
70 abort "bezier: overflow 1"
71 }
72 tmp <- copy sy
73 tmp <- multiply sy
74 {
75 break-if-not-overflow
76 abort "bezier: overflow 2"
77 }
78 dist1 <- add tmp
79 }
80
81 var dist2/edx: int <- copy xx
82 {
83 dist2 <- multiply xx
84 {
85 break-if-not-overflow
86 abort "bezier: overflow 3"
87 }
88 tmp <- copy yy
89 tmp <- multiply yy
90 {
91 break-if-not-overflow
92 abort "bezier: overflow 4"
93 }
94 dist2 <- add tmp
95 }
96
97 compare dist1, dist2
98 break-if-<=
99
100 tmp <- copy x0
101 copy-to x2, tmp
102 tmp <- copy sx
103 tmp <- add x1
104 copy-to x0, tmp
105
106 tmp <- copy y0
107 copy-to y2, tmp
108 tmp <- copy sy
109 tmp <- add y1
110 copy-to y0, tmp
111
112 var negative-1/eax: int <- copy -1
113 var negative-1-f/xmm1: float <- convert negative-1
114 cur-f <- multiply negative-1-f
115 }
116 var x/ecx: int <- copy x0
117 var y/edx: int <- copy y0
118 var zero-f: float
119
120 $draw-monotonic-bezier:curve: {
121 compare cur-f, zero-f
122 break-if-=
123
124 tmp <- copy sx
125 add-to xx, tmp
126
127 tmp <- copy x2
128 tmp <- subtract x
129 tmp <- sgn tmp
130 copy-to sx, tmp
131
132 tmp <- copy sx
133 tmp <- multiply xx
134 copy-to xx, tmp
135
136 tmp <- copy sy
137 add-to yy, tmp
138
139 tmp <- copy y2
140 tmp <- subtract y
141 tmp <- sgn tmp
142 copy-to sy, tmp
143
144 tmp <- copy sy
145 tmp <- multiply yy
146 copy-to yy, tmp
147
148 tmp <- copy xx
149 tmp <- multiply yy
150 {
151 break-if-not-overflow
152 abort "bezier: overflow 5"
153 }
154 tmp <- shift-left 1
155 {
156 break-if-not-overflow
157 abort "bezier: overflow 6"
158 }
159 copy-to xy, tmp
160
161 tmp <- copy xx
162 tmp <- multiply tmp
163 {
164 break-if-not-overflow
165 abort "bezier: overflow 7"
166 }
167 copy-to xx, tmp
168
169 tmp <- copy yy
170 tmp <- multiply tmp
171 {
172 break-if-not-overflow
173 abort "bezier: overflow 7"
174 }
175 copy-to yy, tmp
176
177 {
178 var tmp-f/xmm0: float <- copy cur-f
179 var sx-f/xmm1: float <- convert sx
180 tmp-f <- multiply sx-f
181 var sy-f/xmm1: float <- convert sy
182 tmp-f <- multiply sy-f
183 compare tmp-f, zero-f
184 break-if-float>=
185
186 negate xx
187 negate yy
188 negate xy
189
190 var negative-1/eax: int <- copy -1
191 var negative-1-f/xmm1: float <- convert negative-1
192 cur-f <- multiply negative-1-f
193 }
194 var four/ebx: int <- copy 4
195 var dx-f/xmm5: float <- convert four
196 var dy-f/xmm6: float <- convert four
197
198 {
199 var tmp/xmm0: float <- convert sy
200 dx-f <- multiply tmp
201 dx-f <- multiply cur-f
202 tmp <- convert x1
203 var tmp2/xmm3: float <- convert x
204 tmp <- subtract tmp2
205 dx-f <- multiply tmp
206 tmp <- convert xx
207 dx-f <- add tmp
208 tmp <- convert xy
209 dx-f <- subtract tmp
210 }
211
212 {
213 var tmp/xmm0: float <- convert sx
214 dy-f <- multiply tmp
215 dy-f <- multiply cur-f
216 tmp <- convert y
217 var tmp2/xmm3: float <- convert y1
218 tmp <- subtract tmp2
219 dy-f <- multiply tmp
220 tmp <- convert yy
221 dy-f <- add tmp
222 tmp <- convert xy
223 dy-f <- subtract tmp
224 }
225
226 tmp <- copy xx
227 add-to xx, tmp
228
229 tmp <- copy yy
230 add-to yy, tmp
231
232 var err-f/xmm7: float <- copy dx-f
233 err-f <- add dy-f
234 var xy-f/xmm0: float <- convert xy
235 err-f <- add xy-f
236
237 $draw-monotonic-bezier:loop: {
238 pixel screen, x, y, color
239
240 {
241 compare x, x2
242 break-if-!=
243 compare y, y2
244 break-if-!=
245 return
246 }
247
248 var perform-y-step?/eax: boolean <- copy 0/false
249 var two-err-f/xmm0: float <- copy err-f
250 {
251 var two/ebx: int <- copy 2
252 var two-f/xmm1: float <- convert two
253 two-err-f <- multiply two-f
254 compare two-err-f, dx-f
255 break-if-float>=
256 perform-y-step? <- copy 1/true
257 }
258
259 {
260 compare two-err-f, dy-f
261 break-if-float<=
262
263 x <- add sx
264
265 var xy-f/xmm0: float <- convert xy
266 dx-f <- subtract xy-f
267
268 var yy-f/xmm0: float <- convert yy
269 dy-f <- add yy-f
270
271 err-f <- add dy-f
272 }
273
274 {
275 compare perform-y-step?, 0/false
276 break-if-=
277
278 y <- add sy
279
280 var xy-f/xmm0: float <- convert xy
281 dy-f <- subtract xy-f
282
283 var xx-f/xmm0: float <- convert xx
284 dx-f <- add xx-f
285
286 err-f <- add dx-f
287 }
288
289 compare dy-f, dx-f
290 loop-if-float<
291 }
292 }
293
294 draw-line screen, x y, x2 y2, color
295 }
296
297
298 fn bezier-point u: float, x0: int, x1: int, x2: int -> _/eax: int {
299 var one/eax: int <- copy 1
300 var u-prime/xmm0: float <- convert one
301 u-prime <- subtract u
302 var result/xmm1: float <- convert x0
303 result <- multiply u-prime
304 result <- multiply u-prime
305 var term2/xmm2: float <- convert x1
306 term2 <- multiply u
307 term2 <- multiply u-prime
308 result <- add term2
309 result <- add term2
310 var term3/xmm2: float <- convert x2
311 term3 <- multiply u
312 term3 <- multiply u
313 result <- add term3
314 var result/eax: int <- convert result
315 return result
316 }