Home | History | Annotate | Download | only in smooth
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  ftgrays.c                                                              */
      4 /*                                                                         */
      5 /*    A new `perfect' anti-aliasing renderer (body).                       */
      6 /*                                                                         */
      7 /*  Copyright 2000-2003, 2005-2013 by                                      */
      8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
      9 /*                                                                         */
     10 /*  This file is part of the FreeType project, and may only be used,       */
     11 /*  modified, and distributed under the terms of the FreeType project      */
     12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
     13 /*  this file you indicate that you have read the license and              */
     14 /*  understand and accept it fully.                                        */
     15 /*                                                                         */
     16 /***************************************************************************/
     17 
     18   /*************************************************************************/
     19   /*                                                                       */
     20   /* This file can be compiled without the rest of the FreeType engine, by */
     21   /* defining the _STANDALONE_ macro when compiling it.  You also need to  */
     22   /* put the files `ftgrays.h' and `ftimage.h' into the current            */
     23   /* compilation directory.  Typically, you could do something like        */
     24   /*                                                                       */
     25   /* - copy `src/smooth/ftgrays.c' (this file) to your current directory   */
     26   /*                                                                       */
     27   /* - copy `include/freetype/ftimage.h' and `src/smooth/ftgrays.h' to the */
     28   /*   same directory                                                      */
     29   /*                                                                       */
     30   /* - compile `ftgrays' with the _STANDALONE_ macro defined, as in        */
     31   /*                                                                       */
     32   /*     cc -c -D_STANDALONE_ ftgrays.c                                    */
     33   /*                                                                       */
     34   /* The renderer can be initialized with a call to                        */
     35   /* `ft_gray_raster.raster_new'; an anti-aliased bitmap can be generated  */
     36   /* with a call to `ft_gray_raster.raster_render'.                        */
     37   /*                                                                       */
     38   /* See the comments and documentation in the file `ftimage.h' for more   */
     39   /* details on how the raster works.                                      */
     40   /*                                                                       */
     41   /*************************************************************************/
     42 
     43   /*************************************************************************/
     44   /*                                                                       */
     45   /* This is a new anti-aliasing scan-converter for FreeType 2.  The       */
     46   /* algorithm used here is _very_ different from the one in the standard  */
     47   /* `ftraster' module.  Actually, `ftgrays' computes the _exact_          */
     48   /* coverage of the outline on each pixel cell.                           */
     49   /*                                                                       */
     50   /* It is based on ideas that I initially found in Raph Levien's          */
     51   /* excellent LibArt graphics library (see http://www.levien.com/libart   */
     52   /* for more information, though the web pages do not tell anything       */
     53   /* about the renderer; you'll have to dive into the source code to       */
     54   /* understand how it works).                                             */
     55   /*                                                                       */
     56   /* Note, however, that this is a _very_ different implementation         */
     57   /* compared to Raph's.  Coverage information is stored in a very         */
     58   /* different way, and I don't use sorted vector paths.  Also, it doesn't */
     59   /* use floating point values.                                            */
     60   /*                                                                       */
     61   /* This renderer has the following advantages:                           */
     62   /*                                                                       */
     63   /* - It doesn't need an intermediate bitmap.  Instead, one can supply a  */
     64   /*   callback function that will be called by the renderer to draw gray  */
     65   /*   spans on any target surface.  You can thus do direct composition on */
     66   /*   any kind of bitmap, provided that you give the renderer the right   */
     67   /*   callback.                                                           */
     68   /*                                                                       */
     69   /* - A perfect anti-aliaser, i.e., it computes the _exact_ coverage on   */
     70   /*   each pixel cell.                                                    */
     71   /*                                                                       */
     72   /* - It performs a single pass on the outline (the `standard' FT2        */
     73   /*   renderer makes two passes).                                         */
     74   /*                                                                       */
     75   /* - It can easily be modified to render to _any_ number of gray levels  */
     76   /*   cheaply.                                                            */
     77   /*                                                                       */
     78   /* - For small (< 20) pixel sizes, it is faster than the standard        */
     79   /*   renderer.                                                           */
     80   /*                                                                       */
     81   /*************************************************************************/
     82 
     83 
     84   /*************************************************************************/
     85   /*                                                                       */
     86   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     87   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     88   /* messages during execution.                                            */
     89   /*                                                                       */
     90 #undef  FT_COMPONENT
     91 #define FT_COMPONENT  trace_smooth
     92 
     93 
     94 #ifdef _STANDALONE_
     95 
     96 
     97   /* Auxiliary macros for token concatenation. */
     98 #define FT_ERR_XCAT( x, y )  x ## y
     99 #define FT_ERR_CAT( x, y )   FT_ERR_XCAT( x, y )
    100 
    101 
    102   /* define this to dump debugging information */
    103 /* #define FT_DEBUG_LEVEL_TRACE */
    104 
    105 
    106 #ifdef FT_DEBUG_LEVEL_TRACE
    107 #include <stdio.h>
    108 #include <stdarg.h>
    109 #endif
    110 
    111 #include <stddef.h>
    112 #include <string.h>
    113 #include <setjmp.h>
    114 #include <limits.h>
    115 #define FT_UINT_MAX  UINT_MAX
    116 #define FT_INT_MAX   INT_MAX
    117 
    118 #define ft_memset   memset
    119 
    120 #define ft_setjmp   setjmp
    121 #define ft_longjmp  longjmp
    122 #define ft_jmp_buf  jmp_buf
    123 
    124 typedef ptrdiff_t  FT_PtrDist;
    125 
    126 
    127 #define ErrRaster_Invalid_Mode      -2
    128 #define ErrRaster_Invalid_Outline   -1
    129 #define ErrRaster_Invalid_Argument  -3
    130 #define ErrRaster_Memory_Overflow   -4
    131 
    132 #define FT_BEGIN_HEADER
    133 #define FT_END_HEADER
    134 
    135 #include "ftimage.h"
    136 #include "ftgrays.h"
    137 
    138 
    139   /* This macro is used to indicate that a function parameter is unused. */
    140   /* Its purpose is simply to reduce compiler warnings.  Note also that  */
    141   /* simply defining it as `(void)x' doesn't avoid warnings with certain */
    142   /* ANSI compilers (e.g. LCC).                                          */
    143 #define FT_UNUSED( x )  (x) = (x)
    144 
    145 
    146   /* we only use level 5 & 7 tracing messages; cf. ftdebug.h */
    147 
    148 #ifdef FT_DEBUG_LEVEL_TRACE
    149 
    150   void
    151   FT_Message( const char*  fmt,
    152               ... )
    153   {
    154     va_list  ap;
    155 
    156 
    157     va_start( ap, fmt );
    158     vfprintf( stderr, fmt, ap );
    159     va_end( ap );
    160   }
    161 
    162 
    163   /* empty function useful for setting a breakpoint to catch errors */
    164   int
    165   FT_Throw( int          error,
    166             int          line,
    167             const char*  file )
    168   {
    169     FT_UNUSED( error );
    170     FT_UNUSED( line );
    171     FT_UNUSED( file );
    172 
    173     return 0;
    174   }
    175 
    176 
    177   /* we don't handle tracing levels in stand-alone mode; */
    178 #ifndef FT_TRACE5
    179 #define FT_TRACE5( varformat )  FT_Message varformat
    180 #endif
    181 #ifndef FT_TRACE7
    182 #define FT_TRACE7( varformat )  FT_Message varformat
    183 #endif
    184 #ifndef FT_ERROR
    185 #define FT_ERROR( varformat )   FT_Message varformat
    186 #endif
    187 
    188 #define FT_THROW( e )                               \
    189           ( FT_Throw( FT_ERR_CAT( ErrRaster, e ),   \
    190                       __LINE__,                     \
    191                       __FILE__ )                  | \
    192             FT_ERR_CAT( ErrRaster, e )            )
    193 
    194 #else /* !FT_DEBUG_LEVEL_TRACE */
    195 
    196 #define FT_TRACE5( x )  do { } while ( 0 )     /* nothing */
    197 #define FT_TRACE7( x )  do { } while ( 0 )     /* nothing */
    198 #define FT_ERROR( x )   do { } while ( 0 )     /* nothing */
    199 #define FT_THROW( e )   FT_ERR_CAT( ErrRaster_, e )
    200 
    201 
    202 #endif /* !FT_DEBUG_LEVEL_TRACE */
    203 
    204 
    205 #define FT_DEFINE_OUTLINE_FUNCS( class_,               \
    206                                  move_to_, line_to_,   \
    207                                  conic_to_, cubic_to_, \
    208                                  shift_, delta_ )      \
    209           static const FT_Outline_Funcs class_ =       \
    210           {                                            \
    211             move_to_,                                  \
    212             line_to_,                                  \
    213             conic_to_,                                 \
    214             cubic_to_,                                 \
    215             shift_,                                    \
    216             delta_                                     \
    217          };
    218 
    219 #define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_,            \
    220                                 raster_new_, raster_reset_,       \
    221                                 raster_set_mode_, raster_render_, \
    222                                 raster_done_ )                    \
    223           const FT_Raster_Funcs class_ =                          \
    224           {                                                       \
    225             glyph_format_,                                        \
    226             raster_new_,                                          \
    227             raster_reset_,                                        \
    228             raster_set_mode_,                                     \
    229             raster_render_,                                       \
    230             raster_done_                                          \
    231          };
    232 
    233 
    234 #else /* !_STANDALONE_ */
    235 
    236 
    237 #include "../../include/ft2build.h"
    238 #include "ftgrays.h"
    239 #include "../../include/freetype/internal/ftobjs.h"
    240 #include "../../include/freetype/internal/ftdebug.h"
    241 #include "../../include/freetype/ftoutln.h"
    242 
    243 #include "ftsmerrs.h"
    244 
    245 #include "ftspic.h"
    246 
    247 #define Smooth_Err_Invalid_Mode     Smooth_Err_Cannot_Render_Glyph
    248 #define Smooth_Err_Memory_Overflow  Smooth_Err_Out_Of_Memory
    249 #define ErrRaster_Memory_Overflow   Smooth_Err_Out_Of_Memory
    250 
    251 
    252 #endif /* !_STANDALONE_ */
    253 
    254 
    255 #ifndef FT_MEM_SET
    256 #define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
    257 #endif
    258 
    259 #ifndef FT_MEM_ZERO
    260 #define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
    261 #endif
    262 
    263   /* as usual, for the speed hungry :-) */
    264 
    265 #undef RAS_ARG
    266 #undef RAS_ARG_
    267 #undef RAS_VAR
    268 #undef RAS_VAR_
    269 
    270 #ifndef FT_STATIC_RASTER
    271 
    272 #define RAS_ARG   gray_PWorker  worker
    273 #define RAS_ARG_  gray_PWorker  worker,
    274 
    275 #define RAS_VAR   worker
    276 #define RAS_VAR_  worker,
    277 
    278 #else /* FT_STATIC_RASTER */
    279 
    280 #define RAS_ARG   /* empty */
    281 #define RAS_ARG_  /* empty */
    282 #define RAS_VAR   /* empty */
    283 #define RAS_VAR_  /* empty */
    284 
    285 #endif /* FT_STATIC_RASTER */
    286 
    287 
    288   /* must be at least 6 bits! */
    289 #define PIXEL_BITS  8
    290 
    291 #undef FLOOR
    292 #undef CEILING
    293 #undef TRUNC
    294 #undef SCALED
    295 
    296 #define ONE_PIXEL       ( 1L << PIXEL_BITS )
    297 #define PIXEL_MASK      ( -1L << PIXEL_BITS )
    298 #define TRUNC( x )      ( (TCoord)( (x) >> PIXEL_BITS ) )
    299 #define SUBPIXELS( x )  ( (TPos)(x) << PIXEL_BITS )
    300 #define FLOOR( x )      ( (x) & -ONE_PIXEL )
    301 #define CEILING( x )    ( ( (x) + ONE_PIXEL - 1 ) & -ONE_PIXEL )
    302 #define ROUND( x )      ( ( (x) + ONE_PIXEL / 2 ) & -ONE_PIXEL )
    303 
    304 #if PIXEL_BITS >= 6
    305 #define UPSCALE( x )    ( (x) << ( PIXEL_BITS - 6 ) )
    306 #define DOWNSCALE( x )  ( (x) >> ( PIXEL_BITS - 6 ) )
    307 #else
    308 #define UPSCALE( x )    ( (x) >> ( 6 - PIXEL_BITS ) )
    309 #define DOWNSCALE( x )  ( (x) << ( 6 - PIXEL_BITS ) )
    310 #endif
    311 
    312 
    313   /*************************************************************************/
    314   /*                                                                       */
    315   /*   TYPE DEFINITIONS                                                    */
    316   /*                                                                       */
    317 
    318   /* don't change the following types to FT_Int or FT_Pos, since we might */
    319   /* need to define them to "float" or "double" when experimenting with   */
    320   /* new algorithms                                                       */
    321 
    322   typedef long  TCoord;   /* integer scanline/pixel coordinate */
    323   typedef long  TPos;     /* sub-pixel coordinate              */
    324 
    325   /* determine the type used to store cell areas.  This normally takes at */
    326   /* least PIXEL_BITS*2 + 1 bits.  On 16-bit systems, we need to use      */
    327   /* `long' instead of `int', otherwise bad things happen                 */
    328 
    329 #if PIXEL_BITS <= 7
    330 
    331   typedef int  TArea;
    332 
    333 #else /* PIXEL_BITS >= 8 */
    334 
    335   /* approximately determine the size of integers using an ANSI-C header */
    336 #if FT_UINT_MAX == 0xFFFFU
    337   typedef long  TArea;
    338 #else
    339   typedef int   TArea;
    340 #endif
    341 
    342 #endif /* PIXEL_BITS >= 8 */
    343 
    344 
    345   /* maximum number of gray spans in a call to the span callback */
    346 #define FT_MAX_GRAY_SPANS  32
    347 
    348 
    349   typedef struct TCell_*  PCell;
    350 
    351   typedef struct  TCell_
    352   {
    353     TPos    x;     /* same with gray_TWorker.ex    */
    354     TCoord  cover; /* same with gray_TWorker.cover */
    355     TArea   area;
    356     PCell   next;
    357 
    358   } TCell;
    359 
    360 
    361 #if defined( _MSC_VER )      /* Visual C++ (and Intel C++) */
    362   /* We disable the warning `structure was padded due to   */
    363   /* __declspec(align())' in order to compile cleanly with */
    364   /* the maximum level of warnings.                        */
    365 #pragma warning( push )
    366 #pragma warning( disable : 4324 )
    367 #endif /* _MSC_VER */
    368 
    369   typedef struct  gray_TWorker_
    370   {
    371     TCoord  ex, ey;
    372     TPos    min_ex, max_ex;
    373     TPos    min_ey, max_ey;
    374     TPos    count_ex, count_ey;
    375 
    376     TArea   area;
    377     TCoord  cover;
    378     int     invalid;
    379 
    380     PCell       cells;
    381     FT_PtrDist  max_cells;
    382     FT_PtrDist  num_cells;
    383 
    384     TCoord  cx, cy;
    385     TPos    x,  y;
    386 
    387     TPos    last_ey;
    388 
    389     FT_Vector   bez_stack[32 * 3 + 1];
    390     int         lev_stack[32];
    391 
    392     FT_Outline  outline;
    393     FT_Bitmap   target;
    394     FT_BBox     clip_box;
    395 
    396     FT_Span     gray_spans[FT_MAX_GRAY_SPANS];
    397     int         num_gray_spans;
    398 
    399     FT_Raster_Span_Func  render_span;
    400     void*                render_span_data;
    401     int                  span_y;
    402 
    403     int  band_size;
    404     int  band_shoot;
    405 
    406     ft_jmp_buf  jump_buffer;
    407 
    408     void*       buffer;
    409     long        buffer_size;
    410 
    411     PCell*     ycells;
    412     TPos       ycount;
    413 
    414   } gray_TWorker, *gray_PWorker;
    415 
    416 #if defined( _MSC_VER )
    417 #pragma warning( pop )
    418 #endif
    419 
    420 
    421 #ifndef FT_STATIC_RASTER
    422 #define ras  (*worker)
    423 #else
    424   static gray_TWorker  ras;
    425 #endif
    426 
    427 
    428   typedef struct gray_TRaster_
    429   {
    430     void*         buffer;
    431     long          buffer_size;
    432     int           band_size;
    433     void*         memory;
    434     gray_PWorker  worker;
    435 
    436   } gray_TRaster, *gray_PRaster;
    437 
    438 
    439 
    440   /*************************************************************************/
    441   /*                                                                       */
    442   /* Initialize the cells table.                                           */
    443   /*                                                                       */
    444   static void
    445   gray_init_cells( RAS_ARG_ void*  buffer,
    446                    long            byte_size )
    447   {
    448     ras.buffer      = buffer;
    449     ras.buffer_size = byte_size;
    450 
    451     ras.ycells      = (PCell*) buffer;
    452     ras.cells       = NULL;
    453     ras.max_cells   = 0;
    454     ras.num_cells   = 0;
    455     ras.area        = 0;
    456     ras.cover       = 0;
    457     ras.invalid     = 1;
    458   }
    459 
    460 
    461   /*************************************************************************/
    462   /*                                                                       */
    463   /* Compute the outline bounding box.                                     */
    464   /*                                                                       */
    465   static void
    466   gray_compute_cbox( RAS_ARG )
    467   {
    468     FT_Outline*  outline = &ras.outline;
    469     FT_Vector*   vec     = outline->points;
    470     FT_Vector*   limit   = vec + outline->n_points;
    471 
    472 
    473     if ( outline->n_points <= 0 )
    474     {
    475       ras.min_ex = ras.max_ex = 0;
    476       ras.min_ey = ras.max_ey = 0;
    477       return;
    478     }
    479 
    480     ras.min_ex = ras.max_ex = vec->x;
    481     ras.min_ey = ras.max_ey = vec->y;
    482 
    483     vec++;
    484 
    485     for ( ; vec < limit; vec++ )
    486     {
    487       TPos  x = vec->x;
    488       TPos  y = vec->y;
    489 
    490 
    491       if ( x < ras.min_ex ) ras.min_ex = x;
    492       if ( x > ras.max_ex ) ras.max_ex = x;
    493       if ( y < ras.min_ey ) ras.min_ey = y;
    494       if ( y > ras.max_ey ) ras.max_ey = y;
    495     }
    496 
    497     /* truncate the bounding box to integer pixels */
    498     ras.min_ex = ras.min_ex >> 6;
    499     ras.min_ey = ras.min_ey >> 6;
    500     ras.max_ex = ( ras.max_ex + 63 ) >> 6;
    501     ras.max_ey = ( ras.max_ey + 63 ) >> 6;
    502   }
    503 
    504 
    505   /*************************************************************************/
    506   /*                                                                       */
    507   /* Record the current cell in the table.                                 */
    508   /*                                                                       */
    509   static PCell
    510   gray_find_cell( RAS_ARG )
    511   {
    512     PCell  *pcell, cell;
    513     TPos    x = ras.ex;
    514 
    515 
    516     if ( x > ras.count_ex )
    517       x = ras.count_ex;
    518 
    519     pcell = &ras.ycells[ras.ey];
    520     for (;;)
    521     {
    522       cell = *pcell;
    523       if ( cell == NULL || cell->x > x )
    524         break;
    525 
    526       if ( cell->x == x )
    527         goto Exit;
    528 
    529       pcell = &cell->next;
    530     }
    531 
    532     if ( ras.num_cells >= ras.max_cells )
    533       ft_longjmp( ras.jump_buffer, 1 );
    534 
    535     cell        = ras.cells + ras.num_cells++;
    536     cell->x     = x;
    537     cell->area  = 0;
    538     cell->cover = 0;
    539 
    540     cell->next  = *pcell;
    541     *pcell      = cell;
    542 
    543   Exit:
    544     return cell;
    545   }
    546 
    547 
    548   static void
    549   gray_record_cell( RAS_ARG )
    550   {
    551     if ( !ras.invalid && ( ras.area | ras.cover ) )
    552     {
    553       PCell  cell = gray_find_cell( RAS_VAR );
    554 
    555 
    556       cell->area  += ras.area;
    557       cell->cover += ras.cover;
    558     }
    559   }
    560 
    561 
    562   /*************************************************************************/
    563   /*                                                                       */
    564   /* Set the current cell to a new position.                               */
    565   /*                                                                       */
    566   static void
    567   gray_set_cell( RAS_ARG_ TCoord  ex,
    568                           TCoord  ey )
    569   {
    570     /* Move the cell pointer to a new position.  We set the `invalid'      */
    571     /* flag to indicate that the cell isn't part of those we're interested */
    572     /* in during the render phase.  This means that:                       */
    573     /*                                                                     */
    574     /* . the new vertical position must be within min_ey..max_ey-1.        */
    575     /* . the new horizontal position must be strictly less than max_ex     */
    576     /*                                                                     */
    577     /* Note that if a cell is to the left of the clipping region, it is    */
    578     /* actually set to the (min_ex-1) horizontal position.                 */
    579 
    580     /* All cells that are on the left of the clipping region go to the */
    581     /* min_ex - 1 horizontal position.                                 */
    582     ey -= ras.min_ey;
    583 
    584     if ( ex > ras.max_ex )
    585       ex = ras.max_ex;
    586 
    587     ex -= ras.min_ex;
    588     if ( ex < 0 )
    589       ex = -1;
    590 
    591     /* are we moving to a different cell ? */
    592     if ( ex != ras.ex || ey != ras.ey )
    593     {
    594       /* record the current one if it is valid */
    595       if ( !ras.invalid )
    596         gray_record_cell( RAS_VAR );
    597 
    598       ras.area  = 0;
    599       ras.cover = 0;
    600     }
    601 
    602     ras.ex      = ex;
    603     ras.ey      = ey;
    604     ras.invalid = ( (unsigned)ey >= (unsigned)ras.count_ey ||
    605                               ex >= ras.count_ex           );
    606   }
    607 
    608 
    609   /*************************************************************************/
    610   /*                                                                       */
    611   /* Start a new contour at a given cell.                                  */
    612   /*                                                                       */
    613   static void
    614   gray_start_cell( RAS_ARG_ TCoord  ex,
    615                             TCoord  ey )
    616   {
    617     if ( ex > ras.max_ex )
    618       ex = (TCoord)( ras.max_ex );
    619 
    620     if ( ex < ras.min_ex )
    621       ex = (TCoord)( ras.min_ex - 1 );
    622 
    623     ras.area    = 0;
    624     ras.cover   = 0;
    625     ras.ex      = ex - ras.min_ex;
    626     ras.ey      = ey - ras.min_ey;
    627     ras.last_ey = SUBPIXELS( ey );
    628     ras.invalid = 0;
    629 
    630     gray_set_cell( RAS_VAR_ ex, ey );
    631   }
    632 
    633 
    634   /*************************************************************************/
    635   /*                                                                       */
    636   /* Render a scanline as one or more cells.                               */
    637   /*                                                                       */
    638   static void
    639   gray_render_scanline( RAS_ARG_ TCoord  ey,
    640                                  TPos    x1,
    641                                  TCoord  y1,
    642                                  TPos    x2,
    643                                  TCoord  y2 )
    644   {
    645     TCoord  ex1, ex2, fx1, fx2, delta, mod;
    646     long    p, first, dx;
    647     int     incr;
    648 
    649 
    650     dx = x2 - x1;
    651 
    652     ex1 = TRUNC( x1 );
    653     ex2 = TRUNC( x2 );
    654     fx1 = (TCoord)( x1 - SUBPIXELS( ex1 ) );
    655     fx2 = (TCoord)( x2 - SUBPIXELS( ex2 ) );
    656 
    657     /* trivial case.  Happens often */
    658     if ( y1 == y2 )
    659     {
    660       gray_set_cell( RAS_VAR_ ex2, ey );
    661       return;
    662     }
    663 
    664     /* everything is located in a single cell.  That is easy! */
    665     /*                                                        */
    666     if ( ex1 == ex2 )
    667     {
    668       delta      = y2 - y1;
    669       ras.area  += (TArea)(( fx1 + fx2 ) * delta);
    670       ras.cover += delta;
    671       return;
    672     }
    673 
    674     /* ok, we'll have to render a run of adjacent cells on the same */
    675     /* scanline...                                                  */
    676     /*                                                              */
    677     p     = ( ONE_PIXEL - fx1 ) * ( y2 - y1 );
    678     first = ONE_PIXEL;
    679     incr  = 1;
    680 
    681     if ( dx < 0 )
    682     {
    683       p     = fx1 * ( y2 - y1 );
    684       first = 0;
    685       incr  = -1;
    686       dx    = -dx;
    687     }
    688 
    689     delta = (TCoord)( p / dx );
    690     mod   = (TCoord)( p % dx );
    691     if ( mod < 0 )
    692     {
    693       delta--;
    694       mod += (TCoord)dx;
    695     }
    696 
    697     ras.area  += (TArea)(( fx1 + first ) * delta);
    698     ras.cover += delta;
    699 
    700     ex1 += incr;
    701     gray_set_cell( RAS_VAR_ ex1, ey );
    702     y1  += delta;
    703 
    704     if ( ex1 != ex2 )
    705     {
    706       TCoord  lift, rem;
    707 
    708 
    709       p    = ONE_PIXEL * ( y2 - y1 + delta );
    710       lift = (TCoord)( p / dx );
    711       rem  = (TCoord)( p % dx );
    712       if ( rem < 0 )
    713       {
    714         lift--;
    715         rem += (TCoord)dx;
    716       }
    717 
    718       mod -= (int)dx;
    719 
    720       while ( ex1 != ex2 )
    721       {
    722         delta = lift;
    723         mod  += rem;
    724         if ( mod >= 0 )
    725         {
    726           mod -= (TCoord)dx;
    727           delta++;
    728         }
    729 
    730         ras.area  += (TArea)(ONE_PIXEL * delta);
    731         ras.cover += delta;
    732         y1        += delta;
    733         ex1       += incr;
    734         gray_set_cell( RAS_VAR_ ex1, ey );
    735       }
    736     }
    737 
    738     delta      = y2 - y1;
    739     ras.area  += (TArea)(( fx2 + ONE_PIXEL - first ) * delta);
    740     ras.cover += delta;
    741   }
    742 
    743 
    744   /*************************************************************************/
    745   /*                                                                       */
    746   /* Render a given line as a series of scanlines.                         */
    747   /*                                                                       */
    748   static void
    749   gray_render_line( RAS_ARG_ TPos  to_x,
    750                              TPos  to_y )
    751   {
    752     TCoord  ey1, ey2, fy1, fy2, mod;
    753     TPos    dx, dy, x, x2;
    754     long    p, first;
    755     int     delta, rem, lift, incr;
    756 
    757 
    758     ey1 = TRUNC( ras.last_ey );
    759     ey2 = TRUNC( to_y );     /* if (ey2 >= ras.max_ey) ey2 = ras.max_ey-1; */
    760     fy1 = (TCoord)( ras.y - ras.last_ey );
    761     fy2 = (TCoord)( to_y - SUBPIXELS( ey2 ) );
    762 
    763     dx = to_x - ras.x;
    764     dy = to_y - ras.y;
    765 
    766     /* XXX: we should do something about the trivial case where dx == 0, */
    767     /*      as it happens very often!                                    */
    768 
    769     /* perform vertical clipping */
    770     {
    771       TCoord  min, max;
    772 
    773 
    774       min = ey1;
    775       max = ey2;
    776       if ( ey1 > ey2 )
    777       {
    778         min = ey2;
    779         max = ey1;
    780       }
    781       if ( min >= ras.max_ey || max < ras.min_ey )
    782         goto End;
    783     }
    784 
    785     /* everything is on a single scanline */
    786     if ( ey1 == ey2 )
    787     {
    788       gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, to_x, fy2 );
    789       goto End;
    790     }
    791 
    792     /* vertical line - avoid calling gray_render_scanline */
    793     incr = 1;
    794 
    795     if ( dx == 0 )
    796     {
    797       TCoord  ex     = TRUNC( ras.x );
    798       TCoord  two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 );
    799       TArea   area;
    800 
    801 
    802       first = ONE_PIXEL;
    803       if ( dy < 0 )
    804       {
    805         first = 0;
    806         incr  = -1;
    807       }
    808 
    809       delta      = (int)( first - fy1 );
    810       ras.area  += (TArea)two_fx * delta;
    811       ras.cover += delta;
    812       ey1       += incr;
    813 
    814       gray_set_cell( RAS_VAR_ ex, ey1 );
    815 
    816       delta = (int)( first + first - ONE_PIXEL );
    817       area  = (TArea)two_fx * delta;
    818       while ( ey1 != ey2 )
    819       {
    820         ras.area  += area;
    821         ras.cover += delta;
    822         ey1       += incr;
    823 
    824         gray_set_cell( RAS_VAR_ ex, ey1 );
    825       }
    826 
    827       delta      = (int)( fy2 - ONE_PIXEL + first );
    828       ras.area  += (TArea)two_fx * delta;
    829       ras.cover += delta;
    830 
    831       goto End;
    832     }
    833 
    834     /* ok, we have to render several scanlines */
    835     p     = ( ONE_PIXEL - fy1 ) * dx;
    836     first = ONE_PIXEL;
    837     incr  = 1;
    838 
    839     if ( dy < 0 )
    840     {
    841       p     = fy1 * dx;
    842       first = 0;
    843       incr  = -1;
    844       dy    = -dy;
    845     }
    846 
    847     delta = (int)( p / dy );
    848     mod   = (int)( p % dy );
    849     if ( mod < 0 )
    850     {
    851       delta--;
    852       mod += (TCoord)dy;
    853     }
    854 
    855     x = ras.x + delta;
    856     gray_render_scanline( RAS_VAR_ ey1, ras.x, fy1, x, (TCoord)first );
    857 
    858     ey1 += incr;
    859     gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
    860 
    861     if ( ey1 != ey2 )
    862     {
    863       p     = ONE_PIXEL * dx;
    864       lift  = (int)( p / dy );
    865       rem   = (int)( p % dy );
    866       if ( rem < 0 )
    867       {
    868         lift--;
    869         rem += (int)dy;
    870       }
    871       mod -= (int)dy;
    872 
    873       while ( ey1 != ey2 )
    874       {
    875         delta = lift;
    876         mod  += rem;
    877         if ( mod >= 0 )
    878         {
    879           mod -= (int)dy;
    880           delta++;
    881         }
    882 
    883         x2 = x + delta;
    884         gray_render_scanline( RAS_VAR_ ey1, x,
    885                                        (TCoord)( ONE_PIXEL - first ), x2,
    886                                        (TCoord)first );
    887         x = x2;
    888 
    889         ey1 += incr;
    890         gray_set_cell( RAS_VAR_ TRUNC( x ), ey1 );
    891       }
    892     }
    893 
    894     gray_render_scanline( RAS_VAR_ ey1, x,
    895                                    (TCoord)( ONE_PIXEL - first ), to_x,
    896                                    fy2 );
    897 
    898   End:
    899     ras.x       = to_x;
    900     ras.y       = to_y;
    901     ras.last_ey = SUBPIXELS( ey2 );
    902   }
    903 
    904 
    905   static void
    906   gray_split_conic( FT_Vector*  base )
    907   {
    908     TPos  a, b;
    909 
    910 
    911     base[4].x = base[2].x;
    912     b = base[1].x;
    913     a = base[3].x = ( base[2].x + b ) / 2;
    914     b = base[1].x = ( base[0].x + b ) / 2;
    915     base[2].x = ( a + b ) / 2;
    916 
    917     base[4].y = base[2].y;
    918     b = base[1].y;
    919     a = base[3].y = ( base[2].y + b ) / 2;
    920     b = base[1].y = ( base[0].y + b ) / 2;
    921     base[2].y = ( a + b ) / 2;
    922   }
    923 
    924 
    925   static void
    926   gray_render_conic( RAS_ARG_ const FT_Vector*  control,
    927                               const FT_Vector*  to )
    928   {
    929     TPos        dx, dy;
    930     TPos        min, max, y;
    931     int         top, level;
    932     int*        levels;
    933     FT_Vector*  arc;
    934 
    935 
    936     levels = ras.lev_stack;
    937 
    938     arc      = ras.bez_stack;
    939     arc[0].x = UPSCALE( to->x );
    940     arc[0].y = UPSCALE( to->y );
    941     arc[1].x = UPSCALE( control->x );
    942     arc[1].y = UPSCALE( control->y );
    943     arc[2].x = ras.x;
    944     arc[2].y = ras.y;
    945     top      = 0;
    946 
    947     dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
    948     dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
    949     if ( dx < dy )
    950       dx = dy;
    951 
    952     if ( dx < ONE_PIXEL / 4 )
    953       goto Draw;
    954 
    955     /* short-cut the arc that crosses the current band */
    956     min = max = arc[0].y;
    957 
    958     y = arc[1].y;
    959     if ( y < min ) min = y;
    960     if ( y > max ) max = y;
    961 
    962     y = arc[2].y;
    963     if ( y < min ) min = y;
    964     if ( y > max ) max = y;
    965 
    966     if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
    967       goto Draw;
    968 
    969     level = 0;
    970     do
    971     {
    972       dx >>= 2;
    973       level++;
    974     } while ( dx > ONE_PIXEL / 4 );
    975 
    976     levels[0] = level;
    977 
    978     do
    979     {
    980       level = levels[top];
    981       if ( level > 0 )
    982       {
    983         gray_split_conic( arc );
    984         arc += 2;
    985         top++;
    986         levels[top] = levels[top - 1] = level - 1;
    987         continue;
    988       }
    989 
    990     Draw:
    991       gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
    992       top--;
    993       arc -= 2;
    994 
    995     } while ( top >= 0 );
    996   }
    997 
    998 
    999   static void
   1000   gray_split_cubic( FT_Vector*  base )
   1001   {
   1002     TPos  a, b, c, d;
   1003 
   1004 
   1005     base[6].x = base[3].x;
   1006     c = base[1].x;
   1007     d = base[2].x;
   1008     base[1].x = a = ( base[0].x + c ) / 2;
   1009     base[5].x = b = ( base[3].x + d ) / 2;
   1010     c = ( c + d ) / 2;
   1011     base[2].x = a = ( a + c ) / 2;
   1012     base[4].x = b = ( b + c ) / 2;
   1013     base[3].x = ( a + b ) / 2;
   1014 
   1015     base[6].y = base[3].y;
   1016     c = base[1].y;
   1017     d = base[2].y;
   1018     base[1].y = a = ( base[0].y + c ) / 2;
   1019     base[5].y = b = ( base[3].y + d ) / 2;
   1020     c = ( c + d ) / 2;
   1021     base[2].y = a = ( a + c ) / 2;
   1022     base[4].y = b = ( b + c ) / 2;
   1023     base[3].y = ( a + b ) / 2;
   1024   }
   1025 
   1026 
   1027   static void
   1028   gray_render_cubic( RAS_ARG_ const FT_Vector*  control1,
   1029                               const FT_Vector*  control2,
   1030                               const FT_Vector*  to )
   1031   {
   1032     FT_Vector*  arc;
   1033     TPos        min, max, y;
   1034 
   1035 
   1036     arc      = ras.bez_stack;
   1037     arc[0].x = UPSCALE( to->x );
   1038     arc[0].y = UPSCALE( to->y );
   1039     arc[1].x = UPSCALE( control2->x );
   1040     arc[1].y = UPSCALE( control2->y );
   1041     arc[2].x = UPSCALE( control1->x );
   1042     arc[2].y = UPSCALE( control1->y );
   1043     arc[3].x = ras.x;
   1044     arc[3].y = ras.y;
   1045 
   1046     /* Short-cut the arc that crosses the current band. */
   1047     min = max = arc[0].y;
   1048 
   1049     y = arc[1].y;
   1050     if ( y < min )
   1051       min = y;
   1052     if ( y > max )
   1053       max = y;
   1054 
   1055     y = arc[2].y;
   1056     if ( y < min )
   1057       min = y;
   1058     if ( y > max )
   1059       max = y;
   1060 
   1061     y = arc[3].y;
   1062     if ( y < min )
   1063       min = y;
   1064     if ( y > max )
   1065       max = y;
   1066 
   1067     if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
   1068       goto Draw;
   1069 
   1070     for (;;)
   1071     {
   1072       /* Decide whether to split or draw. See `Rapid Termination          */
   1073       /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
   1074       /* F. Hain, at                                                      */
   1075       /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
   1076 
   1077       {
   1078         TPos  dx, dy, dx_, dy_;
   1079         TPos  dx1, dy1, dx2, dy2;
   1080         TPos  L, s, s_limit;
   1081 
   1082 
   1083         /* dx and dy are x and y components of the P0-P3 chord vector. */
   1084         dx = arc[3].x - arc[0].x;
   1085         dy = arc[3].y - arc[0].y;
   1086 
   1087         /* L is an (under)estimate of the Euclidean distance P0-P3.       */
   1088         /*                                                                */
   1089         /* If dx >= dy, then r = sqrt(dx^2 + dy^2) can be overestimated   */
   1090         /* with least maximum error by                                    */
   1091         /*                                                                */
   1092         /*   r_upperbound = dx + (sqrt(2) - 1) * dy  ,                    */
   1093         /*                                                                */
   1094         /* where sqrt(2) - 1 can be (over)estimated by 107/256, giving an */
   1095         /* error of no more than 8.4%.                                    */
   1096         /*                                                                */
   1097         /* Similarly, some elementary calculus shows that r can be        */
   1098         /* underestimated with least maximum error by                     */
   1099         /*                                                                */
   1100         /*   r_lowerbound = sqrt(2 + sqrt(2)) / 2 * dx                    */
   1101         /*                  + sqrt(2 - sqrt(2)) / 2 * dy  .               */
   1102         /*                                                                */
   1103         /* 236/256 and 97/256 are (under)estimates of the two algebraic   */
   1104         /* numbers, giving an error of no more than 8.1%.                 */
   1105 
   1106         dx_ = FT_ABS( dx );
   1107         dy_ = FT_ABS( dy );
   1108 
   1109         /* This is the same as                     */
   1110         /*                                         */
   1111         /*   L = ( 236 * FT_MAX( dx_, dy_ )        */
   1112         /*       + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */
   1113         L = ( dx_ > dy_ ? 236 * dx_ +  97 * dy_
   1114                         :  97 * dx_ + 236 * dy_ ) >> 8;
   1115 
   1116         /* Avoid possible arithmetic overflow below by splitting. */
   1117         if ( L > 32767 )
   1118           goto Split;
   1119 
   1120         /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
   1121         s_limit = L * (TPos)( ONE_PIXEL / 6 );
   1122 
   1123         /* s is L * the perpendicular distance from P1 to the line P0-P3. */
   1124         dx1 = arc[1].x - arc[0].x;
   1125         dy1 = arc[1].y - arc[0].y;
   1126         s = FT_ABS( dy * dx1 - dx * dy1 );
   1127 
   1128         if ( s > s_limit )
   1129           goto Split;
   1130 
   1131         /* s is L * the perpendicular distance from P2 to the line P0-P3. */
   1132         dx2 = arc[2].x - arc[0].x;
   1133         dy2 = arc[2].y - arc[0].y;
   1134         s = FT_ABS( dy * dx2 - dx * dy2 );
   1135 
   1136         if ( s > s_limit )
   1137           goto Split;
   1138 
   1139         /* Split super curvy segments where the off points are so far
   1140            from the chord that the angles P0-P1-P3 or P0-P2-P3 become
   1141            acute as detected by appropriate dot products. */
   1142         if ( dx1 * ( dx1 - dx ) + dy1 * ( dy1 - dy ) > 0 ||
   1143              dx2 * ( dx2 - dx ) + dy2 * ( dy2 - dy ) > 0 )
   1144           goto Split;
   1145 
   1146         /* No reason to split. */
   1147         goto Draw;
   1148       }
   1149 
   1150     Split:
   1151       gray_split_cubic( arc );
   1152       arc += 3;
   1153       continue;
   1154 
   1155     Draw:
   1156       gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
   1157 
   1158       if ( arc == ras.bez_stack )
   1159         return;
   1160 
   1161       arc -= 3;
   1162     }
   1163   }
   1164 
   1165 
   1166   static int
   1167   gray_move_to( const FT_Vector*  to,
   1168                 gray_PWorker      worker )
   1169   {
   1170     TPos  x, y;
   1171 
   1172 
   1173     /* record current cell, if any */
   1174     gray_record_cell( RAS_VAR );
   1175 
   1176     /* start to a new position */
   1177     x = UPSCALE( to->x );
   1178     y = UPSCALE( to->y );
   1179 
   1180     gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
   1181 
   1182     worker->x = x;
   1183     worker->y = y;
   1184     return 0;
   1185   }
   1186 
   1187 
   1188   static int
   1189   gray_line_to( const FT_Vector*  to,
   1190                 gray_PWorker      worker )
   1191   {
   1192     gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
   1193     return 0;
   1194   }
   1195 
   1196 
   1197   static int
   1198   gray_conic_to( const FT_Vector*  control,
   1199                  const FT_Vector*  to,
   1200                  gray_PWorker      worker )
   1201   {
   1202     gray_render_conic( RAS_VAR_ control, to );
   1203     return 0;
   1204   }
   1205 
   1206 
   1207   static int
   1208   gray_cubic_to( const FT_Vector*  control1,
   1209                  const FT_Vector*  control2,
   1210                  const FT_Vector*  to,
   1211                  gray_PWorker      worker )
   1212   {
   1213     gray_render_cubic( RAS_VAR_ control1, control2, to );
   1214     return 0;
   1215   }
   1216 
   1217 
   1218   static void
   1219   gray_render_span( int             y,
   1220                     int             count,
   1221                     const FT_Span*  spans,
   1222                     gray_PWorker    worker )
   1223   {
   1224     unsigned char*  p;
   1225     FT_Bitmap*      map = &worker->target;
   1226 
   1227 
   1228     /* first of all, compute the scanline offset */
   1229     p = (unsigned char*)map->buffer - y * map->pitch;
   1230     if ( map->pitch >= 0 )
   1231       p += (unsigned)( ( map->rows - 1 ) * map->pitch );
   1232 
   1233     for ( ; count > 0; count--, spans++ )
   1234     {
   1235       unsigned char  coverage = spans->coverage;
   1236 
   1237 
   1238       if ( coverage )
   1239       {
   1240         /* For small-spans it is faster to do it by ourselves than
   1241          * calling `memset'.  This is mainly due to the cost of the
   1242          * function call.
   1243          */
   1244         if ( spans->len >= 8 )
   1245           FT_MEM_SET( p + spans->x, (unsigned char)coverage, spans->len );
   1246         else
   1247         {
   1248           unsigned char*  q = p + spans->x;
   1249 
   1250 
   1251           switch ( spans->len )
   1252           {
   1253           case 7: *q++ = (unsigned char)coverage;
   1254           case 6: *q++ = (unsigned char)coverage;
   1255           case 5: *q++ = (unsigned char)coverage;
   1256           case 4: *q++ = (unsigned char)coverage;
   1257           case 3: *q++ = (unsigned char)coverage;
   1258           case 2: *q++ = (unsigned char)coverage;
   1259           case 1: *q   = (unsigned char)coverage;
   1260           default:
   1261             ;
   1262           }
   1263         }
   1264       }
   1265     }
   1266   }
   1267 
   1268 
   1269   static void
   1270   gray_hline( RAS_ARG_ TCoord  x,
   1271                        TCoord  y,
   1272                        TPos    area,
   1273                        TCoord  acount )
   1274   {
   1275     int  coverage;
   1276 
   1277 
   1278     /* compute the coverage line's coverage, depending on the    */
   1279     /* outline fill rule                                         */
   1280     /*                                                           */
   1281     /* the coverage percentage is area/(PIXEL_BITS*PIXEL_BITS*2) */
   1282     /*                                                           */
   1283     coverage = (int)( area >> ( PIXEL_BITS * 2 + 1 - 8 ) );
   1284                                                     /* use range 0..256 */
   1285     if ( coverage < 0 )
   1286       coverage = -coverage;
   1287 
   1288     if ( ras.outline.flags & FT_OUTLINE_EVEN_ODD_FILL )
   1289     {
   1290       coverage &= 511;
   1291 
   1292       if ( coverage > 256 )
   1293         coverage = 512 - coverage;
   1294       else if ( coverage == 256 )
   1295         coverage = 255;
   1296     }
   1297     else
   1298     {
   1299       /* normal non-zero winding rule */
   1300       if ( coverage >= 256 )
   1301         coverage = 255;
   1302     }
   1303 
   1304     y += (TCoord)ras.min_ey;
   1305     x += (TCoord)ras.min_ex;
   1306 
   1307     /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
   1308     if ( x >= 32767 )
   1309       x = 32767;
   1310 
   1311     /* FT_Span.y is an integer, so limit our coordinates appropriately */
   1312     if ( y >= FT_INT_MAX )
   1313       y = FT_INT_MAX;
   1314 
   1315     if ( coverage )
   1316     {
   1317       FT_Span*  span;
   1318       int       count;
   1319 
   1320 
   1321       /* see whether we can add this span to the current list */
   1322       count = ras.num_gray_spans;
   1323       span  = ras.gray_spans + count - 1;
   1324       if ( count > 0                          &&
   1325            ras.span_y == y                    &&
   1326            (int)span->x + span->len == (int)x &&
   1327            span->coverage == coverage         )
   1328       {
   1329         span->len = (unsigned short)( span->len + acount );
   1330         return;
   1331       }
   1332 
   1333       if ( ras.span_y != y || count >= FT_MAX_GRAY_SPANS )
   1334       {
   1335         if ( ras.render_span && count > 0 )
   1336           ras.render_span( ras.span_y, count, ras.gray_spans,
   1337                            ras.render_span_data );
   1338 
   1339 #ifdef FT_DEBUG_LEVEL_TRACE
   1340 
   1341         if ( count > 0 )
   1342         {
   1343           int  n;
   1344 
   1345 
   1346           FT_TRACE7(( "y = %3d ", ras.span_y ));
   1347           span = ras.gray_spans;
   1348           for ( n = 0; n < count; n++, span++ )
   1349             FT_TRACE7(( "[%d..%d]:%02x ",
   1350                         span->x, span->x + span->len - 1, span->coverage ));
   1351           FT_TRACE7(( "\n" ));
   1352         }
   1353 
   1354 #endif /* FT_DEBUG_LEVEL_TRACE */
   1355 
   1356         ras.num_gray_spans = 0;
   1357         ras.span_y         = (int)y;
   1358 
   1359         count = 0;
   1360         span  = ras.gray_spans;
   1361       }
   1362       else
   1363         span++;
   1364 	  // Fix the Vulnerability Report FoxIT Reader - MSVR-10-0077.
   1365 	  // Limited to the value range of 'x', we have to crop it for avoid the overflow.
   1366 	  if (x < 32768) {
   1367       /* add a gray span to the current list */
   1368       span->x        = (short)x;
   1369       span->len      = (unsigned short)acount;
   1370       span->coverage = (unsigned char)coverage;
   1371 
   1372       ras.num_gray_spans++;
   1373 	  }
   1374     }
   1375   }
   1376 
   1377 
   1378 #ifdef FT_DEBUG_LEVEL_TRACE
   1379 
   1380   /* to be called while in the debugger --                                */
   1381   /* this function causes a compiler warning since it is unused otherwise */
   1382   static void
   1383   gray_dump_cells( RAS_ARG )
   1384   {
   1385     int  yindex;
   1386 
   1387 
   1388     for ( yindex = 0; yindex < ras.ycount; yindex++ )
   1389     {
   1390       PCell  cell;
   1391 
   1392 
   1393       printf( "%3d:", yindex );
   1394 
   1395       for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
   1396         printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area );
   1397       printf( "\n" );
   1398     }
   1399   }
   1400 
   1401 #endif /* FT_DEBUG_LEVEL_TRACE */
   1402 
   1403 
   1404   static void
   1405   gray_sweep( RAS_ARG_ const FT_Bitmap*  target )
   1406   {
   1407     int  yindex;
   1408 
   1409     FT_UNUSED( target );
   1410 
   1411 
   1412     if ( ras.num_cells == 0 )
   1413       return;
   1414 
   1415     ras.num_gray_spans = 0;
   1416 
   1417     FT_TRACE7(( "gray_sweep: start\n" ));
   1418 
   1419     for ( yindex = 0; yindex < ras.ycount; yindex++ )
   1420     {
   1421       PCell   cell  = ras.ycells[yindex];
   1422       TCoord  cover = 0;
   1423       TCoord  x     = 0;
   1424 
   1425 
   1426       for ( ; cell != NULL; cell = cell->next )
   1427       {
   1428         TPos  area;
   1429 
   1430 
   1431         if ( cell->x > x && cover != 0 )
   1432           gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
   1433                       cell->x - x );
   1434 
   1435         cover += cell->cover;
   1436         area   = cover * ( ONE_PIXEL * 2 ) - cell->area;
   1437 
   1438         if ( area != 0 && cell->x >= 0 )
   1439           gray_hline( RAS_VAR_ cell->x, yindex, area, 1 );
   1440 
   1441         x = cell->x + 1;
   1442       }
   1443 
   1444       if ( cover != 0 )
   1445         gray_hline( RAS_VAR_ x, yindex, cover * ( ONE_PIXEL * 2 ),
   1446                     ras.count_ex - x );
   1447     }
   1448 
   1449     if ( ras.render_span && ras.num_gray_spans > 0 )
   1450       ras.render_span( ras.span_y, ras.num_gray_spans,
   1451                        ras.gray_spans, ras.render_span_data );
   1452 
   1453 #ifdef FT_DEBUG_LEVEL_TRACE
   1454 
   1455     if ( ras.num_gray_spans > 0 )
   1456     {
   1457       FT_Span*  span;
   1458       int       n;
   1459 
   1460 
   1461       FT_TRACE7(( "y = %3d ", ras.span_y ));
   1462       span = ras.gray_spans;
   1463       for ( n = 0; n < ras.num_gray_spans; n++, span++ )
   1464         FT_TRACE7(( "[%d..%d]:%02x ",
   1465                     span->x, span->x + span->len - 1, span->coverage ));
   1466       FT_TRACE7(( "\n" ));
   1467     }
   1468 
   1469     FT_TRACE7(( "gray_sweep: end\n" ));
   1470 
   1471 #endif /* FT_DEBUG_LEVEL_TRACE */
   1472 
   1473   }
   1474 
   1475 
   1476 #ifdef _STANDALONE_
   1477 
   1478   /*************************************************************************/
   1479   /*                                                                       */
   1480   /*  The following function should only compile in stand-alone mode,      */
   1481   /*  i.e., when building this component without the rest of FreeType.     */
   1482   /*                                                                       */
   1483   /*************************************************************************/
   1484 
   1485   /*************************************************************************/
   1486   /*                                                                       */
   1487   /* <Function>                                                            */
   1488   /*    FT_Outline_Decompose                                               */
   1489   /*                                                                       */
   1490   /* <Description>                                                         */
   1491   /*    Walk over an outline's structure to decompose it into individual   */
   1492   /*    segments and Bzier arcs.  This function is also able to emit      */
   1493   /*    `move to' and `close to' operations to indicate the start and end  */
   1494   /*    of new contours in the outline.                                    */
   1495   /*                                                                       */
   1496   /* <Input>                                                               */
   1497   /*    outline        :: A pointer to the source target.                  */
   1498   /*                                                                       */
   1499   /*    func_interface :: A table of `emitters', i.e., function pointers   */
   1500   /*                      called during decomposition to indicate path     */
   1501   /*                      operations.                                      */
   1502   /*                                                                       */
   1503   /* <InOut>                                                               */
   1504   /*    user           :: A typeless pointer which is passed to each       */
   1505   /*                      emitter during the decomposition.  It can be     */
   1506   /*                      used to store the state during the               */
   1507   /*                      decomposition.                                   */
   1508   /*                                                                       */
   1509   /* <Return>                                                              */
   1510   /*    Error code.  0 means success.                                      */
   1511   /*                                                                       */
   1512   static int
   1513   FT_Outline_Decompose( const FT_Outline*        outline,
   1514                         const FT_Outline_Funcs*  func_interface,
   1515                         void*                    user )
   1516   {
   1517 #undef SCALED
   1518 #define SCALED( x )  ( ( (x) << shift ) - delta )
   1519 
   1520     FT_Vector   v_last;
   1521     FT_Vector   v_control;
   1522     FT_Vector   v_start;
   1523 
   1524     FT_Vector*  point;
   1525     FT_Vector*  limit;
   1526     char*       tags;
   1527 
   1528     int         error;
   1529 
   1530     int   n;         /* index of contour in outline     */
   1531     int   first;     /* index of first point in contour */
   1532     char  tag;       /* current point's state           */
   1533 
   1534     int   shift;
   1535     TPos  delta;
   1536 
   1537 
   1538     if ( !outline || !func_interface )
   1539       return FT_THROW( Invalid_Argument );
   1540 
   1541     shift = func_interface->shift;
   1542     delta = func_interface->delta;
   1543     first = 0;
   1544 
   1545     for ( n = 0; n < outline->n_contours; n++ )
   1546     {
   1547       int  last;  /* index of last point in contour */
   1548 
   1549 
   1550       FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
   1551 
   1552       last  = outline->contours[n];
   1553       if ( last < 0 )
   1554         goto Invalid_Outline;
   1555       limit = outline->points + last;
   1556 
   1557       v_start   = outline->points[first];
   1558       v_start.x = SCALED( v_start.x );
   1559       v_start.y = SCALED( v_start.y );
   1560 
   1561       v_last   = outline->points[last];
   1562       v_last.x = SCALED( v_last.x );
   1563       v_last.y = SCALED( v_last.y );
   1564 
   1565       v_control = v_start;
   1566 
   1567       point = outline->points + first;
   1568       tags  = outline->tags   + first;
   1569       tag   = FT_CURVE_TAG( tags[0] );
   1570 
   1571       /* A contour cannot start with a cubic control point! */
   1572       if ( tag == FT_CURVE_TAG_CUBIC )
   1573         goto Invalid_Outline;
   1574 
   1575       /* check first point to determine origin */
   1576       if ( tag == FT_CURVE_TAG_CONIC )
   1577       {
   1578         /* first point is conic control.  Yes, this happens. */
   1579         if ( FT_CURVE_TAG( outline->tags[last] ) == FT_CURVE_TAG_ON )
   1580         {
   1581           /* start at last point if it is on the curve */
   1582           v_start = v_last;
   1583           limit--;
   1584         }
   1585         else
   1586         {
   1587           /* if both first and last points are conic,         */
   1588           /* start at their middle and record its position    */
   1589           /* for closure                                      */
   1590           v_start.x = ( v_start.x + v_last.x ) / 2;
   1591           v_start.y = ( v_start.y + v_last.y ) / 2;
   1592 
   1593           v_last = v_start;
   1594         }
   1595         point--;
   1596         tags--;
   1597       }
   1598 
   1599       FT_TRACE5(( "  move to (%.2f, %.2f)\n",
   1600                   v_start.x / 64.0, v_start.y / 64.0 ));
   1601       error = func_interface->move_to( &v_start, user );
   1602       if ( error )
   1603         goto Exit;
   1604 
   1605       while ( point < limit )
   1606       {
   1607         point++;
   1608         tags++;
   1609 
   1610         tag = FT_CURVE_TAG( tags[0] );
   1611         switch ( tag )
   1612         {
   1613         case FT_CURVE_TAG_ON:  /* emit a single line_to */
   1614           {
   1615             FT_Vector  vec;
   1616 
   1617 
   1618             vec.x = SCALED( point->x );
   1619             vec.y = SCALED( point->y );
   1620 
   1621             FT_TRACE5(( "  line to (%.2f, %.2f)\n",
   1622                         vec.x / 64.0, vec.y / 64.0 ));
   1623             error = func_interface->line_to( &vec, user );
   1624             if ( error )
   1625               goto Exit;
   1626             continue;
   1627           }
   1628 
   1629         case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
   1630           v_control.x = SCALED( point->x );
   1631           v_control.y = SCALED( point->y );
   1632 
   1633         Do_Conic:
   1634           if ( point < limit )
   1635           {
   1636             FT_Vector  vec;
   1637             FT_Vector  v_middle;
   1638 
   1639 
   1640             point++;
   1641             tags++;
   1642             tag = FT_CURVE_TAG( tags[0] );
   1643 
   1644             vec.x = SCALED( point->x );
   1645             vec.y = SCALED( point->y );
   1646 
   1647             if ( tag == FT_CURVE_TAG_ON )
   1648             {
   1649               FT_TRACE5(( "  conic to (%.2f, %.2f)"
   1650                           " with control (%.2f, %.2f)\n",
   1651                           vec.x / 64.0, vec.y / 64.0,
   1652                           v_control.x / 64.0, v_control.y / 64.0 ));
   1653               error = func_interface->conic_to( &v_control, &vec, user );
   1654               if ( error )
   1655                 goto Exit;
   1656               continue;
   1657             }
   1658 
   1659             if ( tag != FT_CURVE_TAG_CONIC )
   1660               goto Invalid_Outline;
   1661 
   1662             v_middle.x = ( v_control.x + vec.x ) / 2;
   1663             v_middle.y = ( v_control.y + vec.y ) / 2;
   1664 
   1665             FT_TRACE5(( "  conic to (%.2f, %.2f)"
   1666                         " with control (%.2f, %.2f)\n",
   1667                         v_middle.x / 64.0, v_middle.y / 64.0,
   1668                         v_control.x / 64.0, v_control.y / 64.0 ));
   1669             error = func_interface->conic_to( &v_control, &v_middle, user );
   1670             if ( error )
   1671               goto Exit;
   1672 
   1673             v_control = vec;
   1674             goto Do_Conic;
   1675           }
   1676 
   1677           FT_TRACE5(( "  conic to (%.2f, %.2f)"
   1678                       " with control (%.2f, %.2f)\n",
   1679                       v_start.x / 64.0, v_start.y / 64.0,
   1680                       v_control.x / 64.0, v_control.y / 64.0 ));
   1681           error = func_interface->conic_to( &v_control, &v_start, user );
   1682           goto Close;
   1683 
   1684         default:  /* FT_CURVE_TAG_CUBIC */
   1685           {
   1686             FT_Vector  vec1, vec2;
   1687 
   1688 
   1689             if ( point + 1 > limit                             ||
   1690                  FT_CURVE_TAG( tags[1] ) != FT_CURVE_TAG_CUBIC )
   1691               goto Invalid_Outline;
   1692 
   1693             point += 2;
   1694             tags  += 2;
   1695 
   1696             vec1.x = SCALED( point[-2].x );
   1697             vec1.y = SCALED( point[-2].y );
   1698 
   1699             vec2.x = SCALED( point[-1].x );
   1700             vec2.y = SCALED( point[-1].y );
   1701 
   1702             if ( point <= limit )
   1703             {
   1704               FT_Vector  vec;
   1705 
   1706 
   1707               vec.x = SCALED( point->x );
   1708               vec.y = SCALED( point->y );
   1709 
   1710               FT_TRACE5(( "  cubic to (%.2f, %.2f)"
   1711                           " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
   1712                           vec.x / 64.0, vec.y / 64.0,
   1713                           vec1.x / 64.0, vec1.y / 64.0,
   1714                           vec2.x / 64.0, vec2.y / 64.0 ));
   1715               error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
   1716               if ( error )
   1717                 goto Exit;
   1718               continue;
   1719             }
   1720 
   1721             FT_TRACE5(( "  cubic to (%.2f, %.2f)"
   1722                         " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
   1723                         v_start.x / 64.0, v_start.y / 64.0,
   1724                         vec1.x / 64.0, vec1.y / 64.0,
   1725                         vec2.x / 64.0, vec2.y / 64.0 ));
   1726             error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
   1727             goto Close;
   1728           }
   1729         }
   1730       }
   1731 
   1732       /* close the contour with a line segment */
   1733       FT_TRACE5(( "  line to (%.2f, %.2f)\n",
   1734                   v_start.x / 64.0, v_start.y / 64.0 ));
   1735       error = func_interface->line_to( &v_start, user );
   1736 
   1737    Close:
   1738       if ( error )
   1739         goto Exit;
   1740 
   1741       first = last + 1;
   1742     }
   1743 
   1744     FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
   1745     return 0;
   1746 
   1747   Exit:
   1748     FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
   1749     return error;
   1750 
   1751   Invalid_Outline:
   1752     return FT_THROW( Invalid_Outline );
   1753   }
   1754 
   1755 #endif /* _STANDALONE_ */
   1756 
   1757 
   1758   typedef struct  gray_TBand_
   1759   {
   1760     TPos  min, max;
   1761 
   1762   } gray_TBand;
   1763 
   1764     FT_DEFINE_OUTLINE_FUNCS(func_interface,
   1765       (FT_Outline_MoveTo_Func) gray_move_to,
   1766       (FT_Outline_LineTo_Func) gray_line_to,
   1767       (FT_Outline_ConicTo_Func)gray_conic_to,
   1768       (FT_Outline_CubicTo_Func)gray_cubic_to,
   1769       0,
   1770       0
   1771     )
   1772 
   1773   static int
   1774   gray_convert_glyph_inner( RAS_ARG )
   1775   {
   1776 
   1777     volatile int  error = 0;
   1778 
   1779 #ifdef FT_CONFIG_OPTION_PIC
   1780       FT_Outline_Funcs func_interface;
   1781       Init_Class_func_interface(&func_interface);
   1782 #endif
   1783 #ifndef _FX_MANAGED_CODE_
   1784     if ( ft_setjmp( ras.jump_buffer ) == 0 )
   1785     {
   1786 #endif
   1787       error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
   1788       gray_record_cell( RAS_VAR );
   1789 #ifndef _FX_MANAGED_CODE_
   1790 	}
   1791     else
   1792       error = FT_THROW( Memory_Overflow );
   1793 #endif
   1794     return error;
   1795   }
   1796 
   1797 
   1798   static int
   1799   gray_convert_glyph( RAS_ARG )
   1800   {
   1801     gray_TBand            bands[40];
   1802     gray_TBand* volatile  band;
   1803     int volatile          n, num_bands;
   1804     TPos volatile         min, max, max_y;
   1805     FT_BBox*              clip;
   1806 
   1807 
   1808     /* Set up state in the raster object */
   1809     gray_compute_cbox( RAS_VAR );
   1810 
   1811     /* clip to target bitmap, exit if nothing to do */
   1812     clip = &ras.clip_box;
   1813 
   1814     if ( ras.max_ex <= clip->xMin || ras.min_ex >= clip->xMax ||
   1815          ras.max_ey <= clip->yMin || ras.min_ey >= clip->yMax )
   1816       return 0;
   1817 
   1818     if ( ras.min_ex < clip->xMin ) ras.min_ex = clip->xMin;
   1819     if ( ras.min_ey < clip->yMin ) ras.min_ey = clip->yMin;
   1820 
   1821     if ( ras.max_ex > clip->xMax ) ras.max_ex = clip->xMax;
   1822     if ( ras.max_ey > clip->yMax ) ras.max_ey = clip->yMax;
   1823 
   1824     ras.count_ex = ras.max_ex - ras.min_ex;
   1825     ras.count_ey = ras.max_ey - ras.min_ey;
   1826 
   1827     /* set up vertical bands */
   1828     num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
   1829     if ( num_bands == 0 )
   1830       num_bands = 1;
   1831     if ( num_bands >= 39 )
   1832       num_bands = 39;
   1833 
   1834     ras.band_shoot = 0;
   1835 
   1836     min   = ras.min_ey;
   1837     max_y = ras.max_ey;
   1838 
   1839     for ( n = 0; n < num_bands; n++, min = max )
   1840     {
   1841       max = min + ras.band_size;
   1842       if ( n == num_bands - 1 || max > max_y )
   1843         max = max_y;
   1844 
   1845       bands[0].min = min;
   1846       bands[0].max = max;
   1847       band         = bands;
   1848 
   1849       while ( band >= bands )
   1850       {
   1851         TPos  bottom, top, middle;
   1852         int   error;
   1853 
   1854         {
   1855           PCell  cells_max;
   1856           int    yindex;
   1857           long   cell_start, cell_end, cell_mod;
   1858 
   1859 
   1860           ras.ycells = (PCell*)ras.buffer;
   1861           ras.ycount = band->max - band->min;
   1862 
   1863           cell_start = sizeof ( PCell ) * ras.ycount;
   1864           cell_mod   = cell_start % sizeof ( TCell );
   1865           if ( cell_mod > 0 )
   1866             cell_start += sizeof ( TCell ) - cell_mod;
   1867 
   1868           cell_end  = ras.buffer_size;
   1869           cell_end -= cell_end % sizeof ( TCell );
   1870 
   1871           cells_max = (PCell)( (char*)ras.buffer + cell_end );
   1872           ras.cells = (PCell)( (char*)ras.buffer + cell_start );
   1873           if ( ras.cells >= cells_max )
   1874             goto ReduceBands;
   1875 
   1876           ras.max_cells = cells_max - ras.cells;
   1877           if ( ras.max_cells < 2 )
   1878             goto ReduceBands;
   1879 
   1880           for ( yindex = 0; yindex < ras.ycount; yindex++ )
   1881             ras.ycells[yindex] = NULL;
   1882         }
   1883 
   1884         ras.num_cells = 0;
   1885         ras.invalid   = 1;
   1886         ras.min_ey    = band->min;
   1887         ras.max_ey    = band->max;
   1888         ras.count_ey  = band->max - band->min;
   1889 
   1890         error = gray_convert_glyph_inner( RAS_VAR );
   1891 
   1892         if ( !error )
   1893         {
   1894           gray_sweep( RAS_VAR_ &ras.target );
   1895           band--;
   1896           continue;
   1897         }
   1898         else if ( error != ErrRaster_Memory_Overflow )
   1899           return 1;
   1900 
   1901       ReduceBands:
   1902         /* render pool overflow; we will reduce the render band by half */
   1903         bottom = band->min;
   1904         top    = band->max;
   1905         middle = bottom + ( ( top - bottom ) >> 1 );
   1906 
   1907         /* This is too complex for a single scanline; there must */
   1908         /* be some problems.                                     */
   1909         if ( middle == bottom )
   1910         {
   1911 #ifdef FT_DEBUG_LEVEL_TRACE
   1912           FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
   1913 #endif
   1914           return 1;
   1915         }
   1916 
   1917         if ( bottom-top >= ras.band_size )
   1918           ras.band_shoot++;
   1919 
   1920         band[1].min = bottom;
   1921         band[1].max = middle;
   1922         band[0].min = middle;
   1923         band[0].max = top;
   1924         band++;
   1925       }
   1926     }
   1927 
   1928     if ( ras.band_shoot > 8 && ras.band_size > 16 )
   1929       ras.band_size = ras.band_size / 2;
   1930 
   1931     return 0;
   1932   }
   1933 
   1934 
   1935   static int
   1936   gray_raster_render( gray_PRaster             raster,
   1937                       const FT_Raster_Params*  params )
   1938   {
   1939     const FT_Outline*  outline    = (const FT_Outline*)params->source;
   1940     const FT_Bitmap*   target_map = params->target;
   1941     gray_PWorker       worker;
   1942 
   1943 
   1944     if ( !raster || !raster->buffer || !raster->buffer_size )
   1945       return FT_THROW( Invalid_Argument );
   1946 
   1947     if ( !outline )
   1948       return FT_THROW( Invalid_Outline );
   1949 
   1950     /* return immediately if the outline is empty */
   1951     if ( outline->n_points == 0 || outline->n_contours <= 0 )
   1952       return 0;
   1953 
   1954     if ( !outline->contours || !outline->points )
   1955       return FT_THROW( Invalid_Outline );
   1956 
   1957     if ( outline->n_points !=
   1958            outline->contours[outline->n_contours - 1] + 1 )
   1959       return FT_THROW( Invalid_Outline );
   1960 
   1961     worker = raster->worker;
   1962 
   1963     /* if direct mode is not set, we must have a target bitmap */
   1964     if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
   1965     {
   1966       if ( !target_map )
   1967         return FT_THROW( Invalid_Argument );
   1968 
   1969       /* nothing to do */
   1970       if ( !target_map->width || !target_map->rows )
   1971         return 0;
   1972 
   1973       if ( !target_map->buffer )
   1974         return FT_THROW( Invalid_Argument );
   1975     }
   1976 
   1977     /* this version does not support monochrome rendering */
   1978     if ( !( params->flags & FT_RASTER_FLAG_AA ) )
   1979       return FT_THROW( Invalid_Mode );
   1980 
   1981     /* compute clipping box */
   1982     if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
   1983     {
   1984       /* compute clip box from target pixmap */
   1985       ras.clip_box.xMin = 0;
   1986       ras.clip_box.yMin = 0;
   1987       ras.clip_box.xMax = target_map->width;
   1988       ras.clip_box.yMax = target_map->rows;
   1989     }
   1990     else if ( params->flags & FT_RASTER_FLAG_CLIP )
   1991       ras.clip_box = params->clip_box;
   1992     else
   1993     {
   1994       ras.clip_box.xMin = -32768L;
   1995       ras.clip_box.yMin = -32768L;
   1996       ras.clip_box.xMax =  32767L;
   1997       ras.clip_box.yMax =  32767L;
   1998     }
   1999 
   2000     gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size );
   2001 
   2002     ras.outline        = *outline;
   2003     ras.num_cells      = 0;
   2004     ras.invalid        = 1;
   2005     ras.band_size      = raster->band_size;
   2006     ras.num_gray_spans = 0;
   2007 
   2008     if ( params->flags & FT_RASTER_FLAG_DIRECT )
   2009     {
   2010       ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
   2011       ras.render_span_data = params->user;
   2012     }
   2013     else
   2014     {
   2015       ras.target           = *target_map;
   2016       ras.render_span      = (FT_Raster_Span_Func)gray_render_span;
   2017       ras.render_span_data = &ras;
   2018     }
   2019 
   2020     return gray_convert_glyph( RAS_VAR );
   2021   }
   2022 
   2023 
   2024   /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/
   2025   /****                         a static object.                   *****/
   2026 
   2027 #ifdef _STANDALONE_
   2028 
   2029   static int
   2030   gray_raster_new( void*       memory,
   2031                    FT_Raster*  araster )
   2032   {
   2033     static gray_TRaster  the_raster;
   2034 
   2035     FT_UNUSED( memory );
   2036 
   2037 
   2038     *araster = (FT_Raster)&the_raster;
   2039     FT_MEM_ZERO( &the_raster, sizeof ( the_raster ) );
   2040 
   2041     return 0;
   2042   }
   2043 
   2044 
   2045   static void
   2046   gray_raster_done( FT_Raster  raster )
   2047   {
   2048     /* nothing */
   2049     FT_UNUSED( raster );
   2050   }
   2051 
   2052 #else /* !_STANDALONE_ */
   2053 
   2054   static int
   2055   gray_raster_new( FT_Memory   memory,
   2056                    FT_Raster*  araster )
   2057   {
   2058     FT_Error      error;
   2059     gray_PRaster  raster = NULL;
   2060 
   2061 
   2062     *araster = 0;
   2063     if ( !FT_ALLOC( raster, sizeof ( gray_TRaster ) ) )
   2064     {
   2065       raster->memory = memory;
   2066       *araster       = (FT_Raster)raster;
   2067     }
   2068 
   2069     return error;
   2070   }
   2071 
   2072 
   2073   static void
   2074   gray_raster_done( FT_Raster  raster )
   2075   {
   2076     FT_Memory  memory = (FT_Memory)((gray_PRaster)raster)->memory;
   2077 
   2078 
   2079     FT_FREE( raster );
   2080   }
   2081 
   2082 #endif /* !_STANDALONE_ */
   2083 
   2084 
   2085   static void
   2086   gray_raster_reset( FT_Raster  raster,
   2087                      char*      pool_base,
   2088                      long       pool_size )
   2089   {
   2090     gray_PRaster  rast = (gray_PRaster)raster;
   2091 
   2092 
   2093     if ( raster )
   2094     {
   2095       if ( pool_base && pool_size >= (long)sizeof ( gray_TWorker ) + 2048 )
   2096       {
   2097         gray_PWorker  worker = (gray_PWorker)pool_base;
   2098 
   2099 
   2100         rast->worker      = worker;
   2101         rast->buffer      = pool_base +
   2102                               ( ( sizeof ( gray_TWorker ) +
   2103                                   sizeof ( TCell ) - 1 )  &
   2104                                 ~( sizeof ( TCell ) - 1 ) );
   2105         rast->buffer_size = (long)( ( pool_base + pool_size ) -
   2106                                     (char*)rast->buffer ) &
   2107                                       ~( sizeof ( TCell ) - 1 );
   2108         rast->band_size   = (int)( rast->buffer_size /
   2109                                      ( sizeof ( TCell ) * 8 ) );
   2110       }
   2111       else
   2112       {
   2113         rast->buffer      = NULL;
   2114         rast->buffer_size = 0;
   2115         rast->worker      = NULL;
   2116       }
   2117     }
   2118   }
   2119 
   2120 
   2121   FT_DEFINE_RASTER_FUNCS(ft_grays_raster,
   2122     FT_GLYPH_FORMAT_OUTLINE,
   2123 
   2124     (FT_Raster_New_Func)     gray_raster_new,
   2125     (FT_Raster_Reset_Func)   gray_raster_reset,
   2126     (FT_Raster_Set_Mode_Func)0,
   2127     (FT_Raster_Render_Func)  gray_raster_render,
   2128     (FT_Raster_Done_Func)    gray_raster_done
   2129   )
   2130 
   2131 
   2132 /* END */
   2133 
   2134 
   2135 /* Local Variables: */
   2136 /* coding: utf-8    */
   2137 /* End:             */
   2138