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