< prev index next >

src/java.desktop/share/native/libfreetype/src/raster/ftraster.c

Print this page

        

@@ -1,53 +1,53 @@
-/***************************************************************************/
-/*                                                                         */
-/*  ftraster.c                                                             */
-/*                                                                         */
-/*    The FreeType glyph rasterizer (body).                                */
-/*                                                                         */
-/*  Copyright 1996-2018 by                                                 */
-/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
-/*                                                                         */
-/*  This file is part of the FreeType project, and may only be used,       */
-/*  modified, and distributed under the terms of the FreeType project      */
-/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
-/*  this file you indicate that you have read the license and              */
-/*  understand and accept it fully.                                        */
-/*                                                                         */
-/***************************************************************************/
+/****************************************************************************
+ *
+ * ftraster.c
+ *
+ *   The FreeType glyph rasterizer (body).
+ *
+ * Copyright (C) 1996-2019 by
+ * David Turner, Robert Wilhelm, and Werner Lemberg.
+ *
+ * This file is part of the FreeType project, and may only be used,
+ * modified, and distributed under the terms of the FreeType project
+ * license, LICENSE.TXT.  By continuing to use, modify, or distribute
+ * this file you indicate that you have read the license and
+ * understand and accept it fully.
+ *
+ */
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* This file can be compiled without the rest of the FreeType engine, by */
-  /* defining the STANDALONE_ macro when compiling it.  You also need to   */
-  /* put the files `ftimage.h' and `ftmisc.h' into the $(incdir)           */
-  /* directory.  Typically, you should do something like                   */
-  /*                                                                       */
-  /* - copy `src/raster/ftraster.c' (this file) to your current directory  */
-  /*                                                                       */
-  /* - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your */
-  /*   current directory                                                   */
-  /*                                                                       */
-  /* - compile `ftraster' with the STANDALONE_ macro defined, as in        */
-  /*                                                                       */
-  /*     cc -c -DSTANDALONE_ ftraster.c                                    */
-  /*                                                                       */
-  /* The renderer can be initialized with a call to                        */
-  /* `ft_standard_raster.raster_new'; a bitmap can be generated            */
-  /* with a call to `ft_standard_raster.raster_render'.                    */
-  /*                                                                       */
-  /* See the comments and documentation in the file `ftimage.h' for more   */
-  /* details on how the raster works.                                      */
-  /*                                                                       */
-  /*************************************************************************/
+  /**************************************************************************
+   *
+   * This file can be compiled without the rest of the FreeType engine, by
+   * defining the STANDALONE_ macro when compiling it.  You also need to
+   * put the files `ftimage.h' and `ftmisc.h' into the $(incdir)
+   * directory.  Typically, you should do something like
+   *
+   * - copy `src/raster/ftraster.c' (this file) to your current directory
+   *
+   * - copy `include/freetype/ftimage.h' and `src/raster/ftmisc.h' to your
+   *   current directory
+   *
+   * - compile `ftraster' with the STANDALONE_ macro defined, as in
+   *
+   *     cc -c -DSTANDALONE_ ftraster.c
+   *
+   * The renderer can be initialized with a call to
+   * `ft_standard_raster.raster_new'; a bitmap can be generated
+   * with a call to `ft_standard_raster.raster_render'.
+   *
+   * See the comments and documentation in the file `ftimage.h' for more
+   * details on how the raster works.
+   *
+   */
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* This is a rewrite of the FreeType 1.x scan-line converter             */
-  /*                                                                       */
-  /*************************************************************************/
+  /**************************************************************************
+   *
+   * This is a rewrite of the FreeType 1.x scan-line converter
+   *
+   */
 
 #ifdef STANDALONE_
 
   /* The size in bytes of the render pool used by the scan-line converter  */
   /* to do all of its work.                                                */

@@ -63,86 +63,85 @@
 #else /* !STANDALONE_ */
 
 #include <ft2build.h>
 #include "ftraster.h"
 #include FT_INTERNAL_CALC_H   /* for FT_MulDiv and FT_MulDiv_No_Round */
-
-#include "rastpic.h"
+#include FT_OUTLINE_H         /* for FT_Outline_Get_CBox              */
 
 #endif /* !STANDALONE_ */
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* A simple technical note on how the raster works                       */
-  /* -----------------------------------------------                       */
-  /*                                                                       */
-  /*   Converting an outline into a bitmap is achieved in several steps:   */
-  /*                                                                       */
-  /*   1 - Decomposing the outline into successive `profiles'.  Each       */
-  /*       profile is simply an array of scanline intersections on a given */
-  /*       dimension.  A profile's main attributes are                     */
-  /*                                                                       */
-  /*       o its scanline position boundaries, i.e. `Ymin' and `Ymax'      */
-  /*                                                                       */
-  /*       o an array of intersection coordinates for each scanline        */
-  /*         between `Ymin' and `Ymax'                                     */
-  /*                                                                       */
-  /*       o a direction, indicating whether it was built going `up' or    */
-  /*         `down', as this is very important for filling rules           */
-  /*                                                                       */
-  /*       o its drop-out mode                                             */
-  /*                                                                       */
-  /*   2 - Sweeping the target map's scanlines in order to compute segment */
-  /*       `spans' which are then filled.  Additionally, this pass         */
-  /*       performs drop-out control.                                      */
-  /*                                                                       */
-  /*   The outline data is parsed during step 1 only.  The profiles are    */
-  /*   built from the bottom of the render pool, used as a stack.  The     */
-  /*   following graphics shows the profile list under construction:       */
-  /*                                                                       */
-  /*     __________________________________________________________ _ _    */
-  /*    |         |                 |         |                 |          */
-  /*    | profile | coordinates for | profile | coordinates for |-->       */
-  /*    |    1    |  profile 1      |    2    |  profile 2      |-->       */
-  /*    |_________|_________________|_________|_________________|__ _ _    */
-  /*                                                                       */
-  /*    ^                                                       ^          */
-  /*    |                                                       |          */
-  /* start of render pool                                      top         */
-  /*                                                                       */
-  /*   The top of the profile stack is kept in the `top' variable.         */
-  /*                                                                       */
-  /*   As you can see, a profile record is pushed on top of the render     */
-  /*   pool, which is then followed by its coordinates/intersections.  If  */
-  /*   a change of direction is detected in the outline, a new profile is  */
-  /*   generated until the end of the outline.                             */
-  /*                                                                       */
-  /*   Note that when all profiles have been generated, the function       */
-  /*   Finalize_Profile_Table() is used to record, for each profile, its   */
-  /*   bottom-most scanline as well as the scanline above its upmost       */
-  /*   boundary.  These positions are called `y-turns' because they (sort  */
-  /*   of) correspond to local extrema.  They are stored in a sorted list  */
-  /*   built from the top of the render pool as a downwards stack:         */
-  /*                                                                       */
-  /*      _ _ _______________________________________                      */
-  /*                            |                    |                     */
-  /*                         <--| sorted list of     |                     */
-  /*                         <--|  extrema scanlines |                     */
-  /*      _ _ __________________|____________________|                     */
-  /*                                                                       */
-  /*                            ^                    ^                     */
-  /*                            |                    |                     */
-  /*                         maxBuff           sizeBuff = end of pool      */
-  /*                                                                       */
-  /*   This list is later used during the sweep phase in order to          */
-  /*   optimize performance (see technical note on the sweep below).       */
-  /*                                                                       */
-  /*   Of course, the raster detects whether the two stacks collide and    */
-  /*   handles the situation properly.                                     */
-  /*                                                                       */
-  /*************************************************************************/
+  /**************************************************************************
+   *
+   * A simple technical note on how the raster works
+   * -----------------------------------------------
+   *
+   *   Converting an outline into a bitmap is achieved in several steps:
+   *
+   *   1 - Decomposing the outline into successive `profiles'.  Each
+   *       profile is simply an array of scanline intersections on a given
+   *       dimension.  A profile's main attributes are
+   *
+   *       o its scanline position boundaries, i.e. `Ymin' and `Ymax'
+   *
+   *       o an array of intersection coordinates for each scanline
+   *         between `Ymin' and `Ymax'
+   *
+   *       o a direction, indicating whether it was built going `up' or
+   *         `down', as this is very important for filling rules
+   *
+   *       o its drop-out mode
+   *
+   *   2 - Sweeping the target map's scanlines in order to compute segment
+   *       `spans' which are then filled.  Additionally, this pass
+   *       performs drop-out control.
+   *
+   *   The outline data is parsed during step 1 only.  The profiles are
+   *   built from the bottom of the render pool, used as a stack.  The
+   *   following graphics shows the profile list under construction:
+   *
+   *    __________________________________________________________ _ _
+   *   |         |                 |         |                 |
+   *   | profile | coordinates for | profile | coordinates for |-->
+   *   |    1    |  profile 1      |    2    |  profile 2      |-->
+   *   |_________|_________________|_________|_________________|__ _ _
+   *
+   *   ^                                                       ^
+   *   |                                                       |
+   * start of render pool                                      top
+   *
+   *   The top of the profile stack is kept in the `top' variable.
+   *
+   *   As you can see, a profile record is pushed on top of the render
+   *   pool, which is then followed by its coordinates/intersections.  If
+   *   a change of direction is detected in the outline, a new profile is
+   *   generated until the end of the outline.
+   *
+   *   Note that when all profiles have been generated, the function
+   *   Finalize_Profile_Table() is used to record, for each profile, its
+   *   bottom-most scanline as well as the scanline above its upmost
+   *   boundary.  These positions are called `y-turns' because they (sort
+   *   of) correspond to local extrema.  They are stored in a sorted list
+   *   built from the top of the render pool as a downwards stack:
+   *
+   *     _ _ _______________________________________
+   *                           |                    |
+   *                        <--| sorted list of     |
+   *                        <--|  extrema scanlines |
+   *     _ _ __________________|____________________|
+   *
+   *                           ^                    ^
+   *                           |                    |
+   *                         maxBuff           sizeBuff = end of pool
+   *
+   *   This list is later used during the sweep phase in order to
+   *   optimize performance (see technical note on the sweep below).
+   *
+   *   Of course, the raster detects whether the two stacks collide and
+   *   handles the situation properly.
+   *
+   */
 
 
   /*************************************************************************/
   /*************************************************************************/
   /**                                                                     **/

@@ -161,18 +160,18 @@
   /**  OTHER MACROS (do not change)                                       **/
   /**                                                                     **/
   /*************************************************************************/
   /*************************************************************************/
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
-  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
-  /* messages during execution.                                            */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
+   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
+   * messages during execution.
+   */
 #undef  FT_COMPONENT
-#define FT_COMPONENT  trace_raster
+#define FT_COMPONENT  raster
 
 
 #ifdef STANDALONE_
 
   /* Auxiliary macros for token concatenation. */

@@ -450,13 +449,13 @@
 
 #define FLOOR( x )    ( (x) & -ras.precision )
 #define CEILING( x )  ( ( (x) + ras.precision - 1 ) & -ras.precision )
 #define TRUNC( x )    ( (Long)(x) >> ras.precision_bits )
 #define FRAC( x )     ( (x) & ( ras.precision - 1 ) )
-#define SCALED( x )   ( ( (x) < 0 ? -( -(x) << ras.scale_shift )   \
-                                  :  (  (x) << ras.scale_shift ) ) \
-                        - ras.precision_half )
+
+  /* scale and shift grid to pixel centers */
+#define SCALED( x )   ( (x) * ras.precision_scale - ras.precision_half )
 
 #define IS_BOTTOM_OVERSHOOT( x ) \
           (Bool)( CEILING( x ) - x >= ras.precision_half )
 #define IS_TOP_OVERSHOOT( x )    \
           (Bool)( x - FLOOR( x ) >= ras.precision_half )

@@ -474,17 +473,14 @@
   struct  black_TWorker_
   {
     Int         precision_bits;     /* precision related variables         */
     Int         precision;
     Int         precision_half;
-    Int         precision_shift;
+    Int         precision_scale;
     Int         precision_step;
     Int         precision_jitter;
 
-    Int         scale_shift;        /* == precision_shift   for bitmaps    */
-                                    /* == precision_shift+1 for pixmaps    */
-
     PLong       buff;               /* The profiles buffer                 */
     PLong       sizeBuff;           /* Render pool size                    */
     PLong       maxBuff;            /* Profiles buffer size                */
     PLong       top;                /* Current cursor in buffer            */
 

@@ -493,12 +489,11 @@
     Int         numTurns;           /* number of Y-turns in outline        */
 
     TPoint*     arc;                /* current Bezier arc pointer          */
 
     UShort      bWidth;             /* target bitmap width                 */
-    PByte       bTarget;            /* target bitmap buffer                */
-    PByte       gTarget;            /* target pixmap buffer                */
+    PByte       bOrigin;            /* target bitmap bottom-left origin    */
 
     Long        lastX, lastY;
     Long        minY, maxY;
 
     UShort      num_Profs;          /* current number of profiles          */

@@ -517,12 +512,10 @@
 
     FT_Bitmap   target;             /* description of target bit/pixmap    */
     FT_Outline  outline;
 
     Long        traceOfs;           /* current offset in target bitmap     */
-    Long        traceG;             /* current offset in target pixmap     */
-
     Short       traceIncr;          /* sweep's increment in target bitmap  */
 
     /* dispatch variables */
 
     Function_Sweep_Init*  Proc_Sweep_Init;

@@ -570,22 +563,23 @@
   /**                                                                     **/
   /*************************************************************************/
   /*************************************************************************/
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Set_High_Precision                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Set precision variables according to param flag.                   */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    High :: Set to True for high precision (typically for ppem < 24),  */
-  /*            false otherwise.                                           */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Set_High_Precision
+   *
+   * @Description:
+   *   Set precision variables according to param flag.
+   *
+   * @Input:
+   *   High ::
+   *     Set to True for high precision (typically for ppem < 24),
+   *     false otherwise.
+   */
   static void
   Set_High_Precision( RAS_ARGS Int  High )
   {
     /*
      * `precision_step' is used in `Bezier_Up' to decide when to split a

@@ -623,33 +617,35 @@
     }
 
     FT_TRACE6(( "Set_High_Precision(%s)\n", High ? "true" : "false" ));
 
     ras.precision       = 1 << ras.precision_bits;
-    ras.precision_half  = ras.precision / 2;
-    ras.precision_shift = ras.precision_bits - Pixel_Bits;
+    ras.precision_half  = ras.precision >> 1;
+    ras.precision_scale = ras.precision >> Pixel_Bits;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    New_Profile                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Create a new profile in the render pool.                           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    aState    :: The state/orientation of the new profile.             */
-  /*                                                                       */
-  /*    overshoot :: Whether the profile's unrounded start position        */
-  /*                 differs by at least a half pixel.                     */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*   SUCCESS on success.  FAILURE in case of overflow or of incoherent   */
-  /*   profile.                                                            */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   New_Profile
+   *
+   * @Description:
+   *   Create a new profile in the render pool.
+   *
+   * @Input:
+   *   aState ::
+   *     The state/orientation of the new profile.
+   *
+   *   overshoot ::
+   *     Whether the profile's unrounded start position
+   *     differs by at least a half pixel.
+   *
+   * @Return:
+   *  SUCCESS on success.  FAILURE in case of overflow or of incoherent
+   *  profile.
+   */
   static Bool
   New_Profile( RAS_ARGS TStates  aState,
                         Bool     overshoot )
   {
     if ( !ras.fProfile )

@@ -704,25 +700,26 @@
 
     return SUCCESS;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    End_Profile                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Finalize the current profile.                                      */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    overshoot :: Whether the profile's unrounded end position differs  */
-  /*                 by at least a half pixel.                             */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS on success.  FAILURE in case of overflow or incoherency.   */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   End_Profile
+   *
+   * @Description:
+   *   Finalize the current profile.
+   *
+   * @Input:
+   *   overshoot ::
+   *     Whether the profile's unrounded end position differs
+   *     by at least a half pixel.
+   *
+   * @Return:
+   *   SUCCESS on success.  FAILURE in case of overflow or incoherency.
+   */
   static Bool
   End_Profile( RAS_ARGS Bool  overshoot )
   {
     Long  h;
 

@@ -776,25 +773,25 @@
 
     return SUCCESS;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Insert_Y_Turn                                                      */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Insert a salient into the sorted list placed on top of the render  */
-  /*    pool.                                                              */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    New y scanline position.                                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Insert_Y_Turn
+   *
+   * @Description:
+   *   Insert a salient into the sorted list placed on top of the render
+   *   pool.
+   *
+   * @Input:
+   *   New y scanline position.
+   *
+   * @Return:
+   *   SUCCESS on success.  FAILURE in case of overflow.
+   */
   static Bool
   Insert_Y_Turn( RAS_ARGS Int  y )
   {
     PLong  y_turns;
     Int    n;

@@ -832,21 +829,21 @@
 
     return SUCCESS;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Finalize_Profile_Table                                             */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Adjust all links in the profiles list.                             */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS on success.  FAILURE in case of overflow.                  */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Finalize_Profile_Table
+   *
+   * @Description:
+   *   Adjust all links in the profiles list.
+   *
+   * @Return:
+   *   SUCCESS on success.  FAILURE in case of overflow.
+   */
   static Bool
   Finalize_Profile_Table( RAS_ARG )
   {
     UShort    n;
     PProfile  p;

@@ -892,26 +889,26 @@
 
     return SUCCESS;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Split_Conic                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Subdivide one conic Bezier into two joint sub-arcs in the Bezier   */
-  /*    stack.                                                             */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    None (subdivided Bezier is taken from the top of the stack).       */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    This routine is the `beef' of this component.  It is  _the_ inner  */
-  /*    loop that should be optimized to hell to get the best performance. */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Split_Conic
+   *
+   * @Description:
+   *   Subdivide one conic Bezier into two joint sub-arcs in the Bezier
+   *   stack.
+   *
+   * @Input:
+   *   None (subdivided Bezier is taken from the top of the stack).
+   *
+   * @Note:
+   *   This routine is the `beef' of this component.  It is  _the_ inner
+   *   loop that should be optimized to hell to get the best performance.
+   */
   static void
   Split_Conic( TPoint*  base )
   {
     Long  a, b;
 

@@ -931,24 +928,24 @@
     /* hand optimized.  gcc doesn't seem to be too good at common      */
     /* expression substitution and instruction scheduling ;-)          */
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Split_Cubic                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Subdivide a third-order Bezier arc into two joint sub-arcs in the  */
-  /*    Bezier stack.                                                      */
-  /*                                                                       */
-  /* <Note>                                                                */
-  /*    This routine is the `beef' of the component.  It is one of _the_   */
-  /*    inner loops that should be optimized like hell to get the best     */
-  /*    performance.                                                       */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Split_Cubic
+   *
+   * @Description:
+   *   Subdivide a third-order Bezier arc into two joint sub-arcs in the
+   *   Bezier stack.
+   *
+   * @Note:
+   *   This routine is the `beef' of the component.  It is one of _the_
+   *   inner loops that should be optimized like hell to get the best
+   *   performance.
+   */
   static void
   Split_Cubic( TPoint*  base )
   {
     Long  a, b, c, d;
 

@@ -973,35 +970,41 @@
     base[4].y = b = ( b + c + 1 ) >> 1;
     base[3].y = ( a + b + 1 ) >> 1;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Line_Up                                                            */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Compute the x-coordinates of an ascending line segment and store   */
-  /*    them in the render pool.                                           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    x1   :: The x-coordinate of the segment's start point.             */
-  /*                                                                       */
-  /*    y1   :: The y-coordinate of the segment's start point.             */
-  /*                                                                       */
-  /*    x2   :: The x-coordinate of the segment's end point.               */
-  /*                                                                       */
-  /*    y2   :: The y-coordinate of the segment's end point.               */
-  /*                                                                       */
-  /*    miny :: A lower vertical clipping bound value.                     */
-  /*                                                                       */
-  /*    maxy :: An upper vertical clipping bound value.                    */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS on success, FAILURE on render pool overflow.               */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Line_Up
+   *
+   * @Description:
+   *   Compute the x-coordinates of an ascending line segment and store
+   *   them in the render pool.
+   *
+   * @Input:
+   *   x1 ::
+   *     The x-coordinate of the segment's start point.
+   *
+   *   y1 ::
+   *     The y-coordinate of the segment's start point.
+   *
+   *   x2 ::
+   *     The x-coordinate of the segment's end point.
+   *
+   *   y2 ::
+   *     The y-coordinate of the segment's end point.
+   *
+   *   miny ::
+   *     A lower vertical clipping bound value.
+   *
+   *   maxy ::
+   *     An upper vertical clipping bound value.
+   *
+   * @Return:
+   *   SUCCESS on success, FAILURE on render pool overflow.
+   */
   static Bool
   Line_Up( RAS_ARGS Long  x1,
                     Long  y1,
                     Long  x2,
                     Long  y2,

@@ -1112,35 +1115,41 @@
     ras.top = top;
     return SUCCESS;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Line_Down                                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Compute the x-coordinates of an descending line segment and store  */
-  /*    them in the render pool.                                           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    x1   :: The x-coordinate of the segment's start point.             */
-  /*                                                                       */
-  /*    y1   :: The y-coordinate of the segment's start point.             */
-  /*                                                                       */
-  /*    x2   :: The x-coordinate of the segment's end point.               */
-  /*                                                                       */
-  /*    y2   :: The y-coordinate of the segment's end point.               */
-  /*                                                                       */
-  /*    miny :: A lower vertical clipping bound value.                     */
-  /*                                                                       */
-  /*    maxy :: An upper vertical clipping bound value.                    */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS on success, FAILURE on render pool overflow.               */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Line_Down
+   *
+   * @Description:
+   *   Compute the x-coordinates of an descending line segment and store
+   *   them in the render pool.
+   *
+   * @Input:
+   *   x1 ::
+   *     The x-coordinate of the segment's start point.
+   *
+   *   y1 ::
+   *     The y-coordinate of the segment's start point.
+   *
+   *   x2 ::
+   *     The x-coordinate of the segment's end point.
+   *
+   *   y2 ::
+   *     The y-coordinate of the segment's end point.
+   *
+   *   miny ::
+   *     A lower vertical clipping bound value.
+   *
+   *   maxy ::
+   *     An upper vertical clipping bound value.
+   *
+   * @Return:
+   *   SUCCESS on success, FAILURE on render pool overflow.
+   */
   static Bool
   Line_Down( RAS_ARGS Long  x1,
                       Long  y1,
                       Long  x2,
                       Long  y2,

@@ -1163,31 +1172,35 @@
 
   /* A function type describing the functions used to split Bezier arcs */
   typedef void  (*TSplitter)( TPoint*  base );
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Bezier_Up                                                          */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Compute the x-coordinates of an ascending Bezier arc and store     */
-  /*    them in the render pool.                                           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
-  /*                                                                       */
-  /*    splitter :: The function to split Bezier arcs.                     */
-  /*                                                                       */
-  /*    miny     :: A lower vertical clipping bound value.                 */
-  /*                                                                       */
-  /*    maxy     :: An upper vertical clipping bound value.                */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS on success, FAILURE on render pool overflow.               */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Bezier_Up
+   *
+   * @Description:
+   *   Compute the x-coordinates of an ascending Bezier arc and store
+   *   them in the render pool.
+   *
+   * @Input:
+   *   degree ::
+   *     The degree of the Bezier arc (either 2 or 3).
+   *
+   *   splitter ::
+   *     The function to split Bezier arcs.
+   *
+   *   miny ::
+   *     A lower vertical clipping bound value.
+   *
+   *   maxy ::
+   *     An upper vertical clipping bound value.
+   *
+   * @Return:
+   *   SUCCESS on success, FAILURE on render pool overflow.
+   */
   static Bool
   Bezier_Up( RAS_ARGS Int        degree,
                       TSplitter  splitter,
                       Long       miny,
                       Long       maxy )

@@ -1296,31 +1309,35 @@
     ras.arc -= degree;
     return SUCCESS;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Bezier_Down                                                        */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Compute the x-coordinates of an descending Bezier arc and store    */
-  /*    them in the render pool.                                           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    degree   :: The degree of the Bezier arc (either 2 or 3).          */
-  /*                                                                       */
-  /*    splitter :: The function to split Bezier arcs.                     */
-  /*                                                                       */
-  /*    miny     :: A lower vertical clipping bound value.                 */
-  /*                                                                       */
-  /*    maxy     :: An upper vertical clipping bound value.                */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS on success, FAILURE on render pool overflow.               */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Bezier_Down
+   *
+   * @Description:
+   *   Compute the x-coordinates of an descending Bezier arc and store
+   *   them in the render pool.
+   *
+   * @Input:
+   *   degree ::
+   *     The degree of the Bezier arc (either 2 or 3).
+   *
+   *   splitter ::
+   *     The function to split Bezier arcs.
+   *
+   *   miny ::
+   *     A lower vertical clipping bound value.
+   *
+   *   maxy ::
+   *     An upper vertical clipping bound value.
+   *
+   * @Return:
+   *   SUCCESS on success, FAILURE on render pool overflow.
+   */
   static Bool
   Bezier_Down( RAS_ARGS Int        degree,
                         TSplitter  splitter,
                         Long       miny,
                         Long       maxy )

@@ -1345,29 +1362,31 @@
     arc[0].y = -arc[0].y;
     return result;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Line_To                                                            */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Inject a new line segment and adjust the Profiles list.            */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*   x :: The x-coordinate of the segment's end point (its start point   */
-  /*        is stored in `lastX').                                         */
-  /*                                                                       */
-  /*   y :: The y-coordinate of the segment's end point (its start point   */
-  /*        is stored in `lastY').                                         */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
-  /*   profile.                                                            */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Line_To
+   *
+   * @Description:
+   *   Inject a new line segment and adjust the Profiles list.
+   *
+   * @Input:
+   *  x ::
+   *    The x-coordinate of the segment's end point (its start point
+   *    is stored in `lastX').
+   *
+   *  y ::
+   *    The y-coordinate of the segment's end point (its start point
+   *    is stored in `lastY').
+   *
+   * @Return:
+   *  SUCCESS on success, FAILURE on render pool overflow or incorrect
+   *  profile.
+   */
   static Bool
   Line_To( RAS_ARGS Long  x,
                     Long  y )
   {
     /* First, detect a change of direction */

@@ -1439,33 +1458,37 @@
 
     return SUCCESS;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Conic_To                                                           */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Inject a new conic arc and adjust the profile list.                */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*   cx :: The x-coordinate of the arc's new control point.              */
-  /*                                                                       */
-  /*   cy :: The y-coordinate of the arc's new control point.              */
-  /*                                                                       */
-  /*   x  :: The x-coordinate of the arc's end point (its start point is   */
-  /*         stored in `lastX').                                           */
-  /*                                                                       */
-  /*   y  :: The y-coordinate of the arc's end point (its start point is   */
-  /*         stored in `lastY').                                           */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
-  /*   profile.                                                            */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Conic_To
+   *
+   * @Description:
+   *   Inject a new conic arc and adjust the profile list.
+   *
+   * @Input:
+   *  cx ::
+   *    The x-coordinate of the arc's new control point.
+   *
+   *  cy ::
+   *    The y-coordinate of the arc's new control point.
+   *
+   *  x ::
+   *    The x-coordinate of the arc's end point (its start point is
+   *    stored in `lastX').
+   *
+   *  y ::
+   *    The y-coordinate of the arc's end point (its start point is
+   *    stored in `lastY').
+   *
+   * @Return:
+   *  SUCCESS on success, FAILURE on render pool overflow or incorrect
+   *  profile.
+   */
   static Bool
   Conic_To( RAS_ARGS Long  cx,
                      Long  cy,
                      Long  x,
                      Long  y )

@@ -1556,37 +1579,43 @@
   Fail:
     return FAILURE;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Cubic_To                                                           */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Inject a new cubic arc and adjust the profile list.                */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*   cx1 :: The x-coordinate of the arc's first new control point.       */
-  /*                                                                       */
-  /*   cy1 :: The y-coordinate of the arc's first new control point.       */
-  /*                                                                       */
-  /*   cx2 :: The x-coordinate of the arc's second new control point.      */
-  /*                                                                       */
-  /*   cy2 :: The y-coordinate of the arc's second new control point.      */
-  /*                                                                       */
-  /*   x   :: The x-coordinate of the arc's end point (its start point is  */
-  /*          stored in `lastX').                                          */
-  /*                                                                       */
-  /*   y   :: The y-coordinate of the arc's end point (its start point is  */
-  /*          stored in `lastY').                                          */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*   SUCCESS on success, FAILURE on render pool overflow or incorrect    */
-  /*   profile.                                                            */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Cubic_To
+   *
+   * @Description:
+   *   Inject a new cubic arc and adjust the profile list.
+   *
+   * @Input:
+   *  cx1 ::
+   *    The x-coordinate of the arc's first new control point.
+   *
+   *  cy1 ::
+   *    The y-coordinate of the arc's first new control point.
+   *
+   *  cx2 ::
+   *    The x-coordinate of the arc's second new control point.
+   *
+   *  cy2 ::
+   *    The y-coordinate of the arc's second new control point.
+   *
+   *  x ::
+   *    The x-coordinate of the arc's end point (its start point is
+   *    stored in `lastX').
+   *
+   *  y ::
+   *    The y-coordinate of the arc's end point (its start point is
+   *    stored in `lastY').
+   *
+   * @Return:
+   *  SUCCESS on success, FAILURE on render pool overflow or incorrect
+   *  profile.
+   */
   static Bool
   Cubic_To( RAS_ARGS Long  cx1,
                      Long  cy1,
                      Long  cx2,
                      Long  cy2,

@@ -1703,31 +1732,34 @@
                          x = y;          \
                          y = swap;       \
                        } while ( 0 )
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Decompose_Curve                                                    */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Scan the outline arrays in order to emit individual segments and   */
-  /*    Beziers by calling Line_To() and Bezier_To().  It handles all      */
-  /*    weird cases, like when the first point is off the curve, or when   */
-  /*    there are simply no `on' points in the contour!                    */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    first   :: The index of the first point in the contour.            */
-  /*                                                                       */
-  /*    last    :: The index of the last point in the contour.             */
-  /*                                                                       */
-  /*    flipped :: If set, flip the direction of the curve.                */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS on success, FAILURE on error.                              */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Decompose_Curve
+   *
+   * @Description:
+   *   Scan the outline arrays in order to emit individual segments and
+   *   Beziers by calling Line_To() and Bezier_To().  It handles all
+   *   weird cases, like when the first point is off the curve, or when
+   *   there are simply no `on' points in the contour!
+   *
+   * @Input:
+   *   first ::
+   *     The index of the first point in the contour.
+   *
+   *   last ::
+   *     The index of the last point in the contour.
+   *
+   *   flipped ::
+   *     If set, flip the direction of the curve.
+   *
+   * @Return:
+   *   SUCCESS on success, FAILURE on error.
+   */
   static Bool
   Decompose_Curve( RAS_ARGS UShort  first,
                             UShort  last,
                             Int     flipped )
   {

@@ -1932,26 +1964,27 @@
   Fail:
     return FAILURE;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Convert_Glyph                                                      */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Convert a glyph into a series of segments and arcs and make a      */
-  /*    profiles list with them.                                           */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    flipped :: If set, flip the direction of curve.                    */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    SUCCESS on success, FAILURE if any error was encountered during    */
-  /*    rendering.                                                         */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Convert_Glyph
+   *
+   * @Description:
+   *   Convert a glyph into a series of segments and arcs and make a
+   *   profiles list with them.
+   *
+   * @Input:
+   *   flipped ::
+   *     If set, flip the direction of curve.
+   *
+   * @Return:
+   *   SUCCESS on success, FAILURE if any error was encountered during
+   *   rendering.
+   */
   static Bool
   Convert_Glyph( RAS_ARGS Int  flipped )
   {
     Int   i;
     UInt  start;

@@ -2026,29 +2059,29 @@
   /**                                                                     **/
   /*************************************************************************/
   /*************************************************************************/
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /*  Init_Linked                                                          */
-  /*                                                                       */
-  /*    Initializes an empty linked list.                                  */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * Init_Linked
+   *
+   *   Initializes an empty linked list.
+   */
   static void
   Init_Linked( TProfileList*  l )
   {
     *l = NULL;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /*  InsNew                                                               */
-  /*                                                                       */
-  /*    Inserts a new profile in a linked list.                            */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * InsNew
+   *
+   *   Inserts a new profile in a linked list.
+   */
   static void
   InsNew( PProfileList  list,
           PProfile      profile )
   {
     PProfile  *old, current;

@@ -2070,16 +2103,16 @@
     profile->link = current;
     *old          = profile;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /*  DelOld                                                               */
-  /*                                                                       */
-  /*    Removes an old profile from a linked list.                         */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * DelOld
+   *
+   *   Removes an old profile from a linked list.
+   */
   static void
   DelOld( PProfileList  list,
           PProfile      profile )
   {
     PProfile  *old, current;

@@ -2103,18 +2136,18 @@
     /* we should never get there, unless the profile was not part of */
     /* the list.                                                     */
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /*  Sort                                                                 */
-  /*                                                                       */
-  /*    Sorts a trace list.  In 95%, the list is already sorted.  We need  */
-  /*    an algorithm which is fast in this case.  Bubble sort is enough    */
-  /*    and simple.                                                        */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * Sort
+   *
+   *   Sorts a trace list.  In 95%, the list is already sorted.  We need
+   *   an algorithm which is fast in this case.  Bubble sort is enough
+   *   and simple.
+   */
   static void
   Sort( PProfileList  list )
   {
     PProfile  *old, current, next;
 

@@ -2161,18 +2194,18 @@
       next = current->link;
     }
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /*  Vertical Sweep Procedure Set                                         */
-  /*                                                                       */
-  /*  These four routines are used during the vertical black/white sweep   */
-  /*  phase by the generic Draw_Sweep() function.                          */
-  /*                                                                       */
-  /*************************************************************************/
+  /**************************************************************************
+   *
+   * Vertical Sweep Procedure Set
+   *
+   * These four routines are used during the vertical black/white sweep
+   * phase by the generic Draw_Sweep() function.
+   *
+   */
 
   static void
   Vertical_Sweep_Init( RAS_ARGS Short*  min,
                                 Short*  max )
   {

@@ -2181,12 +2214,10 @@
     FT_UNUSED( max );
 
 
     ras.traceIncr = (Short)-pitch;
     ras.traceOfs  = -*min * pitch;
-    if ( pitch > 0 )
-      ras.traceOfs += (Long)( ras.target.rows - 1 ) * pitch;
   }
 
 
   static void
   Vertical_Sweep_Span( RAS_ARGS Short       y,

@@ -2213,17 +2244,22 @@
                 x2 / (double)ras.precision,
                 dropOutControl ));
 
     /* Drop-out control */
 
-    e1 = TRUNC( CEILING( x1 ) );
+    e1 = CEILING( x1 );
+    e2 = FLOOR( x2 );
 
+    /* take care of the special case where both the left */
+    /* and right contour lie exactly on pixel centers    */
     if ( dropOutControl != 2                             &&
-         x2 - x1 - ras.precision <= ras.precision_jitter )
+         x2 - x1 - ras.precision <= ras.precision_jitter &&
+         e1 != x1 && e2 != x2                            )
       e2 = e1;
-    else
-      e2 = TRUNC( FLOOR( x2 ) );
+
+    e1 = TRUNC( e1 );
+    e2 = TRUNC( e2 );
 
     if ( e2 >= 0 && e1 < ras.bWidth )
     {
       Int   c1, c2;
       Byte  f1, f2;

@@ -2240,26 +2276,23 @@
       c2 = (Short)( e2 >> 3 );
 
       f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
       f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
 
-      target = ras.bTarget + ras.traceOfs + c1;
+      target = ras.bOrigin + ras.traceOfs + c1;
       c2 -= c1;
 
       if ( c2 > 0 )
       {
         target[0] |= f1;
 
         /* memset() is slower than the following code on many platforms. */
         /* This is due to the fact that, in the vast majority of cases,  */
         /* the span length in bytes is relatively small.                 */
-        c2--;
-        while ( c2 > 0 )
-        {
+        while ( --c2 > 0 )
           *(++target) = 0xFF;
-          c2--;
-        }
+
         target[1] |= f2;
       }
       else
         *target |= ( f1 & f2 );
     }

@@ -2398,11 +2431,11 @@
 
         c1 = (Short)( e1 >> 3 );
         f1 = (Short)( e1 &  7 );
 
         if ( e1 >= 0 && e1 < ras.bWidth                      &&
-             ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+             ras.bOrigin[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
           goto Exit;
       }
       else
         goto Exit;
     }

@@ -2414,11 +2447,11 @@
       FT_TRACE7(( " -> x=%d (drop-out)", e1 ));
 
       c1 = (Short)( e1 >> 3 );
       f1 = (Short)( e1 & 7 );
 
-      ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
+      ras.bOrigin[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
     }
 
   Exit:
     FT_TRACE7(( "\n" ));
   }

@@ -2429,18 +2462,18 @@
   {
     ras.traceOfs += ras.traceIncr;
   }
 
 
-  /***********************************************************************/
-  /*                                                                     */
-  /*  Horizontal Sweep Procedure Set                                     */
-  /*                                                                     */
-  /*  These four routines are used during the horizontal black/white     */
-  /*  sweep phase by the generic Draw_Sweep() function.                  */
-  /*                                                                     */
-  /***********************************************************************/
+  /************************************************************************
+   *
+   * Horizontal Sweep Procedure Set
+   *
+   * These four routines are used during the horizontal black/white
+   * sweep phase by the generic Draw_Sweep() function.
+   *
+   */
 
   static void
   Horizontal_Sweep_Init( RAS_ARGS Short*  min,
                                   Short*  max )
   {

@@ -2481,23 +2514,18 @@
 
         if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
         {
           Byte   f1;
           PByte  bits;
-          PByte  p;
 
 
           FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
 
-          bits = ras.bTarget + ( y >> 3 );
+          bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
           f1   = (Byte)( 0x80 >> ( y & 7 ) );
-          p    = bits - e1 * ras.target.pitch;
 
-          if ( ras.target.pitch > 0 )
-            p += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
-
-          p[0] |= f1;
+          bits[0] |= f1;
         }
       }
 
       FT_TRACE7(( "\n" ));
     }

@@ -2595,17 +2623,13 @@
         /* check that the other pixel isn't set */
         e1 = ( pxl == e1 ) ? e2 : e1;
 
         e1 = TRUNC( e1 );
 
-        bits = ras.bTarget + ( y >> 3 );
+        bits = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
         f1   = (Byte)( 0x80 >> ( y & 7 ) );
 
-        bits -= e1 * ras.target.pitch;
-        if ( ras.target.pitch > 0 )
-          bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
-
         if ( e1 >= 0                     &&
              (ULong)e1 < ras.target.rows &&
              *bits & f1                  )
           goto Exit;
       }

@@ -2617,16 +2641,12 @@
 
     if ( e1 >= 0 && (ULong)e1 < ras.target.rows )
     {
       FT_TRACE7(( " -> y=%d (drop-out)", e1 ));
 
-      bits  = ras.bTarget + ( y >> 3 );
+      bits  = ras.bOrigin + ( y >> 3 ) - e1 * ras.target.pitch;
       f1    = (Byte)( 0x80 >> ( y & 7 ) );
-      bits -= e1 * ras.target.pitch;
-
-      if ( ras.target.pitch > 0 )
-        bits += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
 
       bits[0] |= f1;
     }
 
   Exit:

@@ -2640,15 +2660,15 @@
     /* Nothing, really */
     FT_UNUSED_RASTER;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /*  Generic Sweep Drawing routine                                        */
-  /*                                                                       */
-  /*************************************************************************/
+  /**************************************************************************
+   *
+   * Generic Sweep Drawing routine
+   *
+   */
 
   static Bool
   Draw_Sweep( RAS_ARG )
   {
     Short         y, y_change, y_height;

@@ -2886,24 +2906,113 @@
 
     goto Next_Line;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Render_Single_Pass                                                 */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Perform one sweep with sub-banding.                                */
-  /*                                                                       */
-  /* <Input>                                                               */
-  /*    flipped :: If set, flip the direction of the outline.              */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    Renderer error code.                                               */
-  /*                                                                       */
+#ifdef STANDALONE_
+
+  /**************************************************************************
+   *
+   * The following functions should only compile in stand-alone mode,
+   * i.e., when building this component without the rest of FreeType.
+   *
+   */
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   FT_Outline_Get_CBox
+   *
+   * @Description:
+   *   Return an outline's `control box'.  The control box encloses all
+   *   the outline's points, including Bézier control points.  Though it
+   *   coincides with the exact bounding box for most glyphs, it can be
+   *   slightly larger in some situations (like when rotating an outline
+   *   that contains Bézier outside arcs).
+   *
+   *   Computing the control box is very fast, while getting the bounding
+   *   box can take much more time as it needs to walk over all segments
+   *   and arcs in the outline.  To get the latter, you can use the
+   *   `ftbbox' component, which is dedicated to this single task.
+   *
+   * @Input:
+   *   outline ::
+   *     A pointer to the source outline descriptor.
+   *
+   * @Output:
+   *   acbox ::
+   *     The outline's control box.
+   *
+   * @Note:
+   *   See @FT_Glyph_Get_CBox for a discussion of tricky fonts.
+   */
+
+  static void
+  FT_Outline_Get_CBox( const FT_Outline*  outline,
+                       FT_BBox           *acbox )
+  {
+    Long  xMin, yMin, xMax, yMax;
+
+
+    if ( outline && acbox )
+    {
+      if ( outline->n_points == 0 )
+      {
+        xMin = 0;
+        yMin = 0;
+        xMax = 0;
+        yMax = 0;
+      }
+      else
+      {
+        FT_Vector*  vec   = outline->points;
+        FT_Vector*  limit = vec + outline->n_points;
+
+
+        xMin = xMax = vec->x;
+        yMin = yMax = vec->y;
+        vec++;
+
+        for ( ; vec < limit; vec++ )
+        {
+          Long  x, y;
+
+
+          x = vec->x;
+          if ( x < xMin ) xMin = x;
+          if ( x > xMax ) xMax = x;
+
+          y = vec->y;
+          if ( y < yMin ) yMin = y;
+          if ( y > yMax ) yMax = y;
+        }
+      }
+      acbox->xMin = xMin;
+      acbox->xMax = xMax;
+      acbox->yMin = yMin;
+      acbox->yMax = yMax;
+    }
+  }
+
+#endif /* STANDALONE_ */
+
+
+  /**************************************************************************
+   *
+   * @Function:
+   *   Render_Single_Pass
+   *
+   * @Description:
+   *   Perform one sweep with sub-banding.
+   *
+   * @Input:
+   *   flipped ::
+   *     If set, flip the direction of the outline.
+   *
+   * @Return:
+   *   Renderer error code.
+   */
   static int
   Render_Single_Pass( RAS_ARGS Bool  flipped )
   {
     Short  i, j, k;
 

@@ -2961,30 +3070,29 @@
 
     return SUCCESS;
   }
 
 
-  /*************************************************************************/
-  /*                                                                       */
-  /* <Function>                                                            */
-  /*    Render_Glyph                                                       */
-  /*                                                                       */
-  /* <Description>                                                         */
-  /*    Render a glyph in a bitmap.  Sub-banding if needed.                */
-  /*                                                                       */
-  /* <Return>                                                              */
-  /*    FreeType error code.  0 means success.                             */
-  /*                                                                       */
+  /**************************************************************************
+   *
+   * @Function:
+   *   Render_Glyph
+   *
+   * @Description:
+   *   Render a glyph in a bitmap.  Sub-banding if needed.
+   *
+   * @Return:
+   *   FreeType error code.  0 means success.
+   */
   static FT_Error
   Render_Glyph( RAS_ARG )
   {
     FT_Error  error;
 
 
     Set_High_Precision( RAS_VARS ras.outline.flags &
                                  FT_OUTLINE_HIGH_PRECISION );
-    ras.scale_shift = ras.precision_shift;
 
     if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
       ras.dropOutControl = 2;
     else
     {

@@ -3011,11 +3119,14 @@
     ras.band_top            = 0;
     ras.band_stack[0].y_min = 0;
     ras.band_stack[0].y_max = (Short)( ras.target.rows - 1 );
 
     ras.bWidth  = (UShort)ras.target.width;
-    ras.bTarget = (Byte*)ras.target.buffer;
+    ras.bOrigin = (Byte*)ras.target.buffer;
+
+    if ( ras.target.pitch > 0 )
+      ras.bOrigin += (Long)( ras.target.rows - 1 ) * ras.target.pitch;
 
     if ( ( error = Render_Single_Pass( RAS_VARS 0 ) ) != 0 )
       return error;
 
     /* Horizontal Sweep */

@@ -3183,24 +3294,10 @@
       return Raster_Err_None;
 
     if ( !target_map->buffer )
       return FT_THROW( Invalid );
 
-    /* reject too large outline coordinates */
-    {
-      FT_Vector*  vec   = outline->points;
-      FT_Vector*  limit = vec + outline->n_points;
-
-
-      for ( ; vec < limit; vec++ )
-      {
-        if ( vec->x < -0x1000000L || vec->x > 0x1000000L ||
-             vec->y < -0x1000000L || vec->y > 0x1000000L )
-         return FT_THROW( Invalid );
-      }
-    }
-
     ras.outline = *outline;
     ras.target  = *target_map;
 
     worker->buff     = buffer;
     worker->sizeBuff = (&buffer)[1]; /* Points to right after buffer. */
< prev index next >