1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* t42parse.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* Type 42 font parser (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 2002 by Roberto Alameda. */ 8*37da2899SCharles.Forsyth /* */ 9*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 10*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 11*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 12*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 13*37da2899SCharles.Forsyth /* understand and accept it fully. */ 14*37da2899SCharles.Forsyth /* */ 15*37da2899SCharles.Forsyth /***************************************************************************/ 16*37da2899SCharles.Forsyth 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth #include "t42parse.h" 19*37da2899SCharles.Forsyth #include "t42error.h" 20*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 21*37da2899SCharles.Forsyth #include FT_INTERNAL_STREAM_H 22*37da2899SCharles.Forsyth #include FT_LIST_H 23*37da2899SCharles.Forsyth #include FT_INTERNAL_POSTSCRIPT_AUX_H 24*37da2899SCharles.Forsyth 25*37da2899SCharles.Forsyth 26*37da2899SCharles.Forsyth /*************************************************************************/ 27*37da2899SCharles.Forsyth /* */ 28*37da2899SCharles.Forsyth /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 29*37da2899SCharles.Forsyth /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 30*37da2899SCharles.Forsyth /* messages during execution. */ 31*37da2899SCharles.Forsyth /* */ 32*37da2899SCharles.Forsyth #undef FT_COMPONENT 33*37da2899SCharles.Forsyth #define FT_COMPONENT trace_t42 34*37da2899SCharles.Forsyth 35*37da2899SCharles.Forsyth 36*37da2899SCharles.Forsyth static void 37*37da2899SCharles.Forsyth t42_parse_font_name( T42_Face face, 38*37da2899SCharles.Forsyth T42_Loader loader ); 39*37da2899SCharles.Forsyth 40*37da2899SCharles.Forsyth static void 41*37da2899SCharles.Forsyth t42_parse_font_bbox( T42_Face face, 42*37da2899SCharles.Forsyth T42_Loader loader ); 43*37da2899SCharles.Forsyth 44*37da2899SCharles.Forsyth static void 45*37da2899SCharles.Forsyth t42_parse_font_matrix( T42_Face face, 46*37da2899SCharles.Forsyth T42_Loader loader ); 47*37da2899SCharles.Forsyth static void 48*37da2899SCharles.Forsyth t42_parse_encoding( T42_Face face, 49*37da2899SCharles.Forsyth T42_Loader loader ); 50*37da2899SCharles.Forsyth 51*37da2899SCharles.Forsyth static void 52*37da2899SCharles.Forsyth t42_parse_charstrings( T42_Face face, 53*37da2899SCharles.Forsyth T42_Loader loader ); 54*37da2899SCharles.Forsyth 55*37da2899SCharles.Forsyth static void 56*37da2899SCharles.Forsyth t42_parse_sfnts( T42_Face face, 57*37da2899SCharles.Forsyth T42_Loader loader ); 58*37da2899SCharles.Forsyth 59*37da2899SCharles.Forsyth 60*37da2899SCharles.Forsyth static const 61*37da2899SCharles.Forsyth T1_FieldRec t42_keywords[] = { 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsyth #undef FT_STRUCTURE 64*37da2899SCharles.Forsyth #define FT_STRUCTURE T1_FontInfo 65*37da2899SCharles.Forsyth #undef T1CODE 66*37da2899SCharles.Forsyth #define T1CODE T1_FIELD_LOCATION_FONT_INFO 67*37da2899SCharles.Forsyth 68*37da2899SCharles.Forsyth T1_FIELD_STRING ( "version", version ) 69*37da2899SCharles.Forsyth T1_FIELD_STRING ( "Notice", notice ) 70*37da2899SCharles.Forsyth T1_FIELD_STRING ( "FullName", full_name ) 71*37da2899SCharles.Forsyth T1_FIELD_STRING ( "FamilyName", family_name ) 72*37da2899SCharles.Forsyth T1_FIELD_STRING ( "Weight", weight ) 73*37da2899SCharles.Forsyth T1_FIELD_NUM ( "ItalicAngle", italic_angle ) 74*37da2899SCharles.Forsyth T1_FIELD_TYPE_BOOL( "isFixedPitch", is_fixed_pitch ) 75*37da2899SCharles.Forsyth T1_FIELD_NUM ( "UnderlinePosition", underline_position ) 76*37da2899SCharles.Forsyth T1_FIELD_NUM ( "UnderlineThickness", underline_thickness ) 77*37da2899SCharles.Forsyth 78*37da2899SCharles.Forsyth #undef FT_STRUCTURE 79*37da2899SCharles.Forsyth #define FT_STRUCTURE T1_FontRec 80*37da2899SCharles.Forsyth #undef T1CODE 81*37da2899SCharles.Forsyth #define T1CODE T1_FIELD_LOCATION_FONT_DICT 82*37da2899SCharles.Forsyth 83*37da2899SCharles.Forsyth T1_FIELD_NUM( "PaintType", paint_type ) 84*37da2899SCharles.Forsyth T1_FIELD_NUM( "FontType", font_type ) 85*37da2899SCharles.Forsyth T1_FIELD_NUM( "StrokeWidth", stroke_width ) 86*37da2899SCharles.Forsyth 87*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "FontName", t42_parse_font_name ) 88*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "FontBBox", t42_parse_font_bbox ) 89*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "FontMatrix", t42_parse_font_matrix ) 90*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "Encoding", t42_parse_encoding ) 91*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "CharStrings", t42_parse_charstrings ) 92*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "sfnts", t42_parse_sfnts ) 93*37da2899SCharles.Forsyth 94*37da2899SCharles.Forsyth { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 } 95*37da2899SCharles.Forsyth }; 96*37da2899SCharles.Forsyth 97*37da2899SCharles.Forsyth 98*37da2899SCharles.Forsyth #define T1_Add_Table( p, i, o, l ) (p)->funcs.add( (p), i, o, l ) 99*37da2899SCharles.Forsyth #define T1_Done_Table( p ) \ 100*37da2899SCharles.Forsyth do \ 101*37da2899SCharles.Forsyth { \ 102*37da2899SCharles.Forsyth if ( (p)->funcs.done ) \ 103*37da2899SCharles.Forsyth (p)->funcs.done( p ); \ 104*37da2899SCharles.Forsyth } while ( 0 ) 105*37da2899SCharles.Forsyth #define T1_Release_Table( p ) \ 106*37da2899SCharles.Forsyth do \ 107*37da2899SCharles.Forsyth { \ 108*37da2899SCharles.Forsyth if ( (p)->funcs.release ) \ 109*37da2899SCharles.Forsyth (p)->funcs.release( p ); \ 110*37da2899SCharles.Forsyth } while ( 0 ) 111*37da2899SCharles.Forsyth 112*37da2899SCharles.Forsyth #define T1_Skip_Spaces( p ) (p)->root.funcs.skip_spaces( &(p)->root ) 113*37da2899SCharles.Forsyth #define T1_Skip_Alpha( p ) (p)->root.funcs.skip_alpha ( &(p)->root ) 114*37da2899SCharles.Forsyth 115*37da2899SCharles.Forsyth #define T1_ToInt( p ) (p)->root.funcs.to_int( &(p)->root ) 116*37da2899SCharles.Forsyth #define T1_ToFixed( p, t ) (p)->root.funcs.to_fixed( &(p)->root, t ) 117*37da2899SCharles.Forsyth 118*37da2899SCharles.Forsyth #define T1_ToCoordArray( p, m, c ) \ 119*37da2899SCharles.Forsyth (p)->root.funcs.to_coord_array( &(p)->root, m, c ) 120*37da2899SCharles.Forsyth #define T1_ToFixedArray( p, m, f, t ) \ 121*37da2899SCharles.Forsyth (p)->root.funcs.to_fixed_array( &(p)->root, m, f, t ) 122*37da2899SCharles.Forsyth #define T1_ToToken( p, t ) \ 123*37da2899SCharles.Forsyth (p)->root.funcs.to_token( &(p)->root, t ) 124*37da2899SCharles.Forsyth #define T1_ToTokenArray( p, t, m, c ) \ 125*37da2899SCharles.Forsyth (p)->root.funcs.to_token_array( &(p)->root, t, m, c ) 126*37da2899SCharles.Forsyth 127*37da2899SCharles.Forsyth #define T1_Load_Field( p, f, o, m, pf ) \ 128*37da2899SCharles.Forsyth (p)->root.funcs.load_field( &(p)->root, f, o, m, pf ) 129*37da2899SCharles.Forsyth #define T1_Load_Field_Table( p, f, o, m, pf ) \ 130*37da2899SCharles.Forsyth (p)->root.funcs.load_field_table( &(p)->root, f, o, m, pf ) 131*37da2899SCharles.Forsyth 132*37da2899SCharles.Forsyth 133*37da2899SCharles.Forsyth /********************* Parsing Functions ******************/ 134*37da2899SCharles.Forsyth 135*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) t42_parser_init(T42_Parser parser,FT_Stream stream,FT_Memory memory,PSAux_Service psaux)136*37da2899SCharles.Forsyth t42_parser_init( T42_Parser parser, 137*37da2899SCharles.Forsyth FT_Stream stream, 138*37da2899SCharles.Forsyth FT_Memory memory, 139*37da2899SCharles.Forsyth PSAux_Service psaux ) 140*37da2899SCharles.Forsyth { 141*37da2899SCharles.Forsyth FT_Error error = T42_Err_Ok; 142*37da2899SCharles.Forsyth FT_Long size; 143*37da2899SCharles.Forsyth 144*37da2899SCharles.Forsyth 145*37da2899SCharles.Forsyth psaux->ps_parser_funcs->init( &parser->root, 0, 0, memory ); 146*37da2899SCharles.Forsyth 147*37da2899SCharles.Forsyth parser->stream = stream; 148*37da2899SCharles.Forsyth parser->base_len = 0; 149*37da2899SCharles.Forsyth parser->base_dict = 0; 150*37da2899SCharles.Forsyth parser->in_memory = 0; 151*37da2899SCharles.Forsyth 152*37da2899SCharles.Forsyth /*******************************************************************/ 153*37da2899SCharles.Forsyth /* */ 154*37da2899SCharles.Forsyth /* Here a short summary of what is going on: */ 155*37da2899SCharles.Forsyth /* */ 156*37da2899SCharles.Forsyth /* When creating a new Type 42 parser, we try to locate and load */ 157*37da2899SCharles.Forsyth /* the base dictionary, loading the whole font into memory. */ 158*37da2899SCharles.Forsyth /* */ 159*37da2899SCharles.Forsyth /* When `loading' the base dictionary, we only setup pointers in */ 160*37da2899SCharles.Forsyth /* the case of a memory-based stream. Otherwise, we allocate */ 161*37da2899SCharles.Forsyth /* and load the base dictionary in it. */ 162*37da2899SCharles.Forsyth /* */ 163*37da2899SCharles.Forsyth /* parser->in_memory is set if we have a memory stream. */ 164*37da2899SCharles.Forsyth /* */ 165*37da2899SCharles.Forsyth 166*37da2899SCharles.Forsyth if ( FT_STREAM_SEEK( 0L ) ) 167*37da2899SCharles.Forsyth goto Exit; 168*37da2899SCharles.Forsyth 169*37da2899SCharles.Forsyth size = stream->size; 170*37da2899SCharles.Forsyth 171*37da2899SCharles.Forsyth /* now, try to load `size' bytes of the `base' dictionary we */ 172*37da2899SCharles.Forsyth /* found previously */ 173*37da2899SCharles.Forsyth 174*37da2899SCharles.Forsyth /* if it is a memory-based resource, set up pointers */ 175*37da2899SCharles.Forsyth if ( !stream->read ) 176*37da2899SCharles.Forsyth { 177*37da2899SCharles.Forsyth parser->base_dict = (FT_Byte*)stream->base + stream->pos; 178*37da2899SCharles.Forsyth parser->base_len = size; 179*37da2899SCharles.Forsyth parser->in_memory = 1; 180*37da2899SCharles.Forsyth 181*37da2899SCharles.Forsyth /* check that the `size' field is valid */ 182*37da2899SCharles.Forsyth if ( FT_STREAM_SKIP( size ) ) 183*37da2899SCharles.Forsyth goto Exit; 184*37da2899SCharles.Forsyth } 185*37da2899SCharles.Forsyth else 186*37da2899SCharles.Forsyth { 187*37da2899SCharles.Forsyth /* read segment in memory */ 188*37da2899SCharles.Forsyth if ( FT_ALLOC( parser->base_dict, size ) || 189*37da2899SCharles.Forsyth FT_STREAM_READ( parser->base_dict, size ) ) 190*37da2899SCharles.Forsyth goto Exit; 191*37da2899SCharles.Forsyth 192*37da2899SCharles.Forsyth parser->base_len = size; 193*37da2899SCharles.Forsyth } 194*37da2899SCharles.Forsyth 195*37da2899SCharles.Forsyth /* Now check font format; we must see `%!PS-TrueTypeFont' */ 196*37da2899SCharles.Forsyth if (size <= 17 || 197*37da2899SCharles.Forsyth ( ft_strncmp( (const char*)parser->base_dict, 198*37da2899SCharles.Forsyth "%!PS-TrueTypeFont", 17) ) ) 199*37da2899SCharles.Forsyth error = T42_Err_Unknown_File_Format; 200*37da2899SCharles.Forsyth else 201*37da2899SCharles.Forsyth { 202*37da2899SCharles.Forsyth parser->root.base = parser->base_dict; 203*37da2899SCharles.Forsyth parser->root.cursor = parser->base_dict; 204*37da2899SCharles.Forsyth parser->root.limit = parser->root.cursor + parser->base_len; 205*37da2899SCharles.Forsyth } 206*37da2899SCharles.Forsyth 207*37da2899SCharles.Forsyth Exit: 208*37da2899SCharles.Forsyth if ( error && !parser->in_memory ) 209*37da2899SCharles.Forsyth FT_FREE( parser->base_dict ); 210*37da2899SCharles.Forsyth 211*37da2899SCharles.Forsyth return error; 212*37da2899SCharles.Forsyth } 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth 215*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) t42_parser_done(T42_Parser parser)216*37da2899SCharles.Forsyth t42_parser_done( T42_Parser parser ) 217*37da2899SCharles.Forsyth { 218*37da2899SCharles.Forsyth FT_Memory memory = parser->root.memory; 219*37da2899SCharles.Forsyth 220*37da2899SCharles.Forsyth 221*37da2899SCharles.Forsyth /* free the base dictionary only when we have a disk stream */ 222*37da2899SCharles.Forsyth if ( !parser->in_memory ) 223*37da2899SCharles.Forsyth FT_FREE( parser->base_dict ); 224*37da2899SCharles.Forsyth 225*37da2899SCharles.Forsyth parser->root.funcs.done( &parser->root ); 226*37da2899SCharles.Forsyth } 227*37da2899SCharles.Forsyth 228*37da2899SCharles.Forsyth 229*37da2899SCharles.Forsyth static int t42_is_alpha(FT_Byte c)230*37da2899SCharles.Forsyth t42_is_alpha( FT_Byte c ) 231*37da2899SCharles.Forsyth { 232*37da2899SCharles.Forsyth /* Note: we must accept "+" as a valid character, as it is used in */ 233*37da2899SCharles.Forsyth /* embedded type1 fonts in PDF documents. */ 234*37da2899SCharles.Forsyth /* */ 235*37da2899SCharles.Forsyth return ( ft_isalnum( c ) || 236*37da2899SCharles.Forsyth c == '.' || 237*37da2899SCharles.Forsyth c == '_' || 238*37da2899SCharles.Forsyth c == '-' || 239*37da2899SCharles.Forsyth c == '+' ); 240*37da2899SCharles.Forsyth } 241*37da2899SCharles.Forsyth 242*37da2899SCharles.Forsyth 243*37da2899SCharles.Forsyth static int t42_is_space(FT_Byte c)244*37da2899SCharles.Forsyth t42_is_space( FT_Byte c ) 245*37da2899SCharles.Forsyth { 246*37da2899SCharles.Forsyth return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ); 247*37da2899SCharles.Forsyth } 248*37da2899SCharles.Forsyth 249*37da2899SCharles.Forsyth 250*37da2899SCharles.Forsyth static void t42_parse_font_name(T42_Face face,T42_Loader loader)251*37da2899SCharles.Forsyth t42_parse_font_name( T42_Face face, 252*37da2899SCharles.Forsyth T42_Loader loader ) 253*37da2899SCharles.Forsyth { 254*37da2899SCharles.Forsyth T42_Parser parser = &loader->parser; 255*37da2899SCharles.Forsyth FT_Error error; 256*37da2899SCharles.Forsyth FT_Memory memory = parser->root.memory; 257*37da2899SCharles.Forsyth FT_Int len; 258*37da2899SCharles.Forsyth FT_Byte* cur; 259*37da2899SCharles.Forsyth FT_Byte* cur2; 260*37da2899SCharles.Forsyth FT_Byte* limit; 261*37da2899SCharles.Forsyth 262*37da2899SCharles.Forsyth 263*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 264*37da2899SCharles.Forsyth 265*37da2899SCharles.Forsyth cur = parser->root.cursor; 266*37da2899SCharles.Forsyth limit = parser->root.limit; 267*37da2899SCharles.Forsyth 268*37da2899SCharles.Forsyth if ( cur >= limit - 1 || 269*37da2899SCharles.Forsyth ( *cur != '/' && *cur != '(') ) 270*37da2899SCharles.Forsyth return; 271*37da2899SCharles.Forsyth 272*37da2899SCharles.Forsyth cur++; 273*37da2899SCharles.Forsyth cur2 = cur; 274*37da2899SCharles.Forsyth while ( cur2 < limit && t42_is_alpha( *cur2 ) ) 275*37da2899SCharles.Forsyth cur2++; 276*37da2899SCharles.Forsyth 277*37da2899SCharles.Forsyth len = (FT_Int)( cur2 - cur ); 278*37da2899SCharles.Forsyth if ( len > 0 ) 279*37da2899SCharles.Forsyth { 280*37da2899SCharles.Forsyth if ( FT_ALLOC( face->type1.font_name, len + 1 ) ) 281*37da2899SCharles.Forsyth { 282*37da2899SCharles.Forsyth parser->root.error = error; 283*37da2899SCharles.Forsyth return; 284*37da2899SCharles.Forsyth } 285*37da2899SCharles.Forsyth 286*37da2899SCharles.Forsyth FT_MEM_COPY( face->type1.font_name, cur, len ); 287*37da2899SCharles.Forsyth face->type1.font_name[len] = '\0'; 288*37da2899SCharles.Forsyth } 289*37da2899SCharles.Forsyth parser->root.cursor = cur2; 290*37da2899SCharles.Forsyth } 291*37da2899SCharles.Forsyth 292*37da2899SCharles.Forsyth 293*37da2899SCharles.Forsyth static void t42_parse_font_bbox(T42_Face face,T42_Loader loader)294*37da2899SCharles.Forsyth t42_parse_font_bbox( T42_Face face, 295*37da2899SCharles.Forsyth T42_Loader loader ) 296*37da2899SCharles.Forsyth { 297*37da2899SCharles.Forsyth T42_Parser parser = &loader->parser; 298*37da2899SCharles.Forsyth FT_BBox* bbox = &face->type1.font_bbox; 299*37da2899SCharles.Forsyth 300*37da2899SCharles.Forsyth bbox->xMin = T1_ToInt( parser ); 301*37da2899SCharles.Forsyth bbox->yMin = T1_ToInt( parser ); 302*37da2899SCharles.Forsyth bbox->xMax = T1_ToInt( parser ); 303*37da2899SCharles.Forsyth bbox->yMax = T1_ToInt( parser ); 304*37da2899SCharles.Forsyth } 305*37da2899SCharles.Forsyth 306*37da2899SCharles.Forsyth 307*37da2899SCharles.Forsyth static void t42_parse_font_matrix(T42_Face face,T42_Loader loader)308*37da2899SCharles.Forsyth t42_parse_font_matrix( T42_Face face, 309*37da2899SCharles.Forsyth T42_Loader loader ) 310*37da2899SCharles.Forsyth { 311*37da2899SCharles.Forsyth T42_Parser parser = &loader->parser; 312*37da2899SCharles.Forsyth FT_Matrix* matrix = &face->type1.font_matrix; 313*37da2899SCharles.Forsyth FT_Vector* offset = &face->type1.font_offset; 314*37da2899SCharles.Forsyth FT_Face root = (FT_Face)&face->root; 315*37da2899SCharles.Forsyth FT_Fixed temp[6]; 316*37da2899SCharles.Forsyth FT_Fixed temp_scale; 317*37da2899SCharles.Forsyth 318*37da2899SCharles.Forsyth 319*37da2899SCharles.Forsyth (void)T1_ToFixedArray( parser, 6, temp, 3 ); 320*37da2899SCharles.Forsyth 321*37da2899SCharles.Forsyth temp_scale = ABS( temp[3] ); 322*37da2899SCharles.Forsyth 323*37da2899SCharles.Forsyth /* Set Units per EM based on FontMatrix values. We set the value to */ 324*37da2899SCharles.Forsyth /* 1000 / temp_scale, because temp_scale was already multiplied by */ 325*37da2899SCharles.Forsyth /* 1000 (in t1_tofixed, from psobjs.c). */ 326*37da2899SCharles.Forsyth 327*37da2899SCharles.Forsyth root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L, 328*37da2899SCharles.Forsyth temp_scale ) >> 16 ); 329*37da2899SCharles.Forsyth 330*37da2899SCharles.Forsyth /* we need to scale the values by 1.0/temp_scale */ 331*37da2899SCharles.Forsyth if ( temp_scale != 0x10000L ) { 332*37da2899SCharles.Forsyth temp[0] = FT_DivFix( temp[0], temp_scale ); 333*37da2899SCharles.Forsyth temp[1] = FT_DivFix( temp[1], temp_scale ); 334*37da2899SCharles.Forsyth temp[2] = FT_DivFix( temp[2], temp_scale ); 335*37da2899SCharles.Forsyth temp[4] = FT_DivFix( temp[4], temp_scale ); 336*37da2899SCharles.Forsyth temp[5] = FT_DivFix( temp[5], temp_scale ); 337*37da2899SCharles.Forsyth temp[3] = 0x10000L; 338*37da2899SCharles.Forsyth } 339*37da2899SCharles.Forsyth 340*37da2899SCharles.Forsyth matrix->xx = temp[0]; 341*37da2899SCharles.Forsyth matrix->yx = temp[1]; 342*37da2899SCharles.Forsyth matrix->xy = temp[2]; 343*37da2899SCharles.Forsyth matrix->yy = temp[3]; 344*37da2899SCharles.Forsyth 345*37da2899SCharles.Forsyth /* note that the offsets must be expressed in integer font units */ 346*37da2899SCharles.Forsyth offset->x = temp[4] >> 16; 347*37da2899SCharles.Forsyth offset->y = temp[5] >> 16; 348*37da2899SCharles.Forsyth } 349*37da2899SCharles.Forsyth 350*37da2899SCharles.Forsyth 351*37da2899SCharles.Forsyth static void t42_parse_encoding(T42_Face face,T42_Loader loader)352*37da2899SCharles.Forsyth t42_parse_encoding( T42_Face face, 353*37da2899SCharles.Forsyth T42_Loader loader ) 354*37da2899SCharles.Forsyth { 355*37da2899SCharles.Forsyth T42_Parser parser = &loader->parser; 356*37da2899SCharles.Forsyth FT_Byte* cur = parser->root.cursor; 357*37da2899SCharles.Forsyth FT_Byte* limit = parser->root.limit; 358*37da2899SCharles.Forsyth 359*37da2899SCharles.Forsyth PSAux_Service psaux = (PSAux_Service)face->psaux; 360*37da2899SCharles.Forsyth 361*37da2899SCharles.Forsyth 362*37da2899SCharles.Forsyth /* skip whitespace */ 363*37da2899SCharles.Forsyth while ( t42_is_space( *cur ) ) 364*37da2899SCharles.Forsyth { 365*37da2899SCharles.Forsyth cur++; 366*37da2899SCharles.Forsyth if ( cur >= limit ) 367*37da2899SCharles.Forsyth { 368*37da2899SCharles.Forsyth FT_ERROR(( "t42_parse_encoding: out of bounds!\n" )); 369*37da2899SCharles.Forsyth parser->root.error = T42_Err_Invalid_File_Format; 370*37da2899SCharles.Forsyth return; 371*37da2899SCharles.Forsyth } 372*37da2899SCharles.Forsyth } 373*37da2899SCharles.Forsyth 374*37da2899SCharles.Forsyth /* if we have a number, then the encoding is an array, */ 375*37da2899SCharles.Forsyth /* and we must load it now */ 376*37da2899SCharles.Forsyth if ( (FT_Byte)( *cur - '0' ) < 10 ) 377*37da2899SCharles.Forsyth { 378*37da2899SCharles.Forsyth T1_Encoding encode = &face->type1.encoding; 379*37da2899SCharles.Forsyth FT_Int count, n; 380*37da2899SCharles.Forsyth PS_Table char_table = &loader->encoding_table; 381*37da2899SCharles.Forsyth FT_Memory memory = parser->root.memory; 382*37da2899SCharles.Forsyth FT_Error error; 383*37da2899SCharles.Forsyth 384*37da2899SCharles.Forsyth 385*37da2899SCharles.Forsyth /* read the number of entries in the encoding, should be 256 */ 386*37da2899SCharles.Forsyth count = T1_ToInt( parser ); 387*37da2899SCharles.Forsyth if ( parser->root.error ) 388*37da2899SCharles.Forsyth return; 389*37da2899SCharles.Forsyth 390*37da2899SCharles.Forsyth /* we use a T1_Table to store our charnames */ 391*37da2899SCharles.Forsyth loader->num_chars = encode->num_chars = count; 392*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( encode->char_index, count ) || 393*37da2899SCharles.Forsyth FT_NEW_ARRAY( encode->char_name, count ) || 394*37da2899SCharles.Forsyth FT_SET_ERROR( psaux->ps_table_funcs->init( 395*37da2899SCharles.Forsyth char_table, count, memory ) ) ) 396*37da2899SCharles.Forsyth { 397*37da2899SCharles.Forsyth parser->root.error = error; 398*37da2899SCharles.Forsyth return; 399*37da2899SCharles.Forsyth } 400*37da2899SCharles.Forsyth 401*37da2899SCharles.Forsyth /* We need to `zero' out encoding_table.elements */ 402*37da2899SCharles.Forsyth for ( n = 0; n < count; n++ ) 403*37da2899SCharles.Forsyth { 404*37da2899SCharles.Forsyth char* notdef = (char *)".notdef"; 405*37da2899SCharles.Forsyth 406*37da2899SCharles.Forsyth 407*37da2899SCharles.Forsyth T1_Add_Table( char_table, n, notdef, 8 ); 408*37da2899SCharles.Forsyth } 409*37da2899SCharles.Forsyth 410*37da2899SCharles.Forsyth /* Now, we will need to read a record of the form */ 411*37da2899SCharles.Forsyth /* ... charcode /charname ... for each entry in our table */ 412*37da2899SCharles.Forsyth /* */ 413*37da2899SCharles.Forsyth /* We simply look for a number followed by an immediate */ 414*37da2899SCharles.Forsyth /* name. Note that this ignores correctly the sequence */ 415*37da2899SCharles.Forsyth /* that is often seen in type1 fonts: */ 416*37da2899SCharles.Forsyth /* */ 417*37da2899SCharles.Forsyth /* 0 1 255 { 1 index exch /.notdef put } for dup */ 418*37da2899SCharles.Forsyth /* */ 419*37da2899SCharles.Forsyth /* used to clean the encoding array before anything else. */ 420*37da2899SCharles.Forsyth /* */ 421*37da2899SCharles.Forsyth /* We stop when we encounter a `def'. */ 422*37da2899SCharles.Forsyth 423*37da2899SCharles.Forsyth cur = parser->root.cursor; 424*37da2899SCharles.Forsyth limit = parser->root.limit; 425*37da2899SCharles.Forsyth n = 0; 426*37da2899SCharles.Forsyth 427*37da2899SCharles.Forsyth for ( ; cur < limit; ) 428*37da2899SCharles.Forsyth { 429*37da2899SCharles.Forsyth FT_Byte c; 430*37da2899SCharles.Forsyth 431*37da2899SCharles.Forsyth 432*37da2899SCharles.Forsyth c = *cur; 433*37da2899SCharles.Forsyth 434*37da2899SCharles.Forsyth /* we stop when we encounter a `def' */ 435*37da2899SCharles.Forsyth if ( c == 'd' && cur + 3 < limit ) 436*37da2899SCharles.Forsyth { 437*37da2899SCharles.Forsyth if ( cur[1] == 'e' && 438*37da2899SCharles.Forsyth cur[2] == 'f' && 439*37da2899SCharles.Forsyth t42_is_space( cur[-1] ) && 440*37da2899SCharles.Forsyth t42_is_space( cur[3] ) ) 441*37da2899SCharles.Forsyth { 442*37da2899SCharles.Forsyth FT_TRACE6(( "encoding end\n" )); 443*37da2899SCharles.Forsyth break; 444*37da2899SCharles.Forsyth } 445*37da2899SCharles.Forsyth } 446*37da2899SCharles.Forsyth 447*37da2899SCharles.Forsyth /* otherwise, we must find a number before anything else */ 448*37da2899SCharles.Forsyth if ( (FT_Byte)( c - '0' ) < 10 ) 449*37da2899SCharles.Forsyth { 450*37da2899SCharles.Forsyth FT_Int charcode; 451*37da2899SCharles.Forsyth 452*37da2899SCharles.Forsyth 453*37da2899SCharles.Forsyth parser->root.cursor = cur; 454*37da2899SCharles.Forsyth charcode = T1_ToInt( parser ); 455*37da2899SCharles.Forsyth cur = parser->root.cursor; 456*37da2899SCharles.Forsyth 457*37da2899SCharles.Forsyth /* skip whitespace */ 458*37da2899SCharles.Forsyth while ( cur < limit && t42_is_space( *cur ) ) 459*37da2899SCharles.Forsyth cur++; 460*37da2899SCharles.Forsyth 461*37da2899SCharles.Forsyth if ( cur < limit && *cur == '/' ) 462*37da2899SCharles.Forsyth { 463*37da2899SCharles.Forsyth /* bingo, we have an immediate name -- it must be a */ 464*37da2899SCharles.Forsyth /* character name */ 465*37da2899SCharles.Forsyth FT_Byte* cur2 = cur + 1; 466*37da2899SCharles.Forsyth FT_Int len; 467*37da2899SCharles.Forsyth 468*37da2899SCharles.Forsyth 469*37da2899SCharles.Forsyth while ( cur2 < limit && t42_is_alpha( *cur2 ) ) 470*37da2899SCharles.Forsyth cur2++; 471*37da2899SCharles.Forsyth 472*37da2899SCharles.Forsyth len = (FT_Int)( cur2 - cur - 1 ); 473*37da2899SCharles.Forsyth 474*37da2899SCharles.Forsyth parser->root.error = T1_Add_Table( char_table, charcode, 475*37da2899SCharles.Forsyth cur + 1, len + 1 ); 476*37da2899SCharles.Forsyth char_table->elements[charcode][len] = '\0'; 477*37da2899SCharles.Forsyth if ( parser->root.error ) 478*37da2899SCharles.Forsyth return; 479*37da2899SCharles.Forsyth 480*37da2899SCharles.Forsyth cur = cur2; 481*37da2899SCharles.Forsyth } 482*37da2899SCharles.Forsyth } 483*37da2899SCharles.Forsyth else 484*37da2899SCharles.Forsyth cur++; 485*37da2899SCharles.Forsyth } 486*37da2899SCharles.Forsyth 487*37da2899SCharles.Forsyth face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; 488*37da2899SCharles.Forsyth parser->root.cursor = cur; 489*37da2899SCharles.Forsyth } 490*37da2899SCharles.Forsyth /* Otherwise, we should have either `StandardEncoding', */ 491*37da2899SCharles.Forsyth /* `ExpertEncoding', or `ISOLatin1Encoding' */ 492*37da2899SCharles.Forsyth else 493*37da2899SCharles.Forsyth { 494*37da2899SCharles.Forsyth if ( cur + 17 < limit && 495*37da2899SCharles.Forsyth ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) 496*37da2899SCharles.Forsyth face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; 497*37da2899SCharles.Forsyth 498*37da2899SCharles.Forsyth else if ( cur + 15 < limit && 499*37da2899SCharles.Forsyth ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) 500*37da2899SCharles.Forsyth face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; 501*37da2899SCharles.Forsyth 502*37da2899SCharles.Forsyth else if ( cur + 18 < limit && 503*37da2899SCharles.Forsyth ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) 504*37da2899SCharles.Forsyth face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; 505*37da2899SCharles.Forsyth 506*37da2899SCharles.Forsyth else { 507*37da2899SCharles.Forsyth FT_ERROR(( "t42_parse_encoding: invalid token!\n" )); 508*37da2899SCharles.Forsyth parser->root.error = T42_Err_Invalid_File_Format; 509*37da2899SCharles.Forsyth } 510*37da2899SCharles.Forsyth } 511*37da2899SCharles.Forsyth } 512*37da2899SCharles.Forsyth 513*37da2899SCharles.Forsyth 514*37da2899SCharles.Forsyth static FT_UInt t42_hexval(FT_Byte v)515*37da2899SCharles.Forsyth t42_hexval( FT_Byte v ) 516*37da2899SCharles.Forsyth { 517*37da2899SCharles.Forsyth FT_UInt d; 518*37da2899SCharles.Forsyth 519*37da2899SCharles.Forsyth d = (FT_UInt)( v - 'A' ); 520*37da2899SCharles.Forsyth if ( d < 6 ) 521*37da2899SCharles.Forsyth { 522*37da2899SCharles.Forsyth d += 10; 523*37da2899SCharles.Forsyth goto Exit; 524*37da2899SCharles.Forsyth } 525*37da2899SCharles.Forsyth 526*37da2899SCharles.Forsyth d = (FT_UInt)( v - 'a' ); 527*37da2899SCharles.Forsyth if ( d < 6 ) 528*37da2899SCharles.Forsyth { 529*37da2899SCharles.Forsyth d += 10; 530*37da2899SCharles.Forsyth goto Exit; 531*37da2899SCharles.Forsyth } 532*37da2899SCharles.Forsyth 533*37da2899SCharles.Forsyth d = (FT_UInt)( v - '0' ); 534*37da2899SCharles.Forsyth if ( d < 10 ) 535*37da2899SCharles.Forsyth goto Exit; 536*37da2899SCharles.Forsyth 537*37da2899SCharles.Forsyth d = 0; 538*37da2899SCharles.Forsyth 539*37da2899SCharles.Forsyth Exit: 540*37da2899SCharles.Forsyth return d; 541*37da2899SCharles.Forsyth } 542*37da2899SCharles.Forsyth 543*37da2899SCharles.Forsyth 544*37da2899SCharles.Forsyth static void t42_parse_sfnts(T42_Face face,T42_Loader loader)545*37da2899SCharles.Forsyth t42_parse_sfnts( T42_Face face, 546*37da2899SCharles.Forsyth T42_Loader loader ) 547*37da2899SCharles.Forsyth { 548*37da2899SCharles.Forsyth T42_Parser parser = &loader->parser; 549*37da2899SCharles.Forsyth FT_Memory memory = parser->root.memory; 550*37da2899SCharles.Forsyth FT_Byte* cur = parser->root.cursor; 551*37da2899SCharles.Forsyth FT_Byte* limit = parser->root.limit; 552*37da2899SCharles.Forsyth FT_Error error; 553*37da2899SCharles.Forsyth FT_Int num_tables = 0, status; 554*37da2899SCharles.Forsyth FT_ULong count, ttf_size = 0, string_size = 0; 555*37da2899SCharles.Forsyth FT_Bool in_string = 0; 556*37da2899SCharles.Forsyth FT_Byte v = 0; 557*37da2899SCharles.Forsyth 558*37da2899SCharles.Forsyth 559*37da2899SCharles.Forsyth /* The format is `/sfnts [ <...> <...> ... ] def' */ 560*37da2899SCharles.Forsyth 561*37da2899SCharles.Forsyth while ( t42_is_space( *cur ) ) 562*37da2899SCharles.Forsyth cur++; 563*37da2899SCharles.Forsyth 564*37da2899SCharles.Forsyth if (*cur++ == '[') 565*37da2899SCharles.Forsyth { 566*37da2899SCharles.Forsyth status = 0; 567*37da2899SCharles.Forsyth count = 0; 568*37da2899SCharles.Forsyth } 569*37da2899SCharles.Forsyth else 570*37da2899SCharles.Forsyth { 571*37da2899SCharles.Forsyth FT_ERROR(( "t42_parse_sfnts: can't find begin of sfnts vector!\n" )); 572*37da2899SCharles.Forsyth error = T42_Err_Invalid_File_Format; 573*37da2899SCharles.Forsyth goto Fail; 574*37da2899SCharles.Forsyth } 575*37da2899SCharles.Forsyth 576*37da2899SCharles.Forsyth while ( cur < limit - 2 ) 577*37da2899SCharles.Forsyth { 578*37da2899SCharles.Forsyth while ( t42_is_space( *cur ) ) 579*37da2899SCharles.Forsyth cur++; 580*37da2899SCharles.Forsyth 581*37da2899SCharles.Forsyth switch ( *cur ) 582*37da2899SCharles.Forsyth { 583*37da2899SCharles.Forsyth case ']': 584*37da2899SCharles.Forsyth parser->root.cursor = cur++; 585*37da2899SCharles.Forsyth return; 586*37da2899SCharles.Forsyth 587*37da2899SCharles.Forsyth case '<': 588*37da2899SCharles.Forsyth in_string = 1; 589*37da2899SCharles.Forsyth string_size = 0; 590*37da2899SCharles.Forsyth cur++; 591*37da2899SCharles.Forsyth continue; 592*37da2899SCharles.Forsyth 593*37da2899SCharles.Forsyth case '>': 594*37da2899SCharles.Forsyth if ( !in_string ) 595*37da2899SCharles.Forsyth { 596*37da2899SCharles.Forsyth FT_ERROR(( "t42_parse_sfnts: found unpaired `>'!\n" )); 597*37da2899SCharles.Forsyth error = T42_Err_Invalid_File_Format; 598*37da2899SCharles.Forsyth goto Fail; 599*37da2899SCharles.Forsyth } 600*37da2899SCharles.Forsyth 601*37da2899SCharles.Forsyth /* A string can have, as a last byte, */ 602*37da2899SCharles.Forsyth /* a zero byte for padding. If so, ignore it */ 603*37da2899SCharles.Forsyth if ( ( v == 0 ) && ( string_size % 2 == 1 ) ) 604*37da2899SCharles.Forsyth count--; 605*37da2899SCharles.Forsyth in_string = 0; 606*37da2899SCharles.Forsyth cur++; 607*37da2899SCharles.Forsyth continue; 608*37da2899SCharles.Forsyth 609*37da2899SCharles.Forsyth case '%': 610*37da2899SCharles.Forsyth if ( !in_string ) 611*37da2899SCharles.Forsyth { 612*37da2899SCharles.Forsyth /* Comment found; skip till end of line */ 613*37da2899SCharles.Forsyth while ( *cur != '\n' ) 614*37da2899SCharles.Forsyth cur++; 615*37da2899SCharles.Forsyth continue; 616*37da2899SCharles.Forsyth } 617*37da2899SCharles.Forsyth else 618*37da2899SCharles.Forsyth { 619*37da2899SCharles.Forsyth FT_ERROR(( "t42_parse_sfnts: found `%' in string!\n" )); 620*37da2899SCharles.Forsyth error = T42_Err_Invalid_File_Format; 621*37da2899SCharles.Forsyth goto Fail; 622*37da2899SCharles.Forsyth } 623*37da2899SCharles.Forsyth 624*37da2899SCharles.Forsyth default: 625*37da2899SCharles.Forsyth if ( !ft_xdigit( *cur ) || !ft_xdigit( *(cur + 1) ) ) 626*37da2899SCharles.Forsyth { 627*37da2899SCharles.Forsyth FT_ERROR(( "t42_parse_sfnts: found non-hex characters in string" )); 628*37da2899SCharles.Forsyth error = T42_Err_Invalid_File_Format; 629*37da2899SCharles.Forsyth goto Fail; 630*37da2899SCharles.Forsyth } 631*37da2899SCharles.Forsyth 632*37da2899SCharles.Forsyth v = (FT_Byte)( 16 * t42_hexval( cur[0] ) + t42_hexval( cur[1] ) ); 633*37da2899SCharles.Forsyth cur += 2; 634*37da2899SCharles.Forsyth string_size++; 635*37da2899SCharles.Forsyth } 636*37da2899SCharles.Forsyth 637*37da2899SCharles.Forsyth switch ( status ) 638*37da2899SCharles.Forsyth { 639*37da2899SCharles.Forsyth case 0: /* The '[' was read, so load offset table, 12 bytes */ 640*37da2899SCharles.Forsyth if ( count < 12 ) 641*37da2899SCharles.Forsyth { 642*37da2899SCharles.Forsyth face->ttf_data[count++] = v; 643*37da2899SCharles.Forsyth continue; 644*37da2899SCharles.Forsyth } 645*37da2899SCharles.Forsyth else 646*37da2899SCharles.Forsyth { 647*37da2899SCharles.Forsyth num_tables = 16 * face->ttf_data[4] + face->ttf_data[5]; 648*37da2899SCharles.Forsyth status = 1; 649*37da2899SCharles.Forsyth ttf_size = 12 + 16 * num_tables; 650*37da2899SCharles.Forsyth 651*37da2899SCharles.Forsyth if ( FT_REALLOC( face->ttf_data, 12, ttf_size ) ) 652*37da2899SCharles.Forsyth goto Fail; 653*37da2899SCharles.Forsyth } 654*37da2899SCharles.Forsyth /* No break, fall-through */ 655*37da2899SCharles.Forsyth 656*37da2899SCharles.Forsyth case 1: /* The offset table is read; read now the table directory */ 657*37da2899SCharles.Forsyth if ( count < ttf_size ) 658*37da2899SCharles.Forsyth { 659*37da2899SCharles.Forsyth face->ttf_data[count++] = v; 660*37da2899SCharles.Forsyth continue; 661*37da2899SCharles.Forsyth } 662*37da2899SCharles.Forsyth else 663*37da2899SCharles.Forsyth { 664*37da2899SCharles.Forsyth int i; 665*37da2899SCharles.Forsyth FT_ULong len; 666*37da2899SCharles.Forsyth 667*37da2899SCharles.Forsyth 668*37da2899SCharles.Forsyth for ( i = 0; i < num_tables; i++ ) 669*37da2899SCharles.Forsyth { 670*37da2899SCharles.Forsyth FT_Byte* p = face->ttf_data + 12 + 16*i + 12; 671*37da2899SCharles.Forsyth 672*37da2899SCharles.Forsyth len = FT_PEEK_ULONG( p ); 673*37da2899SCharles.Forsyth 674*37da2899SCharles.Forsyth /* Pad to a 4-byte boundary length */ 675*37da2899SCharles.Forsyth ttf_size += ( len + 3 ) & ~3; 676*37da2899SCharles.Forsyth } 677*37da2899SCharles.Forsyth 678*37da2899SCharles.Forsyth status = 2; 679*37da2899SCharles.Forsyth face->ttf_size = ttf_size; 680*37da2899SCharles.Forsyth 681*37da2899SCharles.Forsyth if ( FT_REALLOC( face->ttf_data, 12 + 16 * num_tables, 682*37da2899SCharles.Forsyth ttf_size + 1 ) ) 683*37da2899SCharles.Forsyth goto Fail; 684*37da2899SCharles.Forsyth } 685*37da2899SCharles.Forsyth /* No break, fall-through */ 686*37da2899SCharles.Forsyth 687*37da2899SCharles.Forsyth case 2: /* We are reading normal tables; just swallow them */ 688*37da2899SCharles.Forsyth face->ttf_data[count++] = v; 689*37da2899SCharles.Forsyth 690*37da2899SCharles.Forsyth } 691*37da2899SCharles.Forsyth } 692*37da2899SCharles.Forsyth 693*37da2899SCharles.Forsyth /* If control reaches this point, the format was not valid */ 694*37da2899SCharles.Forsyth error = T42_Err_Invalid_File_Format; 695*37da2899SCharles.Forsyth 696*37da2899SCharles.Forsyth Fail: 697*37da2899SCharles.Forsyth parser->root.error = error; 698*37da2899SCharles.Forsyth } 699*37da2899SCharles.Forsyth 700*37da2899SCharles.Forsyth 701*37da2899SCharles.Forsyth static void t42_parse_charstrings(T42_Face face,T42_Loader loader)702*37da2899SCharles.Forsyth t42_parse_charstrings( T42_Face face, 703*37da2899SCharles.Forsyth T42_Loader loader ) 704*37da2899SCharles.Forsyth { 705*37da2899SCharles.Forsyth T42_Parser parser = &loader->parser; 706*37da2899SCharles.Forsyth PS_Table code_table = &loader->charstrings; 707*37da2899SCharles.Forsyth PS_Table name_table = &loader->glyph_names; 708*37da2899SCharles.Forsyth FT_Memory memory = parser->root.memory; 709*37da2899SCharles.Forsyth FT_Error error; 710*37da2899SCharles.Forsyth 711*37da2899SCharles.Forsyth PSAux_Service psaux = (PSAux_Service)face->psaux; 712*37da2899SCharles.Forsyth 713*37da2899SCharles.Forsyth FT_Byte* cur; 714*37da2899SCharles.Forsyth FT_Byte* limit = parser->root.limit; 715*37da2899SCharles.Forsyth FT_Int n; 716*37da2899SCharles.Forsyth 717*37da2899SCharles.Forsyth 718*37da2899SCharles.Forsyth loader->num_glyphs = T1_ToInt( parser ); 719*37da2899SCharles.Forsyth if ( parser->root.error ) 720*37da2899SCharles.Forsyth return; 721*37da2899SCharles.Forsyth 722*37da2899SCharles.Forsyth /* initialize tables */ 723*37da2899SCharles.Forsyth 724*37da2899SCharles.Forsyth error = psaux->ps_table_funcs->init( code_table, 725*37da2899SCharles.Forsyth loader->num_glyphs, 726*37da2899SCharles.Forsyth memory ); 727*37da2899SCharles.Forsyth if ( error ) 728*37da2899SCharles.Forsyth goto Fail; 729*37da2899SCharles.Forsyth 730*37da2899SCharles.Forsyth error = psaux->ps_table_funcs->init( name_table, 731*37da2899SCharles.Forsyth loader->num_glyphs, 732*37da2899SCharles.Forsyth memory ); 733*37da2899SCharles.Forsyth if ( error ) 734*37da2899SCharles.Forsyth goto Fail; 735*37da2899SCharles.Forsyth 736*37da2899SCharles.Forsyth n = 0; 737*37da2899SCharles.Forsyth 738*37da2899SCharles.Forsyth for (;;) 739*37da2899SCharles.Forsyth { 740*37da2899SCharles.Forsyth /* the format is simple: */ 741*37da2899SCharles.Forsyth /* `/glyphname' + index + def */ 742*37da2899SCharles.Forsyth /* */ 743*37da2899SCharles.Forsyth /* note that we stop when we find an `end' */ 744*37da2899SCharles.Forsyth /* */ 745*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 746*37da2899SCharles.Forsyth 747*37da2899SCharles.Forsyth cur = parser->root.cursor; 748*37da2899SCharles.Forsyth if ( cur >= limit ) 749*37da2899SCharles.Forsyth break; 750*37da2899SCharles.Forsyth 751*37da2899SCharles.Forsyth /* we stop when we find an `end' keyword */ 752*37da2899SCharles.Forsyth if ( *cur == 'e' && 753*37da2899SCharles.Forsyth cur + 3 < limit && 754*37da2899SCharles.Forsyth cur[1] == 'n' && 755*37da2899SCharles.Forsyth cur[2] == 'd' ) 756*37da2899SCharles.Forsyth break; 757*37da2899SCharles.Forsyth 758*37da2899SCharles.Forsyth if ( *cur != '/' ) 759*37da2899SCharles.Forsyth T1_Skip_Alpha( parser ); 760*37da2899SCharles.Forsyth else 761*37da2899SCharles.Forsyth { 762*37da2899SCharles.Forsyth FT_Byte* cur2 = cur + 1; 763*37da2899SCharles.Forsyth FT_Int len; 764*37da2899SCharles.Forsyth 765*37da2899SCharles.Forsyth 766*37da2899SCharles.Forsyth while ( cur2 < limit && t42_is_alpha( *cur2 ) ) 767*37da2899SCharles.Forsyth cur2++; 768*37da2899SCharles.Forsyth len = (FT_Int)( cur2 - cur - 1 ); 769*37da2899SCharles.Forsyth 770*37da2899SCharles.Forsyth error = T1_Add_Table( name_table, n, cur + 1, len + 1 ); 771*37da2899SCharles.Forsyth if ( error ) 772*37da2899SCharles.Forsyth goto Fail; 773*37da2899SCharles.Forsyth 774*37da2899SCharles.Forsyth /* add a trailing zero to the name table */ 775*37da2899SCharles.Forsyth name_table->elements[n][len] = '\0'; 776*37da2899SCharles.Forsyth 777*37da2899SCharles.Forsyth parser->root.cursor = cur2; 778*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 779*37da2899SCharles.Forsyth 780*37da2899SCharles.Forsyth cur2 = cur = parser->root.cursor; 781*37da2899SCharles.Forsyth if ( cur >= limit ) 782*37da2899SCharles.Forsyth break; 783*37da2899SCharles.Forsyth 784*37da2899SCharles.Forsyth while ( cur2 < limit && t42_is_alpha( *cur2 ) ) 785*37da2899SCharles.Forsyth cur2++; 786*37da2899SCharles.Forsyth len = (FT_Int)( cur2 - cur ); 787*37da2899SCharles.Forsyth 788*37da2899SCharles.Forsyth error = T1_Add_Table( code_table, n, cur, len + 1 ); 789*37da2899SCharles.Forsyth if ( error ) 790*37da2899SCharles.Forsyth goto Fail; 791*37da2899SCharles.Forsyth 792*37da2899SCharles.Forsyth code_table->elements[n][len] = '\0'; 793*37da2899SCharles.Forsyth 794*37da2899SCharles.Forsyth n++; 795*37da2899SCharles.Forsyth if ( n >= loader->num_glyphs ) 796*37da2899SCharles.Forsyth break; 797*37da2899SCharles.Forsyth } 798*37da2899SCharles.Forsyth } 799*37da2899SCharles.Forsyth 800*37da2899SCharles.Forsyth /* Index 0 must be a .notdef element */ 801*37da2899SCharles.Forsyth if ( ft_strcmp( (char *)name_table->elements[0], ".notdef" ) ) 802*37da2899SCharles.Forsyth { 803*37da2899SCharles.Forsyth FT_ERROR(( "t42_parse_charstrings: Index 0 is not `.notdef'!\n" )); 804*37da2899SCharles.Forsyth error = T42_Err_Invalid_File_Format; 805*37da2899SCharles.Forsyth goto Fail; 806*37da2899SCharles.Forsyth } 807*37da2899SCharles.Forsyth 808*37da2899SCharles.Forsyth loader->num_glyphs = n; 809*37da2899SCharles.Forsyth return; 810*37da2899SCharles.Forsyth 811*37da2899SCharles.Forsyth Fail: 812*37da2899SCharles.Forsyth parser->root.error = error; 813*37da2899SCharles.Forsyth } 814*37da2899SCharles.Forsyth 815*37da2899SCharles.Forsyth 816*37da2899SCharles.Forsyth static FT_Error t42_load_keyword(T42_Face face,T42_Loader loader,T1_Field field)817*37da2899SCharles.Forsyth t42_load_keyword( T42_Face face, 818*37da2899SCharles.Forsyth T42_Loader loader, 819*37da2899SCharles.Forsyth T1_Field field ) 820*37da2899SCharles.Forsyth { 821*37da2899SCharles.Forsyth FT_Error error; 822*37da2899SCharles.Forsyth void* dummy_object; 823*37da2899SCharles.Forsyth void** objects; 824*37da2899SCharles.Forsyth FT_UInt max_objects = 0; 825*37da2899SCharles.Forsyth 826*37da2899SCharles.Forsyth 827*37da2899SCharles.Forsyth /* if the keyword has a dedicated callback, call it */ 828*37da2899SCharles.Forsyth if ( field->type == T1_FIELD_TYPE_CALLBACK ) { 829*37da2899SCharles.Forsyth field->reader( (FT_Face)face, loader ); 830*37da2899SCharles.Forsyth error = loader->parser.root.error; 831*37da2899SCharles.Forsyth goto Exit; 832*37da2899SCharles.Forsyth } 833*37da2899SCharles.Forsyth 834*37da2899SCharles.Forsyth /* now, the keyword is either a simple field, or a table of fields; */ 835*37da2899SCharles.Forsyth /* we are now going to take care of it */ 836*37da2899SCharles.Forsyth switch ( field->location ) 837*37da2899SCharles.Forsyth { 838*37da2899SCharles.Forsyth case T1_FIELD_LOCATION_FONT_INFO: 839*37da2899SCharles.Forsyth dummy_object = &face->type1.font_info; 840*37da2899SCharles.Forsyth objects = &dummy_object; 841*37da2899SCharles.Forsyth break; 842*37da2899SCharles.Forsyth 843*37da2899SCharles.Forsyth default: 844*37da2899SCharles.Forsyth dummy_object = &face->type1; 845*37da2899SCharles.Forsyth objects = &dummy_object; 846*37da2899SCharles.Forsyth } 847*37da2899SCharles.Forsyth 848*37da2899SCharles.Forsyth if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY || 849*37da2899SCharles.Forsyth field->type == T1_FIELD_TYPE_FIXED_ARRAY ) 850*37da2899SCharles.Forsyth error = T1_Load_Field_Table( &loader->parser, field, 851*37da2899SCharles.Forsyth objects, max_objects, 0 ); 852*37da2899SCharles.Forsyth else 853*37da2899SCharles.Forsyth error = T1_Load_Field( &loader->parser, field, 854*37da2899SCharles.Forsyth objects, max_objects, 0 ); 855*37da2899SCharles.Forsyth 856*37da2899SCharles.Forsyth Exit: 857*37da2899SCharles.Forsyth return error; 858*37da2899SCharles.Forsyth } 859*37da2899SCharles.Forsyth 860*37da2899SCharles.Forsyth 861*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) t42_parse_dict(T42_Face face,T42_Loader loader,FT_Byte * base,FT_Long size)862*37da2899SCharles.Forsyth t42_parse_dict( T42_Face face, 863*37da2899SCharles.Forsyth T42_Loader loader, 864*37da2899SCharles.Forsyth FT_Byte* base, 865*37da2899SCharles.Forsyth FT_Long size ) 866*37da2899SCharles.Forsyth { 867*37da2899SCharles.Forsyth T42_Parser parser = &loader->parser; 868*37da2899SCharles.Forsyth FT_Byte* cur = base; 869*37da2899SCharles.Forsyth FT_Byte* limit = cur + size; 870*37da2899SCharles.Forsyth FT_UInt n_keywords = sizeof ( t42_keywords ) / 871*37da2899SCharles.Forsyth sizeof ( t42_keywords[0] ); 872*37da2899SCharles.Forsyth 873*37da2899SCharles.Forsyth 874*37da2899SCharles.Forsyth parser->root.cursor = base; 875*37da2899SCharles.Forsyth parser->root.limit = base + size; 876*37da2899SCharles.Forsyth parser->root.error = 0; 877*37da2899SCharles.Forsyth 878*37da2899SCharles.Forsyth for ( ; cur < limit; cur++ ) 879*37da2899SCharles.Forsyth { 880*37da2899SCharles.Forsyth /* look for `FontDirectory', which causes problems on some fonts */ 881*37da2899SCharles.Forsyth if ( *cur == 'F' && cur + 25 < limit && 882*37da2899SCharles.Forsyth ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 ) 883*37da2899SCharles.Forsyth { 884*37da2899SCharles.Forsyth FT_Byte* cur2; 885*37da2899SCharles.Forsyth 886*37da2899SCharles.Forsyth 887*37da2899SCharles.Forsyth /* skip the `FontDirectory' keyword */ 888*37da2899SCharles.Forsyth cur += 13; 889*37da2899SCharles.Forsyth cur2 = cur; 890*37da2899SCharles.Forsyth 891*37da2899SCharles.Forsyth /* lookup the `known' keyword */ 892*37da2899SCharles.Forsyth while ( cur < limit && *cur != 'k' && 893*37da2899SCharles.Forsyth ft_strncmp( (char*)cur, "known", 5 ) ) 894*37da2899SCharles.Forsyth cur++; 895*37da2899SCharles.Forsyth 896*37da2899SCharles.Forsyth if ( cur < limit ) 897*37da2899SCharles.Forsyth { 898*37da2899SCharles.Forsyth T1_TokenRec token; 899*37da2899SCharles.Forsyth 900*37da2899SCharles.Forsyth 901*37da2899SCharles.Forsyth /* skip the `known' keyword and the token following it */ 902*37da2899SCharles.Forsyth cur += 5; 903*37da2899SCharles.Forsyth loader->parser.root.cursor = cur; 904*37da2899SCharles.Forsyth T1_ToToken( &loader->parser, &token ); 905*37da2899SCharles.Forsyth 906*37da2899SCharles.Forsyth /* if the last token was an array, skip it! */ 907*37da2899SCharles.Forsyth if ( token.type == T1_TOKEN_TYPE_ARRAY ) 908*37da2899SCharles.Forsyth cur2 = parser->root.cursor; 909*37da2899SCharles.Forsyth } 910*37da2899SCharles.Forsyth cur = cur2; 911*37da2899SCharles.Forsyth } 912*37da2899SCharles.Forsyth /* look for immediates */ 913*37da2899SCharles.Forsyth else if ( *cur == '/' && cur + 2 < limit ) 914*37da2899SCharles.Forsyth { 915*37da2899SCharles.Forsyth FT_Byte* cur2; 916*37da2899SCharles.Forsyth FT_UInt i, len; 917*37da2899SCharles.Forsyth 918*37da2899SCharles.Forsyth 919*37da2899SCharles.Forsyth cur++; 920*37da2899SCharles.Forsyth cur2 = cur; 921*37da2899SCharles.Forsyth while ( cur2 < limit && t42_is_alpha( *cur2 ) ) 922*37da2899SCharles.Forsyth cur2++; 923*37da2899SCharles.Forsyth 924*37da2899SCharles.Forsyth len = (FT_UInt)( cur2 - cur ); 925*37da2899SCharles.Forsyth if ( len > 0 && len < 22 ) /* XXX What shall it this 22? */ 926*37da2899SCharles.Forsyth { 927*37da2899SCharles.Forsyth /* now, compare the immediate name to the keyword table */ 928*37da2899SCharles.Forsyth 929*37da2899SCharles.Forsyth /* Loop through all known keywords */ 930*37da2899SCharles.Forsyth for ( i = 0; i < n_keywords; i++ ) 931*37da2899SCharles.Forsyth { 932*37da2899SCharles.Forsyth T1_Field keyword = (T1_Field)&t42_keywords[i]; 933*37da2899SCharles.Forsyth FT_Byte *name = (FT_Byte*)keyword->ident; 934*37da2899SCharles.Forsyth 935*37da2899SCharles.Forsyth 936*37da2899SCharles.Forsyth if ( !name ) 937*37da2899SCharles.Forsyth continue; 938*37da2899SCharles.Forsyth 939*37da2899SCharles.Forsyth if ( ( len == ft_strlen( (const char *)name ) ) && 940*37da2899SCharles.Forsyth ( ft_memcmp( cur, name, len ) == 0 ) ) 941*37da2899SCharles.Forsyth { 942*37da2899SCharles.Forsyth /* we found it -- run the parsing callback! */ 943*37da2899SCharles.Forsyth parser->root.cursor = cur2; 944*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 945*37da2899SCharles.Forsyth parser->root.error = t42_load_keyword(face, 946*37da2899SCharles.Forsyth loader, 947*37da2899SCharles.Forsyth keyword ); 948*37da2899SCharles.Forsyth if ( parser->root.error ) 949*37da2899SCharles.Forsyth return parser->root.error; 950*37da2899SCharles.Forsyth cur = parser->root.cursor; 951*37da2899SCharles.Forsyth break; 952*37da2899SCharles.Forsyth } 953*37da2899SCharles.Forsyth } 954*37da2899SCharles.Forsyth } 955*37da2899SCharles.Forsyth } 956*37da2899SCharles.Forsyth } 957*37da2899SCharles.Forsyth return parser->root.error; 958*37da2899SCharles.Forsyth } 959*37da2899SCharles.Forsyth 960*37da2899SCharles.Forsyth 961*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) t42_loader_init(T42_Loader loader,T42_Face face)962*37da2899SCharles.Forsyth t42_loader_init( T42_Loader loader, 963*37da2899SCharles.Forsyth T42_Face face ) 964*37da2899SCharles.Forsyth { 965*37da2899SCharles.Forsyth FT_UNUSED( face ); 966*37da2899SCharles.Forsyth 967*37da2899SCharles.Forsyth FT_MEM_ZERO( loader, sizeof ( *loader ) ); 968*37da2899SCharles.Forsyth loader->num_glyphs = 0; 969*37da2899SCharles.Forsyth loader->num_chars = 0; 970*37da2899SCharles.Forsyth 971*37da2899SCharles.Forsyth /* initialize the tables -- simply set their `init' field to 0 */ 972*37da2899SCharles.Forsyth loader->encoding_table.init = 0; 973*37da2899SCharles.Forsyth loader->charstrings.init = 0; 974*37da2899SCharles.Forsyth loader->glyph_names.init = 0; 975*37da2899SCharles.Forsyth } 976*37da2899SCharles.Forsyth 977*37da2899SCharles.Forsyth 978*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) t42_loader_done(T42_Loader loader)979*37da2899SCharles.Forsyth t42_loader_done( T42_Loader loader ) 980*37da2899SCharles.Forsyth { 981*37da2899SCharles.Forsyth T42_Parser parser = &loader->parser; 982*37da2899SCharles.Forsyth 983*37da2899SCharles.Forsyth 984*37da2899SCharles.Forsyth /* finalize tables */ 985*37da2899SCharles.Forsyth T1_Release_Table( &loader->encoding_table ); 986*37da2899SCharles.Forsyth T1_Release_Table( &loader->charstrings ); 987*37da2899SCharles.Forsyth T1_Release_Table( &loader->glyph_names ); 988*37da2899SCharles.Forsyth 989*37da2899SCharles.Forsyth /* finalize parser */ 990*37da2899SCharles.Forsyth t42_parser_done( parser ); 991*37da2899SCharles.Forsyth } 992*37da2899SCharles.Forsyth 993*37da2899SCharles.Forsyth 994*37da2899SCharles.Forsyth /* END */ 995