Commit 2b30c17fd389586fe8955b9346fc665f73accb30

David Turner 2001-12-12T16:07:29

* src/pshint/pshglob.c: adding correct BlueScale/BlueShift support, plus family blues processing * src/cff/cffgload.c: started adding support for the Postscript hinter

diff --git a/ChangeLog b/ChangeLog
index 40e12f5..fcd8dda 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,10 @@
+2001-12-12  David Turner  <david@freetype.org>
+
+    * src/pshint/pshglob.c: adding correct BlueScale/BlueShift support,
+    plus family blues processing
+
+    * src/cff/cffgload.c: started adding support for the Postscript hinter
+
 2001-12-12  Werner Lemberg  <wl@gnu.org>
 
 	* builds/unix/freetype2.m4: Some portability fixes.
diff --git a/src/cff/cffgload.c b/src/cff/cffgload.c
index 508f2fa..2e8c55a 100644
--- a/src/cff/cffgload.c
+++ b/src/cff/cffgload.c
@@ -23,6 +23,7 @@
 #include FT_INTERNAL_SFNT_H
 #include FT_OUTLINE_H
 #include FT_TRUETYPE_TAGS_H
+#include FT_INTERNAL_POSTSCRIPT_HINTS_H
 
 #include "cffload.h"
 #include "cffgload.h"
@@ -701,6 +702,7 @@
     FT_Fixed           seed;
     FT_Fixed*          stack;
 
+    T2_Hints_Funcs     hinter;
 
     /* set default width */
     decoder->num_hints  = 0;
@@ -720,6 +722,8 @@
     zone          = decoder->zones;
     stack         = decoder->top;
 
+    hinter = (T2_Hints_Funcs) builder->hints_funcs;
+
     builder->path_begun = 0;
 
     zone->base           = charstring_base;
@@ -731,6 +735,10 @@
     x = builder->pos_x;
     y = builder->pos_y;
 
+    /* begin hints recording session, if any */
+    if ( hinter )
+      hinter->open( hinter->hints );
+
     /* now, execute loop */
     while ( ip < limit )
     {
@@ -1053,24 +1061,41 @@
         case cff_op_vstem:
         case cff_op_hstemhm:
         case cff_op_vstemhm:
-          /* if the number of arguments is not even, the first one */
-          /* is simply the glyph width, encoded as the difference  */
-          /* to nominalWidthX                                      */
+          /* the number of arguments is always even here */
           FT_TRACE4(( op == cff_op_hstem   ? " hstem"   :
-                      op == cff_op_vstem   ? " vstem"   :
-                      op == cff_op_hstemhm ? " hstemhm" :
-                                             " vstemhm" ));
+                    ( op == cff_op_vstem   ? " vstem"   :
+                    ( op == cff_op_hstemhm ? " hstemhm" : " vstemhm" )) ));
+          
+          if ( hinter )
+            hinter->stems( hinter->hints,
+                           ( op == cff_op_vstem || op == cff_op_vstemhm ),
+                           num_args/2,
+                           args );
+            
           decoder->num_hints += num_args / 2;
           args = stack;
           break;
+        
 
         case cff_op_hintmask:
         case cff_op_cntrmask:
-          FT_TRACE4(( op == cff_op_hintmask ? " hintmask"
-                                            : " cntrmask" ));
+          FT_TRACE4(( op == cff_op_hintmask ? " hintmask" : " cntrmask" ));
 
           decoder->num_hints += num_args / 2;
 
+          if ( hinter )
+          {
+            if ( op == cff_op_hintmask )
+              hinter->hintmask( hinter->hints,
+                                builder->current->n_points,
+                                (decoder->num_hints+7) >> 3,
+                                ip );
+            else
+              hinter->counter( hinter->hints,
+                               (decoder->num_hints+7) >> 3,
+                               ip );
+          }
+                              
 #ifdef FT_DEBUG_LEVEL_TRACE
           {
             FT_UInt maskbyte;
@@ -1617,6 +1642,18 @@
 
           close_contour( builder );
 
+          /* close hints recording session */
+          if ( hinter )
+          {
+            if (hinter->close( hinter->hints, builder->current->n_points ))
+              goto Syntax_Error;
+            
+            /* apply hints to the loaded glyph outline now */
+            hinter->apply( hinter->hints,
+                           builder->current,
+                           (PSH_Globals)builder->hints_globals );
+          }
+
           /* add current outline to the glyph slot */
           FT_GlyphLoader_Add( builder->loader );
 
diff --git a/src/cff/cffgload.h b/src/cff/cffgload.h
index 187ed70..d100bd0 100644
--- a/src/cff/cffgload.h
+++ b/src/cff/cffgload.h
@@ -112,6 +112,9 @@ FT_BEGIN_HEADER
     FT_Error          error;         /* only used for memory errors */
     FT_Bool           metrics_only;
 
+    void*             hints_funcs;    /* hinter-specific */
+    void*             hints_globals;  /* hinter-specific */
+
   } CFF_Builder;
 
 
diff --git a/src/pshinter/pshglob.c b/src/pshinter/pshglob.c
index 7162d0a..406ca11 100644
--- a/src/pshinter/pshglob.c
+++ b/src/pshinter/pshglob.c
@@ -345,6 +345,50 @@
     FT_UInt         num;
     PSH_Blue_Table  table = 0;
 
+    /*                                                        */
+    /* determine wether we need to suppress overshoots or not */
+    /* we simply need to compare the vertical scale parameter */
+    /* to the raw bluescale value. Here's why                 */
+    /*                                                        */
+    /*   we need to suppress overshoots for all pointsizes    */
+    /*   at 300dpi that satisfy:                              */
+    /*                                                        */
+    /*      pointsize < 240*bluescale + 0.49                  */
+    /*                                                        */
+    /*   this corresponds to:                                 */
+    /*                                                        */
+    /*      pixelsize < 1000*bluescale + 49/24                */
+    /*                                                        */
+    /*      scale*EM_Size < 1000*bluescale + 49/24            */
+    /*                                                        */
+    /*   however, for normal Type 1 fonts, EM_Size is 1000 !! */
+    /*   we thus only check:                                  */
+    /*                                                        */
+    /*      scale < bluescale + 49/24000                      */
+    /*                                                        */
+    /*   which we shorten to                                  */
+    /*                                                        */
+    /*      "scale < bluescale"                               */
+    /*                                                        */
+    blues->no_overshoots = FT_BOOL( scale < blues->blue_scale );
+
+    /*                                                        */
+    /*  the blue threshold is the font units distance under   */
+    /*  which overshoots are suppressed due to the BlueShift  */
+    /*  even if the scale is greater than BlueScale           */
+    /*                                                        */
+    /*  it's the smallest distance such that                  */
+    /*                                                        */
+    /*    dist <= BlueShift && dist*scale <= 0.5 pixels       */
+    /*                                                        */
+    {
+      FT_Int  threshold = blues->blue_shift;
+      
+      while ( threshold > 0 && FT_MulFix( threshold, scale ) > 32 )
+        threshold --;
+      
+      blues->blue_threshold = threshold;
+    }
 
     for ( num = 0; num < 4; num++ )
     {
@@ -388,7 +432,46 @@
       }
     }
 
-    /* XXX: we should process the family / normal tables here! */
+    /* process the families now */
+    for ( num = 0; num < 2; num++ )
+    { 
+      PSH_Blue_Zone    zone1, zone2;
+      FT_UInt          count1, count2;
+      PSH_Blue_Table   normal, family;
+      
+      switch (num)
+      {
+        case 0:
+          normal = &blues->normal_top;
+          family = &blues->family_top;
+          break;
+          
+        default:
+          normal = &blues->normal_bottom;
+          family = &blues->family_bottom;
+      }
+      
+      zone1  = normal->zones;
+      count1 = normal->count;
+      for ( ; count1 > 0; count1--, zone1++ )
+      {
+        /* try to find a family zone whose reference position is less */
+        /* than 1 pixel far from the current zone..                   */
+        zone2  = family->zones;
+        count2 = family->count;
+        for ( ; count2 > 0; count2--, zone2++ )
+        {
+          if ( FT_MulFix( zone1->org_ref - zone2->org_ref, scale ) < 64 )
+          {
+            zone1->cur_top    = zone2->cur_top;
+            zone1->cur_bottom = zone2->cur_bottom;
+            zone1->cur_ref    = zone2->cur_ref;
+            zone1->cur_delta  = zone2->cur_delta;
+            break;
+          }
+        }
+      }
+    }
   }
 
 
@@ -400,11 +483,15 @@
   {
     PSH_Blue_Table  table;
     FT_UInt         count;
+    FT_Pos          delta;
     PSH_Blue_Zone   zone;
+    FT_Int          no_shoots;
 
 
     alignment->align = 0;
 
+    no_shoots = blues->no_overshoots;
+
     /* lookup stem top in top zones table */
     table = &blues->normal_top;
     count = table->count;
@@ -412,13 +499,17 @@
 
     for ( ; count > 0; count--, zone++ )
     {
-      if ( stem_top < zone->org_bottom )
+      delta = stem_top - zone->org_bottom;
+      if ( delta < 0 )
         break;
 
       if ( stem_top <= zone->org_top )
       {
-        alignment->align    |= PSH_BLUE_ALIGN_TOP;
-        alignment->align_top = zone->cur_ref;
+        if ( no_shoots || delta <= blues->blue_threshold )
+        {
+          alignment->align    |= PSH_BLUE_ALIGN_TOP;
+          alignment->align_top = zone->cur_ref;
+        }
         break;
       }
     }
@@ -426,17 +517,21 @@
     /* look up stem bottom in bottom zones table */
     table = &blues->normal_bottom;
     count = table->count;
-    zone  = table->zones;
+    zone  = table->zones + count-1;
 
-    for ( ; count > 0; count--, zone++ )
+    for ( ; count > 0; count--, zone-- )
     {
-      if ( stem_bot < zone->org_bottom )
+      delta = zone->org_top - stem_bot;
+      if ( delta < 0 )
         break;
 
-      if ( stem_bot <= zone->org_top )
+      if ( stem_bot >= zone->org_bottom )
       {
-        alignment->align    |= PSH_BLUE_ALIGN_BOT;
-        alignment->align_bot = zone->cur_ref;
+        if ( no_shoots || delta < blues->blue_shift )
+        {
+          alignment->align    |= PSH_BLUE_ALIGN_BOT;
+          alignment->align_bot = zone->cur_ref;
+        }
         break;
       }
     }
@@ -543,6 +638,11 @@
                            priv->family_blues, priv->num_family_other_blues,
                            priv->family_other_blues, priv->blue_fuzz, 1 );
 
+      globals->blues.blue_scale = priv->blue_scale ? priv->blue_scale
+                                                   : (0.039625*0x400000L);
+      
+      globals->blues.blue_shift = priv->blue_shift;
+
       globals->dimension[0].scale_mult  = 0;
       globals->dimension[0].scale_delta = 0;
       globals->dimension[1].scale_mult  = 0;
diff --git a/src/pshinter/pshglob.h b/src/pshinter/pshglob.h
index b34f32f..569e6e7 100644
--- a/src/pshinter/pshglob.h
+++ b/src/pshinter/pshglob.h
@@ -120,7 +120,11 @@ FT_BEGIN_HEADER
     PSH_Blue_TableRec  normal_bottom;
     PSH_Blue_TableRec  family_top;
     PSH_Blue_TableRec  family_bottom;
+
     FT_Fixed           blue_scale;
+    FT_Int             blue_shift;
+    FT_Int             blue_threshold;
+    FT_Bool            no_overshoots;
 
   } PSH_BluesRec, *PSH_Blues;