1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16 package raster
17
18 import (
19 "strconv"
20
21 "golang.org/x/image/math/fixed"
22 )
23
24
25
26 type cell struct {
27 xi int
28 area, cover int
29 next int
30 }
31
32 type Rasterizer struct {
33
34
35 UseNonZeroWinding bool
36
37 Dx, Dy int
38
39
40 width int
41
42
43 splitScale2, splitScale3 int
44
45
46 a fixed.Point26_6
47
48 xi, yi int
49 area, cover int
50
51
52 cell []cell
53
54 cellIndex []int
55
56 cellBuf [256]cell
57 cellIndexBuf [64]int
58 spanBuf [64]Span
59 }
60
61
62
63 func (r *Rasterizer) findCell() int {
64 if r.yi < 0 || r.yi >= len(r.cellIndex) {
65 return -1
66 }
67 xi := r.xi
68 if xi < 0 {
69 xi = -1
70 } else if xi > r.width {
71 xi = r.width
72 }
73 i, prev := r.cellIndex[r.yi], -1
74 for i != -1 && r.cell[i].xi <= xi {
75 if r.cell[i].xi == xi {
76 return i
77 }
78 i, prev = r.cell[i].next, i
79 }
80 c := len(r.cell)
81 if c == cap(r.cell) {
82 buf := make([]cell, c, 4*c)
83 copy(buf, r.cell)
84 r.cell = buf[0 : c+1]
85 } else {
86 r.cell = r.cell[0 : c+1]
87 }
88 r.cell[c] = cell{xi, 0, 0, i}
89 if prev == -1 {
90 r.cellIndex[r.yi] = c
91 } else {
92 r.cell[prev].next = c
93 }
94 return c
95 }
96
97
98 func (r *Rasterizer) saveCell() {
99 if r.area != 0 || r.cover != 0 {
100 i := r.findCell()
101 if i != -1 {
102 r.cell[i].area += r.area
103 r.cell[i].cover += r.cover
104 }
105 r.area = 0
106 r.cover = 0
107 }
108 }
109
110
111 func (r *Rasterizer) setCell(xi, yi int) {
112 if r.xi != xi || r.yi != yi {
113 r.saveCell()
114 r.xi, r.yi = xi, yi
115 }
116 }
117
118
119
120
121 func (r *Rasterizer) scan(yi int, x0, y0f, x1, y1f fixed.Int26_6) {
122
123 x0i := int(x0) / 64
124 x0f := x0 - fixed.Int26_6(64*x0i)
125 x1i := int(x1) / 64
126 x1f := x1 - fixed.Int26_6(64*x1i)
127
128
129 if y0f == y1f {
130 r.setCell(x1i, yi)
131 return
132 }
133 dx, dy := x1-x0, y1f-y0f
134
135 if x0i == x1i {
136 r.area += int((x0f + x1f) * dy)
137 r.cover += int(dy)
138 return
139 }
140
141
142
143 var (
144 p, q, edge0, edge1 fixed.Int26_6
145 xiDelta int
146 )
147 if dx > 0 {
148 p, q = (64-x0f)*dy, dx
149 edge0, edge1, xiDelta = 0, 64, 1
150 } else {
151 p, q = x0f*dy, -dx
152 edge0, edge1, xiDelta = 64, 0, -1
153 }
154 yDelta, yRem := p/q, p%q
155 if yRem < 0 {
156 yDelta -= 1
157 yRem += q
158 }
159
160 xi, y := x0i, y0f
161 r.area += int((x0f + edge1) * yDelta)
162 r.cover += int(yDelta)
163 xi, y = xi+xiDelta, y+yDelta
164 r.setCell(xi, yi)
165 if xi != x1i {
166
167 p = 64 * (y1f - y + yDelta)
168 fullDelta, fullRem := p/q, p%q
169 if fullRem < 0 {
170 fullDelta -= 1
171 fullRem += q
172 }
173 yRem -= q
174 for xi != x1i {
175 yDelta = fullDelta
176 yRem += fullRem
177 if yRem >= 0 {
178 yDelta += 1
179 yRem -= q
180 }
181 r.area += int(64 * yDelta)
182 r.cover += int(yDelta)
183 xi, y = xi+xiDelta, y+yDelta
184 r.setCell(xi, yi)
185 }
186 }
187
188 yDelta = y1f - y
189 r.area += int((edge0 + x1f) * yDelta)
190 r.cover += int(yDelta)
191 }
192
193
194 func (r *Rasterizer) Start(a fixed.Point26_6) {
195 r.setCell(int(a.X/64), int(a.Y/64))
196 r.a = a
197 }
198
199
200 func (r *Rasterizer) Add1(b fixed.Point26_6) {
201 x0, y0 := r.a.X, r.a.Y
202 x1, y1 := b.X, b.Y
203 dx, dy := x1-x0, y1-y0
204
205
206 y0i := int(y0) / 64
207 y0f := y0 - fixed.Int26_6(64*y0i)
208 y1i := int(y1) / 64
209 y1f := y1 - fixed.Int26_6(64*y1i)
210
211 if y0i == y1i {
212
213 r.scan(y0i, x0, y0f, x1, y1f)
214
215 } else if dx == 0 {
216
217
218 var (
219 edge0, edge1 fixed.Int26_6
220 yiDelta int
221 )
222 if dy > 0 {
223 edge0, edge1, yiDelta = 0, 64, 1
224 } else {
225 edge0, edge1, yiDelta = 64, 0, -1
226 }
227 x0i, yi := int(x0)/64, y0i
228 x0fTimes2 := (int(x0) - (64 * x0i)) * 2
229
230 dcover := int(edge1 - y0f)
231 darea := int(x0fTimes2 * dcover)
232 r.area += darea
233 r.cover += dcover
234 yi += yiDelta
235 r.setCell(x0i, yi)
236
237 dcover = int(edge1 - edge0)
238 darea = int(x0fTimes2 * dcover)
239 for yi != y1i {
240 r.area += darea
241 r.cover += dcover
242 yi += yiDelta
243 r.setCell(x0i, yi)
244 }
245
246 dcover = int(y1f - edge0)
247 darea = int(x0fTimes2 * dcover)
248 r.area += darea
249 r.cover += dcover
250
251 } else {
252
253
254
255 var (
256 p, q, edge0, edge1 fixed.Int26_6
257 yiDelta int
258 )
259 if dy > 0 {
260 p, q = (64-y0f)*dx, dy
261 edge0, edge1, yiDelta = 0, 64, 1
262 } else {
263 p, q = y0f*dx, -dy
264 edge0, edge1, yiDelta = 64, 0, -1
265 }
266 xDelta, xRem := p/q, p%q
267 if xRem < 0 {
268 xDelta -= 1
269 xRem += q
270 }
271
272 x, yi := x0, y0i
273 r.scan(yi, x, y0f, x+xDelta, edge1)
274 x, yi = x+xDelta, yi+yiDelta
275 r.setCell(int(x)/64, yi)
276 if yi != y1i {
277
278 p = 64 * dx
279 fullDelta, fullRem := p/q, p%q
280 if fullRem < 0 {
281 fullDelta -= 1
282 fullRem += q
283 }
284 xRem -= q
285 for yi != y1i {
286 xDelta = fullDelta
287 xRem += fullRem
288 if xRem >= 0 {
289 xDelta += 1
290 xRem -= q
291 }
292 r.scan(yi, x, edge0, x+xDelta, edge1)
293 x, yi = x+xDelta, yi+yiDelta
294 r.setCell(int(x)/64, yi)
295 }
296 }
297
298 r.scan(yi, x, edge0, x1, y1f)
299 }
300
301 r.a = b
302 }
303
304
305 func (r *Rasterizer) Add2(b, c fixed.Point26_6) {
306
307
308
309 dev := maxAbs(r.a.X-2*b.X+c.X, r.a.Y-2*b.Y+c.Y) / fixed.Int26_6(r.splitScale2)
310 nsplit := 0
311 for dev > 0 {
312 dev /= 4
313 nsplit++
314 }
315
316
317 const maxNsplit = 16
318 if nsplit > maxNsplit {
319 panic("freetype/raster: Add2 nsplit too large: " + strconv.Itoa(nsplit))
320 }
321
322 var (
323 pStack [2*maxNsplit + 3]fixed.Point26_6
324 sStack [maxNsplit + 1]int
325 i int
326 )
327 sStack[0] = nsplit
328 pStack[0] = c
329 pStack[1] = b
330 pStack[2] = r.a
331 for i >= 0 {
332 s := sStack[i]
333 p := pStack[2*i:]
334 if s > 0 {
335
336
337
338 mx := p[1].X
339 p[4].X = p[2].X
340 p[3].X = (p[4].X + mx) / 2
341 p[1].X = (p[0].X + mx) / 2
342 p[2].X = (p[1].X + p[3].X) / 2
343 my := p[1].Y
344 p[4].Y = p[2].Y
345 p[3].Y = (p[4].Y + my) / 2
346 p[1].Y = (p[0].Y + my) / 2
347 p[2].Y = (p[1].Y + p[3].Y) / 2
348
349 sStack[i] = s - 1
350 sStack[i+1] = s - 1
351 i++
352 } else {
353
354
355 midx := (p[0].X + 2*p[1].X + p[2].X) / 4
356 midy := (p[0].Y + 2*p[1].Y + p[2].Y) / 4
357 r.Add1(fixed.Point26_6{midx, midy})
358 r.Add1(p[0])
359 i--
360 }
361 }
362 }
363
364
365 func (r *Rasterizer) Add3(b, c, d fixed.Point26_6) {
366
367
368 dev2 := maxAbs(r.a.X-3*(b.X+c.X)+d.X, r.a.Y-3*(b.Y+c.Y)+d.Y) / fixed.Int26_6(r.splitScale2)
369 dev3 := maxAbs(r.a.X-2*b.X+d.X, r.a.Y-2*b.Y+d.Y) / fixed.Int26_6(r.splitScale3)
370 nsplit := 0
371 for dev2 > 0 || dev3 > 0 {
372 dev2 /= 8
373 dev3 /= 4
374 nsplit++
375 }
376
377
378 const maxNsplit = 16
379 if nsplit > maxNsplit {
380 panic("freetype/raster: Add3 nsplit too large: " + strconv.Itoa(nsplit))
381 }
382
383 var (
384 pStack [3*maxNsplit + 4]fixed.Point26_6
385 sStack [maxNsplit + 1]int
386 i int
387 )
388 sStack[0] = nsplit
389 pStack[0] = d
390 pStack[1] = c
391 pStack[2] = b
392 pStack[3] = r.a
393 for i >= 0 {
394 s := sStack[i]
395 p := pStack[3*i:]
396 if s > 0 {
397
398
399
400 m01x := (p[0].X + p[1].X) / 2
401 m12x := (p[1].X + p[2].X) / 2
402 m23x := (p[2].X + p[3].X) / 2
403 p[6].X = p[3].X
404 p[5].X = m23x
405 p[1].X = m01x
406 p[2].X = (m01x + m12x) / 2
407 p[4].X = (m12x + m23x) / 2
408 p[3].X = (p[2].X + p[4].X) / 2
409 m01y := (p[0].Y + p[1].Y) / 2
410 m12y := (p[1].Y + p[2].Y) / 2
411 m23y := (p[2].Y + p[3].Y) / 2
412 p[6].Y = p[3].Y
413 p[5].Y = m23y
414 p[1].Y = m01y
415 p[2].Y = (m01y + m12y) / 2
416 p[4].Y = (m12y + m23y) / 2
417 p[3].Y = (p[2].Y + p[4].Y) / 2
418
419 sStack[i] = s - 1
420 sStack[i+1] = s - 1
421 i++
422 } else {
423
424 midx := (p[0].X + 3*(p[1].X+p[2].X) + p[3].X) / 8
425 midy := (p[0].Y + 3*(p[1].Y+p[2].Y) + p[3].Y) / 8
426 r.Add1(fixed.Point26_6{midx, midy})
427 r.Add1(p[0])
428 i--
429 }
430 }
431 }
432
433
434 func (r *Rasterizer) AddPath(p Path) {
435 for i := 0; i < len(p); {
436 switch p[i] {
437 case 0:
438 r.Start(
439 fixed.Point26_6{p[i+1], p[i+2]},
440 )
441 i += 4
442 case 1:
443 r.Add1(
444 fixed.Point26_6{p[i+1], p[i+2]},
445 )
446 i += 4
447 case 2:
448 r.Add2(
449 fixed.Point26_6{p[i+1], p[i+2]},
450 fixed.Point26_6{p[i+3], p[i+4]},
451 )
452 i += 6
453 case 3:
454 r.Add3(
455 fixed.Point26_6{p[i+1], p[i+2]},
456 fixed.Point26_6{p[i+3], p[i+4]},
457 fixed.Point26_6{p[i+5], p[i+6]},
458 )
459 i += 8
460 default:
461 panic("freetype/raster: bad path")
462 }
463 }
464 }
465
466
467 func (r *Rasterizer) AddStroke(q Path, width fixed.Int26_6, cr Capper, jr Joiner) {
468 Stroke(r, q, width, cr, jr)
469 }
470
471
472
473
474
475 func (r *Rasterizer) areaToAlpha(area int) uint32 {
476
477
478
479
480 a := (area + 1) >> 1
481 if a < 0 {
482 a = -a
483 }
484 alpha := uint32(a)
485 if r.UseNonZeroWinding {
486 if alpha > 0x0fff {
487 alpha = 0x0fff
488 }
489 } else {
490 alpha &= 0x1fff
491 if alpha > 0x1000 {
492 alpha = 0x2000 - alpha
493 } else if alpha == 0x1000 {
494 alpha = 0x0fff
495 }
496 }
497
498
499 return alpha<<4 | alpha>>8
500 }
501
502
503
504
505
506 func (r *Rasterizer) Rasterize(p Painter) {
507 r.saveCell()
508 s := 0
509 for yi := 0; yi < len(r.cellIndex); yi++ {
510 xi, cover := 0, 0
511 for c := r.cellIndex[yi]; c != -1; c = r.cell[c].next {
512 if cover != 0 && r.cell[c].xi > xi {
513 alpha := r.areaToAlpha(cover * 64 * 2)
514 if alpha != 0 {
515 xi0, xi1 := xi, r.cell[c].xi
516 if xi0 < 0 {
517 xi0 = 0
518 }
519 if xi1 >= r.width {
520 xi1 = r.width
521 }
522 if xi0 < xi1 {
523 r.spanBuf[s] = Span{yi + r.Dy, xi0 + r.Dx, xi1 + r.Dx, alpha}
524 s++
525 }
526 }
527 }
528 cover += r.cell[c].cover
529 alpha := r.areaToAlpha(cover*64*2 - r.cell[c].area)
530 xi = r.cell[c].xi + 1
531 if alpha != 0 {
532 xi0, xi1 := r.cell[c].xi, xi
533 if xi0 < 0 {
534 xi0 = 0
535 }
536 if xi1 >= r.width {
537 xi1 = r.width
538 }
539 if xi0 < xi1 {
540 r.spanBuf[s] = Span{yi + r.Dy, xi0 + r.Dx, xi1 + r.Dx, alpha}
541 s++
542 }
543 }
544 if s > len(r.spanBuf)-2 {
545 p.Paint(r.spanBuf[:s], false)
546 s = 0
547 }
548 }
549 }
550 p.Paint(r.spanBuf[:s], true)
551 }
552
553
554 func (r *Rasterizer) Clear() {
555 r.a = fixed.Point26_6{}
556 r.xi = 0
557 r.yi = 0
558 r.area = 0
559 r.cover = 0
560 r.cell = r.cell[:0]
561 for i := 0; i < len(r.cellIndex); i++ {
562 r.cellIndex[i] = -1
563 }
564 }
565
566
567
568 func (r *Rasterizer) SetBounds(width, height int) {
569 if width < 0 {
570 width = 0
571 }
572 if height < 0 {
573 height = 0
574 }
575
576
577 ss2, ss3 := 32, 16
578 if width > 24 || height > 24 {
579 ss2, ss3 = 2*ss2, 2*ss3
580 if width > 120 || height > 120 {
581 ss2, ss3 = 2*ss2, 2*ss3
582 }
583 }
584 r.width = width
585 r.splitScale2 = ss2
586 r.splitScale3 = ss3
587 r.cell = r.cellBuf[:0]
588 if height > len(r.cellIndexBuf) {
589 r.cellIndex = make([]int, height)
590 } else {
591 r.cellIndex = r.cellIndexBuf[:height]
592 }
593 r.Clear()
594 }
595
596
597 func NewRasterizer(width, height int) *Rasterizer {
598 r := new(Rasterizer)
599 r.SetBounds(width, height)
600 return r
601 }
602
View as plain text