misc/libfreetype/src/pfr/pfrload.c
changeset 9372 915436ff64ab
parent 9371 f3840de881bd
child 9373 b769a8e38cbd
equal deleted inserted replaced
9371:f3840de881bd 9372:915436ff64ab
     1 /***************************************************************************/
       
     2 /*                                                                         */
       
     3 /*  pfrload.c                                                              */
       
     4 /*                                                                         */
       
     5 /*    FreeType PFR loader (body).                                          */
       
     6 /*                                                                         */
       
     7 /*  Copyright 2002, 2003, 2004, 2005, 2007, 2009, 2010 by                  */
       
     8 /*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
       
     9 /*                                                                         */
       
    10 /*  This file is part of the FreeType project, and may only be used,       */
       
    11 /*  modified, and distributed under the terms of the FreeType project      */
       
    12 /*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
       
    13 /*  this file you indicate that you have read the license and              */
       
    14 /*  understand and accept it fully.                                        */
       
    15 /*                                                                         */
       
    16 /***************************************************************************/
       
    17 
       
    18 
       
    19 #include "pfrload.h"
       
    20 #include FT_INTERNAL_DEBUG_H
       
    21 #include FT_INTERNAL_STREAM_H
       
    22 
       
    23 #include "pfrerror.h"
       
    24 
       
    25 #undef  FT_COMPONENT
       
    26 #define FT_COMPONENT  trace_pfr
       
    27 
       
    28 
       
    29   /*************************************************************************/
       
    30   /*************************************************************************/
       
    31   /*****                                                               *****/
       
    32   /*****                          EXTRA ITEMS                          *****/
       
    33   /*****                                                               *****/
       
    34   /*************************************************************************/
       
    35   /*************************************************************************/
       
    36 
       
    37 
       
    38   FT_LOCAL_DEF( FT_Error )
       
    39   pfr_extra_items_skip( FT_Byte*  *pp,
       
    40                         FT_Byte*   limit )
       
    41   {
       
    42     return pfr_extra_items_parse( pp, limit, NULL, NULL );
       
    43   }
       
    44 
       
    45 
       
    46   FT_LOCAL_DEF( FT_Error )
       
    47   pfr_extra_items_parse( FT_Byte*       *pp,
       
    48                          FT_Byte*        limit,
       
    49                          PFR_ExtraItem   item_list,
       
    50                          FT_Pointer      item_data )
       
    51   {
       
    52     FT_Error  error = PFR_Err_Ok;
       
    53     FT_Byte*  p     = *pp;
       
    54     FT_UInt   num_items, item_type, item_size;
       
    55 
       
    56 
       
    57     PFR_CHECK( 1 );
       
    58     num_items = PFR_NEXT_BYTE( p );
       
    59 
       
    60     for ( ; num_items > 0; num_items-- )
       
    61     {
       
    62       PFR_CHECK( 2 );
       
    63       item_size = PFR_NEXT_BYTE( p );
       
    64       item_type = PFR_NEXT_BYTE( p );
       
    65 
       
    66       PFR_CHECK( item_size );
       
    67 
       
    68       if ( item_list )
       
    69       {
       
    70         PFR_ExtraItem  extra = item_list;
       
    71 
       
    72 
       
    73         for ( extra = item_list; extra->parser != NULL; extra++ )
       
    74         {
       
    75           if ( extra->type == item_type )
       
    76           {
       
    77             error = extra->parser( p, p + item_size, item_data );
       
    78             if ( error ) goto Exit;
       
    79 
       
    80             break;
       
    81           }
       
    82         }
       
    83       }
       
    84 
       
    85       p += item_size;
       
    86     }
       
    87 
       
    88   Exit:
       
    89     *pp = p;
       
    90     return error;
       
    91 
       
    92   Too_Short:
       
    93     FT_ERROR(( "pfr_extra_items_parse: invalid extra items table\n" ));
       
    94     error = PFR_Err_Invalid_Table;
       
    95     goto Exit;
       
    96   }
       
    97 
       
    98 
       
    99   /*************************************************************************/
       
   100   /*************************************************************************/
       
   101   /*****                                                               *****/
       
   102   /*****                          PFR HEADER                           *****/
       
   103   /*****                                                               *****/
       
   104   /*************************************************************************/
       
   105   /*************************************************************************/
       
   106 
       
   107    static const FT_Frame_Field  pfr_header_fields[] =
       
   108    {
       
   109 #undef  FT_STRUCTURE
       
   110 #define FT_STRUCTURE  PFR_HeaderRec
       
   111 
       
   112      FT_FRAME_START( 58 ),
       
   113        FT_FRAME_ULONG ( signature ),
       
   114        FT_FRAME_USHORT( version ),
       
   115        FT_FRAME_USHORT( signature2 ),
       
   116        FT_FRAME_USHORT( header_size ),
       
   117 
       
   118        FT_FRAME_USHORT( log_dir_size ),
       
   119        FT_FRAME_USHORT( log_dir_offset ),
       
   120 
       
   121        FT_FRAME_USHORT( log_font_max_size ),
       
   122        FT_FRAME_UOFF3 ( log_font_section_size ),
       
   123        FT_FRAME_UOFF3 ( log_font_section_offset ),
       
   124 
       
   125        FT_FRAME_USHORT( phy_font_max_size ),
       
   126        FT_FRAME_UOFF3 ( phy_font_section_size ),
       
   127        FT_FRAME_UOFF3 ( phy_font_section_offset ),
       
   128 
       
   129        FT_FRAME_USHORT( gps_max_size ),
       
   130        FT_FRAME_UOFF3 ( gps_section_size ),
       
   131        FT_FRAME_UOFF3 ( gps_section_offset ),
       
   132 
       
   133        FT_FRAME_BYTE  ( max_blue_values ),
       
   134        FT_FRAME_BYTE  ( max_x_orus ),
       
   135        FT_FRAME_BYTE  ( max_y_orus ),
       
   136 
       
   137        FT_FRAME_BYTE  ( phy_font_max_size_high ),
       
   138        FT_FRAME_BYTE  ( color_flags ),
       
   139 
       
   140        FT_FRAME_UOFF3 ( bct_max_size ),
       
   141        FT_FRAME_UOFF3 ( bct_set_max_size ),
       
   142        FT_FRAME_UOFF3 ( phy_bct_set_max_size ),
       
   143 
       
   144        FT_FRAME_USHORT( num_phy_fonts ),
       
   145        FT_FRAME_BYTE  ( max_vert_stem_snap ),
       
   146        FT_FRAME_BYTE  ( max_horz_stem_snap ),
       
   147        FT_FRAME_USHORT( max_chars ),
       
   148      FT_FRAME_END
       
   149    };
       
   150 
       
   151 
       
   152   FT_LOCAL_DEF( FT_Error )
       
   153   pfr_header_load( PFR_Header  header,
       
   154                    FT_Stream   stream )
       
   155   {
       
   156     FT_Error  error;
       
   157 
       
   158 
       
   159     /* read header directly */
       
   160     if ( !FT_STREAM_SEEK( 0 )                                &&
       
   161          !FT_STREAM_READ_FIELDS( pfr_header_fields, header ) )
       
   162     {
       
   163       /* make a few adjustments to the header */
       
   164       header->phy_font_max_size +=
       
   165         (FT_UInt32)header->phy_font_max_size_high << 16;
       
   166     }
       
   167 
       
   168     return error;
       
   169   }
       
   170 
       
   171 
       
   172   FT_LOCAL_DEF( FT_Bool )
       
   173   pfr_header_check( PFR_Header  header )
       
   174   {
       
   175     FT_Bool  result = 1;
       
   176 
       
   177 
       
   178     /* check signature and header size */
       
   179     if ( header->signature  != 0x50465230L ||   /* "PFR0" */
       
   180          header->version     > 4           ||
       
   181          header->header_size < 58          ||
       
   182          header->signature2 != 0x0d0a      )    /* CR/LF  */
       
   183     {
       
   184       result = 0;
       
   185     }
       
   186     return  result;
       
   187   }
       
   188 
       
   189 
       
   190   /***********************************************************************/
       
   191   /***********************************************************************/
       
   192   /*****                                                             *****/
       
   193   /*****                    PFR LOGICAL FONTS                        *****/
       
   194   /*****                                                             *****/
       
   195   /***********************************************************************/
       
   196   /***********************************************************************/
       
   197 
       
   198 
       
   199   FT_LOCAL_DEF( FT_Error )
       
   200   pfr_log_font_count( FT_Stream  stream,
       
   201                       FT_UInt32  section_offset,
       
   202                       FT_UInt   *acount )
       
   203   {
       
   204     FT_Error  error;
       
   205     FT_UInt   count;
       
   206     FT_UInt   result = 0;
       
   207 
       
   208 
       
   209     if ( FT_STREAM_SEEK( section_offset ) || FT_READ_USHORT( count ) )
       
   210       goto Exit;
       
   211 
       
   212     result = count;
       
   213 
       
   214   Exit:
       
   215     *acount = result;
       
   216     return error;
       
   217   }
       
   218 
       
   219 
       
   220   FT_LOCAL_DEF( FT_Error )
       
   221   pfr_log_font_load( PFR_LogFont  log_font,
       
   222                      FT_Stream    stream,
       
   223                      FT_UInt      idx,
       
   224                      FT_UInt32    section_offset,
       
   225                      FT_Bool      size_increment )
       
   226   {
       
   227     FT_UInt    num_log_fonts;
       
   228     FT_UInt    flags;
       
   229     FT_UInt32  offset;
       
   230     FT_UInt32  size;
       
   231     FT_Error   error;
       
   232 
       
   233 
       
   234     if ( FT_STREAM_SEEK( section_offset ) ||
       
   235          FT_READ_USHORT( num_log_fonts )  )
       
   236       goto Exit;
       
   237 
       
   238     if ( idx >= num_log_fonts )
       
   239       return PFR_Err_Invalid_Argument;
       
   240 
       
   241     if ( FT_STREAM_SKIP( idx * 5 ) ||
       
   242          FT_READ_USHORT( size )    ||
       
   243          FT_READ_UOFF3 ( offset )  )
       
   244       goto Exit;
       
   245 
       
   246     /* save logical font size and offset */
       
   247     log_font->size   = size;
       
   248     log_font->offset = offset;
       
   249 
       
   250     /* now, check the rest of the table before loading it */
       
   251     {
       
   252       FT_Byte*  p;
       
   253       FT_Byte*  limit;
       
   254       FT_UInt   local;
       
   255 
       
   256 
       
   257       if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
       
   258         goto Exit;
       
   259 
       
   260       p     = stream->cursor;
       
   261       limit = p + size;
       
   262 
       
   263       PFR_CHECK(13);
       
   264 
       
   265       log_font->matrix[0] = PFR_NEXT_LONG( p );
       
   266       log_font->matrix[1] = PFR_NEXT_LONG( p );
       
   267       log_font->matrix[2] = PFR_NEXT_LONG( p );
       
   268       log_font->matrix[3] = PFR_NEXT_LONG( p );
       
   269 
       
   270       flags = PFR_NEXT_BYTE( p );
       
   271 
       
   272       local = 0;
       
   273       if ( flags & PFR_LOG_STROKE )
       
   274       {
       
   275         local++;
       
   276         if ( flags & PFR_LOG_2BYTE_STROKE )
       
   277           local++;
       
   278 
       
   279         if ( (flags & PFR_LINE_JOIN_MASK) == PFR_LINE_JOIN_MITER )
       
   280           local += 3;
       
   281       }
       
   282       if ( flags & PFR_LOG_BOLD )
       
   283       {
       
   284         local++;
       
   285         if ( flags & PFR_LOG_2BYTE_BOLD )
       
   286           local++;
       
   287       }
       
   288 
       
   289       PFR_CHECK( local );
       
   290 
       
   291       if ( flags & PFR_LOG_STROKE )
       
   292       {
       
   293         log_font->stroke_thickness = ( flags & PFR_LOG_2BYTE_STROKE )
       
   294                                      ? PFR_NEXT_SHORT( p )
       
   295                                      : PFR_NEXT_BYTE( p );
       
   296 
       
   297         if ( ( flags & PFR_LINE_JOIN_MASK ) == PFR_LINE_JOIN_MITER )
       
   298           log_font->miter_limit = PFR_NEXT_LONG( p );
       
   299       }
       
   300 
       
   301       if ( flags & PFR_LOG_BOLD )
       
   302       {
       
   303         log_font->bold_thickness = ( flags & PFR_LOG_2BYTE_BOLD )
       
   304                                    ? PFR_NEXT_SHORT( p )
       
   305                                    : PFR_NEXT_BYTE( p );
       
   306       }
       
   307 
       
   308       if ( flags & PFR_LOG_EXTRA_ITEMS )
       
   309       {
       
   310         error = pfr_extra_items_skip( &p, limit );
       
   311         if (error) goto Fail;
       
   312       }
       
   313 
       
   314       PFR_CHECK(5);
       
   315       log_font->phys_size   = PFR_NEXT_USHORT( p );
       
   316       log_font->phys_offset = PFR_NEXT_ULONG( p );
       
   317       if ( size_increment )
       
   318       {
       
   319         PFR_CHECK( 1 );
       
   320         log_font->phys_size += (FT_UInt32)PFR_NEXT_BYTE( p ) << 16;
       
   321       }
       
   322     }
       
   323 
       
   324   Fail:
       
   325     FT_FRAME_EXIT();
       
   326 
       
   327   Exit:
       
   328     return error;
       
   329 
       
   330   Too_Short:
       
   331     FT_ERROR(( "pfr_log_font_load: invalid logical font table\n" ));
       
   332     error = PFR_Err_Invalid_Table;
       
   333     goto Fail;
       
   334   }
       
   335 
       
   336 
       
   337   /***********************************************************************/
       
   338   /***********************************************************************/
       
   339   /*****                                                             *****/
       
   340   /*****                    PFR PHYSICAL FONTS                       *****/
       
   341   /*****                                                             *****/
       
   342   /***********************************************************************/
       
   343   /***********************************************************************/
       
   344 
       
   345 
       
   346   /* load bitmap strikes lists */
       
   347   FT_CALLBACK_DEF( FT_Error )
       
   348   pfr_extra_item_load_bitmap_info( FT_Byte*     p,
       
   349                                    FT_Byte*     limit,
       
   350                                    PFR_PhyFont  phy_font )
       
   351   {
       
   352     FT_Memory   memory = phy_font->memory;
       
   353     PFR_Strike  strike;
       
   354     FT_UInt     flags0;
       
   355     FT_UInt     n, count, size1;
       
   356     FT_Error    error = PFR_Err_Ok;
       
   357 
       
   358 
       
   359     PFR_CHECK( 5 );
       
   360 
       
   361     p += 3;  /* skip bctSize */
       
   362     flags0 = PFR_NEXT_BYTE( p );
       
   363     count  = PFR_NEXT_BYTE( p );
       
   364 
       
   365     /* re-allocate when needed */
       
   366     if ( phy_font->num_strikes + count > phy_font->max_strikes )
       
   367     {
       
   368       FT_UInt  new_max = FT_PAD_CEIL( phy_font->num_strikes + count, 4 );
       
   369 
       
   370 
       
   371       if ( FT_RENEW_ARRAY( phy_font->strikes,
       
   372                            phy_font->num_strikes,
       
   373                            new_max ) )
       
   374         goto Exit;
       
   375 
       
   376       phy_font->max_strikes = new_max;
       
   377     }
       
   378 
       
   379     size1 = 1 + 1 + 1 + 2 + 2 + 1;
       
   380     if ( flags0 & PFR_STRIKE_2BYTE_XPPM )
       
   381       size1++;
       
   382 
       
   383     if ( flags0 & PFR_STRIKE_2BYTE_YPPM )
       
   384       size1++;
       
   385 
       
   386     if ( flags0 & PFR_STRIKE_3BYTE_SIZE )
       
   387       size1++;
       
   388 
       
   389     if ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
       
   390       size1++;
       
   391 
       
   392     if ( flags0 & PFR_STRIKE_2BYTE_COUNT )
       
   393       size1++;
       
   394 
       
   395     strike = phy_font->strikes + phy_font->num_strikes;
       
   396 
       
   397     PFR_CHECK( count * size1 );
       
   398 
       
   399     for ( n = 0; n < count; n++, strike++ )
       
   400     {
       
   401       strike->x_ppm       = ( flags0 & PFR_STRIKE_2BYTE_XPPM )
       
   402                             ? PFR_NEXT_USHORT( p )
       
   403                             : PFR_NEXT_BYTE( p );
       
   404 
       
   405       strike->y_ppm       = ( flags0 & PFR_STRIKE_2BYTE_YPPM )
       
   406                             ? PFR_NEXT_USHORT( p )
       
   407                             : PFR_NEXT_BYTE( p );
       
   408 
       
   409       strike->flags       = PFR_NEXT_BYTE( p );
       
   410 
       
   411       strike->bct_size    = ( flags0 & PFR_STRIKE_3BYTE_SIZE )
       
   412                             ? PFR_NEXT_ULONG( p )
       
   413                             : PFR_NEXT_USHORT( p );
       
   414 
       
   415       strike->bct_offset  = ( flags0 & PFR_STRIKE_3BYTE_OFFSET )
       
   416                             ? PFR_NEXT_ULONG( p )
       
   417                             : PFR_NEXT_USHORT( p );
       
   418 
       
   419       strike->num_bitmaps = ( flags0 & PFR_STRIKE_2BYTE_COUNT )
       
   420                             ? PFR_NEXT_USHORT( p )
       
   421                             : PFR_NEXT_BYTE( p );
       
   422     }
       
   423 
       
   424     phy_font->num_strikes += count;
       
   425 
       
   426   Exit:
       
   427     return error;
       
   428 
       
   429   Too_Short:
       
   430     error = PFR_Err_Invalid_Table;
       
   431     FT_ERROR(( "pfr_extra_item_load_bitmap_info:"
       
   432                " invalid bitmap info table\n" ));
       
   433     goto Exit;
       
   434   }
       
   435 
       
   436 
       
   437   /* Load font ID.  This is a so-called "unique" name that is rather
       
   438    * long and descriptive (like "Tiresias ScreenFont v7.51").
       
   439    *
       
   440    * Note that a PFR font's family name is contained in an *undocumented*
       
   441    * string of the "auxiliary data" portion of a physical font record.  This
       
   442    * may also contain the "real" style name!
       
   443    *
       
   444    * If no family name is present, the font ID is used instead for the
       
   445    * family.
       
   446    */
       
   447   FT_CALLBACK_DEF( FT_Error )
       
   448   pfr_extra_item_load_font_id( FT_Byte*     p,
       
   449                                FT_Byte*     limit,
       
   450                                PFR_PhyFont  phy_font )
       
   451   {
       
   452     FT_Error    error  = PFR_Err_Ok;
       
   453     FT_Memory   memory = phy_font->memory;
       
   454     FT_PtrDist  len    = limit - p;
       
   455 
       
   456 
       
   457     if ( phy_font->font_id != NULL )
       
   458       goto Exit;
       
   459 
       
   460     if ( FT_ALLOC( phy_font->font_id, len + 1 ) )
       
   461       goto Exit;
       
   462 
       
   463     /* copy font ID name, and terminate it for safety */
       
   464     FT_MEM_COPY( phy_font->font_id, p, len );
       
   465     phy_font->font_id[len] = 0;
       
   466 
       
   467   Exit:
       
   468     return error;
       
   469   }
       
   470 
       
   471 
       
   472   /* load stem snap tables */
       
   473   FT_CALLBACK_DEF( FT_Error )
       
   474   pfr_extra_item_load_stem_snaps( FT_Byte*     p,
       
   475                                   FT_Byte*     limit,
       
   476                                   PFR_PhyFont  phy_font )
       
   477   {
       
   478     FT_UInt    count, num_vert, num_horz;
       
   479     FT_Int*    snaps;
       
   480     FT_Error   error  = PFR_Err_Ok;
       
   481     FT_Memory  memory = phy_font->memory;
       
   482 
       
   483 
       
   484     if ( phy_font->vertical.stem_snaps != NULL )
       
   485       goto Exit;
       
   486 
       
   487     PFR_CHECK( 1 );
       
   488     count = PFR_NEXT_BYTE( p );
       
   489 
       
   490     num_vert = count & 15;
       
   491     num_horz = count >> 4;
       
   492     count    = num_vert + num_horz;
       
   493 
       
   494     PFR_CHECK( count * 2 );
       
   495 
       
   496     if ( FT_NEW_ARRAY( snaps, count ) )
       
   497       goto Exit;
       
   498 
       
   499     phy_font->vertical.stem_snaps = snaps;
       
   500     phy_font->horizontal.stem_snaps = snaps + num_vert;
       
   501 
       
   502     for ( ; count > 0; count--, snaps++ )
       
   503       *snaps = FT_NEXT_SHORT( p );
       
   504 
       
   505   Exit:
       
   506     return error;
       
   507 
       
   508   Too_Short:
       
   509     error = PFR_Err_Invalid_Table;
       
   510     FT_ERROR(( "pfr_exta_item_load_stem_snaps:"
       
   511                " invalid stem snaps table\n" ));
       
   512     goto Exit;
       
   513   }
       
   514 
       
   515 
       
   516 
       
   517   /* load kerning pair data */
       
   518   FT_CALLBACK_DEF( FT_Error )
       
   519   pfr_extra_item_load_kerning_pairs( FT_Byte*     p,
       
   520                                      FT_Byte*     limit,
       
   521                                      PFR_PhyFont  phy_font )
       
   522   {
       
   523     PFR_KernItem  item   = NULL;
       
   524     FT_Error      error  = PFR_Err_Ok;
       
   525     FT_Memory     memory = phy_font->memory;
       
   526 
       
   527 
       
   528     FT_TRACE2(( "pfr_extra_item_load_kerning_pairs()\n" ));
       
   529 
       
   530     if ( FT_NEW( item ) )
       
   531       goto Exit;
       
   532 
       
   533     PFR_CHECK( 4 );
       
   534 
       
   535     item->pair_count = PFR_NEXT_BYTE( p );
       
   536     item->base_adj   = PFR_NEXT_SHORT( p );
       
   537     item->flags      = PFR_NEXT_BYTE( p );
       
   538     item->offset     = phy_font->offset + ( p - phy_font->cursor );
       
   539 
       
   540 #ifndef PFR_CONFIG_NO_CHECKS
       
   541     item->pair_size = 3;
       
   542 
       
   543     if ( item->flags & PFR_KERN_2BYTE_CHAR )
       
   544       item->pair_size += 2;
       
   545 
       
   546     if ( item->flags & PFR_KERN_2BYTE_ADJ )
       
   547       item->pair_size += 1;
       
   548 
       
   549     PFR_CHECK( item->pair_count * item->pair_size );
       
   550 #endif
       
   551 
       
   552     /* load first and last pairs into the item to speed up */
       
   553     /* lookup later...                                     */
       
   554     if ( item->pair_count > 0 )
       
   555     {
       
   556       FT_UInt   char1, char2;
       
   557       FT_Byte*  q;
       
   558 
       
   559 
       
   560       if ( item->flags & PFR_KERN_2BYTE_CHAR )
       
   561       {
       
   562         q     = p;
       
   563         char1 = PFR_NEXT_USHORT( q );
       
   564         char2 = PFR_NEXT_USHORT( q );
       
   565 
       
   566         item->pair1 = PFR_KERN_INDEX( char1, char2 );
       
   567 
       
   568         q = p + item->pair_size * ( item->pair_count - 1 );
       
   569         char1 = PFR_NEXT_USHORT( q );
       
   570         char2 = PFR_NEXT_USHORT( q );
       
   571 
       
   572         item->pair2 = PFR_KERN_INDEX( char1, char2 );
       
   573       }
       
   574       else
       
   575       {
       
   576         q     = p;
       
   577         char1 = PFR_NEXT_BYTE( q );
       
   578         char2 = PFR_NEXT_BYTE( q );
       
   579 
       
   580         item->pair1 = PFR_KERN_INDEX( char1, char2 );
       
   581 
       
   582         q = p + item->pair_size * ( item->pair_count - 1 );
       
   583         char1 = PFR_NEXT_BYTE( q );
       
   584         char2 = PFR_NEXT_BYTE( q );
       
   585 
       
   586         item->pair2 = PFR_KERN_INDEX( char1, char2 );
       
   587       }
       
   588 
       
   589       /* add new item to the current list */
       
   590       item->next                 = NULL;
       
   591       *phy_font->kern_items_tail = item;
       
   592       phy_font->kern_items_tail  = &item->next;
       
   593       phy_font->num_kern_pairs  += item->pair_count;
       
   594     }
       
   595     else
       
   596     {
       
   597       /* empty item! */
       
   598       FT_FREE( item );
       
   599     }
       
   600 
       
   601   Exit:
       
   602     return error;
       
   603 
       
   604   Too_Short:
       
   605     FT_FREE( item );
       
   606 
       
   607     error = PFR_Err_Invalid_Table;
       
   608     FT_ERROR(( "pfr_extra_item_load_kerning_pairs:"
       
   609                " invalid kerning pairs table\n" ));
       
   610     goto Exit;
       
   611   }
       
   612 
       
   613 
       
   614 
       
   615   static const PFR_ExtraItemRec  pfr_phy_font_extra_items[] =
       
   616   {
       
   617     { 1, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_bitmap_info },
       
   618     { 2, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_font_id },
       
   619     { 3, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_stem_snaps },
       
   620     { 4, (PFR_ExtraItem_ParseFunc)pfr_extra_item_load_kerning_pairs },
       
   621     { 0, NULL }
       
   622   };
       
   623 
       
   624 
       
   625   /* Loads a name from the auxiliary data.  Since this extracts undocumented
       
   626    * strings from the font file, we need to be careful here.
       
   627    */
       
   628   static FT_Error
       
   629   pfr_aux_name_load( FT_Byte*     p,
       
   630                      FT_UInt      len,
       
   631                      FT_Memory    memory,
       
   632                      FT_String*  *astring )
       
   633   {
       
   634     FT_Error    error = PFR_Err_Ok;
       
   635     FT_String*  result = NULL;
       
   636     FT_UInt     n, ok;
       
   637 
       
   638 
       
   639     if ( len > 0 && p[len - 1] == 0 )
       
   640       len--;
       
   641 
       
   642     /* check that each character is ASCII for making sure not to
       
   643        load garbage
       
   644      */
       
   645     ok = ( len > 0 );
       
   646     for ( n = 0; n < len; n++ )
       
   647       if ( p[n] < 32 || p[n] > 127 )
       
   648       {
       
   649         ok = 0;
       
   650         break;
       
   651       }
       
   652 
       
   653     if ( ok )
       
   654     {
       
   655       if ( FT_ALLOC( result, len + 1 ) )
       
   656         goto Exit;
       
   657 
       
   658       FT_MEM_COPY( result, p, len );
       
   659       result[len] = 0;
       
   660     }
       
   661   Exit:
       
   662     *astring = result;
       
   663     return error;
       
   664   }
       
   665 
       
   666 
       
   667   FT_LOCAL_DEF( void )
       
   668   pfr_phy_font_done( PFR_PhyFont  phy_font,
       
   669                      FT_Memory    memory )
       
   670   {
       
   671     FT_FREE( phy_font->font_id );
       
   672     FT_FREE( phy_font->family_name );
       
   673     FT_FREE( phy_font->style_name );
       
   674 
       
   675     FT_FREE( phy_font->vertical.stem_snaps );
       
   676     phy_font->vertical.num_stem_snaps = 0;
       
   677 
       
   678     phy_font->horizontal.stem_snaps     = NULL;
       
   679     phy_font->horizontal.num_stem_snaps = 0;
       
   680 
       
   681     FT_FREE( phy_font->strikes );
       
   682     phy_font->num_strikes = 0;
       
   683     phy_font->max_strikes = 0;
       
   684 
       
   685     FT_FREE( phy_font->chars );
       
   686     phy_font->num_chars    = 0;
       
   687     phy_font->chars_offset = 0;
       
   688 
       
   689     FT_FREE( phy_font->blue_values );
       
   690     phy_font->num_blue_values = 0;
       
   691 
       
   692     {
       
   693       PFR_KernItem  item, next;
       
   694 
       
   695 
       
   696       item = phy_font->kern_items;
       
   697       while ( item )
       
   698       {
       
   699         next = item->next;
       
   700         FT_FREE( item );
       
   701         item = next;
       
   702       }
       
   703       phy_font->kern_items      = NULL;
       
   704       phy_font->kern_items_tail = NULL;
       
   705     }
       
   706 
       
   707     phy_font->num_kern_pairs = 0;
       
   708   }
       
   709 
       
   710 
       
   711   FT_LOCAL_DEF( FT_Error )
       
   712   pfr_phy_font_load( PFR_PhyFont  phy_font,
       
   713                      FT_Stream    stream,
       
   714                      FT_UInt32    offset,
       
   715                      FT_UInt32    size )
       
   716   {
       
   717     FT_Error   error;
       
   718     FT_Memory  memory = stream->memory;
       
   719     FT_UInt    flags;
       
   720     FT_ULong   num_aux;
       
   721     FT_Byte*   p;
       
   722     FT_Byte*   limit;
       
   723 
       
   724 
       
   725     phy_font->memory = memory;
       
   726     phy_font->offset = offset;
       
   727 
       
   728     phy_font->kern_items      = NULL;
       
   729     phy_font->kern_items_tail = &phy_font->kern_items;
       
   730 
       
   731     if ( FT_STREAM_SEEK( offset ) || FT_FRAME_ENTER( size ) )
       
   732       goto Exit;
       
   733 
       
   734     phy_font->cursor = stream->cursor;
       
   735 
       
   736     p     = stream->cursor;
       
   737     limit = p + size;
       
   738 
       
   739     PFR_CHECK( 15 );
       
   740     phy_font->font_ref_number    = PFR_NEXT_USHORT( p );
       
   741     phy_font->outline_resolution = PFR_NEXT_USHORT( p );
       
   742     phy_font->metrics_resolution = PFR_NEXT_USHORT( p );
       
   743     phy_font->bbox.xMin          = PFR_NEXT_SHORT( p );
       
   744     phy_font->bbox.yMin          = PFR_NEXT_SHORT( p );
       
   745     phy_font->bbox.xMax          = PFR_NEXT_SHORT( p );
       
   746     phy_font->bbox.yMax          = PFR_NEXT_SHORT( p );
       
   747     phy_font->flags      = flags = PFR_NEXT_BYTE( p );
       
   748 
       
   749     /* get the standard advance for non-proportional fonts */
       
   750     if ( !(flags & PFR_PHY_PROPORTIONAL) )
       
   751     {
       
   752       PFR_CHECK( 2 );
       
   753       phy_font->standard_advance = PFR_NEXT_SHORT( p );
       
   754     }
       
   755 
       
   756     /* load the extra items when present */
       
   757     if ( flags & PFR_PHY_EXTRA_ITEMS )
       
   758     {
       
   759       error =  pfr_extra_items_parse( &p, limit,
       
   760                                       pfr_phy_font_extra_items, phy_font );
       
   761 
       
   762       if ( error )
       
   763         goto Fail;
       
   764     }
       
   765 
       
   766     /* In certain fonts, the auxiliary bytes contain interesting  */
       
   767     /* information. These are not in the specification but can be */
       
   768     /* guessed by looking at the content of a few PFR0 fonts.     */
       
   769     PFR_CHECK( 3 );
       
   770     num_aux = PFR_NEXT_ULONG( p );
       
   771 
       
   772     if ( num_aux > 0 )
       
   773     {
       
   774       FT_Byte*  q = p;
       
   775       FT_Byte*  q2;
       
   776 
       
   777 
       
   778       PFR_CHECK( num_aux );
       
   779       p += num_aux;
       
   780 
       
   781       while ( num_aux > 0 )
       
   782       {
       
   783         FT_UInt  length, type;
       
   784 
       
   785 
       
   786         if ( q + 4 > p )
       
   787           break;
       
   788 
       
   789         length = PFR_NEXT_USHORT( q );
       
   790         if ( length < 4 || length > num_aux )
       
   791           break;
       
   792 
       
   793         q2   = q + length - 2;
       
   794         type = PFR_NEXT_USHORT( q );
       
   795 
       
   796         switch ( type )
       
   797         {
       
   798         case 1:
       
   799           /* this seems to correspond to the font's family name,
       
   800            * padded to 16-bits with one zero when necessary
       
   801            */
       
   802           error = pfr_aux_name_load( q, length - 4U, memory,
       
   803                                      &phy_font->family_name );
       
   804           if ( error )
       
   805             goto Exit;
       
   806           break;
       
   807 
       
   808         case 2:
       
   809           if ( q + 32 > q2 )
       
   810             break;
       
   811 
       
   812           q += 10;
       
   813           phy_font->ascent  = PFR_NEXT_SHORT( q );
       
   814           phy_font->descent = PFR_NEXT_SHORT( q );
       
   815           phy_font->leading = PFR_NEXT_SHORT( q );
       
   816           q += 16;
       
   817           break;
       
   818 
       
   819         case 3:
       
   820           /* this seems to correspond to the font's style name,
       
   821            * padded to 16-bits with one zero when necessary
       
   822            */
       
   823           error = pfr_aux_name_load( q, length - 4U, memory,
       
   824                                      &phy_font->style_name );
       
   825           if ( error )
       
   826             goto Exit;
       
   827           break;
       
   828 
       
   829         default:
       
   830           ;
       
   831         }
       
   832 
       
   833         q        = q2;
       
   834         num_aux -= length;
       
   835       }
       
   836     }
       
   837 
       
   838     /* read the blue values */
       
   839     {
       
   840       FT_UInt  n, count;
       
   841 
       
   842 
       
   843       PFR_CHECK( 1 );
       
   844       phy_font->num_blue_values = count = PFR_NEXT_BYTE( p );
       
   845 
       
   846       PFR_CHECK( count * 2 );
       
   847 
       
   848       if ( FT_NEW_ARRAY( phy_font->blue_values, count ) )
       
   849         goto Fail;
       
   850 
       
   851       for ( n = 0; n < count; n++ )
       
   852         phy_font->blue_values[n] = PFR_NEXT_SHORT( p );
       
   853     }
       
   854 
       
   855     PFR_CHECK( 8 );
       
   856     phy_font->blue_fuzz  = PFR_NEXT_BYTE( p );
       
   857     phy_font->blue_scale = PFR_NEXT_BYTE( p );
       
   858 
       
   859     phy_font->vertical.standard   = PFR_NEXT_USHORT( p );
       
   860     phy_font->horizontal.standard = PFR_NEXT_USHORT( p );
       
   861 
       
   862     /* read the character descriptors */
       
   863     {
       
   864       FT_UInt  n, count, Size;
       
   865 
       
   866 
       
   867       phy_font->num_chars    = count = PFR_NEXT_USHORT( p );
       
   868       phy_font->chars_offset = offset + ( p - stream->cursor );
       
   869 
       
   870       if ( FT_NEW_ARRAY( phy_font->chars, count ) )
       
   871         goto Fail;
       
   872 
       
   873       Size = 1 + 1 + 2;
       
   874       if ( flags & PFR_PHY_2BYTE_CHARCODE )
       
   875         Size += 1;
       
   876 
       
   877       if ( flags & PFR_PHY_PROPORTIONAL )
       
   878         Size += 2;
       
   879 
       
   880       if ( flags & PFR_PHY_ASCII_CODE )
       
   881         Size += 1;
       
   882 
       
   883       if ( flags & PFR_PHY_2BYTE_GPS_SIZE )
       
   884         Size += 1;
       
   885 
       
   886       if ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
       
   887         Size += 1;
       
   888 
       
   889       PFR_CHECK( count * Size );
       
   890 
       
   891       for ( n = 0; n < count; n++ )
       
   892       {
       
   893         PFR_Char  cur = &phy_font->chars[n];
       
   894 
       
   895 
       
   896         cur->char_code = ( flags & PFR_PHY_2BYTE_CHARCODE )
       
   897                          ? PFR_NEXT_USHORT( p )
       
   898                          : PFR_NEXT_BYTE( p );
       
   899 
       
   900         cur->advance   = ( flags & PFR_PHY_PROPORTIONAL )
       
   901                          ? PFR_NEXT_SHORT( p )
       
   902                          : (FT_Int) phy_font->standard_advance;
       
   903 
       
   904 #if 0
       
   905         cur->ascii     = ( flags & PFR_PHY_ASCII_CODE )
       
   906                          ? PFR_NEXT_BYTE( p )
       
   907                          : 0;
       
   908 #else
       
   909         if ( flags & PFR_PHY_ASCII_CODE )
       
   910           p += 1;
       
   911 #endif
       
   912         cur->gps_size  = ( flags & PFR_PHY_2BYTE_GPS_SIZE )
       
   913                          ? PFR_NEXT_USHORT( p )
       
   914                          : PFR_NEXT_BYTE( p );
       
   915 
       
   916         cur->gps_offset = ( flags & PFR_PHY_3BYTE_GPS_OFFSET )
       
   917                           ? PFR_NEXT_ULONG( p )
       
   918                           : PFR_NEXT_USHORT( p );
       
   919       }
       
   920     }
       
   921 
       
   922     /* that's it! */
       
   923 
       
   924   Fail:
       
   925     FT_FRAME_EXIT();
       
   926 
       
   927     /* save position of bitmap info */
       
   928     phy_font->bct_offset = FT_STREAM_POS();
       
   929     phy_font->cursor     = NULL;
       
   930 
       
   931   Exit:
       
   932     return error;
       
   933 
       
   934   Too_Short:
       
   935     error = PFR_Err_Invalid_Table;
       
   936     FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
       
   937     goto Fail;
       
   938   }
       
   939 
       
   940 
       
   941 /* END */