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