[CMAKE]
[reactos.git] / lib / 3rdparty / freetype / src / cff / cffload.c
index 64d1395..000cbe3 100644 (file)
@@ -4,7 +4,8 @@
 /*                                                                         */
 /*    OpenType and CFF data/program tables loader (body).                  */
 /*                                                                         */
-/*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009 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
 
 
       if ( offsize < 1 || offsize > 4 )
       {
-        error = FT_Err_Invalid_Table;
+        error = CFF_Err_Invalid_Table;
         goto Exit;
       }
 
   }
 
 
-  /* 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 )
+      {
+        FT_TRACE0(( "cff_index_get_pointers:"
+                    " invalid first offset value %d set to zero\n",
+                    cur_offset ));
+        cur_offset = 0;
+      }
+
+      if ( !pool )
+        t[0] = org_bytes + cur_offset;
+      else
+        t[0] = new_bytes + cur_offset;
+
+      for ( n = 1; n <= idx->count; n++ )
       {
-        /* at this point, `idx->offsets' can't be NULL */
-        offset = idx->offsets[n];
-        if ( !offset )
-          offset = old_offset;
+        FT_ULong  next_offset = idx->offsets[n] - 1;
 
-        /* two sanity checks for invalid offset tables */
-        else if ( offset < old_offset )
-          offset = old_offset;
 
-        else if ( offset - 1 >= idx->data_size && n < idx->count )
-          offset = old_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;
 
-        t[n] = idx->bytes + offset - 1;
+        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++;
+          }
+        }
 
-        old_offset = offset;
+        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_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_Index           idx,
-                            FT_UInt             sid,
-                            FT_Service_PsCMaps  psnames )
+  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 ( !font->psnames )
+      return NULL;
 
-      if ( adobe_name )
-      {
-        FT_Memory  memory = idx->stream->memory;
-        FT_Error   error;
-
-
-        (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;
 
     /* When multiple GIDs map to the same CID, we choose the lowest */
     FT_UInt  result = 0;
 
 
-    if ( cid < charset->max_cid )
+    if ( cid <= charset->max_cid )
       result = charset->cids[cid];
 
     return result;
             goto Exit;
 
           for ( j = 1; j < num_glyphs; j++ )
-          {
-            FT_UShort sid = FT_GET_USHORT();
-
-
-            /* this constant is given in the CFF specification */
-            if ( sid < 65000L )
-              charset->sids[j] = sid;
-            else
-            {
-              FT_TRACE0(( "cff_charset_load:"
-                          " invalid SID value %d set to zero\n", sid ));
-              charset->sids[j] = 0;
-            }
-          }
+            charset->sids[j] = FT_GET_USHORT();
 
           FT_FRAME_EXIT();
         }
                 goto Exit;
             }
 
-            /* check whether the range contains at least one valid glyph; */
-            /* the constant is given in the CFF specification             */
-            if ( glyph_sid >= 65000L ) {
-              FT_ERROR(( "cff_charset_load: invalid SID range\n" ));
-              error = CFF_Err_Invalid_File_Format;
-              goto Exit;
-            }
-
             /* try to rescue some of the SIDs if `nleft' is too large */
-            if ( nleft > 65000L - 1L || glyph_sid >= 65000L - nleft ) {
-              FT_ERROR(( "cff_charset_load: invalid SID range trimmed\n" ));
-              nleft = ( FT_UInt )( 65000L - 1L - glyph_sid );
+            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. */
           if ( gid != 0 )
           {
             encoding->codes[j] = (FT_UShort)gid;
-
-            if ( encoding->count < j + 1 )
-              encoding->count = j + 1;
+            encoding->count    = j + 1;
           }
           else
           {
       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_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;
 
     /* 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 )
       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;
 
     /* 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->registry );
-    FT_FREE( font->ordering );
-
-    FT_FREE( font->global_subrs );
     FT_FREE( font->font_name );
+    FT_FREE( font->global_subrs );
+    FT_FREE( font->strings );
+    FT_FREE( font->string_pool );
   }