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