[CMAKE]
[reactos.git] / lib / 3rdparty / freetype / src / smooth / ftgrays.c
index 5a4a544..a85e160 100644 (file)
@@ -4,7 +4,7 @@
 /*                                                                         */
 /*    A new `perfect' anti-aliasing renderer (body).                       */
 /*                                                                         */
-/*  Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007 by                   */
+/*  Copyright 2000-2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010 by */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
 #define FT_COMPONENT  trace_smooth
 
 
+#ifdef _STANDALONE_
 
 
-#ifdef _STANDALONE_
+  /* define this to dump debugging information */
+/* #define FT_DEBUG_LEVEL_TRACE */
+
 
-#include <string.h>             /* for ft_memcpy() */
+#ifdef FT_DEBUG_LEVEL_TRACE
+#include <stdio.h>
+#include <stdarg.h>
+#endif
+
+#include <stddef.h>
+#include <string.h>
 #include <setjmp.h>
 #include <limits.h>
 #define FT_UINT_MAX  UINT_MAX
+#define FT_INT_MAX   INT_MAX
 
 #define ft_memset   memset
 
 #define ft_longjmp  longjmp
 #define ft_jmp_buf  jmp_buf
 
+typedef ptrdiff_t  FT_PtrDist;
+
 
 #define ErrRaster_Invalid_Mode      -2
 #define ErrRaster_Invalid_Outline   -1
 #include "ftimage.h"
 #include "ftgrays.h"
 
+
   /* 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.                  */
+
+  /* we only use level 5 & 7 tracing messages; cf. ftdebug.h */
+
+#ifdef FT_DEBUG_LEVEL_TRACE
+
+  void
+  FT_Message( const char*  fmt,
+              ... )
+  {
+    va_list  ap;
+
+
+    va_start( ap, fmt );
+    vfprintf( stderr, fmt, ap );
+    va_end( ap );
+  }
+
+  /* we don't handle tracing levels in stand-alone mode; */
+#ifndef FT_TRACE5
+#define FT_TRACE5( varformat )  FT_Message varformat
+#endif
+#ifndef FT_TRACE7
+#define FT_TRACE7( varformat )  FT_Message varformat
+#endif
 #ifndef FT_ERROR
-#define FT_ERROR( x )  do ; while ( 0 )     /* nothing */
+#define FT_ERROR( varformat )   FT_Message varformat
 #endif
 
-#ifndef FT_TRACE
-#define FT_TRACE( x )  do ; while ( 0 )     /* nothing */
-#endif
+#else /* !FT_DEBUG_LEVEL_TRACE */
+
+#define FT_TRACE5( x )  do { } while ( 0 )     /* nothing */
+#define FT_TRACE7( x )  do { } while ( 0 )     /* nothing */
+#define FT_ERROR( x )   do { } while ( 0 )     /* nothing */
+
+#endif /* !FT_DEBUG_LEVEL_TRACE */
+
+
+#define FT_DEFINE_OUTLINE_FUNCS( class_,               \
+                                 move_to_, line_to_,   \
+                                 conic_to_, cubic_to_, \
+                                 shift_, delta_ )      \
+          static const FT_Outline_Funcs class_ =       \
+          {                                            \
+            move_to_,                                  \
+            line_to_,                                  \
+            conic_to_,                                 \
+            cubic_to_,                                 \
+            shift_,                                    \
+            delta_                                     \
+         };
+
+#define FT_DEFINE_RASTER_FUNCS( class_, glyph_format_,            \
+                                raster_new_, raster_reset_,       \
+                                raster_set_mode_, raster_render_, \
+                                raster_done_ )                    \
+          const FT_Raster_Funcs class_ =                          \
+          {                                                       \
+            glyph_format_,                                        \
+            raster_new_,                                          \
+            raster_reset_,                                        \
+            raster_set_mode_,                                     \
+            raster_render_,                                       \
+            raster_done_                                          \
+         };
 
 #else /* !_STANDALONE_ */
 
+
 #include <ft2build.h>
 #include "ftgrays.h"
 #include FT_INTERNAL_OBJECTS_H
 
 #include "ftsmerrs.h"
 
-#define ErrRaster_Invalid_Mode     Smooth_Err_Cannot_Render_Glyph
-#define ErrRaster_Invalid_Outline  Smooth_Err_Invalid_Outline
-#define ErrRaster_Memory_Overflow  Smooth_Err_Out_Of_Memory
-#define ErrRaster_Invalid_Argument Smooth_Err_Bad_Argument
+#include "ftspic.h"
 
-#endif /* !_STANDALONE_ */
+#define ErrRaster_Invalid_Mode      Smooth_Err_Cannot_Render_Glyph
+#define ErrRaster_Invalid_Outline   Smooth_Err_Invalid_Outline
+#define ErrRaster_Memory_Overflow   Smooth_Err_Out_Of_Memory
+#define ErrRaster_Invalid_Argument  Smooth_Err_Invalid_Argument
 
+#endif /* !_STANDALONE_ */
 
 #ifndef FT_MEM_SET
 #define FT_MEM_SET( d, s, c )  ft_memset( d, s, c )
 #define FT_MEM_ZERO( dest, count )  FT_MEM_SET( dest, 0, count )
 #endif
 
-  /* define this to dump debugging information */
-#define xxxDEBUG_GRAYS
-
-
   /* as usual, for the speed hungry :-) */
 
 #ifndef FT_STATIC_RASTER
 
-
 #define RAS_ARG   PWorker  worker
 #define RAS_ARG_  PWorker  worker,
 
 #define RAS_VAR   worker
 #define RAS_VAR_  worker,
 
-#define ras       (*worker)
-
-
 #else /* FT_STATIC_RASTER */
 
-
 #define RAS_ARG   /* empty */
 #define RAS_ARG_  /* empty */
 #define RAS_VAR   /* empty */
 #define RAS_VAR_  /* empty */
 
-  static TWorker  ras;
-
-
 #endif /* FT_STATIC_RASTER */
 
 
   /* need to define them to "float" or "double" when experimenting with   */
   /* new algorithms                                                       */
 
-  typedef int   TCoord;   /* integer scanline/pixel coordinate */
+  typedef long  TCoord;   /* integer scanline/pixel coordinate */
   typedef long  TPos;     /* sub-pixel coordinate              */
 
   /* determine the type used to store cell areas.  This normally takes at */
 
   typedef struct  TCell_
   {
-    int    x;
-    int    cover;
+    TPos   x;     /* same with TWorker.ex */
+    TCoord cover; /* same with TWorker.cover */
     TArea  area;
     PCell  next;
 
     TPos    count_ex, count_ey;
 
     TArea   area;
-    int     cover;
+    TCoord  cover;
     int     invalid;
 
     PCell   cells;
-    int     max_cells;
-    int     num_cells;
+    FT_PtrDist  max_cells;
+    FT_PtrDist  num_cells;
 
     TCoord  cx, cy;
     TPos    x,  y;
 
     int  band_size;
     int  band_shoot;
-    int  conic_level;
-    int  cubic_level;
 
     ft_jmp_buf  jump_buffer;
 
     long        buffer_size;
 
     PCell*     ycells;
-    int        ycount;
+    TPos       ycount;
 
   } TWorker, *PWorker;
 
 
+#ifndef FT_STATIC_RASTER
+#define ras  (*worker)
+#else
+  static TWorker  ras;
+#endif
+
+
   typedef struct TRaster_
   {
     void*    buffer;
   gray_find_cell( RAS_ARG )
   {
     PCell  *pcell, cell;
-    int     x = ras.ex;
+    TPos    x = ras.ex;
 
 
-    if ( x > ras.max_ex )
-      x = ras.max_ex;
+    if ( x > ras.count_ex )
+      x = ras.count_ex;
 
     pcell = &ras.ycells[ras.ey];
     for (;;)
                                  TPos    x2,
                                  TCoord  y2 )
   {
-    TCoord  ex1, ex2, fx1, fx2, delta;
+    TCoord  ex1, ex2, fx1, fx2, delta, mod, lift, rem;
     long    p, first, dx;
-    int     incr, lift, mod, rem;
+    int     incr;
 
 
     dx = x2 - x1;
     if ( ex1 == ex2 )
     {
       delta      = y2 - y1;
-      ras.area  += (TArea)( fx1 + fx2 ) * delta;
+      ras.area  += (TArea)(( fx1 + fx2 ) * delta);
       ras.cover += delta;
       return;
     }
       mod += (TCoord)dx;
     }
 
-    ras.area  += (TArea)( fx1 + first ) * delta;
+    ras.area  += (TArea)(( fx1 + first ) * delta);
     ras.cover += delta;
 
     ex1 += incr;
           delta++;
         }
 
-        ras.area  += (TArea)ONE_PIXEL * delta;
+        ras.area  += (TArea)(ONE_PIXEL * delta);
         ras.cover += delta;
         y1        += delta;
         ex1       += incr;
     }
 
     delta      = y2 - y1;
-    ras.area  += (TArea)( fx2 + ONE_PIXEL - first ) * delta;
+    ras.area  += (TArea)(( fx2 + ONE_PIXEL - first ) * delta);
     ras.cover += delta;
   }
 
   gray_render_line( RAS_ARG_ TPos  to_x,
                              TPos  to_y )
   {
-    TCoord  ey1, ey2, fy1, fy2;
+    TCoord  ey1, ey2, fy1, fy2, mod;
     TPos    dx, dy, x, x2;
     long    p, first;
-    int     delta, rem, mod, lift, incr;
+    int     delta, rem, lift, incr;
 
 
     ey1 = TRUNC( ras.last_ey );
     {
       TCoord  ex     = TRUNC( ras.x );
       TCoord  two_fx = (TCoord)( ( ras.x - SUBPIXELS( ex ) ) << 1 );
-      TPos    area;
+      TArea   area;
 
 
       first = ONE_PIXEL;
       ras.cover += delta;
       ey1       += incr;
 
-      gray_set_cell( &ras, ex, ey1 );
+      gray_set_cell( RAS_VAR_ ex, ey1 );
 
       delta = (int)( first + first - ONE_PIXEL );
       area  = (TArea)two_fx * delta;
         ras.cover += delta;
         ey1       += incr;
 
-        gray_set_cell( &ras, ex, ey1 );
+        gray_set_cell( RAS_VAR_ ex, ey1 );
       }
 
       delta      = (int)( fy2 - ONE_PIXEL + first );
     FT_Vector*  arc;
 
 
-    dx = DOWNSCALE( ras.x ) + to->x - ( control->x << 1 );
-    if ( dx < 0 )
-      dx = -dx;
-    dy = DOWNSCALE( ras.y ) + to->y - ( control->y << 1 );
-    if ( dy < 0 )
-      dy = -dy;
+    arc      = ras.bez_stack;
+    arc[0].x = UPSCALE( to->x );
+    arc[0].y = UPSCALE( to->y );
+    arc[1].x = UPSCALE( control->x );
+    arc[1].y = UPSCALE( control->y );
+    arc[2].x = ras.x;
+    arc[2].y = ras.y;
+
+    dx = FT_ABS( arc[2].x + arc[0].x - 2 * arc[1].x );
+    dy = FT_ABS( arc[2].y + arc[0].y - 2 * arc[1].y );
     if ( dx < dy )
       dx = dy;
 
-    level = 1;
-    dx = dx / ras.conic_level;
-    while ( dx > 0 )
+    if ( dx <= ONE_PIXEL / 4 )
     {
-      dx >>= 2;
-      level++;
+      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+      return;
     }
 
-    /* a shortcut to speed things up */
-    if ( level <= 1 )
+    level = 0;
+    while ( dx > ONE_PIXEL / 4 )
     {
-      /* we compute the mid-point directly in order to avoid */
-      /* calling gray_split_conic()                          */
-      TPos  to_x, to_y, mid_x, mid_y;
-
-
-      to_x  = UPSCALE( to->x );
-      to_y  = UPSCALE( to->y );
-      mid_x = ( ras.x + to_x + 2 * UPSCALE( control->x ) ) / 4;
-      mid_y = ( ras.y + to_y + 2 * UPSCALE( control->y ) ) / 4;
-
-      gray_render_line( RAS_VAR_ mid_x, mid_y );
-      gray_render_line( RAS_VAR_ to_x, to_y );
-
-      return;
+      dx >>= 2;
+      level++;
     }
 
-    arc       = ras.bez_stack;
     levels    = ras.lev_stack;
-    top       = 0;
     levels[0] = level;
-
-    arc[0].x = UPSCALE( to->x );
-    arc[0].y = UPSCALE( to->y );
-    arc[1].x = UPSCALE( control->x );
-    arc[1].y = UPSCALE( control->y );
-    arc[2].x = ras.x;
-    arc[2].y = ras.y;
+    top       = 0;
 
     while ( top >= 0 )
     {
       }
 
     Draw:
-      {
-        TPos  to_x, to_y, mid_x, mid_y;
-
-
-        to_x  = arc[0].x;
-        to_y  = arc[0].y;
-        mid_x = ( ras.x + to_x + 2 * arc[1].x ) / 4;
-        mid_y = ( ras.y + to_y + 2 * arc[1].y ) / 4;
-
-        gray_render_line( RAS_VAR_ mid_x, mid_y );
-        gray_render_line( RAS_VAR_ to_x, to_y );
-
-        top--;
-        arc -= 2;
-      }
+      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
+      top--;
+      arc -= 2;
     }
 
     return;
                               const FT_Vector*  control2,
                               const FT_Vector*  to )
   {
-    TPos        dx, dy, da, db;
-    int         top, level;
-    int*        levels;
     FT_Vector*  arc;
 
 
-    dx = DOWNSCALE( ras.x ) + to->x - ( control1->x << 1 );
-    if ( dx < 0 )
-      dx = -dx;
-    dy = DOWNSCALE( ras.y ) + to->y - ( control1->y << 1 );
-    if ( dy < 0 )
-      dy = -dy;
-    if ( dx < dy )
-      dx = dy;
-    da = dx;
-
-    dx = DOWNSCALE( ras.x ) + to->x - 3 * ( control1->x + control2->x );
-    if ( dx < 0 )
-      dx = -dx;
-    dy = DOWNSCALE( ras.y ) + to->y - 3 * ( control1->x + control2->y );
-    if ( dy < 0 )
-      dy = -dy;
-    if ( dx < dy )
-      dx = dy;
-    db = dx;
-
-    level = 1;
-    da    = da / ras.cubic_level;
-    db    = db / ras.conic_level;
-    while ( da > 0 || db > 0 )
-    {
-      da >>= 2;
-      db >>= 3;
-      level++;
-    }
-
-    if ( level <= 1 )
-    {
-      TPos   to_x, to_y, mid_x, mid_y;
-
-
-      to_x  = UPSCALE( to->x );
-      to_y  = UPSCALE( to->y );
-      mid_x = ( ras.x + to_x +
-                3 * UPSCALE( control1->x + control2->x ) ) / 8;
-      mid_y = ( ras.y + to_y +
-                3 * UPSCALE( control1->y + control2->y ) ) / 8;
-
-      gray_render_line( RAS_VAR_ mid_x, mid_y );
-      gray_render_line( RAS_VAR_ to_x, to_y );
-      return;
-    }
-
     arc      = ras.bez_stack;
     arc[0].x = UPSCALE( to->x );
     arc[0].y = UPSCALE( to->y );
     arc[3].x = ras.x;
     arc[3].y = ras.y;
 
-    levels    = ras.lev_stack;
-    top       = 0;
-    levels[0] = level;
-
-    while ( top >= 0 )
+    for (;;)
     {
-      level = levels[top];
-      if ( level > 1 )
-      {
-        /* check that the arc crosses the current band */
-        TPos  min, max, y;
+      /* Check that the arc crosses the current band. */
+      TPos  min, max, y;
 
 
-        min = max = arc[0].y;
-        y = arc[1].y;
-        if ( y < min ) min = y;
-        if ( y > max ) max = y;
-        y = arc[2].y;
-        if ( y < min ) min = y;
-        if ( y > max ) max = y;
-        y = arc[3].y;
-        if ( y < min ) min = y;
-        if ( y > max ) max = y;
-        if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < 0 )
-          goto Draw;
-        gray_split_cubic( arc );
-        arc += 3;
-        top ++;
-        levels[top] = levels[top - 1] = level - 1;
-        continue;
-      }
+      min = max = arc[0].y;
 
-    Draw:
-      {
-        TPos  to_x, to_y, mid_x, mid_y;
+      y = arc[1].y;
+      if ( y < min )
+        min = y;
+      if ( y > max )
+        max = y;
+
+      y = arc[2].y;
+      if ( y < min )
+        min = y;
+      if ( y > max )
+        max = y;
 
+      y = arc[3].y;
+      if ( y < min )
+        min = y;
+      if ( y > max )
+        max = y;
 
-        to_x  = arc[0].x;
-        to_y  = arc[0].y;
-        mid_x = ( ras.x + to_x + 3 * ( arc[1].x + arc[2].x ) ) / 8;
-        mid_y = ( ras.y + to_y + 3 * ( arc[1].y + arc[2].y ) ) / 8;
+      if ( TRUNC( min ) >= ras.max_ey || TRUNC( max ) < ras.min_ey )
+        goto Draw;
 
-        gray_render_line( RAS_VAR_ mid_x, mid_y );
-        gray_render_line( RAS_VAR_ to_x, to_y );
-        top --;
-        arc -= 3;
+      /* Decide whether to split or draw. See `Rapid Termination          */
+      /* Evaluation for Recursive Subdivision of Bezier Curves' by Thomas */
+      /* F. Hain, at                                                      */
+      /* http://www.cis.southalabama.edu/~hain/general/Publications/Bezier/Camera-ready%20CISST02%202.pdf */
+
+      {
+        TPos  dx, dy, dx_, dy_;
+        TPos  dx1, dy1, dx2, dy2;
+        TPos  L, s, s_limit;
+
+
+        /* dx and dy are x and y components of the P0-P3 chord vector. */
+        dx = arc[3].x - arc[0].x;
+        dy = arc[3].y - arc[0].y;
+
+        /* L is an (under)estimate of the Euclidean distance P0-P3.       */
+        /*                                                                */
+        /* If dx >= dy, then r = sqrt(dx^2 + dy^2) can be overestimated   */
+        /* with least maximum error by                                    */
+        /*                                                                */
+        /*   r_upperbound = dx + (sqrt(2) - 1) * dy  ,                    */
+        /*                                                                */
+        /* where sqrt(2) - 1 can be (over)estimated by 107/256, giving an */
+        /* error of no more than 8.4%.                                    */
+        /*                                                                */
+        /* Similarly, some elementary calculus shows that r can be        */
+        /* underestimated with least maximum error by                     */
+        /*                                                                */
+        /*   r_lowerbound = sqrt(2 + sqrt(2)) / 2 * dx                    */
+        /*                  + sqrt(2 - sqrt(2)) / 2 * dy  .               */
+        /*                                                                */
+        /* 236/256 and 97/256 are (under)estimates of the two algebraic   */
+        /* numbers, giving an error of no more than 8.1%.                 */
+
+        dx_ = FT_ABS( dx );
+        dy_ = FT_ABS( dy );
+
+        /* This is the same as                     */
+        /*                                         */
+        /*   L = ( 236 * FT_MAX( dx_, dy_ )        */
+        /*       + 97 * FT_MIN( dx_, dy_ ) ) >> 8; */
+        L = ( dx_ > dy_ ? 236 * dx_ +  97 * dy_
+                        :  97 * dx_ + 236 * dy_ ) >> 8;
+
+        /* Avoid possible arithmetic overflow below by splitting. */
+        if ( L > 32767 )
+          goto Split;
+
+        /* Max deviation may be as much as (s/L) * 3/4 (if Hain's v = 1). */
+        s_limit = L * (TPos)( ONE_PIXEL / 6 );
+
+        /* s is L * the perpendicular distance from P1 to the line P0-P3. */
+        dx1 = arc[1].x - arc[0].x;
+        dy1 = arc[1].y - arc[0].y;
+        s = FT_ABS( dy * dx1 - dx * dy1 );
+
+        if ( s > s_limit )
+          goto Split;
+
+        /* s is L * the perpendicular distance from P2 to the line P0-P3. */
+        dx2 = arc[2].x - arc[0].x;
+        dy2 = arc[2].y - arc[0].y;
+        s = FT_ABS( dy * dx2 - dx * dy2 );
+
+        if ( s > s_limit )
+          goto Split;
+
+        /* If P1 or P2 is outside P0-P3, split the curve. */
+        if ( dy * dy1 + dx * dx1 < 0                                     ||
+             dy * dy2 + dx * dx2 < 0                                     ||
+             dy * (arc[3].y - arc[1].y) + dx * (arc[3].x - arc[1].x) < 0 ||
+             dy * (arc[3].y - arc[2].y) + dx * (arc[3].x - arc[2].x) < 0 )
+          goto Split;
+
+        /* No reason to split. */
+        goto Draw;
       }
-    }
 
-    return;
-  }
+    Split:
+      gray_split_cubic( arc );
+      arc += 3;
+      continue;
+
+    Draw:
+      gray_render_line( RAS_VAR_ arc[0].x, arc[0].y );
 
+      if ( arc == ras.bez_stack )
+        return;
+
+      arc -= 3;
+    }
+  }
 
 
   static int
 
 
     /* record current cell, if any */
-    gray_record_cell( worker );
+    gray_record_cell( RAS_VAR );
 
     /* start to a new position */
     x = UPSCALE( to->x );
     y = UPSCALE( to->y );
 
-    gray_start_cell( worker, TRUNC( x ), TRUNC( y ) );
+    gray_start_cell( RAS_VAR_ TRUNC( x ), TRUNC( y ) );
 
     worker->x = x;
     worker->y = y;
   gray_line_to( const FT_Vector*  to,
                 PWorker           worker )
   {
-    gray_render_line( worker, UPSCALE( to->x ), UPSCALE( to->y ) );
+    gray_render_line( RAS_VAR_ UPSCALE( to->x ), UPSCALE( to->y ) );
     return 0;
   }
 
                  const FT_Vector*  to,
                  PWorker           worker )
   {
-    gray_render_conic( worker, control, to );
+    gray_render_conic( RAS_VAR_ control, to );
     return 0;
   }
 
                  const FT_Vector*  to,
                  PWorker           worker )
   {
-    gray_render_cubic( worker, control1, control2, to );
+    gray_render_cubic( RAS_VAR_ control1, control2, to );
     return 0;
   }
 
     /* first of all, compute the scanline offset */
     p = (unsigned char*)map->buffer - y * map->pitch;
     if ( map->pitch >= 0 )
-      p += ( map->rows - 1 ) * map->pitch;
+      p += (unsigned)( ( map->rows - 1 ) * map->pitch );
 
     for ( ; count > 0; count--, spans++ )
     {
   gray_hline( RAS_ARG_ TCoord  x,
                        TCoord  y,
                        TPos    area,
-                       int     acount )
+                       TCoord  acount )
   {
     FT_Span*  span;
     int       count;
     x += (TCoord)ras.min_ex;
 
     /* FT_Span.x is a 16-bit short, so limit our coordinates appropriately */
-    if ( x >= 32768 )
+    if ( x >= 32767 )
       x = 32767;
 
+    /* FT_Span.y is an integer, so limit our coordinates appropriately */
+    if ( y >= FT_INT_MAX )
+      y = FT_INT_MAX;
+
     if ( coverage )
     {
       /* see whether we can add this span to the current list */
         if ( ras.render_span && count > 0 )
           ras.render_span( ras.span_y, count, ras.gray_spans,
                            ras.render_span_data );
-        /* ras.render_span( span->y, ras.gray_spans, count ); */
 
-#ifdef DEBUG_GRAYS
+#ifdef FT_DEBUG_LEVEL_TRACE
 
-        if ( ras.span_y >= 0 )
+        if ( count > 0 )
         {
           int  n;
 
 
-          fprintf( stderr, "y=%3d ", ras.span_y );
+          FT_TRACE7(( "y = %3d ", ras.span_y ));
           span = ras.gray_spans;
           for ( n = 0; n < count; n++, span++ )
-            fprintf( stderr, "[%d..%d]:%02x ",
-                     span->x, span->x + span->len - 1, span->coverage );
-          fprintf( stderr, "\n" );
+            FT_TRACE7(( "[%d..%d]:%02x ",
+                        span->x, span->x + span->len - 1, span->coverage ));
+          FT_TRACE7(( "\n" ));
         }
 
-#endif /* DEBUG_GRAYS */
+#endif /* FT_DEBUG_LEVEL_TRACE */
 
         ras.num_gray_spans = 0;
-        ras.span_y         = y;
+        ras.span_y         = (int)y;
 
         count = 0;
         span  = ras.gray_spans;
   }
 
 
-#ifdef DEBUG_GRAYS
+#ifdef FT_DEBUG_LEVEL_TRACE
 
-  /* to be called while in the debugger */
+  /* to be called while in the debugger --                                */
+  /* this function causes a compiler warning since it is unused otherwise */
+  static void
   gray_dump_cells( RAS_ARG )
   {
     int  yindex;
       printf( "%3d:", yindex );
 
       for ( cell = ras.ycells[yindex]; cell != NULL; cell = cell->next )
-        printf( " (%3d, c:%4d, a:%6d)", cell->x, cell->cover, cell->area );
+        printf( " (%3ld, c:%4ld, a:%6d)", cell->x, cell->cover, cell->area );
       printf( "\n" );
     }
   }
 
-#endif /* DEBUG_GRAYS */
+#endif /* FT_DEBUG_LEVEL_TRACE */
 
 
   static void
 
     ras.num_gray_spans = 0;
 
+    FT_TRACE7(( "gray_sweep: start\n" ));
+
     for ( yindex = 0; yindex < ras.ycount; yindex++ )
     {
       PCell   cell  = ras.ycells[yindex];
 
       for ( ; cell != NULL; cell = cell->next )
       {
-        TArea  area;
+        TPos  area;
 
 
         if ( cell->x > x && cover != 0 )
     if ( ras.render_span && ras.num_gray_spans > 0 )
       ras.render_span( ras.span_y, ras.num_gray_spans,
                        ras.gray_spans, ras.render_span_data );
+
+    FT_TRACE7(( "gray_sweep: end\n" ));
   }
 
 
 
   /*************************************************************************/
   /*                                                                       */
-  /*  The following function should only compile in stand_alone mode,      */
+  /*  The following function should only compile in stand-alone mode,      */
   /*  i.e., when building this component without the rest of FreeType.     */
   /*                                                                       */
   /*************************************************************************/
   /*    FT_Outline_Decompose                                               */
   /*                                                                       */
   /* <Description>                                                         */
-  /*    Walks over an outline's structure to decompose it into individual  */
-  /*    segments and Bezier arcs.  This function is also able to emit      */
+  /*    Walk over an outline's structure to decompose it into individual   */
+  /*    segments and Bézier arcs.  This function is also able to emit      */
   /*    `move to' and `close to' operations to indicate the start and end  */
   /*    of new contours in the outline.                                    */
   /*                                                                       */
   /* <Input>                                                               */
   /*    outline        :: A pointer to the source target.                  */
   /*                                                                       */
-  /*    func_interface :: A table of `emitters', i.e,. function pointers   */
+  /*    func_interface :: A table of `emitters', i.e., function pointers   */
   /*                      called during decomposition to indicate path     */
   /*                      operations.                                      */
   /*                                                                       */
+  /* <InOut>                                                               */
   /*    user           :: A typeless pointer which is passed to each       */
   /*                      emitter during the decomposition.  It can be     */
   /*                      used to store the state during the               */
   /* <Return>                                                              */
   /*    Error code.  0 means success.                                      */
   /*                                                                       */
-  static
-  int  FT_Outline_Decompose( const FT_Outline*        outline,
-                             const FT_Outline_Funcs*  func_interface,
-                             void*                    user )
+  static int
+  FT_Outline_Decompose( const FT_Outline*        outline,
+                        const FT_Outline_Funcs*  func_interface,
+                        void*                    user )
   {
 #undef SCALED
-#if 0
 #define SCALED( x )  ( ( (x) << shift ) - delta )
-#else
-#define SCALED( x )  (x)
-#endif
 
     FT_Vector   v_last;
     FT_Vector   v_control;
     FT_Vector*  limit;
     char*       tags;
 
+    int         error;
+
     int   n;         /* index of contour in outline     */
     int   first;     /* index of first point in contour */
-    int   error;
     char  tag;       /* current point's state           */
 
-#if 0
-    int   shift = func_interface->shift;
-    TPos  delta = func_interface->delta;
-#endif
+    int   shift;
+    TPos  delta;
+
 
+    if ( !outline || !func_interface )
+      return ErrRaster_Invalid_Argument;
 
+    shift = func_interface->shift;
+    delta = func_interface->delta;
     first = 0;
 
     for ( n = 0; n < outline->n_contours; n++ )
       int  last;  /* index of last point in contour */
 
 
+      FT_TRACE5(( "FT_Outline_Decompose: Outline %d\n", n ));
+
       last  = outline->contours[n];
+      if ( last < 0 )
+        goto Invalid_Outline;
       limit = outline->points + last;
 
-      v_start = outline->points[first];
-      v_last  = outline->points[last];
-
+      v_start   = outline->points[first];
       v_start.x = SCALED( v_start.x );
       v_start.y = SCALED( v_start.y );
 
-      v_last.x  = SCALED( v_last.x );
-      v_last.y  = SCALED( v_last.y );
+      v_last   = outline->points[last];
+      v_last.x = SCALED( v_last.x );
+      v_last.y = SCALED( v_last.y );
 
       v_control = v_start;
 
       point = outline->points + first;
-      tags  = outline->tags  + first;
+      tags  = outline->tags   + first;
       tag   = FT_CURVE_TAG( tags[0] );
 
       /* A contour cannot start with a cubic control point! */
         tags--;
       }
 
+      FT_TRACE5(( "  move to (%.2f, %.2f)\n",
+                  v_start.x / 64.0, v_start.y / 64.0 ));
       error = func_interface->move_to( &v_start, user );
       if ( error )
         goto Exit;
             vec.x = SCALED( point->x );
             vec.y = SCALED( point->y );
 
+            FT_TRACE5(( "  line to (%.2f, %.2f)\n",
+                        vec.x / 64.0, vec.y / 64.0 ));
             error = func_interface->line_to( &vec, user );
             if ( error )
               goto Exit;
           }
 
         case FT_CURVE_TAG_CONIC:  /* consume conic arcs */
-          {
-            v_control.x = SCALED( point->x );
-            v_control.y = SCALED( point->y );
+          v_control.x = SCALED( point->x );
+          v_control.y = SCALED( point->y );
 
-          Do_Conic:
-            if ( point < limit )
-            {
-              FT_Vector  vec;
-              FT_Vector  v_middle;
-
-
-              point++;
-              tags++;
-              tag = FT_CURVE_TAG( tags[0] );
-
-              vec.x = SCALED( point->x );
-              vec.y = SCALED( point->y );
+        Do_Conic:
+          if ( point < limit )
+          {
+            FT_Vector  vec;
+            FT_Vector  v_middle;
 
-              if ( tag == FT_CURVE_TAG_ON )
-              {
-                error = func_interface->conic_to( &v_control, &vec,
-                                                  user );
-                if ( error )
-                  goto Exit;
-                continue;
-              }
 
-              if ( tag != FT_CURVE_TAG_CONIC )
-                goto Invalid_Outline;
+            point++;
+            tags++;
+            tag = FT_CURVE_TAG( tags[0] );
 
-              v_middle.x = ( v_control.x + vec.x ) / 2;
-              v_middle.y = ( v_control.y + vec.y ) / 2;
+            vec.x = SCALED( point->x );
+            vec.y = SCALED( point->y );
 
-              error = func_interface->conic_to( &v_control, &v_middle,
-                                                user );
+            if ( tag == FT_CURVE_TAG_ON )
+            {
+              FT_TRACE5(( "  conic to (%.2f, %.2f)"
+                          " with control (%.2f, %.2f)\n",
+                          vec.x / 64.0, vec.y / 64.0,
+                          v_control.x / 64.0, v_control.y / 64.0 ));
+              error = func_interface->conic_to( &v_control, &vec, user );
               if ( error )
                 goto Exit;
-
-              v_control = vec;
-              goto Do_Conic;
+              continue;
             }
 
-            error = func_interface->conic_to( &v_control, &v_start,
-                                              user );
-            goto Close;
+            if ( tag != FT_CURVE_TAG_CONIC )
+              goto Invalid_Outline;
+
+            v_middle.x = ( v_control.x + vec.x ) / 2;
+            v_middle.y = ( v_control.y + vec.y ) / 2;
+
+            FT_TRACE5(( "  conic to (%.2f, %.2f)"
+                        " with control (%.2f, %.2f)\n",
+                        v_middle.x / 64.0, v_middle.y / 64.0,
+                        v_control.x / 64.0, v_control.y / 64.0 ));
+            error = func_interface->conic_to( &v_control, &v_middle, user );
+            if ( error )
+              goto Exit;
+
+            v_control = vec;
+            goto Do_Conic;
           }
 
+          FT_TRACE5(( "  conic to (%.2f, %.2f)"
+                      " with control (%.2f, %.2f)\n",
+                      v_start.x / 64.0, v_start.y / 64.0,
+                      v_control.x / 64.0, v_control.y / 64.0 ));
+          error = func_interface->conic_to( &v_control, &v_start, user );
+          goto Close;
+
         default:  /* FT_CURVE_TAG_CUBIC */
           {
             FT_Vector  vec1, vec2;
               vec.x = SCALED( point->x );
               vec.y = SCALED( point->y );
 
+              FT_TRACE5(( "  cubic to (%.2f, %.2f)"
+                          " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
+                          vec.x / 64.0, vec.y / 64.0,
+                          vec1.x / 64.0, vec1.y / 64.0,
+                          vec2.x / 64.0, vec2.y / 64.0 ));
               error = func_interface->cubic_to( &vec1, &vec2, &vec, user );
               if ( error )
                 goto Exit;
               continue;
             }
 
+            FT_TRACE5(( "  cubic to (%.2f, %.2f)"
+                        " with controls (%.2f, %.2f) and (%.2f, %.2f)\n",
+                        v_start.x / 64.0, v_start.y / 64.0,
+                        vec1.x / 64.0, vec1.y / 64.0,
+                        vec2.x / 64.0, vec2.y / 64.0 ));
             error = func_interface->cubic_to( &vec1, &vec2, &v_start, user );
             goto Close;
           }
       }
 
       /* close the contour with a line segment */
+      FT_TRACE5(( "  line to (%.2f, %.2f)\n",
+                  v_start.x / 64.0, v_start.y / 64.0 ));
       error = func_interface->line_to( &v_start, user );
 
    Close:
       first = last + 1;
     }
 
+    FT_TRACE5(( "FT_Outline_Decompose: Done\n", n ));
     return 0;
 
   Exit:
+    FT_TRACE5(( "FT_Outline_Decompose: Error %d\n", error ));
     return error;
 
   Invalid_Outline:
 
   } TBand;
 
-
-  static int
-  gray_convert_glyph_inner( RAS_ARG )
-  {
-    static
-    const FT_Outline_Funcs  func_interface =
-    {
+    FT_DEFINE_OUTLINE_FUNCS(func_interface,
       (FT_Outline_MoveTo_Func) gray_move_to,
       (FT_Outline_LineTo_Func) gray_line_to,
       (FT_Outline_ConicTo_Func)gray_conic_to,
       (FT_Outline_CubicTo_Func)gray_cubic_to,
       0,
       0
-    };
+    )
+
+  static int
+  gray_convert_glyph_inner( RAS_ARG )
+  {
 
     volatile int  error = 0;
 
+#ifdef FT_CONFIG_OPTION_PIC
+      FT_Outline_Funcs func_interface;
+      Init_Class_func_interface(&func_interface);
+#endif
+
     if ( ft_setjmp( ras.jump_buffer ) == 0 )
     {
       error = FT_Outline_Decompose( &ras.outline, &func_interface, &ras );
       gray_record_cell( RAS_VAR );
     }
     else
-    {
       error = ErrRaster_Memory_Overflow;
-    }
 
     return error;
   }
     ras.count_ex = ras.max_ex - ras.min_ex;
     ras.count_ey = ras.max_ey - ras.min_ey;
 
-    /* simple heuristic used to speed-up the bezier decomposition -- see */
-    /* the code in gray_render_conic() and gray_render_cubic() for more  */
-    /* details                                                           */
-    ras.conic_level = 32;
-    ras.cubic_level = 16;
-
-    {
-      int level = 0;
-
-
-      if ( ras.count_ex > 24 || ras.count_ey > 24 )
-        level++;
-      if ( ras.count_ex > 120 || ras.count_ey > 120 )
-        level++;
-
-      ras.conic_level <<= level;
-      ras.cubic_level <<= level;
-    }
-
-    /* setup vertical bands */
+    /* set up vertical bands */
     num_bands = (int)( ( ras.max_ey - ras.min_ey ) / ras.band_size );
-    if ( num_bands == 0 )  num_bands = 1;
-    if ( num_bands >= 39 ) num_bands = 39;
+    if ( num_bands == 0 )
+      num_bands = 1;
+    if ( num_bands >= 39 )
+      num_bands = 39;
 
     ras.band_shoot = 0;
 
         /* be some problems.                                     */
         if ( middle == bottom )
         {
-#ifdef DEBUG_GRAYS
-          fprintf( stderr, "Rotten glyph!\n" );
+#ifdef FT_DEBUG_LEVEL_TRACE
+          FT_TRACE7(( "gray_convert_glyph: rotten glyph\n" ));
 #endif
           return 1;
         }
     if ( !raster || !raster->buffer || !raster->buffer_size )
       return ErrRaster_Invalid_Argument;
 
+    if ( !outline )
+      return ErrRaster_Invalid_Outline;
+
     /* return immediately if the outline is empty */
     if ( outline->n_points == 0 || outline->n_contours <= 0 )
       return 0;
 
-    if ( !outline || !outline->contours || !outline->points )
+    if ( !outline->contours || !outline->points )
       return ErrRaster_Invalid_Outline;
 
     if ( outline->n_points !=
     worker = raster->worker;
 
     /* if direct mode is not set, we must have a target bitmap */
-    if ( ( params->flags & FT_RASTER_FLAG_DIRECT ) == 0 )
+    if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
     {
       if ( !target_map )
         return ErrRaster_Invalid_Argument;
       return ErrRaster_Invalid_Mode;
 
     /* compute clipping box */
-    if ( ( params->flags & FT_RASTER_FLAG_DIRECT ) == 0 )
+    if ( !( params->flags & FT_RASTER_FLAG_DIRECT ) )
     {
       /* compute clip box from target pixmap */
       ras.clip_box.xMin = 0;
       ras.clip_box.yMax = target_map->rows;
     }
     else if ( params->flags & FT_RASTER_FLAG_CLIP )
-    {
       ras.clip_box = params->clip_box;
-    }
     else
     {
       ras.clip_box.xMin = -32768L;
       ras.clip_box.yMax =  32767L;
     }
 
-    gray_init_cells( worker, raster->buffer, raster->buffer_size );
+    gray_init_cells( RAS_VAR_ raster->buffer, raster->buffer_size );
 
-    ras.outline   = *outline;
-    ras.num_cells = 0;
-    ras.invalid   = 1;
-    ras.band_size = raster->band_size;
+    ras.outline        = *outline;
+    ras.num_cells      = 0;
+    ras.invalid        = 1;
+    ras.band_size      = raster->band_size;
     ras.num_gray_spans = 0;
 
-    if ( target_map )
-      ras.target = *target_map;
-
-    ras.render_span      = (FT_Raster_Span_Func)gray_render_span;
-    ras.render_span_data = &ras;
-
     if ( params->flags & FT_RASTER_FLAG_DIRECT )
     {
       ras.render_span      = (FT_Raster_Span_Func)params->gray_spans;
       ras.render_span_data = params->user;
     }
+    else
+    {
+      ras.target           = *target_map;
+      ras.render_span      = (FT_Raster_Span_Func)gray_render_span;
+      ras.render_span_data = &ras;
+    }
 
-    return gray_convert_glyph( worker );
+    return gray_convert_glyph( RAS_VAR );
   }
 
 
-  /**** RASTER OBJECT CREATION: In standalone mode, we simply use *****/
-  /****                         a static object.                  *****/
+  /**** RASTER OBJECT CREATION: In stand-alone mode, we simply use *****/
+  /****                         a static object.                   *****/
 
 #ifdef _STANDALONE_
 
     FT_UNUSED( raster );
   }
 
-#else /* _STANDALONE_ */
+#else /* !_STANDALONE_ */
 
   static int
   gray_raster_new( FT_Memory   memory,
                    FT_Raster*  araster )
   {
     FT_Error  error;
-    PRaster   raster;
+    PRaster   raster = NULL;
 
 
     *araster = 0;
     FT_FREE( raster );
   }
 
-#endif /* _STANDALONE_ */
+#endif /* !_STANDALONE_ */
 
 
   static void
   }
 
 
-  const FT_Raster_Funcs  ft_grays_raster =
-  {
+  FT_DEFINE_RASTER_FUNCS(ft_grays_raster,
     FT_GLYPH_FORMAT_OUTLINE,
 
     (FT_Raster_New_Func)     gray_raster_new,
     (FT_Raster_Set_Mode_Func)0,
     (FT_Raster_Render_Func)  gray_raster_render,
     (FT_Raster_Done_Func)    gray_raster_done
-  };
+  )
 
 
 /* END */
+
+
+/* Local Variables: */
+/* coding: utf-8    */
+/* End:             */