[CMAKE]
[reactos.git] / lib / 3rdparty / freetype / src / cff / cffload.c
index dd2f113..000cbe3 100644 (file)
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    OpenType and CFF data/program tables loader (body).                  */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 by             */
+/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009,   */
+/*            2010 by                                                      */
 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
 /*                                                                         */
 /*  This file is part of the FreeType project, and may only be used,       */
@@ -20,7 +21,6 @@
 #include FT_INTERNAL_DEBUG_H
 #include FT_INTERNAL_OBJECTS_H
 #include FT_INTERNAL_STREAM_H
-#include FT_SERVICE_POSTSCRIPT_CMAPS_H
 #include FT_TRUETYPE_TAGS_H
 #include FT_TYPE1_TABLES_H
 
@@ -31,6 +31,7 @@
 
 
 #if 1
+
   static const FT_UShort  cff_isoadobe_charset[229] =
   {
       0,   1,   2,   3,   4,   5,   6,   7,
     363, 364, 365, 366, 367, 368, 369, 370,
     371, 372, 373, 374, 375, 376, 377, 378
   };
-#endif
+
+#endif /* 1 */
 
 
   FT_LOCAL_DEF( FT_UShort )
   cff_get_standard_encoding( FT_UInt  charcode )
   {
-    return  (FT_UShort)(charcode < 256 ? cff_standard_encoding[charcode] : 0);
+    return (FT_UShort)( charcode < 256 ? cff_standard_encoding[charcode]
+                                       : 0 );
   }
 
 
 
       if ( offsize < 1 || offsize > 4 )
       {
-        error = FT_Err_Invalid_Table;
+        error = CFF_Err_Invalid_Table;
         goto Exit;
       }
 
   static FT_Error
   cff_index_load_offsets( CFF_Index  idx )
   {
-    FT_Error   error  = 0;
+    FT_Error   error  = CFF_Err_Ok;
     FT_Stream  stream = idx->stream;
     FT_Memory  memory = stream->memory;
 
   }
 
 
-  /* allocate a table containing pointers to an index's elements */
+  /* Allocate a table containing pointers to an index's elements. */
+  /* The `pool' argument makes this function convert the index    */
+  /* entries to C-style strings (this is, NULL-terminated).       */
   static FT_Error
   cff_index_get_pointers( CFF_Index   idx,
-                          FT_Byte***  table )
+                          FT_Byte***  table,
+                          FT_Byte**   pool )
   {
-    FT_Error   error  = CFF_Err_Ok;
-    FT_Memory  memory = idx->stream->memory;
-    FT_ULong   n, offset, old_offset;
+    FT_Error   error     = CFF_Err_Ok;
+    FT_Memory  memory    = idx->stream->memory;
     FT_Byte**  t;
+    FT_Byte*   new_bytes = NULL;
 
 
-    *table = 0;
+    *table = NULL;
 
     if ( idx->offsets == NULL )
     {
         goto Exit;
     }
 
-    if ( idx->count > 0 && !FT_NEW_ARRAY( t, idx->count + 1 ) )
+    if ( idx->count > 0                                        &&
+         !FT_NEW_ARRAY( t, idx->count + 1 )                    &&
+         ( !pool || !FT_ALLOC( new_bytes,
+                               idx->data_size + idx->count ) ) )
     {
-      old_offset = 1;
-      for ( n = 0; n <= idx->count; n++ )
+      FT_ULong  n, cur_offset;
+      FT_ULong  extra = 0;
+      FT_Byte*  org_bytes = idx->bytes;
+
+
+      /* at this point, `idx->offsets' can't be NULL */
+      cur_offset = idx->offsets[0] - 1;
+
+      /* sanity check */
+      if ( cur_offset >= idx->data_size )
       {
-        offset = idx->offsets[n];
-        if ( !offset )
-          offset = old_offset;
+        FT_TRACE0(( "cff_index_get_pointers:"
+                    " invalid first offset value %d set to zero\n",
+                    cur_offset ));
+        cur_offset = 0;
+      }
 
-        /* two sanity checks for invalid offset tables */
-        else if ( offset < old_offset )
-          offset = old_offset;
+      if ( !pool )
+        t[0] = org_bytes + cur_offset;
+      else
+        t[0] = new_bytes + cur_offset;
 
-        else if ( offset - 1 >= idx->data_size && n < idx->count )
-          offset = old_offset;
+      for ( n = 1; n <= idx->count; n++ )
+      {
+        FT_ULong  next_offset = idx->offsets[n] - 1;
 
-        t[n] = idx->bytes + offset - 1;
 
-        old_offset = offset;
+        /* empty slot + two sanity checks for invalid offset tables */
+        if ( next_offset == 0                                    ||
+             next_offset < cur_offset                            ||
+             ( next_offset >= idx->data_size && n < idx->count ) )
+          next_offset = cur_offset;
+
+        if ( !pool )
+          t[n] = org_bytes + next_offset;
+        else
+        {
+          t[n] = new_bytes + next_offset + extra;
+
+          if ( next_offset != cur_offset )
+          {
+            FT_MEM_COPY( t[n - 1], org_bytes + cur_offset, t[n] - t[n - 1] );
+            t[n][0] = '\0';
+            t[n]   += 1;
+            extra++;
+          }
+        }
+
+        cur_offset = next_offset;
       }
       *table = t;
+
+      if ( pool )
+        *pool = new_bytes;
     }
 
   Exit:
         }
       }
 
+      /* XXX: should check off2 does not exceed the end of this entry; */
+      /*      at present, only truncate off2 at the end of this stream */
+      if ( off2 > stream->size + 1                    ||
+           idx->data_offset > stream->size - off2 + 1 )
+      {
+        FT_ERROR(( "cff_index_access_element:"
+                   " offset to next entry (%d)"
+                   " exceeds the end of stream (%d)\n",
+                   off2, stream->size - idx->data_offset + 1 ));
+        off2 = stream->size - idx->data_offset + 1;
+      }
+
       /* access element */
       if ( off1 && off2 > off1 )
       {
   }
 
 
+  /* get an entry from Name INDEX */
   FT_LOCAL_DEF( FT_String* )
-  cff_index_get_name( CFF_Index  idx,
-                      FT_UInt    element )
+  cff_index_get_name( CFF_Font  font,
+                      FT_UInt   element )
   {
+    CFF_Index   idx = &font->name_index;
     FT_Memory   memory = idx->stream->memory;
     FT_Byte*    bytes;
     FT_ULong    byte_len;
   }
 
 
+  /* get an entry from String INDEX */
   FT_LOCAL_DEF( FT_String* )
-  cff_index_get_sid_string( CFF_Index           idx,
-                            FT_UInt             sid,
-                            FT_Service_PsCMaps  psnames )
+  cff_index_get_string( CFF_Font  font,
+                        FT_UInt   element )
+  {
+    return ( element < font->num_strings )
+             ? (FT_String*)font->strings[element]
+             : NULL;
+  }
+
+
+  FT_LOCAL_DEF( FT_String* )
+  cff_index_get_sid_string( CFF_Font  font,
+                            FT_UInt   sid )
   {
     /* value 0xFFFFU indicates a missing dictionary entry */
     if ( sid == 0xFFFFU )
-      return 0;
+      return NULL;
 
     /* if it is not a standard string, return it */
     if ( sid > 390 )
-      return cff_index_get_name( idx, sid - 391 );
+      return cff_index_get_string( font, sid - 391 );
 
     /* CID-keyed CFF fonts don't have glyph names */
-    if ( !psnames )
-      return 0;
-
-    /* that's a standard string, fetch a copy from the PSName module */
-    {
-      FT_String*   name       = 0;
-      const char*  adobe_name = psnames->adobe_std_strings( sid );
-
-
-      if ( adobe_name )
-      {
-        FT_Memory  memory = idx->stream->memory;
-        FT_Error   error;
-
+    if ( !font->psnames )
+      return NULL;
 
-        (void)FT_STRDUP( name, adobe_name );
-
-        FT_UNUSED( error );
-      }
-
-      return name;
-    }
+    /* this is a standard string */
+    return (FT_String *)font->psnames->adobe_std_strings( sid );
   }
 
 
                             FT_UInt      num_glyphs,
                             FT_Memory    memory )
   {
-    FT_Error   error   = FT_Err_Ok;
+    FT_Error   error   = CFF_Err_Ok;
     FT_UInt    i;
+    FT_Long    j;
     FT_UShort  max_cid = 0;
 
 
       goto Exit;
 
     for ( i = 0; i < num_glyphs; i++ )
+    {
       if ( charset->sids[i] > max_cid )
         max_cid = charset->sids[i];
-    max_cid++;
+    }
 
-    if ( FT_NEW_ARRAY( charset->cids, max_cid ) )
+    if ( FT_NEW_ARRAY( charset->cids, (FT_ULong)max_cid + 1 ) )
       goto Exit;
 
-    for ( i = 0; i < num_glyphs; i++ )
-      charset->cids[charset->sids[i]] = (FT_UShort)i;
+    /* When multiple GIDs map to the same CID, we choose the lowest */
+    /* GID.  This is not described in any spec, but it matches the  */
+    /* behaviour of recent Acroread versions.                       */
+    for ( j = num_glyphs - 1; j >= 0 ; j-- )
+      charset->cids[charset->sids[j]] = (FT_UShort)j;
 
     charset->max_cid    = max_cid;
     charset->num_glyphs = num_glyphs;
     FT_UInt  result = 0;
 
 
-    if ( cid < charset->max_cid )
+    if ( cid <= charset->max_cid )
       result = charset->cids[cid];
 
     return result;
                 goto Exit;
             }
 
+            /* try to rescue some of the SIDs if `nleft' is too large */
+            if ( glyph_sid > 0xFFFFL - nleft )
+            {
+              FT_ERROR(( "cff_charset_load: invalid SID range trimmed"
+                         " nleft=%d -> %d\n", nleft, 0xFFFFL - glyph_sid ));
+              nleft = ( FT_UInt )( 0xFFFFL - glyph_sid );
+            }
+
             /* Fill in the range of sids -- `nleft + 1' glyphs. */
             for ( i = 0; j < num_glyphs && i <= nleft; i++, j++, glyph_sid++ )
               charset->sids[j] = glyph_sid;
         break;
 
       default:
-        FT_ERROR(( "cff_charset_load: invalid table format!\n" ));
+        FT_ERROR(( "cff_charset_load: invalid table format\n" ));
         error = CFF_Err_Invalid_File_Format;
         goto Exit;
       }
         if ( num_glyphs > 229 )
         {
           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
-                     "predefined charset (Adobe ISO-Latin)!\n" ));
+                     "predefined charset (Adobe ISO-Latin)\n" ));
           error = CFF_Err_Invalid_File_Format;
           goto Exit;
         }
         if ( num_glyphs > 166 )
         {
           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
-                     "predefined charset (Adobe Expert)!\n" ));
+                     "predefined charset (Adobe Expert)\n" ));
           error = CFF_Err_Invalid_File_Format;
           goto Exit;
         }
         if ( num_glyphs > 87 )
         {
           FT_ERROR(( "cff_charset_load: implicit charset larger than\n"
-                     "predefined charset (Adobe Expert Subset)!\n" ));
+                     "predefined charset (Adobe Expert Subset)\n" ));
           error = CFF_Err_Invalid_File_Format;
           goto Exit;
         }
         break;
 
       default:
-        FT_ERROR(( "cff_encoding_load: invalid table format!\n" ));
+        FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
         error = CFF_Err_Invalid_File_Format;
         goto Exit;
       }
           if ( gid != 0 )
           {
             encoding->codes[j] = (FT_UShort)gid;
-
-            if ( encoding->count < j + 1 )
-              encoding->count = j + 1;
+            encoding->count    = j + 1;
           }
           else
           {
         break;
 
       default:
-        FT_ERROR(( "cff_encoding_load: invalid table format!\n" ));
+        FT_ERROR(( "cff_encoding_load: invalid table format\n" ));
         error = CFF_Err_Invalid_File_Format;
         goto Exit;
       }
                     CFF_Index    idx,
                     FT_UInt      font_index,
                     FT_Stream    stream,
-                    FT_ULong     base_offset )
+                    FT_ULong     base_offset,
+                    FT_Library   library )
   {
     FT_Error         error;
     CFF_ParserRec    parser;
     CFF_Private      priv = &font->private_dict;
 
 
-    cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict );
+    cff_parser_init( &parser, CFF_CODE_TOPDICT, &font->font_dict, library );
 
     /* set defaults */
     FT_MEM_ZERO( top, sizeof ( *top ) );
     top->cid_ordering        = 0xFFFFU;
     top->cid_font_name       = 0xFFFFU;
 
-    error = cff_index_access_element( idx, font_index, &dict, &dict_len ) ||
-            cff_parser_run( &parser, dict, dict + dict_len );
+    error = cff_index_access_element( idx, font_index, &dict, &dict_len );
+    if ( !error )
+      error = cff_parser_run( &parser, dict, dict + dict_len );
 
     cff_index_forget_element( idx, &dict );
 
       priv->expansion_factor = (FT_Fixed)( 0.06 * 0x10000L );
       priv->blue_scale       = (FT_Fixed)( 0.039625 * 0x10000L * 1000 );
 
-      cff_parser_init( &parser, CFF_CODE_PRIVATE, priv );
+      cff_parser_init( &parser, CFF_CODE_PRIVATE, priv, library );
 
       if ( FT_STREAM_SEEK( base_offset + font->font_dict.private_offset ) ||
            FT_FRAME_ENTER( font->font_dict.private_size )                 )
       if ( error )
         goto Exit;
 
-      font->num_local_subrs = font->local_subrs_index.count;
       error = cff_index_get_pointers( &font->local_subrs_index,
-                                      &font->local_subrs );
+                                      &font->local_subrs, NULL );
       if ( error )
         goto Exit;
     }
 
 
   FT_LOCAL_DEF( FT_Error )
-  cff_font_load( FT_Stream  stream,
+  cff_font_load( FT_Library library,
+                 FT_Stream  stream,
                  FT_Int     face_index,
-                 CFF_Font   font )
+                 CFF_Font   font,
+                 FT_Bool    pure_cff )
   {
     static const FT_Frame_Field  cff_header_fields[] =
     {
     FT_Memory        memory = stream->memory;
     FT_ULong         base_offset;
     CFF_FontRecDict  dict;
+    CFF_IndexRec     string_index;
 
 
     FT_ZERO( font );
+    FT_ZERO( &string_index );
 
     font->stream = stream;
     font->memory = memory;
          font->header_size      < 4 ||
          font->absolute_offsize > 4 )
     {
-      FT_TRACE2(( "[not a CFF font header!]\n" ));
+      FT_TRACE2(( "[not a CFF font header]\n" ));
       error = CFF_Err_Unknown_File_Format;
       goto Exit;
     }
 
     /* read the name, top dict, string and global subrs index */
     if ( FT_SET_ERROR( cff_index_init( &font->name_index,
-                                       stream, 0 ) )              ||
+                                       stream, 0 ) )                  ||
          FT_SET_ERROR( cff_index_init( &font->font_dict_index,
-                                       stream, 0 ) )              ||
-         FT_SET_ERROR( cff_index_init( &font->string_index,
-                                       stream, 0 ) )              ||
+                                       stream, 0 ) )                  ||
+         FT_SET_ERROR( cff_index_init( &string_index,
+                                       stream, 1 ) )                  ||
          FT_SET_ERROR( cff_index_init( &font->global_subrs_index,
-                                       stream, 1 ) )              )
+                                       stream, 1 ) )                  ||
+         FT_SET_ERROR( cff_index_get_pointers( &string_index,
+                                               &font->strings,
+                                               &font->string_pool ) ) )
       goto Exit;
 
+    font->num_strings = string_index.count;
+
     /* well, we don't really forget the `disabled' fonts... */
     font->num_faces = font->name_index.count;
     if ( face_index >= (FT_Int)font->num_faces )
                               &font->font_dict_index,
                               face_index,
                               stream,
-                              base_offset );
+                              base_offset,
+                              library );
     if ( error )
       goto Exit;
 
 
       if ( fd_index.count > CFF_MAX_CID_FONTS )
       {
-        FT_ERROR(( "cff_font_load: FD array too large in CID font\n" ));
+        FT_TRACE0(( "cff_font_load: FD array too large in CID font\n" ));
         goto Fail_CID;
       }
 
       {
         sub = font->subfonts[idx];
         error = cff_subfont_load( sub, &fd_index, idx,
-                                  stream, base_offset );
+                                  stream, base_offset, library );
         if ( error )
           goto Fail_CID;
       }
     /* read the charstrings index now */
     if ( dict->charstrings_offset == 0 )
     {
-      FT_ERROR(( "cff_font_load: no charstrings offset!\n" ));
+      FT_ERROR(( "cff_font_load: no charstrings offset\n" ));
       error = CFF_Err_Unknown_File_Format;
       goto Exit;
     }
 
-    /* explicit the global subrs */
-    font->num_global_subrs = font->global_subrs_index.count;
-    font->num_glyphs       = font->charstrings_index.count;
+    font->num_glyphs = font->charstrings_index.count;
 
     error = cff_index_get_pointers( &font->global_subrs_index,
-                                    &font->global_subrs ) ;
+                                    &font->global_subrs, NULL );
 
     if ( error )
       goto Exit;
     /* read the Charset and Encoding tables if available */
     if ( font->num_glyphs > 0 )
     {
-      FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU );
+      FT_Bool  invert = FT_BOOL( dict->cid_registry != 0xFFFFU && pure_cff );
 
 
       error = cff_charset_load( &font->charset, font->num_glyphs, stream,
         if ( error )
           goto Exit;
       }
-      else
-        /* CID-keyed fonts only need CIDs */
-        FT_FREE( font->charset.sids );
     }
 
     /* get the font name (/CIDFontName for CID-keyed fonts, */
     /* /FontName otherwise)                                 */
-    font->font_name = cff_index_get_name( &font->name_index, face_index );
+    font->font_name = cff_index_get_name( font, face_index );
 
   Exit:
+    cff_index_done( &string_index );
+
     return error;
   }
 
 
 
     cff_index_done( &font->global_subrs_index );
-    cff_index_done( &font->string_index );
     cff_index_done( &font->font_dict_index );
     cff_index_done( &font->name_index );
     cff_index_done( &font->charstrings_index );
 
     CFF_Done_FD_Select( &font->fd_select, font->stream );
 
-    if (font->font_info != NULL)
-    {
-      FT_FREE( font->font_info->version );
-      FT_FREE( font->font_info->notice );
-      FT_FREE( font->font_info->full_name );
-      FT_FREE( font->font_info->family_name );
-      FT_FREE( font->font_info->weight );
-      FT_FREE( font->font_info );
-    }
+    FT_FREE( font->font_info );
 
-    FT_FREE( font->global_subrs );
     FT_FREE( font->font_name );
+    FT_FREE( font->global_subrs );
+    FT_FREE( font->strings );
+    FT_FREE( font->string_pool );
   }