shithub: freetype+ttf2subf

Download patch

ref: 5df5dbb722cf008b3f617448d8d28fde4d725556
parent: c91dfa39e8863318f092b4d38b31e7dca32d5b40
author: Werner Lemberg <[email protected]>
date: Sun Jun 22 09:40:08 EDT 2008

Enable access to the various dropout rules of the B&W rasterizer.
Pass dropout rules from the TT bytecode interpreter to the
rasterizer; temporarily this is enabled only if
`USE_SCAN_CONVERSION_RULES' is defined.

* include/freetype/ftimage.h (FT_OUTLINE_SMART_DROPOUTS,
FT_OUTLINE_EXCLUDE_STUBS): New flags for for FT_Outline.

* src/raster/ftraster.c (Vertical_Sweep_Drop, Horizontal_Sweep_Drop,
Horizontal_Gray_Sweep_Drop): Use same mode numbers as given in the
OpenType specification.
Fix mode 4 computation.
(Render_Glyph, Render_Gray_Glyph): Handle new outline flags.

* src/truetype/ttgload.c (TT_Load_Glyph)
[USE_SCAN_CONVERSION_RULES]: Convert scan conversion mode to
FT_OUTLINE_XXX flags.

* src/truetype/ttinterp.c (Ins_SCANCTRL): Enable ppem check.

git/fs: mount .git/fs: mount/attach disallowed
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,25 @@
+2008-06-21  Werner Lemberg  <[email protected]>
+
+	Enable access to the various dropout rules of the B&W rasterizer.
+	Pass dropout rules from the TT bytecode interpreter to the
+	rasterizer; temporarily this is enabled only if
+	`USE_SCAN_CONVERSION_RULES' is defined.
+
+	* include/freetype/ftimage.h (FT_OUTLINE_SMART_DROPOUTS,
+	FT_OUTLINE_EXCLUDE_STUBS): New flags for for FT_Outline.
+
+	* src/raster/ftraster.c (Vertical_Sweep_Drop, Horizontal_Sweep_Drop,
+	Horizontal_Gray_Sweep_Drop): Use same mode numbers as given in the
+	OpenType specification.
+	Fix mode 4 computation.
+	(Render_Glyph, Render_Gray_Glyph): Handle new outline flags.
+
+	* src/truetype/ttgload.c (TT_Load_Glyph)
+	[USE_SCAN_CONVERSION_RULES]: Convert scan conversion mode to
+	FT_OUTLINE_XXX flags.
+
+	* src/truetype/ttinterp.c (Ins_SCANCTRL): Enable ppem check.
+
 2008-06-19  Werner Lemberg  <[email protected]>
 
 	* src/cff/cffobjs.c (cff_face_init): Compute final
--- a/include/freetype/ftimage.h
+++ b/include/freetype/ftimage.h
@@ -352,7 +352,7 @@
   /*************************************************************************/
   /*                                                                       */
   /* <Enum>                                                                */
-  /*   FT_OUTLINE_FLAGS                                                    */
+  /*    FT_OUTLINE_FLAGS                                                   */
   /*                                                                       */
   /* <Description>                                                         */
   /*    A list of bit-field constants use for the flags in an outline's    */
@@ -359,60 +359,66 @@
   /*    `flags' field.                                                     */
   /*                                                                       */
   /* <Values>                                                              */
-  /*    FT_OUTLINE_NONE           :: Value 0 is reserved.                  */
+  /*    FT_OUTLINE_NONE ::                                                 */
+  /*      Value 0 is reserved.                                             */
   /*                                                                       */
-  /*    FT_OUTLINE_OWNER          :: If set, this flag indicates that the  */
-  /*                                 outline's field arrays (i.e.,         */
-  /*                                 `points', `flags' & `contours') are   */
-  /*                                 `owned' by the outline object, and    */
-  /*                                 should thus be freed when it is       */
-  /*                                 destroyed.                            */
+  /*    FT_OUTLINE_OWNER ::                                                */
+  /*      If set, this flag indicates that the outline's field arrays      */
+  /*      (i.e., `points', `flags', and `contours') are `owned' by the     */
+  /*      outline object, and should thus be freed when it is destroyed.   */
   /*                                                                       */
-  /*   FT_OUTLINE_EVEN_ODD_FILL   :: By default, outlines are filled using */
-  /*                                 the non-zero winding rule.  If set to */
-  /*                                 1, the outline will be filled using   */
-  /*                                 the even-odd fill rule (only works    */
-  /*                                 with the smooth raster).              */
+  /*    FT_OUTLINE_EVEN_ODD_FILL ::                                        */
+  /*      By default, outlines are filled using the non-zero winding rule. */
+  /*      If set to 1, the outline will be filled using the even-odd fill  */
+  /*      rule (only works with the smooth raster).                        */
   /*                                                                       */
-  /*   FT_OUTLINE_REVERSE_FILL    :: By default, outside contours of an    */
-  /*                                 outline are oriented in clock-wise    */
-  /*                                 direction, as defined in the TrueType */
-  /*                                 specification.  This flag is set if   */
-  /*                                 the outline uses the opposite         */
-  /*                                 direction (typically for Type 1       */
-  /*                                 fonts).  This flag is ignored by the  */
-  /*                                 scan-converter.                       */
+  /*    FT_OUTLINE_REVERSE_FILL ::                                         */
+  /*      By default, outside contours of an outline are oriented in       */
+  /*      clock-wise direction, as defined in the TrueType specification.  */
+  /*      This flag is set if the outline uses the opposite direction      */
+  /*      (typically for Type 1 fonts).  This flag is ignored by the scan  */
+  /*      converter.                                                       */
   /*                                                                       */
-  /*   FT_OUTLINE_IGNORE_DROPOUTS :: By default, the scan converter will   */
-  /*                                 try to detect drop-outs in an outline */
-  /*                                 and correct the glyph bitmap to       */
-  /*                                 ensure consistent shape continuity.   */
-  /*                                 If set, this flag hints the scan-line */
-  /*                                 converter to ignore such cases.       */
+  /*    FT_OUTLINE_IGNORE_DROPOUTS ::                                      */
+  /*      By default, the scan converter will try to detect drop-outs in   */
+  /*      an outline and correct the glyph bitmap to ensure consistent     */
+  /*      shape continuity.  If set, this flag hints the scan-line         */
+  /*      converter to ignore such cases.                                  */
   /*                                                                       */
-  /*   FT_OUTLINE_HIGH_PRECISION  :: This flag indicates that the          */
-  /*                                 scan-line converter should try to     */
-  /*                                 convert this outline to bitmaps with  */
-  /*                                 the highest possible quality.  It is  */
-  /*                                 typically set for small character     */
-  /*                                 sizes.  Note that this is only a      */
-  /*                                 hint, that might be completely        */
-  /*                                 ignored by a given scan-converter.    */
+  /*    FT_OUTLINE_SMART_DROPOUTS ::                                       */
+  /*      Select smart dropout control.  If unset, use simple dropout      */
+  /*      control.  Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set.         */
   /*                                                                       */
-  /*   FT_OUTLINE_SINGLE_PASS     :: This flag is set to force a given     */
-  /*                                 scan-converter to only use a single   */
-  /*                                 pass over the outline to render a     */
-  /*                                 bitmap glyph image.  Normally, it is  */
-  /*                                 set for very large character sizes.   */
-  /*                                 It is only a hint, that might be      */
-  /*                                 completely ignored by a given         */
-  /*                                 scan-converter.                       */
+  /*    FT_OUTLINE_INCLUDE_STUBS ::                                        */
+  /*      If set, turn pixels on for `stubs', otherwise exclude them.      */
+  /*      Ignored if @FT_OUTLINE_IGNORE_DROPOUTS is set.                   */
   /*                                                                       */
+  /*    FT_OUTLINE_HIGH_PRECISION ::                                       */
+  /*      This flag indicates that the scan-line converter should try to   */
+  /*      convert this outline to bitmaps with the highest possible        */
+  /*      quality.  It is typically set for small character sizes.  Note   */
+  /*      that this is only a hint that might be completely ignored by a   */
+  /*      given scan-converter.                                            */
+  /*                                                                       */
+  /*    FT_OUTLINE_SINGLE_PASS ::                                          */
+  /*      This flag is set to force a given scan-converter to only use a   */
+  /*      single pass over the outline to render a bitmap glyph image.     */
+  /*      Normally, it is set for very large character sizes.  It is only  */
+  /*      a hint that might be completely ignored by a given               */
+  /*      scan-converter.                                                  */
+  /*                                                                       */
+  /* <Note>                                                                */
+  /*    Please refer to the description of the `SCANTYPE' instruction in   */
+  /*    the OpenType specification (in file `ttinst1.doc') how simple      */
+  /*    drop-outs, smart drop-outs, and stubs are defined.                 */
+  /*                                                                       */
 #define FT_OUTLINE_NONE             0x0
 #define FT_OUTLINE_OWNER            0x1
 #define FT_OUTLINE_EVEN_ODD_FILL    0x2
 #define FT_OUTLINE_REVERSE_FILL     0x4
 #define FT_OUTLINE_IGNORE_DROPOUTS  0x8
+#define FT_OUTLINE_SMART_DROPOUTS   0x10
+#define FT_OUTLINE_INCLUDE_STUBS    0x20
 
 #define FT_OUTLINE_HIGH_PRECISION   0x100
 #define FT_OUTLINE_SINGLE_PASS      0x200
--- a/include/freetype/internal/ftgloadr.h
+++ b/include/freetype/internal/ftgloadr.h
@@ -67,11 +67,11 @@
 
   typedef struct  FT_GlyphLoadRec_
   {
-    FT_Outline   outline;       /* outline             */
-    FT_Vector*   extra_points;  /* extra points table  */
+    FT_Outline   outline;       /* outline                   */
+    FT_Vector*   extra_points;  /* extra points table        */
     FT_Vector*   extra_points2; /* second extra points table */
-    FT_UInt      num_subglyphs; /* number of subglyphs */
-    FT_SubGlyph  subglyphs;     /* subglyphs           */
+    FT_UInt      num_subglyphs; /* number of subglyphs       */
+    FT_SubGlyph  subglyphs;     /* subglyphs                 */
 
   } FT_GlyphLoadRec, *FT_GlyphLoad;
 
--- a/src/raster/ftraster.c
+++ b/src/raster/ftraster.c
@@ -2150,8 +2150,10 @@
       f1 = (Byte)  ( 0xFF >> ( e1 & 7 ) );
       f2 = (Byte) ~( 0x7F >> ( e2 & 7 ) );
 
-      if ( ras.gray_min_x > c1 ) ras.gray_min_x = (short)c1;
-      if ( ras.gray_max_x < c2 ) ras.gray_max_x = (short)c2;
+      if ( ras.gray_min_x > c1 )
+        ras.gray_min_x = (short)c1;
+      if ( ras.gray_max_x < c2 )
+        ras.gray_max_x = (short)c2;
 
       target = ras.bTarget + ras.traceOfs + c1;
       c2 -= c1;
@@ -2184,15 +2186,44 @@
                                 PProfile    left,
                                 PProfile    right )
   {
-    Long   e1, e2;
+    Long   e1, e2, pxl;
     Short  c1, f1;
 
 
     /* Drop-out control */
 
-    e1 = CEILING( x1 );
-    e2 = FLOOR  ( x2 );
+    /*   e2            x2                    x1           e1   */
+    /*                                                         */
+    /*                 ^                     |                 */
+    /*                 |                     |                 */
+    /*   +-------------+---------------------+------------+    */
+    /*                 |                     |                 */
+    /*                 |                     v                 */
+    /*                                                         */
+    /* pixel         contour              contour       pixel  */
+    /* center                                           center */
 
+    /* drop-out mode    scan conversion rules (as defined in OpenType) */
+    /* --------------------------------------------------------------- */
+    /*  0                1, 2, 3                                       */
+    /*  1                1, 2, 4                                       */
+    /*  2                1, 2                                          */
+    /*  3                same as mode 2                                */
+    /*  4                1, 2, 5                                       */
+    /*  5                1, 2, 6                                       */
+    /*  6, 7             same as mode 2                                */
+
+    /* FIXXXME: The specification doesn't discuss the case where the */
+    /*          intersections degenerate to a single point.          */
+#if 0
+    if ( x1 == x2 )
+      return;
+#endif
+
+    e1  = CEILING( x1 );
+    e2  = FLOOR  ( x2 );
+    pxl = e1;
+
     if ( e1 > e2 )
     {
       if ( e1 == e2 + ras.precision )
@@ -2199,19 +2230,20 @@
       {
         switch ( ras.dropOutControl )
         {
-        case 1:
-          e1 = e2;
+        case 0: /* simple drop-outs including stubs */
+          pxl = e2;
           break;
 
-        case 4:
-          e1 = CEILING( (x1 + x2 + 1) / 2 );
+        case 4: /* smart drop-outs including stubs */
+          pxl = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
           break;
 
-        case 2:
-        case 5:
-          /* Drop-out Control Rule #4 */
+        case 1: /* simple drop-outs excluding stubs */
+        case 5: /* smart drop-outs excluding stubs  */
 
-          /* The spec is not very clear regarding rule #4.  It      */
+          /* Drop-out Control Rules #4 and #6 */
+
+          /* The spec is not very clear regarding those rules.  It  */
           /* presents a method that is way too costly to implement  */
           /* while the general idea seems to get rid of `stubs'.    */
           /*                                                        */
@@ -2233,7 +2265,6 @@
           /* FIXXXME: uncommenting this line solves the disappearing */
           /*          bit problem in the `7' of verdana 10pts, but   */
           /*          makes a new one in the `C' of arial 14pts      */
-
 #if 0
           if ( x2 - x1 < ras.precision_half )
 #endif
@@ -2247,33 +2278,33 @@
               return;
           }
 
-          /* check that the rightmost pixel isn't set */
+          if ( ras.dropOutControl == 1 )
+            pxl = e2;
+          else
+            pxl = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
+          break;
 
-          e1 = TRUNC( e1 );
+        default: /* modes 2, 3, 6, 7 */
+          return;  /* no drop-out control */
+        }
 
-          c1 = (Short)( e1 >> 3 );
-          f1 = (Short)( e1 &  7 );
+        /* check that the other pixel isn't set */
+        e1 = pxl == e1 ? e2 : e1;
 
-          if ( e1 >= 0 && e1 < ras.bWidth                      &&
-               ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
-            return;
+        e1 = TRUNC( e1 );
 
-          if ( ras.dropOutControl == 2 )
-            e1 = e2;
-          else
-            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+        c1 = (Short)( e1 >> 3 );
+        f1 = (Short)( e1 &  7 );
 
-          break;
-
-        default:
-          return;  /* unsupported mode */
-        }
+        if ( e1 >= 0 && e1 < ras.bWidth                      &&
+             ras.bTarget[ras.traceOfs + c1] & ( 0x80 >> f1 ) )
+          return;
       }
       else
         return;
     }
 
-    e1 = TRUNC( e1 );
+    e1 = TRUNC( pxl );
 
     if ( e1 >= 0 && e1 < ras.bWidth )
     {
@@ -2280,8 +2311,10 @@
       c1 = (Short)( e1 >> 3 );
       f1 = (Short)( e1 & 7 );
 
-      if ( ras.gray_min_x > c1 ) ras.gray_min_x = c1;
-      if ( ras.gray_max_x < c1 ) ras.gray_max_x = c1;
+      if ( ras.gray_min_x > c1 )
+        ras.gray_min_x = c1;
+      if ( ras.gray_max_x < c1 )
+        ras.gray_max_x = c1;
 
       ras.bTarget[ras.traceOfs + c1] |= (char)( 0x80 >> f1 );
     }
@@ -2365,7 +2398,7 @@
                                   PProfile    left,
                                   PProfile    right )
   {
-    Long   e1, e2;
+    Long   e1, e2, pxl;
     PByte  bits;
     Byte   f1;
 
@@ -2372,9 +2405,27 @@
 
     /* During the horizontal sweep, we only take care of drop-outs */
 
-    e1 = CEILING( x1 );
-    e2 = FLOOR  ( x2 );
+    /* e1     +       <-- pixel center */
+    /*        |                        */
+    /* x1  ---+-->    <-- contour      */
+    /*        |                        */
+    /*        |                        */
+    /* x2  <--+---    <-- contour      */
+    /*        |                        */
+    /*        |                        */
+    /* e2     +       <-- pixel center */
 
+    /* FIXXXME: The specification doesn't discuss the case where the */
+    /*          intersections degenerate to a single point.          */
+#if 0
+    if ( x1 == x2 )
+      return;
+#endif
+
+    e1  = CEILING( x1 );
+    e2  = FLOOR  ( x2 );
+    pxl = e1;
+
     if ( e1 > e2 )
     {
       if ( e1 == e2 + ras.precision )
@@ -2381,24 +2432,18 @@
       {
         switch ( ras.dropOutControl )
         {
-        case 1:
-          e1 = e2;
+        case 0: /* simple drop-outs including stubs */
+          pxl = e2;
           break;
 
-        case 4:
-          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+        case 4: /* smart drop-outs including stubs */
+          pxl = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
           break;
 
-        case 2:
-        case 5:
+        case 1: /* simple drop-outs excluding stubs */
+        case 5: /* smart drop-outs excluding stubs  */
+          /* see Vertical_Sweep_Drop for details */
 
-          /* Drop-out Control Rule #4 */
-
-          /* The spec is not very clear regarding rule #4.  It      */
-          /* presents a method that is way too costly to implement  */
-          /* while the general idea seems to get rid of `stubs'.    */
-          /*                                                        */
-
           /* rightmost stub test */
           if ( left->next == right && left->height <= 0 )
             return;
@@ -2407,32 +2452,32 @@
           if ( right->next == left && left->start == y )
             return;
 
-          /* check that the rightmost pixel isn't set */
+          if ( ras.dropOutControl == 1 )
+            pxl = e2;
+          else
+            pxl = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
+          break;
 
-          e1 = TRUNC( e1 );
+        default: /* modes 2, 3, 6, 7 */
+          return;  /* no drop-out control */
+        }
 
-          bits = ras.bTarget + ( y >> 3 );
-          f1   = (Byte)( 0x80 >> ( y & 7 ) );
+        /* check that the other pixel isn't set */
+        e1 = pxl == e1 ? e2 : e1;
 
-          bits -= e1 * ras.target.pitch;
-          if ( ras.target.pitch > 0 )
-            bits += ( ras.target.rows - 1 ) * ras.target.pitch;
+        e1 = TRUNC( e1 );
 
-          if ( e1 >= 0              &&
-               e1 < ras.target.rows &&
-               *bits & f1 )
-            return;
+        bits = ras.bTarget + ( y >> 3 );
+        f1   = (Byte)( 0x80 >> ( y & 7 ) );
 
-          if ( ras.dropOutControl == 2 )
-            e1 = e2;
-          else
-            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+        bits -= e1 * ras.target.pitch;
+        if ( ras.target.pitch > 0 )
+          bits += ( ras.target.rows - 1 ) * ras.target.pitch;
 
-          break;
-
-        default:
-          return;  /* unsupported mode */
-        }
+        if ( e1 >= 0              &&
+             e1 < ras.target.rows &&
+             *bits & f1           )
+          return;
       }
       else
         return;
@@ -2441,7 +2486,7 @@
     bits = ras.bTarget + ( y >> 3 );
     f1   = (Byte)( 0x80 >> ( y & 7 ) );
 
-    e1 = TRUNC( e1 );
+    e1 = TRUNC( pxl );
 
     if ( e1 >= 0 && e1 < ras.target.rows )
     {
@@ -2627,6 +2672,14 @@
 
 
     /* During the horizontal sweep, we only take care of drop-outs */
+
+    /* FIXXXME: The specification doesn't discuss the case where the */
+    /*          intersections degenerate to a single point.          */
+#if 0
+    if ( x1 == x2 )
+      return;
+#endif
+
     e1 = CEILING( x1 );
     e2 = FLOOR  ( x2 );
 
@@ -2636,24 +2689,18 @@
       {
         switch ( ras.dropOutControl )
         {
-        case 1:
+        case 0: /* simple drop-outs including stubs */
           e1 = e2;
           break;
 
-        case 4:
-          e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+        case 4: /* smart drop-outs including stubs */
+          e1 = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
           break;
 
-        case 2:
-        case 5:
+        case 1: /* simple drop-outs excluding stubs */
+        case 5: /* smart drop-outs excluding stubs  */
+          /* see Vertical_Sweep_Drop for details */
 
-          /* Drop-out Control Rule #4 */
-
-          /* The spec is not very clear regarding rule #4.  It      */
-          /* presents a method that is way too costly to implement  */
-          /* while the general idea seems to get rid of `stubs'.    */
-          /*                                                        */
-
           /* rightmost stub test */
           if ( left->next == right && left->height <= 0 )
             return;
@@ -2662,15 +2709,15 @@
           if ( right->next == left && left->start == y )
             return;
 
-          if ( ras.dropOutControl == 2 )
+          if ( ras.dropOutControl == 1 )
             e1 = e2;
           else
-            e1 = CEILING( ( x1 + x2 + 1 ) / 2 );
+            e1 = FLOOR( ( x1 + x2 + 1 ) / 2 + ras.precision_half );
 
           break;
 
-        default:
-          return;  /* unsupported mode */
+        default: /* modes 2, 3, 6, 7 */
+          return;  /* no drop-out control */
         }
       }
       else
@@ -2742,8 +2789,10 @@
       bottom = (Short)P->start;
       top    = (Short)( P->start + P->height - 1 );
 
-      if ( min_Y > bottom ) min_Y = bottom;
-      if ( max_Y < top    ) max_Y = top;
+      if ( min_Y > bottom )
+        min_Y = bottom;
+      if ( max_Y < top )
+        max_Y = top;
 
       P->X = 0;
       InsNew( &waiting, P );
@@ -3039,14 +3088,24 @@
 
     Set_High_Precision( RAS_VARS ras.outline.flags &
                         FT_OUTLINE_HIGH_PRECISION );
-    ras.scale_shift    = ras.precision_shift;
-    /* Drop-out mode 2 is hard-coded since this is the only mode used */
-    /* on Windows platforms.  Using other modes, as specified by the  */
-    /* font, results in misplaced pixels.                             */
-    ras.dropOutControl = 2;
-    ras.second_pass    = (FT_Byte)( !( ras.outline.flags &
-                                       FT_OUTLINE_SINGLE_PASS ) );
+    ras.scale_shift = ras.precision_shift;
 
+    if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
+      ras.dropOutControl = 2;
+    else
+    {
+      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
+        ras.dropOutControl = 4;
+      else
+        ras.dropOutControl = 0;
+
+      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
+        ras.dropOutControl += 1;
+    }
+
+    ras.second_pass = (FT_Byte)( !( ras.outline.flags &
+                                    FT_OUTLINE_SINGLE_PASS ) );
+
     /* Vertical Sweep */
     ras.Proc_Sweep_Init = Vertical_Sweep_Init;
     ras.Proc_Sweep_Span = Vertical_Sweep_Span;
@@ -3106,13 +3165,23 @@
 
     Set_High_Precision( RAS_VARS ras.outline.flags &
                         FT_OUTLINE_HIGH_PRECISION );
-    ras.scale_shift    = ras.precision_shift + 1;
-    /* Drop-out mode 2 is hard-coded since this is the only mode used */
-    /* on Windows platforms.  Using other modes, as specified by the  */
-    /* font, results in misplaced pixels.                             */
-    ras.dropOutControl = 2;
-    ras.second_pass    = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
+    ras.scale_shift = ras.precision_shift + 1;
 
+    if ( ras.outline.flags & FT_OUTLINE_IGNORE_DROPOUTS )
+      ras.dropOutControl = 2;
+    else
+    {
+      if ( ras.outline.flags & FT_OUTLINE_SMART_DROPOUTS )
+        ras.dropOutControl = 4;
+      else
+        ras.dropOutControl = 0;
+
+      if ( !( ras.outline.flags & FT_OUTLINE_INCLUDE_STUBS ) )
+        ras.dropOutControl += 1;
+    }
+
+    ras.second_pass = !( ras.outline.flags & FT_OUTLINE_SINGLE_PASS );
+
     /* Vertical Sweep */
 
     ras.band_top            = 0;
@@ -3351,15 +3420,15 @@
     if ( !target_map->buffer )
       return Raster_Err_Invalid;
 
-    ras.outline  = *outline;
-    ras.target   = *target_map;
+    ras.outline = *outline;
+    ras.target  = *target_map;
 
-    worker->buff        = (PLong) raster->buffer;
-    worker->sizeBuff    = worker->buff +
-                            raster->buffer_size / sizeof ( Long );
+    worker->buff       = (PLong) raster->buffer;
+    worker->sizeBuff   = worker->buff +
+                           raster->buffer_size / sizeof ( Long );
 #ifdef FT_RASTER_OPTION_ANTI_ALIASING
-    worker->grays       = raster->grays;
-    worker->gray_width  = raster->gray_width;
+    worker->grays      = raster->grays;
+    worker->gray_width = raster->gray_width;
 #endif
 
     return ( ( params->flags & FT_RASTER_FLAG_AA )
--- a/src/truetype/ttgload.c
+++ b/src/truetype/ttgload.c
@@ -557,10 +557,10 @@
       FT_Stream  stream = loader->stream;
 
 
-      /* we must undo the FT_FRAME_ENTER in order to point to the */
-      /* composite instructions, if we find some.               */
-      /* we will process them later...                          */
-      /*                                                        */
+      /* we must undo the FT_FRAME_ENTER in order to point */
+      /* to the composite instructions, if we find some.   */
+      /* We will process them later.                       */
+      /*                                                   */
       loader->ins_pos = (FT_ULong)( FT_STREAM_POS() +
                                     p - limit );
     }
@@ -1957,6 +1957,37 @@
         if ( ( face->header.Flags & 2 ) == 0 && loader.pp1.x )
           FT_Outline_Translate( &glyph->outline, -loader.pp1.x, 0 );
       }
+
+#ifdef TT_USE_BYTECODE_INTERPRETER
+
+      if ( loader.exec->GS.scan_control )
+      {
+        /* convert scan conversion mode to FT_OUTLINE_XXX flags */
+        switch ( loader.exec->GS.scan_type )
+        {
+        case 0: /* simple drop-outs including stubs */
+          glyph->outline.flags |= FT_OUTLINE_INCLUDE_STUBS;
+          break;
+        case 1: /* simple drop-outs excluding stubs */
+          /* nothing; it's the default rendering mode */
+          break;
+        case 4: /* smart drop-outs including stubs */
+          glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS |
+                                  FT_OUTLINE_INCLUDE_STUBS;
+          break;
+        case 5: /* smart drop-outs excluding stubs  */
+          glyph->outline.flags |= FT_OUTLINE_SMART_DROPOUTS;
+          break;
+
+        default: /* no drop-out control */
+          glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
+          break;
+        }
+      }
+      else 
+        glyph->outline.flags |= FT_OUTLINE_IGNORE_DROPOUTS;
+
+#endif /* TT_USE_BYTECODE_INTERPRETER */
 
       compute_glyph_metrics( &loader, glyph_index );
     }
--- a/src/truetype/ttinterp.c
+++ b/src/truetype/ttinterp.c
@@ -693,7 +693,7 @@
   /*    exec  :: A handle to the target execution context.                 */
   /*                                                                       */
   /* <Return>                                                              */
-  /*    TrueTyoe error code.  0 means success.                             */
+  /*    TrueType error code.  0 means success.                             */
   /*                                                                       */
   /* <Note>                                                                */
   /*    Only the glyph loader and debugger should call this function.      */
@@ -5092,12 +5092,8 @@
       return;
     }
 
-    A *= 64;
-
-#if 0
-    if ( ( args[0] & 0x100 ) != 0 && CUR.metrics.pointSize <= A )
+    if ( ( args[0] & 0x100 ) != 0 && CUR.tt_metrics.ppem < A )
       CUR.GS.scan_control = TRUE;
-#endif
 
     if ( ( args[0] & 0x200 ) != 0 && CUR.tt_metrics.rotated )
       CUR.GS.scan_control = TRUE;
@@ -5105,10 +5101,8 @@
     if ( ( args[0] & 0x400 ) != 0 && CUR.tt_metrics.stretched )
       CUR.GS.scan_control = TRUE;
 
-#if 0
-    if ( ( args[0] & 0x800 ) != 0 && CUR.metrics.pointSize > A )
+    if ( ( args[0] & 0x800 ) != 0 && CUR.tt_metrics.ppem >= A )
       CUR.GS.scan_control = FALSE;
-#endif
 
     if ( ( args[0] & 0x1000 ) != 0 && CUR.tt_metrics.rotated )
       CUR.GS.scan_control = FALSE;