Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
4349 | Serge | 1 | |
2 | |||
3 | |||
4 | |||
5 | |||
6 | |||
7 | |||
8 | |||
9 | rasterizer. The rasterizer is of quite general purpose and could |
||
10 | easily be integrated into other programs. |
||
11 | |||
12 | |||
13 | |||
14 | |||
15 | |||
16 | 1. Requirements |
||
17 | 2. Profiles and Spans |
||
18 | a. Sweeping the Shape |
||
19 | b. Decomposing Outlines into Profiles |
||
20 | c. The Render Pool |
||
21 | d. Computing Profiles Extents |
||
22 | e. Computing Profiles Coordinates |
||
23 | f. Sweeping and Sorting the Spans |
||
24 | |||
25 | |||
26 | |||
27 | =============== |
||
28 | |||
29 | |||
30 | representation of a shape into a bitmap. The FreeType rasterizer |
||
31 | has been originally developed to render the glyphs found in |
||
32 | TrueType files, made up of segments and second-order Béziers. |
||
33 | Meanwhile it has been extended to render third-order Bézier curves |
||
34 | also. This document is an explanation of its design and |
||
35 | implementation. |
||
36 | |||
37 | |||
38 | common rasterization techniques is assumed. |
||
39 | |||
40 | |||
41 | |||
42 | ======================== |
||
43 | |||
44 | |||
45 | --------------- |
||
46 | |||
47 | |||
48 | already done. The glyph is thus described by a list of points in |
||
49 | the device space. |
||
50 | |||
51 | |||
52 | used orientation is: |
||
53 | |||
54 | |||
55 | |||
56 | | reference orientation |
||
57 | | |
||
58 | *----> x |
||
59 | 0 |
||
60 | |||
61 | |||
62 | |||
63 | value and 6 bits are used for the fractional part. |
||
64 | Consequently, the `distance' between two neighbouring pixels is |
||
65 | 64 `units' (1 unit = 1/64th of a pixel). |
||
66 | |||
67 | |||
68 | integer coordinates. The TrueType bytecode interpreter, |
||
69 | however, assumes that the lower left edge of a pixel (which is |
||
70 | taken to be a square with a length of 1 unit) has integer |
||
71 | coordinates. |
||
72 | |||
73 | |||
74 | |||
75 | | | |
||
76 | | (1,1) | (0.5,0.5) |
||
77 | +-----------+ +-----+-----+ |
||
78 | | | | | | |
||
79 | | | | | | |
||
80 | | | | o-----+-----> x |
||
81 | | | | (0,0) | |
||
82 | | | | | |
||
83 | o-----------+-----> x +-----------+ |
||
84 | (0,0) (-0.5,-0.5) |
||
85 | |||
86 | |||
87 | |||
88 | |||
89 | |||
90 | |||
91 | |||
92 | `outlines'. A contour is simply a closed curve that delimits an |
||
93 | outer or inner region of the glyph. It is described by a series |
||
94 | of successive points of the points table. |
||
95 | |||
96 | |||
97 | whether it is `on' or `off' the curve. Two successive `on' |
||
98 | points indicate a line segment joining the two points. |
||
99 | |||
100 | |||
101 | (conic) Bézier parametric arc, defined by these three points |
||
102 | (the `off' point being the control point, and the `on' ones the |
||
103 | start and end points). Similarly, a third-degree (cubic) Bézier |
||
104 | curve is described by four points (two `off' control points |
||
105 | between two `on' points). |
||
106 | |||
107 | |||
108 | points forces the rasterizer to create, during rendering, an |
||
109 | `on' point amidst them, at their exact middle. This greatly |
||
110 | facilitates the definition of successive Bézier arcs. |
||
111 | |||
112 | |||
113 | |||
114 | |||
115 | |||
116 | |||
117 | |||
118 | |||
119 | |||
120 | |||
121 | |||
122 | |||
123 | |||
124 | |||
125 | |||
126 | |||
127 | They exhibit, however, one very useful property of Bézier arcs: |
||
128 | Each point of the curve is a weighted average of the control |
||
129 | points. |
||
130 | |||
131 | |||
132 | value of t, each arc point lies within the triangle (polygon) |
||
133 | defined by the arc's three (four) control points. |
||
134 | |||
135 | |||
136 | rasterization of third-order curves is completely identical. |
||
137 | |||
138 | |||
139 | |||
140 | |||
141 | |||
142 | * off curve |
||
143 | __---__ |
||
144 | #-__ _-- -_ |
||
145 | --__ _- - |
||
146 | --__ # \ |
||
147 | --__ # |
||
148 | -# |
||
149 | Two `on' points |
||
150 | Two `on' points and one `off' point |
||
151 | between them |
||
152 | |||
153 | |||
154 | # __ Two `on' points with two `off' |
||
155 | \ - - points between them. The point |
||
156 | \ / \ marked `0' is the middle of the |
||
157 | - 0 \ `off' points, and is a `virtual |
||
158 | -_ _- # on' point where the curve passes. |
||
159 | -- It does not appear in the point |
||
160 | * list. |
||
161 | |||
162 | |||
163 | |||
164 | --------------------- |
||
165 | |||
166 | |||
167 | made by the rasterizer to build a bitmap from a vector |
||
168 | representation. Note that the actual implementation is slightly |
||
169 | different, due to performance tuning and other factors. |
||
170 | |||
171 | |||
172 | more convenient to understand. |
||
173 | |||
174 | |||
175 | |||
176 | |||
177 | |||
178 | simple horizontal segments, then turn them on in the target |
||
179 | bitmap. These segments are called `spans'. |
||
180 | |||
181 | |||
182 | _-- -_ |
||
183 | _- - |
||
184 | - \ |
||
185 | / \ |
||
186 | / \ |
||
187 | | \ |
||
188 | |||
189 | |||
190 | _----------_ with spans. |
||
191 | _-------------- |
||
192 | ----------------\ |
||
193 | /-----------------\ This is typically done from the top |
||
194 | / \ to the bottom of the shape, in a |
||
195 | | | \ movement called a `sweep'. |
||
196 | V |
||
197 | |||
198 | |||
199 | _----------_ |
||
200 | _-------------- |
||
201 | ----------------\ |
||
202 | /-----------------\ |
||
203 | /-------------------\ |
||
204 | |---------------------\ |
||
205 | |||
206 | |||
207 | |||
208 | coordinates, which are simply the x coordinates of the shape's |
||
209 | contours, taken on the y scanlines. |
||
210 | |||
211 | |||
212 | |||
213 | /---/ |---| several spans per scanline. |
||
214 | | /---/ |---| |
||
215 | | /---/_______|---| When rendering this shape to the |
||
216 | V /----------------| current scanline y, we must |
||
217 | /-----------------| compute the x values of the |
||
218 | a /----| |---| points a, b, c, and d. |
||
219 | - - - * * - - - - * * - - y - |
||
220 | / / b c| |d |
||
221 | |||
222 | |||
223 | |||
224 | /---/ |---| And then turn on the spans a-b |
||
225 | /---/ |---| and c-d. |
||
226 | /---/_______|---| |
||
227 | /----------------| |
||
228 | /-----------------| |
||
229 | a /----| |---| |
||
230 | - - - ####### - - - - ##### - - y - |
||
231 | / / b c| |d |
||
232 | |||
233 | |||
234 | |||
235 | |||
236 | |||
237 | information: |
||
238 | |||
239 | |||
240 | number of shape points intersecting the scanline (these are |
||
241 | the points a, b, c, and d in the above example). |
||
242 | |||
243 | |||
244 | |||
245 | |||
246 | `decomposition' which converts the glyph into *profiles*. |
||
247 | |||
248 | |||
249 | be either ascending or descending, i.e., it is monotonic in the |
||
250 | vertical direction (we also say y-monotonic). There is no such |
||
251 | thing as a horizontal profile, as we shall see. |
||
252 | |||
253 | |||
254 | |||
255 | |||
256 | |||
257 | 1 2 |
||
258 | ---->---- is made of two |
||
259 | | | | | |
||
260 | | | profiles | | |
||
261 | ^ v ^ + v |
||
262 | | | | | |
||
263 | | | | | |
||
264 | ----<---- |
||
265 | |||
266 | |||
267 | |||
268 | |||
269 | |||
270 | |||
271 | |||
272 | |||
273 | |||
274 | ^ | \ \ | \ |
||
275 | | | \ \ profiles | \ | |
||
276 | | | \ v ^ | \ | |
||
277 | | \ | | + \ v |
||
278 | | \ | | \ |
||
279 | P1 ---___ \ ---___ \ |
||
280 | ---_\ ---_ \ |
||
281 | <--__ P3 up down |
||
282 | |||
283 | |||
284 | |||
285 | |||
286 | |||
287 | |||
288 | / | / ___ / | |
||
289 | / | / | / | / | |
||
290 | | | / / => | v / / |
||
291 | | | | | | | ^ | |
||
292 | ^ | |___| | | ^ + | + | + v |
||
293 | | | | v | | |
||
294 | | | | up | |
||
295 | |___________| | down | |
||
296 | |||
297 | |||
298 | |||
299 | |||
300 | |||
301 | that are not part of the profiles themselves. |
||
302 | |||
303 | |||
304 | associates one horizontal *pixel* coordinate to each bitmap |
||
305 | *scanline* crossed by the contour's section containing the |
||
306 | profile. Note that profiles are *oriented* up or down along the |
||
307 | glyph's original flow orientation. |
||
308 | |||
309 | |||
310 | `edgelists'. |
||
311 | |||
312 | |||
313 | |||
314 | |||
315 | |||
316 | light systems, including embedded systems with very few memory. |
||
317 | |||
318 | |||
319 | pool for all its needs by managing this memory directly in it. |
||
320 | The algorithms that are used for profile computation make it |
||
321 | possible to use the pool as a simple growing heap. This means |
||
322 | that this memory management is actually quite easy and faster |
||
323 | than any kind of malloc()/free() combination. |
||
324 | |||
325 | |||
326 | dealing with profiles too large and numerous to lie all at once |
||
327 | in the render pool, to immediately decompose recursively the |
||
328 | rendering process into independent sub-tasks, each taking less |
||
329 | memory to be performed (see `sub-banding' below). |
||
330 | |||
331 | |||
332 | enough for nearly all renditions, though nearly 100% slower than |
||
333 | a more comfortable 16KByte or 32KByte pool (that was tested with |
||
334 | complex glyphs at sizes over 500 pixels). |
||
335 | |||
336 | |||
337 | |||
338 | |||
339 | |||
340 | the x pixel coordinate of its intersection with a contour. |
||
341 | |||
342 | |||
343 | convenient to think that we need a profile's height before |
||
344 | allocating it in the pool and computing its coordinates. |
||
345 | |||
346 | |||
347 | y-monotonic section of a contour. We thus need to compute these |
||
348 | sections from the vectorial description. In order to do that, |
||
349 | we are obliged to compute all (local and global) y extrema of |
||
350 | the glyph (minima and maxima). |
||
351 | |||
352 | |||
353 | |||
354 | two y-extrema, which are simply |
||
355 | |\ |
||
356 | | \ P2.y as a vertical maximum |
||
357 | | \ P3.y as a vertical minimum |
||
358 | | \ |
||
359 | | \ P1.y is not a vertical extremum (though |
||
360 | | \ it is a horizontal minimum, which we |
||
361 | P1 ---___ \ don't need). |
||
362 | ---_\ |
||
363 | P3 |
||
364 | |||
365 | |||
366 | |||
367 | scanlines. The triangle's height is certainly (P3.y-P2.y+1) |
||
368 | pixel units, but its profiles' heights are computed in |
||
369 | scanlines. The exact conversion is simple: |
||
370 | |||
371 | |||
372 | - max scanline = CEILING( max y ) |
||
373 | |||
374 | |||
375 | necessarily y-monotonic (i.e., flat, ascending, or descending), |
||
376 | which makes extrema computations easy, the ascent of an arc can |
||
377 | vary between its control points. |
||
378 | |||
379 | |||
380 | |||
381 | * |
||
382 | # on curve |
||
383 | * off curve |
||
384 | __-x--_ |
||
385 | _-- -_ |
||
386 | P1 _- - A non y-monotonic Bézier arc. |
||
387 | # \ |
||
388 | - The arc goes from P1 to P3. |
||
389 | \ |
||
390 | \ P3 |
||
391 | # |
||
392 | |||
393 | |||
394 | |||
395 | according to their control points. I will state here, without |
||
396 | proof, that the monotony condition can be expressed as: |
||
397 | |||
398 | |||
399 | |||
400 | |||
401 | |||
402 | |||
403 | |||
404 | |||
405 | |||
406 | |||
407 | They are, however, extremely important, as any arc that does not |
||
408 | satisfy them necessarily contains an extremum. |
||
409 | |||
410 | |||
411 | which is then one of its `on' points: |
||
412 | |||
413 | |||
414 | |||
415 | #---__ * P1P2P3 is ever-descending, but P1 |
||
416 | -_ is an y-extremum. |
||
417 | - |
||
418 | ---_ \ |
||
419 | -> \ |
||
420 | \ P3 |
||
421 | # |
||
422 | |||
423 | |||
424 | |||
425 | |||
426 | |||
427 | |||
428 | * |
||
429 | # on curve |
||
430 | * off curve |
||
431 | __-x--_ |
||
432 | _-- -_ |
||
433 | P1 _- - A non-y-monotonic Bézier arc. |
||
434 | # \ |
||
435 | - Here we have |
||
436 | \ P2.y >= P1.y && |
||
437 | \ P3 P2.y >= P3.y (!) |
||
438 | # |
||
439 | |||
440 | |||
441 | |||
442 | to compute a profile's height (the point marked by an `x'). The |
||
443 | arc's equation indicates that a direct computation is possible, |
||
444 | but we rely on a different technique, which use will become |
||
445 | apparent soon. |
||
446 | |||
447 | |||
448 | decomposed into two sub-arcs, which are themselves Bézier arcs. |
||
449 | Moreover, it is easy to prove that there is at most one vertical |
||
450 | extremum on each Bézier arc (for second-degree curves; similar |
||
451 | conditions can be found for third-order arcs). |
||
452 | |||
453 | |||
454 | two sub-arcs Q1Q2Q3 and R1R2R3: |
||
455 | |||
456 | |||
457 | |||
458 | * |
||
459 | # on curve |
||
460 | * off curve |
||
461 | |||
462 | |||
463 | |||
464 | __---__ |
||
465 | _-- --_ |
||
466 | _- -_ |
||
467 | - - |
||
468 | / \ |
||
469 | / \ |
||
470 | # # |
||
471 | P1 P3 |
||
472 | |||
473 | |||
474 | |||
475 | |||
476 | * |
||
477 | |||
478 | |||
479 | |||
480 | |||
481 | Q2 R2 Q1Q2Q3 and R1R2R3 |
||
482 | * __-#-__ * |
||
483 | _-- --_ |
||
484 | _- R1 -_ Q1 = P1 R3 = P3 |
||
485 | - - Q2 = (P1+P2)/2 R2 = (P2+P3)/2 |
||
486 | / \ |
||
487 | / \ Q3 = R1 = (Q2+R2)/2 |
||
488 | # # |
||
489 | Q1 R3 Note that Q2, R2, and Q3=R1 |
||
490 | are on a single line which is |
||
491 | tangent to the curve. |
||
492 | |||
493 | |||
494 | |||
495 | smaller sub-arcs. Note that in the above drawing, both sub-arcs |
||
496 | are monotonic, and that the extremum is then Q3=R1. However, in |
||
497 | a more general case, only one sub-arc is guaranteed to be |
||
498 | monotonic. Getting back to our former example: |
||
499 | |||
500 | |||
501 | |||
502 | * |
||
503 | |||
504 | |||
505 | _-- #_ |
||
506 | Q1 _- Q3 - R2 |
||
507 | # \ * |
||
508 | - |
||
509 | \ |
||
510 | \ R3 |
||
511 | # |
||
512 | |||
513 | |||
514 | |||
515 | is ever descending: We thus know that it doesn't contain the |
||
516 | extremum. We can then re-subdivide Q1Q2Q3 into two sub-arcs and |
||
517 | go on recursively, stopping when we encounter two monotonic |
||
518 | subarcs, or when the subarcs become simply too small. |
||
519 | |||
520 | |||
521 | iterative process of finding an extremum is called `flattening'. |
||
522 | |||
523 | |||
524 | |||
525 | |||
526 | |||
527 | it in the render pool. The next task is to compute coordinates |
||
528 | for each scanline. |
||
529 | |||
530 | |||
531 | using the Euclidean algorithm (also known as Bresenham). |
||
532 | However, for Bézier arcs, the job is a little more complicated. |
||
533 | |||
534 | |||
535 | result of flattening the curve, which means that they are all |
||
536 | y-monotonic (ascending or descending, and never flat). We now |
||
537 | have to compute the intersections of arcs with the profile's |
||
538 | scanlines. One way is to use a similar scheme to flattening |
||
539 | called `stepping'. |
||
540 | |||
541 | |||
542 | |||
543 | --------------------- P3. Suppose that we need to |
||
544 | compute its intersections with the |
||
545 | drawn scanlines. As already |
||
546 | --------------------- mentioned this can be done |
||
547 | directly, but the involved |
||
548 | * P2 _---# P3 algorithm is far too slow. |
||
549 | ------------- _-- -- |
||
550 | _- |
||
551 | _/ Instead, it is still possible to |
||
552 | ---------/----------- use the decomposition property in |
||
553 | / the same recursive way, i.e., |
||
554 | | subdivide the arc into subarcs |
||
555 | ------|-------------- until these get too small to cross |
||
556 | | more than one scanline! |
||
557 | | |
||
558 | -----|--------------- This is very easily done using a |
||
559 | | rasterizer-managed stack of |
||
560 | | subarcs. |
||
561 | # P1 |
||
562 | |||
563 | |||
564 | |||
565 | |||
566 | |||
567 | build (and fill) the spans. |
||
568 | |||
569 | |||
570 | fill rule (but with opposite directions), we place, on each |
||
571 | scanline, the present profiles in two separate lists. |
||
572 | |||
573 | |||
574 | profiles, while the other `right' list contains the descending |
||
575 | profiles. |
||
576 | |||
577 | |||
578 | property ensures that the two lists contain the same number of |
||
579 | elements. |
||
580 | |||
581 | |||
582 | |||
583 | |||
584 | |||
585 | |||
586 | value in the right list. |
||
587 | |||
588 | |||
589 | |||
590 | / / | | four profiles. Two of |
||
591 | >/ / | | | them are ascending (1 & |
||
592 | 1// / ^ | | | 2 3), while the two others |
||
593 | // // 3| | | v are descending (2 & 4). |
||
594 | / //4 | | | On the given scanline, |
||
595 | a / /< | | the left list is (1,3), |
||
596 | - - - *-----* - - - - *---* - - y - and the right one is |
||
597 | / / b c| |d (4,2) (sorted). |
||
598 | |||
599 | |||
600 | 1 to 4 (i.e. a-b) and 3 to 2 |
||
601 | (i.e. c-d)! |
||
602 | |||
603 | |||
604 | |||
605 | of 100, the lists' order is kept from one scanline to the next. |
||
606 | We can thus implement it with two simple singly-linked lists, |
||
607 | sorted by a classic bubble-sort, which takes a minimum amount of |
||
608 | time when the lists are already sorted. |
||
609 | |||
610 | |||
611 | structures, like arrays to perform `faster' sorting. It turned |
||
612 | out that this old scheme is not faster than the one described |
||
613 | above. |
||
614 | |||
615 | |||
616 | the target bitmap. |
||
617 | |||
618 | |||
619 | |||
620 | |||
621 | David Turner, Robert Wilhelm, and Werner Lemberg. |
||
622 | |||
623 | |||
624 | modified, and distributed under the terms of the FreeType project |
||
625 | license, LICENSE.TXT. By continuing to use, modify, or distribute this |
||
626 | file you indicate that you have read the license and understand and |
||
627 | accept it fully. |
||
628 | |||
629 | |||
630 | |||
631 | |||
632 | |||
633 | coding: utf-8 |
||
634 | End:>=>=>-->--__>---- |
||
635 |