- Remove svn:needs-lock, svn:eol-type, and svn:eol-tyle properties.
[reactos.git] / reactos / lib / 3rdparty / freetype / src / raster / ftraster.c
index 403f4d6..4cfca4e 100644 (file)
-/***************************************************************************/\r
-/*                                                                         */\r
-/*  ftraster.c                                                             */\r
-/*                                                                         */\r
-/*    The FreeType glyph rasterizer (body).                                */\r
-/*                                                                         */\r
-/*  Copyright 1996-2001, 2002, 2003, 2005, 2007 by                         */\r
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */\r
-/*                                                                         */\r
-/*  This file is part of the FreeType project, and may only be used,       */\r
-/*  modified, and distributed under the terms of the FreeType project      */\r
-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */\r
-/*  this file you indicate that you have read the license and              */\r
-/*  understand and accept it fully.                                        */\r
-/*                                                                         */\r
-/***************************************************************************/\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* This file can be compiled without the rest of the FreeType engine, by */\r
-  /* defining the _STANDALONE_ macro when compiling it.  You also need to  */\r
-  /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir)           */\r
-  /* directory.  Typically, you should do something like                   */\r
-  /*                                                                       */\r
-  /* - copy `src/raster/ftraster.c' (this file) to your current directory  */\r
-  /*                                                                       */\r
-  /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h'         */\r
-  /*   to your current directory                                           */\r
-  /*                                                                       */\r
-  /* - compile `ftraster' with the _STANDALONE_ macro defined, as in       */\r
-  /*                                                                       */\r
-  /*     cc -c -D_STANDALONE_ ftraster.c                                   */\r
-  /*                                                                       */\r
-  /* The renderer can be initialized with a call to                        */\r
-  /* `ft_standard_raster.raster_new'; a bitmap can be generated            */\r
-  /* with a call to `ft_standard_raster.raster_render'.                    */\r
-  /*                                                                       */\r
-  /* See the comments and documentation in the file `ftimage.h' for more   */\r
-  /* details on how the raster works.                                      */\r
-  /*                                                                       */\r
-  /*************************************************************************/\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* This is a rewrite of the FreeType 1.x scan-line converter             */\r
-  /*                                                                       */\r
-  /*************************************************************************/\r
-\r
-#ifdef _STANDALONE_\r
-\r
-#include "ftmisc.h"\r
-#include "ftimage.h"\r
-\r
-#else /* !_STANDALONE_ */\r
-\r
-#include <ft2build.h>\r
-#include "ftraster.h"\r
-#include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */\r
-\r
-#endif /* !_STANDALONE_ */\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* A simple technical note on how the raster works                       */\r
-  /* -----------------------------------------------                       */\r
-  /*                                                                       */\r
-  /*   Converting an outline into a bitmap is achieved in several steps:   */\r
-  /*                                                                       */\r
-  /*   1 - Decomposing the outline into successive `profiles'.  Each       */\r
-  /*       profile is simply an array of scanline intersections on a given */\r
-  /*       dimension.  A profile's main attributes are                     */\r
-  /*                                                                       */\r
-  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'.     */\r
-  /*                                                                       */\r
-  /*       o an array of intersection coordinates for each scanline        */\r
-  /*         between `Ymin' and `Ymax'.                                    */\r
-  /*                                                                       */\r
-  /*       o a direction, indicating whether it was built going `up' or    */\r
-  /*         `down', as this is very important for filling rules.          */\r
-  /*                                                                       */\r
-  /*   2 - Sweeping the target map's scanlines in order to compute segment */\r
-  /*       `spans' which are then filled.  Additionally, this pass         */\r
-  /*       performs drop-out control.                                      */\r
-  /*                                                                       */\r
-  /*   The outline data is parsed during step 1 only.  The profiles are    */\r
-  /*   built from the bottom of the render pool, used as a stack.  The     */\r
-  /*   following graphics shows the profile list under construction:       */\r
-  /*                                                                       */\r
-  /*     ____________________________________________________________ _ _  */\r
-  /*    |         |                   |         |                 |        */\r
-  /*    | profile | coordinates for   | profile | coordinates for |-->     */\r
-  /*    |    1    |  profile 1        |    2    |  profile 2      |-->     */\r
-  /*    |_________|___________________|_________|_________________|__ _ _  */\r
-  /*                                                                       */\r
-  /*    ^                                                         ^        */\r
-  /*    |                                                         |        */\r
-  /*  start of render pool                                       top       */\r
-  /*                                                                       */\r
-  /*   The top of the profile stack is kept in the `top' variable.         */\r
-  /*                                                                       */\r
-  /*   As you can see, a profile record is pushed on top of the render     */\r
-  /*   pool, which is then followed by its coordinates/intersections.  If  */\r
-  /*   a change of direction is detected in the outline, a new profile is  */\r
-  /*   generated until the end of the outline.                             */\r
-  /*                                                                       */\r
-  /*   Note that when all profiles have been generated, the function       */\r
-  /*   Finalize_Profile_Table() is used to record, for each profile, its   */\r
-  /*   bottom-most scanline as well as the scanline above its upmost       */\r
-  /*   boundary.  These positions are called `y-turns' because they (sort  */\r
-  /*   of) correspond to local extrema.  They are stored in a sorted list  */\r
-  /*   built from the top of the render pool as a downwards stack:         */\r
-  /*                                                                       */\r
-  /*      _ _ _______________________________________                      */\r
-  /*                            |                    |                     */\r
-  /*                         <--| sorted list of     |                     */\r
-  /*                         <--|  extrema scanlines |                     */\r
-  /*      _ _ __________________|____________________|                     */\r
-  /*                                                                       */\r
-  /*                            ^                    ^                     */\r
-  /*                            |                    |                     */\r
-  /*                         maxBuff           sizeBuff = end of pool      */\r
-  /*                                                                       */\r
-  /*   This list is later used during the sweep phase in order to          */\r
-  /*   optimize performance (see technical note on the sweep below).       */\r
-  /*                                                                       */\r
-  /*   Of course, the raster detects whether the two stacks collide and    */\r
-  /*   handles the situation properly.                                     */\r
-  /*                                                                       */\r
-  /*************************************************************************/\r
-\r
-\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-  /**                                                                     **/\r
-  /**  CONFIGURATION MACROS                                               **/\r
-  /**                                                                     **/\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-\r
-  /* define DEBUG_RASTER if you want to compile a debugging version */\r
-#define xxxDEBUG_RASTER\r
-\r
-  /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */\r
-  /* 5-levels anti-aliasing                                                */\r
-#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS\r
-#define FT_RASTER_OPTION_ANTI_ALIASING\r
-#endif\r
-\r
-  /* The size of the two-lines intermediate bitmap used */\r
-  /* for anti-aliasing, in bytes.                       */\r
-#define RASTER_GRAY_LINES  2048\r
-\r
-\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-  /**                                                                     **/\r
-  /**  OTHER MACROS (do not change)                                       **/\r
-  /**                                                                     **/\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */\r
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */\r
-  /* messages during execution.                                            */\r
-  /*                                                                       */\r
-#undef  FT_COMPONENT\r
-#define FT_COMPONENT  trace_raster\r
-\r
-\r
-#ifdef _STANDALONE_\r
-\r
-\r
-  /* This macro is used to indicate that a function parameter is unused. */\r
-  /* Its purpose is simply to reduce compiler warnings.  Note also that  */\r
-  /* simply defining it as `(void)x' doesn't avoid warnings with certain */\r
-  /* ANSI compilers (e.g. LCC).                                          */\r
-#define FT_UNUSED( x )  (x) = (x)\r
-\r
-  /* Disable the tracing mechanism for simplicity -- developers can      */\r
-  /* activate it easily by redefining these two macros.                  */\r
-#ifndef FT_ERROR\r
-#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */\r
-#endif\r
-\r
-#ifndef FT_TRACE\r
-#define FT_TRACE( x )   do ; while ( 0 )    /* nothing */\r
-#define FT_TRACE1( x )  do ; while ( 0 )    /* nothing */\r
-#define FT_TRACE6( x )  do ; while ( 0 )    /* nothing */\r
-#endif\r
-\r
-#define Raster_Err_None          0\r
-#define Raster_Err_Not_Ini      -1\r
-#define Raster_Err_Overflow     -2\r
-#define Raster_Err_Neg_Height   -3\r
-#define Raster_Err_Invalid      -4\r
-#define Raster_Err_Unsupported  -5\r
-\r
-#define ft_memset   memset\r
-\r
-#else /* _STANDALONE_ */\r
-\r
-\r
-#include FT_INTERNAL_OBJECTS_H\r
-#include FT_INTERNAL_DEBUG_H        /* for FT_TRACE() and FT_ERROR() */\r
-\r
-#include "rasterrs.h"\r
-\r
-#define Raster_Err_None         Raster_Err_Ok\r
-#define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized\r
-#define Raster_Err_Overflow     Raster_Err_Raster_Overflow\r
-#define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height\r
-#define Raster_Err_Invalid      Raster_Err_Invalid_Outline\r
-#define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph\r
-\r
-\r
-#endif /* _STANDALONE_ */\r
-\r
-\r
-#ifndef FT_MEM_SET\r
-#define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )\r
-#endif\r
-\r
-#ifndef FT_MEM_ZERO\r
-#define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )\r
-#endif\r
-\r
-  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */\r
-  /* typically a small value and the result of a*b is known to fit into */\r
-  /* 32 bits.                                                           */\r
-#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )\r
-\r
-  /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */\r
-  /* for clipping computations.  It simply uses the FT_MulDiv() function   */\r
-  /* defined in `ftcalc.h'.                                                */\r
-#define SMulDiv  FT_MulDiv\r
-\r
-  /* The rasterizer is a very general purpose component; please leave */\r
-  /* the following redefinitions there (you never know your target    */\r
-  /* environment).                                                    */\r
-\r
-#ifndef TRUE\r
-#define TRUE   1\r
-#endif\r
-\r
-#ifndef FALSE\r
-#define FALSE  0\r
-#endif\r
-\r
-#ifndef NULL\r
-#define NULL  (void*)0\r
-#endif\r
-\r
-#ifndef SUCCESS\r
-#define SUCCESS  0\r
-#endif\r
-\r
-#ifndef FAILURE\r
-#define FAILURE  1\r
-#endif\r
-\r
-\r
-#define MaxBezier  32   /* The maximum number of stacked Bezier curves. */\r
-                        /* Setting this constant to more than 32 is a   */\r
-                        /* pure waste of space.                         */\r
-\r
-#define Pixel_Bits  6   /* fractional bits of *input* coordinates */\r
-\r
-\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-  /**                                                                     **/\r
-  /**  SIMPLE TYPE DECLARATIONS                                           **/\r
-  /**                                                                     **/\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-\r
-  typedef int             Int;\r
-  typedef unsigned int    UInt;\r
-  typedef short           Short;\r
-  typedef unsigned short  UShort, *PUShort;\r
-  typedef long            Long, *PLong;\r
-  typedef unsigned long   ULong;\r
-\r
-  typedef unsigned char   Byte, *PByte;\r
-  typedef char            Bool;\r
-\r
-\r
-  typedef union  Alignment_\r
-  {\r
-    long    l;\r
-    void*   p;\r
-    void  (*f)(void);\r
-\r
-  } Alignment, *PAlignment;\r
-\r
-\r
-  typedef struct  TPoint_\r
-  {\r
-    Long  x;\r
-    Long  y;\r
-\r
-  } TPoint;\r
-\r
-\r
-  typedef enum  TFlow_\r
-  {\r
-    Flow_None = 0,\r
-    Flow_Up   = 1,\r
-    Flow_Down = -1\r
-\r
-  } TFlow;\r
-\r
-\r
-  /* States of each line, arc, and profile */\r
-  typedef enum  TStates_\r
-  {\r
-    Unknown_State,\r
-    Ascending_State,\r
-    Descending_State,\r
-    Flat_State\r
-\r
-  } TStates;\r
-\r
-\r
-  typedef struct TProfile_  TProfile;\r
-  typedef TProfile*         PProfile;\r
-\r
-  struct  TProfile_\r
-  {\r
-    FT_F26Dot6  X;           /* current coordinate during sweep        */\r
-    PProfile    link;        /* link to next profile - various purpose */\r
-    PLong       offset;      /* start of profile's data in render pool */\r
-    int         flow;        /* Profile orientation: Asc/Descending    */\r
-    long        height;      /* profile's height in scanlines          */\r
-    long        start;       /* profile's starting scanline            */\r
-\r
-    unsigned    countL;      /* number of lines to step before this    */\r
-                             /* profile becomes drawable               */\r
-\r
-    PProfile    next;        /* next profile in same contour, used     */\r
-                             /* during drop-out control                */\r
-  };\r
-\r
-  typedef PProfile   TProfileList;\r
-  typedef PProfile*  PProfileList;\r
-\r
-\r
-  /* Simple record used to implement a stack of bands, required */\r
-  /* by the sub-banding mechanism                               */\r
-  typedef struct  TBand_\r
-  {\r
-    Short  y_min;   /* band's minimum */\r
-    Short  y_max;   /* band's maximum */\r
-\r
-  } TBand;\r
-\r
-\r
-#define AlignProfileSize \\r
-  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )\r
-\r
-\r
-#ifdef FT_STATIC_RASTER\r
-\r
-\r
-#define RAS_ARGS       /* void */\r
-#define RAS_ARG        /* void */\r
-\r
-#define RAS_VARS       /* void */\r
-#define RAS_VAR        /* void */\r
-\r
-#define FT_UNUSED_RASTER  do ; while ( 0 )\r
-\r
-\r
-#else /* FT_STATIC_RASTER */\r
-\r
-\r
-#define RAS_ARGS       PWorker    worker,\r
-#define RAS_ARG        PWorker    worker\r
-\r
-#define RAS_VARS       worker,\r
-#define RAS_VAR        worker\r
-\r
-#define FT_UNUSED_RASTER  FT_UNUSED( worker )\r
-\r
-\r
-#endif /* FT_STATIC_RASTER */\r
-\r
-\r
-  typedef struct TWorker_   TWorker, *PWorker;\r
-\r
-\r
-  /* prototypes used for sweep function dispatch */\r
-  typedef void\r
-  Function_Sweep_Init( RAS_ARGS Short*  min,\r
-                                Short*  max );\r
-\r
-  typedef void\r
-  Function_Sweep_Span( RAS_ARGS Short       y,\r
-                                FT_F26Dot6  x1,\r
-                                FT_F26Dot6  x2,\r
-                                PProfile    left,\r
-                                PProfile    right );\r
-\r
-  typedef void\r
-  Function_Sweep_Step( RAS_ARG );\r
-\r
-\r
-  /* NOTE: These operations are only valid on 2's complement processors */\r
-\r
-#define FLOOR( x )    ( (x) & -ras.precision )\r
-#define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )\r
-#define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )\r
-#define FRAC( x )     ( (x) & ( ras.precision - 1 ) )\r
-#define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )\r
-\r
-  /* Note that I have moved the location of some fields in the */\r
-  /* structure to ensure that the most used variables are used */\r
-  /* at the top.  Thus, their offset can be coded with less    */\r
-  /* opcodes, and it results in a smaller executable.          */\r
-\r
-  struct  TWorker_\r
-  {\r
-    Int       precision_bits;       /* precision related variables         */\r
-    Int       precision;\r
-    Int       precision_half;\r
-    Long      precision_mask;\r
-    Int       precision_shift;\r
-    Int       precision_step;\r
-    Int       precision_jitter;\r
-\r
-    Int       scale_shift;          /* == precision_shift   for bitmaps    */\r
-                                    /* == precision_shift+1 for pixmaps    */\r
-\r
-    PLong     buff;                 /* The profiles buffer                 */\r
-    PLong     sizeBuff;             /* Render pool size                    */\r
-    PLong     maxBuff;              /* Profiles buffer size                */\r
-    PLong     top;                  /* Current cursor in buffer            */\r
-\r
-    FT_Error  error;\r
-\r
-    Int       numTurns;             /* number of Y-turns in outline        */\r
-\r
-    TPoint*   arc;                  /* current Bezier arc pointer          */\r
-\r
-    UShort    bWidth;               /* target bitmap width                 */\r
-    PByte     bTarget;              /* target bitmap buffer                */\r
-    PByte     gTarget;              /* target pixmap buffer                */\r
-\r
-    Long      lastX, lastY, minY, maxY;\r
-\r
-    UShort    num_Profs;            /* current number of profiles          */\r
-\r
-    Bool      fresh;                /* signals a fresh new profile which   */\r
-                                    /* 'start' field must be completed     */\r
-    Bool      joint;                /* signals that the last arc ended     */\r
-                                    /* exactly on a scanline.  Allows      */\r
-                                    /* removal of doublets                 */\r
-    PProfile  cProfile;             /* current profile                     */\r
-    PProfile  fProfile;             /* head of linked list of profiles     */\r
-    PProfile  gProfile;             /* contour's first profile in case     */\r
-                                    /* of impact                           */\r
-\r
-    TStates   state;                /* rendering state                     */\r
-\r
-    FT_Bitmap   target;             /* description of target bit/pixmap    */\r
-    FT_Outline  outline;\r
-\r
-    Long      traceOfs;             /* current offset in target bitmap     */\r
-    Long      traceG;               /* current offset in target pixmap     */\r
-\r
-    Short     traceIncr;            /* sweep's increment in target bitmap  */\r
-\r
-    Short     gray_min_x;           /* current min x during gray rendering */\r
-    Short     gray_max_x;           /* current max x during gray rendering */\r
-\r
-    /* dispatch variables */\r
-\r
-    Function_Sweep_Init*  Proc_Sweep_Init;\r
-    Function_Sweep_Span*  Proc_Sweep_Span;\r
-    Function_Sweep_Span*  Proc_Sweep_Drop;\r
-    Function_Sweep_Step*  Proc_Sweep_Step;\r
-\r
-    Byte      dropOutControl;       /* current drop_out control method     */\r
-\r
-    Bool      second_pass;          /* indicates whether a horizontal pass */\r
-                                    /* should be performed to control      */\r
-                                    /* drop-out accurately when calling    */\r
-                                    /* Render_Glyph.  Note that there is   */\r
-                                    /* no horizontal pass during gray      */\r
-                                    /* rendering.                          */\r
-\r
-    TPoint    arcs[3 * MaxBezier + 1]; /* The Bezier stack                 */\r
-\r
-    TBand     band_stack[16];       /* band stack used for sub-banding     */\r
-    Int       band_top;             /* band stack top                      */\r
-\r
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING\r
-\r
-    Byte*     grays;\r
-\r
-    Byte      gray_lines[RASTER_GRAY_LINES];\r
-                                /* Intermediate table used to render the   */\r
-                                /* graylevels pixmaps.                     */\r
-                                /* gray_lines is a buffer holding two      */\r
-                                /* monochrome scanlines                    */\r
-\r
-    Short     gray_width;       /* width in bytes of one monochrome        */\r
-                                /* intermediate scanline of gray_lines.    */\r
-                                /* Each gray pixel takes 2 bits long there */\r
-\r
-                       /* The gray_lines must hold 2 lines, thus with size */\r
-                       /* in bytes of at least `gray_width*2'.             */\r
-\r
-#endif /* FT_RASTER_ANTI_ALIASING */\r
-\r
-  };\r
-\r
-\r
-  typedef struct TRaster_\r
-  {\r
-    char*     buffer;\r
-    long      buffer_size;\r
-    void*     memory;\r
-    PWorker   worker;\r
-    Byte      grays[5];\r
-    Short     gray_width;\r
-\r
-  } TRaster, *PRaster;\r
-\r
-#ifdef FT_STATIC_RASTER\r
-\r
-  static TWorker   cur_ras;\r
-#define ras  cur_ras\r
-\r
-#else\r
-\r
-#define ras  (*worker)\r
-\r
-#endif /* FT_STATIC_RASTER */\r
-\r
-\r
-static const char  count_table[256] =\r
-{\r
-  0 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4,\r
-  1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,\r
-  1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,\r
-  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,\r
-  1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,\r
-  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,\r
-  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,\r
-  3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,\r
-  1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,\r
-  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,\r
-  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,\r
-  3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,\r
-  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,\r
-  3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,\r
-  3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,\r
-  4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 , 5 , 6 , 6 , 7 , 6 , 7 , 7 , 8 };\r
-\r
-\r
-\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-  /**                                                                     **/\r
-  /**  PROFILES COMPUTATION                                               **/\r
-  /**                                                                     **/\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Set_High_Precision                                                 */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Sets precision variables according to param flag.                  */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    High :: Set to True for high precision (typically for ppem < 18),  */\r
-  /*            false otherwise.                                           */\r
-  /*                                                                       */\r
-  static void\r
-  Set_High_Precision( RAS_ARGS Int  High )\r
-  {\r
-    if ( High )\r
-    {\r
-      ras.precision_bits   = 10;\r
-      ras.precision_step   = 128;\r
-      ras.precision_jitter = 24;\r
-    }\r
-    else\r
-    {\r
-      ras.precision_bits   = 6;\r
-      ras.precision_step   = 32;\r
-      ras.precision_jitter = 2;\r
-    }\r
-\r
-    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));\r
-\r
-    ras.precision       = 1 << ras.precision_bits;\r
-    ras.precision_half  = ras.precision / 2;\r
-    ras.precision_shift = ras.precision_bits - Pixel_Bits;\r
-    ras.precision_mask  = -ras.precision;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    New_Profile                                                        */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Creates a new profile in the render pool.                          */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    aState :: The state/orientation of the new profile.                */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */\r
-  /*   profile.                                                            */\r
-  /*                                                                       */\r
-  static Bool\r
-  New_Profile( RAS_ARGS TStates  aState )\r
-  {\r
-    if ( !ras.fProfile )\r
-    {\r
-      ras.cProfile  = (PProfile)ras.top;\r
-      ras.fProfile  = ras.cProfile;\r
-      ras.top      += AlignProfileSize;\r
-    }\r
-\r
-    if ( ras.top >= ras.maxBuff )\r
-    {\r
-      ras.error = Raster_Err_Overflow;\r
-      return FAILURE;\r
-    }\r
-\r
-    switch ( aState )\r
-    {\r
-    case Ascending_State:\r
-      ras.cProfile->flow = Flow_Up;\r
-      FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));\r
-      break;\r
-\r
-    case Descending_State:\r
-      ras.cProfile->flow = Flow_Down;\r
-      FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));\r
-      break;\r
-\r
-    default:\r
-      FT_ERROR(( "New_Profile: invalid profile direction!\n" ));\r
-      ras.error = Raster_Err_Invalid;\r
-      return FAILURE;\r
-    }\r
-\r
-    ras.cProfile->start  = 0;\r
-    ras.cProfile->height = 0;\r
-    ras.cProfile->offset = ras.top;\r
-    ras.cProfile->link   = (PProfile)0;\r
-    ras.cProfile->next   = (PProfile)0;\r
-\r
-    if ( !ras.gProfile )\r
-      ras.gProfile = ras.cProfile;\r
-\r
-    ras.state = aState;\r
-    ras.fresh = TRUE;\r
-    ras.joint = FALSE;\r
-\r
-    return SUCCESS;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    End_Profile                                                        */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Finalizes the current profile.                                     */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */\r
-  /*                                                                       */\r
-  static Bool\r
-  End_Profile( RAS_ARG )\r
-  {\r
-    Long      h;\r
-    PProfile  oldProfile;\r
-\r
-\r
-    h = (Long)( ras.top - ras.cProfile->offset );\r
-\r
-    if ( h < 0 )\r
-    {\r
-      FT_ERROR(( "End_Profile: negative height encountered!\n" ));\r
-      ras.error = Raster_Err_Neg_Height;\r
-      return FAILURE;\r
-    }\r
-\r
-    if ( h > 0 )\r
-    {\r
-      FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",\r
-                  (long)ras.cProfile, ras.cProfile->start, h ));\r
-\r
-      oldProfile           = ras.cProfile;\r
-      ras.cProfile->height = h;\r
-      ras.cProfile         = (PProfile)ras.top;\r
-\r
-      ras.top             += AlignProfileSize;\r
-\r
-      ras.cProfile->height = 0;\r
-      ras.cProfile->offset = ras.top;\r
-      oldProfile->next     = ras.cProfile;\r
-      ras.num_Profs++;\r
-    }\r
-\r
-    if ( ras.top >= ras.maxBuff )\r
-    {\r
-      FT_TRACE1(( "overflow in End_Profile\n" ));\r
-      ras.error = Raster_Err_Overflow;\r
-      return FAILURE;\r
-    }\r
-\r
-    ras.joint = FALSE;\r
-\r
-    return SUCCESS;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Insert_Y_Turn                                                      */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Inserts a salient into the sorted list placed on top of the render */\r
-  /*    pool.                                                              */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    New y scanline position.                                           */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    SUCCESS on success.  FAILURE in case of overflow.                  */\r
-  /*                                                                       */\r
-  static Bool\r
-  Insert_Y_Turn( RAS_ARGS Int  y )\r
-  {\r
-    PLong  y_turns;\r
-    Int    y2, n;\r
-\r
-\r
-    n       = ras.numTurns - 1;\r
-    y_turns = ras.sizeBuff - ras.numTurns;\r
-\r
-    /* look for first y value that is <= */\r
-    while ( n >= 0 && y < y_turns[n] )\r
-      n--;\r
-\r
-    /* if it is <, simply insert it, ignore if == */\r
-    if ( n >= 0 && y > y_turns[n] )\r
-      while ( n >= 0 )\r
-      {\r
-        y2 = (Int)y_turns[n];\r
-        y_turns[n] = y;\r
-        y = y2;\r
-        n--;\r
-      }\r
-\r
-    if ( n < 0 )\r
-    {\r
-      ras.maxBuff--;\r
-      if ( ras.maxBuff <= ras.top )\r
-      {\r
-        ras.error = Raster_Err_Overflow;\r
-        return FAILURE;\r
-      }\r
-      ras.numTurns++;\r
-      ras.sizeBuff[-ras.numTurns] = y;\r
-    }\r
-\r
-    return SUCCESS;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Finalize_Profile_Table                                             */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Adjusts all links in the profiles list.                            */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    SUCCESS on success.  FAILURE in case of overflow.                  */\r
-  /*                                                                       */\r
-  static Bool\r
-  Finalize_Profile_Table( RAS_ARG )\r
-  {\r
-    Int       bottom, top;\r
-    UShort    n;\r
-    PProfile  p;\r
-\r
-\r
-    n = ras.num_Profs;\r
-\r
-    if ( n > 1 )\r
-    {\r
-      p = ras.fProfile;\r
-      while ( n > 0 )\r
-      {\r
-        if ( n > 1 )\r
-          p->link = (PProfile)( p->offset + p->height );\r
-        else\r
-          p->link = NULL;\r
-\r
-        switch ( p->flow )\r
-        {\r
-        case Flow_Down:\r
-          bottom     = (Int)( p->start - p->height + 1 );\r
-          top        = (Int)p->start;\r
-          p->start   = bottom;\r
-          p->offset += p->height - 1;\r
-          break;\r
-\r
-        case Flow_Up:\r
-        default:\r
-          bottom = (Int)p->start;\r
-          top    = (Int)( p->start + p->height - 1 );\r
-        }\r
-\r
-        if ( Insert_Y_Turn( RAS_VARS bottom )   ||\r
-             Insert_Y_Turn( RAS_VARS top + 1 )  )\r
-          return FAILURE;\r
-\r
-        p = p->link;\r
-        n--;\r
-      }\r
-    }\r
-    else\r
-      ras.fProfile = NULL;\r
-\r
-    return SUCCESS;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Split_Conic                                                        */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Subdivides one conic Bezier into two joint sub-arcs in the Bezier  */\r
-  /*    stack.                                                             */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    None (subdivided Bezier is taken from the top of the stack).       */\r
-  /*                                                                       */\r
-  /* <Note>                                                                */\r
-  /*    This routine is the `beef' of this component.  It is  _the_ inner  */\r
-  /*    loop that should be optimized to hell to get the best performance. */\r
-  /*                                                                       */\r
-  static void\r
-  Split_Conic( TPoint*  base )\r
-  {\r
-    Long  a, b;\r
-\r
-\r
-    base[4].x = base[2].x;\r
-    b = base[1].x;\r
-    a = base[3].x = ( base[2].x + b ) / 2;\r
-    b = base[1].x = ( base[0].x + b ) / 2;\r
-    base[2].x = ( a + b ) / 2;\r
-\r
-    base[4].y = base[2].y;\r
-    b = base[1].y;\r
-    a = base[3].y = ( base[2].y + b ) / 2;\r
-    b = base[1].y = ( base[0].y + b ) / 2;\r
-    base[2].y = ( a + b ) / 2;\r
-\r
-    /* hand optimized.  gcc doesn't seem to be too good at common      */\r
-    /* expression substitution and instruction scheduling ;-)          */\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Split_Cubic                                                        */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Subdivides a third-order Bezier arc into two joint sub-arcs in the */\r
-  /*    Bezier stack.                                                      */\r
-  /*                                                                       */\r
-  /* <Note>                                                                */\r
-  /*    This routine is the `beef' of the component.  It is one of _the_   */\r
-  /*    inner loops that should be optimized like hell to get the best     */\r
-  /*    performance.                                                       */\r
-  /*                                                                       */\r
-  static void\r
-  Split_Cubic( TPoint*  base )\r
-  {\r
-    Long  a, b, c, d;\r
-\r
-\r
-    base[6].x = base[3].x;\r
-    c = base[1].x;\r
-    d = base[2].x;\r
-    base[1].x = a = ( base[0].x + c + 1 ) >> 1;\r
-    base[5].x = b = ( base[3].x + d + 1 ) >> 1;\r
-    c = ( c + d + 1 ) >> 1;\r
-    base[2].x = a = ( a + c + 1 ) >> 1;\r
-    base[4].x = b = ( b + c + 1 ) >> 1;\r
-    base[3].x = ( a + b + 1 ) >> 1;\r
-\r
-    base[6].y = base[3].y;\r
-    c = base[1].y;\r
-    d = base[2].y;\r
-    base[1].y = a = ( base[0].y + c + 1 ) >> 1;\r
-    base[5].y = b = ( base[3].y + d + 1 ) >> 1;\r
-    c = ( c + d + 1 ) >> 1;\r
-    base[2].y = a = ( a + c + 1 ) >> 1;\r
-    base[4].y = b = ( b + c + 1 ) >> 1;\r
-    base[3].y = ( a + b + 1 ) >> 1;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Line_Up                                                            */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Computes the x-coordinates of an ascending line segment and stores */\r
-  /*    them in the render pool.                                           */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    x1   :: The x-coordinate of the segment's start point.             */\r
-  /*                                                                       */\r
-  /*    y1   :: The y-coordinate of the segment's start point.             */\r
-  /*                                                                       */\r
-  /*    x2   :: The x-coordinate of the segment's end point.               */\r
-  /*                                                                       */\r
-  /*    y2   :: The y-coordinate of the segment's end point.               */\r
-  /*                                                                       */\r
-  /*    miny :: A lower vertical clipping bound value.                     */\r
-  /*                                                                       */\r
-  /*    maxy :: An upper vertical clipping bound value.                    */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    SUCCESS on success, FAILURE on render pool overflow.               */\r
-  /*                                                                       */\r
-  static Bool\r
-  Line_Up( RAS_ARGS Long  x1,\r
-                    Long  y1,\r
-                    Long  x2,\r
-                    Long  y2,\r
-                    Long  miny,\r
-                    Long  maxy )\r
-  {\r
-    Long   Dx, Dy;\r
-    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */\r
-    Long   Ix, Rx, Ax;\r
-\r
-    PLong  top;\r
-\r
-\r
-    Dx = x2 - x1;\r
-    Dy = y2 - y1;\r
-\r
-    if ( Dy <= 0 || y2 < miny || y1 > maxy )\r
-      return SUCCESS;\r
-\r
-    if ( y1 < miny )\r
-    {\r
-      /* Take care: miny-y1 can be a very large value; we use     */\r
-      /*            a slow MulDiv function to avoid clipping bugs */\r
-      x1 += SMulDiv( Dx, miny - y1, Dy );\r
-      e1  = (Int)TRUNC( miny );\r
-      f1  = 0;\r
-    }\r
-    else\r
-    {\r
-      e1 = (Int)TRUNC( y1 );\r
-      f1 = (Int)FRAC( y1 );\r
-    }\r
-\r
-    if ( y2 > maxy )\r
-    {\r
-      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */\r
-      e2  = (Int)TRUNC( maxy );\r
-      f2  = 0;\r
-    }\r
-    else\r
-    {\r
-      e2 = (Int)TRUNC( y2 );\r
-      f2 = (Int)FRAC( y2 );\r
-    }\r
-\r
-    if ( f1 > 0 )\r
-    {\r
-      if ( e1 == e2 )\r
-        return SUCCESS;\r
-      else\r
-      {\r
-        x1 += FMulDiv( Dx, ras.precision - f1, Dy );\r
-        e1 += 1;\r
-      }\r
-    }\r
-    else\r
-      if ( ras.joint )\r
-      {\r
-        ras.top--;\r
-        ras.joint = FALSE;\r
-      }\r
-\r
-    ras.joint = (char)( f2 == 0 );\r
-\r
-    if ( ras.fresh )\r
-    {\r
-      ras.cProfile->start = e1;\r
-      ras.fresh           = FALSE;\r
-    }\r
-\r
-    size = e2 - e1 + 1;\r
-    if ( ras.top + size >= ras.maxBuff )\r
-    {\r
-      ras.error = Raster_Err_Overflow;\r
-      return FAILURE;\r
-    }\r
-\r
-    if ( Dx > 0 )\r
-    {\r
-      Ix = ( ras.precision * Dx ) / Dy;\r
-      Rx = ( ras.precision * Dx ) % Dy;\r
-      Dx = 1;\r
-    }\r
-    else\r
-    {\r
-      Ix = -( ( ras.precision * -Dx ) / Dy );\r
-      Rx =    ( ras.precision * -Dx ) % Dy;\r
-      Dx = -1;\r
-    }\r
-\r
-    Ax  = -Dy;\r
-    top = ras.top;\r
-\r
-    while ( size > 0 )\r
-    {\r
-      *top++ = x1;\r
-\r
-      x1 += Ix;\r
-      Ax += Rx;\r
-      if ( Ax >= 0 )\r
-      {\r
-        Ax -= Dy;\r
-        x1 += Dx;\r
-      }\r
-      size--;\r
-    }\r
-\r
-    ras.top = top;\r
-    return SUCCESS;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Line_Down                                                          */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Computes the x-coordinates of an descending line segment and       */\r
-  /*    stores them in the render pool.                                    */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    x1   :: The x-coordinate of the segment's start point.             */\r
-  /*                                                                       */\r
-  /*    y1   :: The y-coordinate of the segment's start point.             */\r
-  /*                                                                       */\r
-  /*    x2   :: The x-coordinate of the segment's end point.               */\r
-  /*                                                                       */\r
-  /*    y2   :: The y-coordinate of the segment's end point.               */\r
-  /*                                                                       */\r
-  /*    miny :: A lower vertical clipping bound value.                     */\r
-  /*                                                                       */\r
-  /*    maxy :: An upper vertical clipping bound value.                    */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    SUCCESS on success, FAILURE on render pool overflow.               */\r
-  /*                                                                       */\r
-  static Bool\r
-  Line_Down( RAS_ARGS Long  x1,\r
-                      Long  y1,\r
-                      Long  x2,\r
-                      Long  y2,\r
-                      Long  miny,\r
-                      Long  maxy )\r
-  {\r
-    Bool  result, fresh;\r
-\r
-\r
-    fresh  = ras.fresh;\r
-\r
-    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );\r
-\r
-    if ( fresh && !ras.fresh )\r
-      ras.cProfile->start = -ras.cProfile->start;\r
-\r
-    return result;\r
-  }\r
-\r
-\r
-  /* A function type describing the functions used to split Bezier arcs */\r
-  typedef void  (*TSplitter)( TPoint*  base );\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Bezier_Up                                                          */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Computes the x-coordinates of an ascending Bezier arc and stores   */\r
-  /*    them in the render pool.                                           */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */\r
-  /*                                                                       */\r
-  /*    splitter :: The function to split Bezier arcs.                     */\r
-  /*                                                                       */\r
-  /*    miny     :: A lower vertical clipping bound value.                 */\r
-  /*                                                                       */\r
-  /*    maxy     :: An upper vertical clipping bound value.                */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    SUCCESS on success, FAILURE on render pool overflow.               */\r
-  /*                                                                       */\r
-  static Bool\r
-  Bezier_Up( RAS_ARGS Int        degree,\r
-                      TSplitter  splitter,\r
-                      Long       miny,\r
-                      Long       maxy )\r
-  {\r
-    Long   y1, y2, e, e2, e0;\r
-    Short  f1;\r
-\r
-    TPoint*  arc;\r
-    TPoint*  start_arc;\r
-\r
-    PLong top;\r
-\r
-\r
-    arc = ras.arc;\r
-    y1  = arc[degree].y;\r
-    y2  = arc[0].y;\r
-    top = ras.top;\r
-\r
-    if ( y2 < miny || y1 > maxy )\r
-      goto Fin;\r
-\r
-    e2 = FLOOR( y2 );\r
-\r
-    if ( e2 > maxy )\r
-      e2 = maxy;\r
-\r
-    e0 = miny;\r
-\r
-    if ( y1 < miny )\r
-      e = miny;\r
-    else\r
-    {\r
-      e  = CEILING( y1 );\r
-      f1 = (Short)( FRAC( y1 ) );\r
-      e0 = e;\r
-\r
-      if ( f1 == 0 )\r
-      {\r
-        if ( ras.joint )\r
-        {\r
-          top--;\r
-          ras.joint = FALSE;\r
-        }\r
-\r
-        *top++ = arc[degree].x;\r
-\r
-        e += ras.precision;\r
-      }\r
-    }\r
-\r
-    if ( ras.fresh )\r
-    {\r
-      ras.cProfile->start = TRUNC( e0 );\r
-      ras.fresh = FALSE;\r
-    }\r
-\r
-    if ( e2 < e )\r
-      goto Fin;\r
-\r
-    if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )\r
-    {\r
-      ras.top   = top;\r
-      ras.error = Raster_Err_Overflow;\r
-      return FAILURE;\r
-    }\r
-\r
-    start_arc = arc;\r
-\r
-    while ( arc >= start_arc && e <= e2 )\r
-    {\r
-      ras.joint = FALSE;\r
-\r
-      y2 = arc[0].y;\r
-\r
-      if ( y2 > e )\r
-      {\r
-        y1 = arc[degree].y;\r
-        if ( y2 - y1 >= ras.precision_step )\r
-        {\r
-          splitter( arc );\r
-          arc += degree;\r
-        }\r
-        else\r
-        {\r
-          *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,\r
-                                            e - y1, y2 - y1 );\r
-          arc -= degree;\r
-          e   += ras.precision;\r
-        }\r
-      }\r
-      else\r
-      {\r
-        if ( y2 == e )\r
-        {\r
-          ras.joint  = TRUE;\r
-          *top++     = arc[0].x;\r
-\r
-          e += ras.precision;\r
-        }\r
-        arc -= degree;\r
-      }\r
-    }\r
-\r
-  Fin:\r
-    ras.top  = top;\r
-    ras.arc -= degree;\r
-    return SUCCESS;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Bezier_Down                                                        */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Computes the x-coordinates of an descending Bezier arc and stores  */\r
-  /*    them in the render pool.                                           */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */\r
-  /*                                                                       */\r
-  /*    splitter :: The function to split Bezier arcs.                     */\r
-  /*                                                                       */\r
-  /*    miny     :: A lower vertical clipping bound value.                 */\r
-  /*                                                                       */\r
-  /*    maxy     :: An upper vertical clipping bound value.                */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    SUCCESS on success, FAILURE on render pool overflow.               */\r
-  /*                                                                       */\r
-  static Bool\r
-  Bezier_Down( RAS_ARGS Int        degree,\r
-                        TSplitter  splitter,\r
-                        Long       miny,\r
-                        Long       maxy )\r
-  {\r
-    TPoint*  arc = ras.arc;\r
-    Bool     result, fresh;\r
-\r
-\r
-    arc[0].y = -arc[0].y;\r
-    arc[1].y = -arc[1].y;\r
-    arc[2].y = -arc[2].y;\r
-    if ( degree > 2 )\r
-      arc[3].y = -arc[3].y;\r
-\r
-    fresh = ras.fresh;\r
-\r
-    result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );\r
-\r
-    if ( fresh && !ras.fresh )\r
-      ras.cProfile->start = -ras.cProfile->start;\r
-\r
-    arc[0].y = -arc[0].y;\r
-    return result;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Line_To                                                            */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Injects a new line segment and adjusts Profiles list.              */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*   x :: The x-coordinate of the segment's end point (its start point   */\r
-  /*        is stored in `lastX').                                         */\r
-  /*                                                                       */\r
-  /*   y :: The y-coordinate of the segment's end point (its start point   */\r
-  /*        is stored in `lastY').                                         */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */\r
-  /*   profile.                                                            */\r
-  /*                                                                       */\r
-  static Bool\r
-  Line_To( RAS_ARGS Long  x,\r
-                    Long  y )\r
-  {\r
-    /* First, detect a change of direction */\r
-\r
-    switch ( ras.state )\r
-    {\r
-    case Unknown_State:\r
-      if ( y > ras.lastY )\r
-      {\r
-        if ( New_Profile( RAS_VARS Ascending_State ) )\r
-          return FAILURE;\r
-      }\r
-      else\r
-      {\r
-        if ( y < ras.lastY )\r
-          if ( New_Profile( RAS_VARS Descending_State ) )\r
-            return FAILURE;\r
-      }\r
-      break;\r
-\r
-    case Ascending_State:\r
-      if ( y < ras.lastY )\r
-      {\r
-        if ( End_Profile( RAS_VAR )                   ||\r
-             New_Profile( RAS_VARS Descending_State ) )\r
-          return FAILURE;\r
-      }\r
-      break;\r
-\r
-    case Descending_State:\r
-      if ( y > ras.lastY )\r
-      {\r
-        if ( End_Profile( RAS_VAR )                  ||\r
-             New_Profile( RAS_VARS Ascending_State ) )\r
-          return FAILURE;\r
-      }\r
-      break;\r
-\r
-    default:\r
-      ;\r
-    }\r
-\r
-    /* Then compute the lines */\r
-\r
-    switch ( ras.state )\r
-    {\r
-    case Ascending_State:\r
-      if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,\r
-                    x, y, ras.minY, ras.maxY ) )\r
-        return FAILURE;\r
-      break;\r
-\r
-    case Descending_State:\r
-      if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,\r
-                      x, y, ras.minY, ras.maxY ) )\r
-        return FAILURE;\r
-      break;\r
-\r
-    default:\r
-      ;\r
-    }\r
-\r
-    ras.lastX = x;\r
-    ras.lastY = y;\r
-\r
-    return SUCCESS;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Conic_To                                                           */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Injects a new conic arc and adjusts the profile list.              */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*   cx :: The x-coordinate of the arc's new control point.              */\r
-  /*                                                                       */\r
-  /*   cy :: The y-coordinate of the arc's new control point.              */\r
-  /*                                                                       */\r
-  /*   x  :: The x-coordinate of the arc's end point (its start point is   */\r
-  /*         stored in `lastX').                                           */\r
-  /*                                                                       */\r
-  /*   y  :: The y-coordinate of the arc's end point (its start point is   */\r
-  /*         stored in `lastY').                                           */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */\r
-  /*   profile.                                                            */\r
-  /*                                                                       */\r
-  static Bool\r
-  Conic_To( RAS_ARGS Long  cx,\r
-                     Long  cy,\r
-                     Long  x,\r
-                     Long  y )\r
-  {\r
-    Long     y1, y2, y3, x3, ymin, ymax;\r
-    TStates  state_bez;\r
-\r
-\r
-    ras.arc      = ras.arcs;\r
-    ras.arc[2].x = ras.lastX;\r
-    ras.arc[2].y = ras.lastY;\r
-    ras.arc[1].x = cx; ras.arc[1].y = cy;\r
-    ras.arc[0].x = x;  ras.arc[0].y = y;\r
-\r
-    do\r
-    {\r
-      y1 = ras.arc[2].y;\r
-      y2 = ras.arc[1].y;\r
-      y3 = ras.arc[0].y;\r
-      x3 = ras.arc[0].x;\r
-\r
-      /* first, categorize the Bezier arc */\r
-\r
-      if ( y1 <= y3 )\r
-      {\r
-        ymin = y1;\r
-        ymax = y3;\r
-      }\r
-      else\r
-      {\r
-        ymin = y3;\r
-        ymax = y1;\r
-      }\r
-\r
-      if ( y2 < ymin || y2 > ymax )\r
-      {\r
-        /* this arc has no given direction, split it! */\r
-        Split_Conic( ras.arc );\r
-        ras.arc += 2;\r
-      }\r
-      else if ( y1 == y3 )\r
-      {\r
-        /* this arc is flat, ignore it and pop it from the Bezier stack */\r
-        ras.arc -= 2;\r
-      }\r
-      else\r
-      {\r
-        /* the arc is y-monotonous, either ascending or descending */\r
-        /* detect a change of direction                            */\r
-        state_bez = y1 < y3 ? Ascending_State : Descending_State;\r
-        if ( ras.state != state_bez )\r
-        {\r
-          /* finalize current profile if any */\r
-          if ( ras.state != Unknown_State   &&\r
-               End_Profile( RAS_VAR ) )\r
-            goto Fail;\r
-\r
-          /* create a new profile */\r
-          if ( New_Profile( RAS_VARS state_bez ) )\r
-            goto Fail;\r
-        }\r
-\r
-        /* now call the appropriate routine */\r
-        if ( state_bez == Ascending_State )\r
-        {\r
-          if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )\r
-            goto Fail;\r
-        }\r
-        else\r
-          if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )\r
-            goto Fail;\r
-      }\r
-\r
-    } while ( ras.arc >= ras.arcs );\r
-\r
-    ras.lastX = x3;\r
-    ras.lastY = y3;\r
-\r
-    return SUCCESS;\r
-\r
-  Fail:\r
-    return FAILURE;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Cubic_To                                                           */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Injects a new cubic arc and adjusts the profile list.              */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*   cx1 :: The x-coordinate of the arc's first new control point.       */\r
-  /*                                                                       */\r
-  /*   cy1 :: The y-coordinate of the arc's first new control point.       */\r
-  /*                                                                       */\r
-  /*   cx2 :: The x-coordinate of the arc's second new control point.      */\r
-  /*                                                                       */\r
-  /*   cy2 :: The y-coordinate of the arc's second new control point.      */\r
-  /*                                                                       */\r
-  /*   x   :: The x-coordinate of the arc's end point (its start point is  */\r
-  /*          stored in `lastX').                                          */\r
-  /*                                                                       */\r
-  /*   y   :: The y-coordinate of the arc's end point (its start point is  */\r
-  /*          stored in `lastY').                                          */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */\r
-  /*   profile.                                                            */\r
-  /*                                                                       */\r
-  static Bool\r
-  Cubic_To( RAS_ARGS Long  cx1,\r
-                     Long  cy1,\r
-                     Long  cx2,\r
-                     Long  cy2,\r
-                     Long  x,\r
-                     Long  y )\r
-  {\r
-    Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;\r
-    TStates  state_bez;\r
-\r
-\r
-    ras.arc      = ras.arcs;\r
-    ras.arc[3].x = ras.lastX;\r
-    ras.arc[3].y = ras.lastY;\r
-    ras.arc[2].x = cx1; ras.arc[2].y = cy1;\r
-    ras.arc[1].x = cx2; ras.arc[1].y = cy2;\r
-    ras.arc[0].x = x;   ras.arc[0].y = y;\r
-\r
-    do\r
-    {\r
-      y1 = ras.arc[3].y;\r
-      y2 = ras.arc[2].y;\r
-      y3 = ras.arc[1].y;\r
-      y4 = ras.arc[0].y;\r
-      x4 = ras.arc[0].x;\r
-\r
-      /* first, categorize the Bezier arc */\r
-\r
-      if ( y1 <= y4 )\r
-      {\r
-        ymin1 = y1;\r
-        ymax1 = y4;\r
-      }\r
-      else\r
-      {\r
-        ymin1 = y4;\r
-        ymax1 = y1;\r
-      }\r
-\r
-      if ( y2 <= y3 )\r
-      {\r
-        ymin2 = y2;\r
-        ymax2 = y3;\r
-      }\r
-      else\r
-      {\r
-        ymin2 = y3;\r
-        ymax2 = y2;\r
-      }\r
-\r
-      if ( ymin2 < ymin1 || ymax2 > ymax1 )\r
-      {\r
-        /* this arc has no given direction, split it! */\r
-        Split_Cubic( ras.arc );\r
-        ras.arc += 3;\r
-      }\r
-      else if ( y1 == y4 )\r
-      {\r
-        /* this arc is flat, ignore it and pop it from the Bezier stack */\r
-        ras.arc -= 3;\r
-      }\r
-      else\r
-      {\r
-        state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;\r
-\r
-        /* detect a change of direction */\r
-        if ( ras.state != state_bez )\r
-        {\r
-          if ( ras.state != Unknown_State   &&\r
-               End_Profile( RAS_VAR ) )\r
-            goto Fail;\r
-\r
-          if ( New_Profile( RAS_VARS state_bez ) )\r
-            goto Fail;\r
-        }\r
-\r
-        /* compute intersections */\r
-        if ( state_bez == Ascending_State )\r
-        {\r
-          if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )\r
-            goto Fail;\r
-        }\r
-        else\r
-          if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )\r
-            goto Fail;\r
-      }\r
-\r
-    } while ( ras.arc >= ras.arcs );\r
-\r
-    ras.lastX = x4;\r
-    ras.lastY = y4;\r
-\r
-    return SUCCESS;\r
-\r
-  Fail:\r
-    return FAILURE;\r
-  }\r
-\r
-\r
-#undef  SWAP_\r
-#define SWAP_( x, y )  do                \\r
-                       {                 \\r
-                         Long  swap = x; \\r
-                                         \\r
-                                         \\r
-                         x = y;          \\r
-                         y = swap;       \\r
-                       } while ( 0 )\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Decompose_Curve                                                    */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Scans the outline arrays in order to emit individual segments and  */\r
-  /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */\r
-  /*    weird cases, like when the first point is off the curve, or when   */\r
-  /*    there are simply no `on' points in the contour!                    */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    first   :: The index of the first point in the contour.            */\r
-  /*                                                                       */\r
-  /*    last    :: The index of the last point in the contour.             */\r
-  /*                                                                       */\r
-  /*    flipped :: If set, flip the direction of the curve.                */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    SUCCESS on success, FAILURE on error.                              */\r
-  /*                                                                       */\r
-  static Bool\r
-  Decompose_Curve( RAS_ARGS UShort  first,\r
-                            UShort  last,\r
-                            int     flipped )\r
-  {\r
-    FT_Vector   v_last;\r
-    FT_Vector   v_control;\r
-    FT_Vector   v_start;\r
-\r
-    FT_Vector*  points;\r
-    FT_Vector*  point;\r
-    FT_Vector*  limit;\r
-    char*       tags;\r
-\r
-    unsigned    tag;       /* current point's state           */\r
-\r
-\r
-    points = ras.outline.points;\r
-    limit  = points + last;\r
-\r
-    v_start.x = SCALED( points[first].x );\r
-    v_start.y = SCALED( points[first].y );\r
-    v_last.x  = SCALED( points[last].x );\r
-    v_last.y  = SCALED( points[last].y );\r
-\r
-    if ( flipped )\r
-    {\r
-      SWAP_( v_start.x, v_start.y );\r
-      SWAP_( v_last.x, v_last.y );\r
-    }\r
-\r
-    v_control = v_start;\r
-\r
-    point = points + first;\r
-    tags  = ras.outline.tags  + first;\r
-    tag   = FT_CURVE_TAG( tags[0] );\r
-\r
-    /* A contour cannot start with a cubic control point! */\r
-    if ( tag == FT_CURVE_TAG_CUBIC )\r
-      goto Invalid_Outline;\r
-\r
-    /* check first point to determine origin */\r
-    if ( tag == FT_CURVE_TAG_CONIC )\r
-    {\r
-      /* first point is conic control.  Yes, this happens. */\r
-      if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )\r
-      {\r
-        /* start at last point if it is on the curve */\r
-        v_start = v_last;\r
-        limit--;\r
-      }\r
-      else\r
-      {\r
-        /* if both first and last points are conic,         */\r
-        /* start at their middle and record its position    */\r
-        /* for closure                                      */\r
-        v_start.x = ( v_start.x + v_last.x ) / 2;\r
-        v_start.y = ( v_start.y + v_last.y ) / 2;\r
-\r
-        v_last = v_start;\r
-      }\r
-      point--;\r
-      tags--;\r
-    }\r
-\r
-    ras.lastX = v_start.x;\r
-    ras.lastY = v_start.y;\r
-\r
-    while ( point < limit )\r
-    {\r
-      point++;\r
-      tags++;\r
-\r
-      tag = FT_CURVE_TAG( tags[0] );\r
-\r
-      switch ( tag )\r
-      {\r
-      case FT_CURVE_TAG_ON:  /* emit a single line_to */\r
-        {\r
-          Long  x, y;\r
-\r
-\r
-          x = SCALED( point->x );\r
-          y = SCALED( point->y );\r
-          if ( flipped )\r
-            SWAP_( x, y );\r
-\r
-          if ( Line_To( RAS_VARS x, y ) )\r
-            goto Fail;\r
-          continue;\r
-        }\r
-\r
-      case FT_CURVE_TAG_CONIC:  /* consume conic arcs */\r
-        v_control.x = SCALED( point[0].x );\r
-        v_control.y = SCALED( point[0].y );\r
-\r
-        if ( flipped )\r
-          SWAP_( v_control.x, v_control.y );\r
-\r
-      Do_Conic:\r
-        if ( point < limit )\r
-        {\r
-          FT_Vector  v_middle;\r
-          Long       x, y;\r
-\r
-\r
-          point++;\r
-          tags++;\r
-          tag = FT_CURVE_TAG( tags[0] );\r
-\r
-          x = SCALED( point[0].x );\r
-          y = SCALED( point[0].y );\r
-\r
-          if ( flipped )\r
-            SWAP_( x, y );\r
-\r
-          if ( tag == FT_CURVE_TAG_ON )\r
-          {\r
-            if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )\r
-              goto Fail;\r
-            continue;\r
-          }\r
-\r
-          if ( tag != FT_CURVE_TAG_CONIC )\r
-            goto Invalid_Outline;\r
-\r
-          v_middle.x = ( v_control.x + x ) / 2;\r
-          v_middle.y = ( v_control.y + y ) / 2;\r
-\r
-          if ( Conic_To( RAS_VARS v_control.x, v_control.y,\r
-                                  v_middle.x,  v_middle.y ) )\r
-            goto Fail;\r
-\r
-          v_control.x = x;\r
-          v_control.y = y;\r
-\r
-          goto Do_Conic;\r
-        }\r
-\r
-        if ( Conic_To( RAS_VARS v_control.x, v_control.y,\r
-                                v_start.x,   v_start.y ) )\r
-          goto Fail;\r
-\r
-        goto Close;\r
-\r
-      default:  /* FT_CURVE_TAG_CUBIC */\r
-        {\r
-          Long  x1, y1, x2, y2, x3, y3;\r
-\r
-\r
-          if ( point + 1 > limit                             ||\r
-               FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )\r
-            goto Invalid_Outline;\r
-\r
-          point += 2;\r
-          tags  += 2;\r
-\r
-          x1 = SCALED( point[-2].x );\r
-          y1 = SCALED( point[-2].y );\r
-          x2 = SCALED( point[-1].x );\r
-          y2 = SCALED( point[-1].y );\r
-          x3 = SCALED( point[ 0].x );\r
-          y3 = SCALED( point[ 0].y );\r
-\r
-          if ( flipped )\r
-          {\r
-            SWAP_( x1, y1 );\r
-            SWAP_( x2, y2 );\r
-            SWAP_( x3, y3 );\r
-          }\r
-\r
-          if ( point <= limit )\r
-          {\r
-            if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )\r
-              goto Fail;\r
-            continue;\r
-          }\r
-\r
-          if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )\r
-            goto Fail;\r
-          goto Close;\r
-        }\r
-      }\r
-    }\r
-\r
-    /* close the contour with a line segment */\r
-    if ( Line_To( RAS_VARS v_start.x, v_start.y ) )\r
-      goto Fail;\r
-\r
-  Close:\r
-    return SUCCESS;\r
-\r
-  Invalid_Outline:\r
-    ras.error = Raster_Err_Invalid;\r
-\r
-  Fail:\r
-    return FAILURE;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Convert_Glyph                                                      */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Converts a glyph into a series of segments and arcs and makes a    */\r
-  /*    profiles list with them.                                           */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    flipped :: If set, flip the direction of curve.                    */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    SUCCESS on success, FAILURE if any error was encountered during    */\r
-  /*    rendering.                                                         */\r
-  /*                                                                       */\r
-  static Bool\r
-  Convert_Glyph( RAS_ARGS int  flipped )\r
-  {\r
-    int       i;\r
-    unsigned  start;\r
-\r
-    PProfile  lastProfile;\r
-\r
-\r
-    ras.fProfile = NULL;\r
-    ras.joint    = FALSE;\r
-    ras.fresh    = FALSE;\r
-\r
-    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;\r
-\r
-    ras.numTurns = 0;\r
-\r
-    ras.cProfile         = (PProfile)ras.top;\r
-    ras.cProfile->offset = ras.top;\r
-    ras.num_Profs        = 0;\r
-\r
-    start = 0;\r
-\r
-    for ( i = 0; i < ras.outline.n_contours; i++ )\r
-    {\r
-      ras.state    = Unknown_State;\r
-      ras.gProfile = NULL;\r
-\r
-      if ( Decompose_Curve( RAS_VARS (unsigned short)start,\r
-                            ras.outline.contours[i],\r
-                            flipped ) )\r
-        return FAILURE;\r
-\r
-      start = ras.outline.contours[i] + 1;\r
-\r
-      /* We must now see whether the extreme arcs join or not */\r
-      if ( FRAC( ras.lastY ) == 0 &&\r
-           ras.lastY >= ras.minY  &&\r
-           ras.lastY <= ras.maxY  )\r
-        if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )\r
-          ras.top--;\r
-        /* Note that ras.gProfile can be nil if the contour was too small */\r
-        /* to be drawn.                                                   */\r
-\r
-      lastProfile = ras.cProfile;\r
-      if ( End_Profile( RAS_VAR ) )\r
-        return FAILURE;\r
-\r
-      /* close the `next profile in contour' linked list */\r
-      if ( ras.gProfile )\r
-        lastProfile->next = ras.gProfile;\r
-    }\r
-\r
-    if ( Finalize_Profile_Table( RAS_VAR ) )\r
-      return FAILURE;\r
-\r
-    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-  /**                                                                     **/\r
-  /**  SCAN-LINE SWEEPS AND DRAWING                                       **/\r
-  /**                                                                     **/\r
-  /*************************************************************************/\r
-  /*************************************************************************/\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /*  Init_Linked                                                          */\r
-  /*                                                                       */\r
-  /*    Initializes an empty linked list.                                  */\r
-  /*                                                                       */\r
-  static void\r
-  Init_Linked( TProfileList*  l )\r
-  {\r
-    *l = NULL;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /*  InsNew                                                               */\r
-  /*                                                                       */\r
-  /*    Inserts a new profile in a linked list.                            */\r
-  /*                                                                       */\r
-  static void\r
-  InsNew( PProfileList  list,\r
-          PProfile      profile )\r
-  {\r
-    PProfile  *old, current;\r
-    Long       x;\r
-\r
-\r
-    old     = list;\r
-    current = *old;\r
-    x       = profile->X;\r
-\r
-    while ( current )\r
-    {\r
-      if ( x < current->X )\r
-        break;\r
-      old     = &current->link;\r
-      current = *old;\r
-    }\r
-\r
-    profile->link = current;\r
-    *old          = profile;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /*  DelOld                                                               */\r
-  /*                                                                       */\r
-  /*    Removes an old profile from a linked list.                         */\r
-  /*                                                                       */\r
-  static void\r
-  DelOld( PProfileList  list,\r
-          PProfile      profile )\r
-  {\r
-    PProfile  *old, current;\r
-\r
-\r
-    old     = list;\r
-    current = *old;\r
-\r
-    while ( current )\r
-    {\r
-      if ( current == profile )\r
-      {\r
-        *old = current->link;\r
-        return;\r
-      }\r
-\r
-      old     = &current->link;\r
-      current = *old;\r
-    }\r
-\r
-    /* we should never get there, unless the profile was not part of */\r
-    /* the list.                                                     */\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /*  Sort                                                                 */\r
-  /*                                                                       */\r
-  /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */\r
-  /*    an algorithm which is fast in this case.  Bubble sort is enough    */\r
-  /*    and simple.                                                        */\r
-  /*                                                                       */\r
-  static void\r
-  Sort( PProfileList  list )\r
-  {\r
-    PProfile  *old, current, next;\r
-\r
-\r
-    /* First, set the new X coordinate of each profile */\r
-    current = *list;\r
-    while ( current )\r
-    {\r
-      current->X       = *current->offset;\r
-      current->offset += current->flow;\r
-      current->height--;\r
-      current = current->link;\r
-    }\r
-\r
-    /* Then sort them */\r
-    old     = list;\r
-    current = *old;\r
-\r
-    if ( !current )\r
-      return;\r
-\r
-    next = current->link;\r
-\r
-    while ( next )\r
-    {\r
-      if ( current->X <= next->X )\r
-      {\r
-        old     = &current->link;\r
-        current = *old;\r
-\r
-        if ( !current )\r
-          return;\r
-      }\r
-      else\r
-      {\r
-        *old          = next;\r
-        current->link = next->link;\r
-        next->link    = current;\r
-\r
-        old     = list;\r
-        current = *old;\r
-      }\r
-\r
-      next = current->link;\r
-    }\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /*  Vertical Sweep Procedure Set                                         */\r
-  /*                                                                       */\r
-  /*  These four routines are used during the vertical black/white sweep   */\r
-  /*  phase by the generic Draw_Sweep() function.                          */\r
-  /*                                                                       */\r
-  /*************************************************************************/\r
-\r
-  static void\r
-  Vertical_Sweep_Init( RAS_ARGS Short*  min,\r
-                                Short*  max )\r
-  {\r
-    Long  pitch = ras.target.pitch;\r
-\r
-    FT_UNUSED( max );\r
-\r
-\r
-    ras.traceIncr = (Short)-pitch;\r
-    ras.traceOfs  = -*min * pitch;\r
-    if ( pitch > 0 )\r
-      ras.traceOfs += ( ras.target.rows - 1 ) * pitch;\r
-\r
-    ras.gray_min_x = 0;\r
-    ras.gray_max_x = 0;\r
-  }\r
-\r
-\r
-  static void\r
-  Vertical_Sweep_Span( RAS_ARGS Short       y,\r
-                                FT_F26Dot6  x1,\r
-                                FT_F26Dot6  x2,\r
-                                PProfile    left,\r
-                                PProfile    right )\r
-  {\r
-    Long   e1, e2;\r
-    int    c1, c2;\r
-    Byte   f1, f2;\r
-    Byte*  target;\r
-\r
-    FT_UNUSED( y );\r
-    FT_UNUSED( left );\r
-    FT_UNUSED( right );\r
-\r
-\r
-    /* Drop-out control */\r
-\r
-    e1 = TRUNC( CEILING( x1 ) );\r
-\r
-    if ( x2 - x1 - ras.precision <= ras.precision_jitter )\r
-      e2 = e1;\r
-    else\r
-      e2 = TRUNC( FLOOR( x2 ) );\r
-\r
-    if ( e2 >= 0 && e1 < ras.bWidth )\r
-    {\r
-      if ( e1 < 0 )\r
-        e1 = 0;\r
-      if ( e2 >= ras.bWidth )\r
-        e2 = ras.bWidth - 1;\r
-\r
-      c1 = (Short)( e1 >> 3 );\r
-      c2 = (Short)( e2 >> 3 );\r
-\r
-      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );\r
-      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );\r
-\r
-      if ( ras.gray_min_x > c1 ) ras.gray_min_x = (short)c1;\r
-      if ( ras.gray_max_x < c2 ) ras.gray_max_x = (short)c2;\r
-\r
-      target = ras.bTarget + ras.traceOfs + c1;\r
-      c2 -= c1;\r
-\r
-      if ( c2 > 0 )\r
-      {\r
-        target[0] |= f1;\r
-\r
-        /* memset() is slower than the following code on many platforms. */\r
-        /* This is due to the fact that, in the vast majority of cases,  */\r
-        /* the span length in bytes is relatively small.                 */\r
-        c2--;\r
-        while ( c2 > 0 )\r
-        {\r
-          *(++target) = 0xFF;\r
-          c2--;\r
-        }\r
-        target[1] |= f2;\r
-      }\r
-      else\r
-        *target |= ( f1 & f2 );\r
-    }\r
-  }\r
-\r
-\r
-  static void\r
-  Vertical_Sweep_Drop( RAS_ARGS Short       y,\r
-                                FT_F26Dot6  x1,\r
-                                FT_F26Dot6  x2,\r
-                                PProfile    left,\r
-                                PProfile    right )\r
-  {\r
-    Long   e1, e2;\r
-    Short  c1, f1;\r
-\r
-\r
-    /* Drop-out control */\r
-\r
-    e1 = CEILING( x1 );\r
-    e2 = FLOOR  ( x2 );\r
-\r
-    if ( e1 > e2 )\r
-    {\r
-      if ( e1 == e2 + ras.precision )\r
-      {\r
-        switch ( ras.dropOutControl )\r
-        {\r
-        case 1:\r
-          e1 = e2;\r
-          break;\r
-\r
-        case 4:\r
-          e1 = CEILING( (x1 + x2 + 1) / 2 );\r
-          break;\r
-\r
-        case 2:\r
-        case 5:\r
-          /* Drop-out Control Rule #4 */\r
-\r
-          /* The spec is not very clear regarding rule #4.  It      */\r
-          /* presents a method that is way too costly to implement  */\r
-          /* while the general idea seems to get rid of `stubs'.    */\r
-          /*                                                        */\r
-          /* Here, we only get rid of stubs recognized if:          */\r
-          /*                                                        */\r
-          /*  upper stub:                                           */\r
-          /*                                                        */\r
-          /*   - P_Left and P_Right are in the same contour         */\r
-          /*   - P_Right is the successor of P_Left in that contour */\r
-          /*   - y is the top of P_Left and P_Right                 */\r
-          /*                                                        */\r
-          /*  lower stub:                                           */\r
-          /*                                                        */\r
-          /*   - P_Left and P_Right are in the same contour         */\r
-          /*   - P_Left is the successor of P_Right in that contour */\r
-          /*   - y is the bottom of P_Left                          */\r
-          /*                                                        */\r
-\r
-          /* FIXXXME: uncommenting this line solves the disappearing */\r
-          /*          bit problem in the `7' of verdana 10pts, but   */\r
-          /*          makes a new one in the `C' of arial 14pts      */\r
-\r
-#if 0\r
-          if ( x2 - x1 < ras.precision_half )\r
-#endif\r
-          {\r
-            /* upper stub test */\r
-            if ( left->next == right && left->height <= 0 )\r
-              return;\r
-\r
-            /* lower stub test */\r
-            if ( right->next == left && left->start == y )\r
-              return;\r
-          }\r
-\r
-          /* check that the rightmost pixel isn't set */\r
-\r
-          e1 = TRUNC( e1 );\r
-\r
-          c1 = (Short)( e1 >> 3 );\r
-          f1 = (Short)( e1 &  7 );\r
-\r
-          if ( e1 >= 0 && e1 < ras.bWidth                      &&\r
-               ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )\r
-            return;\r
-\r
-          if ( ras.dropOutControl == 2 )\r
-            e1 = e2;\r
-          else\r
-            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );\r
-\r
-          break;\r
-\r
-        default:\r
-          return;  /* unsupported mode */\r
-        }\r
-      }\r
-      else\r
-        return;\r
-    }\r
-\r
-    e1 = TRUNC( e1 );\r
-\r
-    if ( e1 >= 0 && e1 < ras.bWidth )\r
-    {\r
-      c1 = (Short)( e1 >> 3 );\r
-      f1 = (Short)( e1 & 7 );\r
-\r
-      if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;\r
-      if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;\r
-\r
-      ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );\r
-    }\r
-  }\r
-\r
-\r
-  static void\r
-  Vertical_Sweep_Step( RAS_ARG )\r
-  {\r
-    ras.traceOfs += ras.traceIncr;\r
-  }\r
-\r
-\r
-  /***********************************************************************/\r
-  /*                                                                     */\r
-  /*  Horizontal Sweep Procedure Set                                     */\r
-  /*                                                                     */\r
-  /*  These four routines are used during the horizontal black/white     */\r
-  /*  sweep phase by the generic Draw_Sweep() function.                  */\r
-  /*                                                                     */\r
-  /***********************************************************************/\r
-\r
-  static void\r
-  Horizontal_Sweep_Init( RAS_ARGS Short*  min,\r
-                                  Short*  max )\r
-  {\r
-    /* nothing, really */\r
-    FT_UNUSED_RASTER;\r
-    FT_UNUSED( min );\r
-    FT_UNUSED( max );\r
-  }\r
-\r
-\r
-  static void\r
-  Horizontal_Sweep_Span( RAS_ARGS Short       y,\r
-                                  FT_F26Dot6  x1,\r
-                                  FT_F26Dot6  x2,\r
-                                  PProfile    left,\r
-                                  PProfile    right )\r
-  {\r
-    Long   e1, e2;\r
-    PByte  bits;\r
-    Byte   f1;\r
-\r
-    FT_UNUSED( left );\r
-    FT_UNUSED( right );\r
-\r
-\r
-    if ( x2 - x1 < ras.precision )\r
-    {\r
-      e1 = CEILING( x1 );\r
-      e2 = FLOOR  ( x2 );\r
-\r
-      if ( e1 == e2 )\r
-      {\r
-        bits = ras.bTarget + ( y >> 3 );\r
-        f1   = (Byte)( 0x80 >> ( y & 7 ) );\r
-\r
-        e1 = TRUNC( e1 );\r
-\r
-        if ( e1 >= 0 && e1 < ras.target.rows )\r
-        {\r
-          PByte  p;\r
-\r
-\r
-          p = bits - e1*ras.target.pitch;\r
-          if ( ras.target.pitch > 0 )\r
-            p += ( ras.target.rows - 1 ) * ras.target.pitch;\r
-\r
-          p[0] |= f1;\r
-        }\r
-      }\r
-    }\r
-  }\r
-\r
-\r
-  static void\r
-  Horizontal_Sweep_Drop( RAS_ARGS Short       y,\r
-                                  FT_F26Dot6  x1,\r
-                                  FT_F26Dot6  x2,\r
-                                  PProfile    left,\r
-                                  PProfile    right )\r
-  {\r
-    Long   e1, e2;\r
-    PByte  bits;\r
-    Byte   f1;\r
-\r
-\r
-    /* During the horizontal sweep, we only take care of drop-outs */\r
-\r
-    e1 = CEILING( x1 );\r
-    e2 = FLOOR  ( x2 );\r
-\r
-    if ( e1 > e2 )\r
-    {\r
-      if ( e1 == e2 + ras.precision )\r
-      {\r
-        switch ( ras.dropOutControl )\r
-        {\r
-        case 1:\r
-          e1 = e2;\r
-          break;\r
-\r
-        case 4:\r
-          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );\r
-          break;\r
-\r
-        case 2:\r
-        case 5:\r
-\r
-          /* Drop-out Control Rule #4 */\r
-\r
-          /* The spec is not very clear regarding rule #4.  It      */\r
-          /* presents a method that is way too costly to implement  */\r
-          /* while the general idea seems to get rid of `stubs'.    */\r
-          /*                                                        */\r
-\r
-          /* rightmost stub test */\r
-          if ( left->next == right && left->height <= 0 )\r
-            return;\r
-\r
-          /* leftmost stub test */\r
-          if ( right->next == left && left->start == y )\r
-            return;\r
-\r
-          /* check that the rightmost pixel isn't set */\r
-\r
-          e1 = TRUNC( e1 );\r
-\r
-          bits = ras.bTarget + ( y >> 3 );\r
-          f1   = (Byte)( 0x80 >> ( y & 7 ) );\r
-\r
-          bits -= e1 * ras.target.pitch;\r
-          if ( ras.target.pitch > 0 )\r
-            bits += ( ras.target.rows - 1 ) * ras.target.pitch;\r
-\r
-          if ( e1 >= 0              &&\r
-               e1 < ras.target.rows &&\r
-               *bits & f1 )\r
-            return;\r
-\r
-          if ( ras.dropOutControl == 2 )\r
-            e1 = e2;\r
-          else\r
-            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );\r
-\r
-          break;\r
-\r
-        default:\r
-          return;  /* unsupported mode */\r
-        }\r
-      }\r
-      else\r
-        return;\r
-    }\r
-\r
-    bits = ras.bTarget + ( y >> 3 );\r
-    f1   = (Byte)( 0x80 >> ( y & 7 ) );\r
-\r
-    e1 = TRUNC( e1 );\r
-\r
-    if ( e1 >= 0 && e1 < ras.target.rows )\r
-    {\r
-      bits -= e1 * ras.target.pitch;\r
-      if ( ras.target.pitch > 0 )\r
-        bits += ( ras.target.rows - 1 ) * ras.target.pitch;\r
-\r
-      bits[0] |= f1;\r
-    }\r
-  }\r
-\r
-\r
-  static void\r
-  Horizontal_Sweep_Step( RAS_ARG )\r
-  {\r
-    /* Nothing, really */\r
-    FT_UNUSED_RASTER;\r
-  }\r
-\r
-\r
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /*  Vertical Gray Sweep Procedure Set                                    */\r
-  /*                                                                       */\r
-  /*  These two routines are used during the vertical gray-levels sweep    */\r
-  /*  phase by the generic Draw_Sweep() function.                          */\r
-  /*                                                                       */\r
-  /*  NOTES                                                                */\r
-  /*                                                                       */\r
-  /*  - The target pixmap's width *must* be a multiple of 4.               */\r
-  /*                                                                       */\r
-  /*  - You have to use the function Vertical_Sweep_Span() for the gray    */\r
-  /*    span call.                                                         */\r
-  /*                                                                       */\r
-  /*************************************************************************/\r
-\r
-  static void\r
-  Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,\r
-                                     Short*  max )\r
-  {\r
-    Long  pitch, byte_len;\r
-\r
-\r
-    *min = *min & -2;\r
-    *max = ( *max + 3 ) & -2;\r
-\r
-    ras.traceOfs  = 0;\r
-    pitch         = ras.target.pitch;\r
-    byte_len      = -pitch;\r
-    ras.traceIncr = (Short)byte_len;\r
-    ras.traceG    = ( *min / 2 ) * byte_len;\r
-\r
-    if ( pitch > 0 )\r
-    {\r
-      ras.traceG += ( ras.target.rows - 1 ) * pitch;\r
-      byte_len    = -byte_len;\r
-    }\r
-\r
-    ras.gray_min_x =  (Short)byte_len;\r
-    ras.gray_max_x = -(Short)byte_len;\r
-  }\r
-\r
-\r
-  static void\r
-  Vertical_Gray_Sweep_Step( RAS_ARG )\r
-  {\r
-    Int    c1, c2;\r
-    PByte  pix, bit, bit2;\r
-    char*  count = (char*)count_table;\r
-    Byte*  grays;\r
-\r
-\r
-    ras.traceOfs += ras.gray_width;\r
-\r
-    if ( ras.traceOfs > ras.gray_width )\r
-    {\r
-      pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;\r
-      grays = ras.grays;\r
-\r
-      if ( ras.gray_max_x >= 0 )\r
-      {\r
-        Long   last_pixel = ras.target.width - 1;\r
-        Int    last_cell  = last_pixel >> 2;\r
-        Int    last_bit   = last_pixel & 3;\r
-        Bool   over       = 0;\r
-\r
-\r
-        if ( ras.gray_max_x >= last_cell && last_bit != 3 )\r
-        {\r
-          ras.gray_max_x = last_cell - 1;\r
-          over = 1;\r
-        }\r
-\r
-        if ( ras.gray_min_x < 0 )\r
-          ras.gray_min_x = 0;\r
-\r
-        bit   = ras.bTarget + ras.gray_min_x;\r
-        bit2  = bit + ras.gray_width;\r
-\r
-        c1 = ras.gray_max_x - ras.gray_min_x;\r
-\r
-        while ( c1 >= 0 )\r
-        {\r
-          c2 = count[*bit] + count[*bit2];\r
-\r
-          if ( c2 )\r
-          {\r
-            pix[0] = grays[(c2 >> 12) & 0x000F];\r
-            pix[1] = grays[(c2 >> 8 ) & 0x000F];\r
-            pix[2] = grays[(c2 >> 4 ) & 0x000F];\r
-            pix[3] = grays[ c2        & 0x000F];\r
-\r
-            *bit  = 0;\r
-            *bit2 = 0;\r
-          }\r
-\r
-          bit++;\r
-          bit2++;\r
-          pix += 4;\r
-          c1--;\r
-        }\r
-\r
-        if ( over )\r
-        {\r
-          c2 = count[*bit] + count[*bit2];\r
-          if ( c2 )\r
-          {\r
-            switch ( last_bit )\r
-            {\r
-            case 2:\r
-              pix[2] = grays[(c2 >> 4 ) & 0x000F];\r
-            case 1:\r
-              pix[1] = grays[(c2 >> 8 ) & 0x000F];\r
-            default:\r
-              pix[0] = grays[(c2 >> 12) & 0x000F];\r
-            }\r
-\r
-            *bit  = 0;\r
-            *bit2 = 0;\r
-          }\r
-        }\r
-      }\r
-\r
-      ras.traceOfs = 0;\r
-      ras.traceG  += ras.traceIncr;\r
-\r
-      ras.gray_min_x =  32000;\r
-      ras.gray_max_x = -32000;\r
-    }\r
-  }\r
-\r
-\r
-  static void\r
-  Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,\r
-                                       FT_F26Dot6  x1,\r
-                                       FT_F26Dot6  x2,\r
-                                       PProfile    left,\r
-                                       PProfile    right )\r
-  {\r
-    /* nothing, really */\r
-    FT_UNUSED_RASTER;\r
-    FT_UNUSED( y );\r
-    FT_UNUSED( x1 );\r
-    FT_UNUSED( x2 );\r
-    FT_UNUSED( left );\r
-    FT_UNUSED( right );\r
-  }\r
-\r
-\r
-  static void\r
-  Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,\r
-                                       FT_F26Dot6  x1,\r
-                                       FT_F26Dot6  x2,\r
-                                       PProfile    left,\r
-                                       PProfile    right )\r
-  {\r
-    Long   e1, e2;\r
-    PByte  pixel;\r
-    Byte   color;\r
-\r
-\r
-    /* During the horizontal sweep, we only take care of drop-outs */\r
-    e1 = CEILING( x1 );\r
-    e2 = FLOOR  ( x2 );\r
-\r
-    if ( e1 > e2 )\r
-    {\r
-      if ( e1 == e2 + ras.precision )\r
-      {\r
-        switch ( ras.dropOutControl )\r
-        {\r
-        case 1:\r
-          e1 = e2;\r
-          break;\r
-\r
-        case 4:\r
-          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );\r
-          break;\r
-\r
-        case 2:\r
-        case 5:\r
-\r
-          /* Drop-out Control Rule #4 */\r
-\r
-          /* The spec is not very clear regarding rule #4.  It      */\r
-          /* presents a method that is way too costly to implement  */\r
-          /* while the general idea seems to get rid of `stubs'.    */\r
-          /*                                                        */\r
-\r
-          /* rightmost stub test */\r
-          if ( left->next == right && left->height <= 0 )\r
-            return;\r
-\r
-          /* leftmost stub test */\r
-          if ( right->next == left && left->start == y )\r
-            return;\r
-\r
-          if ( ras.dropOutControl == 2 )\r
-            e1 = e2;\r
-          else\r
-            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );\r
-\r
-          break;\r
-\r
-        default:\r
-          return;  /* unsupported mode */\r
-        }\r
-      }\r
-      else\r
-        return;\r
-    }\r
-\r
-    if ( e1 >= 0 )\r
-    {\r
-      if ( x2 - x1 >= ras.precision_half )\r
-        color = ras.grays[2];\r
-      else\r
-        color = ras.grays[1];\r
-\r
-      e1 = TRUNC( e1 ) / 2;\r
-      if ( e1 < ras.target.rows )\r
-      {\r
-        pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;\r
-        if ( ras.target.pitch > 0 )\r
-          pixel += ( ras.target.rows - 1 ) * ras.target.pitch;\r
-\r
-        if ( pixel[0] == ras.grays[0] )\r
-          pixel[0] = color;\r
-      }\r
-    }\r
-  }\r
-\r
-\r
-#endif /* FT_RASTER_OPTION_ANTI_ALIASING */\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /*  Generic Sweep Drawing routine                                        */\r
-  /*                                                                       */\r
-  /*************************************************************************/\r
-\r
-  static Bool\r
-  Draw_Sweep( RAS_ARG )\r
-  {\r
-    Short         y, y_change, y_height;\r
-\r
-    PProfile      P, Q, P_Left, P_Right;\r
-\r
-    Short         min_Y, max_Y, top, bottom, dropouts;\r
-\r
-    Long          x1, x2, xs, e1, e2;\r
-\r
-    TProfileList  waiting;\r
-    TProfileList  draw_left, draw_right;\r
-\r
-\r
-    /* Init empty linked lists */\r
-\r
-    Init_Linked( &waiting );\r
-\r
-    Init_Linked( &draw_left  );\r
-    Init_Linked( &draw_right );\r
-\r
-    /* first, compute min and max Y */\r
-\r
-    P     = ras.fProfile;\r
-    max_Y = (Short)TRUNC( ras.minY );\r
-    min_Y = (Short)TRUNC( ras.maxY );\r
-\r
-    while ( P )\r
-    {\r
-      Q = P->link;\r
-\r
-      bottom = (Short)P->start;\r
-      top    = (Short)( P->start + P->height - 1 );\r
-\r
-      if ( min_Y > bottom ) min_Y = bottom;\r
-      if ( max_Y < top    ) max_Y = top;\r
-\r
-      P->X = 0;\r
-      InsNew( &waiting, P );\r
-\r
-      P = Q;\r
-    }\r
-\r
-    /* Check the Y-turns */\r
-    if ( ras.numTurns == 0 )\r
-    {\r
-      ras.error = Raster_Err_Invalid;\r
-      return FAILURE;\r
-    }\r
-\r
-    /* Now inits the sweep */\r
-\r
-    ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );\r
-\r
-    /* Then compute the distance of each profile from min_Y */\r
-\r
-    P = waiting;\r
-\r
-    while ( P )\r
-    {\r
-      P->countL = (UShort)( P->start - min_Y );\r
-      P = P->link;\r
-    }\r
-\r
-    /* Let's go */\r
-\r
-    y        = min_Y;\r
-    y_height = 0;\r
-\r
-    if ( ras.numTurns > 0 &&\r
-         ras.sizeBuff[-ras.numTurns] == min_Y )\r
-      ras.numTurns--;\r
-\r
-    while ( ras.numTurns > 0 )\r
-    {\r
-      /* look in the waiting list for new activations */\r
-\r
-      P = waiting;\r
-\r
-      while ( P )\r
-      {\r
-        Q = P->link;\r
-        P->countL -= y_height;\r
-        if ( P->countL == 0 )\r
-        {\r
-          DelOld( &waiting, P );\r
-\r
-          switch ( P->flow )\r
-          {\r
-          case Flow_Up:\r
-            InsNew( &draw_left,  P );\r
-            break;\r
-\r
-          case Flow_Down:\r
-            InsNew( &draw_right, P );\r
-            break;\r
-          }\r
-        }\r
-\r
-        P = Q;\r
-      }\r
-\r
-      /* Sort the drawing lists */\r
-\r
-      Sort( &draw_left );\r
-      Sort( &draw_right );\r
-\r
-      y_change = (Short)ras.sizeBuff[-ras.numTurns--];\r
-      y_height = (Short)( y_change - y );\r
-\r
-      while ( y < y_change )\r
-      {\r
-        /* Let's trace */\r
-\r
-        dropouts = 0;\r
-\r
-        P_Left  = draw_left;\r
-        P_Right = draw_right;\r
-\r
-        while ( P_Left )\r
-        {\r
-          x1 = P_Left ->X;\r
-          x2 = P_Right->X;\r
-\r
-          if ( x1 > x2 )\r
-          {\r
-            xs = x1;\r
-            x1 = x2;\r
-            x2 = xs;\r
-          }\r
-\r
-          if ( x2 - x1 <= ras.precision )\r
-          {\r
-            e1 = FLOOR( x1 );\r
-            e2 = CEILING( x2 );\r
-\r
-            if ( ras.dropOutControl != 0                 &&\r
-                 ( e1 > e2 || e2 == e1 + ras.precision ) )\r
-            {\r
-              /* a drop out was detected */\r
-\r
-              P_Left ->X = x1;\r
-              P_Right->X = x2;\r
-\r
-              /* mark profile for drop-out processing */\r
-              P_Left->countL = 1;\r
-              dropouts++;\r
-\r
-              goto Skip_To_Next;\r
-            }\r
-          }\r
-\r
-          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );\r
-\r
-        Skip_To_Next:\r
-\r
-          P_Left  = P_Left->link;\r
-          P_Right = P_Right->link;\r
-        }\r
-\r
-        /* now perform the dropouts _after_ the span drawing -- */\r
-        /* drop-outs processing has been moved out of the loop  */\r
-        /* for performance tuning                               */\r
-        if ( dropouts > 0 )\r
-          goto Scan_DropOuts;\r
-\r
-      Next_Line:\r
-\r
-        ras.Proc_Sweep_Step( RAS_VAR );\r
-\r
-        y++;\r
-\r
-        if ( y < y_change )\r
-        {\r
-          Sort( &draw_left  );\r
-          Sort( &draw_right );\r
-        }\r
-      }\r
-\r
-      /* Now finalize the profiles that needs it */\r
-\r
-      P = draw_left;\r
-      while ( P )\r
-      {\r
-        Q = P->link;\r
-        if ( P->height == 0 )\r
-          DelOld( &draw_left, P );\r
-        P = Q;\r
-      }\r
-\r
-      P = draw_right;\r
-      while ( P )\r
-      {\r
-        Q = P->link;\r
-        if ( P->height == 0 )\r
-          DelOld( &draw_right, P );\r
-        P = Q;\r
-      }\r
-    }\r
-\r
-    /* for gray-scaling, flushes the bitmap scanline cache */\r
-    while ( y <= max_Y )\r
-    {\r
-      ras.Proc_Sweep_Step( RAS_VAR );\r
-      y++;\r
-    }\r
-\r
-    return SUCCESS;\r
-\r
-  Scan_DropOuts:\r
-\r
-    P_Left  = draw_left;\r
-    P_Right = draw_right;\r
-\r
-    while ( P_Left )\r
-    {\r
-      if ( P_Left->countL )\r
-      {\r
-        P_Left->countL = 0;\r
-#if 0\r
-        dropouts--;  /* -- this is useful when debugging only */\r
-#endif\r
-        ras.Proc_Sweep_Drop( RAS_VARS y,\r
-                                      P_Left->X,\r
-                                      P_Right->X,\r
-                                      P_Left,\r
-                                      P_Right );\r
-      }\r
-\r
-      P_Left  = P_Left->link;\r
-      P_Right = P_Right->link;\r
-    }\r
-\r
-    goto Next_Line;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Render_Single_Pass                                                 */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Performs one sweep with sub-banding.                               */\r
-  /*                                                                       */\r
-  /* <Input>                                                               */\r
-  /*    flipped :: If set, flip the direction of the outline.              */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    Renderer error code.                                               */\r
-  /*                                                                       */\r
-  static int\r
-  Render_Single_Pass( RAS_ARGS Bool  flipped )\r
-  {\r
-    Short  i, j, k;\r
-\r
-\r
-    while ( ras.band_top >= 0 )\r
-    {\r
-      ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;\r
-      ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;\r
-\r
-      ras.top = ras.buff;\r
-\r
-      ras.error = Raster_Err_None;\r
-\r
-      if ( Convert_Glyph( RAS_VARS flipped ) )\r
-      {\r
-        if ( ras.error != Raster_Err_Overflow )\r
-          return FAILURE;\r
-\r
-        ras.error = Raster_Err_None;\r
-\r
-        /* sub-banding */\r
-\r
-#ifdef DEBUG_RASTER\r
-        ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );\r
-#endif\r
-\r
-        i = ras.band_stack[ras.band_top].y_min;\r
-        j = ras.band_stack[ras.band_top].y_max;\r
-\r
-        k = (Short)( ( i + j ) / 2 );\r
-\r
-        if ( ras.band_top >= 7 || k < i )\r
-        {\r
-          ras.band_top = 0;\r
-          ras.error    = Raster_Err_Invalid;\r
-\r
-          return ras.error;\r
-        }\r
-\r
-        ras.band_stack[ras.band_top + 1].y_min = k;\r
-        ras.band_stack[ras.band_top + 1].y_max = j;\r
-\r
-        ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );\r
-\r
-        ras.band_top++;\r
-      }\r
-      else\r
-      {\r
-        if ( ras.fProfile )\r
-          if ( Draw_Sweep( RAS_VAR ) )\r
-             return ras.error;\r
-        ras.band_top--;\r
-      }\r
-    }\r
-\r
-    return SUCCESS;\r
-  }\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Render_Glyph                                                       */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Renders a glyph in a bitmap.  Sub-banding if needed.               */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    FreeType error code.  0 means success.                             */\r
-  /*                                                                       */\r
-  FT_LOCAL_DEF( FT_Error )\r
-  Render_Glyph( RAS_ARG )\r
-  {\r
-    FT_Error  error;\r
-\r
-\r
-    Set_High_Precision( RAS_VARS ras.outline.flags &\r
-                        FT_OUTLINE_HIGH_PRECISION );\r
-    ras.scale_shift    = ras.precision_shift;\r
-    /* Drop-out mode 2 is hard-coded since this is the only mode used */\r
-    /* on Windows platforms.  Using other modes, as specified by the  */\r
-    /* font, results in misplaced pixels.                             */\r
-    ras.dropOutControl = 2;\r
-    ras.second_pass    = (FT_Byte)( !( ras.outline.flags &\r
-                                       FT_OUTLINE_SINGLE_PASS ) );\r
-\r
-    /* Vertical Sweep */\r
-    ras.Proc_Sweep_Init = Vertical_Sweep_Init;\r
-    ras.Proc_Sweep_Span = Vertical_Sweep_Span;\r
-    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;\r
-    ras.Proc_Sweep_Step = Vertical_Sweep_Step;\r
-\r
-    ras.band_top            = 0;\r
-    ras.band_stack[0].y_min = 0;\r
-    ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );\r
-\r
-    ras.bWidth  = (unsigned short)ras.target.width;\r
-    ras.bTarget = (Byte*)ras.target.buffer;\r
-\r
-    if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )\r
-      return error;\r
-\r
-    /* Horizontal Sweep */\r
-    if ( ras.second_pass && ras.dropOutControl != 0 )\r
-    {\r
-      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;\r
-      ras.Proc_Sweep_Span = Horizontal_Sweep_Span;\r
-      ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;\r
-      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;\r
-\r
-      ras.band_top            = 0;\r
-      ras.band_stack[0].y_min = 0;\r
-      ras.band_stack[0].y_max = (short)( ras.target.width - 1 );\r
-\r
-      if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )\r
-        return error;\r
-    }\r
-\r
-    return Raster_Err_None;\r
-  }\r
-\r
-\r
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING\r
-\r
-\r
-  /*************************************************************************/\r
-  /*                                                                       */\r
-  /* <Function>                                                            */\r
-  /*    Render_Gray_Glyph                                                  */\r
-  /*                                                                       */\r
-  /* <Description>                                                         */\r
-  /*    Renders a glyph with grayscaling.  Sub-banding if needed.          */\r
-  /*                                                                       */\r
-  /* <Return>                                                              */\r
-  /*    FreeType error code.  0 means success.                             */\r
-  /*                                                                       */\r
-  FT_LOCAL_DEF( FT_Error )\r
-  Render_Gray_Glyph( RAS_ARG )\r
-  {\r
-    Long      pixel_width;\r
-    FT_Error  error;\r
-\r
-\r
-    Set_High_Precision( RAS_VARS ras.outline.flags &\r
-                        FT_OUTLINE_HIGH_PRECISION );\r
-    ras.scale_shift    = ras.precision_shift + 1;\r
-    /* Drop-out mode 2 is hard-coded since this is the only mode used */\r
-    /* on Windows platforms.  Using other modes, as specified by the  */\r
-    /* font, results in misplaced pixels.                             */\r
-    ras.dropOutControl = 2;\r
-    ras.second_pass    = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );\r
-\r
-    /* Vertical Sweep */\r
-\r
-    ras.band_top            = 0;\r
-    ras.band_stack[0].y_min = 0;\r
-    ras.band_stack[0].y_max = 2 * ras.target.rows - 1;\r
-\r
-    ras.bWidth  = ras.gray_width;\r
-    pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );\r
-\r
-    if ( ras.bWidth > pixel_width )\r
-      ras.bWidth = pixel_width;\r
-\r
-    ras.bWidth  = ras.bWidth * 8;\r
-    ras.bTarget = (Byte*)ras.gray_lines;\r
-    ras.gTarget = (Byte*)ras.target.buffer;\r
-\r
-    ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;\r
-    ras.Proc_Sweep_Span = Vertical_Sweep_Span;\r
-    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;\r
-    ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;\r
-\r
-    error = Render_Single_Pass( RAS_VARS 0 );\r
-    if ( error )\r
-      return error;\r
-\r
-    /* Horizontal Sweep */\r
-    if ( ras.second_pass && ras.dropOutControl != 0 )\r
-    {\r
-      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;\r
-      ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;\r
-      ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;\r
-      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;\r
-\r
-      ras.band_top            = 0;\r
-      ras.band_stack[0].y_min = 0;\r
-      ras.band_stack[0].y_max = ras.target.width * 2 - 1;\r
-\r
-      error = Render_Single_Pass( RAS_VARS 1 );\r
-      if ( error )\r
-        return error;\r
-    }\r
-\r
-    return Raster_Err_None;\r
-  }\r
-\r
-#else /* !FT_RASTER_OPTION_ANTI_ALIASING */\r
-\r
-  FT_LOCAL_DEF( FT_Error )\r
-  Render_Gray_Glyph( RAS_ARG )\r
-  {\r
-    FT_UNUSED_RASTER;\r
-\r
-    return Raster_Err_Unsupported;\r
-  }\r
-\r
-#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */\r
-\r
-\r
-  static void\r
-  ft_black_init( PRaster  raster )\r
-  {\r
-    FT_UNUSED( raster );\r
-\r
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING\r
-    FT_UInt  n;\r
-\r
-\r
-    /* set default 5-levels gray palette */\r
-    for ( n = 0; n < 5; n++ )\r
-      raster->grays[n] = n * 255 / 4;\r
-\r
-    raster->gray_width = RASTER_GRAY_LINES / 2;\r
-\r
-#endif\r
-  }\r
-\r
-\r
-  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/\r
-  /****                         a static object.                  *****/\r
-\r
-\r
-#ifdef _STANDALONE_\r
-\r
-\r
-  static int\r
-  ft_black_new( void*      memory,\r
-                FT_Raster  *araster )\r
-  {\r
-     static TRaster  the_raster;\r
-\r
-\r
-     *araster = (FT_Raster)&the_raster;\r
-     FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );\r
-     ft_black_init( &the_raster );\r
-\r
-     return 0;\r
-  }\r
-\r
-\r
-  static void\r
-  ft_black_done( FT_Raster  raster )\r
-  {\r
-    /* nothing */\r
-    FT_UNUSED( raster );\r
-  }\r
-\r
-\r
-#else /* _STANDALONE_ */\r
-\r
-\r
-  static int\r
-  ft_black_new( FT_Memory   memory,\r
-                PRaster    *araster )\r
-  {\r
-    FT_Error  error;\r
-    PRaster   raster;\r
-\r
-\r
-    *araster = 0;\r
-    if ( !FT_NEW( raster ) )\r
-    {\r
-      raster->memory = memory;\r
-      ft_black_init( raster );\r
-\r
-      *araster = raster;\r
-    }\r
-\r
-    return error;\r
-  }\r
-\r
-\r
-  static void\r
-  ft_black_done( PRaster  raster )\r
-  {\r
-    FT_Memory  memory = (FT_Memory)raster->memory;\r
-    FT_FREE( raster );\r
-  }\r
-\r
-\r
-#endif /* _STANDALONE_ */\r
-\r
-\r
-  static void\r
-  ft_black_reset( PRaster   raster,\r
-                  char*     pool_base,\r
-                  long      pool_size )\r
-  {\r
-    if ( raster )\r
-    {\r
-      if ( pool_base && pool_size >= (long)sizeof(TWorker) + 2048 )\r
-      {\r
-        PWorker  worker = (PWorker)pool_base;\r
-\r
-\r
-        raster->buffer      = pool_base + ( (sizeof ( *worker ) + 7 ) & ~7 );\r
-        raster->buffer_size = ( ( pool_base + pool_size ) -\r
-                                (char*)raster->buffer ) / sizeof ( Long );\r
-        raster->worker      = worker;\r
-      }\r
-      else\r
-      {\r
-        raster->buffer      = NULL;\r
-        raster->buffer_size = 0;\r
-        raster->worker      = NULL;\r
-      }\r
-    }\r
-  }\r
-\r
-\r
-  static void\r
-  ft_black_set_mode( PRaster            raster,\r
-                     unsigned long      mode,\r
-                     const char*        palette )\r
-  {\r
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING\r
-\r
-    if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )\r
-    {\r
-      /* set 5-levels gray palette */\r
-      raster->grays[0] = palette[0];\r
-      raster->grays[1] = palette[1];\r
-      raster->grays[2] = palette[2];\r
-      raster->grays[3] = palette[3];\r
-      raster->grays[4] = palette[4];\r
-    }\r
-\r
-#else\r
-\r
-    FT_UNUSED( raster );\r
-    FT_UNUSED( mode );\r
-    FT_UNUSED( palette );\r
-\r
-#endif\r
-  }\r
-\r
-\r
-  static int\r
-  ft_black_render( PRaster                  raster,\r
-                   const FT_Raster_Params*  params )\r
-  {\r
-    const FT_Outline*  outline    = (const FT_Outline*)params->source;\r
-    const FT_Bitmap*   target_map = params->target;\r
-    PWorker            worker;\r
-\r
-\r
-    if ( !raster || !raster->buffer || !raster->buffer_size )\r
-      return Raster_Err_Not_Ini;\r
-\r
-    /* return immediately if the outline is empty */\r
-    if ( outline->n_points == 0 || outline->n_contours <= 0 )\r
-      return Raster_Err_None;\r
-\r
-    if ( !outline || !outline->contours || !outline->points )\r
-      return Raster_Err_Invalid;\r
-\r
-    if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )\r
-      return Raster_Err_Invalid;\r
-\r
-    worker = raster->worker;\r
-\r
-    /* this version of the raster does not support direct rendering, sorry */\r
-    if ( params->flags & FT_RASTER_FLAG_DIRECT )\r
-      return Raster_Err_Unsupported;\r
-\r
-    if ( !target_map || !target_map->buffer )\r
-      return Raster_Err_Invalid;\r
-\r
-    ras.outline  = *outline;\r
-    ras.target   = *target_map;\r
-\r
-    worker->buff        = (PLong) raster->buffer;\r
-    worker->sizeBuff    = worker->buff +\r
-                            raster->buffer_size / sizeof ( Long );\r
-#ifdef FT_RASTER_OPTION_ANTI_ALIASING\r
-    worker->grays       = raster->grays;\r
-    worker->gray_width  = raster->gray_width;\r
-#endif\r
-\r
-    return ( ( params->flags & FT_RASTER_FLAG_AA )\r
-               ? Render_Gray_Glyph( RAS_VAR )\r
-               : Render_Glyph( RAS_VAR ) );\r
-  }\r
-\r
-\r
-  const FT_Raster_Funcs  ft_standard_raster =\r
-  {\r
-    FT_GLYPH_FORMAT_OUTLINE,\r
-    (FT_Raster_New_Func)     ft_black_new,\r
-    (FT_Raster_Reset_Func)   ft_black_reset,\r
-    (FT_Raster_Set_Mode_Func)ft_black_set_mode,\r
-    (FT_Raster_Render_Func)  ft_black_render,\r
-    (FT_Raster_Done_Func)    ft_black_done\r
-  };\r
-\r
-\r
-/* END */\r
+/***************************************************************************/
+/*                                                                         */
+/*  ftraster.c                                                             */
+/*                                                                         */
+/*    The FreeType glyph rasterizer (body).                                */
+/*                                                                         */
+/*  Copyright 1996-2001, 2002, 2003, 2005, 2007 by                         */
+/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
+/*                                                                         */
+/*  This file is part of the FreeType project, and may only be used,       */
+/*  modified, and distributed under the terms of the FreeType project      */
+/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
+/*  this file you indicate that you have read the license and              */
+/*  understand and accept it fully.                                        */
+/*                                                                         */
+/***************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This file can be compiled without the rest of the FreeType engine, by */
+  /* defining the _STANDALONE_ macro when compiling it.  You also need to  */
+  /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir)           */
+  /* directory.  Typically, you should do something like                   */
+  /*                                                                       */
+  /* - copy `src/raster/ftraster.c' (this file) to your current directory  */
+  /*                                                                       */
+  /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h'         */
+  /*   to your current directory                                           */
+  /*                                                                       */
+  /* - compile `ftraster' with the _STANDALONE_ macro defined, as in       */
+  /*                                                                       */
+  /*     cc -c -D_STANDALONE_ ftraster.c                                   */
+  /*                                                                       */
+  /* The renderer can be initialized with a call to                        */
+  /* `ft_standard_raster.raster_new'; a bitmap can be generated            */
+  /* with a call to `ft_standard_raster.raster_render'.                    */
+  /*                                                                       */
+  /* See the comments and documentation in the file `ftimage.h' for more   */
+  /* details on how the raster works.                                      */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* This is a rewrite of the FreeType 1.x scan-line converter             */
+  /*                                                                       */
+  /*************************************************************************/
+
+#ifdef _STANDALONE_
+
+#include "ftmisc.h"
+#include "ftimage.h"
+
+#else /* !_STANDALONE_ */
+
+#include <ft2build.h>
+#include "ftraster.h"
+#include FT_INTERNAL_CALC_H   /* for FT_MulDiv only */
+
+#endif /* !_STANDALONE_ */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* A simple technical note on how the raster works                       */
+  /* -----------------------------------------------                       */
+  /*                                                                       */
+  /*   Converting an outline into a bitmap is achieved in several steps:   */
+  /*                                                                       */
+  /*   1 - Decomposing the outline into successive `profiles'.  Each       */
+  /*       profile is simply an array of scanline intersections on a given */
+  /*       dimension.  A profile's main attributes are                     */
+  /*                                                                       */
+  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'.     */
+  /*                                                                       */
+  /*       o an array of intersection coordinates for each scanline        */
+  /*         between `Ymin' and `Ymax'.                                    */
+  /*                                                                       */
+  /*       o a direction, indicating whether it was built going `up' or    */
+  /*         `down', as this is very important for filling rules.          */
+  /*                                                                       */
+  /*   2 - Sweeping the target map's scanlines in order to compute segment */
+  /*       `spans' which are then filled.  Additionally, this pass         */
+  /*       performs drop-out control.                                      */
+  /*                                                                       */
+  /*   The outline data is parsed during step 1 only.  The profiles are    */
+  /*   built from the bottom of the render pool, used as a stack.  The     */
+  /*   following graphics shows the profile list under construction:       */
+  /*                                                                       */
+  /*     ____________________________________________________________ _ _  */
+  /*    |         |                   |         |                 |        */
+  /*    | profile | coordinates for   | profile | coordinates for |-->     */
+  /*    |    1    |  profile 1        |    2    |  profile 2      |-->     */
+  /*    |_________|___________________|_________|_________________|__ _ _  */
+  /*                                                                       */
+  /*    ^                                                         ^        */
+  /*    |                                                         |        */
+  /*  start of render pool                                       top       */
+  /*                                                                       */
+  /*   The top of the profile stack is kept in the `top' variable.         */
+  /*                                                                       */
+  /*   As you can see, a profile record is pushed on top of the render     */
+  /*   pool, which is then followed by its coordinates/intersections.  If  */
+  /*   a change of direction is detected in the outline, a new profile is  */
+  /*   generated until the end of the outline.                             */
+  /*                                                                       */
+  /*   Note that when all profiles have been generated, the function       */
+  /*   Finalize_Profile_Table() is used to record, for each profile, its   */
+  /*   bottom-most scanline as well as the scanline above its upmost       */
+  /*   boundary.  These positions are called `y-turns' because they (sort  */
+  /*   of) correspond to local extrema.  They are stored in a sorted list  */
+  /*   built from the top of the render pool as a downwards stack:         */
+  /*                                                                       */
+  /*      _ _ _______________________________________                      */
+  /*                            |                    |                     */
+  /*                         <--| sorted list of     |                     */
+  /*                         <--|  extrema scanlines |                     */
+  /*      _ _ __________________|____________________|                     */
+  /*                                                                       */
+  /*                            ^                    ^                     */
+  /*                            |                    |                     */
+  /*                         maxBuff           sizeBuff = end of pool      */
+  /*                                                                       */
+  /*   This list is later used during the sweep phase in order to          */
+  /*   optimize performance (see technical note on the sweep below).       */
+  /*                                                                       */
+  /*   Of course, the raster detects whether the two stacks collide and    */
+  /*   handles the situation properly.                                     */
+  /*                                                                       */
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  CONFIGURATION MACROS                                               **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /* define DEBUG_RASTER if you want to compile a debugging version */
+#define xxxDEBUG_RASTER
+
+  /* undefine FT_RASTER_OPTION_ANTI_ALIASING if you do not want to support */
+  /* 5-levels anti-aliasing                                                */
+#ifdef FT_CONFIG_OPTION_5_GRAY_LEVELS
+#define FT_RASTER_OPTION_ANTI_ALIASING
+#endif
+
+  /* The size of the two-lines intermediate bitmap used */
+  /* for anti-aliasing, in bytes.                       */
+#define RASTER_GRAY_LINES  2048
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  OTHER MACROS (do not change)                                       **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
+  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
+  /* messages during execution.                                            */
+  /*                                                                       */
+#undef  FT_COMPONENT
+#define FT_COMPONENT  trace_raster
+
+
+#ifdef _STANDALONE_
+
+
+  /* This macro is used to indicate that a function parameter is unused. */
+  /* Its purpose is simply to reduce compiler warnings.  Note also that  */
+  /* simply defining it as `(void)x' doesn't avoid warnings with certain */
+  /* ANSI compilers (e.g. LCC).                                          */
+#define FT_UNUSED( x )  (x) = (x)
+
+  /* Disable the tracing mechanism for simplicity -- developers can      */
+  /* activate it easily by redefining these two macros.                  */
+#ifndef FT_ERROR
+#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
+#endif
+
+#ifndef FT_TRACE
+#define FT_TRACE( x )   do ; while ( 0 )    /* nothing */
+#define FT_TRACE1( x )  do ; while ( 0 )    /* nothing */
+#define FT_TRACE6( x )  do ; while ( 0 )    /* nothing */
+#endif
+
+#define Raster_Err_None          0
+#define Raster_Err_Not_Ini      -1
+#define Raster_Err_Overflow     -2
+#define Raster_Err_Neg_Height   -3
+#define Raster_Err_Invalid      -4
+#define Raster_Err_Unsupported  -5
+
+#define ft_memset   memset
+
+#else /* _STANDALONE_ */
+
+
+#include FT_INTERNAL_OBJECTS_H
+#include FT_INTERNAL_DEBUG_H        /* for FT_TRACE() and FT_ERROR() */
+
+#include "rasterrs.h"
+
+#define Raster_Err_None         Raster_Err_Ok
+#define Raster_Err_Not_Ini      Raster_Err_Raster_Uninitialized
+#define Raster_Err_Overflow     Raster_Err_Raster_Overflow
+#define Raster_Err_Neg_Height   Raster_Err_Raster_Negative_Height
+#define Raster_Err_Invalid      Raster_Err_Invalid_Outline
+#define Raster_Err_Unsupported  Raster_Err_Cannot_Render_Glyph
+
+
+#endif /* _STANDALONE_ */
+
+
+#ifndef FT_MEM_SET
+#define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
+#endif
+
+#ifndef FT_MEM_ZERO
+#define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
+#endif
+
+  /* FMulDiv means `Fast MulDiv'; it is used in case where `b' is       */
+  /* typically a small value and the result of a*b is known to fit into */
+  /* 32 bits.                                                           */
+#define FMulDiv( a, b, c )  ( (a) * (b) / (c) )
+
+  /* On the other hand, SMulDiv means `Slow MulDiv', and is used typically */
+  /* for clipping computations.  It simply uses the FT_MulDiv() function   */
+  /* defined in `ftcalc.h'.                                                */
+#define SMulDiv  FT_MulDiv
+
+  /* The rasterizer is a very general purpose component; please leave */
+  /* the following redefinitions there (you never know your target    */
+  /* environment).                                                    */
+
+#ifndef TRUE
+#define TRUE   1
+#endif
+
+#ifndef FALSE
+#define FALSE  0
+#endif
+
+#ifndef NULL
+#define NULL  (void*)0
+#endif
+
+#ifndef SUCCESS
+#define SUCCESS  0
+#endif
+
+#ifndef FAILURE
+#define FAILURE  1
+#endif
+
+
+#define MaxBezier  32   /* The maximum number of stacked Bezier curves. */
+                        /* Setting this constant to more than 32 is a   */
+                        /* pure waste of space.                         */
+
+#define Pixel_Bits  6   /* fractional bits of *input* coordinates */
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  SIMPLE TYPE DECLARATIONS                                           **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+  typedef int             Int;
+  typedef unsigned int    UInt;
+  typedef short           Short;
+  typedef unsigned short  UShort, *PUShort;
+  typedef long            Long, *PLong;
+  typedef unsigned long   ULong;
+
+  typedef unsigned char   Byte, *PByte;
+  typedef char            Bool;
+
+
+  typedef union  Alignment_
+  {
+    long    l;
+    void*   p;
+    void  (*f)(void);
+
+  } Alignment, *PAlignment;
+
+
+  typedef struct  TPoint_
+  {
+    Long  x;
+    Long  y;
+
+  } TPoint;
+
+
+  typedef enum  TFlow_
+  {
+    Flow_None = 0,
+    Flow_Up   = 1,
+    Flow_Down = -1
+
+  } TFlow;
+
+
+  /* States of each line, arc, and profile */
+  typedef enum  TStates_
+  {
+    Unknown_State,
+    Ascending_State,
+    Descending_State,
+    Flat_State
+
+  } TStates;
+
+
+  typedef struct TProfile_  TProfile;
+  typedef TProfile*         PProfile;
+
+  struct  TProfile_
+  {
+    FT_F26Dot6  X;           /* current coordinate during sweep        */
+    PProfile    link;        /* link to next profile - various purpose */
+    PLong       offset;      /* start of profile's data in render pool */
+    int         flow;        /* Profile orientation: Asc/Descending    */
+    long        height;      /* profile's height in scanlines          */
+    long        start;       /* profile's starting scanline            */
+
+    unsigned    countL;      /* number of lines to step before this    */
+                             /* profile becomes drawable               */
+
+    PProfile    next;        /* next profile in same contour, used     */
+                             /* during drop-out control                */
+  };
+
+  typedef PProfile   TProfileList;
+  typedef PProfile*  PProfileList;
+
+
+  /* Simple record used to implement a stack of bands, required */
+  /* by the sub-banding mechanism                               */
+  typedef struct  TBand_
+  {
+    Short  y_min;   /* band's minimum */
+    Short  y_max;   /* band's maximum */
+
+  } TBand;
+
+
+#define AlignProfileSize \
+  ( ( sizeof ( TProfile ) + sizeof ( Alignment ) - 1 ) / sizeof ( long ) )
+
+
+#ifdef FT_STATIC_RASTER
+
+
+#define RAS_ARGS       /* void */
+#define RAS_ARG        /* void */
+
+#define RAS_VARS       /* void */
+#define RAS_VAR        /* void */
+
+#define FT_UNUSED_RASTER  do ; while ( 0 )
+
+
+#else /* FT_STATIC_RASTER */
+
+
+#define RAS_ARGS       PWorker    worker,
+#define RAS_ARG        PWorker    worker
+
+#define RAS_VARS       worker,
+#define RAS_VAR        worker
+
+#define FT_UNUSED_RASTER  FT_UNUSED( worker )
+
+
+#endif /* FT_STATIC_RASTER */
+
+
+  typedef struct TWorker_   TWorker, *PWorker;
+
+
+  /* prototypes used for sweep function dispatch */
+  typedef void
+  Function_Sweep_Init( RAS_ARGS Short*  min,
+                                Short*  max );
+
+  typedef void
+  Function_Sweep_Span( RAS_ARGS Short       y,
+                                FT_F26Dot6  x1,
+                                FT_F26Dot6  x2,
+                                PProfile    left,
+                                PProfile    right );
+
+  typedef void
+  Function_Sweep_Step( RAS_ARG );
+
+
+  /* NOTE: These operations are only valid on 2's complement processors */
+
+#define FLOOR( x )    ( (x) & -ras.precision )
+#define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
+#define TRUNC( x )    ( (signed long)(x) >> ras.precision_bits )
+#define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
+#define SCALED( x )   ( ( (x) << ras.scale_shift ) - ras.precision_half )
+
+  /* Note that I have moved the location of some fields in the */
+  /* structure to ensure that the most used variables are used */
+  /* at the top.  Thus, their offset can be coded with less    */
+  /* opcodes, and it results in a smaller executable.          */
+
+  struct  TWorker_
+  {
+    Int       precision_bits;       /* precision related variables         */
+    Int       precision;
+    Int       precision_half;
+    Long      precision_mask;
+    Int       precision_shift;
+    Int       precision_step;
+    Int       precision_jitter;
+
+    Int       scale_shift;          /* == precision_shift   for bitmaps    */
+                                    /* == precision_shift+1 for pixmaps    */
+
+    PLong     buff;                 /* The profiles buffer                 */
+    PLong     sizeBuff;             /* Render pool size                    */
+    PLong     maxBuff;              /* Profiles buffer size                */
+    PLong     top;                  /* Current cursor in buffer            */
+
+    FT_Error  error;
+
+    Int       numTurns;             /* number of Y-turns in outline        */
+
+    TPoint*   arc;                  /* current Bezier arc pointer          */
+
+    UShort    bWidth;               /* target bitmap width                 */
+    PByte     bTarget;              /* target bitmap buffer                */
+    PByte     gTarget;              /* target pixmap buffer                */
+
+    Long      lastX, lastY, minY, maxY;
+
+    UShort    num_Profs;            /* current number of profiles          */
+
+    Bool      fresh;                /* signals a fresh new profile which   */
+                                    /* 'start' field must be completed     */
+    Bool      joint;                /* signals that the last arc ended     */
+                                    /* exactly on a scanline.  Allows      */
+                                    /* removal of doublets                 */
+    PProfile  cProfile;             /* current profile                     */
+    PProfile  fProfile;             /* head of linked list of profiles     */
+    PProfile  gProfile;             /* contour's first profile in case     */
+                                    /* of impact                           */
+
+    TStates   state;                /* rendering state                     */
+
+    FT_Bitmap   target;             /* description of target bit/pixmap    */
+    FT_Outline  outline;
+
+    Long      traceOfs;             /* current offset in target bitmap     */
+    Long      traceG;               /* current offset in target pixmap     */
+
+    Short     traceIncr;            /* sweep's increment in target bitmap  */
+
+    Short     gray_min_x;           /* current min x during gray rendering */
+    Short     gray_max_x;           /* current max x during gray rendering */
+
+    /* dispatch variables */
+
+    Function_Sweep_Init*  Proc_Sweep_Init;
+    Function_Sweep_Span*  Proc_Sweep_Span;
+    Function_Sweep_Span*  Proc_Sweep_Drop;
+    Function_Sweep_Step*  Proc_Sweep_Step;
+
+    Byte      dropOutControl;       /* current drop_out control method     */
+
+    Bool      second_pass;          /* indicates whether a horizontal pass */
+                                    /* should be performed to control      */
+                                    /* drop-out accurately when calling    */
+                                    /* Render_Glyph.  Note that there is   */
+                                    /* no horizontal pass during gray      */
+                                    /* rendering.                          */
+
+    TPoint    arcs[3 * MaxBezier + 1]; /* The Bezier stack                 */
+
+    TBand     band_stack[16];       /* band stack used for sub-banding     */
+    Int       band_top;             /* band stack top                      */
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    Byte*     grays;
+
+    Byte      gray_lines[RASTER_GRAY_LINES];
+                                /* Intermediate table used to render the   */
+                                /* graylevels pixmaps.                     */
+                                /* gray_lines is a buffer holding two      */
+                                /* monochrome scanlines                    */
+
+    Short     gray_width;       /* width in bytes of one monochrome        */
+                                /* intermediate scanline of gray_lines.    */
+                                /* Each gray pixel takes 2 bits long there */
+
+                       /* The gray_lines must hold 2 lines, thus with size */
+                       /* in bytes of at least `gray_width*2'.             */
+
+#endif /* FT_RASTER_ANTI_ALIASING */
+
+  };
+
+
+  typedef struct TRaster_
+  {
+    char*     buffer;
+    long      buffer_size;
+    void*     memory;
+    PWorker   worker;
+    Byte      grays[5];
+    Short     gray_width;
+
+  } TRaster, *PRaster;
+
+#ifdef FT_STATIC_RASTER
+
+  static TWorker   cur_ras;
+#define ras  cur_ras
+
+#else
+
+#define ras  (*worker)
+
+#endif /* FT_STATIC_RASTER */
+
+
+static const char  count_table[256] =
+{
+  0 , 1 , 1 , 2 , 1 , 2 , 2 , 3 , 1 , 2 , 2 , 3 , 2 , 3 , 3 , 4,
+  1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
+  1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
+  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+  1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
+  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+  3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
+  1 , 2 , 2 , 3 , 2 , 3 , 3 , 4 , 2 , 3 , 3 , 4 , 3 , 4 , 4 , 5,
+  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+  3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
+  2 , 3 , 3 , 4 , 3 , 4 , 4 , 5 , 3 , 4 , 4 , 5 , 4 , 5 , 5 , 6,
+  3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
+  3 , 4 , 4 , 5 , 4 , 5 , 5 , 6 , 4 , 5 , 5 , 6 , 5 , 6 , 6 , 7,
+  4 , 5 , 5 , 6 , 5 , 6 , 6 , 7 , 5 , 6 , 6 , 7 , 6 , 7 , 7 , 8 };
+
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  PROFILES COMPUTATION                                               **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Set_High_Precision                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Sets precision variables according to param flag.                  */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    High :: Set to True for high precision (typically for ppem < 18),  */
+  /*            false otherwise.                                           */
+  /*                                                                       */
+  static void
+  Set_High_Precision( RAS_ARGS Int  High )
+  {
+    if ( High )
+    {
+      ras.precision_bits   = 10;
+      ras.precision_step   = 128;
+      ras.precision_jitter = 24;
+    }
+    else
+    {
+      ras.precision_bits   = 6;
+      ras.precision_step   = 32;
+      ras.precision_jitter = 2;
+    }
+
+    FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
+
+    ras.precision       = 1 << ras.precision_bits;
+    ras.precision_half  = ras.precision / 2;
+    ras.precision_shift = ras.precision_bits - Pixel_Bits;
+    ras.precision_mask  = -ras.precision;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    New_Profile                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Creates a new profile in the render pool.                          */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    aState :: The state/orientation of the new profile.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static Bool
+  New_Profile( RAS_ARGS TStates  aState )
+  {
+    if ( !ras.fProfile )
+    {
+      ras.cProfile  = (PProfile)ras.top;
+      ras.fProfile  = ras.cProfile;
+      ras.top      += AlignProfileSize;
+    }
+
+    if ( ras.top >= ras.maxBuff )
+    {
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    switch ( aState )
+    {
+    case Ascending_State:
+      ras.cProfile->flow = Flow_Up;
+      FT_TRACE6(( "New ascending profile = %lx\n", (long)ras.cProfile ));
+      break;
+
+    case Descending_State:
+      ras.cProfile->flow = Flow_Down;
+      FT_TRACE6(( "New descending profile = %lx\n", (long)ras.cProfile ));
+      break;
+
+    default:
+      FT_ERROR(( "New_Profile: invalid profile direction!\n" ));
+      ras.error = Raster_Err_Invalid;
+      return FAILURE;
+    }
+
+    ras.cProfile->start  = 0;
+    ras.cProfile->height = 0;
+    ras.cProfile->offset = ras.top;
+    ras.cProfile->link   = (PProfile)0;
+    ras.cProfile->next   = (PProfile)0;
+
+    if ( !ras.gProfile )
+      ras.gProfile = ras.cProfile;
+
+    ras.state = aState;
+    ras.fresh = TRUE;
+    ras.joint = FALSE;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    End_Profile                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Finalizes the current profile.                                     */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
+  /*                                                                       */
+  static Bool
+  End_Profile( RAS_ARG )
+  {
+    Long      h;
+    PProfile  oldProfile;
+
+
+    h = (Long)( ras.top - ras.cProfile->offset );
+
+    if ( h < 0 )
+    {
+      FT_ERROR(( "End_Profile: negative height encountered!\n" ));
+      ras.error = Raster_Err_Neg_Height;
+      return FAILURE;
+    }
+
+    if ( h > 0 )
+    {
+      FT_TRACE6(( "Ending profile %lx, start = %ld, height = %ld\n",
+                  (long)ras.cProfile, ras.cProfile->start, h ));
+
+      oldProfile           = ras.cProfile;
+      ras.cProfile->height = h;
+      ras.cProfile         = (PProfile)ras.top;
+
+      ras.top             += AlignProfileSize;
+
+      ras.cProfile->height = 0;
+      ras.cProfile->offset = ras.top;
+      oldProfile->next     = ras.cProfile;
+      ras.num_Profs++;
+    }
+
+    if ( ras.top >= ras.maxBuff )
+    {
+      FT_TRACE1(( "overflow in End_Profile\n" ));
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    ras.joint = FALSE;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Insert_Y_Turn                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Inserts a salient into the sorted list placed on top of the render */
+  /*    pool.                                                              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    New y scanline position.                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
+  /*                                                                       */
+  static Bool
+  Insert_Y_Turn( RAS_ARGS Int  y )
+  {
+    PLong  y_turns;
+    Int    y2, n;
+
+
+    n       = ras.numTurns - 1;
+    y_turns = ras.sizeBuff - ras.numTurns;
+
+    /* look for first y value that is <= */
+    while ( n >= 0 && y < y_turns[n] )
+      n--;
+
+    /* if it is <, simply insert it, ignore if == */
+    if ( n >= 0 && y > y_turns[n] )
+      while ( n >= 0 )
+      {
+        y2 = (Int)y_turns[n];
+        y_turns[n] = y;
+        y = y2;
+        n--;
+      }
+
+    if ( n < 0 )
+    {
+      ras.maxBuff--;
+      if ( ras.maxBuff <= ras.top )
+      {
+        ras.error = Raster_Err_Overflow;
+        return FAILURE;
+      }
+      ras.numTurns++;
+      ras.sizeBuff[-ras.numTurns] = y;
+    }
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Finalize_Profile_Table                                             */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Adjusts all links in the profiles list.                            */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
+  /*                                                                       */
+  static Bool
+  Finalize_Profile_Table( RAS_ARG )
+  {
+    Int       bottom, top;
+    UShort    n;
+    PProfile  p;
+
+
+    n = ras.num_Profs;
+
+    if ( n > 1 )
+    {
+      p = ras.fProfile;
+      while ( n > 0 )
+      {
+        if ( n > 1 )
+          p->link = (PProfile)( p->offset + p->height );
+        else
+          p->link = NULL;
+
+        switch ( p->flow )
+        {
+        case Flow_Down:
+          bottom     = (Int)( p->start - p->height + 1 );
+          top        = (Int)p->start;
+          p->start   = bottom;
+          p->offset += p->height - 1;
+          break;
+
+        case Flow_Up:
+        default:
+          bottom = (Int)p->start;
+          top    = (Int)( p->start + p->height - 1 );
+        }
+
+        if ( Insert_Y_Turn( RAS_VARS bottom )   ||
+             Insert_Y_Turn( RAS_VARS top + 1 )  )
+          return FAILURE;
+
+        p = p->link;
+        n--;
+      }
+    }
+    else
+      ras.fProfile = NULL;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Split_Conic                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Subdivides one conic Bezier into two joint sub-arcs in the Bezier  */
+  /*    stack.                                                             */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    None (subdivided Bezier is taken from the top of the stack).       */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This routine is the `beef' of this component.  It is  _the_ inner  */
+  /*    loop that should be optimized to hell to get the best performance. */
+  /*                                                                       */
+  static void
+  Split_Conic( TPoint*  base )
+  {
+    Long  a, b;
+
+
+    base[4].x = base[2].x;
+    b = base[1].x;
+    a = base[3].x = ( base[2].x + b ) / 2;
+    b = base[1].x = ( base[0].x + b ) / 2;
+    base[2].x = ( a + b ) / 2;
+
+    base[4].y = base[2].y;
+    b = base[1].y;
+    a = base[3].y = ( base[2].y + b ) / 2;
+    b = base[1].y = ( base[0].y + b ) / 2;
+    base[2].y = ( a + b ) / 2;
+
+    /* hand optimized.  gcc doesn't seem to be too good at common      */
+    /* expression substitution and instruction scheduling ;-)          */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Split_Cubic                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Subdivides a third-order Bezier arc into two joint sub-arcs in the */
+  /*    Bezier stack.                                                      */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    This routine is the `beef' of the component.  It is one of _the_   */
+  /*    inner loops that should be optimized like hell to get the best     */
+  /*    performance.                                                       */
+  /*                                                                       */
+  static void
+  Split_Cubic( TPoint*  base )
+  {
+    Long  a, b, c, d;
+
+
+    base[6].x = base[3].x;
+    c = base[1].x;
+    d = base[2].x;
+    base[1].x = a = ( base[0].x + c + 1 ) >> 1;
+    base[5].x = b = ( base[3].x + d + 1 ) >> 1;
+    c = ( c + d + 1 ) >> 1;
+    base[2].x = a = ( a + c + 1 ) >> 1;
+    base[4].x = b = ( b + c + 1 ) >> 1;
+    base[3].x = ( a + b + 1 ) >> 1;
+
+    base[6].y = base[3].y;
+    c = base[1].y;
+    d = base[2].y;
+    base[1].y = a = ( base[0].y + c + 1 ) >> 1;
+    base[5].y = b = ( base[3].y + d + 1 ) >> 1;
+    c = ( c + d + 1 ) >> 1;
+    base[2].y = a = ( a + c + 1 ) >> 1;
+    base[4].y = b = ( b + c + 1 ) >> 1;
+    base[3].y = ( a + b + 1 ) >> 1;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_Up                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an ascending line segment and stores */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x1   :: The x-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    y1   :: The y-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    x2   :: The x-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    y2   :: The y-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    miny :: A lower vertical clipping bound value.                     */
+  /*                                                                       */
+  /*    maxy :: An upper vertical clipping bound value.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static Bool
+  Line_Up( RAS_ARGS Long  x1,
+                    Long  y1,
+                    Long  x2,
+                    Long  y2,
+                    Long  miny,
+                    Long  maxy )
+  {
+    Long   Dx, Dy;
+    Int    e1, e2, f1, f2, size;     /* XXX: is `Short' sufficient? */
+    Long   Ix, Rx, Ax;
+
+    PLong  top;
+
+
+    Dx = x2 - x1;
+    Dy = y2 - y1;
+
+    if ( Dy <= 0 || y2 < miny || y1 > maxy )
+      return SUCCESS;
+
+    if ( y1 < miny )
+    {
+      /* Take care: miny-y1 can be a very large value; we use     */
+      /*            a slow MulDiv function to avoid clipping bugs */
+      x1 += SMulDiv( Dx, miny - y1, Dy );
+      e1  = (Int)TRUNC( miny );
+      f1  = 0;
+    }
+    else
+    {
+      e1 = (Int)TRUNC( y1 );
+      f1 = (Int)FRAC( y1 );
+    }
+
+    if ( y2 > maxy )
+    {
+      /* x2 += FMulDiv( Dx, maxy - y2, Dy );  UNNECESSARY */
+      e2  = (Int)TRUNC( maxy );
+      f2  = 0;
+    }
+    else
+    {
+      e2 = (Int)TRUNC( y2 );
+      f2 = (Int)FRAC( y2 );
+    }
+
+    if ( f1 > 0 )
+    {
+      if ( e1 == e2 )
+        return SUCCESS;
+      else
+      {
+        x1 += FMulDiv( Dx, ras.precision - f1, Dy );
+        e1 += 1;
+      }
+    }
+    else
+      if ( ras.joint )
+      {
+        ras.top--;
+        ras.joint = FALSE;
+      }
+
+    ras.joint = (char)( f2 == 0 );
+
+    if ( ras.fresh )
+    {
+      ras.cProfile->start = e1;
+      ras.fresh           = FALSE;
+    }
+
+    size = e2 - e1 + 1;
+    if ( ras.top + size >= ras.maxBuff )
+    {
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    if ( Dx > 0 )
+    {
+      Ix = ( ras.precision * Dx ) / Dy;
+      Rx = ( ras.precision * Dx ) % Dy;
+      Dx = 1;
+    }
+    else
+    {
+      Ix = -( ( ras.precision * -Dx ) / Dy );
+      Rx =    ( ras.precision * -Dx ) % Dy;
+      Dx = -1;
+    }
+
+    Ax  = -Dy;
+    top = ras.top;
+
+    while ( size > 0 )
+    {
+      *top++ = x1;
+
+      x1 += Ix;
+      Ax += Rx;
+      if ( Ax >= 0 )
+      {
+        Ax -= Dy;
+        x1 += Dx;
+      }
+      size--;
+    }
+
+    ras.top = top;
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_Down                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an descending line segment and       */
+  /*    stores them in the render pool.                                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    x1   :: The x-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    y1   :: The y-coordinate of the segment's start point.             */
+  /*                                                                       */
+  /*    x2   :: The x-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    y2   :: The y-coordinate of the segment's end point.               */
+  /*                                                                       */
+  /*    miny :: A lower vertical clipping bound value.                     */
+  /*                                                                       */
+  /*    maxy :: An upper vertical clipping bound value.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static Bool
+  Line_Down( RAS_ARGS Long  x1,
+                      Long  y1,
+                      Long  x2,
+                      Long  y2,
+                      Long  miny,
+                      Long  maxy )
+  {
+    Bool  result, fresh;
+
+
+    fresh  = ras.fresh;
+
+    result = Line_Up( RAS_VARS x1, -y1, x2, -y2, -maxy, -miny );
+
+    if ( fresh && !ras.fresh )
+      ras.cProfile->start = -ras.cProfile->start;
+
+    return result;
+  }
+
+
+  /* A function type describing the functions used to split Bezier arcs */
+  typedef void  (*TSplitter)( TPoint*  base );
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Bezier_Up                                                          */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an ascending Bezier arc and stores   */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
+  /*                                                                       */
+  /*    splitter :: The function to split Bezier arcs.                     */
+  /*                                                                       */
+  /*    miny     :: A lower vertical clipping bound value.                 */
+  /*                                                                       */
+  /*    maxy     :: An upper vertical clipping bound value.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static Bool
+  Bezier_Up( RAS_ARGS Int        degree,
+                      TSplitter  splitter,
+                      Long       miny,
+                      Long       maxy )
+  {
+    Long   y1, y2, e, e2, e0;
+    Short  f1;
+
+    TPoint*  arc;
+    TPoint*  start_arc;
+
+    PLong top;
+
+
+    arc = ras.arc;
+    y1  = arc[degree].y;
+    y2  = arc[0].y;
+    top = ras.top;
+
+    if ( y2 < miny || y1 > maxy )
+      goto Fin;
+
+    e2 = FLOOR( y2 );
+
+    if ( e2 > maxy )
+      e2 = maxy;
+
+    e0 = miny;
+
+    if ( y1 < miny )
+      e = miny;
+    else
+    {
+      e  = CEILING( y1 );
+      f1 = (Short)( FRAC( y1 ) );
+      e0 = e;
+
+      if ( f1 == 0 )
+      {
+        if ( ras.joint )
+        {
+          top--;
+          ras.joint = FALSE;
+        }
+
+        *top++ = arc[degree].x;
+
+        e += ras.precision;
+      }
+    }
+
+    if ( ras.fresh )
+    {
+      ras.cProfile->start = TRUNC( e0 );
+      ras.fresh = FALSE;
+    }
+
+    if ( e2 < e )
+      goto Fin;
+
+    if ( ( top + TRUNC( e2 - e ) + 1 ) >= ras.maxBuff )
+    {
+      ras.top   = top;
+      ras.error = Raster_Err_Overflow;
+      return FAILURE;
+    }
+
+    start_arc = arc;
+
+    while ( arc >= start_arc && e <= e2 )
+    {
+      ras.joint = FALSE;
+
+      y2 = arc[0].y;
+
+      if ( y2 > e )
+      {
+        y1 = arc[degree].y;
+        if ( y2 - y1 >= ras.precision_step )
+        {
+          splitter( arc );
+          arc += degree;
+        }
+        else
+        {
+          *top++ = arc[degree].x + FMulDiv( arc[0].x-arc[degree].x,
+                                            e - y1, y2 - y1 );
+          arc -= degree;
+          e   += ras.precision;
+        }
+      }
+      else
+      {
+        if ( y2 == e )
+        {
+          ras.joint  = TRUE;
+          *top++     = arc[0].x;
+
+          e += ras.precision;
+        }
+        arc -= degree;
+      }
+    }
+
+  Fin:
+    ras.top  = top;
+    ras.arc -= degree;
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Bezier_Down                                                        */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Computes the x-coordinates of an descending Bezier arc and stores  */
+  /*    them in the render pool.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
+  /*                                                                       */
+  /*    splitter :: The function to split Bezier arcs.                     */
+  /*                                                                       */
+  /*    miny     :: A lower vertical clipping bound value.                 */
+  /*                                                                       */
+  /*    maxy     :: An upper vertical clipping bound value.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on render pool overflow.               */
+  /*                                                                       */
+  static Bool
+  Bezier_Down( RAS_ARGS Int        degree,
+                        TSplitter  splitter,
+                        Long       miny,
+                        Long       maxy )
+  {
+    TPoint*  arc = ras.arc;
+    Bool     result, fresh;
+
+
+    arc[0].y = -arc[0].y;
+    arc[1].y = -arc[1].y;
+    arc[2].y = -arc[2].y;
+    if ( degree > 2 )
+      arc[3].y = -arc[3].y;
+
+    fresh = ras.fresh;
+
+    result = Bezier_Up( RAS_VARS degree, splitter, -maxy, -miny );
+
+    if ( fresh && !ras.fresh )
+      ras.cProfile->start = -ras.cProfile->start;
+
+    arc[0].y = -arc[0].y;
+    return result;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Line_To                                                            */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new line segment and adjusts Profiles list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   x :: The x-coordinate of the segment's end point (its start point   */
+  /*        is stored in `lastX').                                         */
+  /*                                                                       */
+  /*   y :: The y-coordinate of the segment's end point (its start point   */
+  /*        is stored in `lastY').                                         */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static Bool
+  Line_To( RAS_ARGS Long  x,
+                    Long  y )
+  {
+    /* First, detect a change of direction */
+
+    switch ( ras.state )
+    {
+    case Unknown_State:
+      if ( y > ras.lastY )
+      {
+        if ( New_Profile( RAS_VARS Ascending_State ) )
+          return FAILURE;
+      }
+      else
+      {
+        if ( y < ras.lastY )
+          if ( New_Profile( RAS_VARS Descending_State ) )
+            return FAILURE;
+      }
+      break;
+
+    case Ascending_State:
+      if ( y < ras.lastY )
+      {
+        if ( End_Profile( RAS_VAR )                   ||
+             New_Profile( RAS_VARS Descending_State ) )
+          return FAILURE;
+      }
+      break;
+
+    case Descending_State:
+      if ( y > ras.lastY )
+      {
+        if ( End_Profile( RAS_VAR )                  ||
+             New_Profile( RAS_VARS Ascending_State ) )
+          return FAILURE;
+      }
+      break;
+
+    default:
+      ;
+    }
+
+    /* Then compute the lines */
+
+    switch ( ras.state )
+    {
+    case Ascending_State:
+      if ( Line_Up( RAS_VARS ras.lastX, ras.lastY,
+                    x, y, ras.minY, ras.maxY ) )
+        return FAILURE;
+      break;
+
+    case Descending_State:
+      if ( Line_Down( RAS_VARS ras.lastX, ras.lastY,
+                      x, y, ras.minY, ras.maxY ) )
+        return FAILURE;
+      break;
+
+    default:
+      ;
+    }
+
+    ras.lastX = x;
+    ras.lastY = y;
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Conic_To                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new conic arc and adjusts the profile list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   cx :: The x-coordinate of the arc's new control point.              */
+  /*                                                                       */
+  /*   cy :: The y-coordinate of the arc's new control point.              */
+  /*                                                                       */
+  /*   x  :: The x-coordinate of the arc's end point (its start point is   */
+  /*         stored in `lastX').                                           */
+  /*                                                                       */
+  /*   y  :: The y-coordinate of the arc's end point (its start point is   */
+  /*         stored in `lastY').                                           */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static Bool
+  Conic_To( RAS_ARGS Long  cx,
+                     Long  cy,
+                     Long  x,
+                     Long  y )
+  {
+    Long     y1, y2, y3, x3, ymin, ymax;
+    TStates  state_bez;
+
+
+    ras.arc      = ras.arcs;
+    ras.arc[2].x = ras.lastX;
+    ras.arc[2].y = ras.lastY;
+    ras.arc[1].x = cx; ras.arc[1].y = cy;
+    ras.arc[0].x = x;  ras.arc[0].y = y;
+
+    do
+    {
+      y1 = ras.arc[2].y;
+      y2 = ras.arc[1].y;
+      y3 = ras.arc[0].y;
+      x3 = ras.arc[0].x;
+
+      /* first, categorize the Bezier arc */
+
+      if ( y1 <= y3 )
+      {
+        ymin = y1;
+        ymax = y3;
+      }
+      else
+      {
+        ymin = y3;
+        ymax = y1;
+      }
+
+      if ( y2 < ymin || y2 > ymax )
+      {
+        /* this arc has no given direction, split it! */
+        Split_Conic( ras.arc );
+        ras.arc += 2;
+      }
+      else if ( y1 == y3 )
+      {
+        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        ras.arc -= 2;
+      }
+      else
+      {
+        /* the arc is y-monotonous, either ascending or descending */
+        /* detect a change of direction                            */
+        state_bez = y1 < y3 ? Ascending_State : Descending_State;
+        if ( ras.state != state_bez )
+        {
+          /* finalize current profile if any */
+          if ( ras.state != Unknown_State   &&
+               End_Profile( RAS_VAR ) )
+            goto Fail;
+
+          /* create a new profile */
+          if ( New_Profile( RAS_VARS state_bez ) )
+            goto Fail;
+        }
+
+        /* now call the appropriate routine */
+        if ( state_bez == Ascending_State )
+        {
+          if ( Bezier_Up( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+            goto Fail;
+        }
+        else
+          if ( Bezier_Down( RAS_VARS 2, Split_Conic, ras.minY, ras.maxY ) )
+            goto Fail;
+      }
+
+    } while ( ras.arc >= ras.arcs );
+
+    ras.lastX = x3;
+    ras.lastY = y3;
+
+    return SUCCESS;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Cubic_To                                                           */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Injects a new cubic arc and adjusts the profile list.              */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*   cx1 :: The x-coordinate of the arc's first new control point.       */
+  /*                                                                       */
+  /*   cy1 :: The y-coordinate of the arc's first new control point.       */
+  /*                                                                       */
+  /*   cx2 :: The x-coordinate of the arc's second new control point.      */
+  /*                                                                       */
+  /*   cy2 :: The y-coordinate of the arc's second new control point.      */
+  /*                                                                       */
+  /*   x   :: The x-coordinate of the arc's end point (its start point is  */
+  /*          stored in `lastX').                                          */
+  /*                                                                       */
+  /*   y   :: The y-coordinate of the arc's end point (its start point is  */
+  /*          stored in `lastY').                                          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
+  /*   profile.                                                            */
+  /*                                                                       */
+  static Bool
+  Cubic_To( RAS_ARGS Long  cx1,
+                     Long  cy1,
+                     Long  cx2,
+                     Long  cy2,
+                     Long  x,
+                     Long  y )
+  {
+    Long     y1, y2, y3, y4, x4, ymin1, ymax1, ymin2, ymax2;
+    TStates  state_bez;
+
+
+    ras.arc      = ras.arcs;
+    ras.arc[3].x = ras.lastX;
+    ras.arc[3].y = ras.lastY;
+    ras.arc[2].x = cx1; ras.arc[2].y = cy1;
+    ras.arc[1].x = cx2; ras.arc[1].y = cy2;
+    ras.arc[0].x = x;   ras.arc[0].y = y;
+
+    do
+    {
+      y1 = ras.arc[3].y;
+      y2 = ras.arc[2].y;
+      y3 = ras.arc[1].y;
+      y4 = ras.arc[0].y;
+      x4 = ras.arc[0].x;
+
+      /* first, categorize the Bezier arc */
+
+      if ( y1 <= y4 )
+      {
+        ymin1 = y1;
+        ymax1 = y4;
+      }
+      else
+      {
+        ymin1 = y4;
+        ymax1 = y1;
+      }
+
+      if ( y2 <= y3 )
+      {
+        ymin2 = y2;
+        ymax2 = y3;
+      }
+      else
+      {
+        ymin2 = y3;
+        ymax2 = y2;
+      }
+
+      if ( ymin2 < ymin1 || ymax2 > ymax1 )
+      {
+        /* this arc has no given direction, split it! */
+        Split_Cubic( ras.arc );
+        ras.arc += 3;
+      }
+      else if ( y1 == y4 )
+      {
+        /* this arc is flat, ignore it and pop it from the Bezier stack */
+        ras.arc -= 3;
+      }
+      else
+      {
+        state_bez = ( y1 <= y4 ) ? Ascending_State : Descending_State;
+
+        /* detect a change of direction */
+        if ( ras.state != state_bez )
+        {
+          if ( ras.state != Unknown_State   &&
+               End_Profile( RAS_VAR ) )
+            goto Fail;
+
+          if ( New_Profile( RAS_VARS state_bez ) )
+            goto Fail;
+        }
+
+        /* compute intersections */
+        if ( state_bez == Ascending_State )
+        {
+          if ( Bezier_Up( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+            goto Fail;
+        }
+        else
+          if ( Bezier_Down( RAS_VARS 3, Split_Cubic, ras.minY, ras.maxY ) )
+            goto Fail;
+      }
+
+    } while ( ras.arc >= ras.arcs );
+
+    ras.lastX = x4;
+    ras.lastY = y4;
+
+    return SUCCESS;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+#undef  SWAP_
+#define SWAP_( x, y )  do                \
+                       {                 \
+                         Long  swap = x; \
+                                         \
+                                         \
+                         x = y;          \
+                         y = swap;       \
+                       } while ( 0 )
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Decompose_Curve                                                    */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Scans the outline arrays in order to emit individual segments and  */
+  /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
+  /*    weird cases, like when the first point is off the curve, or when   */
+  /*    there are simply no `on' points in the contour!                    */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    first   :: The index of the first point in the contour.            */
+  /*                                                                       */
+  /*    last    :: The index of the last point in the contour.             */
+  /*                                                                       */
+  /*    flipped :: If set, flip the direction of the curve.                */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE on error.                              */
+  /*                                                                       */
+  static Bool
+  Decompose_Curve( RAS_ARGS UShort  first,
+                            UShort  last,
+                            int     flipped )
+  {
+    FT_Vector   v_last;
+    FT_Vector   v_control;
+    FT_Vector   v_start;
+
+    FT_Vector*  points;
+    FT_Vector*  point;
+    FT_Vector*  limit;
+    char*       tags;
+
+    unsigned    tag;       /* current point's state           */
+
+
+    points = ras.outline.points;
+    limit  = points + last;
+
+    v_start.x = SCALED( points[first].x );
+    v_start.y = SCALED( points[first].y );
+    v_last.x  = SCALED( points[last].x );
+    v_last.y  = SCALED( points[last].y );
+
+    if ( flipped )
+    {
+      SWAP_( v_start.x, v_start.y );
+      SWAP_( v_last.x, v_last.y );
+    }
+
+    v_control = v_start;
+
+    point = points + first;
+    tags  = ras.outline.tags  + first;
+    tag   = FT_CURVE_TAG( tags[0] );
+
+    /* A contour cannot start with a cubic control point! */
+    if ( tag == FT_CURVE_TAG_CUBIC )
+      goto Invalid_Outline;
+
+    /* check first point to determine origin */
+    if ( tag == FT_CURVE_TAG_CONIC )
+    {
+      /* first point is conic control.  Yes, this happens. */
+      if ( FT_CURVE_TAG( ras.outline.tags[last] ) == FT_CURVE_TAG_ON )
+      {
+        /* start at last point if it is on the curve */
+        v_start = v_last;
+        limit--;
+      }
+      else
+      {
+        /* if both first and last points are conic,         */
+        /* start at their middle and record its position    */
+        /* for closure                                      */
+        v_start.x = ( v_start.x + v_last.x ) / 2;
+        v_start.y = ( v_start.y + v_last.y ) / 2;
+
+        v_last = v_start;
+      }
+      point--;
+      tags--;
+    }
+
+    ras.lastX = v_start.x;
+    ras.lastY = v_start.y;
+
+    while ( point < limit )
+    {
+      point++;
+      tags++;
+
+      tag = FT_CURVE_TAG( tags[0] );
+
+      switch ( tag )
+      {
+      case FT_CURVE_TAG_ON:  /* emit a single line_to */
+        {
+          Long  x, y;
+
+
+          x = SCALED( point->x );
+          y = SCALED( point->y );
+          if ( flipped )
+            SWAP_( x, y );
+
+          if ( Line_To( RAS_VARS x, y ) )
+            goto Fail;
+          continue;
+        }
+
+      case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
+        v_control.x = SCALED( point[0].x );
+        v_control.y = SCALED( point[0].y );
+
+        if ( flipped )
+          SWAP_( v_control.x, v_control.y );
+
+      Do_Conic:
+        if ( point < limit )
+        {
+          FT_Vector  v_middle;
+          Long       x, y;
+
+
+          point++;
+          tags++;
+          tag = FT_CURVE_TAG( tags[0] );
+
+          x = SCALED( point[0].x );
+          y = SCALED( point[0].y );
+
+          if ( flipped )
+            SWAP_( x, y );
+
+          if ( tag == FT_CURVE_TAG_ON )
+          {
+            if ( Conic_To( RAS_VARS v_control.x, v_control.y, x, y ) )
+              goto Fail;
+            continue;
+          }
+
+          if ( tag != FT_CURVE_TAG_CONIC )
+            goto Invalid_Outline;
+
+          v_middle.x = ( v_control.x + x ) / 2;
+          v_middle.y = ( v_control.y + y ) / 2;
+
+          if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+                                  v_middle.x,  v_middle.y ) )
+            goto Fail;
+
+          v_control.x = x;
+          v_control.y = y;
+
+          goto Do_Conic;
+        }
+
+        if ( Conic_To( RAS_VARS v_control.x, v_control.y,
+                                v_start.x,   v_start.y ) )
+          goto Fail;
+
+        goto Close;
+
+      default:  /* FT_CURVE_TAG_CUBIC */
+        {
+          Long  x1, y1, x2, y2, x3, y3;
+
+
+          if ( point + 1 > limit                             ||
+               FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
+            goto Invalid_Outline;
+
+          point += 2;
+          tags  += 2;
+
+          x1 = SCALED( point[-2].x );
+          y1 = SCALED( point[-2].y );
+          x2 = SCALED( point[-1].x );
+          y2 = SCALED( point[-1].y );
+          x3 = SCALED( point[ 0].x );
+          y3 = SCALED( point[ 0].y );
+
+          if ( flipped )
+          {
+            SWAP_( x1, y1 );
+            SWAP_( x2, y2 );
+            SWAP_( x3, y3 );
+          }
+
+          if ( point <= limit )
+          {
+            if ( Cubic_To( RAS_VARS x1, y1, x2, y2, x3, y3 ) )
+              goto Fail;
+            continue;
+          }
+
+          if ( Cubic_To( RAS_VARS x1, y1, x2, y2, v_start.x, v_start.y ) )
+            goto Fail;
+          goto Close;
+        }
+      }
+    }
+
+    /* close the contour with a line segment */
+    if ( Line_To( RAS_VARS v_start.x, v_start.y ) )
+      goto Fail;
+
+  Close:
+    return SUCCESS;
+
+  Invalid_Outline:
+    ras.error = Raster_Err_Invalid;
+
+  Fail:
+    return FAILURE;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Convert_Glyph                                                      */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Converts a glyph into a series of segments and arcs and makes a    */
+  /*    profiles list with them.                                           */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    flipped :: If set, flip the direction of curve.                    */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    SUCCESS on success, FAILURE if any error was encountered during    */
+  /*    rendering.                                                         */
+  /*                                                                       */
+  static Bool
+  Convert_Glyph( RAS_ARGS int  flipped )
+  {
+    int       i;
+    unsigned  start;
+
+    PProfile  lastProfile;
+
+
+    ras.fProfile = NULL;
+    ras.joint    = FALSE;
+    ras.fresh    = FALSE;
+
+    ras.maxBuff  = ras.sizeBuff - AlignProfileSize;
+
+    ras.numTurns = 0;
+
+    ras.cProfile         = (PProfile)ras.top;
+    ras.cProfile->offset = ras.top;
+    ras.num_Profs        = 0;
+
+    start = 0;
+
+    for ( i = 0; i < ras.outline.n_contours; i++ )
+    {
+      ras.state    = Unknown_State;
+      ras.gProfile = NULL;
+
+      if ( Decompose_Curve( RAS_VARS (unsigned short)start,
+                            ras.outline.contours[i],
+                            flipped ) )
+        return FAILURE;
+
+      start = ras.outline.contours[i] + 1;
+
+      /* We must now see whether the extreme arcs join or not */
+      if ( FRAC( ras.lastY ) == 0 &&
+           ras.lastY >= ras.minY  &&
+           ras.lastY <= ras.maxY  )
+        if ( ras.gProfile && ras.gProfile->flow == ras.cProfile->flow )
+          ras.top--;
+        /* Note that ras.gProfile can be nil if the contour was too small */
+        /* to be drawn.                                                   */
+
+      lastProfile = ras.cProfile;
+      if ( End_Profile( RAS_VAR ) )
+        return FAILURE;
+
+      /* close the `next profile in contour' linked list */
+      if ( ras.gProfile )
+        lastProfile->next = ras.gProfile;
+    }
+
+    if ( Finalize_Profile_Table( RAS_VAR ) )
+      return FAILURE;
+
+    return (Bool)( ras.top < ras.maxBuff ? SUCCESS : FAILURE );
+  }
+
+
+  /*************************************************************************/
+  /*************************************************************************/
+  /**                                                                     **/
+  /**  SCAN-LINE SWEEPS AND DRAWING                                       **/
+  /**                                                                     **/
+  /*************************************************************************/
+  /*************************************************************************/
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Init_Linked                                                          */
+  /*                                                                       */
+  /*    Initializes an empty linked list.                                  */
+  /*                                                                       */
+  static void
+  Init_Linked( TProfileList*  l )
+  {
+    *l = NULL;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  InsNew                                                               */
+  /*                                                                       */
+  /*    Inserts a new profile in a linked list.                            */
+  /*                                                                       */
+  static void
+  InsNew( PProfileList  list,
+          PProfile      profile )
+  {
+    PProfile  *old, current;
+    Long       x;
+
+
+    old     = list;
+    current = *old;
+    x       = profile->X;
+
+    while ( current )
+    {
+      if ( x < current->X )
+        break;
+      old     = &current->link;
+      current = *old;
+    }
+
+    profile->link = current;
+    *old          = profile;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  DelOld                                                               */
+  /*                                                                       */
+  /*    Removes an old profile from a linked list.                         */
+  /*                                                                       */
+  static void
+  DelOld( PProfileList  list,
+          PProfile      profile )
+  {
+    PProfile  *old, current;
+
+
+    old     = list;
+    current = *old;
+
+    while ( current )
+    {
+      if ( current == profile )
+      {
+        *old = current->link;
+        return;
+      }
+
+      old     = &current->link;
+      current = *old;
+    }
+
+    /* we should never get there, unless the profile was not part of */
+    /* the list.                                                     */
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Sort                                                                 */
+  /*                                                                       */
+  /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
+  /*    an algorithm which is fast in this case.  Bubble sort is enough    */
+  /*    and simple.                                                        */
+  /*                                                                       */
+  static void
+  Sort( PProfileList  list )
+  {
+    PProfile  *old, current, next;
+
+
+    /* First, set the new X coordinate of each profile */
+    current = *list;
+    while ( current )
+    {
+      current->X       = *current->offset;
+      current->offset += current->flow;
+      current->height--;
+      current = current->link;
+    }
+
+    /* Then sort them */
+    old     = list;
+    current = *old;
+
+    if ( !current )
+      return;
+
+    next = current->link;
+
+    while ( next )
+    {
+      if ( current->X <= next->X )
+      {
+        old     = &current->link;
+        current = *old;
+
+        if ( !current )
+          return;
+      }
+      else
+      {
+        *old          = next;
+        current->link = next->link;
+        next->link    = current;
+
+        old     = list;
+        current = *old;
+      }
+
+      next = current->link;
+    }
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Vertical Sweep Procedure Set                                         */
+  /*                                                                       */
+  /*  These four routines are used during the vertical black/white sweep   */
+  /*  phase by the generic Draw_Sweep() function.                          */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static void
+  Vertical_Sweep_Init( RAS_ARGS Short*  min,
+                                Short*  max )
+  {
+    Long  pitch = ras.target.pitch;
+
+    FT_UNUSED( max );
+
+
+    ras.traceIncr = (Short)-pitch;
+    ras.traceOfs  = -*min * pitch;
+    if ( pitch > 0 )
+      ras.traceOfs += ( ras.target.rows - 1 ) * pitch;
+
+    ras.gray_min_x = 0;
+    ras.gray_max_x = 0;
+  }
+
+
+  static void
+  Vertical_Sweep_Span( RAS_ARGS Short       y,
+                                FT_F26Dot6  x1,
+                                FT_F26Dot6  x2,
+                                PProfile    left,
+                                PProfile    right )
+  {
+    Long   e1, e2;
+    int    c1, c2;
+    Byte   f1, f2;
+    Byte*  target;
+
+    FT_UNUSED( y );
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+
+
+    /* Drop-out control */
+
+    e1 = TRUNC( CEILING( x1 ) );
+
+    if ( x2 - x1 - ras.precision <= ras.precision_jitter )
+      e2 = e1;
+    else
+      e2 = TRUNC( FLOOR( x2 ) );
+
+    if ( e2 >= 0 && e1 < ras.bWidth )
+    {
+      if ( e1 < 0 )
+        e1 = 0;
+      if ( e2 >= ras.bWidth )
+        e2 = ras.bWidth - 1;
+
+      c1 = (Short)( e1 >> 3 );
+      c2 = (Short)( e2 >> 3 );
+
+      f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
+      f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
+
+      if ( ras.gray_min_x > c1 ) ras.gray_min_x = (short)c1;
+      if ( ras.gray_max_x < c2 ) ras.gray_max_x = (short)c2;
+
+      target = ras.bTarget + ras.traceOfs + c1;
+      c2 -= c1;
+
+      if ( c2 > 0 )
+      {
+        target[0] |= f1;
+
+        /* memset() is slower than the following code on many platforms. */
+        /* This is due to the fact that, in the vast majority of cases,  */
+        /* the span length in bytes is relatively small.                 */
+        c2--;
+        while ( c2 > 0 )
+        {
+          *(++target) = 0xFF;
+          c2--;
+        }
+        target[1] |= f2;
+      }
+      else
+        *target |= ( f1 & f2 );
+    }
+  }
+
+
+  static void
+  Vertical_Sweep_Drop( RAS_ARGS Short       y,
+                                FT_F26Dot6  x1,
+                                FT_F26Dot6  x2,
+                                PProfile    left,
+                                PProfile    right )
+  {
+    Long   e1, e2;
+    Short  c1, f1;
+
+
+    /* Drop-out control */
+
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( (x1 + x2 + 1) / 2 );
+          break;
+
+        case 2:
+        case 5:
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+          /* Here, we only get rid of stubs recognized if:          */
+          /*                                                        */
+          /*  upper stub:                                           */
+          /*                                                        */
+          /*   - P_Left and P_Right are in the same contour         */
+          /*   - P_Right is the successor of P_Left in that contour */
+          /*   - y is the top of P_Left and P_Right                 */
+          /*                                                        */
+          /*  lower stub:                                           */
+          /*                                                        */
+          /*   - P_Left and P_Right are in the same contour         */
+          /*   - P_Left is the successor of P_Right in that contour */
+          /*   - y is the bottom of P_Left                          */
+          /*                                                        */
+
+          /* FIXXXME: uncommenting this line solves the disappearing */
+          /*          bit problem in the `7' of verdana 10pts, but   */
+          /*          makes a new one in the `C' of arial 14pts      */
+
+#if 0
+          if ( x2 - x1 < ras.precision_half )
+#endif
+          {
+            /* upper stub test */
+            if ( left->next == right && left->height <= 0 )
+              return;
+
+            /* lower stub test */
+            if ( right->next == left && left->start == y )
+              return;
+          }
+
+          /* check that the rightmost pixel isn't set */
+
+          e1 = TRUNC( e1 );
+
+          c1 = (Short)( e1 >> 3 );
+          f1 = (Short)( e1 &  7 );
+
+          if ( e1 >= 0 && e1 < ras.bWidth                      &&
+               ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    e1 = TRUNC( e1 );
+
+    if ( e1 >= 0 && e1 < ras.bWidth )
+    {
+      c1 = (Short)( e1 >> 3 );
+      f1 = (Short)( e1 & 7 );
+
+      if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
+      if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
+
+      ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+    }
+  }
+
+
+  static void
+  Vertical_Sweep_Step( RAS_ARG )
+  {
+    ras.traceOfs += ras.traceIncr;
+  }
+
+
+  /***********************************************************************/
+  /*                                                                     */
+  /*  Horizontal Sweep Procedure Set                                     */
+  /*                                                                     */
+  /*  These four routines are used during the horizontal black/white     */
+  /*  sweep phase by the generic Draw_Sweep() function.                  */
+  /*                                                                     */
+  /***********************************************************************/
+
+  static void
+  Horizontal_Sweep_Init( RAS_ARGS Short*  min,
+                                  Short*  max )
+  {
+    /* nothing, really */
+    FT_UNUSED_RASTER;
+    FT_UNUSED( min );
+    FT_UNUSED( max );
+  }
+
+
+  static void
+  Horizontal_Sweep_Span( RAS_ARGS Short       y,
+                                  FT_F26Dot6  x1,
+                                  FT_F26Dot6  x2,
+                                  PProfile    left,
+                                  PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  bits;
+    Byte   f1;
+
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+
+
+    if ( x2 - x1 < ras.precision )
+    {
+      e1 = CEILING( x1 );
+      e2 = FLOOR  ( x2 );
+
+      if ( e1 == e2 )
+      {
+        bits = ras.bTarget + ( y >> 3 );
+        f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+        e1 = TRUNC( e1 );
+
+        if ( e1 >= 0 && e1 < ras.target.rows )
+        {
+          PByte  p;
+
+
+          p = bits - e1*ras.target.pitch;
+          if ( ras.target.pitch > 0 )
+            p += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+          p[0] |= f1;
+        }
+      }
+    }
+  }
+
+
+  static void
+  Horizontal_Sweep_Drop( RAS_ARGS Short       y,
+                                  FT_F26Dot6  x1,
+                                  FT_F26Dot6  x2,
+                                  PProfile    left,
+                                  PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  bits;
+    Byte   f1;
+
+
+    /* During the horizontal sweep, we only take care of drop-outs */
+
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+          break;
+
+        case 2:
+        case 5:
+
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+
+          /* rightmost stub test */
+          if ( left->next == right && left->height <= 0 )
+            return;
+
+          /* leftmost stub test */
+          if ( right->next == left && left->start == y )
+            return;
+
+          /* check that the rightmost pixel isn't set */
+
+          e1 = TRUNC( e1 );
+
+          bits = ras.bTarget + ( y >> 3 );
+          f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+          bits -= e1 * ras.target.pitch;
+          if ( ras.target.pitch > 0 )
+            bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+          if ( e1 >= 0              &&
+               e1 < ras.target.rows &&
+               *bits & f1 )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    bits = ras.bTarget + ( y >> 3 );
+    f1   = (Byte)( 0x80 >> ( y & 7 ) );
+
+    e1 = TRUNC( e1 );
+
+    if ( e1 >= 0 && e1 < ras.target.rows )
+    {
+      bits -= e1 * ras.target.pitch;
+      if ( ras.target.pitch > 0 )
+        bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+      bits[0] |= f1;
+    }
+  }
+
+
+  static void
+  Horizontal_Sweep_Step( RAS_ARG )
+  {
+    /* Nothing, really */
+    FT_UNUSED_RASTER;
+  }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Vertical Gray Sweep Procedure Set                                    */
+  /*                                                                       */
+  /*  These two routines are used during the vertical gray-levels sweep    */
+  /*  phase by the generic Draw_Sweep() function.                          */
+  /*                                                                       */
+  /*  NOTES                                                                */
+  /*                                                                       */
+  /*  - The target pixmap's width *must* be a multiple of 4.               */
+  /*                                                                       */
+  /*  - You have to use the function Vertical_Sweep_Span() for the gray    */
+  /*    span call.                                                         */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static void
+  Vertical_Gray_Sweep_Init( RAS_ARGS Short*  min,
+                                     Short*  max )
+  {
+    Long  pitch, byte_len;
+
+
+    *min = *min & -2;
+    *max = ( *max + 3 ) & -2;
+
+    ras.traceOfs  = 0;
+    pitch         = ras.target.pitch;
+    byte_len      = -pitch;
+    ras.traceIncr = (Short)byte_len;
+    ras.traceG    = ( *min / 2 ) * byte_len;
+
+    if ( pitch > 0 )
+    {
+      ras.traceG += ( ras.target.rows - 1 ) * pitch;
+      byte_len    = -byte_len;
+    }
+
+    ras.gray_min_x =  (Short)byte_len;
+    ras.gray_max_x = -(Short)byte_len;
+  }
+
+
+  static void
+  Vertical_Gray_Sweep_Step( RAS_ARG )
+  {
+    Int    c1, c2;
+    PByte  pix, bit, bit2;
+    char*  count = (char*)count_table;
+    Byte*  grays;
+
+
+    ras.traceOfs += ras.gray_width;
+
+    if ( ras.traceOfs > ras.gray_width )
+    {
+      pix   = ras.gTarget + ras.traceG + ras.gray_min_x * 4;
+      grays = ras.grays;
+
+      if ( ras.gray_max_x >= 0 )
+      {
+        Long   last_pixel = ras.target.width - 1;
+        Int    last_cell  = last_pixel >> 2;
+        Int    last_bit   = last_pixel & 3;
+        Bool   over       = 0;
+
+
+        if ( ras.gray_max_x >= last_cell && last_bit != 3 )
+        {
+          ras.gray_max_x = last_cell - 1;
+          over = 1;
+        }
+
+        if ( ras.gray_min_x < 0 )
+          ras.gray_min_x = 0;
+
+        bit   = ras.bTarget + ras.gray_min_x;
+        bit2  = bit + ras.gray_width;
+
+        c1 = ras.gray_max_x - ras.gray_min_x;
+
+        while ( c1 >= 0 )
+        {
+          c2 = count[*bit] + count[*bit2];
+
+          if ( c2 )
+          {
+            pix[0] = grays[(c2 >> 12) & 0x000F];
+            pix[1] = grays[(c2 >> 8 ) & 0x000F];
+            pix[2] = grays[(c2 >> 4 ) & 0x000F];
+            pix[3] = grays[ c2        & 0x000F];
+
+            *bit  = 0;
+            *bit2 = 0;
+          }
+
+          bit++;
+          bit2++;
+          pix += 4;
+          c1--;
+        }
+
+        if ( over )
+        {
+          c2 = count[*bit] + count[*bit2];
+          if ( c2 )
+          {
+            switch ( last_bit )
+            {
+            case 2:
+              pix[2] = grays[(c2 >> 4 ) & 0x000F];
+            case 1:
+              pix[1] = grays[(c2 >> 8 ) & 0x000F];
+            default:
+              pix[0] = grays[(c2 >> 12) & 0x000F];
+            }
+
+            *bit  = 0;
+            *bit2 = 0;
+          }
+        }
+      }
+
+      ras.traceOfs = 0;
+      ras.traceG  += ras.traceIncr;
+
+      ras.gray_min_x =  32000;
+      ras.gray_max_x = -32000;
+    }
+  }
+
+
+  static void
+  Horizontal_Gray_Sweep_Span( RAS_ARGS Short       y,
+                                       FT_F26Dot6  x1,
+                                       FT_F26Dot6  x2,
+                                       PProfile    left,
+                                       PProfile    right )
+  {
+    /* nothing, really */
+    FT_UNUSED_RASTER;
+    FT_UNUSED( y );
+    FT_UNUSED( x1 );
+    FT_UNUSED( x2 );
+    FT_UNUSED( left );
+    FT_UNUSED( right );
+  }
+
+
+  static void
+  Horizontal_Gray_Sweep_Drop( RAS_ARGS Short       y,
+                                       FT_F26Dot6  x1,
+                                       FT_F26Dot6  x2,
+                                       PProfile    left,
+                                       PProfile    right )
+  {
+    Long   e1, e2;
+    PByte  pixel;
+    Byte   color;
+
+
+    /* During the horizontal sweep, we only take care of drop-outs */
+    e1 = CEILING( x1 );
+    e2 = FLOOR  ( x2 );
+
+    if ( e1 > e2 )
+    {
+      if ( e1 == e2 + ras.precision )
+      {
+        switch ( ras.dropOutControl )
+        {
+        case 1:
+          e1 = e2;
+          break;
+
+        case 4:
+          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+          break;
+
+        case 2:
+        case 5:
+
+          /* Drop-out Control Rule #4 */
+
+          /* The spec is not very clear regarding rule #4.  It      */
+          /* presents a method that is way too costly to implement  */
+          /* while the general idea seems to get rid of `stubs'.    */
+          /*                                                        */
+
+          /* rightmost stub test */
+          if ( left->next == right && left->height <= 0 )
+            return;
+
+          /* leftmost stub test */
+          if ( right->next == left && left->start == y )
+            return;
+
+          if ( ras.dropOutControl == 2 )
+            e1 = e2;
+          else
+            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+
+          break;
+
+        default:
+          return;  /* unsupported mode */
+        }
+      }
+      else
+        return;
+    }
+
+    if ( e1 >= 0 )
+    {
+      if ( x2 - x1 >= ras.precision_half )
+        color = ras.grays[2];
+      else
+        color = ras.grays[1];
+
+      e1 = TRUNC( e1 ) / 2;
+      if ( e1 < ras.target.rows )
+      {
+        pixel = ras.gTarget - e1 * ras.target.pitch + y / 2;
+        if ( ras.target.pitch > 0 )
+          pixel += ( ras.target.rows - 1 ) * ras.target.pitch;
+
+        if ( pixel[0] == ras.grays[0] )
+          pixel[0] = color;
+      }
+    }
+  }
+
+
+#endif /* FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /*  Generic Sweep Drawing routine                                        */
+  /*                                                                       */
+  /*************************************************************************/
+
+  static Bool
+  Draw_Sweep( RAS_ARG )
+  {
+    Short         y, y_change, y_height;
+
+    PProfile      P, Q, P_Left, P_Right;
+
+    Short         min_Y, max_Y, top, bottom, dropouts;
+
+    Long          x1, x2, xs, e1, e2;
+
+    TProfileList  waiting;
+    TProfileList  draw_left, draw_right;
+
+
+    /* Init empty linked lists */
+
+    Init_Linked( &waiting );
+
+    Init_Linked( &draw_left  );
+    Init_Linked( &draw_right );
+
+    /* first, compute min and max Y */
+
+    P     = ras.fProfile;
+    max_Y = (Short)TRUNC( ras.minY );
+    min_Y = (Short)TRUNC( ras.maxY );
+
+    while ( P )
+    {
+      Q = P->link;
+
+      bottom = (Short)P->start;
+      top    = (Short)( P->start + P->height - 1 );
+
+      if ( min_Y > bottom ) min_Y = bottom;
+      if ( max_Y < top    ) max_Y = top;
+
+      P->X = 0;
+      InsNew( &waiting, P );
+
+      P = Q;
+    }
+
+    /* Check the Y-turns */
+    if ( ras.numTurns == 0 )
+    {
+      ras.error = Raster_Err_Invalid;
+      return FAILURE;
+    }
+
+    /* Now inits the sweep */
+
+    ras.Proc_Sweep_Init( RAS_VARS &min_Y, &max_Y );
+
+    /* Then compute the distance of each profile from min_Y */
+
+    P = waiting;
+
+    while ( P )
+    {
+      P->countL = (UShort)( P->start - min_Y );
+      P = P->link;
+    }
+
+    /* Let's go */
+
+    y        = min_Y;
+    y_height = 0;
+
+    if ( ras.numTurns > 0 &&
+         ras.sizeBuff[-ras.numTurns] == min_Y )
+      ras.numTurns--;
+
+    while ( ras.numTurns > 0 )
+    {
+      /* look in the waiting list for new activations */
+
+      P = waiting;
+
+      while ( P )
+      {
+        Q = P->link;
+        P->countL -= y_height;
+        if ( P->countL == 0 )
+        {
+          DelOld( &waiting, P );
+
+          switch ( P->flow )
+          {
+          case Flow_Up:
+            InsNew( &draw_left,  P );
+            break;
+
+          case Flow_Down:
+            InsNew( &draw_right, P );
+            break;
+          }
+        }
+
+        P = Q;
+      }
+
+      /* Sort the drawing lists */
+
+      Sort( &draw_left );
+      Sort( &draw_right );
+
+      y_change = (Short)ras.sizeBuff[-ras.numTurns--];
+      y_height = (Short)( y_change - y );
+
+      while ( y < y_change )
+      {
+        /* Let's trace */
+
+        dropouts = 0;
+
+        P_Left  = draw_left;
+        P_Right = draw_right;
+
+        while ( P_Left )
+        {
+          x1 = P_Left ->X;
+          x2 = P_Right->X;
+
+          if ( x1 > x2 )
+          {
+            xs = x1;
+            x1 = x2;
+            x2 = xs;
+          }
+
+          if ( x2 - x1 <= ras.precision )
+          {
+            e1 = FLOOR( x1 );
+            e2 = CEILING( x2 );
+
+            if ( ras.dropOutControl != 0                 &&
+                 ( e1 > e2 || e2 == e1 + ras.precision ) )
+            {
+              /* a drop out was detected */
+
+              P_Left ->X = x1;
+              P_Right->X = x2;
+
+              /* mark profile for drop-out processing */
+              P_Left->countL = 1;
+              dropouts++;
+
+              goto Skip_To_Next;
+            }
+          }
+
+          ras.Proc_Sweep_Span( RAS_VARS y, x1, x2, P_Left, P_Right );
+
+        Skip_To_Next:
+
+          P_Left  = P_Left->link;
+          P_Right = P_Right->link;
+        }
+
+        /* now perform the dropouts _after_ the span drawing -- */
+        /* drop-outs processing has been moved out of the loop  */
+        /* for performance tuning                               */
+        if ( dropouts > 0 )
+          goto Scan_DropOuts;
+
+      Next_Line:
+
+        ras.Proc_Sweep_Step( RAS_VAR );
+
+        y++;
+
+        if ( y < y_change )
+        {
+          Sort( &draw_left  );
+          Sort( &draw_right );
+        }
+      }
+
+      /* Now finalize the profiles that needs it */
+
+      P = draw_left;
+      while ( P )
+      {
+        Q = P->link;
+        if ( P->height == 0 )
+          DelOld( &draw_left, P );
+        P = Q;
+      }
+
+      P = draw_right;
+      while ( P )
+      {
+        Q = P->link;
+        if ( P->height == 0 )
+          DelOld( &draw_right, P );
+        P = Q;
+      }
+    }
+
+    /* for gray-scaling, flushes the bitmap scanline cache */
+    while ( y <= max_Y )
+    {
+      ras.Proc_Sweep_Step( RAS_VAR );
+      y++;
+    }
+
+    return SUCCESS;
+
+  Scan_DropOuts:
+
+    P_Left  = draw_left;
+    P_Right = draw_right;
+
+    while ( P_Left )
+    {
+      if ( P_Left->countL )
+      {
+        P_Left->countL = 0;
+#if 0
+        dropouts--;  /* -- this is useful when debugging only */
+#endif
+        ras.Proc_Sweep_Drop( RAS_VARS y,
+                                      P_Left->X,
+                                      P_Right->X,
+                                      P_Left,
+                                      P_Right );
+      }
+
+      P_Left  = P_Left->link;
+      P_Right = P_Right->link;
+    }
+
+    goto Next_Line;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Single_Pass                                                 */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Performs one sweep with sub-banding.                               */
+  /*                                                                       */
+  /* <Input>                                                               */
+  /*    flipped :: If set, flip the direction of the outline.              */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    Renderer error code.                                               */
+  /*                                                                       */
+  static int
+  Render_Single_Pass( RAS_ARGS Bool  flipped )
+  {
+    Short  i, j, k;
+
+
+    while ( ras.band_top >= 0 )
+    {
+      ras.maxY = (Long)ras.band_stack[ras.band_top].y_max * ras.precision;
+      ras.minY = (Long)ras.band_stack[ras.band_top].y_min * ras.precision;
+
+      ras.top = ras.buff;
+
+      ras.error = Raster_Err_None;
+
+      if ( Convert_Glyph( RAS_VARS flipped ) )
+      {
+        if ( ras.error != Raster_Err_Overflow )
+          return FAILURE;
+
+        ras.error = Raster_Err_None;
+
+        /* sub-banding */
+
+#ifdef DEBUG_RASTER
+        ClearBand( RAS_VARS TRUNC( ras.minY ), TRUNC( ras.maxY ) );
+#endif
+
+        i = ras.band_stack[ras.band_top].y_min;
+        j = ras.band_stack[ras.band_top].y_max;
+
+        k = (Short)( ( i + j ) / 2 );
+
+        if ( ras.band_top >= 7 || k < i )
+        {
+          ras.band_top = 0;
+          ras.error    = Raster_Err_Invalid;
+
+          return ras.error;
+        }
+
+        ras.band_stack[ras.band_top + 1].y_min = k;
+        ras.band_stack[ras.band_top + 1].y_max = j;
+
+        ras.band_stack[ras.band_top].y_max = (Short)( k - 1 );
+
+        ras.band_top++;
+      }
+      else
+      {
+        if ( ras.fProfile )
+          if ( Draw_Sweep( RAS_VAR ) )
+             return ras.error;
+        ras.band_top--;
+      }
+    }
+
+    return SUCCESS;
+  }
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Glyph                                                       */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders a glyph in a bitmap.  Sub-banding if needed.               */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF( FT_Error )
+  Render_Glyph( RAS_ARG )
+  {
+    FT_Error  error;
+
+
+    Set_High_Precision( RAS_VARS ras.outline.flags &
+                        FT_OUTLINE_HIGH_PRECISION );
+    ras.scale_shift    = ras.precision_shift;
+    /* Drop-out mode 2 is hard-coded since this is the only mode used */
+    /* on Windows platforms.  Using other modes, as specified by the  */
+    /* font, results in misplaced pixels.                             */
+    ras.dropOutControl = 2;
+    ras.second_pass    = (FT_Byte)( !( ras.outline.flags &
+                                       FT_OUTLINE_SINGLE_PASS ) );
+
+    /* Vertical Sweep */
+    ras.Proc_Sweep_Init = Vertical_Sweep_Init;
+    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+    ras.Proc_Sweep_Step = Vertical_Sweep_Step;
+
+    ras.band_top            = 0;
+    ras.band_stack[0].y_min = 0;
+    ras.band_stack[0].y_max = (short)( ras.target.rows - 1 );
+
+    ras.bWidth  = (unsigned short)ras.target.width;
+    ras.bTarget = (Byte*)ras.target.buffer;
+
+    if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
+      return error;
+
+    /* Horizontal Sweep */
+    if ( ras.second_pass && ras.dropOutControl != 0 )
+    {
+      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+      ras.Proc_Sweep_Span = Horizontal_Sweep_Span;
+      ras.Proc_Sweep_Drop = Horizontal_Sweep_Drop;
+      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+      ras.band_top            = 0;
+      ras.band_stack[0].y_min = 0;
+      ras.band_stack[0].y_max = (short)( ras.target.width - 1 );
+
+      if ( ( error = Render_Single_Pass( RAS_VARS 1 ) ) != 0 )
+        return error;
+    }
+
+    return Raster_Err_None;
+  }
+
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+
+  /*************************************************************************/
+  /*                                                                       */
+  /* <Function>                                                            */
+  /*    Render_Gray_Glyph                                                  */
+  /*                                                                       */
+  /* <Description>                                                         */
+  /*    Renders a glyph with grayscaling.  Sub-banding if needed.          */
+  /*                                                                       */
+  /* <Return>                                                              */
+  /*    FreeType error code.  0 means success.                             */
+  /*                                                                       */
+  FT_LOCAL_DEF( FT_Error )
+  Render_Gray_Glyph( RAS_ARG )
+  {
+    Long      pixel_width;
+    FT_Error  error;
+
+
+    Set_High_Precision( RAS_VARS ras.outline.flags &
+                        FT_OUTLINE_HIGH_PRECISION );
+    ras.scale_shift    = ras.precision_shift + 1;
+    /* Drop-out mode 2 is hard-coded since this is the only mode used */
+    /* on Windows platforms.  Using other modes, as specified by the  */
+    /* font, results in misplaced pixels.                             */
+    ras.dropOutControl = 2;
+    ras.second_pass    = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
+
+    /* Vertical Sweep */
+
+    ras.band_top            = 0;
+    ras.band_stack[0].y_min = 0;
+    ras.band_stack[0].y_max = 2 * ras.target.rows - 1;
+
+    ras.bWidth  = ras.gray_width;
+    pixel_width = 2 * ( ( ras.target.width + 3 ) >> 2 );
+
+    if ( ras.bWidth > pixel_width )
+      ras.bWidth = pixel_width;
+
+    ras.bWidth  = ras.bWidth * 8;
+    ras.bTarget = (Byte*)ras.gray_lines;
+    ras.gTarget = (Byte*)ras.target.buffer;
+
+    ras.Proc_Sweep_Init = Vertical_Gray_Sweep_Init;
+    ras.Proc_Sweep_Span = Vertical_Sweep_Span;
+    ras.Proc_Sweep_Drop = Vertical_Sweep_Drop;
+    ras.Proc_Sweep_Step = Vertical_Gray_Sweep_Step;
+
+    error = Render_Single_Pass( RAS_VARS 0 );
+    if ( error )
+      return error;
+
+    /* Horizontal Sweep */
+    if ( ras.second_pass && ras.dropOutControl != 0 )
+    {
+      ras.Proc_Sweep_Init = Horizontal_Sweep_Init;
+      ras.Proc_Sweep_Span = Horizontal_Gray_Sweep_Span;
+      ras.Proc_Sweep_Drop = Horizontal_Gray_Sweep_Drop;
+      ras.Proc_Sweep_Step = Horizontal_Sweep_Step;
+
+      ras.band_top            = 0;
+      ras.band_stack[0].y_min = 0;
+      ras.band_stack[0].y_max = ras.target.width * 2 - 1;
+
+      error = Render_Single_Pass( RAS_VARS 1 );
+      if ( error )
+        return error;
+    }
+
+    return Raster_Err_None;
+  }
+
+#else /* !FT_RASTER_OPTION_ANTI_ALIASING */
+
+  FT_LOCAL_DEF( FT_Error )
+  Render_Gray_Glyph( RAS_ARG )
+  {
+    FT_UNUSED_RASTER;
+
+    return Raster_Err_Unsupported;
+  }
+
+#endif /* !FT_RASTER_OPTION_ANTI_ALIASING */
+
+
+  static void
+  ft_black_init( PRaster  raster )
+  {
+    FT_UNUSED( raster );
+
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+    FT_UInt  n;
+
+
+    /* set default 5-levels gray palette */
+    for ( n = 0; n < 5; n++ )
+      raster->grays[n] = n * 255 / 4;
+
+    raster->gray_width = RASTER_GRAY_LINES / 2;
+
+#endif
+  }
+
+
+  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
+  /****                         a static object.                  *****/
+
+
+#ifdef _STANDALONE_
+
+
+  static int
+  ft_black_new( void*      memory,
+                FT_Raster  *araster )
+  {
+     static TRaster  the_raster;
+
+
+     *araster = (FT_Raster)&the_raster;
+     FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
+     ft_black_init( &the_raster );
+
+     return 0;
+  }
+
+
+  static void
+  ft_black_done( FT_Raster  raster )
+  {
+    /* nothing */
+    FT_UNUSED( raster );
+  }
+
+
+#else /* _STANDALONE_ */
+
+
+  static int
+  ft_black_new( FT_Memory   memory,
+                PRaster    *araster )
+  {
+    FT_Error  error;
+    PRaster   raster;
+
+
+    *araster = 0;
+    if ( !FT_NEW( raster ) )
+    {
+      raster->memory = memory;
+      ft_black_init( raster );
+
+      *araster = raster;
+    }
+
+    return error;
+  }
+
+
+  static void
+  ft_black_done( PRaster  raster )
+  {
+    FT_Memory  memory = (FT_Memory)raster->memory;
+    FT_FREE( raster );
+  }
+
+
+#endif /* _STANDALONE_ */
+
+
+  static void
+  ft_black_reset( PRaster   raster,
+                  char*     pool_base,
+                  long      pool_size )
+  {
+    if ( raster )
+    {
+      if ( pool_base && pool_size >= (long)sizeof(TWorker) + 2048 )
+      {
+        PWorker  worker = (PWorker)pool_base;
+
+
+        raster->buffer      = pool_base + ( (sizeof ( *worker ) + 7 ) & ~7 );
+        raster->buffer_size = ( ( pool_base + pool_size ) -
+                                (char*)raster->buffer ) / sizeof ( Long );
+        raster->worker      = worker;
+      }
+      else
+      {
+        raster->buffer      = NULL;
+        raster->buffer_size = 0;
+        raster->worker      = NULL;
+      }
+    }
+  }
+
+
+  static void
+  ft_black_set_mode( PRaster            raster,
+                     unsigned long      mode,
+                     const char*        palette )
+  {
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+
+    if ( mode == FT_MAKE_TAG( 'p', 'a', 'l', '5' ) )
+    {
+      /* set 5-levels gray palette */
+      raster->grays[0] = palette[0];
+      raster->grays[1] = palette[1];
+      raster->grays[2] = palette[2];
+      raster->grays[3] = palette[3];
+      raster->grays[4] = palette[4];
+    }
+
+#else
+
+    FT_UNUSED( raster );
+    FT_UNUSED( mode );
+    FT_UNUSED( palette );
+
+#endif
+  }
+
+
+  static int
+  ft_black_render( PRaster                  raster,
+                   const FT_Raster_Params*  params )
+  {
+    const FT_Outline*  outline    = (const FT_Outline*)params->source;
+    const FT_Bitmap*   target_map = params->target;
+    PWorker            worker;
+
+
+    if ( !raster || !raster->buffer || !raster->buffer_size )
+      return Raster_Err_Not_Ini;
+
+    /* return immediately if the outline is empty */
+    if ( outline->n_points == 0 || outline->n_contours <= 0 )
+      return Raster_Err_None;
+
+    if ( !outline || !outline->contours || !outline->points )
+      return Raster_Err_Invalid;
+
+    if ( outline->n_points != outline->contours[outline->n_contours - 1] + 1 )
+      return Raster_Err_Invalid;
+
+    worker = raster->worker;
+
+    /* this version of the raster does not support direct rendering, sorry */
+    if ( params->flags & FT_RASTER_FLAG_DIRECT )
+      return Raster_Err_Unsupported;
+
+    if ( !target_map || !target_map->buffer )
+      return Raster_Err_Invalid;
+
+    ras.outline  = *outline;
+    ras.target   = *target_map;
+
+    worker->buff        = (PLong) raster->buffer;
+    worker->sizeBuff    = worker->buff +
+                            raster->buffer_size / sizeof ( Long );
+#ifdef FT_RASTER_OPTION_ANTI_ALIASING
+    worker->grays       = raster->grays;
+    worker->gray_width  = raster->gray_width;
+#endif
+
+    return ( ( params->flags & FT_RASTER_FLAG_AA )
+               ? Render_Gray_Glyph( RAS_VAR )
+               : Render_Glyph( RAS_VAR ) );
+  }
+
+
+  const FT_Raster_Funcs  ft_standard_raster =
+  {
+    FT_GLYPH_FORMAT_OUTLINE,
+    (FT_Raster_New_Func)     ft_black_new,
+    (FT_Raster_Reset_Func)   ft_black_reset,
+    (FT_Raster_Set_Mode_Func)ft_black_set_mode,
+    (FT_Raster_Render_Func)  ft_black_render,
+    (FT_Raster_Done_Func)    ft_black_done
+  };
+
+
+/* END */