zenilib: zenilib/jni/external/freetype2/src/raster/ftraster.c Source File

zenilib 0.5.3.0

- Main Page
- Modules
- Namespaces
- Classes
- Files

- File List
- File Members

All Classes Namespaces Files Functions Variables Typedefs Enumerations Enumerator Properties Friends Macros Groups Pages
ftraster.c
Go to the documentation of this file.
1 /***************************************************************************/
2 /* */
3 /* ftraster.c */
4 /* */
5 /* The FreeType glyph rasterizer (body). */
6 /* */
7 /* Copyright 1996-2003, 2005, 2007-2012 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
9 /* */
10 /* This file is part of the FreeType project, and may only be used, */
11 /* modified, and distributed under the terms of the FreeType project */
12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
13 /* this file you indicate that you have read the license and */
14 /* understand and accept it fully. */
15 /* */
16 /***************************************************************************/
17
18 /*************************************************************************/
19 /* */
20 /* This file can be compiled without the rest of the FreeType engine, by */
21 /* defining the _STANDALONE_ macro when compiling it. You also need to */
22 /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir) */
23 /* directory. Typically, you should do something like */
24 /* */
25 /* - copy `src/raster/ftraster.c' (this file) to your current directory */
26 /* */
27 /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' */
28 /* to your current directory */
29 /* */
30 /* - compile `ftraster' with the _STANDALONE_ macro defined, as in */
31 /* */
32 /* cc -c -D_STANDALONE_ ftraster.c */
33 /* */
34 /* The renderer can be initialized with a call to */
35 /* `ft_standard_raster.raster_new'; a bitmap can be generated */
36 /* with a call to `ft_standard_raster.raster_render'. */
37 /* */
38 /* See the comments and documentation in the file `ftimage.h' for more */
39 /* details on how the raster works. */
40 /* */
41 /*************************************************************************/
42
43
44 /*************************************************************************/
45 /* */
46 /* This is a rewrite of the FreeType 1.x scan-line converter */
47 /* */
48 /*************************************************************************/
49
50 #ifdef _STANDALONE_
51
52 #define FT_CONFIG_STANDARD_LIBRARY_H <stdlib.h>
53
54 #include <string.h> /* for memset */
55
56 #include "ftmisc.h"
57 #include "ftimage.h"
58
59 #else /* !_STANDALONE_ */
60
61 #include <ft2build.h>
62 #include "ftraster.h"
63 #include FT_INTERNAL_CALC_H /* for FT_MulDiv only */
64
65 #include "rastpic.h"
66
67 #endif /* !_STANDALONE_ */
68
69
70 /*************************************************************************/
71 /* */
72 /* A simple technical note on how the raster works */
73 /* ----------------------------------------------- */
74 /* */
75 /* Converting an outline into a bitmap is achieved in several steps: */
76 /* */
77 /* 1 - Decomposing the outline into successive `profiles'. Each */
78 /* profile is simply an array of scanline intersections on a given */
79 /* dimension. A profile's main attributes are */
80 /* */
81 /* o its scanline position boundaries, i.e. `Ymin' and `Ymax' */
82 /* */
83 /* o an array of intersection coordinates for each scanline */
84 /* between `Ymin' and `Ymax' */
85 /* */
86 /* o a direction, indicating whether it was built going `up' or */
87 /* `down', as this is very important for filling rules */
88 /* */
89 /* o its drop-out mode */
90 /* */
91 /* 2 - Sweeping the target map's scanlines in order to compute segment */
92 /* `spans' which are then filled. Additionally, this pass */
93 /* performs drop-out control. */
94 /* */
95 /* The outline data is parsed during step 1 only. The profiles are */
96 /* built from the bottom of the render pool, used as a stack. The */
97 /* following graphics shows the profile list under construction: */
98 /* */
99 /* __________________________________________________________ _ _ */
100 /* | | | | | */
101 /* | profile | coordinates for | profile | coordinates for |--> */
102 /* | 1 | profile 1 | 2 | profile 2 |--> */
103 /* |_________|_________________|_________|_________________|__ _ _ */
104 /* */
105 /* ^ ^ */
106 /* | | */
107 /* start of render pool top */
108 /* */
109 /* The top of the profile stack is kept in the `top' variable. */
110 /* */
111 /* As you can see, a profile record is pushed on top of the render */
112 /* pool, which is then followed by its coordinates/intersections. If */
113 /* a change of direction is detected in the outline, a new profile is */
114 /* generated until the end of the outline. */
115 /* */
116 /* Note that when all profiles have been generated, the function */
117 /* Finalize_Profile_Table() is used to record, for each profile, its */
118 /* bottom-most scanline as well as the scanline above its upmost */
119 /* boundary. These positions are called `y-turns' because they (sort */
120 /* of) correspond to local extrema. They are stored in a sorted list */
121 /* built from the top of the render pool as a downwards stack: */
122 /* */
123 /* _ _ _______________________________________ */
124 /* | | */
125 /* <--| sorted list of | */
126 /* <--| extrema scanlines | */
127 /* _ _ __________________|____________________| */
128 /* */
129 /* ^ ^ */
130 /* | | */
131 /* maxBuff sizeBuff = end of pool */
132 /* */
133 /* This list is later used during the sweep phase in order to */
134 /* optimize performance (see technical note on the sweep below). */
135 /* */
136 /* Of course, the raster detects whether the two stacks collide and */
137 /* handles the situation properly. */
138 /* */
139 /*************************************************************************/
140
141
142 /*************************************************************************/
143 /*************************************************************************/
147 /*************************************************************************/
148 /*************************************************************************/
149
150 /* define DEBUG_RASTER if you want to compile a debugging version */
151 /* #define DEBUG_RASTER */
152
153 /* define FT_RASTER_OPTION_ANTI_ALIASING if you want to support */
154 /* 5-levels anti-aliasing */
155 /* #define FT_RASTER_OPTION_ANTI_ALIASING */
156
157 /* The size of the two-lines intermediate bitmap used */
158 /* for anti-aliasing, in bytes. */
159 #define RASTER_GRAY_LINES 2048
160
161
162 /*************************************************************************/
163 /*************************************************************************/
167 /*************************************************************************/
168 /*************************************************************************/
169
170 /*************************************************************************/
171 /* */
172 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
173 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
174 /* messages during execution. */
175 /* */
176 #undef FT_COMPONENT
177 #define FT_COMPONENT trace_raster
178
179
180 #ifdef _STANDALONE_
181
182
183 /* This macro is used to indicate that a function parameter is unused. */
184 /* Its purpose is simply to reduce compiler warnings. Note also that */
185 /* simply defining it as `(void)x' doesn't avoid warnings with certain */
186 /* ANSI compilers (e.g. LCC). */
187 #define FT_UNUSED( x ) (x) = (x)
188
189 /* Disable the tracing mechanism for simplicity -- developers can */
190 /* activate it easily by redefining these two macros. */
191 #ifndef FT_ERROR
192 #define FT_ERROR( x ) do { } while ( 0 ) /* nothing */
193 #endif
194
195 #ifndef FT_TRACE
196 #define FT_TRACE( x ) do { } while ( 0 ) /* nothing */
197 #define FT_TRACE1( x ) do { } while ( 0 ) /* nothing */
198 #define FT_TRACE6( x ) do { } while ( 0 ) /* nothing */
199 #endif
200
201 #define Raster_Err_None 0
202 #define Raster_Err_Not_Ini -1
203 #define Raster_Err_Overflow -2
204 #define Raster_Err_Neg_Height -3
205 #define Raster_Err_Invalid -4
206 #define Raster_Err_Unsupported -5
207
208 #define ft_memset memset
209
210 #define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_, raster_new_, \
211 raster_reset_, raster_set_mode_, \
212 raster_render_, raster_done_ ) \
213 const FT_Raster_Funcs class_ = \
214 { \
215 glyph_format_, \
216 raster_new_, \
217 raster_reset_, \
218 raster_set_mode_, \
219 raster_render_, \
220 raster_done_ \
221 };
222
223 #else /* !_STANDALONE_ */
224
225
226 #include FT_INTERNAL_OBJECTS_H
227 #include FT_INTERNAL_DEBUG_H /* for FT_TRACE() and FT_ERROR() */
228
229 #include "rasterrs.h"
230
231 #define Raster_Err_None Raster_Err_Ok
232 #define Raster_Err_Not_Ini Raster_Err_Raster_Uninitialized
233 #define Raster_Err_Overflow Raster_Err_Raster_Overflow
234 #define Raster_Err_Neg_Height Raster_Err_Raster_Negative_Height
235 #define Raster_Err_Invalid Raster_Err_Invalid_Outline
236 #define Raster_Err_Unsupported Raster_Err_Cannot_Render_Glyph
237
238
239 #endif /* !_STANDALONE_ */
240
241
242 #ifndef FT_MEM_SET
243 #define FT_MEM_SET( d, s, c ) ft_memset( d, s, c )
244 #endif
245
246 #ifndef FT_MEM_ZERO
247 #define FT_MEM_ZERO( dest, count ) FT_MEM_SET( dest, 0, count )
248 #endif
249
250 /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is */
251 /* typically a small value and the result of a*b is known to fit into */
252 /* 32 bits. */
253 #define FMulDiv( a, b, c ) ( (a) * (b) / (c) )
254
255 /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
256 /* for clipping computations. It simply uses the FT_MulDiv() function */
257 /* defined in `ftcalc.h'. */
258 #define SMulDiv FT_MulDiv
259
260 /* The rasterizer is a very general purpose component; please leave */
261 /* the following redefinitions there (you never know your target */
262 /* environment). */
263
264 #ifndef TRUE
265 #define TRUE 1
266 #endif
267
268 #ifndef FALSE
269 #define FALSE 0
270 #endif
271
272 #ifndef NULL
273 #define NULL (void*)0
274 #endif
275
276 #ifndef SUCCESS
277 #define SUCCESS 0
278 #endif
279
280 #ifndef FAILURE
281 #define FAILURE 1
282 #endif
283
284
285 #define MaxBezier 32 /* The maximum number of stacked Bezier curves. */
286 /* Setting this constant to more than 32 is a */
287 /* pure waste of space. */
288
289 #define Pixel_Bits 6 /* fractional bits of *input* coordinates */
290
291
292 /*************************************************************************/
293 /*************************************************************************/
297 /*************************************************************************/
298 /*************************************************************************/
299
300 typedef int Int;
301 typedef unsigned int UInt;
302 typedef short Short;
303 typedef unsigned short UShort, *PUShort;
304 typedef long Long, *PLong;
305
306 typedef unsigned char Byte, *PByte;
307 typedef char Bool;
308
309
310 typedef union Alignment_
311 {
312 long l;
313 void* p;
314 void (*f)(void);
315
316 } Alignment, *PAlignment;
317
318
319 typedef struct TPoint_
320 {
321 Long x;
322 Long y;
323
324 } TPoint;
325
326
327 /* values for the `flags' bit field */
328 #define Flow_Up 0x8
329 #define Overshoot_Top 0x10
330 #define Overshoot_Bottom 0x20
331
332
333 /* States of each line, arc, and profile */
334 typedef enum TStates_
335 {
336 Unknown_State,
337 Ascending_State,
338 Descending_State,
339 Flat_State
340
341 } TStates;
342
343
344 typedef struct TProfile_ TProfile;
345 typedef TProfile* PProfile;
346
347 struct TProfile_
348 {
349 FT_F26Dot6 X; /* current coordinate during sweep */
350 PProfile link; /* link to next profile (various purposes) */
351 PLong offset; /* start of profile's data in render pool */
352 unsigned flags; /* Bit 0-2: drop-out mode */
353 /* Bit 3: profile orientation (up/down) */
354 /* Bit 4: is top profile? */
355 /* Bit 5: is bottom profile? */
356 long height; /* profile's height in scanlines */
357 long start; /* profile's starting scanline */
358
359 unsigned countL; /* number of lines to step before this */
360 /* profile becomes drawable */
361
362 PProfile next; /* next profile in same contour, used */
363 /* during drop-out control */
364 };
365
366 typedef PProfile TProfileList;
367 typedef PProfile* PProfileList;
368
369
370 /* Simple record used to implement a stack of bands, required */
371 /* by the sub-banding mechanism */
372 typedef struct black_TBand_
373 {
374 Short y_min; /* band's minimum */
375 Short y_max; /* band's maximum */
376
377 } black_TBand;
378
379
380 #define AlignProfileSize \
381 ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )
382
383
384 #undef RAS_ARG
385 #undef RAS_ARGS
386 #undef RAS_VAR
387 #undef RAS_VARS
388
389 #ifdef FT_STATIC_RASTER
390
391
392 #define RAS_ARGS /* void */
393 #define RAS_ARG /* void */
394
395 #define RAS_VARS /* void */
396 #define RAS_VAR /* void */
397
398 #define FT_UNUSED_RASTER do { } while ( 0 )
399
400
401 #else /* !FT_STATIC_RASTER */
402
403
404 #define RAS_ARGS black_PWorker worker,
405 #define RAS_ARG black_PWorker worker
406
407 #define RAS_VARS worker,
408 #define RAS_VAR worker
409
410 #define FT_UNUSED_RASTER FT_UNUSED( worker )
411
412
413 #endif /* !FT_STATIC_RASTER */
414
415
416 typedef struct black_TWorker_ black_TWorker, *black_PWorker;
417
418
419 /* prototypes used for sweep function dispatch */
420 typedef void
421 Function_Sweep_Init( RAS_ARGS Short* min,
422 Short* max );
423
424 typedef void
425 Function_Sweep_Span( RAS_ARGS Short y,
426 FT_F26Dot6 x1,
427 FT_F26Dot6 x2,
428 PProfile left,
429 PProfile right );
430
431 typedef void
432 Function_Sweep_Step( RAS_ARG );
433
434
435 /* NOTE: These operations are only valid on 2's complement processors */
436 #undef FLOOR
437 #undef CEILING
438 #undef TRUNC
439 #undef SCALED
440
441 #define FLOOR( x ) ( (x) & -ras.precision )
442 #define CEILING( x ) ( ( (x) + ras.precision - 1 ) & -ras.precision )
443 #define TRUNC( x ) ( (signed long)(x) >> ras.precision_bits )
444 #define FRAC( x ) ( (x) & ( ras.precision - 1 ) )
445 #define SCALED( x ) ( ( (x) << ras.scale_shift ) - ras.precision_half )
446
447 #define IS_BOTTOM_OVERSHOOT( x ) ( CEILING( x ) - x >= ras.precision_half )
448 #define IS_TOP_OVERSHOOT( x ) ( x - FLOOR( x ) >= ras.precision_half )
449
450 /* The most used variables are positioned at the top of the structure. */
451 /* Thus, their offset can be coded with less opcodes, resulting in a */
452 /* smaller executable. */
453
454 struct black_TWorker_
455 {
456 Int precision_bits; /* precision related variables */
457 Int precision;
458 Int precision_half;
459 Int precision_shift;
460 Int precision_step;
461 Int precision_jitter;
462
463 Int scale_shift; /* == precision_shift for bitmaps */
464 /* == precision_shift+1 for pixmaps */
465
466 PLong buff; /* The profiles buffer */
467 PLong sizeBuff; /* Render pool size */
468 PLong maxBuff; /* Profiles buffer size */
469 PLong top; /* Current cursor in buffer */
470
471 FT_Error error;
472
473 Int numTurns; /* number of Y-turns in outline */
474
475 TPoint* arc; /* current Bezier arc pointer */
476
477 UShort bWidth; /* target bitmap width */
478 PByte bTarget; /* target bitmap buffer */
479 PByte gTarget; /* target pixmap buffer */
480
481 Long lastX, lastY;
482 Long minY, maxY;
483
484 UShort num_Profs; /* current number of profiles */
485
486 Bool fresh; /* signals a fresh new profile which */
487 /* `start' field must be completed */
488 Bool joint; /* signals that the last arc ended */
489 /* exactly on a scanline. Allows */
490 /* removal of doublets */
491 PProfile cProfile; /* current profile */
492 PProfile fProfile; /* head of linked list of profiles */
493 PProfile gProfile; /* contour's first profile in case */
494 /* of impact */
495
496 TStates state; /* rendering state */
497
498 FT_Bitmap target; /* description of target bit/pixmap */
499 FT_Outline outline;
500
501 Long traceOfs; /* current offset in target bitmap */
502 Long traceG; /* current offset in target pixmap */
503
504 Short traceIncr; /* sweep's increment in target bitmap */
505
506 Short gray_min_x; /* current min x during gray rendering */
507 Short gray_max_x; /* current max x during gray rendering */
508
509 /* dispatch variables */
510
511 Function_Sweep_Init* Proc_Sweep_Init;
512 Function_Sweep_Span* Proc_Sweep_Span;
513 Function_Sweep_Span* Proc_Sweep_Drop;
514 Function_Sweep_Step* Proc_Sweep_Step;
515
516 Byte dropOutControl; /* current drop_out control method */
517
518 Bool second_pass; /* indicates whether a horizontal pass */
519 /* should be performed to control */
520 /* drop-out accurately when calling */
521 /* Render_Glyph. Note that there is */
522 /* no horizontal pass during gray */
523 /* rendering. */
524
525 TPoint arcs[3 * MaxBezier + 1]; /* The Bezier stack */
526
527 black_TBand band_stack[16]; /* band stack used for sub-banding */
528 Int band_top; /* band stack top */
529
530 #ifdef FT_RASTER_OPTION_ANTI_ALIASING
531
532 Byte* grays;
533
534 Byte gray_lines[RASTER_GRAY_LINES];
535 /* Intermediate table used to render the */
536 /* graylevels pixmaps. */
537 /* gray_lines is a buffer holding two */
538 /* monochrome scanlines */
539
540 Short gray_width; /* width in bytes of one monochrome */
541 /* intermediate scanline of gray_lines. */
542 /* Each gray pixel takes 2 bits long there */
543
544 /* The gray_lines must hold 2 lines, thus with size */
545 /* in bytes of at least `gray_width*2'. */
546
547 #endif /* FT_RASTER_ANTI_ALIASING */
548
549 };
550
551
552 typedef struct black_TRaster_
553 {
554 char* buffer;
555 long buffer_size;
556 void* memory;
557 black_PWorker worker;
558 Byte grays[5];
559 Short gray_width;
560
561 } black_TRaster, *black_PRaster;
562
563 #ifdef FT_STATIC_RASTER
564
565 static black_TWorker cur_ras;
566 #define ras cur_ras
567
568 #else /* !FT_STATIC_RASTER */
569
570 #define ras (*worker)
571
572 #endif /* !FT_STATIC_RASTER */
573
574
575 #ifdef FT_RASTER_OPTION_ANTI_ALIASING
576
577 /* A lookup table used to quickly count set bits in four gray 2x2 */
578 /* cells. The values of the table have been produced with the */
579 /* following code: */
580 /* */
581 /* for ( i = 0; i < 256; i++ ) */
582 /* { */
583 /* l = 0; */
584 /* j = i; */
585 /* */
586 /* for ( c = 0; c < 4; c++ ) */
587 /* { */
588 /* l <<= 4; */
589 /* */
590 /* if ( j & 0x80 ) l++; */
591 /* if ( j & 0x40 ) l++; */
592 /* */
593 /* j = ( j << 2 ) & 0xFF; */
594 /* } */
595 /* printf( "0x%04X", l ); */
596 /* } */
597 /* */
598
599 static const short count_table[256] =
600 {
601 0x0000, 0x0001, 0x0001, 0x0002, 0x0010, 0x0011, 0x0011, 0x0012,
602 0x0010, 0x0011, 0x0011, 0x0012, 0x0020, 0x0021, 0x0021, 0x0022,
603 0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
604 0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
605 0x0100, 0x0101, 0x0101, 0x0102, 0x0110, 0x0111, 0x0111, 0x0112,
606 0x0110, 0x0111, 0x0111, 0x0112, 0x0120, 0x0121, 0x0121, 0x0122,
607 0x0200, 0x0201, 0x0201, 0x0202, 0x0210, 0x0211, 0x0211, 0x0212,
608 0x0210, 0x0211, 0x0211, 0x0212, 0x0220, 0x0221, 0x0221, 0x0222,
609 0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
610 0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
611 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
612 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
613 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
614 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
615 0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
616 0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
617 0x1000, 0x1001, 0x1001, 0x1002, 0x1010, 0x1011, 0x1011, 0x1012,
618 0x1010, 0x1011, 0x1011, 0x1012, 0x1020, 0x1021, 0x1021, 0x1022,
619 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
620 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
621 0x1100, 0x1101, 0x1101, 0x1102, 0x1110, 0x1111, 0x1111, 0x1112,
622 0x1110, 0x1111, 0x1111, 0x1112, 0x1120, 0x1121, 0x1121, 0x1122,
623 0x1200, 0x1201, 0x1201, 0x1202, 0x1210, 0x1211, 0x1211, 0x1212,
624 0x1210, 0x1211, 0x1211, 0x1212, 0x1220, 0x1221, 0x1221, 0x1222,
625 0x2000, 0x2001, 0x2001, 0x2002, 0x2010, 0x2011, 0x2011, 0x2012,
626 0x2010, 0x2011, 0x2011, 0x2012, 0x2020, 0x2021, 0x2021, 0x2022,
627 0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
628 0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
629 0x2100, 0x2101, 0x2101, 0x2102, 0x2110, 0x2111, 0x2111, 0x2112,
630 0x2110, 0x2111, 0x2111, 0x2112, 0x2120, 0x2121, 0x2121, 0x2122,
631 0x2200, 0x2201, 0x2201, 0x2202, 0x2210, 0x2211, 0x2211, 0x2212,
632 0x2210, 0x2211, 0x2211, 0x2212, 0x2220, 0x2221, 0x2221, 0x2222
633 };
634
635 #endif /* FT_RASTER_OPTION_ANTI_ALIASING */
636
637
638
639 /*************************************************************************/
640 /*************************************************************************/
644 /*************************************************************************/
645 /*************************************************************************/
646
647
648 /*************************************************************************/
649 /* */
650 /* <Function> */
651 /* Set_High_Precision */
652 /* */
653 /* <Description> */
654 /* Set precision variables according to param flag. */
655 /* */
656 /* <Input> */
657 /* High :: Set to True for high precision (typically for ppem < 18), */
658 /* false otherwise. */
659 /* */
660 static void
661 Set_High_Precision( RAS_ARGS Int High )
662 {
663 /*
664 * `precision_step' is used in `Bezier_Up' to decide when to split a
665 * given y-monotonous Bezier arc that crosses a scanline before
666 * approximating it as a straight segment. The default value of 32 (for
667 * low accuracy) corresponds to
668 *
669 * 32 / 64 == 0.5 pixels ,
670 *
671 * while for the high accuracy case we have
672 *
673 * 256/ (1 << 12) = 0.0625 pixels .
674 *
675 * `precision_jitter' is an epsilon threshold used in
676 * `Vertical_Sweep_Span' to deal with small imperfections in the Bezier
677 * decomposition (after all, we are working with approximations only);
678 * it avoids switching on additional pixels which would cause artifacts
679 * otherwise.
680 *
681 * The value of `precision_jitter' has been determined heuristically.
682 *
683 */
684
685 if ( High )
686 {
687 ras.precision_bits = 12;
688 ras.precision_step = 256;
689 ras.precision_jitter = 30;
690 }
691 else
692 {
693 ras.precision_bits = 6;
694 ras.precision_step = 32;
695 ras.precision_jitter = 2;
696 }
697
698 FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
699
700 ras.precision = 1 << ras.precision_bits;
701 ras.precision_half = ras.precision / 2;
702 ras.precision_shift = ras.precision_bits - Pixel_Bits;
703 }
704
705
706 /*************************************************************************/
707 /* */
708 /* <Function> */
709 /* New_Profile */
710 /* */
711 /* <Description> */
712 /* Create a new profile in the render pool. */
713 /* */
714 /* <Input> */
715 /* aState :: The state/orientation of the new profile. */
716 /* */
717 /* overshoot :: Whether the profile's unrounded start position */
718 /* differs by at least a half pixel. */
719 /* */
720 /* <Return> */
721 /* SUCCESS on success. FAILURE in case of overflow or of incoherent */
722 /* profile. */
723 /* */
724 static Bool
725 New_Profile( RAS_ARGS TStates aState,
726 Bool overshoot )
727 {
728 if ( !ras.fProfile )
729 {
730 ras.cProfile = (PProfile)ras.top;
731 ras.fProfile = ras.cProfile;
732 ras.top += AlignProfileSize;
733 }
734
735 if ( ras.top >= ras.maxBuff )
736 {
737 ras.error = Raster_Err_Overflow;
738 return FAILURE;
739 }
740
741 ras.cProfile->flags = 0;
742 ras.cProfile->start = 0;
743 ras.cProfile->height = 0;
744 ras.cProfile->offset = ras.top;
745 ras.cProfile->link = (PProfile)0;
746 ras.cProfile->next = (PProfile)0;
747 ras.cProfile->flags = ras.dropOutControl;
748
749 switch ( aState )
750 {
751 case Ascending_State:
752 ras.cProfile->flags |= Flow_Up;
753 if ( overshoot )
754 ras.cProfile->flags |= Overshoot_Bottom;
755
756 FT_TRACE6(( "New ascending profile = %p\n", ras.cProfile ));
757 break;
758
759 case Descending_State:
760 if ( overshoot )
761 ras.cProfile->flags |= Overshoot_Top;
762 FT_TRACE6(( "New descending profile = %p\n", ras.cProfile ));
763 break;
764
765 default:
766 FT_ERROR(( "New_Profile: invalid profile direction\n" ));
767 ras.error = Raster_Err_Invalid;
768 return FAILURE;
769 }
770
771 if ( !ras.gProfile )
772 ras.gProfile = ras.cProfile;
773
774 ras.state = aState;
775 ras.fresh = TRUE;
776 ras.joint = FALSE;
777
778 return SUCCESS;
779 }
780
781
782 /*************************************************************************/
783 /* */
784 /* <Function> */
785 /* End_Profile */
786 /* */
787 /* <Description> */
788 /* Finalize the current profile. */
789 /* */
790 /* <Input> */
791 /* overshoot :: Whether the profile's unrounded end position differs */
792 /* by at least a half pixel. */
793 /* */
794 /* <Return> */
795 /* SUCCESS on success. FAILURE in case of overflow or incoherency. */
796 /* */
797 static Bool
798 End_Profile( RAS_ARGS Bool overshoot )
799 {
800 Long h;
801 PProfile oldProfile;
802
803
804 h = (Long)( ras.top - ras.cProfile->offset );
805
806 if ( h < 0 )
807 {
808 FT_ERROR(( "End_Profile: negative height encountered\n" ));
809 ras.error = Raster_Err_Neg_Height;
810 return FAILURE;
811 }
812
813 if ( h > 0 )
814 {
815 FT_TRACE6(( "Ending profile %p, start = %ld, height = %ld\n",
816 ras.cProfile, ras.cProfile->start, h ));
817
818 ras.cProfile->height = h;
819 if ( overshoot )
820 {
821 if ( ras.cProfile->flags & Flow_Up )
822 ras.cProfile->flags |= Overshoot_Top;
823 else
824 ras.cProfile->flags |= Overshoot_Bottom;
825 }
826
827 oldProfile = ras.cProfile;
828 ras.cProfile = (PProfile)ras.top;
829
830 ras.top += AlignProfileSize;
831
832 ras.cProfile->height = 0;
833 ras.cProfile->offset = ras.top;
834
835 oldProfile->next = ras.cProfile;
836 ras.num_Profs++;
837 }
838
839 if ( ras.top >= ras.maxBuff )
840 {
841 FT_TRACE1(( "overflow in End_Profile\n" ));
842 ras.error = Raster_Err_Overflow;
843 return FAILURE;
844 }
845
846 ras.joint = FALSE;
847
848 return SUCCESS;
849 }
850
851
852 /*************************************************************************/
853 /* */
854 /* <Function> */
855 /* Insert_Y_Turn */
856 /* */
857 /* <Description> */
858 /* Insert a salient into the sorted list placed on top of the render */
859 /* pool. */
860 /* */
861 /* <Input> */
862 /* New y scanline position. */
863 /* */
864 /* <Return> */
865 /* SUCCESS on success. FAILURE in case of overflow. */
866 /* */
867 static Bool
868 Insert_Y_Turn( RAS_ARGS Int y )
869 {
870 PLong y_turns;
871 Int y2, n;
872
873
874 n = ras.numTurns - 1;
875 y_turns = ras.sizeBuff - ras.numTurns;
876
877 /* look for first y value that is <= */
878 while ( n >= 0 && y < y_turns[n] )
879 n--;
880
881 /* if it is <, simply insert it, ignore if == */
882 if ( n >= 0 && y > y_turns[n] )
883 while ( n >= 0 )
884 {
885 y2 = (Int)y_turns[n];
886 y_turns[n] = y;
887 y = y2;
888 n--;
889 }
890
891 if ( n < 0 )
892 {
893 ras.maxBuff--;
894 if ( ras.maxBuff <= ras.top )
895 {
896 ras.error = Raster_Err_Overflow;
897 return FAILURE;
898 }
899 ras.numTurns++;
900 ras.sizeBuff[-ras.numTurns] = y;
901 }
902
903 return SUCCESS;
904 }
905
906
907 /*************************************************************************/
908 /* */
909 /* <Function> */
910 /* Finalize_Profile_Table */
911 /* */
912 /* <Description> */
913 /* Adjust all links in the profiles list. */
914 /* */
915 /* <Return> */
916 /* SUCCESS on success. FAILURE in case of overflow. */
917 /* */
918 static Bool
919 Finalize_Profile_Table( RAS_ARG )
920 {
921 Int bottom, top;
922 UShort n;
923 PProfile p;
924
925
926 n = ras.num_Profs;
927 p = ras.fProfile;
928
929 if ( n > 1 && p )
930 {
931 while ( n > 0 )
932 {
933 if ( n > 1 )
934 p->link = (PProfile)( p->offset + p->height );
935 else
936 p->link = NULL;
937
938 if ( p->flags & Flow_Up )
939 {
940 bottom = (Int)p->start;
941 top = (Int)( p->start + p->height - 1 );
942 }
943 else
944 {
945 bottom = (Int)( p->start - p->height + 1 );
946 top = (Int)p->start;
947 p->start = bottom;
948 p->offset += p->height - 1;
949 }
950
951 if ( Insert_Y_Turn( RAS_VARS bottom ) ||
952 Insert_Y_Turn( RAS_VARS top + 1 ) )
953 return FAILURE;
954
955 p = p->link;
956 n--;
957 }
958 }
959 else
960 ras.fProfile = NULL;
961
962 return SUCCESS;
963 }
964
965
966 /*************************************************************************/
967 /* */
968 /* <Function> */
969 /* Split_Conic */
970 /* */
971 /* <Description> */
972 /* Subdivide one conic Bezier into two joint sub-arcs in the Bezier */
973 /* stack. */
974 /* */
975 /* <Input> */
976 /* None (subdivided Bezier is taken from the top of the stack). */
977 /* */
978 /* <Note> */
979 /* This routine is the `beef' of this component. It is _the_ inner */
980 /* loop that should be optimized to hell to get the best performance. */
981 /* */
982 static void
983 Split_Conic( TPoint* base )
984 {
985 Long a, b;
986
987
988 base[4].x = base[2].x;
989 b = base[1].x;
990 a = base[3].x = ( base[2].x + b ) / 2;
991 b = base[1].x = ( base[0].x + b ) / 2;
992 base[2].x = ( a + b ) / 2;
993
994 base[4].y = base[2].y;
995 b = base[1].y;
996 a = base[3].y = ( base[2].y + b ) / 2;
997 b = base[1].y = ( base[0].y + b ) / 2;
998 base[2].y = ( a + b ) / 2;
999
1000 /* hand optimized. gcc doesn't seem to be too good at common */
1001 /* expression substitution and instruction scheduling ;-) */
1002 }
1003
1004
1005 /*************************************************************************/
1006 /* */
1007 /* <Function> */
1008 /* Split_Cubic */
1009 /* */
1010 /* <Description> */
1011 /* Subdivide a third-order Bezier arc into two joint sub-arcs in the */
1012 /* Bezier stack. */
1013 /* */
1014 /* <Note> */
1015 /* This routine is the `beef' of the component. It is one of _the_ */
1016 /* inner loops that should be optimized like hell to get the best */
1017 /* performance. */
1018 /* */
1019 static void
1020 Split_Cubic( TPoint* base )
1021 {
1022 Long a, b, c, d;
1023
1024
1025 base[6].x = base[3].x;
1026 c = base[1].x;
1027 d = base[2].x;
1028 base[1].x = a = ( base[0].x + c + 1 ) >> 1;
1029 base[5].x = b = ( base[3].x + d + 1 ) >> 1;
1030 c = ( c + d + 1 ) >> 1;
1031 base[2].x = a = ( a + c + 1 ) >> 1;
1032 base[4].x = b = ( b + c + 1 ) >> 1;
1033 base[3].x = ( a + b + 1 ) >> 1;
1034
1035 base[6].y = base[3].y;
1036 c = base[1].y;
1037 d = base[2].y;
1038 base[1].y = a = ( base[0].y + c + 1 ) >> 1;
1039 base[5].y = b = ( base[3].y + d + 1 ) >> 1;
1040 c = ( c + d + 1 ) >> 1;
1041 base[2].y = a = ( a + c + 1 ) >> 1;
1042 base[4].y = b = ( b + c + 1 ) >> 1;
1043 base[3].y = ( a + b + 1 ) >> 1;
1044 }
1045
1046
1047 /*************************************************************************/
1048 /* */
1049 /* <Function> */
1050 /* Line_Up */
1051 /* */
1052 /* <Description> */
1053 /* Compute the x-coordinates of an ascending line segment and store */
1054 /* them in the render pool. */
1055 /* */
1056 /* <Input> */
1057 /* x1 :: The x-coordinate of the segment's start point. */
1058 /* */
1059 /* y1 :: The y-coordinate of the segment's start point. */
1060 /* */
1061 /* x2 :: The x-coordinate of the segment's end point. */
1062 /* */
1063 /* y2 :: The y-coordinate of the segment's end point. */
1064 /* */
1065 /* miny :: A lower vertical clipping bound value. */
1066 /* */
1067 /* maxy :: An upper vertical clipping bound value. */
1068 /* */
1069 /* <Return> */
1070 /* SUCCESS on success, FAILURE on render pool overflow. */
1071 /* */
1072 static Bool
1073 Line_Up( RAS_ARGS Long x1,
1074 Long y1,
1075 Long x2,
1076 Long y2,
1077 Long miny,
1078 Long maxy )
1079 {
1080 Long Dx, Dy;
1081 Int e1, e2, f1, f2, size; /* XXX: is `Short' sufficient? */
1082 Long Ix, Rx, Ax;
1083
1084 PLong top;
1085
1086
1087 Dx = x2 - x1;
1088 Dy = y2 - y1;
1089
1090 if ( Dy <= 0 || y2 < miny || y1 > maxy )
1091 return SUCCESS;
1092
1093 if ( y1 < miny )
1094 {
1095 /* Take care: miny-y1 can be a very large value; we use */
1096 /* a slow MulDiv function to avoid clipping bugs */
1097 x1 += SMulDiv( Dx, miny - y1, Dy );
1098 e1 = (Int)TRUNC( miny );
1099 f1 = 0;
1100 }
1101 else
1102 {
1103 e1 = (Int)TRUNC( y1 );
1104 f1 = (Int)FRAC( y1 );
1105 }
1106
1107 if ( y2 > maxy )
1108 {
1109 /* x2 += FMulDiv( Dx, maxy - y2, Dy ); UNNECESSARY */
1110 e2 = (Int)TRUNC( maxy );
1111 f2 = 0;
1112 }
1113 else
1114 {
1115 e2 = (Int)TRUNC( y2 );
1116 f2 = (Int)FRAC( y2 );
1117 }
1118
1119 if ( f1 > 0 )
1120 {
1121 if ( e1 == e2 )
1122 return SUCCESS;
1123 else
1124 {
1125 x1 += SMulDiv( Dx, ras.precision - f1, Dy );
1126 e1 += 1;
1127 }
1128 }
1129 else
1130 if ( ras.joint )
1131 {
1132 ras.top--;
1133 ras.joint = FALSE;
1134 }
1135
1136 ras.joint = (char)( f2 == 0 );
1137
1138 if ( ras.fresh )
1139 {
1140 ras.cProfile->start = e1;
1141 ras.fresh = FALSE;
1142 }
1143
1144 size = e2 - e1 + 1;
1145 if ( ras.top + size >= ras.maxBuff )
1146 {
1147 ras.error = Raster_Err_Overflow;
1148 return FAILURE;
1149 }
1150
1151 if ( Dx > 0 )
1152 {
1153 Ix = SMulDiv( ras.precision, Dx, Dy);
1154 Rx = ( ras.precision * Dx ) % Dy;
1155 Dx = 1;
1156 }
1157 else
1158 {
1159 Ix = SMulDiv( ras.precision, -Dx, Dy) * -1;
1160 Rx = ( ras.precision * -Dx ) % Dy;
1161 Dx = -1;
1162 }
1163
1164 Ax = -Dy;
1165 top = ras.top;
1166
1167 while ( size > 0 )
1168 {
1169 *top++ = x1;
1170
1171 x1 += Ix;
1172 Ax += Rx;
1173 if ( Ax >= 0 )
1174 {
1175 Ax -= Dy;
1176 x1 += Dx;
1177 }
1178 size--;
1179 }
1180
1181 ras.top = top;
1182 return SUCCESS;
1183 }
1184
1185
1186 /*************************************************************************/
1187 /* */
1188 /* <Function> */
1189 /* Line_Down */
1190 /* */
1191 /* <Description> */
1192 /* Compute the x-coordinates of an descending line segment and store */
1193 /* them in the render pool. */
1194 /* */
1195 /* <Input> */
1196 /* x1 :: The x-coordinate of the segment's start point. */
1197 /* */
1198 /* y1 :: The y-coordinate of the segment's start point. */
1199 /* */
1200 /* x2 :: The x-coordinate of the segment's end point. */
1201 /* */
1202 /* y2 :: The y-coordinate of the segment's end point. */
1203 /* */
1204 /* miny :: A lower vertical clipping bound value. */
1205 /* */
1206 /* maxy :: An upper vertical clipping bound value. */
1207 /* */
1208 /* <Return> */
1209 /* SUCCESS on success, FAILURE on render pool overflow. */
1210 /* */
1211 static Bool
1212 Line_Down( RAS_ARGS Long x1,
1213 Long y1,
1214 Long x2,
1215 Long y2,
1216 Long miny,
1217 Long maxy )
1218 {
1219 Bool result, fresh;
1220
1221
1222 fresh = ras.fresh;
1223
1224 result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
1225
1226 if ( fresh && !ras.fresh )
1227 ras.cProfile->start = -ras.cProfile->start;
1228
1229 return result;
1230 }
1231
1232
1233 /* A function type describing the functions used to split Bezier arcs */
1234 typedef void (*TSplitter)( TPoint* base );
1235
1236
1237 /*************************************************************************/
1238 /* */
1239 /* <Function> */
1240 /* Bezier_Up */
1241 /* */
1242 /* <Description> */
1243 /* Compute the x-coordinates of an ascending Bezier arc and store */
1244 /* them in the render pool. */
1245 /* */
1246 /* <Input> */
1247 /* degree :: The degree of the Bezier arc (either 2 or 3). */
1248 /* */
1249 /* splitter :: The function to split Bezier arcs. */
1250 /* */
1251 /* miny :: A lower vertical clipping bound value. */
1252 /* */
1253 /* maxy :: An upper vertical clipping bound value. */
1254 /* */
1255 /* <Return> */
1256 /* SUCCESS on success, FAILURE on render pool overflow. */
1257 /* */
1258 static Bool
1259 Bezier_Up( RAS_ARGS Int degree,
1260 TSplitter splitter,
1261 Long miny,
1262 Long maxy )
1263 {
1264 Long y1, y2, e, e2, e0;
1265 Short f1;
1266
1267 TPoint* arc;
1268 TPoint* start_arc;
1269
1270 PLong top;
1271
1272
1273 arc = ras.arc;
1274 y1 = arc[degree].y;
1275 y2 = arc[0].y;
1276 top = ras.top;
1277
1278 if ( y2 < miny || y1 > maxy )
1279 goto Fin;
1280
1281 e2 = FLOOR( y2 );
1282
1283 if ( e2 > maxy )
1284 e2 = maxy;
1285
1286 e0 = miny;
1287
1288 if ( y1 < miny )
1289 e = miny;
1290 else
1291 {
1292 e = CEILING( y1 );
1293 f1 = (Short)( FRAC( y1 ) );
1294 e0 = e;
1295
1296 if ( f1 == 0 )
1297 {
1298 if ( ras.joint )
1299 {
1300 top--;
1301 ras.joint = FALSE;
1302 }
1303
1304 *top++ = arc[degree].x;
1305
1306 e += ras.precision;
1307 }
1308 }
1309
1310 if ( ras.fresh )
1311 {
1312 ras.cProfile->start = TRUNC( e0 );
1313 ras.fresh = FALSE;
1314 }
1315
1316 if ( e2 < e )
1317 goto Fin;
1318
1319 if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
1320 {
1321 ras.top = top;
1322 ras.error = Raster_Err_Overflow;
1323 return FAILURE;
1324 }
1325
1326 start_arc = arc;
1327
1328 while ( arc >= start_arc && e <= e2 )
1329 {
1330 ras.joint = FALSE;
1331
1332 y2 = arc[0].y;
1333
1334 if ( y2 > e )
1335 {
1336 y1 = arc[degree].y;
1337 if ( y2 - y1 >= ras.precision_step )
1338 {
1339 splitter( arc );
1340 arc += degree;
1341 }
1342 else
1343 {
1344 *top++ = arc[degree].x + FMulDiv( arc[0].x - arc[degree].x,
1345 e - y1, y2 - y1 );
1346 arc -= degree;
1347 e += ras.precision;
1348 }
1349 }
1350 else
1351 {
1352 if ( y2 == e )
1353 {
1354 ras.joint = TRUE;
1355 *top++ = arc[0].x;
1356
1357 e += ras.precision;
1358 }
1359 arc -= degree;
1360 }
1361 }
1362
1363 Fin:
1364 ras.top = top;
1365 ras.arc -= degree;
1366 return SUCCESS;
1367 }
1368
1369
1370 /*************************************************************************/
1371 /* */
1372 /* <Function> */
1373 /* Bezier_Down */
1374 /* */
1375 /* <Description> */
1376 /* Compute the x-coordinates of an descending Bezier arc and store */
1377 /* them in the render pool. */
1378 /* */
1379 /* <Input> */
1380 /* degree :: The degree of the Bezier arc (either 2 or 3). */
1381 /* */
1382 /* splitter :: The function to split Bezier arcs. */
1383 /* */
1384 /* miny :: A lower vertical clipping bound value. */
1385 /* */
1386 /* maxy :: An upper vertical clipping bound value. */
1387 /* */
1388 /* <Return> */
1389 /* SUCCESS on success, FAILURE on render pool overflow. */
1390 /* */
1391 static Bool
1392 Bezier_Down( RAS_ARGS Int degree,
1393 TSplitter splitter,
1394 Long miny,
1395 Long maxy )
1396 {
1397 TPoint* arc = ras.arc;
1398 Bool result, fresh;
1399
1400
1401 arc[0].y = -arc[0].y;
1402 arc[1].y = -arc[1].y;
1403 arc[2].y = -arc[2].y;
1404 if ( degree > 2 )
1405 arc[3].y = -arc[3].y;
1406
1407 fresh = ras.fresh;
1408
1409 result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
1410
1411 if ( fresh && !ras.fresh )
1412 ras.cProfile->start = -ras.cProfile->start;
1413
1414 arc[0].y = -arc[0].y;
1415 return result;
1416 }
1417
1418
1419 /*************************************************************************/
1420 /* */
1421 /* <Function> */
1422 /* Line_To */
1423 /* */
1424 /* <Description> */
1425 /* Inject a new line segment and adjust the Profiles list. */
1426 /* */
1427 /* <Input> */
1428 /* x :: The x-coordinate of the segment's end point (its start point */
1429 /* is stored in `lastX'). */
1430 /* */
1431 /* y :: The y-coordinate of the segment's end point (its start point */
1432 /* is stored in `lastY'). */
1433 /* */
1434 /* <Return> */
1435 /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
1436 /* profile. */
1437 /* */
1438 static Bool
1439 Line_To( RAS_ARGS Long x,
1440 Long y )
1441 {
1442 /* First, detect a change of direction */
1443
1444 switch ( ras.state )
1445 {
1446 case Unknown_State:
1447 if ( y > ras.lastY )
1448 {
1449 if ( New_Profile( RAS_VARS Ascending_State,
1450 IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
1451 return FAILURE;
1452 }
1453 else
1454 {
1455 if ( y < ras.lastY )
1456 if ( New_Profile( RAS_VARS Descending_State,
1457 IS_TOP_OVERSHOOT( ras.lastY ) ) )
1458 return FAILURE;
1459 }
1460 break;
1461
1462 case Ascending_State:
1463 if ( y < ras.lastY )
1464 {
1465 if ( End_Profile( RAS_VARS IS_TOP_OVERSHOOT( ras.lastY ) ) ||
1466 New_Profile( RAS_VARS Descending_State,
1467 IS_TOP_OVERSHOOT( ras.lastY ) ) )
1468 return FAILURE;
1469 }
1470 break;
1471
1472 case Descending_State:
1473 if ( y > ras.lastY )
1474 {
1475 if ( End_Profile( RAS_VARS IS_BOTTOM_OVERSHOOT( ras.lastY ) ) ||
1476 New_Profile( RAS_VARS Ascending_State,
1477 IS_BOTTOM_OVERSHOOT( ras.lastY ) ) )
1478 return FAILURE;
1479 }
1480 break;
1481
1482 default:
1483 ;
1484 }
1485
1486 /* Then compute the lines */
1487
1488 switch ( ras.state )
1489 {
1490 case Ascending_State:
1491 if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
1492 x, y, ras.minY, ras.maxY ) )
1493 return FAILURE;
1494 break;
1495
1496 case Descending_State:
1497 if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
1498 x, y, ras.minY, ras.maxY ) )
1499 return FAILURE;
1500 break;
1501
1502 default:
1503 ;
1504 }
1505
1506 ras.lastX = x;
1507 ras.lastY = y;
1508
1509 return SUCCESS;
1510 }
1511
1512
1513 /*************************************************************************/
1514 /* */
1515 /* <Function> */
1516 /* Conic_To */
1517 /* */
1518 /* <Description> */
1519 /* Inject a new conic arc and adjust the profile list. */
1520 /* */
1521 /* <Input> */
1522 /* cx :: The x-coordinate of the arc's new control point. */
1523 /* */
1524 /* cy :: The y-coordinate of the arc's new control point. */
1525 /* */
1526 /* x :: The x-coordinate of the arc's end point (its start point is */
1527 /* stored in `lastX'). */
1528 /* */
1529 /* y :: The y-coordinate of the arc's end point (its start point is */
1530 /* stored in `lastY'). */
1531 /* */
1532 /* <Return> */
1533 /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
1534 /* profile. */
1535 /* */
1536 static Bool
1537 Conic_To( RAS_ARGS Long cx,
1538 Long cy,
1539 Long x,
1540 Long y )
1541 {
1542 Long y1, y2, y3, x3, ymin, ymax;
1543 TStates state_bez;
1544
1545
1546 ras.arc = ras.arcs;
1547 ras.arc[2].x = ras.lastX;
1548 ras.arc[2].y = ras.lastY;
1549 ras.arc[1].x = cx;
1550 ras.arc[1].y = cy;
1551 ras.arc[0].x = x;
1552 ras.arc[0].y = y;
1553
1554 do
1555 {
1556 y1 = ras.arc[2].y;
1557 y2 = ras.arc[1].y;
1558 y3 = ras.arc[0].y;
1559 x3 = ras.arc[0].x;
1560
1561 /* first, categorize the Bezier arc */
1562
1563 if ( y1 <= y3 )
1564 {
1565 ymin = y1;
1566 ymax = y3;
1567 }
1568 else
1569 {
1570 ymin = y3;
1571 ymax = y1;
1572 }
1573
1574 if ( y2 < ymin || y2 > ymax )
1575 {
1576 /* this arc has no given direction, split it! */
1577 Split_Conic( ras.arc );
1578 ras.arc += 2;
1579 }
1580 else if ( y1 == y3 )
1581 {
1582 /* this arc is flat, ignore it and pop it from the Bezier stack */
1583 ras.arc -= 2;
1584 }
1585 else
1586 {
1587 /* the arc is y-monotonous, either ascending or descending */
1588 /* detect a change of direction */
1589 state_bez = y1 < y3 ? Ascending_State : Descending_State;
1590 if ( ras.state != state_bez )
1591 {
1592 Bool o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )
1593 : IS_TOP_OVERSHOOT( y1 );
1594
1595
1596 /* finalize current profile if any */
1597 if ( ras.state != Unknown_State &&
1598 End_Profile( RAS_VARS o ) )
1599 goto Fail;
1600
1601 /* create a new profile */
1602 if ( New_Profile( RAS_VARS state_bez, o ) )
1603 goto Fail;
1604 }
1605
1606 /* now call the appropriate routine */
1607 if ( state_bez == Ascending_State )
1608 {
1609 if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1610 goto Fail;
1611 }
1612 else
1613 if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
1614 goto Fail;
1615 }
1616
1617 } while ( ras.arc >= ras.arcs );
1618
1619 ras.lastX = x3;
1620 ras.lastY = y3;
1621
1622 return SUCCESS;
1623
1624 Fail:
1625 return FAILURE;
1626 }
1627
1628
1629 /*************************************************************************/
1630 /* */
1631 /* <Function> */
1632 /* Cubic_To */
1633 /* */
1634 /* <Description> */
1635 /* Inject a new cubic arc and adjust the profile list. */
1636 /* */
1637 /* <Input> */
1638 /* cx1 :: The x-coordinate of the arc's first new control point. */
1639 /* */
1640 /* cy1 :: The y-coordinate of the arc's first new control point. */
1641 /* */
1642 /* cx2 :: The x-coordinate of the arc's second new control point. */
1643 /* */
1644 /* cy2 :: The y-coordinate of the arc's second new control point. */
1645 /* */
1646 /* x :: The x-coordinate of the arc's end point (its start point is */
1647 /* stored in `lastX'). */
1648 /* */
1649 /* y :: The y-coordinate of the arc's end point (its start point is */
1650 /* stored in `lastY'). */
1651 /* */
1652 /* <Return> */
1653 /* SUCCESS on success, FAILURE on render pool overflow or incorrect */
1654 /* profile. */
1655 /* */
1656 static Bool
1657 Cubic_To( RAS_ARGS Long cx1,
1658 Long cy1,
1659 Long cx2,
1660 Long cy2,
1661 Long x,
1662 Long y )
1663 {
1664 Long y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
1665 TStates state_bez;
1666
1667
1668 ras.arc = ras.arcs;
1669 ras.arc[3].x = ras.lastX;
1670 ras.arc[3].y = ras.lastY;
1671 ras.arc[2].x = cx1;
1672 ras.arc[2].y = cy1;
1673 ras.arc[1].x = cx2;
1674 ras.arc[1].y = cy2;
1675 ras.arc[0].x = x;
1676 ras.arc[0].y = y;
1677
1678 do
1679 {
1680 y1 = ras.arc[3].y;
1681 y2 = ras.arc[2].y;
1682 y3 = ras.arc[1].y;
1683 y4 = ras.arc[0].y;
1684 x4 = ras.arc[0].x;
1685
1686 /* first, categorize the Bezier arc */
1687
1688 if ( y1 <= y4 )
1689 {
1690 ymin1 = y1;
1691 ymax1 = y4;
1692 }
1693 else
1694 {
1695 ymin1 = y4;
1696 ymax1 = y1;
1697 }
1698
1699 if ( y2 <= y3 )
1700 {
1701 ymin2 = y2;
1702 ymax2 = y3;
1703 }
1704 else
1705 {
1706 ymin2 = y3;
1707 ymax2 = y2;
1708 }
1709
1710 if ( ymin2 < ymin1 || ymax2 > ymax1 )
1711 {
1712 /* this arc has no given direction, split it! */
1713 Split_Cubic( ras.arc );
1714 ras.arc += 3;
1715 }
1716 else if ( y1 == y4 )
1717 {
1718 /* this arc is flat, ignore it and pop it from the Bezier stack */
1719 ras.arc -= 3;
1720 }
1721 else
1722 {
1723 state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
1724
1725 /* detect a change of direction */
1726 if ( ras.state != state_bez )
1727 {
1728 Bool o = state_bez == Ascending_State ? IS_BOTTOM_OVERSHOOT( y1 )
1729 : IS_TOP_OVERSHOOT( y1 );
1730
1731
1732 /* finalize current profile if any */
1733 if ( ras.state != Unknown_State &&
1734 End_Profile( RAS_VARS o ) )
1735 goto Fail;
1736
1737 if ( New_Profile( RAS_VARS state_bez, o ) )
1738 goto Fail;
1739 }
1740
1741 /* compute intersections */
1742 if ( state_bez == Ascending_State )
1743 {
1744 if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1745 goto Fail;
1746 }
1747 else
1748 if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
1749 goto Fail;
1750 }
1751
1752 } while ( ras.arc >= ras.arcs );
1753
1754 ras.lastX = x4;
1755 ras.lastY = y4;
1756
1757 return SUCCESS;
1758
1759 Fail:
1760 return FAILURE;
1761 }
1762
1763
1764 #undef SWAP_
1765 #define SWAP_( x, y ) do \
1766 { \
1767 Long swap = x; \
1768 \
1769 \
1770 x = y; \
1771 y = swap; \
1772 } while ( 0 )
1773
1774
1775 /*************************************************************************/
1776 /* */
1777 /* <Function> */
1778 /* Decompose_Curve */
1779 /* */
1780 /* <Description> */
1781 /* Scan the outline arrays in order to emit individual segments and */
1782 /* Beziers by calling Line_To() and Bezier_To(). It handles all */
1783 /* weird cases, like when the first point is off the curve, or when */
1784 /* there are simply no `on' points in the contour! */
1785 /* */
1786 /* <Input> */
1787 /* first :: The index of the first point in the contour. */
1788 /* */
1789 /* last :: The index of the last point in the contour. */
1790 /* */
1791 /* flipped :: If set, flip the direction of the curve. */
1792 /* */
1793 /* <Return> */
1794 /* SUCCESS on success, FAILURE on error. */
1795 /* */
1796 static Bool
1797 Decompose_Curve( RAS_ARGS UShort first,
1798 UShort last,
1799 int flipped )
1800 {
1801 FT_Vector v_last;
1802 FT_Vector v_control;
1803 FT_Vector v_start;
1804
1805 FT_Vector* points;
1806 FT_Vector* point;
1807 FT_Vector* limit;
1808 char* tags;
1809
1810 unsigned tag; /* current point's state */
1811
1812
1813 points = ras.outline.points;
1814 limit = points + last;
1815
1816 v_start.x = SCALED( points[first].x );
1817 v_start.y = SCALED( points[first].y );
1818 v_last.x = SCALED( points[last].x );
1819 v_last.y = SCALED( points[last].y );
1820
1821 if ( flipped )
1822 {
1823 SWAP_( v_start.x, v_start.y );
1824 SWAP_( v_last.x, v_last.y );
1825 }
1826
1827 v_control = v_start;
1828
1829 point = points + first;
1830 tags = ras.outline.tags + first;
1831
1832 /* set scan mode if necessary */
1833 if ( tags[0] & FT_CURVE_TAG_HAS_SCANMODE )
1834 ras.dropOutControl = (Byte)tags[0] >> 5;
1835
1836 tag = FT_CURVE_TAG( tags[0] );
1837
1838 /* A contour cannot start with a cubic control point! */
1839 if ( tag == FT_CURVE_TAG_CUBIC )
1840 goto Invalid_Outline;
1841
1842 /* check first point to determine origin */
1843 if ( tag == FT_CURVE_TAG_CONIC )
1844 {
1845 /* first point is conic control. Yes, this happens. */
1846 if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )
1847 {
1848 /* start at last point if it is on the curve */
1849 v_start = v_last;
1850 limit--;
1851 }
1852 else
1853 {
1854 /* if both first and last points are conic, */
1855 /* start at their middle and record its position */
1856 /* for closure */
1857 v_start.x = ( v_start.x + v_last.x ) / 2;
1858 v_start.y = ( v_start.y + v_last.y ) / 2;
1859
1860 v_last = v_start;
1861 }
1862 point--;
1863 tags--;
1864 }
1865
1866 ras.lastX = v_start.x;
1867 ras.lastY = v_start.y;
1868
1869 while ( point < limit )
1870 {
1871 point++;
1872 tags++;
1873
1874 tag = FT_CURVE_TAG( tags[0] );
1875
1876 switch ( tag )
1877 {
1878 case FT_CURVE_TAG_ON: /* emit a single line_to */
1879 {
1880 Long x, y;
1881
1882
1883 x = SCALED( point->x );
1884 y = SCALED( point->y );
1885 if ( flipped )
1886 SWAP_( x, y );
1887
1888 if ( Line_To( RAS_VARS x, y ) )
1889 goto Fail;
1890 continue;
1891 }
1892
1893 case FT_CURVE_TAG_CONIC: /* consume conic arcs */
1894 v_control.x = SCALED( point[0].x );
1895 v_control.y = SCALED( point[0].y );
1896
1897 if ( flipped )
1898 SWAP_( v_control.x, v_control.y );
1899
1900 Do_Conic:
1901 if ( point < limit )
1902 {
1903 FT_Vector v_middle;
1904 Long x, y;
1905
1906
1907 point++;
1908 tags++;
1909 tag = FT_CURVE_TAG( tags[0] );
1910
1911 x = SCALED( point[0].x );
1912 y = SCALED( point[0].y );
1913
1914 if ( flipped )
1915 SWAP_( x, y );
1916
1917 if ( tag == FT_CURVE_TAG_ON )
1918 {
1919 if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
1920 goto Fail;
1921 continue;
1922 }
1923
1924 if ( tag != FT_CURVE_TAG_CONIC )
1925 goto Invalid_Outline;
1926
1927 v_middle.x = ( v_control.x + x ) / 2;
1928 v_middle.y = ( v_control.y + y ) / 2;
1929
1930 if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1931 v_middle.x, v_middle.y ) )
1932 goto Fail;
1933
1934 v_control.x = x;
1935 v_control.y = y;
1936
1937 goto Do_Conic;
1938 }
1939
1940 if ( Conic_To( RAS_VARS v_control.x, v_control.y,
1941 v_start.x, v_start.y ) )
1942 goto Fail;
1943
1944 goto Close;
1945
1946 default: /* FT_CURVE_TAG_CUBIC */
1947 {
1948 Long x1, y1, x2, y2, x3, y3;
1949
1950
1951 if ( point + 1 > limit ||
1952 FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
1953 goto Invalid_Outline;
1954
1955 point += 2;
1956 tags += 2;
1957
1958 x1 = SCALED( point[-2].x );
1959 y1 = SCALED( point[-2].y );
1960 x2 = SCALED( point[-1].x );
1961 y2 = SCALED( point[-1].y );
1962
1963 if ( flipped )
1964 {
1965 SWAP_( x1, y1 );
1966 SWAP_( x2, y2 );
1967 }
1968
1969 if ( point <= limit )
1970 {
1971 x3 = SCALED( point[0].x );
1972 y3 = SCALED( point[0].y );
1973
1974 if ( flipped )
1975 SWAP_( x3, y3 );
1976
1977 if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
1978 goto Fail;
1979 continue;
1980 }
1981
1982 if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
1983 goto Fail;
1984 goto Close;
1985 }
1986 }
1987 }
1988
1989 /* close the contour with a line segment */
1990 if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
1991 goto Fail;
1992
1993 Close:
1994 return SUCCESS;
1995
1996 Invalid_Outline:
1997 ras.error = Raster_Err_Invalid;
1998
1999 Fail:
2000 return FAILURE;
2001 }
2002
2003
2004 /*************************************************************************/
2005 /* */
2006 /* <Function> */
2007 /* Convert_Glyph */
2008 /* */
2009 /* <Description> */
2010 /* Convert a glyph into a series of segments and arcs and make a */
2011 /* profiles list with them. */
2012 /* */
2013 /* <Input> */
2014 /* flipped :: If set, flip the direction of curve. */
2015 /* */
2016 /* <Return> */
2017 /* SUCCESS on success, FAILURE if any error was encountered during */
2018 /* rendering. */
2019 /* */
2020 static Bool
2021 Convert_Glyph( RAS_ARGS int flipped )
2022 {
2023 int i;
2024 unsigned start;
2025
2026 PProfile lastProfile;
2027
2028
2029 ras.fProfile = NULL;
2030 ras.joint = FALSE;
2031 ras.fresh = FALSE;
2032
2033 ras.maxBuff = ras.sizeBuff - AlignProfileSize;
2034
2035 ras.numTurns = 0;
2036
2037 ras.cProfile = (PProfile)ras.top;
2038 ras.cProfile->offset = ras.top;
2039 ras.num_Profs = 0;
2040
2041 start = 0;
2042
2043 for ( i = 0; i < ras.outline.n_contours; i++ )
2044 {
2045 Bool o;
2046
2047
2048 ras.state = Unknown_State;
2049 ras.gProfile = NULL;
2050
2051 if ( Decompose_Curve( RAS_VARS (unsigned short)start,
2052 ras.outline.contours[i],
2053 flipped ) )
2054 return FAILURE;
2055
2056 start = ras.outline.contours[i] + 1;
2057
2058 /* we must now check whether the extreme arcs join or not */
2059 if ( FRAC( ras.lastY ) == 0 &&
2060 ras.lastY >= ras.minY &&
2061 ras.lastY <= ras.maxY )
2062 if ( ras.gProfile &&
2063 ( ras.gProfile->flags & Flow_Up ) ==
2064 ( ras.cProfile->flags & Flow_Up ) )
2065 ras.top--;
2066 /* Note that ras.gProfile can be nil if the contour was too small */
2067 /* to be drawn. */
2068
2069 lastProfile = ras.cProfile;
2070 if ( ras.cProfile->flags & Flow_Up )
2071 o = IS_TOP_OVERSHOOT( ras.lastY );
2072 else
2073 o = IS_BOTTOM_OVERSHOOT( ras.lastY );
2074 if ( End_Profile( RAS_VARS o ) )
2075 return FAILURE;
2076
2077 /* close the `next profile in contour' linked list */
2078 if ( ras.gProfile )
2079 lastProfile->next = ras.gProfile;
2080 }
2081
2082 if ( Finalize_Profile_Table( RAS_VAR ) )
2083 return FAILURE;
2084
2085 return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
2086 }
2087
2088
2089 /*************************************************************************/
2090 /*************************************************************************/
2094 /*************************************************************************/
2095 /*************************************************************************/
2096
2097
2098 /*************************************************************************/
2099 /* */
2100 /* Init_Linked */
2101 /* */
2102 /* Initializes an empty linked list. */
2103 /* */
2104 static void
2105 Init_Linked( TProfileList* l )
2106 {
2107 *l = NULL;
2108 }
2109
2110
2111 /*************************************************************************/
2112 /* */
2113 /* InsNew */
2114 /* */
2115 /* Inserts a new profile in a linked list. */
2116 /* */
2117 static void
2118 InsNew( PProfileList list,
2119 PProfile profile )
2120 {
2121 PProfile *old, current;
2122 Long x;
2123
2124
2125 old = list;
2126 current = *old;
2127 x = profile->X;
2128
2129 while ( current )
2130 {
2131 if ( x < current->X )
2132 break;
2133 old = &current->link;
2134 current = *old;
2135 }
2136
2137 profile->link = current;
2138 *old = profile;
2139 }
2140
2141
2142 /*************************************************************************/
2143 /* */
2144 /* DelOld */
2145 /* */
2146 /* Removes an old profile from a linked list. */
2147 /* */
2148 static void
2149 DelOld( PProfileList list,
2150 PProfile profile )
2151 {
2152 PProfile *old, current;
2153
2154
2155 old = list;
2156 current = *old;
2157
2158 while ( current )
2159 {
2160 if ( current == profile )
2161 {
2162 *old = current->link;
2163 return;
2164 }
2165
2166 old = &current->link;
2167 current = *old;
2168 }
2169
2170 /* we should never get there, unless the profile was not part of */
2171 /* the list. */
2172 }
2173
2174
2175 /*************************************************************************/
2176 /* */
2177 /* Sort */
2178 /* */
2179 /* Sorts a trace list. In 95%, the list is already sorted. We need */
2180 /* an algorithm which is fast in this case. Bubble sort is enough */
2181 /* and simple. */
2182 /* */
2183 static void
2184 Sort( PProfileList list )
2185 {
2186 PProfile *old, current, next;
2187
2188
2189 /* First, set the new X coordinate of each profile */
2190 current = *list;
2191 while ( current )
2192 {
2193 current->X = *current->offset;
2194 current->offset += current->flags & Flow_Up ? 1 : -1;
2195 current->height--;
2196 current = current->link;
2197 }
2198
2199 /* Then sort them */
2200 old = list;
2201 current = *old;
2202
2203 if ( !current )
2204 return;
2205
2206 next = current->link;
2207
2208 while ( next )
2209 {
2210 if ( current->X <= next->X )
2211 {
2212 old = &current->link;
2213 current = *old;
2214
2215 if ( !current )
2216 return;
2217 }
2218 else
2219 {
2220 *old = next;
2221 current->link = next->link;
2222 next->link = current;
2223
2224 old = list;
2225 current = *old;
2226 }
2227
2228 next = current->link;
2229 }
2230 }
2231
2232
2233 /*************************************************************************/
2234 /* */
2235 /* Vertical Sweep Procedure Set */
2236 /* */
2237 /* These four routines are used during the vertical black/white sweep */
2238 /* phase by the generic Draw_Sweep() function. */
2239 /* */
2240 /*************************************************************************/
2241
2242 static void
2243 Vertical_Sweep_Init( RAS_ARGS Short* min,
2244 Short* max )
2245 {
2246 Long pitch = ras.target.pitch;
2247
2248 FT_UNUSED( max );
2249
2250
2251 ras.traceIncr = (Short)-pitch;
2252 ras.traceOfs = -*min * pitch;
2253 if ( pitch > 0 )
2254 ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
2255
2256 ras.gray_min_x = 0;
2257 ras.gray_max_x = 0;
2258 }
2259
2260
2261 static void
2262 Vertical_Sweep_Span( RAS_ARGS Short y,
2263 FT_F26Dot6 x1,
2264 FT_F26Dot6 x2,
2265 PProfile left,
2266 PProfile right )
2267 {
2268 Long e1, e2;
2269 int c1, c2;
2270 Byte f1, f2;
2271 Byte* target;
2272
2273 FT_UNUSED( y );
2274 FT_UNUSED( left );
2275 FT_UNUSED( right );
2276
2277
2278 /* Drop-out control */
2279
2280 e1 = TRUNC( CEILING( x1 ) );
2281
2282 if ( x2 - x1 - ras.precision <= ras.precision_jitter )
2283 e2 = e1;
2284 else
2285 e2 = TRUNC( FLOOR( x2 ) );
2286
2287 if ( e2 >= 0 && e1 < ras.bWidth )
2288 {
2289 if ( e1 < 0 )
2290 e1 = 0;
2291 if ( e2 >= ras.bWidth )
2292 e2 = ras.bWidth - 1;
2293
2294 c1 = (Short)( e1 >> 3 );
2295 c2 = (Short)( e2 >> 3 );
2296
2297 f1 = (Byte) ( 0xFF >> ( e1 & 7 ) );
2298 f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
2299
2300 if ( ras.gray_min_x > c1 )
2301 ras.gray_min_x = (short)c1;
2302 if ( ras.gray_max_x < c2 )
2303 ras.gray_max_x = (short)c2;
2304
2305 target = ras.bTarget + ras.traceOfs + c1;
2306 c2 -= c1;
2307
2308 if ( c2 > 0 )
2309 {
2310 target[0] |= f1;
2311
2312 /* memset() is slower than the following code on many platforms. */
2313 /* This is due to the fact that, in the vast majority of cases, */
2314 /* the span length in bytes is relatively small. */
2315 c2--;
2316 while ( c2 > 0 )
2317 {
2318 *(++target) = 0xFF;
2319 c2--;
2320 }
2321 target[1] |= f2;
2322 }
2323 else
2324 *target |= ( f1 & f2 );
2325 }
2326 }
2327
2328
2329 static void
2330 Vertical_Sweep_Drop( RAS_ARGS Short y,
2331 FT_F26Dot6 x1,
2332 FT_F26Dot6 x2,
2333 PProfile left,
2334 PProfile right )
2335 {
2336 Long e1, e2, pxl;
2337 Short c1, f1;
2338
2339
2340 /* Drop-out control */
2341
2342 /* e2 x2 x1 e1 */
2343 /* */
2344 /* ^ | */
2345 /* | | */
2346 /* +-------------+---------------------+------------+ */
2347 /* | | */
2348 /* | v */
2349 /* */
2350 /* pixel contour contour pixel */
2351 /* center center */
2352
2353 /* drop-out mode scan conversion rules (as defined in OpenType) */
2354 /* --------------------------------------------------------------- */
2355 /* 0 1, 2, 3 */
2356 /* 1 1, 2, 4 */
2357 /* 2 1, 2 */
2358 /* 3 same as mode 2 */
2359 /* 4 1, 2, 5 */
2360 /* 5 1, 2, 6 */
2361 /* 6, 7 same as mode 2 */
2362
2363 e1 = CEILING( x1 );
2364 e2 = FLOOR ( x2 );
2365 pxl = e1;
2366
2367 if ( e1 > e2 )
2368 {
2369 Int dropOutControl = left->flags & 7;
2370
2371
2372 if ( e1 == e2 + ras.precision )
2373 {
2374 switch ( dropOutControl )
2375 {
2376 case 0: /* simple drop-outs including stubs */
2377 pxl = e2;
2378 break;
2379
2380 case 4: /* smart drop-outs including stubs */
2381 pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2382 break;
2383
2384 case 1: /* simple drop-outs excluding stubs */
2385 case 5: /* smart drop-outs excluding stubs */
2386
2387 /* Drop-out Control Rules #4 and #6 */
2388
2389 /* The specification neither provides an exact definition */
2390 /* of a `stub' nor gives exact rules to exclude them. */
2391 /* */
2392 /* Here the constraints we use to recognize a stub. */
2393 /* */
2394 /* upper stub: */
2395 /* */
2396 /* - P_Left and P_Right are in the same contour */
2397 /* - P_Right is the successor of P_Left in that contour */
2398 /* - y is the top of P_Left and P_Right */
2399 /* */
2400 /* lower stub: */
2401 /* */
2402 /* - P_Left and P_Right are in the same contour */
2403 /* - P_Left is the successor of P_Right in that contour */
2404 /* - y is the bottom of P_Left */
2405 /* */
2406 /* We draw a stub if the following constraints are met. */
2407 /* */
2408 /* - for an upper or lower stub, there is top or bottom */
2409 /* overshoot, respectively */
2410 /* - the covered interval is greater or equal to a half */
2411 /* pixel */
2412
2413 /* upper stub test */
2414 if ( left->next == right &&
2415 left->height <= 0 &&
2416 !( left->flags & Overshoot_Top &&
2417 x2 - x1 >= ras.precision_half ) )
2418 return;
2419
2420 /* lower stub test */
2421 if ( right->next == left &&
2422 left->start == y &&
2423 !( left->flags & Overshoot_Bottom &&
2424 x2 - x1 >= ras.precision_half ) )
2425 return;
2426
2427 if ( dropOutControl == 1 )
2428 pxl = e2;
2429 else
2430 pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2431 break;
2432
2433 default: /* modes 2, 3, 6, 7 */
2434 return; /* no drop-out control */
2435 }
2436
2437 /* undocumented but confirmed: If the drop-out would result in a */
2438 /* pixel outside of the bounding box, use the pixel inside of the */
2439 /* bounding box instead */
2440 if ( pxl < 0 )
2441 pxl = e1;
2442 else if ( TRUNC( pxl ) >= ras.bWidth )
2443 pxl = e2;
2444
2445 /* check that the other pixel isn't set */
2446 e1 = pxl == e1 ? e2 : e1;
2447
2448 e1 = TRUNC( e1 );
2449
2450 c1 = (Short)( e1 >> 3 );
2451 f1 = (Short)( e1 & 7 );
2452
2453 if ( e1 >= 0 && e1 < ras.bWidth &&
2454 ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
2455 return;
2456 }
2457 else
2458 return;
2459 }
2460
2461 e1 = TRUNC( pxl );
2462
2463 if ( e1 >= 0 && e1 < ras.bWidth )
2464 {
2465 c1 = (Short)( e1 >> 3 );
2466 f1 = (Short)( e1 & 7 );
2467
2468 if ( ras.gray_min_x > c1 )
2469 ras.gray_min_x = c1;
2470 if ( ras.gray_max_x < c1 )
2471 ras.gray_max_x = c1;
2472
2473 ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
2474 }
2475 }
2476
2477
2478 static void
2479 Vertical_Sweep_Step( RAS_ARG )
2480 {
2481 ras.traceOfs += ras.traceIncr;
2482 }
2483
2484
2485 /***********************************************************************/
2486 /* */
2487 /* Horizontal Sweep Procedure Set */
2488 /* */
2489 /* These four routines are used during the horizontal black/white */
2490 /* sweep phase by the generic Draw_Sweep() function. */
2491 /* */
2492 /***********************************************************************/
2493
2494 static void
2495 Horizontal_Sweep_Init( RAS_ARGS Short* min,
2496 Short* max )
2497 {
2498 /* nothing, really */
2499 FT_UNUSED_RASTER;
2500 FT_UNUSED( min );
2501 FT_UNUSED( max );
2502 }
2503
2504
2505 static void
2506 Horizontal_Sweep_Span( RAS_ARGS Short y,
2507 FT_F26Dot6 x1,
2508 FT_F26Dot6 x2,
2509 PProfile left,
2510 PProfile right )
2511 {
2512 Long e1, e2;
2513 PByte bits;
2514 Byte f1;
2515
2516 FT_UNUSED( left );
2517 FT_UNUSED( right );
2518
2519
2520 if ( x2 - x1 < ras.precision )
2521 {
2522 e1 = CEILING( x1 );
2523 e2 = FLOOR ( x2 );
2524
2525 if ( e1 == e2 )
2526 {
2527 bits = ras.bTarget + ( y >> 3 );
2528 f1 = (Byte)( 0x80 >> ( y & 7 ) );
2529
2530 e1 = TRUNC( e1 );
2531
2532 if ( e1 >= 0 && e1 < ras.target.rows )
2533 {
2534 PByte p;
2535
2536
2537 p = bits - e1 * ras.target.pitch;
2538 if ( ras.target.pitch > 0 )
2539 p += ( ras.target.rows - 1 ) * ras.target.pitch;
2540
2541 p[0] |= f1;
2542 }
2543 }
2544 }
2545 }
2546
2547
2548 static void
2549 Horizontal_Sweep_Drop( RAS_ARGS Short y,
2550 FT_F26Dot6 x1,
2551 FT_F26Dot6 x2,
2552 PProfile left,
2553 PProfile right )
2554 {
2555 Long e1, e2, pxl;
2556 PByte bits;
2557 Byte f1;
2558
2559
2560 /* During the horizontal sweep, we only take care of drop-outs */
2561
2562 /* e1 + <-- pixel center */
2563 /* | */
2564 /* x1 ---+--> <-- contour */
2565 /* | */
2566 /* | */
2567 /* x2 <--+--- <-- contour */
2568 /* | */
2569 /* | */
2570 /* e2 + <-- pixel center */
2571
2572 e1 = CEILING( x1 );
2573 e2 = FLOOR ( x2 );
2574 pxl = e1;
2575
2576 if ( e1 > e2 )
2577 {
2578 Int dropOutControl = left->flags & 7;
2579
2580
2581 if ( e1 == e2 + ras.precision )
2582 {
2583 switch ( dropOutControl )
2584 {
2585 case 0: /* simple drop-outs including stubs */
2586 pxl = e2;
2587 break;
2588
2589 case 4: /* smart drop-outs including stubs */
2590 pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2591 break;
2592
2593 case 1: /* simple drop-outs excluding stubs */
2594 case 5: /* smart drop-outs excluding stubs */
2595 /* see Vertical_Sweep_Drop for details */
2596
2597 /* rightmost stub test */
2598 if ( left->next == right &&
2599 left->height <= 0 &&
2600 !( left->flags & Overshoot_Top &&
2601 x2 - x1 >= ras.precision_half ) )
2602 return;
2603
2604 /* leftmost stub test */
2605 if ( right->next == left &&
2606 left->start == y &&
2607 !( left->flags & Overshoot_Bottom &&
2608 x2 - x1 >= ras.precision_half ) )
2609 return;
2610
2611 if ( dropOutControl == 1 )
2612 pxl = e2;
2613 else
2614 pxl = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2615 break;
2616
2617 default: /* modes 2, 3, 6, 7 */
2618 return; /* no drop-out control */
2619 }
2620
2621 /* undocumented but confirmed: If the drop-out would result in a */
2622 /* pixel outside of the bounding box, use the pixel inside of the */
2623 /* bounding box instead */
2624 if ( pxl < 0 )
2625 pxl = e1;
2626 else if ( TRUNC( pxl ) >= ras.target.rows )
2627 pxl = e2;
2628
2629 /* check that the other pixel isn't set */
2630 e1 = pxl == e1 ? e2 : e1;
2631
2632 e1 = TRUNC( e1 );
2633
2634 bits = ras.bTarget + ( y >> 3 );
2635 f1 = (Byte)( 0x80 >> ( y & 7 ) );
2636
2637 bits -= e1 * ras.target.pitch;
2638 if ( ras.target.pitch > 0 )
2639 bits += ( ras.target.rows - 1 ) * ras.target.pitch;
2640
2641 if ( e1 >= 0 &&
2642 e1 < ras.target.rows &&
2643 *bits & f1 )
2644 return;
2645 }
2646 else
2647 return;
2648 }
2649
2650 bits = ras.bTarget + ( y >> 3 );
2651 f1 = (Byte)( 0x80 >> ( y & 7 ) );
2652
2653 e1 = TRUNC( pxl );
2654
2655 if ( e1 >= 0 && e1 < ras.target.rows )
2656 {
2657 bits -= e1 * ras.target.pitch;
2658 if ( ras.target.pitch > 0 )
2659 bits += ( ras.target.rows - 1 ) * ras.target.pitch;
2660
2661 bits[0] |= f1;
2662 }
2663 }
2664
2665
2666 static void
2667 Horizontal_Sweep_Step( RAS_ARG )
2668 {
2669 /* Nothing, really */
2670 FT_UNUSED_RASTER;
2671 }
2672
2673
2674 #ifdef FT_RASTER_OPTION_ANTI_ALIASING
2675
2676
2677 /*************************************************************************/
2678 /* */
2679 /* Vertical Gray Sweep Procedure Set */
2680 /* */
2681 /* These two routines are used during the vertical gray-levels sweep */
2682 /* phase by the generic Draw_Sweep() function. */
2683 /* */
2684 /* NOTES */
2685 /* */
2686 /* - The target pixmap's width *must* be a multiple of 4. */
2687 /* */
2688 /* - You have to use the function Vertical_Sweep_Span() for the gray */
2689 /* span call. */
2690 /* */
2691 /*************************************************************************/
2692
2693 static void
2694 Vertical_Gray_Sweep_Init( RAS_ARGS Short* min,
2695 Short* max )
2696 {
2697 Long pitch, byte_len;
2698
2699
2700 *min = *min & -2;
2701 *max = ( *max + 3 ) & -2;
2702
2703 ras.traceOfs = 0;
2704 pitch = ras.target.pitch;
2705 byte_len = -pitch;
2706 ras.traceIncr = (Short)byte_len;
2707 ras.traceG = ( *min / 2 ) * byte_len;
2708
2709 if ( pitch > 0 )
2710 {
2711 ras.traceG += ( ras.target.rows - 1 ) * pitch;
2712 byte_len = -byte_len;
2713 }
2714
2715 ras.gray_min_x = (Short)byte_len;
2716 ras.gray_max_x = -(Short)byte_len;
2717 }
2718
2719
2720 static void
2721 Vertical_Gray_Sweep_Step( RAS_ARG )
2722 {
2723 Int c1, c2;
2724 PByte pix, bit, bit2;
2725 short* count = (short*)count_table;
2726 Byte* grays;
2727
2728
2729 ras.traceOfs += ras.gray_width;
2730
2731 if ( ras.traceOfs > ras.gray_width )
2732 {
2733 pix = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
2734 grays = ras.grays;
2735
2736 if ( ras.gray_max_x >= 0 )
2737 {
2738 Long last_pixel = ras.target.width - 1;
2739 Int last_cell = last_pixel >> 2;
2740 Int last_bit = last_pixel & 3;
2741 Bool over = 0;
2742
2743
2744 if ( ras.gray_max_x >= last_cell && last_bit != 3 )
2745 {
2746 ras.gray_max_x = last_cell - 1;
2747 over = 1;
2748 }
2749
2750 if ( ras.gray_min_x < 0 )
2751 ras.gray_min_x = 0;
2752
2753 bit = ras.bTarget + ras.gray_min_x;
2754 bit2 = bit + ras.gray_width;
2755
2756 c1 = ras.gray_max_x - ras.gray_min_x;
2757
2758 while ( c1 >= 0 )
2759 {
2760 c2 = count[*bit] + count[*bit2];
2761
2762 if ( c2 )
2763 {
2764 pix[0] = grays[(c2 >> 12) & 0x000F];
2765 pix[1] = grays[(c2 >> 8 ) & 0x000F];
2766 pix[2] = grays[(c2 >> 4 ) & 0x000F];
2767 pix[3] = grays[ c2 & 0x000F];
2768
2769 *bit = 0;
2770 *bit2 = 0;
2771 }
2772
2773 bit++;
2774 bit2++;
2775 pix += 4;
2776 c1--;
2777 }
2778
2779 if ( over )
2780 {
2781 c2 = count[*bit] + count[*bit2];
2782 if ( c2 )
2783 {
2784 switch ( last_bit )
2785 {
2786 case 2:
2787 pix[2] = grays[(c2 >> 4 ) & 0x000F];
2788 case 1:
2789 pix[1] = grays[(c2 >> 8 ) & 0x000F];
2790 default:
2791 pix[0] = grays[(c2 >> 12) & 0x000F];
2792 }
2793
2794 *bit = 0;
2795 *bit2 = 0;
2796 }
2797 }
2798 }
2799
2800 ras.traceOfs = 0;
2801 ras.traceG += ras.traceIncr;
2802
2803 ras.gray_min_x = 32000;
2804 ras.gray_max_x = -32000;
2805 }
2806 }
2807
2808
2809 static void
2810 Horizontal_Gray_Sweep_Span( RAS_ARGS Short y,
2811 FT_F26Dot6 x1,
2812 FT_F26Dot6 x2,
2813 PProfile left,
2814 PProfile right )
2815 {
2816 /* nothing, really */
2817 FT_UNUSED_RASTER;
2818 FT_UNUSED( y );
2819 FT_UNUSED( x1 );
2820 FT_UNUSED( x2 );
2821 FT_UNUSED( left );
2822 FT_UNUSED( right );
2823 }
2824
2825
2826 static void
2827 Horizontal_Gray_Sweep_Drop( RAS_ARGS Short y,
2828 FT_F26Dot6 x1,
2829 FT_F26Dot6 x2,
2830 PProfile left,
2831 PProfile right )
2832 {
2833 Long e1, e2;
2834 PByte pixel;
2835 Byte color;
2836
2837
2838 /* During the horizontal sweep, we only take care of drop-outs */
2839
2840 e1 = CEILING( x1 );
2841 e2 = FLOOR ( x2 );
2842
2843 if ( e1 > e2 )
2844 {
2845 Int dropOutControl = left->flags & 7;
2846
2847
2848 if ( e1 == e2 + ras.precision )
2849 {
2850 switch ( dropOutControl )
2851 {
2852 case 0: /* simple drop-outs including stubs */
2853 e1 = e2;
2854 break;
2855
2856 case 4: /* smart drop-outs including stubs */
2857 e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2858 break;
2859
2860 case 1: /* simple drop-outs excluding stubs */
2861 case 5: /* smart drop-outs excluding stubs */
2862 /* see Vertical_Sweep_Drop for details */
2863
2864 /* rightmost stub test */
2865 if ( left->next == right && left->height <= 0 )
2866 return;
2867
2868 /* leftmost stub test */
2869 if ( right->next == left && left->start == y )
2870 return;
2871
2872 if ( dropOutControl == 1 )
2873 e1 = e2;
2874 else
2875 e1 = FLOOR( ( x1 + x2 - 1 ) / 2 + ras.precision_half );
2876
2877 break;
2878
2879 default: /* modes 2, 3, 6, 7 */
2880 return; /* no drop-out control */
2881 }
2882 }
2883 else
2884 return;
2885 }
2886
2887 if ( e1 >= 0 )
2888 {
2889 if ( x2 - x1 >= ras.precision_half )
2890 color = ras.grays[2];
2891 else
2892 color = ras.grays[1];
2893
2894 e1 = TRUNC( e1 ) / 2;
2895 if ( e1 < ras.target.rows )
2896 {
2897 pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
2898 if ( ras.target.pitch > 0 )
2899 pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
2900
2901 if ( pixel[0] == ras.grays[0] )
2902 pixel[0] = color;
2903 }
2904 }
2905 }
2906
2907
2908 #endif /* FT_RASTER_OPTION_ANTI_ALIASING */
2909
2910
2911 /*************************************************************************/
2912 /* */
2913 /* Generic Sweep Drawing routine */
2914 /* */
2915 /*************************************************************************/
2916
2917 static Bool
2918 Draw_Sweep( RAS_ARG )
2919 {
2920 Short y, y_change, y_height;
2921
2922 PProfile P, Q, P_Left, P_Right;
2923
2924 Short min_Y, max_Y, top, bottom, dropouts;
2925
2926 Long x1, x2, xs, e1, e2;
2927
2928 TProfileList waiting;
2929 TProfileList draw_left, draw_right;
2930
2931
2932 /* initialize empty linked lists */
2933
2934 Init_Linked( &waiting );
2935
2936 Init_Linked( &draw_left );
2937 Init_Linked( &draw_right );
2938
2939 /* first, compute min and max Y */
2940
2941 P = ras.fProfile;
2942 max_Y = (Short)TRUNC( ras.minY );
2943 min_Y = (Short)TRUNC( ras.maxY );
2944
2945 while ( P )
2946 {
2947 Q = P->link;
2948
2949 bottom = (Short)P->start;
2950 top = (Short)( P->start + P->height - 1 );
2951
2952 if ( min_Y > bottom )
2953 min_Y = bottom;
2954 if ( max_Y < top )
2955 max_Y = top;
2956
2957 P->X = 0;
2958 InsNew( &waiting, P );
2959
2960 P = Q;
2961 }
2962
2963 /* check the Y-turns */
2964 if ( ras.numTurns == 0 )
2965 {
2966 ras.error = Raster_Err_Invalid;
2967 return FAILURE;
2968 }
2969
2970 /* now initialize the sweep */
2971
2972 ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
2973
2974 /* then compute the distance of each profile from min_Y */
2975
2976 P = waiting;
2977
2978 while ( P )
2979 {
2980 P->countL = (UShort)( P->start - min_Y );
2981 P = P->link;
2982 }
2983
2984 /* let's go */
2985
2986 y = min_Y;
2987 y_height = 0;
2988
2989 if ( ras.numTurns > 0 &&
2990 ras.sizeBuff[-ras.numTurns] == min_Y )
2991 ras.numTurns--;
2992
2993 while ( ras.numTurns > 0 )
2994 {
2995 /* check waiting list for new activations */
2996
2997 P = waiting;
2998
2999 while ( P )
3000 {
3001 Q = P->link;
3002 P->countL -= y_height;
3003 if ( P->countL == 0 )
3004 {
3005 DelOld( &waiting, P );
3006
3007 if ( P->flags & Flow_Up )
3008 InsNew( &draw_left, P );
3009 else
3010 InsNew( &draw_right, P );
3011 }
3012
3013 P = Q;
3014 }
3015
3016 /* sort the drawing lists */
3017
3018 Sort( &draw_left );
3019 Sort( &draw_right );
3020
3021 y_change = (Short)ras.sizeBuff[-ras.numTurns--];
3022 y_height = (Short)( y_change - y );
3023
3024 while ( y < y_change )
3025 {
3026 /* let's trace */
3027
3028 dropouts = 0;
3029
3030 P_Left = draw_left;
3031 P_Right = draw_right;
3032
3033 while ( P_Left )
3034 {
3035 x1 = P_Left ->X;
3036 x2 = P_Right->X;
3037
3038 if ( x1 > x2 )
3039 {
3040 xs = x1;
3041 x1 = x2;
3042 x2 = xs;
3043 }
3044
3045 e1 = FLOOR( x1 );
3046 e2 = CEILING( x2 );
3047
3048 if ( x2 - x1 <= ras.precision &&
3049 e1 != x1 && e2 != x2 )
3050 {
3051 if ( e1 > e2 || e2 == e1 + ras.precision )
3052 {
3053 Int dropOutControl = P_Left->flags & 7;
3054
3055
3056 if ( dropOutControl != 2 )
3057 {
3058 /* a drop-out was detected */
3059
3060 P_Left ->X = x1;
3061 P_Right->X = x2;
3062
3063 /* mark profile for drop-out processing */
3064 P_Left->countL = 1;
3065 dropouts++;
3066 }
3067
3068 goto Skip_To_Next;
3069 }
3070 }
3071
3072 ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
3073
3074 Skip_To_Next:
3075
3076 P_Left = P_Left->link;
3077 P_Right = P_Right->link;
3078 }
3079
3080 /* handle drop-outs _after_ the span drawing -- */
3081 /* drop-out processing has been moved out of the loop */
3082 /* for performance tuning */
3083 if ( dropouts > 0 )
3084 goto Scan_DropOuts;
3085
3086 Next_Line:
3087
3088 ras.Proc_Sweep_Step( RAS_VAR );
3089
3090 y++;
3091
3092 if ( y < y_change )
3093 {
3094 Sort( &draw_left );
3095 Sort( &draw_right );
3096 }
3097 }
3098
3099 /* now finalize the profiles that need it */
3100
3101 P = draw_left;
3102 while ( P )
3103 {
3104 Q = P->link;
3105 if ( P->height == 0 )
3106 DelOld( &draw_left, P );
3107 P = Q;
3108 }
3109
3110 P = draw_right;
3111 while ( P )
3112 {
3113 Q = P->link;
3114 if ( P->height == 0 )
3115 DelOld( &draw_right, P );
3116 P = Q;
3117 }
3118 }
3119
3120 /* for gray-scaling, flush the bitmap scanline cache */
3121 while ( y <= max_Y )
3122 {
3123 ras.Proc_Sweep_Step( RAS_VAR );
3124 y++;
3125 }
3126
3127 return SUCCESS;
3128
3129 Scan_DropOuts:
3130
3131 P_Left = draw_left;
3132 P_Right = draw_right;
3133
3134 while ( P_Left )
3135 {
3136 if ( P_Left->countL )
3137 {
3138 P_Left->countL = 0;
3139 #if 0
3140 dropouts--; /* -- this is useful when debugging only */
3141 #endif
3142 ras.Proc_Sweep_Drop( RAS_VARS y,
3143 P_Left->X,
3144 P_Right->X,
3145 P_Left,
3146 P_Right );
3147 }
3148
3149 P_Left = P_Left->link;
3150 P_Right = P_Right->link;
3151 }
3152
3153 goto Next_Line;
3154 }
3155
3156
3157 /*************************************************************************/
3158 /* */
3159 /* <Function> */
3160 /* Render_Single_Pass */
3161 /* */
3162 /* <Description> */
3163 /* Perform one sweep with sub-banding. */
3164 /* */
3165 /* <Input> */
3166 /* flipped :: If set, flip the direction of the outline. */
3167 /* */
3168 /* <Return> */
3169 /* Renderer error code. */
3170 /* */
3171 static int
3172 Render_Single_Pass( RAS_ARGS Bool flipped )
3173 {
3174 Short i, j, k;
3175
3176
3177 while ( ras.band_top >= 0 )
3178 {
3179 ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
3180 ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
3181
3182 ras.top = ras.buff;
3183
3184 ras.error = Raster_Err_None;
3185
3186 if ( Convert_Glyph( RAS_VARS flipped ) )
3187 {
3188 if ( ras.error != Raster_Err_Overflow )
3189 return FAILURE;
3190
3191 ras.error = Raster_Err_None;
3192
3193 /* sub-banding */
3194
3195 #ifdef DEBUG_RASTER
3196 ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
3197 #endif
3198
3199 i = ras.band_stack[ras.band_top].y_min;
3200 j = ras.band_stack[ras.band_top].y_max;
3201
3202 k = (Short)( ( i + j ) / 2 );
3203
3204 if ( ras.band_top >= 7 || k < i )
3205 {
3206 ras.band_top = 0;
3207 ras.error = Raster_Err_Invalid;
3208
3209 return ras.error;
3210 }
3211
3212 ras.band_stack[ras.band_top + 1].y_min = k;
3213 ras.band_stack[ras.band_top + 1].y_max = j;
3214
3215 ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
3216
3217 ras.band_top++;
3218 }
3219 else
3220 {
3221 if ( ras.fProfile )
3222 if ( Draw_Sweep( RAS_VAR ) )
3223 return ras.error;
3224 ras.band_top--;
3225 }
3226 }
3227
3228 return SUCCESS;
3229 }
3230
3231
3232 /*************************************************************************/
3233 /* */
3234 /* <Function> */
3235 /* Render_Glyph */
3236 /* */
3237 /* <Description> */
3238 /* Render a glyph in a bitmap. Sub-banding if needed. */
3239 /* */
3240 /* <Return> */
3241 /* FreeType error code. 0 means success. */
3242 /* */
3243 FT_LOCAL_DEF( FT_Error )
3244 Render_Glyph( RAS_ARG )
3245 {
3246 FT_Error error;
3247
3248
3249 Set_High_Precision( RAS_VARS ras.outline.flags &
3250 FT_OUTLINE_HIGH_PRECISION );
3251 ras.scale_shift = ras.precision_shift;
3252
3253 if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
3254 ras.dropOutControl = 2;
3255 else
3256 {
3257 if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
3258 ras.dropOutControl = 4;
3259 else
3260 ras.dropOutControl = 0;
3261
3262 if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
3263 ras.dropOutControl += 1;
3264 }
3265
3266 ras.second_pass = (FT_Byte)( !( ras.outline.flags &
3267 FT_OUTLINE_SINGLE_PASS ) );
3268
3269 /* Vertical Sweep */
3270 ras.Proc_Sweep_Init = Vertical_Sweep_Init;
3271 ras.Proc_Sweep_Span = Vertical_Sweep_Span;
3272 ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
3273 ras.Proc_Sweep_Step = Vertical_Sweep_Step;
3274
3275 ras.band_top = 0;
3276 ras.band_stack[0].y_min = 0;
3277 ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
3278
3279 ras.bWidth = (unsigned short)ras.target.width;
3280 ras.bTarget = (Byte*)ras.target.buffer;
3281
3282 if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
3283 return error;
3284
3285 /* Horizontal Sweep */
3286 if ( ras.second_pass && ras.dropOutControl != 2 )
3287 {
3288 ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3289 ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
3290 ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
3291 ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3292
3293 ras.band_top = 0;
3294 ras.band_stack[0].y_min = 0;
3295 ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
3296
3297 if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
3298 return error;
3299 }
3300
3301 return Raster_Err_None;
3302 }
3303
3304
3305 #ifdef FT_RASTER_OPTION_ANTI_ALIASING
3306
3307 /*************************************************************************/
3308 /* */
3309 /* <Function> */
3310 /* Render_Gray_Glyph */
3311 /* */
3312 /* <Description> */
3313 /* Render a glyph with grayscaling. Sub-banding if needed. */
3314 /* */
3315 /* <Return> */
3316 /* FreeType error code. 0 means success. */
3317 /* */
3318 FT_LOCAL_DEF( FT_Error )
3319 Render_Gray_Glyph( RAS_ARG )
3320 {
3321 Long pixel_width;
3322 FT_Error error;
3323
3324
3325 Set_High_Precision( RAS_VARS ras.outline.flags &
3326 FT_OUTLINE_HIGH_PRECISION );
3327 ras.scale_shift = ras.precision_shift + 1;
3328
3329 if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
3330 ras.dropOutControl = 2;
3331 else
3332 {
3333 if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
3334 ras.dropOutControl = 4;
3335 else
3336 ras.dropOutControl = 0;
3337
3338 if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
3339 ras.dropOutControl += 1;
3340 }
3341
3342 ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
3343
3344 /* Vertical Sweep */
3345
3346 ras.band_top = 0;
3347 ras.band_stack[0].y_min = 0;
3348 ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
3349
3350 ras.bWidth = ras.gray_width;
3351 pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
3352
3353 if ( ras.bWidth > pixel_width )
3354 ras.bWidth = pixel_width;
3355
3356 ras.bWidth = ras.bWidth * 8;
3357 ras.bTarget = (Byte*)ras.gray_lines;
3358 ras.gTarget = (Byte*)ras.target.buffer;
3359
3360 ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
3361 ras.Proc_Sweep_Span = Vertical_Sweep_Span;
3362 ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
3363 ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
3364
3365 error = Render_Single_Pass( RAS_VARS 0 );
3366 if ( error )
3367 return error;
3368
3369 /* Horizontal Sweep */
3370 if ( ras.second_pass && ras.dropOutControl != 2 )
3371 {
3372 ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
3373 ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
3374 ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
3375 ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
3376
3377 ras.band_top = 0;
3378 ras.band_stack[0].y_min = 0;
3379 ras.band_stack[0].y_max = ras.target.width * 2 - 1;
3380
3381 error = Render_Single_Pass( RAS_VARS 1 );
3382 if ( error )
3383 return error;
3384 }
3385
3386 return Raster_Err_None;
3387 }
3388
3389 #else /* !FT_RASTER_OPTION_ANTI_ALIASING */
3390
3391 FT_LOCAL_DEF( FT_Error )
3392 Render_Gray_Glyph( RAS_ARG )
3393 {
3394 FT_UNUSED_RASTER;
3395
3396 return Raster_Err_Unsupported;
3397 }
3398
3399 #endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
3400
3401
3402 static void
3403 ft_black_init( black_PRaster raster )
3404 {
3405 #ifdef FT_RASTER_OPTION_ANTI_ALIASING
3406 FT_UInt n;
3407
3408
3409 /* set default 5-levels gray palette */
3410 for ( n = 0; n < 5; n++ )
3411 raster->grays[n] = n * 255 / 4;
3412
3413 raster->gray_width = RASTER_GRAY_LINES / 2;
3414 #else
3415 FT_UNUSED( raster );
3416 #endif
3417 }
3418
3419
3420 /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
3421 /**** a static object. *****/
3422
3423
3424 #ifdef _STANDALONE_
3425
3426
3427 static int
3428 ft_black_new( void* memory,
3429 FT_Raster *araster )
3430 {
3431 static black_TRaster the_raster;
3432 FT_UNUSED( memory );
3433
3434
3435 *araster = (FT_Raster)&the_raster;
3436 FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
3437 ft_black_init( &the_raster );
3438
3439 return 0;
3440 }
3441
3442
3443 static void
3444 ft_black_done( FT_Raster raster )
3445 {
3446 /* nothing */
3447 FT_UNUSED( raster );
3448 }
3449
3450
3451 #else /* !_STANDALONE_ */
3452
3453
3454 static int
3455 ft_black_new( FT_Memory memory,
3456 black_PRaster *araster )
3457 {
3458 FT_Error error;
3459 black_PRaster raster = NULL;
3460
3461
3462 *araster = 0;
3463 if ( !FT_NEW( raster ) )
3464 {
3465 raster->memory = memory;
3466 ft_black_init( raster );
3467
3468 *araster = raster;
3469 }
3470
3471 return error;
3472 }
3473
3474
3475 static void
3476 ft_black_done( black_PRaster raster )
3477 {
3478 FT_Memory memory = (FT_Memory)raster->memory;
3479
3480
3481 FT_FREE( raster );
3482 }
3483
3484
3485 #endif /* !_STANDALONE_ */
3486
3487
3488 static void
3489 ft_black_reset( black_PRaster raster,
3490 char* pool_base,
3491 long pool_size )
3492 {
3493 if ( raster )
3494 {
3495 if ( pool_base && pool_size >= (long)sizeof ( black_TWorker ) + 2048 )
3496 {
3497 black_PWorker worker = (black_PWorker)pool_base;
3498
3499
3500 raster->buffer = pool_base + ( ( sizeof ( *worker ) + 7 ) & ~7 );
3501 raster->buffer_size = pool_base + pool_size - (char*)raster->buffer;
3502 raster->worker = worker;
3503 }
3504 else
3505 {
3506 raster->buffer = NULL;
3507 raster->buffer_size = 0;
3508 raster->worker = NULL;
3509 }
3510 }
3511 }
3512
3513
3514 static void
3515 ft_black_set_mode( black_PRaster raster,
3516 unsigned long mode,
3517 const char* palette )
3518 {
3519 #ifdef FT_RASTER_OPTION_ANTI_ALIASING
3520
3521 if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
3522 {
3523 /* set 5-levels gray palette */
3524 raster->grays[0] = palette[0];
3525 raster->grays[1] = palette[1];
3526 raster->grays[2] = palette[2];
3527 raster->grays[3] = palette[3];
3528 raster->grays[4] = palette[4];
3529 }
3530
3531 #else
3532
3533 FT_UNUSED( raster );
3534 FT_UNUSED( mode );
3535 FT_UNUSED( palette );
3536
3537 #endif
3538 }
3539
3540
3541 static int
3542 ft_black_render( black_PRaster raster,
3543 const FT_Raster_Params* params )
3544 {
3545 const FT_Outline* outline = (const FT_Outline*)params->source;
3546 const FT_Bitmap* target_map = params->target;
3547 black_PWorker worker;
3548
3549
3550 if ( !raster || !raster->buffer || !raster->buffer_size )
3551 return Raster_Err_Not_Ini;
3552
3553 if ( !outline )
3554 return Raster_Err_Invalid;
3555
3556 /* return immediately if the outline is empty */
3557 if ( outline->n_points == 0 || outline->n_contours <= 0 )
3558 return Raster_Err_None;
3559
3560 if ( !outline->contours || !outline->points )
3561 return Raster_Err_Invalid;
3562
3563 if ( outline->n_points !=
3564 outline->contours[outline->n_contours - 1] + 1 )
3565 return Raster_Err_Invalid;
3566
3567 worker = raster->worker;
3568
3569 /* this version of the raster does not support direct rendering, sorry */
3570 if ( params->flags & FT_RASTER_FLAG_DIRECT )
3571 return Raster_Err_Unsupported;
3572
3573 if ( !target_map )
3574 return Raster_Err_Invalid;
3575
3576 /* nothing to do */
3577 if ( !target_map->width || !target_map->rows )
3578 return Raster_Err_None;
3579
3580 if ( !target_map->buffer )
3581 return Raster_Err_Invalid;
3582
3583 ras.outline = *outline;
3584 ras.target = *target_map;
3585
3586 worker->buff = (PLong) raster->buffer;
3587 worker->sizeBuff = worker->buff +
3588 raster->buffer_size / sizeof ( Long );
3589 #ifdef FT_RASTER_OPTION_ANTI_ALIASING
3590 worker->grays = raster->grays;
3591 worker->gray_width = raster->gray_width;
3592
3593 FT_MEM_ZERO( worker->gray_lines, worker->gray_width * 2 );
3594 #endif
3595
3596 return ( params->flags & FT_RASTER_FLAG_AA )
3597 ? Render_Gray_Glyph( RAS_VAR )
3598 : Render_Glyph( RAS_VAR );
3599 }
3600
3601
3602 FT_DEFINE_RASTER_FUNCS( ft_standard_raster,
3603 FT_GLYPH_FORMAT_OUTLINE,
3604 (FT_Raster_New_Func) ft_black_new,
3605 (FT_Raster_Reset_Func) ft_black_reset,
3606 (FT_Raster_Set_Mode_Func)ft_black_set_mode,
3607 (FT_Raster_Render_Func) ft_black_render,
3608 (FT_Raster_Done_Func) ft_black_done
3609 )
3610
3611
3612 /* END */
FT_OUTLINE_SINGLE_PASS
#define FT_OUTLINE_SINGLE_PASS
Definition: ftimage.h:483
FT_Raster_Params_
Definition: ftimage.h:1104
FT_Error
int FT_Error
Definition: fttypes.h:296
bottom
GLint GLint bottom
Definition: glew.h:7291
FT_Raster_Done_Func
#define FT_Raster_Done_Func
Definition: ftimage.h:1164
Decompose_Curve
static Bool Decompose_Curve(RAS_ARGS UShort first, UShort last, int flipped)
Definition: ftraster.c:1797
profile
png_charp profile
Definition: pngrutil.c:1240
PAlignment
union Alignment_ * PAlignment
Raster_Err_Invalid
#define Raster_Err_Invalid
Definition: ftraster.c:235
Set_High_Precision
static void Set_High_Precision(RAS_ARGS Int High)
Definition: ftraster.c:661
black_TWorker
struct black_TWorker_ black_TWorker
Definition: ftraster.c:416
h
GLfloat GLfloat GLfloat GLfloat h
Definition: glew.h:7294
void
GLvoid **typedef void(GLAPIENTRY *PFNGLGETVERTEXATTRIBDVPROC)(GLuint
Definition: glew.h:1824
Raster_Err_None
#define Raster_Err_None
Definition: ftraster.c:231
ft_black_reset
static void ft_black_reset(black_PRaster raster, char *pool_base, long pool_size)
Definition: ftraster.c:3489
color
GLuint color
Definition: glew.h:7185
FT_Raster
struct FT_RasterRec_ * FT_Raster
Definition: ftimage.h:862
Horizontal_Sweep_Init
static void Horizontal_Sweep_Init(RAS_ARGS Short *min, Short *max)
Definition: ftraster.c:2495
left
GLint left
Definition: glew.h:7291
FT_CURVE_TAG_CUBIC
#define FT_CURVE_TAG_CUBIC
Definition: ftimage.h:518
FT_Raster_Set_Mode_Func
#define FT_Raster_Set_Mode_Func
Definition: ftimage.h:1225
FT_Raster_New_Func
#define FT_Raster_New_Func
Definition: ftimage.h:1147
RASTER_GRAY_LINES
#define RASTER_GRAY_LINES
Definition: ftraster.c:159
FT_OUTLINE_IGNORE_DROPOUTS
#define FT_OUTLINE_IGNORE_DROPOUTS
Definition: ftimage.h:478
start
GLuint start
Definition: glew.h:1239
f
GLclampf f
Definition: glew.h:3390
FT_Outline_::n_contours
short n_contours
Definition: ftimage.h:385
FT_UNUSED_RASTER
#define FT_UNUSED_RASTER
Definition: ftraster.c:410
TSplitter
void(* TSplitter)(TPoint *base)
Definition: ftraster.c:1234
Vertical_Sweep_Step
static void Vertical_Sweep_Step(RAS_ARG)
Definition: ftraster.c:2479
SCALED
#define SCALED(x)
Definition: ftraster.c:445
Insert_Y_Turn
static Bool Insert_Y_Turn(RAS_ARGS Int y)
Definition: ftraster.c:868
TProfileList
PProfile TProfileList
Definition: ftraster.c:366
Vertical_Sweep_Init
static void Vertical_Sweep_Init(RAS_ARGS Short *min, Short *max)
Definition: ftraster.c:2243
TRUE
#define TRUE
Definition: ftraster.c:265
k
int32_t k
Definition: e_log.c:102
e0
int32_t e0
Definition: e_rem_pio2.c:100
Raster_Err_Overflow
#define Raster_Err_Overflow
Definition: ftraster.c:233
n
GLclampd n
Definition: glew.h:7287
black_TBand
struct black_TBand_ black_TBand
Overshoot_Top
#define Overshoot_Top
Definition: ftraster.c:329
FT_Outline_::contours
short * contours
Definition: ftimage.h:390
PByte
unsigned char * PByte
Definition: ftraster.c:306
x
EGLSurface EGLint x
Definition: eglext.h:293
e
return Display return Display Bool Bool int int e
Definition: SDL_x11sym.h:30
FT_Raster_Params_::target
const FT_Bitmap * target
Definition: ftimage.h:1106
Function_Sweep_Init
void Function_Sweep_Init(RAS_ARGS Short *min, Short *max)
Definition: ftraster.c:421
FT_RASTER_FLAG_AA
#define FT_RASTER_FLAG_AA
Definition: ftimage.h:1043
Unknown_State
Definition: ftraster.c:336
FT_Outline_
Definition: ftimage.h:383
j
int32_t j
Definition: e_log.c:102
NULL
#define NULL
Definition: ftraster.c:273
Raster_Err_Not_Ini
#define Raster_Err_Not_Ini
Definition: ftraster.c:232
height
EGLSurface EGLint EGLint EGLint EGLint height
Definition: eglext.h:293
Draw_Sweep
static Bool Draw_Sweep(RAS_ARG)
Definition: ftraster.c:2918
a
GLboolean GLboolean GLboolean GLboolean a
Definition: glew.h:8736
TStates_
TStates_
Definition: ftraster.c:334
ft_black_set_mode
static void ft_black_set_mode(black_PRaster raster, unsigned long mode, const char *palette)
Definition: ftraster.c:3515
ftimage.h
FT_DEFINE_RASTER_FUNCS
#define FT_DEFINE_RASTER_FUNCS(class_, glyph_format_, raster_new_,raster_reset_, raster_set_mode_,raster_render_, raster_done_)
Definition: ftobjs.h:997
PProfileList
PProfile * PProfileList
Definition: ftraster.c:367
d
return Display return Display Bool Bool int d
Definition: SDL_x11sym.h:30
Bezier_Up
static Bool Bezier_Up(RAS_ARGS Int degree, TSplitter splitter, Long miny, Long maxy)
Definition: ftraster.c:1259
TProfile
struct TProfile_ TProfile
Definition: ftraster.c:344
Descending_State
Definition: ftraster.c:338
bits
#define bits
Definition: infblock.c:15
RAS_VAR
#define RAS_VAR
Definition: ftraster.c:408
FALSE
#define FALSE
Definition: ftraster.c:269
Split_Conic
static void Split_Conic(TPoint *base)
Definition: ftraster.c:983
if
if(!yyg->yy_init)
Definition: glslang_lex.cpp:1037
IS_BOTTOM_OVERSHOOT
#define IS_BOTTOM_OVERSHOOT(x)
Definition: ftraster.c:447
y1
GLuint GLfloat GLfloat GLfloat GLfloat y1
Definition: glew.h:11582
SUCCESS
#define SUCCESS
Definition: ftraster.c:277
y2
GLfixed GLfixed GLfixed y2
Definition: glext.h:4559
black_TRaster
struct black_TRaster_ black_TRaster
FT_TRACE1
#define FT_TRACE1(varformat)
Definition: ftdebug.h:158
FT_CURVE_TAG_HAS_SCANMODE
#define FT_CURVE_TAG_HAS_SCANMODE
Definition: ftimage.h:520
FT_ERROR
#define FT_ERROR(varformat)
Definition: ftdebug.h:181
ft_black_render
static int ft_black_render(black_PRaster raster, const FT_Raster_Params *params)
Definition: ftraster.c:3542
FT_Byte
unsigned char FT_Byte
Definition: fttypes.h:150
UShort
unsigned short UShort
Definition: ftraster.c:303
params
GLenum GLvoid ** params
Definition: gl2ext.h:806
DelOld
static void DelOld(PProfileList list, PProfile profile)
Definition: ftraster.c:2149
RAS_VARS
#define RAS_VARS
Definition: ftraster.c:407
target
EGLContext EGLenum target
Definition: eglext.h:87
Alignment
union Alignment_ Alignment
Convert_Glyph
static Bool Convert_Glyph(RAS_ARGS int flipped)
Definition: ftraster.c:2021
Pixel_Bits
#define Pixel_Bits
Definition: ftraster.c:289
buffer
EGLContext EGLenum EGLClientBuffer buffer
Definition: eglext.h:87
FT_FREE
#define FT_FREE(ptr)
Definition: ftmemory.h:286
first
GLint first
Definition: gl2ext.h:1011
result
GLuint64EXT * result
Definition: glew.h:12708
Render_Glyph
Render_Glyph(RAS_ARG)
Definition: ftraster.c:3244
FT_LOCAL_DEF
#define FT_LOCAL_DEF(x)
Definition: ftconfig.h:467
New_Profile
static Bool New_Profile(RAS_ARGS TStates aState, Bool overshoot)
Definition: ftraster.c:725
ftraster.h
FT_Raster_Render_Func
#define FT_Raster_Render_Func
Definition: ftimage.h:1266
Init_Linked
static void Init_Linked(TProfileList *l)
Definition: ftraster.c:2105
for
for(;;)
Definition: glslang_tab.cpp:4773
Short
short Short
Definition: ftraster.c:302
FAILURE
#define FAILURE
Definition: ftraster.c:281
error
FT_Error error
Definition: cffdrivr.c:407
Flat_State
Definition: ftraster.c:339
FT_Vector_::x
FT_Pos x
Definition: ftimage.h:77
Vertical_Sweep_Drop
static void Vertical_Sweep_Drop(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:2330
Ascending_State
Definition: ftraster.c:337
FT_OUTLINE_HIGH_PRECISION
#define FT_OUTLINE_HIGH_PRECISION
Definition: ftimage.h:482
ft_black_done
static void ft_black_done(black_PRaster raster)
Definition: ftraster.c:3476
FT_Bitmap_
Definition: ftimage.h:310
count
GLint GLsizei count
Definition: gl2ext.h:1011
rastpic.h
p
GLfloat GLfloat p
Definition: glew.h:14938
Render_Single_Pass
static int Render_Single_Pass(RAS_ARGS Bool flipped)
Definition: ftraster.c:3172
Cubic_To
static Bool Cubic_To(RAS_ARGS Long cx1, Long cy1, Long cx2, Long cy2, Long x, Long y)
Definition: ftraster.c:1657
SWAP_
#define SWAP_(x, y)
Definition: ftraster.c:1765
FT_Vector_::y
FT_Pos y
Definition: ftimage.h:78
c
const GLfloat * c
Definition: glew.h:14913
FRAC
#define FRAC(x)
Definition: ftraster.c:444
UInt
unsigned int UInt
Definition: ftraster.c:301
limit
GLint limit
Definition: glew.h:11829
FT_Vector_
Definition: ftimage.h:75
Horizontal_Sweep_Drop
static void Horizontal_Sweep_Drop(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:2549
FT_MEM_ZERO
#define FT_MEM_ZERO(dest, count)
Definition: ftraster.c:247
FT_Raster_Params_::flags
int flags
Definition: ftimage.h:1108
TRUNC
#define TRUNC(x)
Definition: ftraster.c:443
top
GLfloat GLfloat GLfloat top
Definition: glew.h:13816
Function_Sweep_Span
void Function_Sweep_Span(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:425
Overshoot_Bottom
#define Overshoot_Bottom
Definition: ftraster.c:330
FT_Outline_::n_points
short n_points
Definition: ftimage.h:386
Finalize_Profile_Table
static Bool Finalize_Profile_Table(RAS_ARG)
Definition: ftraster.c:919
Long
long Long
Definition: ftraster.c:304
Function_Sweep_Step
void Function_Sweep_Step(RAS_ARG)
Definition: ftraster.c:432
Horizontal_Sweep_Step
static void Horizontal_Sweep_Step(RAS_ARG)
Definition: ftraster.c:2667
FT_Memory
typedefFT_BEGIN_HEADER struct FT_MemoryRec_ * FT_Memory
Definition: ftsystem.h:66
End_Profile
static Bool End_Profile(RAS_ARGS Bool overshoot)
Definition: ftraster.c:798
Vertical_Sweep_Span
static void Vertical_Sweep_Span(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:2262
Sort
static void Sort(PProfileList list)
Definition: ftraster.c:2184
x1
GLuint GLfloat GLfloat GLfloat x1
Definition: glew.h:11582
FT_OUTLINE_INCLUDE_STUBS
#define FT_OUTLINE_INCLUDE_STUBS
Definition: ftimage.h:480
FT_RASTER_FLAG_DIRECT
#define FT_RASTER_FLAG_DIRECT
Definition: ftimage.h:1044
sizeof
sizeof(FT_AutofitterRec)
y
EGLSurface EGLint EGLint y
Definition: eglext.h:293
FT_F26Dot6
signed long FT_F26Dot6
Definition: fttypes.h:272
RAS_ARGS
#define RAS_ARGS
Definition: ftraster.c:404
l
GLdouble l
Definition: glew.h:8383
FT_Raster_Reset_Func
#define FT_Raster_Reset_Func
Definition: ftimage.h:1199
TPoint
struct TPoint_ TPoint
MaxBezier
#define MaxBezier
Definition: ftraster.c:285
FT_TRACE6
#define FT_TRACE6(varformat)
Definition: ftdebug.h:163
SMulDiv
#define SMulDiv
Definition: ftraster.c:258
Line_To
static Bool Line_To(RAS_ARGS Long x, Long y)
Definition: ftraster.c:1439
Flow_Up
#define Flow_Up
Definition: ftraster.c:328
ft_black_init
static void ft_black_init(black_PRaster raster)
Definition: ftraster.c:3403
ft2build.h
IS_TOP_OVERSHOOT
#define IS_TOP_OVERSHOOT(x)
Definition: ftraster.c:448
offset
GLintptr offset
Definition: glew.h:1668
Int
int Int
Definition: ftraster.c:300
black_PRaster
struct black_TRaster_ * black_PRaster
flags
GLenum GLsizei GLsizei GLsizei GLsizei GLbitfield flags
Definition: glew.h:2767
CEILING
#define CEILING(x)
Definition: ftraster.c:442
Raster_Err_Neg_Height
#define Raster_Err_Neg_Height
Definition: ftraster.c:234
FT_UInt
unsigned int FT_UInt
Definition: fttypes.h:227
Byte
unsigned char Byte
Definition: zconf.h:219
Conic_To
static Bool Conic_To(RAS_ARGS Long cx, Long cy, Long x, Long y)
Definition: ftraster.c:1537
x2
GLfixed GLfixed x2
Definition: glext.h:4559
RAS_ARG
#define RAS_ARG
Definition: ftraster.c:405
String.h
FT_OUTLINE_SMART_DROPOUTS
#define FT_OUTLINE_SMART_DROPOUTS
Definition: ftimage.h:479
PProfile
TProfile * PProfile
Definition: ftraster.c:345
b
GLdouble GLdouble GLdouble b
Definition: glew.h:8383
FT_CURVE_TAG_ON
#define FT_CURVE_TAG_ON
Definition: ftimage.h:516
points
GLuint GLdouble GLdouble GLint GLint const GLdouble * points
Definition: glew.h:3337
FT_MAKE_TAG
#define FT_MAKE_TAG(_x1, _x2, _x3, _x4)
Definition: fttypes.h:476
FT_CURVE_TAG_CONIC
#define FT_CURVE_TAG_CONIC
Definition: ftimage.h:517
rasterrs.h
min
#define min(x, y)
Definition: os.h:75
ras
#define ras
Definition: ftraster.c:570
FMulDiv
#define FMulDiv(a, b, c)
Definition: ftraster.c:253
FT_NEW
#define FT_NEW(ptr)
Definition: ftmemory.h:288
PLong
long * PLong
Definition: ftraster.c:304
i
int i
Definition: pngrutil.c:1377
precision
GLenum GLint GLint * precision
Definition: glew.h:3391
right
GLfloat right
Definition: glew.h:13816
FT_CURVE_TAG
#define FT_CURVE_TAG(flag)
Definition: ftimage.h:514
FT_Raster_Params_::source
const void * source
Definition: ftimage.h:1107
Bool
char Bool
Definition: ftraster.c:307
FLOOR
#define FLOOR(x)
Definition: ftraster.c:441
PUShort
unsigned short * PUShort
Definition: ftraster.c:303
max
#define max(x, y)
Definition: os.h:79
Raster_Err_Unsupported
#define Raster_Err_Unsupported
Definition: ftraster.c:236
Horizontal_Sweep_Span
static void Horizontal_Sweep_Span(RAS_ARGS Short y, FT_F26Dot6 x1, FT_F26Dot6 x2, PProfile left, PProfile right)
Definition: ftraster.c:2506
Line_Up
static Bool Line_Up(RAS_ARGS Long x1, Long y1, Long x2, Long y2, Long miny, Long maxy)
Definition: ftraster.c:1073
FT_UNUSED
#define FT_UNUSED(arg)
Definition: ftconfig.h:101
mode
GLenum mode
Definition: glew.h:2394
Line_Down
static Bool Line_Down(RAS_ARGS Long x1, Long y1, Long x2, Long y2, Long miny, Long maxy)
Definition: ftraster.c:1212
FT_Outline_::points
FT_Vector * points
Definition: ftimage.h:388
TStates
enum TStates_ TStates
Bezier_Down
static Bool Bezier_Down(RAS_ARGS Int degree, TSplitter splitter, Long miny, Long maxy)
Definition: ftraster.c:1392
Split_Cubic
static void Split_Cubic(TPoint *base)
Definition: ftraster.c:1020
ftmisc.h
FT_GLYPH_FORMAT_OUTLINE
FT_Module_Constructor FT_GLYPH_FORMAT_OUTLINE
Definition: ftrend1.c:283
InsNew
static void InsNew(PProfileList list, PProfile profile)
Definition: ftraster.c:2118
black_PWorker
struct black_TWorker_ * black_PWorker
Definition: ftraster.c:416
AlignProfileSize
#define AlignProfileSize
Definition: ftraster.c:380
ft_black_new
static int ft_black_new(FT_Memory memory, black_PRaster *araster)
Definition: ftraster.c:3455
Render_Gray_Glyph
Render_Gray_Glyph(RAS_ARG)
Definition: ftraster.c:3392
size
GLsizei size
Definition: gl2ext.h:1467