Subversion Repositories Kolibri OS

Rev

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

  1. /***************************************************************************/
  2. /*                                                                         */
  3. /*  t42parse.c                                                             */
  4. /*                                                                         */
  5. /*    Type 42 font parser (body).                                          */
  6. /*                                                                         */
  7. /*  Copyright 2002-2013 by                                                 */
  8. /*  Roberto Alameda.                                                       */
  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 "t42parse.h"
  20. #include "t42error.h"
  21. #include FT_INTERNAL_DEBUG_H
  22. #include FT_INTERNAL_STREAM_H
  23. #include FT_INTERNAL_POSTSCRIPT_AUX_H
  24.  
  25.  
  26.   /*************************************************************************/
  27.   /*                                                                       */
  28.   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
  29.   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
  30.   /* messages during execution.                                            */
  31.   /*                                                                       */
  32. #undef  FT_COMPONENT
  33. #define FT_COMPONENT  trace_t42
  34.  
  35.  
  36.   static void
  37.   t42_parse_font_matrix( T42_Face    face,
  38.                          T42_Loader  loader );
  39.   static void
  40.   t42_parse_encoding( T42_Face    face,
  41.                       T42_Loader  loader );
  42.  
  43.   static void
  44.   t42_parse_charstrings( T42_Face    face,
  45.                          T42_Loader  loader );
  46.  
  47.   static void
  48.   t42_parse_sfnts( T42_Face    face,
  49.                    T42_Loader  loader );
  50.  
  51.  
  52.   /* as Type42 fonts have no Private dict,         */
  53.   /* we set the last argument of T1_FIELD_XXX to 0 */
  54.   static const
  55.   T1_FieldRec  t42_keywords[] =
  56.   {
  57.  
  58. #undef  FT_STRUCTURE
  59. #define FT_STRUCTURE  T1_FontInfo
  60. #undef  T1CODE
  61. #define T1CODE        T1_FIELD_LOCATION_FONT_INFO
  62.  
  63.     T1_FIELD_STRING( "version",            version,             0 )
  64.     T1_FIELD_STRING( "Notice",             notice,              0 )
  65.     T1_FIELD_STRING( "FullName",           full_name,           0 )
  66.     T1_FIELD_STRING( "FamilyName",         family_name,         0 )
  67.     T1_FIELD_STRING( "Weight",             weight,              0 )
  68.     T1_FIELD_NUM   ( "ItalicAngle",        italic_angle,        0 )
  69.     T1_FIELD_BOOL  ( "isFixedPitch",       is_fixed_pitch,      0 )
  70.     T1_FIELD_NUM   ( "UnderlinePosition",  underline_position,  0 )
  71.     T1_FIELD_NUM   ( "UnderlineThickness", underline_thickness, 0 )
  72.  
  73. #undef  FT_STRUCTURE
  74. #define FT_STRUCTURE  PS_FontExtraRec
  75. #undef  T1CODE
  76. #define T1CODE        T1_FIELD_LOCATION_FONT_EXTRA
  77.  
  78.     T1_FIELD_NUM   ( "FSType",             fs_type,             0 )
  79.  
  80. #undef  FT_STRUCTURE
  81. #define FT_STRUCTURE  T1_FontRec
  82. #undef  T1CODE
  83. #define T1CODE        T1_FIELD_LOCATION_FONT_DICT
  84.  
  85.     T1_FIELD_KEY  ( "FontName",    font_name,    0 )
  86.     T1_FIELD_NUM  ( "PaintType",   paint_type,   0 )
  87.     T1_FIELD_NUM  ( "FontType",    font_type,    0 )
  88.     T1_FIELD_FIXED( "StrokeWidth", stroke_width, 0 )
  89.  
  90. #undef  FT_STRUCTURE
  91. #define FT_STRUCTURE  FT_BBox
  92. #undef  T1CODE
  93. #define T1CODE        T1_FIELD_LOCATION_BBOX
  94.  
  95.     T1_FIELD_BBOX("FontBBox", xMin, 0 )
  96.  
  97.     T1_FIELD_CALLBACK( "FontMatrix",  t42_parse_font_matrix, 0 )
  98.     T1_FIELD_CALLBACK( "Encoding",    t42_parse_encoding,    0 )
  99.     T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings, 0 )
  100.     T1_FIELD_CALLBACK( "sfnts",       t42_parse_sfnts,       0 )
  101.  
  102.     { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0, 0 }
  103.   };
  104.  
  105.  
  106. #define T1_Add_Table( p, i, o, l )  (p)->funcs.add( (p), i, o, l )
  107. #define T1_Done_Table( p )          \
  108.           do                        \
  109.           {                         \
  110.             if ( (p)->funcs.done )  \
  111.               (p)->funcs.done( p ); \
  112.           } while ( 0 )
  113. #define T1_Release_Table( p )          \
  114.           do                           \
  115.           {                            \
  116.             if ( (p)->funcs.release )  \
  117.               (p)->funcs.release( p ); \
  118.           } while ( 0 )
  119.  
  120. #define T1_Skip_Spaces( p )    (p)->root.funcs.skip_spaces( &(p)->root )
  121. #define T1_Skip_PS_Token( p )  (p)->root.funcs.skip_PS_token( &(p)->root )
  122.  
  123. #define T1_ToInt( p )                          \
  124.           (p)->root.funcs.to_int( &(p)->root )
  125. #define T1_ToBytes( p, b, m, n, d )                          \
  126.           (p)->root.funcs.to_bytes( &(p)->root, b, m, n, d )
  127.  
  128. #define T1_ToFixedArray( p, m, f, t )                           \
  129.           (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t )
  130. #define T1_ToToken( p, t )                          \
  131.           (p)->root.funcs.to_token( &(p)->root, t )
  132.  
  133. #define T1_Load_Field( p, f, o, m, pf )                         \
  134.           (p)->root.funcs.load_field( &(p)->root, f, o, m, pf )
  135. #define T1_Load_Field_Table( p, f, o, m, pf )                         \
  136.           (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf )
  137.  
  138.  
  139.   /********************* Parsing Functions ******************/
  140.  
  141.   FT_LOCAL_DEF( FT_Error )
  142.   t42_parser_init( T42_Parser     parser,
  143.                    FT_Stream      stream,
  144.                    FT_Memory      memory,
  145.                    PSAux_Service  psaux )
  146.   {
  147.     FT_Error  error = FT_Err_Ok;
  148.     FT_Long   size;
  149.  
  150.  
  151.     psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory );
  152.  
  153.     parser->stream    = stream;
  154.     parser->base_len  = 0;
  155.     parser->base_dict = 0;
  156.     parser->in_memory = 0;
  157.  
  158.     /*******************************************************************/
  159.     /*                                                                 */
  160.     /* Here a short summary of what is going on:                       */
  161.     /*                                                                 */
  162.     /*   When creating a new Type 42 parser, we try to locate and load */
  163.     /*   the base dictionary, loading the whole font into memory.      */
  164.     /*                                                                 */
  165.     /*   When `loading' the base dictionary, we only set up pointers   */
  166.     /*   in the case of a memory-based stream.  Otherwise, we allocate */
  167.     /*   and load the base dictionary in it.                           */
  168.     /*                                                                 */
  169.     /*   parser->in_memory is set if we have a memory stream.          */
  170.     /*                                                                 */
  171.  
  172.     if ( FT_STREAM_SEEK( 0L ) ||
  173.          FT_FRAME_ENTER( 17 ) )
  174.       goto Exit;
  175.  
  176.     if ( ft_memcmp( stream->cursor, "%!PS-TrueTypeFont", 17 ) != 0 )
  177.     {
  178.       FT_TRACE2(( "  not a Type42 font\n" ));
  179.       error = FT_THROW( Unknown_File_Format );
  180.     }
  181.  
  182.     FT_FRAME_EXIT();
  183.  
  184.     if ( error || FT_STREAM_SEEK( 0 ) )
  185.       goto Exit;
  186.  
  187.     size = stream->size;
  188.  
  189.     /* now, try to load `size' bytes of the `base' dictionary we */
  190.     /* found previously                                          */
  191.  
  192.     /* if it is a memory-based resource, set up pointers */
  193.     if ( !stream->read )
  194.     {
  195.       parser->base_dict = (FT_Byte*)stream->base + stream->pos;
  196.       parser->base_len  = size;
  197.       parser->in_memory = 1;
  198.  
  199.       /* check that the `size' field is valid */
  200.       if ( FT_STREAM_SKIP( size ) )
  201.         goto Exit;
  202.     }
  203.     else
  204.     {
  205.       /* read segment in memory */
  206.       if ( FT_ALLOC( parser->base_dict, size )       ||
  207.            FT_STREAM_READ( parser->base_dict, size ) )
  208.         goto Exit;
  209.  
  210.       parser->base_len = size;
  211.     }
  212.  
  213.     parser->root.base   = parser->base_dict;
  214.     parser->root.cursor = parser->base_dict;
  215.     parser->root.limit  = parser->root.cursor + parser->base_len;
  216.  
  217.   Exit:
  218.     if ( error && !parser->in_memory )
  219.       FT_FREE( parser->base_dict );
  220.  
  221.     return error;
  222.   }
  223.  
  224.  
  225.   FT_LOCAL_DEF( void )
  226.   t42_parser_done( T42_Parser  parser )
  227.   {
  228.     FT_Memory  memory = parser->root.memory;
  229.  
  230.  
  231.     /* free the base dictionary only when we have a disk stream */
  232.     if ( !parser->in_memory )
  233.       FT_FREE( parser->base_dict );
  234.  
  235.     parser->root.funcs.done( &parser->root );
  236.   }
  237.  
  238.  
  239.   static int
  240.   t42_is_space( FT_Byte  c )
  241.   {
  242.     return ( c == ' '  || c == '\t'              ||
  243.              c == '\r' || c == '\n' || c == '\f' ||
  244.              c == '\0'                           );
  245.   }
  246.  
  247.  
  248.   static void
  249.   t42_parse_font_matrix( T42_Face    face,
  250.                          T42_Loader  loader )
  251.   {
  252.     T42_Parser  parser = &loader->parser;
  253.     FT_Matrix*  matrix = &face->type1.font_matrix;
  254.     FT_Vector*  offset = &face->type1.font_offset;
  255.     FT_Face     root   = (FT_Face)&face->root;
  256.     FT_Fixed    temp[6];
  257.     FT_Fixed    temp_scale;
  258.  
  259.  
  260.     (void)T1_ToFixedArray( parser, 6, temp, 3 );
  261.  
  262.     temp_scale = FT_ABS( temp[3] );
  263.  
  264.     /* Set Units per EM based on FontMatrix values.  We set the value to */
  265.     /* 1000 / temp_scale, because temp_scale was already multiplied by   */
  266.     /* 1000 (in t1_tofixed, from psobjs.c).                              */
  267.  
  268.     root->units_per_EM = (FT_UShort)FT_DivFix( 1000, temp_scale );
  269.  
  270.     /* we need to scale the values by 1.0/temp_scale */
  271.     if ( temp_scale != 0x10000L )
  272.     {
  273.       temp[0] = FT_DivFix( temp[0], temp_scale );
  274.       temp[1] = FT_DivFix( temp[1], temp_scale );
  275.       temp[2] = FT_DivFix( temp[2], temp_scale );
  276.       temp[4] = FT_DivFix( temp[4], temp_scale );
  277.       temp[5] = FT_DivFix( temp[5], temp_scale );
  278.       temp[3] = 0x10000L;
  279.     }
  280.  
  281.     matrix->xx = temp[0];
  282.     matrix->yx = temp[1];
  283.     matrix->xy = temp[2];
  284.     matrix->yy = temp[3];
  285.  
  286.     /* note that the offsets must be expressed in integer font units */
  287.     offset->x = temp[4] >> 16;
  288.     offset->y = temp[5] >> 16;
  289.   }
  290.  
  291.  
  292.   static void
  293.   t42_parse_encoding( T42_Face    face,
  294.                       T42_Loader  loader )
  295.   {
  296.     T42_Parser  parser = &loader->parser;
  297.     FT_Byte*    cur;
  298.     FT_Byte*    limit  = parser->root.limit;
  299.  
  300.     PSAux_Service  psaux  = (PSAux_Service)face->psaux;
  301.  
  302.  
  303.     T1_Skip_Spaces( parser );
  304.     cur = parser->root.cursor;
  305.     if ( cur >= limit )
  306.     {
  307.       FT_ERROR(( "t42_parse_encoding: out of bounds\n" ));
  308.       parser->root.error = FT_THROW( Invalid_File_Format );
  309.       return;
  310.     }
  311.  
  312.     /* if we have a number or `[', the encoding is an array, */
  313.     /* and we must load it now                               */
  314.     if ( ft_isdigit( *cur ) || *cur == '[' )
  315.     {
  316.       T1_Encoding  encode          = &face->type1.encoding;
  317.       FT_UInt      count, n;
  318.       PS_Table     char_table      = &loader->encoding_table;
  319.       FT_Memory    memory          = parser->root.memory;
  320.       FT_Error     error;
  321.       FT_Bool      only_immediates = 0;
  322.  
  323.  
  324.       /* read the number of entries in the encoding; should be 256 */
  325.       if ( *cur == '[' )
  326.       {
  327.         count           = 256;
  328.         only_immediates = 1;
  329.         parser->root.cursor++;
  330.       }
  331.       else
  332.         count = (FT_UInt)T1_ToInt( parser );
  333.  
  334.       T1_Skip_Spaces( parser );
  335.       if ( parser->root.cursor >= limit )
  336.         return;
  337.  
  338.       /* we use a T1_Table to store our charnames */
  339.       loader->num_chars = encode->num_chars = count;
  340.       if ( FT_NEW_ARRAY( encode->char_index, count )     ||
  341.            FT_NEW_ARRAY( encode->char_name,  count )     ||
  342.            FT_SET_ERROR( psaux->ps_table_funcs->init(
  343.                            char_table, count, memory ) ) )
  344.       {
  345.         parser->root.error = error;
  346.         return;
  347.       }
  348.  
  349.       /* We need to `zero' out encoding_table.elements */
  350.       for ( n = 0; n < count; n++ )
  351.       {
  352.         char*  notdef = (char *)".notdef";
  353.  
  354.  
  355.         T1_Add_Table( char_table, n, notdef, 8 );
  356.       }
  357.  
  358.       /* Now we need to read records of the form                */
  359.       /*                                                        */
  360.       /*   ... charcode /charname ...                           */
  361.       /*                                                        */
  362.       /* for each entry in our table.                           */
  363.       /*                                                        */
  364.       /* We simply look for a number followed by an immediate   */
  365.       /* name.  Note that this ignores correctly the sequence   */
  366.       /* that is often seen in type42 fonts:                    */
  367.       /*                                                        */
  368.       /*   0 1 255 { 1 index exch /.notdef put } for dup        */
  369.       /*                                                        */
  370.       /* used to clean the encoding array before anything else. */
  371.       /*                                                        */
  372.       /* Alternatively, if the array is directly given as       */
  373.       /*                                                        */
  374.       /*   /Encoding [ ... ]                                    */
  375.       /*                                                        */
  376.       /* we only read immediates.                               */
  377.  
  378.       n = 0;
  379.       T1_Skip_Spaces( parser );
  380.  
  381.       while ( parser->root.cursor < limit )
  382.       {
  383.         cur = parser->root.cursor;
  384.  
  385.         /* we stop when we encounter `def' or `]' */
  386.         if ( *cur == 'd' && cur + 3 < limit )
  387.         {
  388.           if ( cur[1] == 'e'          &&
  389.                cur[2] == 'f'          &&
  390.                t42_is_space( cur[3] ) )
  391.           {
  392.             FT_TRACE6(( "encoding end\n" ));
  393.             cur += 3;
  394.             break;
  395.           }
  396.         }
  397.         if ( *cur == ']' )
  398.         {
  399.           FT_TRACE6(( "encoding end\n" ));
  400.           cur++;
  401.           break;
  402.         }
  403.  
  404.         /* check whether we have found an entry */
  405.         if ( ft_isdigit( *cur ) || only_immediates )
  406.         {
  407.           FT_Int  charcode;
  408.  
  409.  
  410.           if ( only_immediates )
  411.             charcode = n;
  412.           else
  413.           {
  414.             charcode = (FT_Int)T1_ToInt( parser );
  415.             T1_Skip_Spaces( parser );
  416.           }
  417.  
  418.           cur = parser->root.cursor;
  419.  
  420.           if ( *cur == '/' && cur + 2 < limit && n < count )
  421.           {
  422.             FT_PtrDist  len;
  423.  
  424.  
  425.             cur++;
  426.  
  427.             parser->root.cursor = cur;
  428.             T1_Skip_PS_Token( parser );
  429.             if ( parser->root.error )
  430.               return;
  431.  
  432.             len = parser->root.cursor - cur;
  433.  
  434.             parser->root.error = T1_Add_Table( char_table, charcode,
  435.                                                cur, len + 1 );
  436.             if ( parser->root.error )
  437.               return;
  438.             char_table->elements[charcode][len] = '\0';
  439.  
  440.             n++;
  441.           }
  442.         }
  443.         else
  444.         {
  445.           T1_Skip_PS_Token( parser );
  446.           if ( parser->root.error )
  447.             return;
  448.         }
  449.  
  450.         T1_Skip_Spaces( parser );
  451.       }
  452.  
  453.       face->type1.encoding_type  = T1_ENCODING_TYPE_ARRAY;
  454.       parser->root.cursor        = cur;
  455.     }
  456.  
  457.     /* Otherwise, we should have either `StandardEncoding', */
  458.     /* `ExpertEncoding', or `ISOLatin1Encoding'             */
  459.     else
  460.     {
  461.       if ( cur + 17 < limit                                            &&
  462.            ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 )
  463.         face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD;
  464.  
  465.       else if ( cur + 15 < limit                                          &&
  466.                 ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 )
  467.         face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT;
  468.  
  469.       else if ( cur + 18 < limit                                             &&
  470.                 ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 )
  471.         face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1;
  472.  
  473.       else
  474.       {
  475.         FT_ERROR(( "t42_parse_encoding: invalid token\n" ));
  476.         parser->root.error = FT_THROW( Invalid_File_Format );
  477.       }
  478.     }
  479.   }
  480.  
  481.  
  482.   typedef enum  T42_Load_Status_
  483.   {
  484.     BEFORE_START,
  485.     BEFORE_TABLE_DIR,
  486.     OTHER_TABLES
  487.  
  488.   } T42_Load_Status;
  489.  
  490.  
  491.   static void
  492.   t42_parse_sfnts( T42_Face    face,
  493.                    T42_Loader  loader )
  494.   {
  495.     T42_Parser  parser = &loader->parser;
  496.     FT_Memory   memory = parser->root.memory;
  497.     FT_Byte*    cur;
  498.     FT_Byte*    limit  = parser->root.limit;
  499.     FT_Error    error;
  500.     FT_Int      num_tables = 0;
  501.     FT_ULong    count, ttf_size = 0;
  502.  
  503.     FT_Long     n, string_size, old_string_size, real_size;
  504.     FT_Byte*    string_buf = NULL;
  505.     FT_Bool     allocated  = 0;
  506.  
  507.     T42_Load_Status  status;
  508.  
  509.  
  510.     /* The format is                                */
  511.     /*                                              */
  512.     /*   /sfnts [ <hexstring> <hexstring> ... ] def */
  513.     /*                                              */
  514.     /* or                                           */
  515.     /*                                              */
  516.     /*   /sfnts [                                   */
  517.     /*      <num_bin_bytes> RD <binary data>        */
  518.     /*      <num_bin_bytes> RD <binary data>        */
  519.     /*      ...                                     */
  520.     /*   ] def                                      */
  521.     /*                                              */
  522.     /* with exactly one space after the `RD' token. */
  523.  
  524.     T1_Skip_Spaces( parser );
  525.  
  526.     if ( parser->root.cursor >= limit || *parser->root.cursor++ != '[' )
  527.     {
  528.       FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector\n" ));
  529.       error = FT_THROW( Invalid_File_Format );
  530.       goto Fail;
  531.     }
  532.  
  533.     T1_Skip_Spaces( parser );
  534.     status          = BEFORE_START;
  535.     string_size     = 0;
  536.     old_string_size = 0;
  537.     count           = 0;
  538.  
  539.     while ( parser->root.cursor < limit )
  540.     {
  541.       cur = parser->root.cursor;
  542.  
  543.       if ( *cur == ']' )
  544.       {
  545.         parser->root.cursor++;
  546.         goto Exit;
  547.       }
  548.  
  549.       else if ( *cur == '<' )
  550.       {
  551.         T1_Skip_PS_Token( parser );
  552.         if ( parser->root.error )
  553.           goto Exit;
  554.  
  555.         /* don't include delimiters */
  556.         string_size = (FT_Long)( ( parser->root.cursor - cur - 2 + 1 ) / 2 );
  557.         if ( FT_REALLOC( string_buf, old_string_size, string_size ) )
  558.           goto Fail;
  559.  
  560.         allocated = 1;
  561.  
  562.         parser->root.cursor = cur;
  563.         (void)T1_ToBytes( parser, string_buf, string_size, &real_size, 1 );
  564.         old_string_size = string_size;
  565.         string_size = real_size;
  566.       }
  567.  
  568.       else if ( ft_isdigit( *cur ) )
  569.       {
  570.         if ( allocated )
  571.         {
  572.           FT_ERROR(( "t42_parse_sfnts: "
  573.                      "can't handle mixed binary and hex strings\n" ));
  574.           error = FT_THROW( Invalid_File_Format );
  575.           goto Fail;
  576.         }
  577.  
  578.         string_size = T1_ToInt( parser );
  579.         if ( string_size < 0 )
  580.         {
  581.           FT_ERROR(( "t42_parse_sfnts: invalid string size\n" ));
  582.           error = FT_THROW( Invalid_File_Format );
  583.           goto Fail;
  584.         }
  585.  
  586.         T1_Skip_PS_Token( parser );             /* `RD' */
  587.         if ( parser->root.error )
  588.           return;
  589.  
  590.         string_buf = parser->root.cursor + 1;   /* one space after `RD' */
  591.  
  592.         if ( limit - parser->root.cursor < string_size )
  593.         {
  594.           FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));
  595.           error = FT_THROW( Invalid_File_Format );
  596.           goto Fail;
  597.         }
  598.         else
  599.           parser->root.cursor += string_size + 1;
  600.       }
  601.  
  602.       if ( !string_buf )
  603.       {
  604.         FT_ERROR(( "t42_parse_sfnts: invalid data in sfnts array\n" ));
  605.         error = FT_THROW( Invalid_File_Format );
  606.         goto Fail;
  607.       }
  608.  
  609.       /* A string can have a trailing zero (odd) byte for padding. */
  610.       /* Ignore it.                                                */
  611.       if ( ( string_size & 1 ) && string_buf[string_size - 1] == 0 )
  612.         string_size--;
  613.  
  614.       if ( !string_size )
  615.       {
  616.         FT_ERROR(( "t42_parse_sfnts: invalid string\n" ));
  617.         error = FT_THROW( Invalid_File_Format );
  618.         goto Fail;
  619.       }
  620.  
  621.       for ( n = 0; n < string_size; n++ )
  622.       {
  623.         switch ( status )
  624.         {
  625.         case BEFORE_START:
  626.           /* load offset table, 12 bytes */
  627.           if ( count < 12 )
  628.           {
  629.             face->ttf_data[count++] = string_buf[n];
  630.             continue;
  631.           }
  632.           else
  633.           {
  634.             num_tables = 16 * face->ttf_data[4] + face->ttf_data[5];
  635.             status     = BEFORE_TABLE_DIR;
  636.             ttf_size   = 12 + 16 * num_tables;
  637.  
  638.             if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) )
  639.               goto Fail;
  640.           }
  641.           /* fall through */
  642.  
  643.         case BEFORE_TABLE_DIR:
  644.           /* the offset table is read; read the table directory */
  645.           if ( count < ttf_size )
  646.           {
  647.             face->ttf_data[count++] = string_buf[n];
  648.             continue;
  649.           }
  650.           else
  651.           {
  652.             int       i;
  653.             FT_ULong  len;
  654.  
  655.  
  656.             for ( i = 0; i < num_tables; i++ )
  657.             {
  658.               FT_Byte*  p = face->ttf_data + 12 + 16 * i + 12;
  659.  
  660.  
  661.               len = FT_PEEK_ULONG( p );
  662.  
  663.               /* Pad to a 4-byte boundary length */
  664.               ttf_size += ( len + 3 ) & ~3;
  665.             }
  666.  
  667.             status         = OTHER_TABLES;
  668.             face->ttf_size = ttf_size;
  669.  
  670.             /* there are no more than 256 tables, so no size check here */
  671.             if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables,
  672.                              ttf_size + 1 ) )
  673.               goto Fail;
  674.           }
  675.           /* fall through */
  676.  
  677.         case OTHER_TABLES:
  678.           /* all other tables are just copied */
  679.           if ( count >= ttf_size )
  680.           {
  681.             FT_ERROR(( "t42_parse_sfnts: too many binary data\n" ));
  682.             error = FT_THROW( Invalid_File_Format );
  683.             goto Fail;
  684.           }
  685.           face->ttf_data[count++] = string_buf[n];
  686.         }
  687.       }
  688.  
  689.       T1_Skip_Spaces( parser );
  690.     }
  691.  
  692.     /* if control reaches this point, the format was not valid */
  693.     error = FT_THROW( Invalid_File_Format );
  694.  
  695.   Fail:
  696.     parser->root.error = error;
  697.  
  698.   Exit:
  699.     if ( allocated )
  700.       FT_FREE( string_buf );
  701.   }
  702.  
  703.  
  704.   static void
  705.   t42_parse_charstrings( T42_Face    face,
  706.                          T42_Loader  loader )
  707.   {
  708.     T42_Parser     parser       = &loader->parser;
  709.     PS_Table       code_table   = &loader->charstrings;
  710.     PS_Table       name_table   = &loader->glyph_names;
  711.     PS_Table       swap_table   = &loader->swap_table;
  712.     FT_Memory      memory       = parser->root.memory;
  713.     FT_Error       error;
  714.  
  715.     PSAux_Service  psaux        = (PSAux_Service)face->psaux;
  716.  
  717.     FT_Byte*       cur;
  718.     FT_Byte*       limit        = parser->root.limit;
  719.     FT_UInt        n;
  720.     FT_UInt        notdef_index = 0;
  721.     FT_Byte        notdef_found = 0;
  722.  
  723.  
  724.     T1_Skip_Spaces( parser );
  725.  
  726.     if ( parser->root.cursor >= limit )
  727.     {
  728.       FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
  729.       error = FT_THROW( Invalid_File_Format );
  730.       goto Fail;
  731.     }
  732.  
  733.     if ( ft_isdigit( *parser->root.cursor ) )
  734.     {
  735.       loader->num_glyphs = (FT_UInt)T1_ToInt( parser );
  736.       if ( parser->root.error )
  737.         return;
  738.     }
  739.     else if ( *parser->root.cursor == '<' )
  740.     {
  741.       /* We have `<< ... >>'.  Count the number of `/' in the dictionary */
  742.       /* to get its size.                                                */
  743.       FT_UInt  count = 0;
  744.  
  745.  
  746.       T1_Skip_PS_Token( parser );
  747.       if ( parser->root.error )
  748.         return;
  749.       T1_Skip_Spaces( parser );
  750.       cur = parser->root.cursor;
  751.  
  752.       while ( parser->root.cursor < limit )
  753.       {
  754.         if ( *parser->root.cursor == '/' )
  755.           count++;
  756.         else if ( *parser->root.cursor == '>' )
  757.         {
  758.           loader->num_glyphs  = count;
  759.           parser->root.cursor = cur;        /* rewind */
  760.           break;
  761.         }
  762.         T1_Skip_PS_Token( parser );
  763.         if ( parser->root.error )
  764.           return;
  765.         T1_Skip_Spaces( parser );
  766.       }
  767.     }
  768.     else
  769.     {
  770.       FT_ERROR(( "t42_parse_charstrings: invalid token\n" ));
  771.       error = FT_THROW( Invalid_File_Format );
  772.       goto Fail;
  773.     }
  774.  
  775.     if ( parser->root.cursor >= limit )
  776.     {
  777.       FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
  778.       error = FT_THROW( Invalid_File_Format );
  779.       goto Fail;
  780.     }
  781.  
  782.     /* initialize tables */
  783.  
  784.     error = psaux->ps_table_funcs->init( code_table,
  785.                                          loader->num_glyphs,
  786.                                          memory );
  787.     if ( error )
  788.       goto Fail;
  789.  
  790.     error = psaux->ps_table_funcs->init( name_table,
  791.                                          loader->num_glyphs,
  792.                                          memory );
  793.     if ( error )
  794.       goto Fail;
  795.  
  796.     /* Initialize table for swapping index notdef_index and */
  797.     /* index 0 names and codes (if necessary).              */
  798.  
  799.     error = psaux->ps_table_funcs->init( swap_table, 4, memory );
  800.     if ( error )
  801.       goto Fail;
  802.  
  803.     n = 0;
  804.  
  805.     for (;;)
  806.     {
  807.       /* The format is simple:                   */
  808.       /*   `/glyphname' + index [+ def]          */
  809.  
  810.       T1_Skip_Spaces( parser );
  811.  
  812.       cur = parser->root.cursor;
  813.       if ( cur >= limit )
  814.         break;
  815.  
  816.       /* We stop when we find an `end' keyword or '>' */
  817.       if ( *cur   == 'e'          &&
  818.            cur + 3 < limit        &&
  819.            cur[1] == 'n'          &&
  820.            cur[2] == 'd'          &&
  821.            t42_is_space( cur[3] ) )
  822.         break;
  823.       if ( *cur == '>' )
  824.         break;
  825.  
  826.       T1_Skip_PS_Token( parser );
  827.       if ( parser->root.error )
  828.         return;
  829.  
  830.       if ( *cur == '/' )
  831.       {
  832.         FT_PtrDist  len;
  833.  
  834.  
  835.         if ( cur + 1 >= limit )
  836.         {
  837.           FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
  838.           error = FT_THROW( Invalid_File_Format );
  839.           goto Fail;
  840.         }
  841.  
  842.         cur++;                              /* skip `/' */
  843.         len = parser->root.cursor - cur;
  844.  
  845.         error = T1_Add_Table( name_table, n, cur, len + 1 );
  846.         if ( error )
  847.           goto Fail;
  848.  
  849.         /* add a trailing zero to the name table */
  850.         name_table->elements[n][len] = '\0';
  851.  
  852.         /* record index of /.notdef */
  853.         if ( *cur == '.'                                              &&
  854.              ft_strcmp( ".notdef",
  855.                         (const char*)(name_table->elements[n]) ) == 0 )
  856.         {
  857.           notdef_index = n;
  858.           notdef_found = 1;
  859.         }
  860.  
  861.         T1_Skip_Spaces( parser );
  862.  
  863.         cur = parser->root.cursor;
  864.  
  865.         (void)T1_ToInt( parser );
  866.         if ( parser->root.cursor >= limit )
  867.         {
  868.           FT_ERROR(( "t42_parse_charstrings: out of bounds\n" ));
  869.           error = FT_THROW( Invalid_File_Format );
  870.           goto Fail;
  871.         }
  872.  
  873.         len = parser->root.cursor - cur;
  874.  
  875.         error = T1_Add_Table( code_table, n, cur, len + 1 );
  876.         if ( error )
  877.           goto Fail;
  878.  
  879.         code_table->elements[n][len] = '\0';
  880.  
  881.         n++;
  882.         if ( n >= loader->num_glyphs )
  883.           break;
  884.       }
  885.     }
  886.  
  887.     loader->num_glyphs = n;
  888.  
  889.     if ( !notdef_found )
  890.     {
  891.       FT_ERROR(( "t42_parse_charstrings: no /.notdef glyph\n" ));
  892.       error = FT_THROW( Invalid_File_Format );
  893.       goto Fail;
  894.     }
  895.  
  896.     /* if /.notdef does not occupy index 0, do our magic. */
  897.     if ( ft_strcmp( (const char*)".notdef",
  898.                     (const char*)name_table->elements[0] ) )
  899.     {
  900.       /* Swap glyph in index 0 with /.notdef glyph.  First, add index 0  */
  901.       /* name and code entries to swap_table.  Then place notdef_index   */
  902.       /* name and code entries into swap_table.  Then swap name and code */
  903.       /* entries at indices notdef_index and 0 using values stored in    */
  904.       /* swap_table.                                                     */
  905.  
  906.       /* Index 0 name */
  907.       error = T1_Add_Table( swap_table, 0,
  908.                             name_table->elements[0],
  909.                             name_table->lengths [0] );
  910.       if ( error )
  911.         goto Fail;
  912.  
  913.       /* Index 0 code */
  914.       error = T1_Add_Table( swap_table, 1,
  915.                             code_table->elements[0],
  916.                             code_table->lengths [0] );
  917.       if ( error )
  918.         goto Fail;
  919.  
  920.       /* Index notdef_index name */
  921.       error = T1_Add_Table( swap_table, 2,
  922.                             name_table->elements[notdef_index],
  923.                             name_table->lengths [notdef_index] );
  924.       if ( error )
  925.         goto Fail;
  926.  
  927.       /* Index notdef_index code */
  928.       error = T1_Add_Table( swap_table, 3,
  929.                             code_table->elements[notdef_index],
  930.                             code_table->lengths [notdef_index] );
  931.       if ( error )
  932.         goto Fail;
  933.  
  934.       error = T1_Add_Table( name_table, notdef_index,
  935.                             swap_table->elements[0],
  936.                             swap_table->lengths [0] );
  937.       if ( error )
  938.         goto Fail;
  939.  
  940.       error = T1_Add_Table( code_table, notdef_index,
  941.                             swap_table->elements[1],
  942.                             swap_table->lengths [1] );
  943.       if ( error )
  944.         goto Fail;
  945.  
  946.       error = T1_Add_Table( name_table, 0,
  947.                             swap_table->elements[2],
  948.                             swap_table->lengths [2] );
  949.       if ( error )
  950.         goto Fail;
  951.  
  952.       error = T1_Add_Table( code_table, 0,
  953.                             swap_table->elements[3],
  954.                             swap_table->lengths [3] );
  955.       if ( error )
  956.         goto Fail;
  957.  
  958.     }
  959.  
  960.     return;
  961.  
  962.   Fail:
  963.     parser->root.error = error;
  964.   }
  965.  
  966.  
  967.   static FT_Error
  968.   t42_load_keyword( T42_Face    face,
  969.                     T42_Loader  loader,
  970.                     T1_Field    field )
  971.   {
  972.     FT_Error  error;
  973.     void*     dummy_object;
  974.     void**    objects;
  975.     FT_UInt   max_objects = 0;
  976.  
  977.  
  978.     /* if the keyword has a dedicated callback, call it */
  979.     if ( field->type == T1_FIELD_TYPE_CALLBACK )
  980.     {
  981.       field->reader( (FT_Face)face, loader );
  982.       error = loader->parser.root.error;
  983.       goto Exit;
  984.     }
  985.  
  986.     /* now the keyword is either a simple field or a table of fields; */
  987.     /* we are now going to take care of it                            */
  988.  
  989.     switch ( field->location )
  990.     {
  991.     case T1_FIELD_LOCATION_FONT_INFO:
  992.       dummy_object = &face->type1.font_info;
  993.       break;
  994.  
  995.     case T1_FIELD_LOCATION_FONT_EXTRA:
  996.       dummy_object = &face->type1.font_extra;
  997.       break;
  998.  
  999.     case T1_FIELD_LOCATION_BBOX:
  1000.       dummy_object = &face->type1.font_bbox;
  1001.       break;
  1002.  
  1003.     default:
  1004.       dummy_object = &face->type1;
  1005.     }
  1006.  
  1007.     objects = &dummy_object;
  1008.  
  1009.     if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY ||
  1010.          field->type == T1_FIELD_TYPE_FIXED_ARRAY   )
  1011.       error = T1_Load_Field_Table( &loader->parser, field,
  1012.                                    objects, max_objects, 0 );
  1013.     else
  1014.       error = T1_Load_Field( &loader->parser, field,
  1015.                              objects, max_objects, 0 );
  1016.  
  1017.    Exit:
  1018.     return error;
  1019.   }
  1020.  
  1021.  
  1022.   FT_LOCAL_DEF( FT_Error )
  1023.   t42_parse_dict( T42_Face    face,
  1024.                   T42_Loader  loader,
  1025.                   FT_Byte*    base,
  1026.                   FT_Long     size )
  1027.   {
  1028.     T42_Parser  parser     = &loader->parser;
  1029.     FT_Byte*    limit;
  1030.     FT_Int      n_keywords = (FT_Int)( sizeof ( t42_keywords ) /
  1031.                                          sizeof ( t42_keywords[0] ) );
  1032.  
  1033.  
  1034.     parser->root.cursor = base;
  1035.     parser->root.limit  = base + size;
  1036.     parser->root.error  = FT_Err_Ok;
  1037.  
  1038.     limit = parser->root.limit;
  1039.  
  1040.     T1_Skip_Spaces( parser );
  1041.  
  1042.     while ( parser->root.cursor < limit )
  1043.     {
  1044.       FT_Byte*  cur;
  1045.  
  1046.  
  1047.       cur = parser->root.cursor;
  1048.  
  1049.       /* look for `FontDirectory' which causes problems for some fonts */
  1050.       if ( *cur == 'F' && cur + 25 < limit                    &&
  1051.            ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 )
  1052.       {
  1053.         FT_Byte*  cur2;
  1054.  
  1055.  
  1056.         /* skip the `FontDirectory' keyword */
  1057.         T1_Skip_PS_Token( parser );
  1058.         T1_Skip_Spaces  ( parser );
  1059.         cur = cur2 = parser->root.cursor;
  1060.  
  1061.         /* look up the `known' keyword */
  1062.         while ( cur < limit )
  1063.         {
  1064.           if ( *cur == 'k' && cur + 5 < limit             &&
  1065.                 ft_strncmp( (char*)cur, "known", 5 ) == 0 )
  1066.             break;
  1067.  
  1068.           T1_Skip_PS_Token( parser );
  1069.           if ( parser->root.error )
  1070.             goto Exit;
  1071.           T1_Skip_Spaces  ( parser );
  1072.           cur = parser->root.cursor;
  1073.         }
  1074.  
  1075.         if ( cur < limit )
  1076.         {
  1077.           T1_TokenRec  token;
  1078.  
  1079.  
  1080.           /* skip the `known' keyword and the token following it */
  1081.           T1_Skip_PS_Token( parser );
  1082.           T1_ToToken( parser, &token );
  1083.  
  1084.           /* if the last token was an array, skip it! */
  1085.           if ( token.type == T1_TOKEN_TYPE_ARRAY )
  1086.             cur2 = parser->root.cursor;
  1087.         }
  1088.         parser->root.cursor = cur2;
  1089.       }
  1090.  
  1091.       /* look for immediates */
  1092.       else if ( *cur == '/' && cur + 2 < limit )
  1093.       {
  1094.         FT_PtrDist  len;
  1095.  
  1096.  
  1097.         cur++;
  1098.  
  1099.         parser->root.cursor = cur;
  1100.         T1_Skip_PS_Token( parser );
  1101.         if ( parser->root.error )
  1102.           goto Exit;
  1103.  
  1104.         len = parser->root.cursor - cur;
  1105.  
  1106.         if ( len > 0 && len < 22 && parser->root.cursor < limit )
  1107.         {
  1108.           int  i;
  1109.  
  1110.  
  1111.           /* now compare the immediate name to the keyword table */
  1112.  
  1113.           /* loop through all known keywords */
  1114.           for ( i = 0; i < n_keywords; i++ )
  1115.           {
  1116.             T1_Field  keyword = (T1_Field)&t42_keywords[i];
  1117.             FT_Byte   *name   = (FT_Byte*)keyword->ident;
  1118.  
  1119.  
  1120.             if ( !name )
  1121.               continue;
  1122.  
  1123.             if ( cur[0] == name[0]                                  &&
  1124.                  len == (FT_PtrDist)ft_strlen( (const char *)name ) &&
  1125.                  ft_memcmp( cur, name, len ) == 0                   )
  1126.             {
  1127.               /* we found it -- run the parsing callback! */
  1128.               parser->root.error = t42_load_keyword( face,
  1129.                                                      loader,
  1130.                                                      keyword );
  1131.               if ( parser->root.error )
  1132.                 return parser->root.error;
  1133.               break;
  1134.             }
  1135.           }
  1136.         }
  1137.       }
  1138.       else
  1139.       {
  1140.         T1_Skip_PS_Token( parser );
  1141.         if ( parser->root.error )
  1142.           goto Exit;
  1143.       }
  1144.  
  1145.       T1_Skip_Spaces( parser );
  1146.     }
  1147.  
  1148.   Exit:
  1149.     return parser->root.error;
  1150.   }
  1151.  
  1152.  
  1153.   FT_LOCAL_DEF( void )
  1154.   t42_loader_init( T42_Loader  loader,
  1155.                    T42_Face    face )
  1156.   {
  1157.     FT_UNUSED( face );
  1158.  
  1159.     FT_MEM_ZERO( loader, sizeof ( *loader ) );
  1160.     loader->num_glyphs = 0;
  1161.     loader->num_chars  = 0;
  1162.  
  1163.     /* initialize the tables -- simply set their `init' field to 0 */
  1164.     loader->encoding_table.init = 0;
  1165.     loader->charstrings.init    = 0;
  1166.     loader->glyph_names.init    = 0;
  1167.   }
  1168.  
  1169.  
  1170.   FT_LOCAL_DEF( void )
  1171.   t42_loader_done( T42_Loader  loader )
  1172.   {
  1173.     T42_Parser  parser = &loader->parser;
  1174.  
  1175.  
  1176.     /* finalize tables */
  1177.     T1_Release_Table( &loader->encoding_table );
  1178.     T1_Release_Table( &loader->charstrings );
  1179.     T1_Release_Table( &loader->glyph_names );
  1180.     T1_Release_Table( &loader->swap_table );
  1181.  
  1182.     /* finalize parser */
  1183.     t42_parser_done( parser );
  1184.   }
  1185.  
  1186.  
  1187. /* END */
  1188.