ftraster.c
上传用户:yisoukefu
上传日期:2020-08-09
资源大小:39506k
文件大小:106k
源码类别:

其他游戏

开发平台:

Visual C++

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  ftraster.c                                                             */
  4. /*                                                                         */
  5. /*    The FreeType glyph rasterizer (body).                                */
  6. /*                                                                         */
  7. /*  Copyright 1996-2001, 2002, 2003, 2005, 2007 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.   /* This file can be compiled without the rest of the FreeType engine, by */
  20.   /* defining the _STANDALONE_ macro when compiling it.  You also need to  */
  21.   /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir)           */
  22.   /* directory.  Typically, you should do something like                   */
  23.   /*                                                                       */
  24.   /* - copy `src/raster/ftraster.c' (this file) to your current directory  */
  25.   /*                                                                       */
  26.   /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h'         */
  27.   /*   to your current directory                                           */
  28.   /*                                                                       */
  29.   /* - compile `ftraster' with the _STANDALONE_ macro defined, as in       */
  30.   /*                                                                       */
  31.   /*     cc -c -D_STANDALONE_ ftraster.c                                   */
  32.   /*                                                                       */
  33.   /* The renderer can be initialized with a call to                        */
  34.   /* `ft_standard_raster.raster_new'; a bitmap can be generated            */
  35.   /* with a call to `ft_standard_raster.raster_render'.                    */
  36.   /*                                                                       */
  37.   /* See the comments and documentation in the file `ftimage.h' for more   */
  38.   /* details on how the raster works.                                      */
  39.   /*                                                                       */
  40.   /*************************************************************************/
  41.   /*************************************************************************/
  42.   /*                                                                       */
  43.   /* This is a rewrite of the FreeType 1.x scan-line converter             */
  44.   /*                                                                       */
  45.   /*************************************************************************/
  46. #ifdef _STANDALONE_
  47. #include "ftmisc.h"
  48. #include "ftimage.h"
  49. #else /* !_STANDALONE_ */
  50. #include <ft2build.h>
  51. #include "ftraster.h"
  52. #include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */
  53. #endif /* !_STANDALONE_ */
  54.   /*************************************************************************/
  55.   /*                                                                       */
  56.   /* A simple technical note on how the raster works                       */
  57.   /* -----------------------------------------------                       */
  58.   /*                                                                       */
  59.   /*   Converting an outline into a bitmap is achieved in several steps:   */
  60.   /*                                                                       */
  61.   /*   1 - Decomposing the outline into successive `profiles'.  Each       */
  62.   /*       profile is simply an array of scanline intersections on a given */
  63.   /*       dimension.  A profile's main attributes are                     */
  64.   /*                                                                       */
  65.   /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'.     */
  66.   /*                                                                       */
  67.   /*       o an array of intersection coordinates for each scanline        */
  68.   /*         between `Ymin' and `Ymax'.                                    */
  69.   /*                                                                       */
  70.   /*       o a direction, indicating whether it was built going `up' or    */
  71.   /*         `down', as this is very important for filling rules.          */
  72.   /*                                                                       */
  73.   /*   2 - Sweeping the target map's scanlines in order to compute segment */
  74.   /*       `spans' which are then filled.  Additionally, this pass         */
  75.   /*       performs drop-out control.                                      */
  76.   /*                                                                       */
  77.   /*   The outline data is parsed during step 1 only.  The profiles are    */
  78.   /*   built from the bottom of the render pool, used as a stack.  The     */
  79.   /*   following graphics shows the profile list under construction:       */
  80.   /*                                                                       */
  81.   /*     ____________________________________________________________ _ _  */
  82.   /*    |         |                   |         |                 |        */
  83.   /*    | profile | coordinates for   | profile | coordinates for |-->     */
  84.   /*    |    1    |  profile 1        |    2    |  profile 2      |-->     */
  85.   /*    |_________|___________________|_________|_________________|__ _ _  */
  86.   /*                                                                       */
  87.   /*    ^                                                         ^        */
  88.   /*    |                                                         |        */
  89.   /*  start of render pool                                       top       */
  90.   /*                                                                       */
  91.   /*   The top of the profile stack is kept in the `top' variable.         */
  92.   /*                                                                       */
  93.   /*   As you can see, a profile record is pushed on top of the render     */
  94.   /*   pool, which is then followed by its coordinates/intersections.  If  */
  95.   /*   a change of direction is detected in the outline, a new profile is  */
  96.   /*   generated until the end of the outline.                             */
  97.   /*                                                                       */
  98.   /*   Note that when all profiles have been generated, the function       */
  99.   /*   Finalize_Profile_Table() is used to record, for each profile, its   */
  100.   /*   bottom-most scanline as well as the scanline above its upmost       */
  101.   /*   boundary.  These positions are called `y-turns' because they (sort  */
  102.   /*   of) correspond to local extrema.  They are stored in a sorted list  */
  103.   /*   built from the top of the render pool as a downwards stack:         */
  104.   /*                                                                       */
  105.   /*      _ _ _______________________________________                      */
  106.   /*                            |                    |                     */
  107.   /*                         <--| sorted list of     |                     */
  108.   /*                         <--|  extrema scanlines |                     */
  109.   /*      _ _ __________________|____________________|                     */
  110.   /*                                                                       */
  111.   /*                            ^                    ^                     */
  112.   /*                            |                    |                     */
  113.   /*                         maxBuff           sizeBuff = end of pool      */
  114.   /*                                                                       */
  115.   /*   This list is later used during the sweep phase in order to          */
  116.   /*   optimize performance (see technical note on the sweep below).       */
  117.   /*                                                                       */
  118.   /*   Of course, the raster detects whether the two stacks collide and    */
  119.   /*   handles the situation properly.                                     */
  120.   /*                                                                       */
  121.   /*************************************************************************/
  122.   /*************************************************************************/
  123.   /*************************************************************************/
  124.   /**                                                                     **/
  125.   /**  CONFIGURATION MACROS                                               **/
  126.   /**                                                                     **/
  127.   /*************************************************************************/
  128.   /*************************************************************************/
  129.   /* define DEBUG_RASTER if you want to compile a debugging version */
  130. #define xxxDEBUG_RASTER
  131.   /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
  132.   /* 5-levels anti-aliasing                                                */
  133. #ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
  134. #define FT_RASTER_OPTION_ANTI_ALIASING
  135. #endif
  136.   /* The size of the two-lines intermediate bitmap used */
  137.   /* for anti-aliasing, in bytes.                       */
  138. #define RASTER_GRAY_LINES  2048
  139.   /*************************************************************************/
  140.   /*************************************************************************/
  141.   /**                                                                     **/
  142.   /**  OTHER MACROS (do not change)                                       **/
  143.   /**                                                                     **/
  144.   /*************************************************************************/
  145.   /*************************************************************************/
  146.   /*************************************************************************/
  147.   /*                                                                       */
  148.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  149.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  150.   /* messages during execution.                                            */
  151.   /*                                                                       */
  152. #undef  FT_COMPONENT
  153. #define FT_COMPONENT  trace_raster
  154. #ifdef _STANDALONE_
  155.   /* This macro is used to indicate that a function parameter is unused. */
  156.   /* Its purpose is simply to reduce compiler warnings.  Note also that  */
  157.   /* simply defining it as `(void)x' doesn't avoid warnings with certain */
  158.   /* ANSI compilers (e.g. LCC).                                          */
  159. #define FT_UNUSED( x )  (x) = (x)
  160.   /* Disable the tracing mechanism for simplicity -- developers can      */
  161.   /* activate it easily by redefining these two macros.                  */
  162. #ifndef FT_ERROR
  163. #define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
  164. #endif
  165. #ifndef FT_TRACE
  166. #define FT_TRACE( x )   do ; while ( 0 )    /* nothing */
  167. #define FT_TRACE1( x )  do ; while ( 0 )    /* nothing */
  168. #define FT_TRACE6( x )  do ; while ( 0 )    /* nothing */
  169. #endif
  170. #define Raster_Err_None          0
  171. #define Raster_Err_Not_Ini      -1
  172. #define Raster_Err_Overflow     -2
  173. #define Raster_Err_Neg_Height   -3
  174. #define Raster_Err_Invalid      -4
  175. #define Raster_Err_Unsupported  -5
  176. #define ft_memset   memset
  177. #else /* _STANDALONE_ */
  178. #include FT_INTERNAL_OBJECTS_H
  179. #include FT_INTERNAL_DEBUG_H        /* for FT_TRACE() and FT_ERROR() */
  180. #include "rasterrs.h"
  181. #define Raster_Err_None         Raster_Err_Ok
  182. #define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
  183. #define Raster_Err_Overflow     Raster_Err_Raster_Overflow
  184. #define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
  185. #define Raster_Err_Invalid      Raster_Err_Invalid_Outline
  186. #define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
  187. #endif /* _STANDALONE_ */
  188. #ifndef FT_MEM_SET
  189. #define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
  190. #endif
  191. #ifndef FT_MEM_ZERO
  192. #define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
  193. #endif
  194.   /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
  195.   /* typically a small value and the result of a*b is known to fit into */
  196.   /* 32 bits.                                                           */
  197. #define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
  198.   /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
  199.   /* for clipping computations.  It simply uses the FT_MulDiv() function   */
  200.   /* defined in `ftcalc.h'.                                                */
  201. #define SMulDiv  FT_MulDiv
  202.   /* The rasterizer is a very general purpose component; please leave */
  203.   /* the following redefinitions there (you never know your target    */
  204.   /* environment).                                                    */
  205. #ifndef TRUE
  206. #define TRUE   1
  207. #endif
  208. #ifndef FALSE
  209. #define FALSE  0
  210. #endif
  211. #ifndef NULL
  212. #define NULL  (void*)0
  213. #endif
  214. #ifndef SUCCESS
  215. #define SUCCESS  0
  216. #endif
  217. #ifndef FAILURE
  218. #define FAILURE  1
  219. #endif
  220. #define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
  221.                         /* Setting this constant to more than 32 is a   */
  222.                         /* pure waste of space.                         */
  223. #define Pixel_Bits  6   /* fractional bits of *input* coordinates */
  224.   /*************************************************************************/
  225.   /*************************************************************************/
  226.   /**                                                                     **/
  227.   /**  SIMPLE TYPE DECLARATIONS                                           **/
  228.   /**                                                                     **/
  229.   /*************************************************************************/
  230.   /*************************************************************************/
  231.   typedef int             Int;
  232.   typedef unsigned int    UInt;
  233.   typedef short           Short;
  234.   typedef unsigned short  UShort, *PUShort;
  235.   typedef long            Long, *PLong;
  236.   typedef unsigned long   ULong;
  237.   typedef unsigned char   Byte, *PByte;
  238.   typedef char            Bool;
  239.   typedef union  Alignment_
  240.   {
  241.     long    l;
  242.     void*   p;
  243.     void  (*f)(void);
  244.   } Alignment, *PAlignment;
  245.   typedef struct  TPoint_
  246.   {
  247.     Long  x;
  248.     Long  y;
  249.   } TPoint;
  250.   typedef enum  TFlow_
  251.   {
  252.     Flow_None = 0,
  253.     Flow_Up   = 1,
  254.     Flow_Down = -1
  255.   } TFlow;
  256.   /* States of each line, arc, and profile */
  257.   typedef enum  TStates_
  258.   {
  259.     Unknown_State,
  260.     Ascending_State,
  261.     Descending_State,
  262.     Flat_State
  263.   } TStates;
  264.   typedef struct TProfile_  TProfile;
  265.   typedef TProfile*         PProfile;
  266.   struct  TProfile_
  267.   {
  268.     FT_F26Dot6  X;           /* current coordinate during sweep        */
  269.     PProfile    link;        /* link to next profile - various purpose */
  270.     PLong       offset;      /* start of profile's data in render pool */
  271.     int         flow;        /* Profile orientation: Asc/Descending    */
  272.     long        height;      /* profile's height in scanlines          */
  273.     long        start;       /* profile's starting scanline            */
  274.     unsigned    countL;      /* number of lines to step before this    */
  275.                              /* profile becomes drawable               */
  276.     PProfile    next;        /* next profile in same contour, used     */
  277.                              /* during drop-out control                */
  278.   };
  279.   typedef PProfile   TProfileList;
  280.   typedef PProfile*  PProfileList;
  281.   /* Simple record used to implement a stack of bands, required */
  282.   /* by the sub-banding mechanism                               */
  283.   typedef struct  TBand_
  284.   {
  285.     Short  y_min;   /* band's minimum */
  286.     Short  y_max;   /* band's maximum */
  287.   } TBand;
  288. #define AlignProfileSize 
  289.   ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )
  290. #ifdef FT_STATIC_RASTER
  291. #define RAS_ARGS       /* void */
  292. #define RAS_ARG        /* void */
  293. #define RAS_VARS       /* void */
  294. #define RAS_VAR        /* void */
  295. #define FT_UNUSED_RASTER  do ; while ( 0 )
  296. #else /* FT_STATIC_RASTER */
  297. #define RAS_ARGS       PWorker    worker,
  298. #define RAS_ARG        PWorker    worker
  299. #define RAS_VARS       worker,
  300. #define RAS_VAR        worker
  301. #define FT_UNUSED_RASTER  FT_UNUSED( worker )
  302. #endif /* FT_STATIC_RASTER */
  303.   typedef struct TWorker_   TWorker, *PWorker;
  304.   /* prototypes used for sweep function dispatch */
  305.   typedef void
  306.   Function_Sweep_Init( RAS_ARGS Short*  min,
  307.                                 Short*  max );
  308.   typedef void
  309.   Function_Sweep_Span( RAS_ARGS Short       y,
  310.                                 FT_F26Dot6  x1,
  311.                                 FT_F26Dot6  x2,
  312.                                 PProfile    left,
  313.                                 PProfile    right );
  314.   typedef void
  315.   Function_Sweep_Step( RAS_ARG );
  316.   /* NOTE: These operations are only valid on 2's complement processors */
  317. #define FLOOR( x )    ( (x) & -ras.precision )
  318. #define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
  319. #define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
  320. #define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
  321. #define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
  322.   /* Note that I have moved the location of some fields in the */
  323.   /* structure to ensure that the most used variables are used */
  324.   /* at the top.  Thus, their offset can be coded with less    */
  325.   /* opcodes, and it results in a smaller executable.          */
  326.   struct  TWorker_
  327.   {
  328.     Int       precision_bits;       /* precision related variables         */
  329.     Int       precision;
  330.     Int       precision_half;
  331.     Long      precision_mask;
  332.     Int       precision_shift;
  333.     Int       precision_step;
  334.     Int       precision_jitter;
  335.     Int       scale_shift;          /* == precision_shift   for bitmaps    */
  336.                                     /* == precision_shift+1 for pixmaps    */
  337.     PLong     buff;                 /* The profiles buffer                 */
  338.     PLong     sizeBuff;             /* Render pool size                    */
  339.     PLong     maxBuff;              /* Profiles buffer size                */
  340.     PLong     top;                  /* Current cursor in buffer            */
  341.     FT_Error  error;
  342.     Int       numTurns;             /* number of Y-turns in outline        */
  343.     TPoint*   arc;                  /* current Bezier arc pointer          */
  344.     UShort    bWidth;               /* target bitmap width                 */
  345.     PByte     bTarget;              /* target bitmap buffer                */
  346.     PByte     gTarget;              /* target pixmap buffer                */
  347.     Long      lastX, lastY, minY, maxY;
  348.     UShort    num_Profs;            /* current number of profiles          */
  349.     Bool      fresh;                /* signals a fresh new profile which   */
  350.                                     /* 'start' field must be completed     */
  351.     Bool      joint;                /* signals that the last arc ended     */
  352.                                     /* exactly on a scanline.  Allows      */
  353.                                     /* removal of doublets                 */
  354.     PProfile  cProfile;             /* current profile                     */
  355.     PProfile  fProfile;             /* head of linked list of profiles     */
  356.     PProfile  gProfile;             /* contour's first profile in case     */
  357.                                     /* of impact                           */
  358.     TStates   state;                /* rendering state                     */
  359.     FT_Bitmap   target;             /* description of target bit/pixmap    */
  360.     FT_Outline  outline;
  361.     Long      traceOfs;             /* current offset in target bitmap     */
  362.     Long      traceG;               /* current offset in target pixmap     */
  363.     Short     traceIncr;            /* sweep's increment in target bitmap  */
  364.     Short     gray_min_x;           /* current min x during gray rendering */
  365.     Short     gray_max_x;           /* current max x during gray rendering */
  366.     /* dispatch variables */
  367.     Function_Sweep_Init*  Proc_Sweep_Init;
  368.     Function_Sweep_Span*  Proc_Sweep_Span;
  369.     Function_Sweep_Span*  Proc_Sweep_Drop;
  370.     Function_Sweep_Step*  Proc_Sweep_Step;
  371.     Byte      dropOutControl;       /* current drop_out control method     */
  372.     Bool      second_pass;          /* indicates whether a horizontal pass */
  373.                                     /* should be performed to control      */
  374.                                     /* drop-out accurately when calling    */
  375.                                     /* Render_Glyph.  Note that there is   */
  376.                                     /* no horizontal pass during gray      */
  377.                                     /* rendering.                          */
  378.     TPoint    arcs[3 * MaxBezier + 1]; /* The Bezier stack                 */
  379.     TBand     band_stack[16];       /* band stack used for sub-banding     */
  380.     Int       band_top;             /* band stack top                      */
  381. #ifdef FT_RASTER_OPTION_ANTI_ALIASING
  382.     Byte*     grays;
  383.     Byte      gray_lines[RASTER_GRAY_LINES];
  384.                                 /* Intermediate table used to render the   */
  385.                                 /* graylevels pixmaps.                     */
  386.                                 /* gray_lines is a buffer holding two      */
  387.                                 /* monochrome scanlines                    */
  388.     Short     gray_width;       /* width in bytes of one monochrome        */
  389.                                 /* intermediate scanline of gray_lines.    */
  390.                                 /* Each gray pixel takes 2 bits long there */
  391.                        /* The gray_lines must hold 2 lines, thus with size */
  392.                        /* in bytes of at least `gray_width*2'.             */
  393. #endif /* FT_RASTER_ANTI_ALIASING */
  394.   };
  395.   typedef struct TRaster_
  396.   {
  397.     char*     buffer;
  398.     long      buffer_size;
  399.     void*     memory;
  400.     PWorker   worker;
  401.     Byte      grays[5];
  402.     Short     gray_width;
  403.   } TRaster, *PRaster;
  404. #ifdef FT_STATIC_RASTER
  405.   static TWorker   cur_ras;
  406. #define ras  cur_ras
  407. #else
  408. #define ras  (*worker)
  409. #endif /* FT_STATIC_RASTER */
  410. static const char  count_table[256] =
  411. {
  412.   0 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4,
  413.   1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
  414.   1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
  415.   2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
  416.   1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
  417.   2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
  418.   2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
  419.   3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
  420.   1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
  421.   2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
  422.   2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
  423.   3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
  424.   2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
  425.   3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
  426.   3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
  427.   4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 , 5 , 6 , 6 , 7 , 6 , 7 , 7 , 8 };
  428.   /*************************************************************************/
  429.   /*************************************************************************/
  430.   /**                                                                     **/
  431.   /**  PROFILES COMPUTATION                                               **/
  432.   /**                                                                     **/
  433.   /*************************************************************************/
  434.   /*************************************************************************/
  435.   /*************************************************************************/
  436.   /*                                                                       */
  437.   /* <Function>                                                            */
  438.   /*    Set_High_Precision                                                 */
  439.   /*                                                                       */
  440.   /* <Description>                                                         */
  441.   /*    Sets precision variables according to param flag.                  */
  442.   /*                                                                       */
  443.   /* <Input>                                                               */
  444.   /*    High :: Set to True for high precision (typically for ppem < 18),  */
  445.   /*            false otherwise.                                           */
  446.   /*                                                                       */
  447.   static void
  448.   Set_High_Precision( RAS_ARGS Int  High )
  449.   {
  450.     if ( High )
  451.     {
  452.       ras.precision_bits   = 10;
  453.       ras.precision_step   = 128;
  454.       ras.precision_jitter = 24;
  455.     }
  456.     else
  457.     {
  458.       ras.precision_bits   = 6;
  459.       ras.precision_step   = 32;
  460.       ras.precision_jitter = 2;
  461.     }
  462.     FT_TRACE6(( "Set_High_Precision(%s)n", High ? "true" : "false" ));
  463.     ras.precision       = 1 << ras.precision_bits;
  464.     ras.precision_half  = ras.precision / 2;
  465.     ras.precision_shift = ras.precision_bits - Pixel_Bits;
  466.     ras.precision_mask  = -ras.precision;
  467.   }
  468.   /*************************************************************************/
  469.   /*                                                                       */
  470.   /* <Function>                                                            */
  471.   /*    New_Profile                                                        */
  472.   /*                                                                       */
  473.   /* <Description>                                                         */
  474.   /*    Creates a new profile in the render pool.                          */
  475.   /*                                                                       */
  476.   /* <Input>                                                               */
  477.   /*    aState :: The state/orientation of the new profile.                */
  478.   /*                                                                       */
  479.   /* <Return>                                                              */
  480.   /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
  481.   /*   profile.                                                            */
  482.   /*                                                                       */
  483.   static Bool
  484.   New_Profile( RAS_ARGS TStates  aState )
  485.   {
  486.     if ( !ras.fProfile )
  487.     {
  488.       ras.cProfile  = (PProfile)ras.top;
  489.       ras.fProfile  = ras.cProfile;
  490.       ras.top      += AlignProfileSize;
  491.     }
  492.     if ( ras.top >= ras.maxBuff )
  493.     {
  494.       ras.error = Raster_Err_Overflow;
  495.       return FAILURE;
  496.     }
  497.     switch ( aState )
  498.     {
  499.     case Ascending_State:
  500.       ras.cProfile->flow = Flow_Up;
  501.       FT_TRACE6(( "New ascending profile = %lxn", (long)ras.cProfile ));
  502.       break;
  503.     case Descending_State:
  504.       ras.cProfile->flow = Flow_Down;
  505.       FT_TRACE6(( "New descending profile = %lxn", (long)ras.cProfile ));
  506.       break;
  507.     default:
  508.       FT_ERROR(( "New_Profile: invalid profile direction!n" ));
  509.       ras.error = Raster_Err_Invalid;
  510.       return FAILURE;
  511.     }
  512.     ras.cProfile->start  = 0;
  513.     ras.cProfile->height = 0;
  514.     ras.cProfile->offset = ras.top;
  515.     ras.cProfile->link   = (PProfile)0;
  516.     ras.cProfile->next   = (PProfile)0;
  517.     if ( !ras.gProfile )
  518.       ras.gProfile = ras.cProfile;
  519.     ras.state = aState;
  520.     ras.fresh = TRUE;
  521.     ras.joint = FALSE;
  522.     return SUCCESS;
  523.   }
  524.   /*************************************************************************/
  525.   /*                                                                       */
  526.   /* <Function>                                                            */
  527.   /*    End_Profile                                                        */
  528.   /*                                                                       */
  529.   /* <Description>                                                         */
  530.   /*    Finalizes the current profile.                                     */
  531.   /*                                                                       */
  532.   /* <Return>                                                              */
  533.   /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
  534.   /*                                                                       */
  535.   static Bool
  536.   End_Profile( RAS_ARG )
  537.   {
  538.     Long      h;
  539.     PProfile  oldProfile;
  540.     h = (Long)( ras.top - ras.cProfile->offset );
  541.     if ( h < 0 )
  542.     {
  543.       FT_ERROR(( "End_Profile: negative height encountered!n" ));
  544.       ras.error = Raster_Err_Neg_Height;
  545.       return FAILURE;
  546.     }
  547.     if ( h > 0 )
  548.     {
  549.       FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ldn",
  550.                   (long)ras.cProfile, ras.cProfile->start, h ));
  551.       oldProfile           = ras.cProfile;
  552.       ras.cProfile->height = h;
  553.       ras.cProfile         = (PProfile)ras.top;
  554.       ras.top             += AlignProfileSize;
  555.       ras.cProfile->height = 0;
  556.       ras.cProfile->offset = ras.top;
  557.       oldProfile->next     = ras.cProfile;
  558.       ras.num_Profs++;
  559.     }
  560.     if ( ras.top >= ras.maxBuff )
  561.     {
  562.       FT_TRACE1(( "overflow in End_Profilen" ));
  563.       ras.error = Raster_Err_Overflow;
  564.       return FAILURE;
  565.     }
  566.     ras.joint = FALSE;
  567.     return SUCCESS;
  568.   }
  569.   /*************************************************************************/
  570.   /*                                                                       */
  571.   /* <Function>                                                            */
  572.   /*    Insert_Y_Turn                                                      */
  573.   /*                                                                       */
  574.   /* <Description>                                                         */
  575.   /*    Inserts a salient into the sorted list placed on top of the render */
  576.   /*    pool.                                                              */
  577.   /*                                                                       */
  578.   /* <Input>                                                               */
  579.   /*    New y scanline position.                                           */
  580.   /*                                                                       */
  581.   /* <Return>                                                              */
  582.   /*    SUCCESS on success.  FAILURE in case of overflow.                  */
  583.   /*                                                                       */
  584.   static Bool
  585.   Insert_Y_Turn( RAS_ARGS Int  y )
  586.   {
  587.     PLong  y_turns;
  588.     Int    y2, n;
  589.     n       = ras.numTurns - 1;
  590.     y_turns = ras.sizeBuff - ras.numTurns;
  591.     /* look for first y value that is <= */
  592.     while ( n >= 0 && y < y_turns[n] )
  593.       n--;
  594.     /* if it is <, simply insert it, ignore if == */
  595.     if ( n >= 0 && y > y_turns[n] )
  596.       while ( n >= 0 )
  597.       {
  598.         y2 = (Int)y_turns[n];
  599.         y_turns[n] = y;
  600.         y = y2;
  601.         n--;
  602.       }
  603.     if ( n < 0 )
  604.     {
  605.       ras.maxBuff--;
  606.       if ( ras.maxBuff <= ras.top )
  607.       {
  608.         ras.error = Raster_Err_Overflow;
  609.         return FAILURE;
  610.       }
  611.       ras.numTurns++;
  612.       ras.sizeBuff[-ras.numTurns] = y;
  613.     }
  614.     return SUCCESS;
  615.   }
  616.   /*************************************************************************/
  617.   /*                                                                       */
  618.   /* <Function>                                                            */
  619.   /*    Finalize_Profile_Table                                             */
  620.   /*                                                                       */
  621.   /* <Description>                                                         */
  622.   /*    Adjusts all links in the profiles list.                            */
  623.   /*                                                                       */
  624.   /* <Return>                                                              */
  625.   /*    SUCCESS on success.  FAILURE in case of overflow.                  */
  626.   /*                                                                       */
  627.   static Bool
  628.   Finalize_Profile_Table( RAS_ARG )
  629.   {
  630.     Int       bottom, top;
  631.     UShort    n;
  632.     PProfile  p;
  633.     n = ras.num_Profs;
  634.     if ( n > 1 )
  635.     {
  636.       p = ras.fProfile;
  637.       while ( n > 0 )
  638.       {
  639.         if ( n > 1 )
  640.           p->link = (PProfile)( p->offset + p->height );
  641.         else
  642.           p->link = NULL;
  643.         switch ( p->flow )
  644.         {
  645.         case Flow_Down:
  646.           bottom     = (Int)( p->start - p->height + 1 );
  647.           top        = (Int)p->start;
  648.           p->start   = bottom;
  649.           p->offset += p->height - 1;
  650.           break;
  651.         case Flow_Up:
  652.         default:
  653.           bottom = (Int)p->start;
  654.           top    = (Int)( p->start + p->height - 1 );
  655.         }
  656.         if ( Insert_Y_Turn( RAS_VARS bottom )   ||
  657.              Insert_Y_Turn( RAS_VARS top + 1 )  )
  658.           return FAILURE;
  659.         p = p->link;
  660.         n--;
  661.       }
  662.     }
  663.     else
  664.       ras.fProfile = NULL;
  665.     return SUCCESS;
  666.   }
  667.   /*************************************************************************/
  668.   /*                                                                       */
  669.   /* <Function>                                                            */
  670.   /*    Split_Conic                                                        */
  671.   /*                                                                       */
  672.   /* <Description>                                                         */
  673.   /*    Subdivides one conic Bezier into two joint sub-arcs in the Bezier  */
  674.   /*    stack.                                                             */
  675.   /*                                                                       */
  676.   /* <Input>                                                               */
  677.   /*    None (subdivided Bezier is taken from the top of the stack).       */
  678.   /*                                                                       */
  679.   /* <Note>                                                                */
  680.   /*    This routine is the `beef' of this component.  It is  _the_ inner  */
  681.   /*    loop that should be optimized to hell to get the best performance. */
  682.   /*                                                                       */
  683.   static void
  684.   Split_Conic( TPoint*  base )
  685.   {
  686.     Long  a, b;
  687.     base[4].x = base[2].x;
  688.     b = base[1].x;
  689.     a = base[3].x = ( base[2].x + b ) / 2;
  690.     b = base[1].x = ( base[0].x + b ) / 2;
  691.     base[2].x = ( a + b ) / 2;
  692.     base[4].y = base[2].y;
  693.     b = base[1].y;
  694.     a = base[3].y = ( base[2].y + b ) / 2;
  695.     b = base[1].y = ( base[0].y + b ) / 2;
  696.     base[2].y = ( a + b ) / 2;
  697.     /* hand optimized.  gcc doesn't seem to be too good at common      */
  698.     /* expression substitution and instruction scheduling ;-)          */
  699.   }
  700.   /*************************************************************************/
  701.   /*                                                                       */
  702.   /* <Function>                                                            */
  703.   /*    Split_Cubic                                                        */
  704.   /*                                                                       */
  705.   /* <Description>                                                         */
  706.   /*    Subdivides a third-order Bezier arc into two joint sub-arcs in the */
  707.   /*    Bezier stack.                                                      */
  708.   /*                                                                       */
  709.   /* <Note>                                                                */
  710.   /*    This routine is the `beef' of the component.  It is one of _the_   */
  711.   /*    inner loops that should be optimized like hell to get the best     */
  712.   /*    performance.                                                       */
  713.   /*                                                                       */
  714.   static void
  715.   Split_Cubic( TPoint*  base )
  716.   {
  717.     Long  a, b, c, d;
  718.     base[6].x = base[3].x;
  719.     c = base[1].x;
  720.     d = base[2].x;
  721.     base[1].x = a = ( base[0].x + c + 1 ) >> 1;
  722.     base[5].x = b = ( base[3].x + d + 1 ) >> 1;
  723.     c = ( c + d + 1 ) >> 1;
  724.     base[2].x = a = ( a + c + 1 ) >> 1;
  725.     base[4].x = b = ( b + c + 1 ) >> 1;
  726.     base[3].x = ( a + b + 1 ) >> 1;
  727.     base[6].y = base[3].y;
  728.     c = base[1].y;
  729.     d = base[2].y;
  730.     base[1].y = a = ( base[0].y + c + 1 ) >> 1;
  731.     base[5].y = b = ( base[3].y + d + 1 ) >> 1;
  732.     c = ( c + d + 1 ) >> 1;
  733.     base[2].y = a = ( a + c + 1 ) >> 1;
  734.     base[4].y = b = ( b + c + 1 ) >> 1;
  735.     base[3].y = ( a + b + 1 ) >> 1;
  736.   }
  737.   /*************************************************************************/
  738.   /*                                                                       */
  739.   /* <Function>                                                            */
  740.   /*    Line_Up                                                            */
  741.   /*                                                                       */
  742.   /* <Description>                                                         */
  743.   /*    Computes the x-coordinates of an ascending line segment and stores */
  744.   /*    them in the render pool.                                           */
  745.   /*                                                                       */
  746.   /* <Input>                                                               */
  747.   /*    x1   :: The x-coordinate of the segment's start point.             */
  748.   /*                                                                       */
  749.   /*    y1   :: The y-coordinate of the segment's start point.             */
  750.   /*                                                                       */
  751.   /*    x2   :: The x-coordinate of the segment's end point.               */
  752.   /*                                                                       */
  753.   /*    y2   :: The y-coordinate of the segment's end point.               */
  754.   /*                                                                       */
  755.   /*    miny :: A lower vertical clipping bound value.                     */
  756.   /*                                                                       */
  757.   /*    maxy :: An upper vertical clipping bound value.                    */
  758.   /*                                                                       */
  759.   /* <Return>                                                              */
  760.   /*    SUCCESS on success, FAILURE on render pool overflow.               */
  761.   /*                                                                       */
  762.   static Bool
  763.   Line_Up( RAS_ARGS Long  x1,
  764.                     Long  y1,
  765.                     Long  x2,
  766.                     Long  y2,
  767.                     Long  miny,
  768.                     Long  maxy )
  769.   {
  770.     Long   Dx, Dy;
  771.     Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
  772.     Long   Ix, Rx, Ax;
  773.     PLong  top;
  774.     Dx = x2 - x1;
  775.     Dy = y2 - y1;
  776.     if ( Dy <= 0 || y2 < miny || y1 > maxy )
  777.       return SUCCESS;
  778.     if ( y1 < miny )
  779.     {
  780.       /* Take care: miny-y1 can be a very large value; we use     */
  781.       /*            a slow MulDiv function to avoid clipping bugs */
  782.       x1 += SMulDiv( Dx, miny - y1, Dy );
  783.       e1  = (Int)TRUNC( miny );
  784.       f1  = 0;
  785.     }
  786.     else
  787.     {
  788.       e1 = (Int)TRUNC( y1 );
  789.       f1 = (Int)FRAC( y1 );
  790.     }
  791.     if ( y2 > maxy )
  792.     {
  793.       /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
  794.       e2  = (Int)TRUNC( maxy );
  795.       f2  = 0;
  796.     }
  797.     else
  798.     {
  799.       e2 = (Int)TRUNC( y2 );
  800.       f2 = (Int)FRAC( y2 );
  801.     }
  802.     if ( f1 > 0 )
  803.     {
  804.       if ( e1 == e2 )
  805.         return SUCCESS;
  806.       else
  807.       {
  808.         x1 += FMulDiv( Dx, ras.precision - f1, Dy );
  809.         e1 += 1;
  810.       }
  811.     }
  812.     else
  813.       if ( ras.joint )
  814.       {
  815.         ras.top--;
  816.         ras.joint = FALSE;
  817.       }
  818.     ras.joint = (char)( f2 == 0 );
  819.     if ( ras.fresh )
  820.     {
  821.       ras.cProfile->start = e1;
  822.       ras.fresh           = FALSE;
  823.     }
  824.     size = e2 - e1 + 1;
  825.     if ( ras.top + size >= ras.maxBuff )
  826.     {
  827.       ras.error = Raster_Err_Overflow;
  828.       return FAILURE;
  829.     }
  830.     if ( Dx > 0 )
  831.     {
  832.       Ix = ( ras.precision * Dx ) / Dy;
  833.       Rx = ( ras.precision * Dx ) % Dy;
  834.       Dx = 1;
  835.     }
  836.     else
  837.     {
  838.       Ix = -( ( ras.precision * -Dx ) / Dy );
  839.       Rx =    ( ras.precision * -Dx ) % Dy;
  840.       Dx = -1;
  841.     }
  842.     Ax  = -Dy;
  843.     top = ras.top;
  844.     while ( size > 0 )
  845.     {
  846.       *top++ = x1;
  847.       x1 += Ix;
  848.       Ax += Rx;
  849.       if ( Ax >= 0 )
  850.       {
  851.         Ax -= Dy;
  852.         x1 += Dx;
  853.       }
  854.       size--;
  855.     }
  856.     ras.top = top;
  857.     return SUCCESS;
  858.   }
  859.   /*************************************************************************/
  860.   /*                                                                       */
  861.   /* <Function>                                                            */
  862.   /*    Line_Down                                                          */
  863.   /*                                                                       */
  864.   /* <Description>                                                         */
  865.   /*    Computes the x-coordinates of an descending line segment and       */
  866.   /*    stores them in the render pool.                                    */
  867.   /*                                                                       */
  868.   /* <Input>                                                               */
  869.   /*    x1   :: The x-coordinate of the segment's start point.             */
  870.   /*                                                                       */
  871.   /*    y1   :: The y-coordinate of the segment's start point.             */
  872.   /*                                                                       */
  873.   /*    x2   :: The x-coordinate of the segment's end point.               */
  874.   /*                                                                       */
  875.   /*    y2   :: The y-coordinate of the segment's end point.               */
  876.   /*                                                                       */
  877.   /*    miny :: A lower vertical clipping bound value.                     */
  878.   /*                                                                       */
  879.   /*    maxy :: An upper vertical clipping bound value.                    */
  880.   /*                                                                       */
  881.   /* <Return>                                                              */
  882.   /*    SUCCESS on success, FAILURE on render pool overflow.               */
  883.   /*                                                                       */
  884.   static Bool
  885.   Line_Down( RAS_ARGS Long  x1,
  886.                       Long  y1,
  887.                       Long  x2,
  888.                       Long  y2,
  889.                       Long  miny,
  890.                       Long  maxy )
  891.   {
  892.     Bool  result, fresh;
  893.     fresh  = ras.fresh;
  894.     result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
  895.     if ( fresh && !ras.fresh )
  896.       ras.cProfile->start = -ras.cProfile->start;
  897.     return result;
  898.   }
  899.   /* A function type describing the functions used to split Bezier arcs */
  900.   typedef void  (*TSplitter)( TPoint*  base );
  901.   /*************************************************************************/
  902.   /*                                                                       */
  903.   /* <Function>                                                            */
  904.   /*    Bezier_Up                                                          */
  905.   /*                                                                       */
  906.   /* <Description>                                                         */
  907.   /*    Computes the x-coordinates of an ascending Bezier arc and stores   */
  908.   /*    them in the render pool.                                           */
  909.   /*                                                                       */
  910.   /* <Input>                                                               */
  911.   /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
  912.   /*                                                                       */
  913.   /*    splitter :: The function to split Bezier arcs.                     */
  914.   /*                                                                       */
  915.   /*    miny     :: A lower vertical clipping bound value.                 */
  916.   /*                                                                       */
  917.   /*    maxy     :: An upper vertical clipping bound value.                */
  918.   /*                                                                       */
  919.   /* <Return>                                                              */
  920.   /*    SUCCESS on success, FAILURE on render pool overflow.               */
  921.   /*                                                                       */
  922.   static Bool
  923.   Bezier_Up( RAS_ARGS Int        degree,
  924.                       TSplitter  splitter,
  925.                       Long       miny,
  926.                       Long       maxy )
  927.   {
  928.     Long   y1, y2, e, e2, e0;
  929.     Short  f1;
  930.     TPoint*  arc;
  931.     TPoint*  start_arc;
  932.     PLong top;
  933.     arc = ras.arc;
  934.     y1  = arc[degree].y;
  935.     y2  = arc[0].y;
  936.     top = ras.top;
  937.     if ( y2 < miny || y1 > maxy )
  938.       goto Fin;
  939.     e2 = FLOOR( y2 );
  940.     if ( e2 > maxy )
  941.       e2 = maxy;
  942.     e0 = miny;
  943.     if ( y1 < miny )
  944.       e = miny;
  945.     else
  946.     {
  947.       e  = CEILING( y1 );
  948.       f1 = (Short)( FRAC( y1 ) );
  949.       e0 = e;
  950.       if ( f1 == 0 )
  951.       {
  952.         if ( ras.joint )
  953.         {
  954.           top--;
  955.           ras.joint = FALSE;
  956.         }
  957.         *top++ = arc[degree].x;
  958.         e += ras.precision;
  959.       }
  960.     }
  961.     if ( ras.fresh )
  962.     {
  963.       ras.cProfile->start = TRUNC( e0 );
  964.       ras.fresh = FALSE;
  965.     }
  966.     if ( e2 < e )
  967.       goto Fin;
  968.     if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
  969.     {
  970.       ras.top   = top;
  971.       ras.error = Raster_Err_Overflow;
  972.       return FAILURE;
  973.     }
  974.     start_arc = arc;
  975.     while ( arc >= start_arc && e <= e2 )
  976.     {
  977.       ras.joint = FALSE;
  978.       y2 = arc[0].y;
  979.       if ( y2 > e )
  980.       {
  981.         y1 = arc[degree].y;
  982.         if ( y2 - y1 >= ras.precision_step )
  983.         {
  984.           splitter( arc );
  985.           arc += degree;
  986.         }
  987.         else
  988.         {
  989.           *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
  990.                                             e - y1, y2 - y1 );
  991.           arc -= degree;
  992.           e   += ras.precision;
  993.         }
  994.       }
  995.       else
  996.       {
  997.         if ( y2 == e )
  998.         {
  999.           ras.joint  = TRUE;
  1000.           *top++     = arc[0].x;
  1001.           e += ras.precision;
  1002.         }
  1003.         arc -= degree;
  1004.       }
  1005.     }
  1006.   Fin:
  1007.     ras.top  = top;
  1008.     ras.arc -= degree;
  1009.     return SUCCESS;
  1010.   }
  1011.   /*************************************************************************/
  1012.   /*                                                                       */
  1013.   /* <Function>                                                            */
  1014.   /*    Bezier_Down                                                        */
  1015.   /*                                                                       */
  1016.   /* <Description>                                                         */
  1017.   /*    Computes the x-coordinates of an descending Bezier arc and stores  */
  1018.   /*    them in the render pool.                                           */
  1019.   /*                                                                       */
  1020.   /* <Input>                                                               */
  1021.   /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
  1022.   /*                                                                       */
  1023.   /*    splitter :: The function to split Bezier arcs.                     */
  1024.   /*                                                                       */
  1025.   /*    miny     :: A lower vertical clipping bound value.                 */
  1026.   /*                                                                       */
  1027.   /*    maxy     :: An upper vertical clipping bound value.                */
  1028.   /*                                                                       */
  1029.   /* <Return>                                                              */
  1030.   /*    SUCCESS on success, FAILURE on render pool overflow.               */
  1031.   /*                                                                       */
  1032.   static Bool
  1033.   Bezier_Down( RAS_ARGS Int        degree,
  1034.                         TSplitter  splitter,
  1035.                         Long       miny,
  1036.                         Long       maxy )
  1037.   {
  1038.     TPoint*  arc = ras.arc;
  1039.     Bool     result, fresh;
  1040.     arc[0].y = -arc[0].y;
  1041.     arc[1].y = -arc[1].y;
  1042.     arc[2].y = -arc[2].y;
  1043.     if ( degree > 2 )
  1044.       arc[3].y = -arc[3].y;
  1045.     fresh = ras.fresh;
  1046.     result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
  1047.     if ( fresh && !ras.fresh )
  1048.       ras.cProfile->start = -ras.cProfile->start;
  1049.     arc[0].y = -arc[0].y;
  1050.     return result;
  1051.   }
  1052.   /*************************************************************************/
  1053.   /*                                                                       */
  1054.   /* <Function>                                                            */
  1055.   /*    Line_To                                                            */
  1056.   /*                                                                       */
  1057.   /* <Description>                                                         */
  1058.   /*    Injects a new line segment and adjusts Profiles list.              */
  1059.   /*                                                                       */
  1060.   /* <Input>                                                               */
  1061.   /*   x :: The x-coordinate of the segment's end point (its start point   */
  1062.   /*        is stored in `lastX').                                         */
  1063.   /*                                                                       */
  1064.   /*   y :: The y-coordinate of the segment's end point (its start point   */
  1065.   /*        is stored in `lastY').                                         */
  1066.   /*                                                                       */
  1067.   /* <Return>                                                              */
  1068.   /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
  1069.   /*   profile.                                                            */
  1070.   /*                                                                       */
  1071.   static Bool
  1072.   Line_To( RAS_ARGS Long  x,
  1073.                     Long  y )
  1074.   {
  1075.     /* First, detect a change of direction */
  1076.     switch ( ras.state )
  1077.     {
  1078.     case Unknown_State:
  1079.       if ( y > ras.lastY )
  1080.       {
  1081.         if ( New_Profile( RAS_VARS Ascending_State ) )
  1082.           return FAILURE;
  1083.       }
  1084.       else
  1085.       {
  1086.         if ( y < ras.lastY )
  1087.           if ( New_Profile( RAS_VARS Descending_State ) )
  1088.             return FAILURE;
  1089.       }
  1090.       break;
  1091.     case Ascending_State:
  1092.       if ( y < ras.lastY )
  1093.       {
  1094.         if ( End_Profile( RAS_VAR )                   ||
  1095.              New_Profile( RAS_VARS Descending_State ) )
  1096.           return FAILURE;
  1097.       }
  1098.       break;
  1099.     case Descending_State:
  1100.       if ( y > ras.lastY )
  1101.       {
  1102.         if ( End_Profile( RAS_VAR )                  ||
  1103.              New_Profile( RAS_VARS Ascending_State ) )
  1104.           return FAILURE;
  1105.       }
  1106.       break;
  1107.     default:
  1108.       ;
  1109.     }
  1110.     /* Then compute the lines */
  1111.     switch ( ras.state )
  1112.     {
  1113.     case Ascending_State:
  1114.       if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
  1115.                     x, y, ras.minY, ras.maxY ) )
  1116.         return FAILURE;
  1117.       break;
  1118.     case Descending_State:
  1119.       if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
  1120.                       x, y, ras.minY, ras.maxY ) )
  1121.         return FAILURE;
  1122.       break;
  1123.     default:
  1124.       ;
  1125.     }
  1126.     ras.lastX = x;
  1127.     ras.lastY = y;
  1128.     return SUCCESS;
  1129.   }
  1130.   /*************************************************************************/
  1131.   /*                                                                       */
  1132.   /* <Function>                                                            */
  1133.   /*    Conic_To                                                           */
  1134.   /*                                                                       */
  1135.   /* <Description>                                                         */
  1136.   /*    Injects a new conic arc and adjusts the profile list.              */
  1137.   /*                                                                       */
  1138.   /* <Input>                                                               */
  1139.   /*   cx :: The x-coordinate of the arc's new control point.              */
  1140.   /*                                                                       */
  1141.   /*   cy :: The y-coordinate of the arc's new control point.              */
  1142.   /*                                                                       */
  1143.   /*   x  :: The x-coordinate of the arc's end point (its start point is   */
  1144.   /*         stored in `lastX').                                           */
  1145.   /*                                                                       */
  1146.   /*   y  :: The y-coordinate of the arc's end point (its start point is   */
  1147.   /*         stored in `lastY').                                           */
  1148.   /*                                                                       */
  1149.   /* <Return>                                                              */
  1150.   /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
  1151.   /*   profile.                                                            */
  1152.   /*                                                                       */
  1153.   static Bool
  1154.   Conic_To( RAS_ARGS Long  cx,
  1155.                      Long  cy,
  1156.                      Long  x,
  1157.                      Long  y )
  1158.   {
  1159.     Long     y1, y2, y3, x3, ymin, ymax;
  1160.     TStates  state_bez;
  1161.     ras.arc      = ras.arcs;
  1162.     ras.arc[2].x = ras.lastX;
  1163.     ras.arc[2].y = ras.lastY;
  1164.     ras.arc[1].x = cx; ras.arc[1].y = cy;
  1165.     ras.arc[0].x = x;  ras.arc[0].y = y;
  1166.     do
  1167.     {
  1168.       y1 = ras.arc[2].y;
  1169.       y2 = ras.arc[1].y;
  1170.       y3 = ras.arc[0].y;
  1171.       x3 = ras.arc[0].x;
  1172.       /* first, categorize the Bezier arc */
  1173.       if ( y1 <= y3 )
  1174.       {
  1175.         ymin = y1;
  1176.         ymax = y3;
  1177.       }
  1178.       else
  1179.       {
  1180.         ymin = y3;
  1181.         ymax = y1;
  1182.       }
  1183.       if ( y2 < ymin || y2 > ymax )
  1184.       {
  1185.         /* this arc has no given direction, split it! */
  1186.         Split_Conic( ras.arc );
  1187.         ras.arc += 2;
  1188.       }
  1189.       else if ( y1 == y3 )
  1190.       {
  1191.         /* this arc is flat, ignore it and pop it from the Bezier stack */
  1192.         ras.arc -= 2;
  1193.       }
  1194.       else
  1195.       {
  1196.         /* the arc is y-monotonous, either ascending or descending */
  1197.         /* detect a change of direction                            */
  1198.         state_bez = y1 < y3 ? Ascending_State : Descending_State;
  1199.         if ( ras.state != state_bez )
  1200.         {
  1201.           /* finalize current profile if any */
  1202.           if ( ras.state != Unknown_State   &&
  1203.                End_Profile( RAS_VAR ) )
  1204.             goto Fail;
  1205.           /* create a new profile */
  1206.           if ( New_Profile( RAS_VARS state_bez ) )
  1207.             goto Fail;
  1208.         }
  1209.         /* now call the appropriate routine */
  1210.         if ( state_bez == Ascending_State )
  1211.         {
  1212.           if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
  1213.             goto Fail;
  1214.         }
  1215.         else
  1216.           if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
  1217.             goto Fail;
  1218.       }
  1219.     } while ( ras.arc >= ras.arcs );
  1220.     ras.lastX = x3;
  1221.     ras.lastY = y3;
  1222.     return SUCCESS;
  1223.   Fail:
  1224.     return FAILURE;
  1225.   }
  1226.   /*************************************************************************/
  1227.   /*                                                                       */
  1228.   /* <Function>                                                            */
  1229.   /*    Cubic_To                                                           */
  1230.   /*                                                                       */
  1231.   /* <Description>                                                         */
  1232.   /*    Injects a new cubic arc and adjusts the profile list.              */
  1233.   /*                                                                       */
  1234.   /* <Input>                                                               */
  1235.   /*   cx1 :: The x-coordinate of the arc's first new control point.       */
  1236.   /*                                                                       */
  1237.   /*   cy1 :: The y-coordinate of the arc's first new control point.       */
  1238.   /*                                                                       */
  1239.   /*   cx2 :: The x-coordinate of the arc's second new control point.      */
  1240.   /*                                                                       */
  1241.   /*   cy2 :: The y-coordinate of the arc's second new control point.      */
  1242.   /*                                                                       */
  1243.   /*   x   :: The x-coordinate of the arc's end point (its start point is  */
  1244.   /*          stored in `lastX').                                          */
  1245.   /*                                                                       */
  1246.   /*   y   :: The y-coordinate of the arc's end point (its start point is  */
  1247.   /*          stored in `lastY').                                          */
  1248.   /*                                                                       */
  1249.   /* <Return>                                                              */
  1250.   /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
  1251.   /*   profile.                                                            */
  1252.   /*                                                                       */
  1253.   static Bool
  1254.   Cubic_To( RAS_ARGS Long  cx1,
  1255.                      Long  cy1,
  1256.                      Long  cx2,
  1257.                      Long  cy2,
  1258.                      Long  x,
  1259.                      Long  y )
  1260.   {
  1261.     Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
  1262.     TStates  state_bez;
  1263.     ras.arc      = ras.arcs;
  1264.     ras.arc[3].x = ras.lastX;
  1265.     ras.arc[3].y = ras.lastY;
  1266.     ras.arc[2].x = cx1; ras.arc[2].y = cy1;
  1267.     ras.arc[1].x = cx2; ras.arc[1].y = cy2;
  1268.     ras.arc[0].x = x;   ras.arc[0].y = y;
  1269.     do
  1270.     {
  1271.       y1 = ras.arc[3].y;
  1272.       y2 = ras.arc[2].y;
  1273.       y3 = ras.arc[1].y;
  1274.       y4 = ras.arc[0].y;
  1275.       x4 = ras.arc[0].x;
  1276.       /* first, categorize the Bezier arc */
  1277.       if ( y1 <= y4 )
  1278.       {
  1279.         ymin1 = y1;
  1280.         ymax1 = y4;
  1281.       }
  1282.       else
  1283.       {
  1284.         ymin1 = y4;
  1285.         ymax1 = y1;
  1286.       }
  1287.       if ( y2 <= y3 )
  1288.       {
  1289.         ymin2 = y2;
  1290.         ymax2 = y3;
  1291.       }
  1292.       else
  1293.       {
  1294.         ymin2 = y3;
  1295.         ymax2 = y2;
  1296.       }
  1297.       if ( ymin2 < ymin1 || ymax2 > ymax1 )
  1298.       {
  1299.         /* this arc has no given direction, split it! */
  1300.         Split_Cubic( ras.arc );
  1301.         ras.arc += 3;
  1302.       }
  1303.       else if ( y1 == y4 )
  1304.       {
  1305.         /* this arc is flat, ignore it and pop it from the Bezier stack */
  1306.         ras.arc -= 3;
  1307.       }
  1308.       else
  1309.       {
  1310.         state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
  1311.         /* detect a change of direction */
  1312.         if ( ras.state != state_bez )
  1313.         {
  1314.           if ( ras.state != Unknown_State   &&
  1315.                End_Profile( RAS_VAR ) )
  1316.             goto Fail;
  1317.           if ( New_Profile( RAS_VARS state_bez ) )
  1318.             goto Fail;
  1319.         }
  1320.         /* compute intersections */
  1321.         if ( state_bez == Ascending_State )
  1322.         {
  1323.           if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
  1324.             goto Fail;
  1325.         }
  1326.         else
  1327.           if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
  1328.             goto Fail;
  1329.       }
  1330.     } while ( ras.arc >= ras.arcs );
  1331.     ras.lastX = x4;
  1332.     ras.lastY = y4;
  1333.     return SUCCESS;
  1334.   Fail:
  1335.     return FAILURE;
  1336.   }
  1337. #undef  SWAP_
  1338. #define SWAP_( x, y )  do                
  1339.                        {                 
  1340.                          Long  swap = x; 
  1341.                                          
  1342.                                          
  1343.                          x = y;          
  1344.                          y = swap;       
  1345.                        } while ( 0 )
  1346.   /*************************************************************************/
  1347.   /*                                                                       */
  1348.   /* <Function>                                                            */
  1349.   /*    Decompose_Curve                                                    */
  1350.   /*                                                                       */
  1351.   /* <Description>                                                         */
  1352.   /*    Scans the outline arrays in order to emit individual segments and  */
  1353.   /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
  1354.   /*    weird cases, like when the first point is off the curve, or when   */
  1355.   /*    there are simply no `on' points in the contour!                    */
  1356.   /*                                                                       */
  1357.   /* <Input>                                                               */
  1358.   /*    first   :: The index of the first point in the contour.            */
  1359.   /*                                                                       */
  1360.   /*    last    :: The index of the last point in the contour.             */
  1361.   /*                                                                       */
  1362.   /*    flipped :: If set, flip the direction of the curve.                */
  1363.   /*                                                                       */
  1364.   /* <Return>                                                              */
  1365.   /*    SUCCESS on success, FAILURE on error.                              */
  1366.   /*                                                                       */
  1367.   static Bool
  1368.   Decompose_Curve( RAS_ARGS UShort  first,
  1369.                             UShort  last,
  1370.                             int     flipped )
  1371.   {
  1372.     FT_Vector   v_last;
  1373.     FT_Vector   v_control;
  1374.     FT_Vector   v_start;
  1375.     FT_Vector*  points;
  1376.     FT_Vector*  point;
  1377.     FT_Vector*  limit;
  1378.     char*       tags;
  1379.     unsigned    tag;       /* current point's state           */
  1380.     points = ras.outline.points;
  1381.     limit  = points + last;
  1382.     v_start.x = SCALED( points[first].x );
  1383.     v_start.y = SCALED( points[first].y );
  1384.     v_last.x  = SCALED( points[last].x );
  1385.     v_last.y  = SCALED( points[last].y );
  1386.     if ( flipped )
  1387.     {
  1388.       SWAP_( v_start.x, v_start.y );
  1389.       SWAP_( v_last.x, v_last.y );
  1390.     }
  1391.     v_control = v_start;
  1392.     point = points + first;
  1393.     tags  = ras.outline.tags  + first;
  1394.     tag   = FT_CURVE_TAG( tags[0] );
  1395.     /* A contour cannot start with a cubic control point! */
  1396.     if ( tag == FT_CURVE_TAG_CUBIC )
  1397.       goto Invalid_Outline;
  1398.     /* check first point to determine origin */
  1399.     if ( tag == FT_CURVE_TAG_CONIC )
  1400.     {
  1401.       /* first point is conic control.  Yes, this happens. */
  1402.       if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )
  1403.       {
  1404.         /* start at last point if it is on the curve */
  1405.         v_start = v_last;
  1406.         limit--;
  1407.       }
  1408.       else
  1409.       {
  1410.         /* if both first and last points are conic,         */
  1411.         /* start at their middle and record its position    */
  1412.         /* for closure                                      */
  1413.         v_start.x = ( v_start.x + v_last.x ) / 2;
  1414.         v_start.y = ( v_start.y + v_last.y ) / 2;
  1415.         v_last = v_start;
  1416.       }
  1417.       point--;
  1418.       tags--;
  1419.     }
  1420.     ras.lastX = v_start.x;
  1421.     ras.lastY = v_start.y;
  1422.     while ( point < limit )
  1423.     {
  1424.       point++;
  1425.       tags++;
  1426.       tag = FT_CURVE_TAG( tags[0] );
  1427.       switch ( tag )
  1428.       {
  1429.       case FT_CURVE_TAG_ON:  /* emit a single line_to */
  1430.         {
  1431.           Long  x, y;
  1432.           x = SCALED( point->x );
  1433.           y = SCALED( point->y );
  1434.           if ( flipped )
  1435.             SWAP_( x, y );
  1436.           if ( Line_To( RAS_VARS x, y ) )
  1437.             goto Fail;
  1438.           continue;
  1439.         }
  1440.       case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
  1441.         v_control.x = SCALED( point[0].x );
  1442.         v_control.y = SCALED( point[0].y );
  1443.         if ( flipped )
  1444.           SWAP_( v_control.x, v_control.y );
  1445.       Do_Conic:
  1446.         if ( point < limit )
  1447.         {
  1448.           FT_Vector  v_middle;
  1449.           Long       x, y;
  1450.           point++;
  1451.           tags++;
  1452.           tag = FT_CURVE_TAG( tags[0] );
  1453.           x = SCALED( point[0].x );
  1454.           y = SCALED( point[0].y );
  1455.           if ( flipped )
  1456.             SWAP_( x, y );
  1457.           if ( tag == FT_CURVE_TAG_ON )
  1458.           {
  1459.             if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
  1460.               goto Fail;
  1461.             continue;
  1462.           }
  1463.           if ( tag != FT_CURVE_TAG_CONIC )
  1464.             goto Invalid_Outline;
  1465.           v_middle.x = ( v_control.x + x ) / 2;
  1466.           v_middle.y = ( v_control.y + y ) / 2;
  1467.           if ( Conic_To( RAS_VARS v_control.x, v_control.y,
  1468.                                   v_middle.x,  v_middle.y ) )
  1469.             goto Fail;
  1470.           v_control.x = x;
  1471.           v_control.y = y;
  1472.           goto Do_Conic;
  1473.         }
  1474.         if ( Conic_To( RAS_VARS v_control.x, v_control.y,
  1475.                                 v_start.x,   v_start.y ) )
  1476.           goto Fail;
  1477.         goto Close;
  1478.       default:  /* FT_CURVE_TAG_CUBIC */
  1479.         {
  1480.           Long  x1, y1, x2, y2, x3, y3;
  1481.           if ( point + 1 > limit                             ||
  1482.                FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
  1483.             goto Invalid_Outline;
  1484.           point += 2;
  1485.           tags  += 2;
  1486.           x1 = SCALED( point[-2].x );
  1487.           y1 = SCALED( point[-2].y );
  1488.           x2 = SCALED( point[-1].x );
  1489.           y2 = SCALED( point[-1].y );
  1490.           x3 = SCALED( point[ 0].x );
  1491.           y3 = SCALED( point[ 0].y );
  1492.           if ( flipped )
  1493.           {
  1494.             SWAP_( x1, y1 );
  1495.             SWAP_( x2, y2 );
  1496.             SWAP_( x3, y3 );
  1497.           }
  1498.           if ( point <= limit )
  1499.           {
  1500.             if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
  1501.               goto Fail;
  1502.             continue;
  1503.           }
  1504.           if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
  1505.             goto Fail;
  1506.           goto Close;
  1507.         }
  1508.       }
  1509.     }
  1510.     /* close the contour with a line segment */
  1511.     if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
  1512.       goto Fail;
  1513.   Close:
  1514.     return SUCCESS;
  1515.   Invalid_Outline:
  1516.     ras.error = Raster_Err_Invalid;
  1517.   Fail:
  1518.     return FAILURE;
  1519.   }
  1520.   /*************************************************************************/
  1521.   /*                                                                       */
  1522.   /* <Function>                                                            */
  1523.   /*    Convert_Glyph                                                      */
  1524.   /*                                                                       */
  1525.   /* <Description>                                                         */
  1526.   /*    Converts a glyph into a series of segments and arcs and makes a    */
  1527.   /*    profiles list with them.                                           */
  1528.   /*                                                                       */
  1529.   /* <Input>                                                               */
  1530.   /*    flipped :: If set, flip the direction of curve.                    */
  1531.   /*                                                                       */
  1532.   /* <Return>                                                              */
  1533.   /*    SUCCESS on success, FAILURE if any error was encountered during    */
  1534.   /*    rendering.                                                         */
  1535.   /*                                                                       */
  1536.   static Bool
  1537.   Convert_Glyph( RAS_ARGS int  flipped )
  1538.   {
  1539.     int       i;
  1540.     unsigned  start;
  1541.     PProfile  lastProfile;
  1542.     ras.fProfile = NULL;
  1543.     ras.joint    = FALSE;
  1544.     ras.fresh    = FALSE;
  1545.     ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
  1546.     ras.numTurns = 0;
  1547.     ras.cProfile         = (PProfile)ras.top;
  1548.     ras.cProfile->offset = ras.top;
  1549.     ras.num_Profs        = 0;
  1550.     start = 0;
  1551.     for ( i = 0; i < ras.outline.n_contours; i++ )
  1552.     {
  1553.       ras.state    = Unknown_State;
  1554.       ras.gProfile = NULL;
  1555.       if ( Decompose_Curve( RAS_VARS (unsigned short)start,
  1556.                             ras.outline.contours[i],
  1557.                             flipped ) )
  1558.         return FAILURE;
  1559.       start = ras.outline.contours[i] + 1;
  1560.       /* We must now see whether the extreme arcs join or not */
  1561.       if ( FRAC( ras.lastY ) == 0 &&
  1562.            ras.lastY >= ras.minY  &&
  1563.            ras.lastY <= ras.maxY  )
  1564.         if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
  1565.           ras.top--;
  1566.         /* Note that ras.gProfile can be nil if the contour was too small */
  1567.         /* to be drawn.                                                   */
  1568.       lastProfile = ras.cProfile;
  1569.       if ( End_Profile( RAS_VAR ) )
  1570.         return FAILURE;
  1571.       /* close the `next profile in contour' linked list */
  1572.       if ( ras.gProfile )
  1573.         lastProfile->next = ras.gProfile;
  1574.     }
  1575.     if ( Finalize_Profile_Table( RAS_VAR ) )
  1576.       return FAILURE;
  1577.     return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
  1578.   }
  1579.   /*************************************************************************/
  1580.   /*************************************************************************/
  1581.   /**                                                                     **/
  1582.   /**  SCAN-LINE SWEEPS AND DRAWING                                       **/
  1583.   /**                                                                     **/
  1584.   /*************************************************************************/
  1585.   /*************************************************************************/
  1586.   /*************************************************************************/
  1587.   /*                                                                       */
  1588.   /*  Init_Linked                                                          */
  1589.   /*                                                                       */
  1590.   /*    Initializes an empty linked list.                                  */
  1591.   /*                                                                       */
  1592.   static void
  1593.   Init_Linked( TProfileList*  l )
  1594.   {
  1595.     *l = NULL;
  1596.   }
  1597.   /*************************************************************************/
  1598.   /*                                                                       */
  1599.   /*  InsNew                                                               */
  1600.   /*                                                                       */
  1601.   /*    Inserts a new profile in a linked list.                            */
  1602.   /*                                                                       */
  1603.   static void
  1604.   InsNew( PProfileList  list,
  1605.           PProfile      profile )
  1606.   {
  1607.     PProfile  *old, current;
  1608.     Long       x;
  1609.     old     = list;
  1610.     current = *old;
  1611.     x       = profile->X;
  1612.     while ( current )
  1613.     {
  1614.       if ( x < current->X )
  1615.         break;
  1616.       old     = &current->link;
  1617.       current = *old;
  1618.     }
  1619.     profile->link = current;
  1620.     *old          = profile;
  1621.   }
  1622.   /*************************************************************************/
  1623.   /*                                                                       */
  1624.   /*  DelOld                                                               */
  1625.   /*                                                                       */
  1626.   /*    Removes an old profile from a linked list.                         */
  1627.   /*                                                                       */
  1628.   static void
  1629.   DelOld( PProfileList  list,
  1630.           PProfile      profile )
  1631.   {
  1632.     PProfile  *old, current;
  1633.     old     = list;
  1634.     current = *old;
  1635.     while ( current )
  1636.     {
  1637.       if ( current == profile )
  1638.       {
  1639.         *old = current->link;
  1640.         return;
  1641.       }
  1642.       old     = &current->link;
  1643.       current = *old;
  1644.     }
  1645.     /* we should never get there, unless the profile was not part of */
  1646.     /* the list.                                                     */
  1647.   }
  1648.   /*************************************************************************/
  1649.   /*                                                                       */
  1650.   /*  Sort                                                                 */
  1651.   /*                                                                       */
  1652.   /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
  1653.   /*    an algorithm which is fast in this case.  Bubble sort is enough    */
  1654.   /*    and simple.                                                        */
  1655.   /*                                                                       */
  1656.   static void
  1657.   Sort( PProfileList  list )
  1658.   {
  1659.     PProfile  *old, current, next;
  1660.     /* First, set the new X coordinate of each profile */
  1661.     current = *list;
  1662.     while ( current )
  1663.     {
  1664.       current->X       = *current->offset;
  1665.       current->offset += current->flow;
  1666.       current->height--;
  1667.       current = current->link;
  1668.     }
  1669.     /* Then sort them */
  1670.     old     = list;
  1671.     current = *old;
  1672.     if ( !current )
  1673.       return;
  1674.     next = current->link;
  1675.     while ( next )
  1676.     {
  1677.       if ( current->X <= next->X )
  1678.       {
  1679.         old     = &current->link;
  1680.         current = *old;
  1681.         if ( !current )
  1682.           return;
  1683.       }
  1684.       else
  1685.       {
  1686.         *old          = next;
  1687.         current->link = next->link;
  1688.         next->link    = current;
  1689.         old     = list;
  1690.         current = *old;
  1691.       }
  1692.       next = current->link;
  1693.     }
  1694.   }
  1695.   /*************************************************************************/
  1696.   /*                                                                       */
  1697.   /*  Vertical Sweep Procedure Set                                         */
  1698.   /*                                                                       */
  1699.   /*  These four routines are used during the vertical black/white sweep   */
  1700.   /*  phase by the generic Draw_Sweep() function.                          */
  1701.   /*                                                                       */
  1702.   /*************************************************************************/
  1703.   static void
  1704.   Vertical_Sweep_Init( RAS_ARGS Short*  min,
  1705.                                 Short*  max )
  1706.   {
  1707.     Long  pitch = ras.target.pitch;
  1708.     FT_UNUSED( max );
  1709.     ras.traceIncr = (Short)-pitch;
  1710.     ras.traceOfs  = -*min * pitch;
  1711.     if ( pitch > 0 )
  1712.       ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
  1713.     ras.gray_min_x = 0;
  1714.     ras.gray_max_x = 0;
  1715.   }
  1716.   static void
  1717.   Vertical_Sweep_Span( RAS_ARGS Short       y,
  1718.                                 FT_F26Dot6  x1,
  1719.                                 FT_F26Dot6  x2,
  1720.                                 PProfile    left,
  1721.                                 PProfile    right )
  1722.   {
  1723.     Long   e1, e2;
  1724.     int    c1, c2;
  1725.     Byte   f1, f2;
  1726.     Byte*  target;
  1727.     FT_UNUSED( y );
  1728.     FT_UNUSED( left );
  1729.     FT_UNUSED( right );
  1730.     /* Drop-out control */
  1731.     e1 = TRUNC( CEILING( x1 ) );
  1732.     if ( x2 - x1 - ras.precision <= ras.precision_jitter )
  1733.       e2 = e1;
  1734.     else
  1735.       e2 = TRUNC( FLOOR( x2 ) );
  1736.     if ( e2 >= 0 && e1 < ras.bWidth )
  1737.     {
  1738.       if ( e1 < 0 )
  1739.         e1 = 0;
  1740.       if ( e2 >= ras.bWidth )
  1741.         e2 = ras.bWidth - 1;
  1742.       c1 = (Short)( e1 >> 3 );
  1743.       c2 = (Short)( e2 >> 3 );
  1744.       f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
  1745.       f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
  1746.       if ( ras.gray_min_x > c1 ) ras.gray_min_x = (short)c1;
  1747.       if ( ras.gray_max_x < c2 ) ras.gray_max_x = (short)c2;
  1748.       target = ras.bTarget + ras.traceOfs + c1;
  1749.       c2 -= c1;
  1750.       if ( c2 > 0 )
  1751.       {
  1752.         target[0] |= f1;
  1753.         /* memset() is slower than the following code on many platforms. */
  1754.         /* This is due to the fact that, in the vast majority of cases,  */
  1755.         /* the span length in bytes is relatively small.                 */
  1756.         c2--;
  1757.         while ( c2 > 0 )
  1758.         {
  1759.           *(++target) = 0xFF;
  1760.           c2--;
  1761.         }
  1762.         target[1] |= f2;
  1763.       }
  1764.       else
  1765.         *target |= ( f1 & f2 );
  1766.     }
  1767.   }
  1768.   static void
  1769.   Vertical_Sweep_Drop( RAS_ARGS Short       y,
  1770.                                 FT_F26Dot6  x1,
  1771.                                 FT_F26Dot6  x2,
  1772.                                 PProfile    left,
  1773.                                 PProfile    right )
  1774.   {
  1775.     Long   e1, e2;
  1776.     Short  c1, f1;
  1777.     /* Drop-out control */
  1778.     e1 = CEILING( x1 );
  1779.     e2 = FLOOR  ( x2 );
  1780.     if ( e1 > e2 )
  1781.     {
  1782.       if ( e1 == e2 + ras.precision )
  1783.       {
  1784.         switch ( ras.dropOutControl )
  1785.         {
  1786.         case 1:
  1787.           e1 = e2;
  1788.           break;
  1789.         case 4:
  1790.           e1 = CEILING( (x1 + x2 + 1) / 2 );
  1791.           break;
  1792.         case 2:
  1793.         case 5:
  1794.           /* Drop-out Control Rule #4 */
  1795.           /* The spec is not very clear regarding rule #4.  It      */
  1796.           /* presents a method that is way too costly to implement  */
  1797.           /* while the general idea seems to get rid of `stubs'.    */
  1798.           /*                                                        */
  1799.           /* Here, we only get rid of stubs recognized if:          */
  1800.           /*                                                        */
  1801.           /*  upper stub:                                           */
  1802.           /*                                                        */
  1803.           /*   - P_Left and P_Right are in the same contour         */
  1804.           /*   - P_Right is the successor of P_Left in that contour */
  1805.           /*   - y is the top of P_Left and P_Right                 */
  1806.           /*                                                        */
  1807.           /*  lower stub:                                           */
  1808.           /*                                                        */
  1809.           /*   - P_Left and P_Right are in the same contour         */
  1810.           /*   - P_Left is the successor of P_Right in that contour */
  1811.           /*   - y is the bottom of P_Left                          */
  1812.           /*                                                        */
  1813.           /* FIXXXME: uncommenting this line solves the disappearing */
  1814.           /*          bit problem in the `7' of verdana 10pts, but   */
  1815.           /*          makes a new one in the `C' of arial 14pts      */
  1816. #if 0
  1817.           if ( x2 - x1 < ras.precision_half )
  1818. #endif
  1819.           {
  1820.             /* upper stub test */
  1821.             if ( left->next == right && left->height <= 0 )
  1822.               return;
  1823.             /* lower stub test */
  1824.             if ( right->next == left && left->start == y )
  1825.               return;
  1826.           }
  1827.           /* check that the rightmost pixel isn't set */
  1828.           e1 = TRUNC( e1 );
  1829.           c1 = (Short)( e1 >> 3 );
  1830.           f1 = (Short)( e1 &  7 );
  1831.           if ( e1 >= 0 && e1 < ras.bWidth                      &&
  1832.                ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
  1833.             return;
  1834.           if ( ras.dropOutControl == 2 )
  1835.             e1 = e2;
  1836.           else
  1837.             e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
  1838.           break;
  1839.         default:
  1840.           return;  /* unsupported mode */
  1841.         }
  1842.       }
  1843.       else
  1844.         return;
  1845.     }
  1846.     e1 = TRUNC( e1 );
  1847.     if ( e1 >= 0 && e1 < ras.bWidth )
  1848.     {
  1849.       c1 = (Short)( e1 >> 3 );
  1850.       f1 = (Short)( e1 & 7 );
  1851.       if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
  1852.       if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
  1853.       ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
  1854.     }
  1855.   }
  1856.   static void
  1857.   Vertical_Sweep_Step( RAS_ARG )
  1858.   {
  1859.     ras.traceOfs += ras.traceIncr;
  1860.   }
  1861.   /***********************************************************************/
  1862.   /*                                                                     */
  1863.   /*  Horizontal Sweep Procedure Set                                     */
  1864.   /*                                                                     */
  1865.   /*  These four routines are used during the horizontal black/white     */
  1866.   /*  sweep phase by the generic Draw_Sweep() function.                  */
  1867.   /*                                                                     */
  1868.   /***********************************************************************/
  1869.   static void
  1870.   Horizontal_Sweep_Init( RAS_ARGS Short*  min,
  1871.                                   Short*  max )
  1872.   {
  1873.     /* nothing, really */
  1874.     FT_UNUSED_RASTER;
  1875.     FT_UNUSED( min );
  1876.     FT_UNUSED( max );
  1877.   }
  1878.   static void
  1879.   Horizontal_Sweep_Span( RAS_ARGS Short       y,
  1880.                                   FT_F26Dot6  x1,
  1881.                                   FT_F26Dot6  x2,
  1882.                                   PProfile    left,
  1883.                                   PProfile    right )
  1884.   {
  1885.     Long   e1, e2;
  1886.     PByte  bits;
  1887.     Byte   f1;
  1888.     FT_UNUSED( left );
  1889.     FT_UNUSED( right );
  1890.     if ( x2 - x1 < ras.precision )
  1891.     {
  1892.       e1 = CEILING( x1 );
  1893.       e2 = FLOOR  ( x2 );
  1894.       if ( e1 == e2 )
  1895.       {
  1896.         bits = ras.bTarget + ( y >> 3 );
  1897.         f1   = (Byte)( 0x80 >> ( y & 7 ) );
  1898.         e1 = TRUNC( e1 );
  1899.         if ( e1 >= 0 && e1 < ras.target.rows )
  1900.         {
  1901.           PByte  p;
  1902.           p = bits - e1*ras.target.pitch;
  1903.           if ( ras.target.pitch > 0 )
  1904.             p += ( ras.target.rows - 1 ) * ras.target.pitch;
  1905.           p[0] |= f1;
  1906.         }
  1907.       }
  1908.     }
  1909.   }
  1910.   static void
  1911.   Horizontal_Sweep_Drop( RAS_ARGS Short       y,
  1912.                                   FT_F26Dot6  x1,
  1913.                                   FT_F26Dot6  x2,
  1914.                                   PProfile    left,
  1915.                                   PProfile    right )
  1916.   {
  1917.     Long   e1, e2;
  1918.     PByte  bits;
  1919.     Byte   f1;
  1920.     /* During the horizontal sweep, we only take care of drop-outs */
  1921.     e1 = CEILING( x1 );
  1922.     e2 = FLOOR  ( x2 );
  1923.     if ( e1 > e2 )
  1924.     {
  1925.       if ( e1 == e2 + ras.precision )
  1926.       {
  1927.         switch ( ras.dropOutControl )
  1928.         {
  1929.         case 1:
  1930.           e1 = e2;
  1931.           break;
  1932.         case 4:
  1933.           e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
  1934.           break;
  1935.         case 2:
  1936.         case 5:
  1937.           /* Drop-out Control Rule #4 */
  1938.           /* The spec is not very clear regarding rule #4.  It      */
  1939.           /* presents a method that is way too costly to implement  */
  1940.           /* while the general idea seems to get rid of `stubs'.    */
  1941.           /*                                                        */
  1942.           /* rightmost stub test */
  1943.           if ( left->next == right && left->height <= 0 )
  1944.             return;
  1945.           /* leftmost stub test */
  1946.           if ( right->next == left && left->start == y )
  1947.             return;
  1948.           /* check that the rightmost pixel isn't set */
  1949.           e1 = TRUNC( e1 );
  1950.           bits = ras.bTarget + ( y >> 3 );
  1951.           f1   = (Byte)( 0x80 >> ( y & 7 ) );
  1952.           bits -= e1 * ras.target.pitch;
  1953.           if ( ras.target.pitch > 0 )
  1954.             bits += ( ras.target.rows - 1 ) * ras.target.pitch;
  1955.           if ( e1 >= 0              &&
  1956.                e1 < ras.target.rows &&
  1957.                *bits & f1 )
  1958.             return;
  1959.           if ( ras.dropOutControl == 2 )
  1960.             e1 = e2;
  1961.           else
  1962.             e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
  1963.           break;
  1964.         default:
  1965.           return;  /* unsupported mode */
  1966.         }
  1967.       }
  1968.       else
  1969.         return;
  1970.     }
  1971.     bits = ras.bTarget + ( y >> 3 );
  1972.     f1   = (Byte)( 0x80 >> ( y & 7 ) );
  1973.     e1 = TRUNC( e1 );
  1974.     if ( e1 >= 0 && e1 < ras.target.rows )
  1975.     {
  1976.       bits -= e1 * ras.target.pitch;
  1977.       if ( ras.target.pitch > 0 )
  1978.         bits += ( ras.target.rows - 1 ) * ras.target.pitch;
  1979.       bits[0] |= f1;
  1980.     }
  1981.   }
  1982.   static void
  1983.   Horizontal_Sweep_Step( RAS_ARG )
  1984.   {
  1985.     /* Nothing, really */
  1986.     FT_UNUSED_RASTER;
  1987.   }
  1988. #ifdef FT_RASTER_OPTION_ANTI_ALIASING
  1989.   /*************************************************************************/
  1990.   /*                                                                       */
  1991.   /*  Vertical Gray Sweep Procedure Set                                    */
  1992.   /*                                                                       */
  1993.   /*  These two routines are used during the vertical gray-levels sweep    */
  1994.   /*  phase by the generic Draw_Sweep() function.                          */
  1995.   /*                                                                       */
  1996.   /*  NOTES                                                                */
  1997.   /*                                                                       */
  1998.   /*  - The target pixmap's width *must* be a multiple of 4.               */
  1999.   /*                                                                       */
  2000.   /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
  2001.   /*    span call.                                                         */
  2002.   /*                                                                       */
  2003.   /*************************************************************************/
  2004.   static void
  2005.   Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
  2006.                                      Short*  max )
  2007.   {
  2008.     Long  pitch, byte_len;
  2009.     *min = *min & -2;
  2010.     *max = ( *max + 3 ) & -2;
  2011.     ras.traceOfs  = 0;
  2012.     pitch         = ras.target.pitch;
  2013.     byte_len      = -pitch;
  2014.     ras.traceIncr = (Short)byte_len;
  2015.     ras.traceG    = ( *min / 2 ) * byte_len;
  2016.     if ( pitch > 0 )
  2017.     {
  2018.       ras.traceG += ( ras.target.rows - 1 ) * pitch;
  2019.       byte_len    = -byte_len;
  2020.     }
  2021.     ras.gray_min_x =  (Short)byte_len;
  2022.     ras.gray_max_x = -(Short)byte_len;
  2023.   }
  2024.   static void
  2025.   Vertical_Gray_Sweep_Step( RAS_ARG )
  2026.   {
  2027.     Int    c1, c2;
  2028.     PByte  pix, bit, bit2;
  2029.     char*  count = (char*)count_table;
  2030.     Byte*  grays;
  2031.     ras.traceOfs += ras.gray_width;
  2032.     if ( ras.traceOfs > ras.gray_width )
  2033.     {
  2034.       pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
  2035.       grays = ras.grays;
  2036.       if ( ras.gray_max_x >= 0 )
  2037.       {
  2038.         Long   last_pixel = ras.target.width - 1;
  2039.         Int    last_cell  = last_pixel >> 2;
  2040.         Int    last_bit   = last_pixel & 3;
  2041.         Bool   over       = 0;
  2042.         if ( ras.gray_max_x >= last_cell && last_bit != 3 )
  2043.         {
  2044.           ras.gray_max_x = last_cell - 1;
  2045.           over = 1;
  2046.         }
  2047.         if ( ras.gray_min_x < 0 )
  2048.           ras.gray_min_x = 0;
  2049.         bit   = ras.bTarget + ras.gray_min_x;
  2050.         bit2  = bit + ras.gray_width;
  2051.         c1 = ras.gray_max_x - ras.gray_min_x;
  2052.         while ( c1 >= 0 )
  2053.         {
  2054.           c2 = count[*bit] + count[*bit2];
  2055.           if ( c2 )
  2056.           {
  2057.             pix[0] = grays[(c2 >> 12) & 0x000F];
  2058.             pix[1] = grays[(c2 >> 8 ) & 0x000F];
  2059.             pix[2] = grays[(c2 >> 4 ) & 0x000F];
  2060.             pix[3] = grays[ c2        & 0x000F];
  2061.             *bit  = 0;
  2062.             *bit2 = 0;
  2063.           }
  2064.           bit++;
  2065.           bit2++;
  2066.           pix += 4;
  2067.           c1--;
  2068.         }
  2069.         if ( over )
  2070.         {
  2071.           c2 = count[*bit] + count[*bit2];
  2072.           if ( c2 )
  2073.           {
  2074.             switch ( last_bit )
  2075.             {
  2076.             case 2:
  2077.               pix[2] = grays[(c2 >> 4 ) & 0x000F];
  2078.             case 1:
  2079.               pix[1] = grays[(c2 >> 8 ) & 0x000F];
  2080.             default:
  2081.               pix[0] = grays[(c2 >> 12) & 0x000F];
  2082.             }
  2083.             *bit  = 0;
  2084.             *bit2 = 0;
  2085.           }
  2086.         }
  2087.       }
  2088.       ras.traceOfs = 0;
  2089.       ras.traceG  += ras.traceIncr;
  2090.       ras.gray_min_x =  32000;
  2091.       ras.gray_max_x = -32000;
  2092.     }
  2093.   }
  2094.   static void
  2095.   Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
  2096.                                        FT_F26Dot6  x1,
  2097.                                        FT_F26Dot6  x2,
  2098.                                        PProfile    left,
  2099.                                        PProfile    right )
  2100.   {
  2101.     /* nothing, really */
  2102.     FT_UNUSED_RASTER;
  2103.     FT_UNUSED( y );
  2104.     FT_UNUSED( x1 );
  2105.     FT_UNUSED( x2 );
  2106.     FT_UNUSED( left );
  2107.     FT_UNUSED( right );
  2108.   }
  2109.   static void
  2110.   Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
  2111.                                        FT_F26Dot6  x1,
  2112.                                        FT_F26Dot6  x2,
  2113.                                        PProfile    left,
  2114.                                        PProfile    right )
  2115.   {
  2116.     Long   e1, e2;
  2117.     PByte  pixel;
  2118.     Byte   color;
  2119.     /* During the horizontal sweep, we only take care of drop-outs */
  2120.     e1 = CEILING( x1 );
  2121.     e2 = FLOOR  ( x2 );
  2122.     if ( e1 > e2 )
  2123.     {
  2124.       if ( e1 == e2 + ras.precision )
  2125.       {
  2126.         switch ( ras.dropOutControl )
  2127.         {
  2128.         case 1:
  2129.           e1 = e2;
  2130.           break;
  2131.         case 4:
  2132.           e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
  2133.           break;
  2134.         case 2:
  2135.         case 5:
  2136.           /* Drop-out Control Rule #4 */
  2137.           /* The spec is not very clear regarding rule #4.  It      */
  2138.           /* presents a method that is way too costly to implement  */
  2139.           /* while the general idea seems to get rid of `stubs'.    */
  2140.           /*                                                        */
  2141.           /* rightmost stub test */
  2142.           if ( left->next == right && left->height <= 0 )
  2143.             return;
  2144.           /* leftmost stub test */
  2145.           if ( right->next == left && left->start == y )
  2146.             return;
  2147.           if ( ras.dropOutControl == 2 )
  2148.             e1 = e2;
  2149.           else
  2150.             e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
  2151.           break;
  2152.         default:
  2153.           return;  /* unsupported mode */
  2154.         }
  2155.       }
  2156.       else
  2157.         return;
  2158.     }
  2159.     if ( e1 >= 0 )
  2160.     {
  2161.       if ( x2 - x1 >= ras.precision_half )
  2162.         color = ras.grays[2];
  2163.       else
  2164.         color = ras.grays[1];
  2165.       e1 = TRUNC( e1 ) / 2;
  2166.       if ( e1 < ras.target.rows )
  2167.       {
  2168.         pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
  2169.         if ( ras.target.pitch > 0 )
  2170.           pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
  2171.         if ( pixel[0] == ras.grays[0] )
  2172.           pixel[0] = color;
  2173.       }
  2174.     }
  2175.   }
  2176. #endif /* FT_RASTER_OPTION_ANTI_ALIASING */
  2177.   /*************************************************************************/
  2178.   /*                                                                       */
  2179.   /*  Generic Sweep Drawing routine                                        */
  2180.   /*                                                                       */
  2181.   /*************************************************************************/
  2182.   static Bool
  2183.   Draw_Sweep( RAS_ARG )
  2184.   {
  2185.     Short         y, y_change, y_height;
  2186.     PProfile      P, Q, P_Left, P_Right;
  2187.     Short         min_Y, max_Y, top, bottom, dropouts;
  2188.     Long          x1, x2, xs, e1, e2;
  2189.     TProfileList  waiting;
  2190.     TProfileList  draw_left, draw_right;
  2191.     /* Init empty linked lists */
  2192.     Init_Linked( &waiting );
  2193.     Init_Linked( &draw_left  );
  2194.     Init_Linked( &draw_right );
  2195.     /* first, compute min and max Y */
  2196.     P     = ras.fProfile;
  2197.     max_Y = (Short)TRUNC( ras.minY );
  2198.     min_Y = (Short)TRUNC( ras.maxY );
  2199.     while ( P )
  2200.     {
  2201.       Q = P->link;
  2202.       bottom = (Short)P->start;
  2203.       top    = (Short)( P->start + P->height - 1 );
  2204.       if ( min_Y > bottom ) min_Y = bottom;
  2205.       if ( max_Y < top    ) max_Y = top;
  2206.       P->X = 0;
  2207.       InsNew( &waiting, P );
  2208.       P = Q;
  2209.     }
  2210.     /* Check the Y-turns */
  2211.     if ( ras.numTurns == 0 )
  2212.     {
  2213.       ras.error = Raster_Err_Invalid;
  2214.       return FAILURE;
  2215.     }
  2216.     /* Now inits the sweep */
  2217.     ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
  2218.     /* Then compute the distance of each profile from min_Y */
  2219.     P = waiting;
  2220.     while ( P )
  2221.     {
  2222.       P->countL = (UShort)( P->start - min_Y );
  2223.       P = P->link;
  2224.     }
  2225.     /* Let's go */
  2226.     y        = min_Y;
  2227.     y_height = 0;
  2228.     if ( ras.numTurns > 0 &&
  2229.          ras.sizeBuff[-ras.numTurns] == min_Y )
  2230.       ras.numTurns--;
  2231.     while ( ras.numTurns > 0 )
  2232.     {
  2233.       /* look in the waiting list for new activations */
  2234.       P = waiting;
  2235.       while ( P )
  2236.       {
  2237.         Q = P->link;
  2238.         P->countL -= y_height;
  2239.         if ( P->countL == 0 )
  2240.         {
  2241.           DelOld( &waiting, P );
  2242.           switch ( P->flow )
  2243.           {
  2244.           case Flow_Up:
  2245.             InsNew( &draw_left,  P );
  2246.             break;
  2247.           case Flow_Down:
  2248.             InsNew( &draw_right, P );
  2249.             break;
  2250.           }
  2251.         }
  2252.         P = Q;
  2253.       }
  2254.       /* Sort the drawing lists */
  2255.       Sort( &draw_left );
  2256.       Sort( &draw_right );
  2257.       y_change = (Short)ras.sizeBuff[-ras.numTurns--];
  2258.       y_height = (Short)( y_change - y );
  2259.       while ( y < y_change )
  2260.       {
  2261.         /* Let's trace */
  2262.         dropouts = 0;
  2263.         P_Left  = draw_left;
  2264.         P_Right = draw_right;
  2265.         while ( P_Left )
  2266.         {
  2267.           x1 = P_Left ->X;
  2268.           x2 = P_Right->X;
  2269.           if ( x1 > x2 )
  2270.           {
  2271.             xs = x1;
  2272.             x1 = x2;
  2273.             x2 = xs;
  2274.           }
  2275.           if ( x2 - x1 <= ras.precision )
  2276.           {
  2277.             e1 = FLOOR( x1 );
  2278.             e2 = CEILING( x2 );
  2279.             if ( ras.dropOutControl != 0                 &&
  2280.                  ( e1 > e2 || e2 == e1 + ras.precision ) )
  2281.             {
  2282.               /* a drop out was detected */
  2283.               P_Left ->X = x1;
  2284.               P_Right->X = x2;
  2285.               /* mark profile for drop-out processing */
  2286.               P_Left->countL = 1;
  2287.               dropouts++;
  2288.               goto Skip_To_Next;
  2289.             }
  2290.           }
  2291.           ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
  2292.         Skip_To_Next:
  2293.           P_Left  = P_Left->link;
  2294.           P_Right = P_Right->link;
  2295.         }
  2296.         /* now perform the dropouts _after_ the span drawing -- */
  2297.         /* drop-outs processing has been moved out of the loop  */
  2298.         /* for performance tuning                               */
  2299.         if ( dropouts > 0 )
  2300.           goto Scan_DropOuts;
  2301.       Next_Line:
  2302.         ras.Proc_Sweep_Step( RAS_VAR );
  2303.         y++;
  2304.         if ( y < y_change )
  2305.         {
  2306.           Sort( &draw_left  );
  2307.           Sort( &draw_right );
  2308.         }
  2309.       }
  2310.       /* Now finalize the profiles that needs it */
  2311.       P = draw_left;
  2312.       while ( P )
  2313.       {
  2314.         Q = P->link;
  2315.         if ( P->height == 0 )
  2316.           DelOld( &draw_left, P );
  2317.         P = Q;
  2318.       }
  2319.       P = draw_right;
  2320.       while ( P )
  2321.       {
  2322.         Q = P->link;
  2323.         if ( P->height == 0 )
  2324.           DelOld( &draw_right, P );
  2325.         P = Q;
  2326.       }
  2327.     }
  2328.     /* for gray-scaling, flushes the bitmap scanline cache */
  2329.     while ( y <= max_Y )
  2330.     {
  2331.       ras.Proc_Sweep_Step( RAS_VAR );
  2332.       y++;
  2333.     }
  2334.     return SUCCESS;
  2335.   Scan_DropOuts:
  2336.     P_Left  = draw_left;
  2337.     P_Right = draw_right;
  2338.     while ( P_Left )
  2339.     {
  2340.       if ( P_Left->countL )
  2341.       {
  2342.         P_Left->countL = 0;
  2343. #if 0
  2344.         dropouts--;  /* -- this is useful when debugging only */
  2345. #endif
  2346.         ras.Proc_Sweep_Drop( RAS_VARS y,
  2347.                                       P_Left->X,
  2348.                                       P_Right->X,
  2349.                                       P_Left,
  2350.                                       P_Right );
  2351.       }
  2352.       P_Left  = P_Left->link;
  2353.       P_Right = P_Right->link;
  2354.     }
  2355.     goto Next_Line;
  2356.   }
  2357.   /*************************************************************************/
  2358.   /*                                                                       */
  2359.   /* <Function>                                                            */
  2360.   /*    Render_Single_Pass                                                 */
  2361.   /*                                                                       */
  2362.   /* <Description>                                                         */
  2363.   /*    Performs one sweep with sub-banding.                               */
  2364.   /*                                                                       */
  2365.   /* <Input>                                                               */
  2366.   /*    flipped :: If set, flip the direction of the outline.              */
  2367.   /*                                                                       */
  2368.   /* <Return>                                                              */
  2369.   /*    Renderer error code.                                               */
  2370.   /*                                                                       */
  2371.   static int
  2372.   Render_Single_Pass( RAS_ARGS Bool  flipped )
  2373.   {
  2374.     Short  i, j, k;
  2375.     while ( ras.band_top >= 0 )
  2376.     {
  2377.       ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
  2378.       ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
  2379.       ras.top = ras.buff;
  2380.       ras.error = Raster_Err_None;
  2381.       if ( Convert_Glyph( RAS_VARS flipped ) )
  2382.       {
  2383.         if ( ras.error != Raster_Err_Overflow )
  2384.           return FAILURE;
  2385.         ras.error = Raster_Err_None;
  2386.         /* sub-banding */
  2387. #ifdef DEBUG_RASTER
  2388.         ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
  2389. #endif
  2390.         i = ras.band_stack[ras.band_top].y_min;
  2391.         j = ras.band_stack[ras.band_top].y_max;
  2392.         k = (Short)( ( i + j ) / 2 );
  2393.         if ( ras.band_top >= 7 || k < i )
  2394.         {
  2395.           ras.band_top = 0;
  2396.           ras.error    = Raster_Err_Invalid;
  2397.           return ras.error;
  2398.         }
  2399.         ras.band_stack[ras.band_top + 1].y_min = k;
  2400.         ras.band_stack[ras.band_top + 1].y_max = j;
  2401.         ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
  2402.         ras.band_top++;
  2403.       }
  2404.       else
  2405.       {
  2406.         if ( ras.fProfile )
  2407.           if ( Draw_Sweep( RAS_VAR ) )
  2408.              return ras.error;
  2409.         ras.band_top--;
  2410.       }
  2411.     }
  2412.     return SUCCESS;
  2413.   }
  2414.   /*************************************************************************/
  2415.   /*                                                                       */
  2416.   /* <Function>                                                            */
  2417.   /*    Render_Glyph                                                       */
  2418.   /*                                                                       */
  2419.   /* <Description>                                                         */
  2420.   /*    Renders a glyph in a bitmap.  Sub-banding if needed.               */
  2421.   /*                                                                       */
  2422.   /* <Return>                                                              */
  2423.   /*    FreeType error code.  0 means success.                             */
  2424.   /*                                                                       */
  2425.   FT_LOCAL_DEF( FT_Error )
  2426.   Render_Glyph( RAS_ARG )
  2427.   {
  2428.     FT_Error  error;
  2429.     Set_High_Precision( RAS_VARS ras.outline.flags &
  2430.                         FT_OUTLINE_HIGH_PRECISION );
  2431.     ras.scale_shift    = ras.precision_shift;
  2432.     /* Drop-out mode 2 is hard-coded since this is the only mode used */
  2433.     /* on Windows platforms.  Using other modes, as specified by the  */
  2434.     /* font, results in misplaced pixels.                             */
  2435.     ras.dropOutControl = 2;
  2436.     ras.second_pass    = (FT_Byte)( !( ras.outline.flags &
  2437.                                        FT_OUTLINE_SINGLE_PASS ) );
  2438.     /* Vertical Sweep */
  2439.     ras.Proc_Sweep_Init = Vertical_Sweep_Init;
  2440.     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
  2441.     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
  2442.     ras.Proc_Sweep_Step = Vertical_Sweep_Step;
  2443.     ras.band_top            = 0;
  2444.     ras.band_stack[0].y_min = 0;
  2445.     ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
  2446.     ras.bWidth  = (unsigned short)ras.target.width;
  2447.     ras.bTarget = (Byte*)ras.target.buffer;
  2448.     if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
  2449.       return error;
  2450.     /* Horizontal Sweep */
  2451.     if ( ras.second_pass && ras.dropOutControl != 0 )
  2452.     {
  2453.       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
  2454.       ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
  2455.       ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
  2456.       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
  2457.       ras.band_top            = 0;
  2458.       ras.band_stack[0].y_min = 0;
  2459.       ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
  2460.       if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
  2461.         return error;
  2462.     }
  2463.     return Raster_Err_None;
  2464.   }
  2465. #ifdef FT_RASTER_OPTION_ANTI_ALIASING
  2466.   /*************************************************************************/
  2467.   /*                                                                       */
  2468.   /* <Function>                                                            */
  2469.   /*    Render_Gray_Glyph                                                  */
  2470.   /*                                                                       */
  2471.   /* <Description>                                                         */
  2472.   /*    Renders a glyph with grayscaling.  Sub-banding if needed.          */
  2473.   /*                                                                       */
  2474.   /* <Return>                                                              */
  2475.   /*    FreeType error code.  0 means success.                             */
  2476.   /*                                                                       */
  2477.   FT_LOCAL_DEF( FT_Error )
  2478.   Render_Gray_Glyph( RAS_ARG )
  2479.   {
  2480.     Long      pixel_width;
  2481.     FT_Error  error;
  2482.     Set_High_Precision( RAS_VARS ras.outline.flags &
  2483.                         FT_OUTLINE_HIGH_PRECISION );
  2484.     ras.scale_shift    = ras.precision_shift + 1;
  2485.     /* Drop-out mode 2 is hard-coded since this is the only mode used */
  2486.     /* on Windows platforms.  Using other modes, as specified by the  */
  2487.     /* font, results in misplaced pixels.                             */
  2488.     ras.dropOutControl = 2;
  2489.     ras.second_pass    = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
  2490.     /* Vertical Sweep */
  2491.     ras.band_top            = 0;
  2492.     ras.band_stack[0].y_min = 0;
  2493.     ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
  2494.     ras.bWidth  = ras.gray_width;
  2495.     pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
  2496.     if ( ras.bWidth > pixel_width )
  2497.       ras.bWidth = pixel_width;
  2498.     ras.bWidth  = ras.bWidth * 8;
  2499.     ras.bTarget = (Byte*)ras.gray_lines;
  2500.     ras.gTarget = (Byte*)ras.target.buffer;
  2501.     ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
  2502.     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
  2503.     ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
  2504.     ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
  2505.     error = Render_Single_Pass( RAS_VARS 0 );
  2506.     if ( error )
  2507.       return error;
  2508.     /* Horizontal Sweep */
  2509.     if ( ras.second_pass && ras.dropOutControl != 0 )
  2510.     {
  2511.       ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
  2512.       ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
  2513.       ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
  2514.       ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
  2515.       ras.band_top            = 0;
  2516.       ras.band_stack[0].y_min = 0;
  2517.       ras.band_stack[0].y_max = ras.target.width * 2 - 1;
  2518.       error = Render_Single_Pass( RAS_VARS 1 );
  2519.       if ( error )
  2520.         return error;
  2521.     }
  2522.     return Raster_Err_None;
  2523.   }
  2524. #else /* !FT_RASTER_OPTION_ANTI_ALIASING */
  2525.   FT_LOCAL_DEF( FT_Error )
  2526.   Render_Gray_Glyph( RAS_ARG )
  2527.   {
  2528.     FT_UNUSED_RASTER;
  2529.     return Raster_Err_Unsupported;
  2530.   }
  2531. #endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
  2532.   static void
  2533.   ft_black_init( PRaster  raster )
  2534.   {
  2535.     FT_UNUSED( raster );
  2536. #ifdef FT_RASTER_OPTION_ANTI_ALIASING
  2537.     FT_UInt  n;
  2538.     /* set default 5-levels gray palette */
  2539.     for ( n = 0; n < 5; n++ )
  2540.       raster->grays[n] = n * 255 / 4;
  2541.     raster->gray_width = RASTER_GRAY_LINES / 2;
  2542. #endif
  2543.   }
  2544.   /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
  2545.   /****                         a static object.                  *****/
  2546. #ifdef _STANDALONE_
  2547.   static int
  2548.   ft_black_new( void*      memory,
  2549.                 FT_Raster  *araster )
  2550.   {
  2551.      static TRaster  the_raster;
  2552.      *araster = (FT_Raster)&the_raster;
  2553.      FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
  2554.      ft_black_init( &the_raster );
  2555.      return 0;
  2556.   }
  2557.   static void
  2558.   ft_black_done( FT_Raster  raster )
  2559.   {
  2560.     /* nothing */
  2561.     FT_UNUSED( raster );
  2562.   }
  2563. #else /* _STANDALONE_ */
  2564.   static int
  2565.   ft_black_new( FT_Memory   memory,
  2566.                 PRaster    *araster )
  2567.   {
  2568.     FT_Error  error;
  2569.     PRaster   raster;
  2570.     *araster = 0;
  2571.     if ( !FT_NEW( raster ) )
  2572.     {
  2573.       raster->memory = memory;
  2574.       ft_black_init( raster );
  2575.       *araster = raster;
  2576.     }
  2577.     return error;
  2578.   }
  2579.   static void
  2580.   ft_black_done( PRaster  raster )
  2581.   {
  2582.     FT_Memory  memory = (FT_Memory)raster->memory;
  2583.     FT_FREE( raster );
  2584.   }
  2585. #endif /* _STANDALONE_ */
  2586.   static void
  2587.   ft_black_reset( PRaster   raster,
  2588.                   char*     pool_base,
  2589.                   long      pool_size )
  2590.   {
  2591.     if ( raster )
  2592.     {
  2593.       if ( pool_base && pool_size >= (long)sizeof(TWorker) + 2048 )
  2594.       {
  2595.         PWorker  worker = (PWorker)pool_base;
  2596.         raster->buffer      = pool_base + ( (sizeof ( *worker ) + 7 ) & ~7 );
  2597.         raster->buffer_size = ( ( pool_base + pool_size ) -
  2598.                                 (char*)raster->buffer ) / sizeof ( Long );
  2599.         raster->worker      = worker;
  2600.       }
  2601.       else
  2602.       {
  2603.         raster->buffer      = NULL;
  2604.         raster->buffer_size = 0;
  2605.         raster->worker      = NULL;
  2606.       }
  2607.     }
  2608.   }
  2609.   static void
  2610.   ft_black_set_mode( PRaster            raster,
  2611.                      unsigned long      mode,
  2612.                      const char*        palette )
  2613.   {
  2614. #ifdef FT_RASTER_OPTION_ANTI_ALIASING
  2615.     if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
  2616.     {
  2617.       /* set 5-levels gray palette */
  2618.       raster->grays[0] = palette[0];
  2619.       raster->grays[1] = palette[1];
  2620.       raster->grays[2] = palette[2];
  2621.       raster->grays[3] = palette[3];
  2622.       raster->grays[4] = palette[4];
  2623.     }
  2624. #else
  2625.     FT_UNUSED( raster );
  2626.     FT_UNUSED( mode );
  2627.     FT_UNUSED( palette );
  2628. #endif
  2629.   }
  2630.   static int
  2631.   ft_black_render( PRaster                  raster,
  2632.                    const FT_Raster_Params*  params )
  2633.   {
  2634.     const FT_Outline*  outline    = (const FT_Outline*)params->source;
  2635.     const FT_Bitmap*   target_map = params->target;
  2636.     PWorker            worker;
  2637.     if ( !raster || !raster->buffer || !raster->buffer_size )
  2638.       return Raster_Err_Not_Ini;
  2639.     /* return immediately if the outline is empty */
  2640.     if ( outline->n_points == 0 || outline->n_contours <= 0 )
  2641.       return Raster_Err_None;
  2642.     if ( !outline || !outline->contours || !outline->points )
  2643.       return Raster_Err_Invalid;
  2644.     if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
  2645.       return Raster_Err_Invalid;
  2646.     worker = raster->worker;
  2647.     /* this version of the raster does not support direct rendering, sorry */
  2648.     if ( params->flags & FT_RASTER_FLAG_DIRECT )
  2649.       return Raster_Err_Unsupported;
  2650.     if ( !target_map || !target_map->buffer )
  2651.       return Raster_Err_Invalid;
  2652.     ras.outline  = *outline;
  2653.     ras.target   = *target_map;
  2654.     worker->buff        = (PLong) raster->buffer;
  2655.     worker->sizeBuff    = worker->buff +
  2656.                             raster->buffer_size / sizeof ( Long );
  2657. #ifdef FT_RASTER_OPTION_ANTI_ALIASING
  2658.     worker->grays       = raster->grays;
  2659.     worker->gray_width  = raster->gray_width;
  2660. #endif
  2661.     return ( ( params->flags & FT_RASTER_FLAG_AA )
  2662.                ? Render_Gray_Glyph( RAS_VAR )
  2663.                : Render_Glyph( RAS_VAR ) );
  2664.   }
  2665.   const FT_Raster_Funcs  ft_standard_raster =
  2666.   {
  2667.     FT_GLYPH_FORMAT_OUTLINE,
  2668.     (FT_Raster_New_Func)     ft_black_new,
  2669.     (FT_Raster_Reset_Func)   ft_black_reset,
  2670.     (FT_Raster_Set_Mode_Func)ft_black_set_mode,
  2671.     (FT_Raster_Render_Func)  ft_black_render,
  2672.     (FT_Raster_Done_Func)    ft_black_done
  2673.   };
  2674. /* END */