Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  pfrload.c                                                              */
  4. /*                                                                         */
  5. /*    FreeType PFR loader (body).                                          */
  6. /*                                                                         */
  7. /*  Copyright 2002-2005, 2007, 2009, 2010, 2013 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 = FT_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 = FT_THROW( 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 FT_THROW( 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 = FT_THROW( 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 = FT_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 = FT_THROW( 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  = FT_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  = NULL;
  480.     FT_Error   error  = FT_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 = FT_THROW( 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  = FT_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 = FT_THROW( 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  = FT_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 = FT_THROW( Invalid_Table );
  936.     FT_ERROR(( "pfr_phy_font_load: invalid physical font table\n" ));
  937.     goto Fail;
  938.   }
  939.  
  940.  
  941. /* END */
  942.