Commit 229d122e928c5b5b6a1d4b613435695a2077c99a

David Turner 2003-02-25T19:20:12

* src/gzip/ftgzip.c: fixed a bug that caused FreeType to loop endlessly when trying to read certain compressed gzip files. The following test could be used to reveal the bug: touch 0123456789 ; gzip 0123456789 ; ftdump 0123456789.gz * src/pfr/pfrobjs.c, src/pfr/pfrload.c, src/pfr/pfrtypes.h: several fixes to the PFR font driver: - the list of available embedded bitmaps was not correctly set in the root FT_FaceRec structure describing the face - the glyph loader always tried to load the outlines when FT_LOAD_SBITS_ONLY was specified - the table loaded now scans for *undocumented* elements of a physical font's auxiliary data record, this is necessary to retrieve the "real" family and style names. NOTE THAT THIS CHANGES THE FAMILY NAME OF MANY PFR FONTS !!

diff --git a/ChangeLog b/ChangeLog
index eb03bf6..53da3db 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,3 +1,29 @@
+2003-02-25  David Turner  <david@freetype.org>
+
+    * src/gzip/ftgzip.c: fixed a bug that caused FreeType to loop endlessly
+    when trying to read certain compressed gzip files. The following test
+    could be used to reveal the bug:
+    
+       touch 0123456789 ; gzip 0123456789 ; ftdump 0123456789.gz
+
+
+    * src/pfr/pfrobjs.c, src/pfr/pfrload.c, src/pfr/pfrtypes.h: several
+    fixes to the PFR font driver:
+    
+      - the list of available embedded bitmaps was not correctly set
+        in the root FT_FaceRec structure describing the face
+      
+      - the glyph loader always tried to load the outlines when
+        FT_LOAD_SBITS_ONLY was specified
+        
+      - the table loaded now scans for *undocumented* elements of a
+        physical font's auxiliary data record, this is necessary to
+        retrieve the "real" family and style names.
+        
+        NOTE THAT THIS CHANGES THE FAMILY NAME OF MANY PFR FONTS !!
+
+
+
 2003-02-18  David Turner  <david@freetype.org>
 
     * src/truetype/ttdriver.c, src/truetype/ttobjs.h, src/truetype/ttobjs.c,
diff --git a/src/gzip/ftgzip.c b/src/gzip/ftgzip.c
index 768dcdc..32c938c 100644
--- a/src/gzip/ftgzip.c
+++ b/src/gzip/ftgzip.c
@@ -376,6 +376,7 @@
       if ( err == Z_STREAM_END )
       {
         zip->limit = zstream->next_out;
+        error      = FT_Err_Invalid_Stream_Operation;
         break;
       }
       else if ( err != Z_OK )
diff --git a/src/pfr/pfrload.c b/src/pfr/pfrload.c
index 0cb32f4..1b81e65 100644
--- a/src/pfr/pfrload.c
+++ b/src/pfr/pfrload.c
@@ -432,7 +432,16 @@
   }
 
 
-  /* load font ID, i.e. name */
+ /* load font ID, this is a so-called "unique" name that is rather
+  * long and descriptive (like "Tiresias ScreenFont v7.51").
+  *
+  * note that a PFR font's family name is contained in an *undocumented*
+  * string of the "auxiliary data" portion of a physical font record. this
+  * may also contain the "real" style name !
+  *
+  * if no family name is present, the font id is used instead for the
+  * family
+  */
   FT_CALLBACK_DEF( FT_Error )
   pfr_extra_item_load_font_id( FT_Byte*     p,
                                FT_Byte*     limit,
@@ -693,12 +702,54 @@
   };
 
 
+ /* loads a name from the auxiliary data. Since this extracts undocumented
+  * strings from the font file, we need to be careful here
+  */
+  static FT_Error
+  pfr_aux_name_load( FT_Byte*     p,
+                     FT_UInt      len,
+                     FT_Memory    memory,
+                     FT_String*  *astring )
+  {
+    FT_Error    error = 0;
+    FT_String*  result = NULL;
+    FT_UInt     n, ok;
+    
+    if ( len > 0 && p[len-1] == 0 )
+      len--;
+
+   /* check that each character is ASCII, that's to be sure
+    * to not load garbage..
+    */    
+    ok = (len > 0);
+    for ( n = 0; n < len; n++ )
+      if ( p[n] < 32 || p[n] > 127 )
+      {
+        ok = 0;
+        break;
+      }
+      
+    if ( ok )
+    {
+      if ( FT_ALLOC( result, len+1 ) )
+        goto Exit;
+      
+      FT_MEM_COPY( result, p, len );
+      result[len] = 0;
+    }
+  Exit:
+    *astring = result;
+    return error;
+  }                     
+
+
   FT_LOCAL_DEF( void )
   pfr_phy_font_done( PFR_PhyFont  phy_font,
                      FT_Memory    memory )
   {
-    if ( phy_font->font_id )
-      FT_FREE( phy_font->font_id );
+    FT_FREE( phy_font->font_id );
+    FT_FREE( phy_font->family_name );
+    FT_FREE( phy_font->style_name );
 
     FT_FREE( phy_font->vertical.stem_snaps );
     phy_font->vertical.num_stem_snaps = 0;
@@ -736,6 +787,7 @@
   }
 
 
+
   FT_LOCAL_DEF( FT_Error )
   pfr_phy_font_load( PFR_PhyFont  phy_font,
                      FT_Stream    stream,
@@ -790,12 +842,82 @@
         goto Fail;
     }
 
-    /* skip the aux bytes */
+    /* in certain fonts, the auxiliary bytes contain interesting  */
+    /* information. These are not in the specification but can be */
+    /* guessed by looking at the content of a few PFR0 fonts      */
     PFR_CHECK( 3 );
     num_aux = PFR_NEXT_ULONG( p );
 
-    PFR_CHECK( num_aux );
-    p += num_aux;
+    if ( num_aux > 0 )
+    {
+      FT_Byte*  q = p;
+      FT_Byte*  q2;
+      
+      PFR_CHECK( num_aux );
+      p += num_aux;
+      
+      while ( num_aux >= 0 )
+      {
+        FT_UInt  length, type;
+        
+        if ( q + 4 > p )
+          break;
+        
+        length = PFR_NEXT_USHORT(q);
+        if ( length < 4 || length > num_aux )
+          break;
+        
+        q2   = q + length - 2;
+        type = PFR_NEXT_USHORT(q);
+
+        switch ( type )
+        {
+          case 1:
+            {
+             /* this seems to correspond to the font's family name,
+              * padded to 16-bits with one zero when necessary
+              */
+              error = pfr_aux_name_load( q, length-4U, memory,
+                                         &phy_font->family_name );
+              if ( error )
+                goto Exit;                                         
+            }
+            break;
+          
+          case 2:
+            {
+              if ( q + 32 > q2 )
+                break;
+
+              q += 10;
+              phy_font->ascent  = PFR_NEXT_SHORT(q);
+              phy_font->descent = PFR_NEXT_SHORT(q);
+              phy_font->leading = PFR_NEXT_SHORT(q);
+              q += 16;
+            }
+            break;
+          
+          case 3:
+            {
+              FT_UInt   n, len, ok;
+              
+             /* this seems to correspond to the font's style name,
+              * padded to 16-bits with one zero when necessary
+              */
+              error = pfr_aux_name_load( q, length-4U, memory,
+                                         &phy_font->style_name );
+              if ( error )
+                goto Exit;                                         
+            }
+            break;
+          
+          default:
+            ;
+        }
+        q        = q2;
+        num_aux -= length;
+      }
+    }
 
     /* read the blue values */
     {
diff --git a/src/pfr/pfrobjs.c b/src/pfr/pfrobjs.c
index 8ede63a..2021848 100644
--- a/src/pfr/pfrobjs.c
+++ b/src/pfr/pfrobjs.c
@@ -41,6 +41,10 @@
   FT_LOCAL_DEF( void )
   pfr_face_done( PFR_Face  face )
   {
+    /* we don't want dangling pointers */
+    face->root.family_name = NULL;
+    face->root.style_name  = NULL;
+    
     /* finalize the physical font record */
     pfr_phy_font_done( &face->phy_font, FT_FACE_MEMORY( face ) );
 
@@ -136,8 +140,18 @@
        if ( phy_font->num_kern_pairs > 0 )
          root->face_flags |= FT_FACE_FLAG_KERNING;
 
-       root->family_name = phy_font->font_id;
-       root->style_name  = NULL;  /* no style name in font file */
+      /* if no family name was found in the "undocumented" auxiliary
+       * data, use the font ID instead. This sucks but is better than
+       * nothing
+       */
+       root->family_name = phy_font->family_name;
+       if ( root->family_name == NULL )
+         root->family_name = phy_font->font_id;
+
+      /* note that the style name can be NULL in certain PFR fonts,
+       * probably meaning "Regular"
+       */
+       root->style_name  = phy_font->style_name;
 
        root->num_fixed_sizes = 0;
        root->available_sizes = 0;
@@ -150,6 +164,27 @@
                               ( ( ( root->ascender - root->descender ) * 12 )
                                 / 10 );
 
+       if ( phy_font->num_strikes > 0 )
+       {
+         FT_UInt          n, count = phy_font->num_strikes;
+         FT_Bitmap_Size*  size;
+         PFR_Strike       strike;
+         FT_Memory        memory = root->stream->memory;
+         
+         
+         if ( FT_NEW_ARRAY( root->available_sizes, count ) )
+           goto Exit;
+         
+         size   = root->available_sizes;
+         strike = phy_font->strikes;
+         for ( n = 0; n < count; n++, size++, strike++ )
+         {
+           size->height = strike->y_ppm;
+           size->width  = strike->x_ppm;
+         }
+         root->num_fixed_sizes = count;
+       }
+
        /* now compute maximum advance width */
        if ( ( phy_font->flags & PFR_PHY_PROPORTIONAL ) == 0 )
          root->max_advance_width = (FT_Short)phy_font->standard_advance;
@@ -255,6 +290,12 @@
         goto Exit;
     }
 
+    if ( load_flags & FT_LOAD_SBITS_ONLY )
+    {
+      error = FT_Err_Invalid_Argument;
+      goto Exit;
+    }
+
     gchar               = face->phy_font.chars + gindex;
     slot->root.format   = FT_GLYPH_FORMAT_OUTLINE;
     outline->n_points   = 0;
diff --git a/src/pfr/pfrtypes.h b/src/pfr/pfrtypes.h
index 3b419da..96744fc 100644
--- a/src/pfr/pfrtypes.h
+++ b/src/pfr/pfrtypes.h
@@ -230,11 +230,17 @@ FT_BEGIN_HEADER
     FT_BBox            bbox;
     FT_UInt            flags;
     FT_UInt            standard_advance;
+    
+    FT_Int             ascent;   /* optional, bbox.yMax if not present */
+    FT_Int             descent;  /* optional, bbox.yMin if not present */
+    FT_Int             leading;  /* optional, 0 if not present         */
 
     PFR_DimensionRec   horizontal;
     PFR_DimensionRec   vertical;
 
     FT_String*         font_id;
+    FT_String*         family_name;
+    FT_String*         style_name;
 
     FT_UInt            num_strikes;
     FT_UInt            max_strikes;