1*37da2899SCharles.Forsyth /***************************************************************************/ 2*37da2899SCharles.Forsyth /* */ 3*37da2899SCharles.Forsyth /* t1load.c */ 4*37da2899SCharles.Forsyth /* */ 5*37da2899SCharles.Forsyth /* Type 1 font loader (body). */ 6*37da2899SCharles.Forsyth /* */ 7*37da2899SCharles.Forsyth /* Copyright 1996-2001, 2002 by */ 8*37da2899SCharles.Forsyth /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 9*37da2899SCharles.Forsyth /* */ 10*37da2899SCharles.Forsyth /* This file is part of the FreeType project, and may only be used, */ 11*37da2899SCharles.Forsyth /* modified, and distributed under the terms of the FreeType project */ 12*37da2899SCharles.Forsyth /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 13*37da2899SCharles.Forsyth /* this file you indicate that you have read the license and */ 14*37da2899SCharles.Forsyth /* understand and accept it fully. */ 15*37da2899SCharles.Forsyth /* */ 16*37da2899SCharles.Forsyth /***************************************************************************/ 17*37da2899SCharles.Forsyth 18*37da2899SCharles.Forsyth 19*37da2899SCharles.Forsyth /*************************************************************************/ 20*37da2899SCharles.Forsyth /* */ 21*37da2899SCharles.Forsyth /* This is the new and improved Type 1 data loader for FreeType 2. The */ 22*37da2899SCharles.Forsyth /* old loader has several problems: it is slow, complex, difficult to */ 23*37da2899SCharles.Forsyth /* maintain, and contains incredible hacks to make it accept some */ 24*37da2899SCharles.Forsyth /* ill-formed Type 1 fonts without hiccup-ing. Moreover, about 5% of */ 25*37da2899SCharles.Forsyth /* the Type 1 fonts on my machine still aren't loaded correctly by it. */ 26*37da2899SCharles.Forsyth /* */ 27*37da2899SCharles.Forsyth /* This version is much simpler, much faster and also easier to read and */ 28*37da2899SCharles.Forsyth /* maintain by a great order of magnitude. The idea behind it is to */ 29*37da2899SCharles.Forsyth /* _not_ try to read the Type 1 token stream with a state machine (i.e. */ 30*37da2899SCharles.Forsyth /* a Postscript-like interpreter) but rather to perform simple pattern */ 31*37da2899SCharles.Forsyth /* matching. */ 32*37da2899SCharles.Forsyth /* */ 33*37da2899SCharles.Forsyth /* Indeed, nearly all data definitions follow a simple pattern like */ 34*37da2899SCharles.Forsyth /* */ 35*37da2899SCharles.Forsyth /* ... /Field <data> ... */ 36*37da2899SCharles.Forsyth /* */ 37*37da2899SCharles.Forsyth /* where <data> can be a number, a boolean, a string, or an array of */ 38*37da2899SCharles.Forsyth /* numbers. There are a few exceptions, namely the encoding, font name, */ 39*37da2899SCharles.Forsyth /* charstrings, and subrs; they are handled with a special pattern */ 40*37da2899SCharles.Forsyth /* matching routine. */ 41*37da2899SCharles.Forsyth /* */ 42*37da2899SCharles.Forsyth /* All other common cases are handled very simply. The matching rules */ 43*37da2899SCharles.Forsyth /* are defined in the file `t1tokens.h' through the use of several */ 44*37da2899SCharles.Forsyth /* macros calls PARSE_XXX. */ 45*37da2899SCharles.Forsyth /* */ 46*37da2899SCharles.Forsyth /* This file is included twice here; the first time to generate parsing */ 47*37da2899SCharles.Forsyth /* callback functions, the second to generate a table of keywords (with */ 48*37da2899SCharles.Forsyth /* pointers to the associated callback). */ 49*37da2899SCharles.Forsyth /* */ 50*37da2899SCharles.Forsyth /* The function `parse_dict' simply scans *linearly* a given dictionary */ 51*37da2899SCharles.Forsyth /* (either the top-level or private one) and calls the appropriate */ 52*37da2899SCharles.Forsyth /* callback when it encounters an immediate keyword. */ 53*37da2899SCharles.Forsyth /* */ 54*37da2899SCharles.Forsyth /* This is by far the fastest way one can find to parse and read all */ 55*37da2899SCharles.Forsyth /* data. */ 56*37da2899SCharles.Forsyth /* */ 57*37da2899SCharles.Forsyth /* This led to tremendous code size reduction. Note that later, the */ 58*37da2899SCharles.Forsyth /* glyph loader will also be _greatly_ simplified, and the automatic */ 59*37da2899SCharles.Forsyth /* hinter will replace the clumsy `t1hinter'. */ 60*37da2899SCharles.Forsyth /* */ 61*37da2899SCharles.Forsyth /*************************************************************************/ 62*37da2899SCharles.Forsyth 63*37da2899SCharles.Forsyth 64*37da2899SCharles.Forsyth #include <ft2build.h> 65*37da2899SCharles.Forsyth #include FT_INTERNAL_DEBUG_H 66*37da2899SCharles.Forsyth #include FT_CONFIG_CONFIG_H 67*37da2899SCharles.Forsyth #include FT_MULTIPLE_MASTERS_H 68*37da2899SCharles.Forsyth #include FT_INTERNAL_TYPE1_TYPES_H 69*37da2899SCharles.Forsyth 70*37da2899SCharles.Forsyth #include "t1load.h" 71*37da2899SCharles.Forsyth #include "t1errors.h" 72*37da2899SCharles.Forsyth 73*37da2899SCharles.Forsyth 74*37da2899SCharles.Forsyth 75*37da2899SCharles.Forsyth /*************************************************************************/ 76*37da2899SCharles.Forsyth /* */ 77*37da2899SCharles.Forsyth /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 78*37da2899SCharles.Forsyth /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 79*37da2899SCharles.Forsyth /* messages during execution. */ 80*37da2899SCharles.Forsyth /* */ 81*37da2899SCharles.Forsyth #undef FT_COMPONENT 82*37da2899SCharles.Forsyth #define FT_COMPONENT trace_t1load 83*37da2899SCharles.Forsyth 84*37da2899SCharles.Forsyth 85*37da2899SCharles.Forsyth #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT 86*37da2899SCharles.Forsyth 87*37da2899SCharles.Forsyth 88*37da2899SCharles.Forsyth /*************************************************************************/ 89*37da2899SCharles.Forsyth /*************************************************************************/ 90*37da2899SCharles.Forsyth /***** *****/ 91*37da2899SCharles.Forsyth /***** MULTIPLE MASTERS SUPPORT *****/ 92*37da2899SCharles.Forsyth /***** *****/ 93*37da2899SCharles.Forsyth /*************************************************************************/ 94*37da2899SCharles.Forsyth /*************************************************************************/ 95*37da2899SCharles.Forsyth 96*37da2899SCharles.Forsyth static FT_Error t1_allocate_blend(T1_Face face,FT_UInt num_designs,FT_UInt num_axis)97*37da2899SCharles.Forsyth t1_allocate_blend( T1_Face face, 98*37da2899SCharles.Forsyth FT_UInt num_designs, 99*37da2899SCharles.Forsyth FT_UInt num_axis ) 100*37da2899SCharles.Forsyth { 101*37da2899SCharles.Forsyth PS_Blend blend; 102*37da2899SCharles.Forsyth FT_Memory memory = face->root.memory; 103*37da2899SCharles.Forsyth FT_Error error = 0; 104*37da2899SCharles.Forsyth 105*37da2899SCharles.Forsyth 106*37da2899SCharles.Forsyth blend = face->blend; 107*37da2899SCharles.Forsyth if ( !blend ) 108*37da2899SCharles.Forsyth { 109*37da2899SCharles.Forsyth if ( FT_NEW( blend ) ) 110*37da2899SCharles.Forsyth goto Exit; 111*37da2899SCharles.Forsyth 112*37da2899SCharles.Forsyth face->blend = blend; 113*37da2899SCharles.Forsyth } 114*37da2899SCharles.Forsyth 115*37da2899SCharles.Forsyth /* allocate design data if needed */ 116*37da2899SCharles.Forsyth if ( num_designs > 0 ) 117*37da2899SCharles.Forsyth { 118*37da2899SCharles.Forsyth if ( blend->num_designs == 0 ) 119*37da2899SCharles.Forsyth { 120*37da2899SCharles.Forsyth FT_UInt nn; 121*37da2899SCharles.Forsyth 122*37da2899SCharles.Forsyth 123*37da2899SCharles.Forsyth /* allocate the blend `private' and `font_info' dictionaries */ 124*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( blend->font_infos[1], num_designs ) || 125*37da2899SCharles.Forsyth FT_NEW_ARRAY( blend->privates[1], num_designs ) || 126*37da2899SCharles.Forsyth FT_NEW_ARRAY( blend->bboxes[1], num_designs ) || 127*37da2899SCharles.Forsyth FT_NEW_ARRAY( blend->weight_vector, num_designs * 2 ) ) 128*37da2899SCharles.Forsyth goto Exit; 129*37da2899SCharles.Forsyth 130*37da2899SCharles.Forsyth blend->default_weight_vector = blend->weight_vector + num_designs; 131*37da2899SCharles.Forsyth 132*37da2899SCharles.Forsyth blend->font_infos[0] = &face->type1.font_info; 133*37da2899SCharles.Forsyth blend->privates [0] = &face->type1.private_dict; 134*37da2899SCharles.Forsyth blend->bboxes [0] = &face->type1.font_bbox; 135*37da2899SCharles.Forsyth 136*37da2899SCharles.Forsyth for ( nn = 2; nn <= num_designs; nn++ ) 137*37da2899SCharles.Forsyth { 138*37da2899SCharles.Forsyth blend->privates[nn] = blend->privates [nn - 1] + 1; 139*37da2899SCharles.Forsyth blend->font_infos[nn] = blend->font_infos[nn - 1] + 1; 140*37da2899SCharles.Forsyth blend->bboxes[nn] = blend->bboxes [nn - 1] + 1; 141*37da2899SCharles.Forsyth } 142*37da2899SCharles.Forsyth 143*37da2899SCharles.Forsyth blend->num_designs = num_designs; 144*37da2899SCharles.Forsyth } 145*37da2899SCharles.Forsyth else if ( blend->num_designs != num_designs ) 146*37da2899SCharles.Forsyth goto Fail; 147*37da2899SCharles.Forsyth } 148*37da2899SCharles.Forsyth 149*37da2899SCharles.Forsyth /* allocate axis data if needed */ 150*37da2899SCharles.Forsyth if ( num_axis > 0 ) 151*37da2899SCharles.Forsyth { 152*37da2899SCharles.Forsyth if ( blend->num_axis != 0 && blend->num_axis != num_axis ) 153*37da2899SCharles.Forsyth goto Fail; 154*37da2899SCharles.Forsyth 155*37da2899SCharles.Forsyth blend->num_axis = num_axis; 156*37da2899SCharles.Forsyth } 157*37da2899SCharles.Forsyth 158*37da2899SCharles.Forsyth /* allocate the blend design pos table if needed */ 159*37da2899SCharles.Forsyth num_designs = blend->num_designs; 160*37da2899SCharles.Forsyth num_axis = blend->num_axis; 161*37da2899SCharles.Forsyth if ( num_designs && num_axis && blend->design_pos[0] == 0 ) 162*37da2899SCharles.Forsyth { 163*37da2899SCharles.Forsyth FT_UInt n; 164*37da2899SCharles.Forsyth 165*37da2899SCharles.Forsyth 166*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( blend->design_pos[0], num_designs * num_axis ) ) 167*37da2899SCharles.Forsyth goto Exit; 168*37da2899SCharles.Forsyth 169*37da2899SCharles.Forsyth for ( n = 1; n < num_designs; n++ ) 170*37da2899SCharles.Forsyth blend->design_pos[n] = blend->design_pos[0] + num_axis * n; 171*37da2899SCharles.Forsyth } 172*37da2899SCharles.Forsyth 173*37da2899SCharles.Forsyth Exit: 174*37da2899SCharles.Forsyth return error; 175*37da2899SCharles.Forsyth 176*37da2899SCharles.Forsyth Fail: 177*37da2899SCharles.Forsyth error = -1; 178*37da2899SCharles.Forsyth goto Exit; 179*37da2899SCharles.Forsyth } 180*37da2899SCharles.Forsyth 181*37da2899SCharles.Forsyth 182*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) T1_Get_Multi_Master(T1_Face face,FT_Multi_Master * master)183*37da2899SCharles.Forsyth T1_Get_Multi_Master( T1_Face face, 184*37da2899SCharles.Forsyth FT_Multi_Master* master ) 185*37da2899SCharles.Forsyth { 186*37da2899SCharles.Forsyth PS_Blend blend = face->blend; 187*37da2899SCharles.Forsyth FT_UInt n; 188*37da2899SCharles.Forsyth FT_Error error; 189*37da2899SCharles.Forsyth 190*37da2899SCharles.Forsyth 191*37da2899SCharles.Forsyth error = T1_Err_Invalid_Argument; 192*37da2899SCharles.Forsyth 193*37da2899SCharles.Forsyth if ( blend ) 194*37da2899SCharles.Forsyth { 195*37da2899SCharles.Forsyth master->num_axis = blend->num_axis; 196*37da2899SCharles.Forsyth master->num_designs = blend->num_designs; 197*37da2899SCharles.Forsyth 198*37da2899SCharles.Forsyth for ( n = 0; n < blend->num_axis; n++ ) 199*37da2899SCharles.Forsyth { 200*37da2899SCharles.Forsyth FT_MM_Axis* axis = master->axis + n; 201*37da2899SCharles.Forsyth PS_DesignMap map = blend->design_map + n; 202*37da2899SCharles.Forsyth 203*37da2899SCharles.Forsyth 204*37da2899SCharles.Forsyth axis->name = blend->axis_names[n]; 205*37da2899SCharles.Forsyth axis->minimum = map->design_points[0]; 206*37da2899SCharles.Forsyth axis->maximum = map->design_points[map->num_points - 1]; 207*37da2899SCharles.Forsyth } 208*37da2899SCharles.Forsyth error = 0; 209*37da2899SCharles.Forsyth } 210*37da2899SCharles.Forsyth return error; 211*37da2899SCharles.Forsyth } 212*37da2899SCharles.Forsyth 213*37da2899SCharles.Forsyth 214*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) T1_Set_MM_Blend(T1_Face face,FT_UInt num_coords,FT_Fixed * coords)215*37da2899SCharles.Forsyth T1_Set_MM_Blend( T1_Face face, 216*37da2899SCharles.Forsyth FT_UInt num_coords, 217*37da2899SCharles.Forsyth FT_Fixed* coords ) 218*37da2899SCharles.Forsyth { 219*37da2899SCharles.Forsyth PS_Blend blend = face->blend; 220*37da2899SCharles.Forsyth FT_Error error; 221*37da2899SCharles.Forsyth FT_UInt n, m; 222*37da2899SCharles.Forsyth 223*37da2899SCharles.Forsyth 224*37da2899SCharles.Forsyth error = T1_Err_Invalid_Argument; 225*37da2899SCharles.Forsyth 226*37da2899SCharles.Forsyth if ( blend && blend->num_axis == num_coords ) 227*37da2899SCharles.Forsyth { 228*37da2899SCharles.Forsyth /* recompute the weight vector from the blend coordinates */ 229*37da2899SCharles.Forsyth error = T1_Err_Ok; 230*37da2899SCharles.Forsyth 231*37da2899SCharles.Forsyth for ( n = 0; n < blend->num_designs; n++ ) 232*37da2899SCharles.Forsyth { 233*37da2899SCharles.Forsyth FT_Fixed result = 0x10000L; /* 1.0 fixed */ 234*37da2899SCharles.Forsyth 235*37da2899SCharles.Forsyth 236*37da2899SCharles.Forsyth for ( m = 0; m < blend->num_axis; m++ ) 237*37da2899SCharles.Forsyth { 238*37da2899SCharles.Forsyth FT_Fixed factor; 239*37da2899SCharles.Forsyth 240*37da2899SCharles.Forsyth 241*37da2899SCharles.Forsyth /* get current blend axis position */ 242*37da2899SCharles.Forsyth factor = coords[m]; 243*37da2899SCharles.Forsyth if ( factor < 0 ) factor = 0; 244*37da2899SCharles.Forsyth if ( factor > 0x10000L ) factor = 0x10000L; 245*37da2899SCharles.Forsyth 246*37da2899SCharles.Forsyth if ( ( n & ( 1 << m ) ) == 0 ) 247*37da2899SCharles.Forsyth factor = 0x10000L - factor; 248*37da2899SCharles.Forsyth 249*37da2899SCharles.Forsyth result = FT_MulFix( result, factor ); 250*37da2899SCharles.Forsyth } 251*37da2899SCharles.Forsyth blend->weight_vector[n] = result; 252*37da2899SCharles.Forsyth } 253*37da2899SCharles.Forsyth 254*37da2899SCharles.Forsyth error = T1_Err_Ok; 255*37da2899SCharles.Forsyth } 256*37da2899SCharles.Forsyth return error; 257*37da2899SCharles.Forsyth } 258*37da2899SCharles.Forsyth 259*37da2899SCharles.Forsyth 260*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) T1_Set_MM_Design(T1_Face face,FT_UInt num_coords,FT_Long * coords)261*37da2899SCharles.Forsyth T1_Set_MM_Design( T1_Face face, 262*37da2899SCharles.Forsyth FT_UInt num_coords, 263*37da2899SCharles.Forsyth FT_Long* coords ) 264*37da2899SCharles.Forsyth { 265*37da2899SCharles.Forsyth PS_Blend blend = face->blend; 266*37da2899SCharles.Forsyth FT_Error error; 267*37da2899SCharles.Forsyth FT_UInt n, p; 268*37da2899SCharles.Forsyth 269*37da2899SCharles.Forsyth 270*37da2899SCharles.Forsyth error = T1_Err_Invalid_Argument; 271*37da2899SCharles.Forsyth if ( blend && blend->num_axis == num_coords ) 272*37da2899SCharles.Forsyth { 273*37da2899SCharles.Forsyth /* compute the blend coordinates through the blend design map */ 274*37da2899SCharles.Forsyth FT_Fixed final_blends[T1_MAX_MM_DESIGNS]; 275*37da2899SCharles.Forsyth 276*37da2899SCharles.Forsyth 277*37da2899SCharles.Forsyth for ( n = 0; n < blend->num_axis; n++ ) 278*37da2899SCharles.Forsyth { 279*37da2899SCharles.Forsyth FT_Long design = coords[n]; 280*37da2899SCharles.Forsyth FT_Fixed the_blend; 281*37da2899SCharles.Forsyth PS_DesignMap map = blend->design_map + n; 282*37da2899SCharles.Forsyth FT_Fixed* designs = map->design_points; 283*37da2899SCharles.Forsyth FT_Fixed* blends = map->blend_points; 284*37da2899SCharles.Forsyth FT_Int before = -1, after = -1; 285*37da2899SCharles.Forsyth 286*37da2899SCharles.Forsyth 287*37da2899SCharles.Forsyth for ( p = 0; p < (FT_UInt)map->num_points; p++ ) 288*37da2899SCharles.Forsyth { 289*37da2899SCharles.Forsyth FT_Fixed p_design = designs[p]; 290*37da2899SCharles.Forsyth 291*37da2899SCharles.Forsyth 292*37da2899SCharles.Forsyth /* exact match ? */ 293*37da2899SCharles.Forsyth if ( design == p_design ) 294*37da2899SCharles.Forsyth { 295*37da2899SCharles.Forsyth the_blend = blends[p]; 296*37da2899SCharles.Forsyth goto Found; 297*37da2899SCharles.Forsyth } 298*37da2899SCharles.Forsyth 299*37da2899SCharles.Forsyth if ( design < p_design ) 300*37da2899SCharles.Forsyth { 301*37da2899SCharles.Forsyth after = p; 302*37da2899SCharles.Forsyth break; 303*37da2899SCharles.Forsyth } 304*37da2899SCharles.Forsyth 305*37da2899SCharles.Forsyth before = p; 306*37da2899SCharles.Forsyth } 307*37da2899SCharles.Forsyth 308*37da2899SCharles.Forsyth /* now, interpolate if needed */ 309*37da2899SCharles.Forsyth if ( before < 0 ) 310*37da2899SCharles.Forsyth the_blend = blends[0]; 311*37da2899SCharles.Forsyth 312*37da2899SCharles.Forsyth else if ( after < 0 ) 313*37da2899SCharles.Forsyth the_blend = blends[map->num_points - 1]; 314*37da2899SCharles.Forsyth 315*37da2899SCharles.Forsyth else 316*37da2899SCharles.Forsyth the_blend = FT_MulDiv( design - designs[before], 317*37da2899SCharles.Forsyth blends [after] - blends [before], 318*37da2899SCharles.Forsyth designs[after] - designs[before] ); 319*37da2899SCharles.Forsyth 320*37da2899SCharles.Forsyth Found: 321*37da2899SCharles.Forsyth final_blends[n] = the_blend; 322*37da2899SCharles.Forsyth } 323*37da2899SCharles.Forsyth 324*37da2899SCharles.Forsyth error = T1_Set_MM_Blend( face, num_coords, final_blends ); 325*37da2899SCharles.Forsyth } 326*37da2899SCharles.Forsyth 327*37da2899SCharles.Forsyth return error; 328*37da2899SCharles.Forsyth } 329*37da2899SCharles.Forsyth 330*37da2899SCharles.Forsyth 331*37da2899SCharles.Forsyth FT_LOCAL_DEF( void ) T1_Done_Blend(T1_Face face)332*37da2899SCharles.Forsyth T1_Done_Blend( T1_Face face ) 333*37da2899SCharles.Forsyth { 334*37da2899SCharles.Forsyth FT_Memory memory = face->root.memory; 335*37da2899SCharles.Forsyth PS_Blend blend = face->blend; 336*37da2899SCharles.Forsyth 337*37da2899SCharles.Forsyth 338*37da2899SCharles.Forsyth if ( blend ) 339*37da2899SCharles.Forsyth { 340*37da2899SCharles.Forsyth FT_UInt num_designs = blend->num_designs; 341*37da2899SCharles.Forsyth FT_UInt num_axis = blend->num_axis; 342*37da2899SCharles.Forsyth FT_UInt n; 343*37da2899SCharles.Forsyth 344*37da2899SCharles.Forsyth 345*37da2899SCharles.Forsyth /* release design pos table */ 346*37da2899SCharles.Forsyth FT_FREE( blend->design_pos[0] ); 347*37da2899SCharles.Forsyth for ( n = 1; n < num_designs; n++ ) 348*37da2899SCharles.Forsyth blend->design_pos[n] = 0; 349*37da2899SCharles.Forsyth 350*37da2899SCharles.Forsyth /* release blend `private' and `font info' dictionaries */ 351*37da2899SCharles.Forsyth FT_FREE( blend->privates[1] ); 352*37da2899SCharles.Forsyth FT_FREE( blend->font_infos[1] ); 353*37da2899SCharles.Forsyth FT_FREE( blend->bboxes[1] ); 354*37da2899SCharles.Forsyth 355*37da2899SCharles.Forsyth for ( n = 0; n < num_designs; n++ ) 356*37da2899SCharles.Forsyth { 357*37da2899SCharles.Forsyth blend->privates [n] = 0; 358*37da2899SCharles.Forsyth blend->font_infos[n] = 0; 359*37da2899SCharles.Forsyth blend->bboxes [n] = 0; 360*37da2899SCharles.Forsyth } 361*37da2899SCharles.Forsyth 362*37da2899SCharles.Forsyth /* release weight vectors */ 363*37da2899SCharles.Forsyth FT_FREE( blend->weight_vector ); 364*37da2899SCharles.Forsyth blend->default_weight_vector = 0; 365*37da2899SCharles.Forsyth 366*37da2899SCharles.Forsyth /* release axis names */ 367*37da2899SCharles.Forsyth for ( n = 0; n < num_axis; n++ ) 368*37da2899SCharles.Forsyth FT_FREE( blend->axis_names[n] ); 369*37da2899SCharles.Forsyth 370*37da2899SCharles.Forsyth /* release design map */ 371*37da2899SCharles.Forsyth for ( n = 0; n < num_axis; n++ ) 372*37da2899SCharles.Forsyth { 373*37da2899SCharles.Forsyth PS_DesignMap dmap = blend->design_map + n; 374*37da2899SCharles.Forsyth 375*37da2899SCharles.Forsyth 376*37da2899SCharles.Forsyth FT_FREE( dmap->design_points ); 377*37da2899SCharles.Forsyth dmap->num_points = 0; 378*37da2899SCharles.Forsyth } 379*37da2899SCharles.Forsyth 380*37da2899SCharles.Forsyth FT_FREE( face->blend ); 381*37da2899SCharles.Forsyth } 382*37da2899SCharles.Forsyth } 383*37da2899SCharles.Forsyth 384*37da2899SCharles.Forsyth 385*37da2899SCharles.Forsyth static void parse_blend_axis_types(T1_Face face,T1_Loader loader)386*37da2899SCharles.Forsyth parse_blend_axis_types( T1_Face face, 387*37da2899SCharles.Forsyth T1_Loader loader ) 388*37da2899SCharles.Forsyth { 389*37da2899SCharles.Forsyth T1_TokenRec axis_tokens[ T1_MAX_MM_AXIS ]; 390*37da2899SCharles.Forsyth FT_Int n, num_axis; 391*37da2899SCharles.Forsyth FT_Error error = 0; 392*37da2899SCharles.Forsyth PS_Blend blend; 393*37da2899SCharles.Forsyth FT_Memory memory; 394*37da2899SCharles.Forsyth 395*37da2899SCharles.Forsyth 396*37da2899SCharles.Forsyth /* take an array of objects */ 397*37da2899SCharles.Forsyth T1_ToTokenArray( &loader->parser, axis_tokens, 398*37da2899SCharles.Forsyth T1_MAX_MM_AXIS, &num_axis ); 399*37da2899SCharles.Forsyth if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS ) 400*37da2899SCharles.Forsyth { 401*37da2899SCharles.Forsyth FT_ERROR(( "parse_blend_axis_types: incorrect number of axes: %d\n", 402*37da2899SCharles.Forsyth num_axis )); 403*37da2899SCharles.Forsyth error = T1_Err_Invalid_File_Format; 404*37da2899SCharles.Forsyth goto Exit; 405*37da2899SCharles.Forsyth } 406*37da2899SCharles.Forsyth 407*37da2899SCharles.Forsyth /* allocate blend if necessary */ 408*37da2899SCharles.Forsyth error = t1_allocate_blend( face, 0, (FT_UInt)num_axis ); 409*37da2899SCharles.Forsyth if ( error ) 410*37da2899SCharles.Forsyth goto Exit; 411*37da2899SCharles.Forsyth 412*37da2899SCharles.Forsyth blend = face->blend; 413*37da2899SCharles.Forsyth memory = face->root.memory; 414*37da2899SCharles.Forsyth 415*37da2899SCharles.Forsyth /* each token is an immediate containing the name of the axis */ 416*37da2899SCharles.Forsyth for ( n = 0; n < num_axis; n++ ) 417*37da2899SCharles.Forsyth { 418*37da2899SCharles.Forsyth T1_Token token = axis_tokens + n; 419*37da2899SCharles.Forsyth FT_Byte* name; 420*37da2899SCharles.Forsyth FT_PtrDist len; 421*37da2899SCharles.Forsyth 422*37da2899SCharles.Forsyth 423*37da2899SCharles.Forsyth /* skip first slash, if any */ 424*37da2899SCharles.Forsyth if ( token->start[0] == '/' ) 425*37da2899SCharles.Forsyth token->start++; 426*37da2899SCharles.Forsyth 427*37da2899SCharles.Forsyth len = token->limit - token->start; 428*37da2899SCharles.Forsyth if ( len <= 0 ) 429*37da2899SCharles.Forsyth { 430*37da2899SCharles.Forsyth error = T1_Err_Invalid_File_Format; 431*37da2899SCharles.Forsyth goto Exit; 432*37da2899SCharles.Forsyth } 433*37da2899SCharles.Forsyth 434*37da2899SCharles.Forsyth if ( FT_ALLOC( blend->axis_names[n], len + 1 ) ) 435*37da2899SCharles.Forsyth goto Exit; 436*37da2899SCharles.Forsyth 437*37da2899SCharles.Forsyth name = (FT_Byte*)blend->axis_names[n]; 438*37da2899SCharles.Forsyth FT_MEM_COPY( name, token->start, len ); 439*37da2899SCharles.Forsyth name[len] = 0; 440*37da2899SCharles.Forsyth } 441*37da2899SCharles.Forsyth 442*37da2899SCharles.Forsyth Exit: 443*37da2899SCharles.Forsyth loader->parser.root.error = error; 444*37da2899SCharles.Forsyth } 445*37da2899SCharles.Forsyth 446*37da2899SCharles.Forsyth 447*37da2899SCharles.Forsyth static void parse_blend_design_positions(T1_Face face,T1_Loader loader)448*37da2899SCharles.Forsyth parse_blend_design_positions( T1_Face face, 449*37da2899SCharles.Forsyth T1_Loader loader ) 450*37da2899SCharles.Forsyth { 451*37da2899SCharles.Forsyth T1_TokenRec design_tokens[ T1_MAX_MM_DESIGNS ]; 452*37da2899SCharles.Forsyth FT_Int num_designs; 453*37da2899SCharles.Forsyth FT_Int num_axis; 454*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 455*37da2899SCharles.Forsyth 456*37da2899SCharles.Forsyth FT_Error error = 0; 457*37da2899SCharles.Forsyth PS_Blend blend; 458*37da2899SCharles.Forsyth 459*37da2899SCharles.Forsyth 460*37da2899SCharles.Forsyth /* get the array of design tokens - compute number of designs */ 461*37da2899SCharles.Forsyth T1_ToTokenArray( parser, design_tokens, T1_MAX_MM_DESIGNS, &num_designs ); 462*37da2899SCharles.Forsyth if ( num_designs <= 0 || num_designs > T1_MAX_MM_DESIGNS ) 463*37da2899SCharles.Forsyth { 464*37da2899SCharles.Forsyth FT_ERROR(( "parse_blend_design_positions:" )); 465*37da2899SCharles.Forsyth FT_ERROR(( " incorrect number of designs: %d\n", 466*37da2899SCharles.Forsyth num_designs )); 467*37da2899SCharles.Forsyth error = T1_Err_Invalid_File_Format; 468*37da2899SCharles.Forsyth goto Exit; 469*37da2899SCharles.Forsyth } 470*37da2899SCharles.Forsyth 471*37da2899SCharles.Forsyth { 472*37da2899SCharles.Forsyth FT_Byte* old_cursor = parser->root.cursor; 473*37da2899SCharles.Forsyth FT_Byte* old_limit = parser->root.limit; 474*37da2899SCharles.Forsyth FT_UInt n; 475*37da2899SCharles.Forsyth 476*37da2899SCharles.Forsyth 477*37da2899SCharles.Forsyth blend = face->blend; 478*37da2899SCharles.Forsyth num_axis = 0; /* make compiler happy */ 479*37da2899SCharles.Forsyth 480*37da2899SCharles.Forsyth for ( n = 0; n < (FT_UInt)num_designs; n++ ) 481*37da2899SCharles.Forsyth { 482*37da2899SCharles.Forsyth T1_TokenRec axis_tokens[ T1_MAX_MM_DESIGNS ]; 483*37da2899SCharles.Forsyth T1_Token token; 484*37da2899SCharles.Forsyth FT_Int axis, n_axis; 485*37da2899SCharles.Forsyth 486*37da2899SCharles.Forsyth 487*37da2899SCharles.Forsyth /* read axis/coordinates tokens */ 488*37da2899SCharles.Forsyth token = design_tokens + n; 489*37da2899SCharles.Forsyth parser->root.cursor = token->start - 1; 490*37da2899SCharles.Forsyth parser->root.limit = token->limit + 1; 491*37da2899SCharles.Forsyth T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &n_axis ); 492*37da2899SCharles.Forsyth 493*37da2899SCharles.Forsyth if ( n == 0 ) 494*37da2899SCharles.Forsyth { 495*37da2899SCharles.Forsyth num_axis = n_axis; 496*37da2899SCharles.Forsyth error = t1_allocate_blend( face, num_designs, num_axis ); 497*37da2899SCharles.Forsyth if ( error ) 498*37da2899SCharles.Forsyth goto Exit; 499*37da2899SCharles.Forsyth blend = face->blend; 500*37da2899SCharles.Forsyth } 501*37da2899SCharles.Forsyth else if ( n_axis != num_axis ) 502*37da2899SCharles.Forsyth { 503*37da2899SCharles.Forsyth FT_ERROR(( "parse_blend_design_positions: incorrect table\n" )); 504*37da2899SCharles.Forsyth error = T1_Err_Invalid_File_Format; 505*37da2899SCharles.Forsyth goto Exit; 506*37da2899SCharles.Forsyth } 507*37da2899SCharles.Forsyth 508*37da2899SCharles.Forsyth /* now, read each axis token into the design position */ 509*37da2899SCharles.Forsyth for ( axis = 0; axis < n_axis; axis++ ) 510*37da2899SCharles.Forsyth { 511*37da2899SCharles.Forsyth T1_Token token2 = axis_tokens + axis; 512*37da2899SCharles.Forsyth 513*37da2899SCharles.Forsyth 514*37da2899SCharles.Forsyth parser->root.cursor = token2->start; 515*37da2899SCharles.Forsyth parser->root.limit = token2->limit; 516*37da2899SCharles.Forsyth blend->design_pos[n][axis] = T1_ToFixed( parser, 0 ); 517*37da2899SCharles.Forsyth } 518*37da2899SCharles.Forsyth } 519*37da2899SCharles.Forsyth 520*37da2899SCharles.Forsyth loader->parser.root.cursor = old_cursor; 521*37da2899SCharles.Forsyth loader->parser.root.limit = old_limit; 522*37da2899SCharles.Forsyth } 523*37da2899SCharles.Forsyth 524*37da2899SCharles.Forsyth Exit: 525*37da2899SCharles.Forsyth loader->parser.root.error = error; 526*37da2899SCharles.Forsyth } 527*37da2899SCharles.Forsyth 528*37da2899SCharles.Forsyth 529*37da2899SCharles.Forsyth static void parse_blend_design_map(T1_Face face,T1_Loader loader)530*37da2899SCharles.Forsyth parse_blend_design_map( T1_Face face, 531*37da2899SCharles.Forsyth T1_Loader loader ) 532*37da2899SCharles.Forsyth { 533*37da2899SCharles.Forsyth FT_Error error = 0; 534*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 535*37da2899SCharles.Forsyth PS_Blend blend; 536*37da2899SCharles.Forsyth T1_TokenRec axis_tokens[T1_MAX_MM_AXIS]; 537*37da2899SCharles.Forsyth FT_Int n, num_axis; 538*37da2899SCharles.Forsyth FT_Byte* old_cursor; 539*37da2899SCharles.Forsyth FT_Byte* old_limit; 540*37da2899SCharles.Forsyth FT_Memory memory = face->root.memory; 541*37da2899SCharles.Forsyth 542*37da2899SCharles.Forsyth 543*37da2899SCharles.Forsyth T1_ToTokenArray( parser, axis_tokens, T1_MAX_MM_AXIS, &num_axis ); 544*37da2899SCharles.Forsyth if ( num_axis <= 0 || num_axis > T1_MAX_MM_AXIS ) 545*37da2899SCharles.Forsyth { 546*37da2899SCharles.Forsyth FT_ERROR(( "parse_blend_design_map: incorrect number of axes: %d\n", 547*37da2899SCharles.Forsyth num_axis )); 548*37da2899SCharles.Forsyth error = T1_Err_Invalid_File_Format; 549*37da2899SCharles.Forsyth goto Exit; 550*37da2899SCharles.Forsyth } 551*37da2899SCharles.Forsyth old_cursor = parser->root.cursor; 552*37da2899SCharles.Forsyth old_limit = parser->root.limit; 553*37da2899SCharles.Forsyth 554*37da2899SCharles.Forsyth error = t1_allocate_blend( face, 0, num_axis ); 555*37da2899SCharles.Forsyth if ( error ) 556*37da2899SCharles.Forsyth goto Exit; 557*37da2899SCharles.Forsyth blend = face->blend; 558*37da2899SCharles.Forsyth 559*37da2899SCharles.Forsyth /* now, read each axis design map */ 560*37da2899SCharles.Forsyth for ( n = 0; n < num_axis; n++ ) 561*37da2899SCharles.Forsyth { 562*37da2899SCharles.Forsyth PS_DesignMap map = blend->design_map + n; 563*37da2899SCharles.Forsyth T1_Token token; 564*37da2899SCharles.Forsyth FT_Int p, num_points; 565*37da2899SCharles.Forsyth 566*37da2899SCharles.Forsyth 567*37da2899SCharles.Forsyth token = axis_tokens + n; 568*37da2899SCharles.Forsyth parser->root.cursor = token->start; 569*37da2899SCharles.Forsyth parser->root.limit = token->limit; 570*37da2899SCharles.Forsyth 571*37da2899SCharles.Forsyth /* count the number of map points */ 572*37da2899SCharles.Forsyth { 573*37da2899SCharles.Forsyth FT_Byte* ptr = token->start; 574*37da2899SCharles.Forsyth FT_Byte* limit = token->limit; 575*37da2899SCharles.Forsyth 576*37da2899SCharles.Forsyth 577*37da2899SCharles.Forsyth num_points = 0; 578*37da2899SCharles.Forsyth for ( ; ptr < limit; ptr++ ) 579*37da2899SCharles.Forsyth if ( ptr[0] == '[' ) 580*37da2899SCharles.Forsyth num_points++; 581*37da2899SCharles.Forsyth } 582*37da2899SCharles.Forsyth if ( num_points <= 0 || num_points > T1_MAX_MM_MAP_POINTS ) 583*37da2899SCharles.Forsyth { 584*37da2899SCharles.Forsyth FT_ERROR(( "parse_blend_design_map: incorrect table\n" )); 585*37da2899SCharles.Forsyth error = T1_Err_Invalid_File_Format; 586*37da2899SCharles.Forsyth goto Exit; 587*37da2899SCharles.Forsyth } 588*37da2899SCharles.Forsyth 589*37da2899SCharles.Forsyth /* allocate design map data */ 590*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( map->design_points, num_points * 2 ) ) 591*37da2899SCharles.Forsyth goto Exit; 592*37da2899SCharles.Forsyth map->blend_points = map->design_points + num_points; 593*37da2899SCharles.Forsyth map->num_points = (FT_Byte)num_points; 594*37da2899SCharles.Forsyth 595*37da2899SCharles.Forsyth for ( p = 0; p < num_points; p++ ) 596*37da2899SCharles.Forsyth { 597*37da2899SCharles.Forsyth map->design_points[p] = T1_ToInt( parser ); 598*37da2899SCharles.Forsyth map->blend_points [p] = T1_ToFixed( parser, 0 ); 599*37da2899SCharles.Forsyth } 600*37da2899SCharles.Forsyth } 601*37da2899SCharles.Forsyth 602*37da2899SCharles.Forsyth parser->root.cursor = old_cursor; 603*37da2899SCharles.Forsyth parser->root.limit = old_limit; 604*37da2899SCharles.Forsyth 605*37da2899SCharles.Forsyth Exit: 606*37da2899SCharles.Forsyth parser->root.error = error; 607*37da2899SCharles.Forsyth } 608*37da2899SCharles.Forsyth 609*37da2899SCharles.Forsyth 610*37da2899SCharles.Forsyth static void parse_weight_vector(T1_Face face,T1_Loader loader)611*37da2899SCharles.Forsyth parse_weight_vector( T1_Face face, 612*37da2899SCharles.Forsyth T1_Loader loader ) 613*37da2899SCharles.Forsyth { 614*37da2899SCharles.Forsyth FT_Error error = 0; 615*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 616*37da2899SCharles.Forsyth PS_Blend blend = face->blend; 617*37da2899SCharles.Forsyth T1_TokenRec master; 618*37da2899SCharles.Forsyth FT_UInt n; 619*37da2899SCharles.Forsyth FT_Byte* old_cursor; 620*37da2899SCharles.Forsyth FT_Byte* old_limit; 621*37da2899SCharles.Forsyth 622*37da2899SCharles.Forsyth 623*37da2899SCharles.Forsyth if ( !blend || blend->num_designs == 0 ) 624*37da2899SCharles.Forsyth { 625*37da2899SCharles.Forsyth FT_ERROR(( "parse_weight_vector: too early!\n" )); 626*37da2899SCharles.Forsyth error = T1_Err_Invalid_File_Format; 627*37da2899SCharles.Forsyth goto Exit; 628*37da2899SCharles.Forsyth } 629*37da2899SCharles.Forsyth 630*37da2899SCharles.Forsyth T1_ToToken( parser, &master ); 631*37da2899SCharles.Forsyth if ( master.type != T1_TOKEN_TYPE_ARRAY ) 632*37da2899SCharles.Forsyth { 633*37da2899SCharles.Forsyth FT_ERROR(( "parse_weight_vector: incorrect format!\n" )); 634*37da2899SCharles.Forsyth error = T1_Err_Invalid_File_Format; 635*37da2899SCharles.Forsyth goto Exit; 636*37da2899SCharles.Forsyth } 637*37da2899SCharles.Forsyth 638*37da2899SCharles.Forsyth old_cursor = parser->root.cursor; 639*37da2899SCharles.Forsyth old_limit = parser->root.limit; 640*37da2899SCharles.Forsyth 641*37da2899SCharles.Forsyth parser->root.cursor = master.start; 642*37da2899SCharles.Forsyth parser->root.limit = master.limit; 643*37da2899SCharles.Forsyth 644*37da2899SCharles.Forsyth for ( n = 0; n < blend->num_designs; n++ ) 645*37da2899SCharles.Forsyth { 646*37da2899SCharles.Forsyth blend->default_weight_vector[n] = 647*37da2899SCharles.Forsyth blend->weight_vector[n] = T1_ToFixed( parser, 0 ); 648*37da2899SCharles.Forsyth } 649*37da2899SCharles.Forsyth 650*37da2899SCharles.Forsyth parser->root.cursor = old_cursor; 651*37da2899SCharles.Forsyth parser->root.limit = old_limit; 652*37da2899SCharles.Forsyth 653*37da2899SCharles.Forsyth Exit: 654*37da2899SCharles.Forsyth parser->root.error = error; 655*37da2899SCharles.Forsyth } 656*37da2899SCharles.Forsyth 657*37da2899SCharles.Forsyth 658*37da2899SCharles.Forsyth /* the keyword `/shareddict' appears in some multiple master fonts */ 659*37da2899SCharles.Forsyth /* with a lot of Postscript garbage behind it (that's completely out */ 660*37da2899SCharles.Forsyth /* of spec!); we detect it and terminate the parsing */ 661*37da2899SCharles.Forsyth /* */ 662*37da2899SCharles.Forsyth static void parse_shared_dict(T1_Face face,T1_Loader loader)663*37da2899SCharles.Forsyth parse_shared_dict( T1_Face face, 664*37da2899SCharles.Forsyth T1_Loader loader ) 665*37da2899SCharles.Forsyth { 666*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 667*37da2899SCharles.Forsyth 668*37da2899SCharles.Forsyth FT_UNUSED( face ); 669*37da2899SCharles.Forsyth 670*37da2899SCharles.Forsyth 671*37da2899SCharles.Forsyth parser->root.cursor = parser->root.limit; 672*37da2899SCharles.Forsyth parser->root.error = 0; 673*37da2899SCharles.Forsyth } 674*37da2899SCharles.Forsyth 675*37da2899SCharles.Forsyth #endif /* T1_CONFIG_OPTION_NO_MM_SUPPORT */ 676*37da2899SCharles.Forsyth 677*37da2899SCharles.Forsyth 678*37da2899SCharles.Forsyth /*************************************************************************/ 679*37da2899SCharles.Forsyth /*************************************************************************/ 680*37da2899SCharles.Forsyth /***** *****/ 681*37da2899SCharles.Forsyth /***** TYPE 1 SYMBOL PARSING *****/ 682*37da2899SCharles.Forsyth /***** *****/ 683*37da2899SCharles.Forsyth /*************************************************************************/ 684*37da2899SCharles.Forsyth /*************************************************************************/ 685*37da2899SCharles.Forsyth 686*37da2899SCharles.Forsyth 687*37da2899SCharles.Forsyth /*************************************************************************/ 688*37da2899SCharles.Forsyth /* */ 689*37da2899SCharles.Forsyth /* First of all, define the token field static variables. This is a set */ 690*37da2899SCharles.Forsyth /* of T1_FieldRec variables used later. */ 691*37da2899SCharles.Forsyth /* */ 692*37da2899SCharles.Forsyth /*************************************************************************/ 693*37da2899SCharles.Forsyth 694*37da2899SCharles.Forsyth 695*37da2899SCharles.Forsyth static FT_Error t1_load_keyword(T1_Face face,T1_Loader loader,T1_Field field)696*37da2899SCharles.Forsyth t1_load_keyword( T1_Face face, 697*37da2899SCharles.Forsyth T1_Loader loader, 698*37da2899SCharles.Forsyth T1_Field field ) 699*37da2899SCharles.Forsyth { 700*37da2899SCharles.Forsyth FT_Error error; 701*37da2899SCharles.Forsyth void* dummy_object; 702*37da2899SCharles.Forsyth void** objects; 703*37da2899SCharles.Forsyth FT_UInt max_objects; 704*37da2899SCharles.Forsyth PS_Blend blend = face->blend; 705*37da2899SCharles.Forsyth 706*37da2899SCharles.Forsyth 707*37da2899SCharles.Forsyth /* if the keyword has a dedicated callback, call it */ 708*37da2899SCharles.Forsyth if ( field->type == T1_FIELD_TYPE_CALLBACK ) 709*37da2899SCharles.Forsyth { 710*37da2899SCharles.Forsyth field->reader( (FT_Face)face, loader ); 711*37da2899SCharles.Forsyth error = loader->parser.root.error; 712*37da2899SCharles.Forsyth goto Exit; 713*37da2899SCharles.Forsyth } 714*37da2899SCharles.Forsyth 715*37da2899SCharles.Forsyth /* now, the keyword is either a simple field, or a table of fields; */ 716*37da2899SCharles.Forsyth /* we are now going to take care of it */ 717*37da2899SCharles.Forsyth switch ( field->location ) 718*37da2899SCharles.Forsyth { 719*37da2899SCharles.Forsyth case T1_FIELD_LOCATION_FONT_INFO: 720*37da2899SCharles.Forsyth dummy_object = &face->type1.font_info; 721*37da2899SCharles.Forsyth objects = &dummy_object; 722*37da2899SCharles.Forsyth max_objects = 0; 723*37da2899SCharles.Forsyth 724*37da2899SCharles.Forsyth if ( blend ) 725*37da2899SCharles.Forsyth { 726*37da2899SCharles.Forsyth objects = (void**)blend->font_infos; 727*37da2899SCharles.Forsyth max_objects = blend->num_designs; 728*37da2899SCharles.Forsyth } 729*37da2899SCharles.Forsyth break; 730*37da2899SCharles.Forsyth 731*37da2899SCharles.Forsyth case T1_FIELD_LOCATION_PRIVATE: 732*37da2899SCharles.Forsyth dummy_object = &face->type1.private_dict; 733*37da2899SCharles.Forsyth objects = &dummy_object; 734*37da2899SCharles.Forsyth max_objects = 0; 735*37da2899SCharles.Forsyth 736*37da2899SCharles.Forsyth if ( blend ) 737*37da2899SCharles.Forsyth { 738*37da2899SCharles.Forsyth objects = (void**)blend->privates; 739*37da2899SCharles.Forsyth max_objects = blend->num_designs; 740*37da2899SCharles.Forsyth } 741*37da2899SCharles.Forsyth break; 742*37da2899SCharles.Forsyth 743*37da2899SCharles.Forsyth case T1_FIELD_LOCATION_BBOX: 744*37da2899SCharles.Forsyth dummy_object = &face->type1.font_bbox; 745*37da2899SCharles.Forsyth objects = &dummy_object; 746*37da2899SCharles.Forsyth max_objects = 0; 747*37da2899SCharles.Forsyth 748*37da2899SCharles.Forsyth if ( blend ) 749*37da2899SCharles.Forsyth { 750*37da2899SCharles.Forsyth objects = (void**)blend->bboxes; 751*37da2899SCharles.Forsyth max_objects = blend->num_designs; 752*37da2899SCharles.Forsyth } 753*37da2899SCharles.Forsyth break; 754*37da2899SCharles.Forsyth 755*37da2899SCharles.Forsyth default: 756*37da2899SCharles.Forsyth dummy_object = &face->type1; 757*37da2899SCharles.Forsyth objects = &dummy_object; 758*37da2899SCharles.Forsyth max_objects = 0; 759*37da2899SCharles.Forsyth } 760*37da2899SCharles.Forsyth 761*37da2899SCharles.Forsyth if ( field->type == T1_FIELD_TYPE_INTEGER_ARRAY || 762*37da2899SCharles.Forsyth field->type == T1_FIELD_TYPE_FIXED_ARRAY ) 763*37da2899SCharles.Forsyth error = T1_Load_Field_Table( &loader->parser, field, 764*37da2899SCharles.Forsyth objects, max_objects, 0 ); 765*37da2899SCharles.Forsyth else 766*37da2899SCharles.Forsyth error = T1_Load_Field( &loader->parser, field, 767*37da2899SCharles.Forsyth objects, max_objects, 0 ); 768*37da2899SCharles.Forsyth 769*37da2899SCharles.Forsyth Exit: 770*37da2899SCharles.Forsyth return error; 771*37da2899SCharles.Forsyth } 772*37da2899SCharles.Forsyth 773*37da2899SCharles.Forsyth 774*37da2899SCharles.Forsyth static int is_space(FT_Byte c)775*37da2899SCharles.Forsyth is_space( FT_Byte c ) 776*37da2899SCharles.Forsyth { 777*37da2899SCharles.Forsyth return ( c == ' ' || c == '\t' || c == '\r' || c == '\n' ); 778*37da2899SCharles.Forsyth } 779*37da2899SCharles.Forsyth 780*37da2899SCharles.Forsyth 781*37da2899SCharles.Forsyth static int is_alpha(FT_Byte c)782*37da2899SCharles.Forsyth is_alpha( FT_Byte c ) 783*37da2899SCharles.Forsyth { 784*37da2899SCharles.Forsyth /* Note: we must accept "+" as a valid character, as it is used in */ 785*37da2899SCharles.Forsyth /* embedded type1 fonts in PDF documents. */ 786*37da2899SCharles.Forsyth /* */ 787*37da2899SCharles.Forsyth return ( ft_isalnum( c ) || 788*37da2899SCharles.Forsyth c == '.' || 789*37da2899SCharles.Forsyth c == '_' || 790*37da2899SCharles.Forsyth c == '-' || 791*37da2899SCharles.Forsyth c == '+' ); 792*37da2899SCharles.Forsyth } 793*37da2899SCharles.Forsyth 794*37da2899SCharles.Forsyth 795*37da2899SCharles.Forsyth static int read_binary_data(T1_Parser parser,FT_Long * size,FT_Byte ** base)796*37da2899SCharles.Forsyth read_binary_data( T1_Parser parser, 797*37da2899SCharles.Forsyth FT_Long* size, 798*37da2899SCharles.Forsyth FT_Byte** base ) 799*37da2899SCharles.Forsyth { 800*37da2899SCharles.Forsyth FT_Byte* cur; 801*37da2899SCharles.Forsyth FT_Byte* limit = parser->root.limit; 802*37da2899SCharles.Forsyth 803*37da2899SCharles.Forsyth 804*37da2899SCharles.Forsyth /* the binary data has the following format */ 805*37da2899SCharles.Forsyth /* */ 806*37da2899SCharles.Forsyth /* `size' [white*] RD white ....... ND */ 807*37da2899SCharles.Forsyth /* */ 808*37da2899SCharles.Forsyth 809*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 810*37da2899SCharles.Forsyth cur = parser->root.cursor; 811*37da2899SCharles.Forsyth 812*37da2899SCharles.Forsyth if ( cur < limit && (FT_Byte)( *cur - '0' ) < 10 ) 813*37da2899SCharles.Forsyth { 814*37da2899SCharles.Forsyth *size = T1_ToInt( parser ); 815*37da2899SCharles.Forsyth 816*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 817*37da2899SCharles.Forsyth T1_Skip_Alpha ( parser ); /* `RD' or `-|' or something else */ 818*37da2899SCharles.Forsyth 819*37da2899SCharles.Forsyth /* there is only one whitespace char after the */ 820*37da2899SCharles.Forsyth /* `RD' or `-|' token */ 821*37da2899SCharles.Forsyth *base = parser->root.cursor + 1; 822*37da2899SCharles.Forsyth 823*37da2899SCharles.Forsyth parser->root.cursor += *size + 1; 824*37da2899SCharles.Forsyth return 1; 825*37da2899SCharles.Forsyth } 826*37da2899SCharles.Forsyth 827*37da2899SCharles.Forsyth FT_ERROR(( "read_binary_data: invalid size field\n" )); 828*37da2899SCharles.Forsyth parser->root.error = T1_Err_Invalid_File_Format; 829*37da2899SCharles.Forsyth return 0; 830*37da2899SCharles.Forsyth } 831*37da2899SCharles.Forsyth 832*37da2899SCharles.Forsyth 833*37da2899SCharles.Forsyth /* we will now define the routines used to handle */ 834*37da2899SCharles.Forsyth /* the `/Encoding', `/Subrs', and `/CharStrings' */ 835*37da2899SCharles.Forsyth /* dictionaries */ 836*37da2899SCharles.Forsyth 837*37da2899SCharles.Forsyth static void parse_font_name(T1_Face face,T1_Loader loader)838*37da2899SCharles.Forsyth parse_font_name( T1_Face face, 839*37da2899SCharles.Forsyth T1_Loader loader ) 840*37da2899SCharles.Forsyth { 841*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 842*37da2899SCharles.Forsyth FT_Error error; 843*37da2899SCharles.Forsyth FT_Memory memory = parser->root.memory; 844*37da2899SCharles.Forsyth FT_PtrDist len; 845*37da2899SCharles.Forsyth FT_Byte* cur; 846*37da2899SCharles.Forsyth FT_Byte* cur2; 847*37da2899SCharles.Forsyth FT_Byte* limit; 848*37da2899SCharles.Forsyth 849*37da2899SCharles.Forsyth 850*37da2899SCharles.Forsyth if ( face->type1.font_name ) 851*37da2899SCharles.Forsyth /* with synthetic fonts, it's possible we get here twice */ 852*37da2899SCharles.Forsyth return; 853*37da2899SCharles.Forsyth 854*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 855*37da2899SCharles.Forsyth 856*37da2899SCharles.Forsyth cur = parser->root.cursor; 857*37da2899SCharles.Forsyth limit = parser->root.limit; 858*37da2899SCharles.Forsyth 859*37da2899SCharles.Forsyth if ( cur >= limit - 1 || *cur != '/' ) 860*37da2899SCharles.Forsyth return; 861*37da2899SCharles.Forsyth 862*37da2899SCharles.Forsyth cur++; 863*37da2899SCharles.Forsyth cur2 = cur; 864*37da2899SCharles.Forsyth while ( cur2 < limit && is_alpha( *cur2 ) ) 865*37da2899SCharles.Forsyth cur2++; 866*37da2899SCharles.Forsyth 867*37da2899SCharles.Forsyth len = cur2 - cur; 868*37da2899SCharles.Forsyth if ( len > 0 ) 869*37da2899SCharles.Forsyth { 870*37da2899SCharles.Forsyth if ( FT_ALLOC( face->type1.font_name, len + 1 ) ) 871*37da2899SCharles.Forsyth { 872*37da2899SCharles.Forsyth parser->root.error = error; 873*37da2899SCharles.Forsyth return; 874*37da2899SCharles.Forsyth } 875*37da2899SCharles.Forsyth 876*37da2899SCharles.Forsyth FT_MEM_COPY( face->type1.font_name, cur, len ); 877*37da2899SCharles.Forsyth face->type1.font_name[len] = '\0'; 878*37da2899SCharles.Forsyth } 879*37da2899SCharles.Forsyth parser->root.cursor = cur2; 880*37da2899SCharles.Forsyth } 881*37da2899SCharles.Forsyth 882*37da2899SCharles.Forsyth 883*37da2899SCharles.Forsyth #if 0 884*37da2899SCharles.Forsyth static void 885*37da2899SCharles.Forsyth parse_font_bbox( T1_Face face, 886*37da2899SCharles.Forsyth T1_Loader loader ) 887*37da2899SCharles.Forsyth { 888*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 889*37da2899SCharles.Forsyth FT_Fixed temp[4]; 890*37da2899SCharles.Forsyth FT_BBox* bbox = &face->type1.font_bbox; 891*37da2899SCharles.Forsyth 892*37da2899SCharles.Forsyth 893*37da2899SCharles.Forsyth (void)T1_ToFixedArray( parser, 4, temp, 0 ); 894*37da2899SCharles.Forsyth bbox->xMin = FT_RoundFix( temp[0] ); 895*37da2899SCharles.Forsyth bbox->yMin = FT_RoundFix( temp[1] ); 896*37da2899SCharles.Forsyth bbox->xMax = FT_RoundFix( temp[2] ); 897*37da2899SCharles.Forsyth bbox->yMax = FT_RoundFix( temp[3] ); 898*37da2899SCharles.Forsyth } 899*37da2899SCharles.Forsyth #endif 900*37da2899SCharles.Forsyth 901*37da2899SCharles.Forsyth 902*37da2899SCharles.Forsyth static void parse_font_matrix(T1_Face face,T1_Loader loader)903*37da2899SCharles.Forsyth parse_font_matrix( T1_Face face, 904*37da2899SCharles.Forsyth T1_Loader loader ) 905*37da2899SCharles.Forsyth { 906*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 907*37da2899SCharles.Forsyth FT_Matrix* matrix = &face->type1.font_matrix; 908*37da2899SCharles.Forsyth FT_Vector* offset = &face->type1.font_offset; 909*37da2899SCharles.Forsyth FT_Face root = (FT_Face)&face->root; 910*37da2899SCharles.Forsyth FT_Fixed temp[6]; 911*37da2899SCharles.Forsyth FT_Fixed temp_scale; 912*37da2899SCharles.Forsyth 913*37da2899SCharles.Forsyth 914*37da2899SCharles.Forsyth if ( matrix->xx || matrix->yx ) 915*37da2899SCharles.Forsyth /* with synthetic fonts, it's possible we get here twice */ 916*37da2899SCharles.Forsyth return; 917*37da2899SCharles.Forsyth 918*37da2899SCharles.Forsyth (void)T1_ToFixedArray( parser, 6, temp, 3 ); 919*37da2899SCharles.Forsyth 920*37da2899SCharles.Forsyth temp_scale = ABS( temp[3] ); 921*37da2899SCharles.Forsyth 922*37da2899SCharles.Forsyth /* Set Units per EM based on FontMatrix values. We set the value to */ 923*37da2899SCharles.Forsyth /* 1000 / temp_scale, because temp_scale was already multiplied by */ 924*37da2899SCharles.Forsyth /* 1000 (in t1_tofixed, from psobjs.c). */ 925*37da2899SCharles.Forsyth 926*37da2899SCharles.Forsyth root->units_per_EM = (FT_UShort)( FT_DivFix( 1000 * 0x10000L, 927*37da2899SCharles.Forsyth temp_scale ) >> 16 ); 928*37da2899SCharles.Forsyth 929*37da2899SCharles.Forsyth /* we need to scale the values by 1.0/temp_scale */ 930*37da2899SCharles.Forsyth if ( temp_scale != 0x10000L ) 931*37da2899SCharles.Forsyth { 932*37da2899SCharles.Forsyth temp[0] = FT_DivFix( temp[0], temp_scale ); 933*37da2899SCharles.Forsyth temp[1] = FT_DivFix( temp[1], temp_scale ); 934*37da2899SCharles.Forsyth temp[2] = FT_DivFix( temp[2], temp_scale ); 935*37da2899SCharles.Forsyth temp[4] = FT_DivFix( temp[4], temp_scale ); 936*37da2899SCharles.Forsyth temp[5] = FT_DivFix( temp[5], temp_scale ); 937*37da2899SCharles.Forsyth temp[3] = 0x10000L; 938*37da2899SCharles.Forsyth } 939*37da2899SCharles.Forsyth 940*37da2899SCharles.Forsyth matrix->xx = temp[0]; 941*37da2899SCharles.Forsyth matrix->yx = temp[1]; 942*37da2899SCharles.Forsyth matrix->xy = temp[2]; 943*37da2899SCharles.Forsyth matrix->yy = temp[3]; 944*37da2899SCharles.Forsyth 945*37da2899SCharles.Forsyth /* note that the offsets must be expressed in integer font units */ 946*37da2899SCharles.Forsyth offset->x = temp[4] >> 16; 947*37da2899SCharles.Forsyth offset->y = temp[5] >> 16; 948*37da2899SCharles.Forsyth } 949*37da2899SCharles.Forsyth 950*37da2899SCharles.Forsyth 951*37da2899SCharles.Forsyth static void parse_encoding(T1_Face face,T1_Loader loader)952*37da2899SCharles.Forsyth parse_encoding( T1_Face face, 953*37da2899SCharles.Forsyth T1_Loader loader ) 954*37da2899SCharles.Forsyth { 955*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 956*37da2899SCharles.Forsyth FT_Byte* cur = parser->root.cursor; 957*37da2899SCharles.Forsyth FT_Byte* limit = parser->root.limit; 958*37da2899SCharles.Forsyth 959*37da2899SCharles.Forsyth PSAux_Service psaux = (PSAux_Service)face->psaux; 960*37da2899SCharles.Forsyth 961*37da2899SCharles.Forsyth 962*37da2899SCharles.Forsyth /* skip whitespace */ 963*37da2899SCharles.Forsyth while ( is_space( *cur ) ) 964*37da2899SCharles.Forsyth { 965*37da2899SCharles.Forsyth cur++; 966*37da2899SCharles.Forsyth if ( cur >= limit ) 967*37da2899SCharles.Forsyth { 968*37da2899SCharles.Forsyth FT_ERROR(( "parse_encoding: out of bounds!\n" )); 969*37da2899SCharles.Forsyth parser->root.error = T1_Err_Invalid_File_Format; 970*37da2899SCharles.Forsyth return; 971*37da2899SCharles.Forsyth } 972*37da2899SCharles.Forsyth } 973*37da2899SCharles.Forsyth 974*37da2899SCharles.Forsyth /* if we have a number, then the encoding is an array, */ 975*37da2899SCharles.Forsyth /* and we must load it now */ 976*37da2899SCharles.Forsyth if ( (FT_Byte)( *cur - '0' ) < 10 ) 977*37da2899SCharles.Forsyth { 978*37da2899SCharles.Forsyth T1_Encoding encode = &face->type1.encoding; 979*37da2899SCharles.Forsyth FT_Int count, n; 980*37da2899SCharles.Forsyth PS_Table char_table = &loader->encoding_table; 981*37da2899SCharles.Forsyth FT_Memory memory = parser->root.memory; 982*37da2899SCharles.Forsyth FT_Error error; 983*37da2899SCharles.Forsyth 984*37da2899SCharles.Forsyth 985*37da2899SCharles.Forsyth if ( encode->char_index ) 986*37da2899SCharles.Forsyth /* with synthetic fonts, it's possible we get here twice */ 987*37da2899SCharles.Forsyth return; 988*37da2899SCharles.Forsyth 989*37da2899SCharles.Forsyth /* read the number of entries in the encoding, should be 256 */ 990*37da2899SCharles.Forsyth count = (FT_Int)T1_ToInt( parser ); 991*37da2899SCharles.Forsyth if ( parser->root.error ) 992*37da2899SCharles.Forsyth return; 993*37da2899SCharles.Forsyth 994*37da2899SCharles.Forsyth /* we use a T1_Table to store our charnames */ 995*37da2899SCharles.Forsyth loader->num_chars = encode->num_chars = count; 996*37da2899SCharles.Forsyth if ( FT_NEW_ARRAY( encode->char_index, count ) || 997*37da2899SCharles.Forsyth FT_NEW_ARRAY( encode->char_name, count ) || 998*37da2899SCharles.Forsyth FT_SET_ERROR( psaux->ps_table_funcs->init( 999*37da2899SCharles.Forsyth char_table, count, memory ) ) ) 1000*37da2899SCharles.Forsyth { 1001*37da2899SCharles.Forsyth parser->root.error = error; 1002*37da2899SCharles.Forsyth return; 1003*37da2899SCharles.Forsyth } 1004*37da2899SCharles.Forsyth 1005*37da2899SCharles.Forsyth /* We need to `zero' out encoding_table.elements */ 1006*37da2899SCharles.Forsyth for ( n = 0; n < count; n++ ) 1007*37da2899SCharles.Forsyth { 1008*37da2899SCharles.Forsyth char* notdef = (char *)".notdef"; 1009*37da2899SCharles.Forsyth 1010*37da2899SCharles.Forsyth 1011*37da2899SCharles.Forsyth T1_Add_Table( char_table, n, notdef, 8 ); 1012*37da2899SCharles.Forsyth } 1013*37da2899SCharles.Forsyth 1014*37da2899SCharles.Forsyth /* Now, we will need to read a record of the form */ 1015*37da2899SCharles.Forsyth /* ... charcode /charname ... for each entry in our table */ 1016*37da2899SCharles.Forsyth /* */ 1017*37da2899SCharles.Forsyth /* We simply look for a number followed by an immediate */ 1018*37da2899SCharles.Forsyth /* name. Note that this ignores correctly the sequence */ 1019*37da2899SCharles.Forsyth /* that is often seen in type1 fonts: */ 1020*37da2899SCharles.Forsyth /* */ 1021*37da2899SCharles.Forsyth /* 0 1 255 { 1 index exch /.notdef put } for dup */ 1022*37da2899SCharles.Forsyth /* */ 1023*37da2899SCharles.Forsyth /* used to clean the encoding array before anything else. */ 1024*37da2899SCharles.Forsyth /* */ 1025*37da2899SCharles.Forsyth /* We stop when we encounter a `def'. */ 1026*37da2899SCharles.Forsyth 1027*37da2899SCharles.Forsyth cur = parser->root.cursor; 1028*37da2899SCharles.Forsyth limit = parser->root.limit; 1029*37da2899SCharles.Forsyth n = 0; 1030*37da2899SCharles.Forsyth 1031*37da2899SCharles.Forsyth for ( ; cur < limit; ) 1032*37da2899SCharles.Forsyth { 1033*37da2899SCharles.Forsyth FT_Byte c; 1034*37da2899SCharles.Forsyth 1035*37da2899SCharles.Forsyth 1036*37da2899SCharles.Forsyth c = *cur; 1037*37da2899SCharles.Forsyth 1038*37da2899SCharles.Forsyth /* we stop when we encounter a `def' */ 1039*37da2899SCharles.Forsyth if ( c == 'd' && cur + 3 < limit ) 1040*37da2899SCharles.Forsyth { 1041*37da2899SCharles.Forsyth if ( cur[1] == 'e' && 1042*37da2899SCharles.Forsyth cur[2] == 'f' && 1043*37da2899SCharles.Forsyth is_space( cur[-1] ) && 1044*37da2899SCharles.Forsyth is_space( cur[3] ) ) 1045*37da2899SCharles.Forsyth { 1046*37da2899SCharles.Forsyth FT_TRACE6(( "encoding end\n" )); 1047*37da2899SCharles.Forsyth break; 1048*37da2899SCharles.Forsyth } 1049*37da2899SCharles.Forsyth } 1050*37da2899SCharles.Forsyth 1051*37da2899SCharles.Forsyth /* otherwise, we must find a number before anything else */ 1052*37da2899SCharles.Forsyth if ( (FT_Byte)( c - '0' ) < 10 ) 1053*37da2899SCharles.Forsyth { 1054*37da2899SCharles.Forsyth FT_Int charcode; 1055*37da2899SCharles.Forsyth 1056*37da2899SCharles.Forsyth 1057*37da2899SCharles.Forsyth parser->root.cursor = cur; 1058*37da2899SCharles.Forsyth charcode = (FT_Int)T1_ToInt( parser ); 1059*37da2899SCharles.Forsyth cur = parser->root.cursor; 1060*37da2899SCharles.Forsyth 1061*37da2899SCharles.Forsyth /* skip whitespace */ 1062*37da2899SCharles.Forsyth while ( cur < limit && is_space( *cur ) ) 1063*37da2899SCharles.Forsyth cur++; 1064*37da2899SCharles.Forsyth 1065*37da2899SCharles.Forsyth if ( cur < limit && *cur == '/' ) 1066*37da2899SCharles.Forsyth { 1067*37da2899SCharles.Forsyth /* bingo, we have an immediate name -- it must be a */ 1068*37da2899SCharles.Forsyth /* character name */ 1069*37da2899SCharles.Forsyth FT_Byte* cur2 = cur + 1; 1070*37da2899SCharles.Forsyth FT_PtrDist len; 1071*37da2899SCharles.Forsyth 1072*37da2899SCharles.Forsyth 1073*37da2899SCharles.Forsyth while ( cur2 < limit && is_alpha( *cur2 ) ) 1074*37da2899SCharles.Forsyth cur2++; 1075*37da2899SCharles.Forsyth 1076*37da2899SCharles.Forsyth len = cur2 - cur - 1; 1077*37da2899SCharles.Forsyth 1078*37da2899SCharles.Forsyth parser->root.error = T1_Add_Table( char_table, charcode, 1079*37da2899SCharles.Forsyth cur + 1, len + 1 ); 1080*37da2899SCharles.Forsyth char_table->elements[charcode][len] = '\0'; 1081*37da2899SCharles.Forsyth if ( parser->root.error ) 1082*37da2899SCharles.Forsyth return; 1083*37da2899SCharles.Forsyth 1084*37da2899SCharles.Forsyth cur = cur2; 1085*37da2899SCharles.Forsyth } 1086*37da2899SCharles.Forsyth } 1087*37da2899SCharles.Forsyth else 1088*37da2899SCharles.Forsyth cur++; 1089*37da2899SCharles.Forsyth } 1090*37da2899SCharles.Forsyth 1091*37da2899SCharles.Forsyth face->type1.encoding_type = T1_ENCODING_TYPE_ARRAY; 1092*37da2899SCharles.Forsyth parser->root.cursor = cur; 1093*37da2899SCharles.Forsyth } 1094*37da2899SCharles.Forsyth /* Otherwise, we should have either `StandardEncoding', */ 1095*37da2899SCharles.Forsyth /* `ExpertEncoding', or `ISOLatin1Encoding' */ 1096*37da2899SCharles.Forsyth else 1097*37da2899SCharles.Forsyth { 1098*37da2899SCharles.Forsyth if ( cur + 17 < limit && 1099*37da2899SCharles.Forsyth ft_strncmp( (const char*)cur, "StandardEncoding", 16 ) == 0 ) 1100*37da2899SCharles.Forsyth face->type1.encoding_type = T1_ENCODING_TYPE_STANDARD; 1101*37da2899SCharles.Forsyth 1102*37da2899SCharles.Forsyth else if ( cur + 15 < limit && 1103*37da2899SCharles.Forsyth ft_strncmp( (const char*)cur, "ExpertEncoding", 14 ) == 0 ) 1104*37da2899SCharles.Forsyth face->type1.encoding_type = T1_ENCODING_TYPE_EXPERT; 1105*37da2899SCharles.Forsyth 1106*37da2899SCharles.Forsyth else if ( cur + 18 < limit && 1107*37da2899SCharles.Forsyth ft_strncmp( (const char*)cur, "ISOLatin1Encoding", 17 ) == 0 ) 1108*37da2899SCharles.Forsyth face->type1.encoding_type = T1_ENCODING_TYPE_ISOLATIN1; 1109*37da2899SCharles.Forsyth 1110*37da2899SCharles.Forsyth else 1111*37da2899SCharles.Forsyth { 1112*37da2899SCharles.Forsyth FT_ERROR(( "parse_encoding: invalid token!\n" )); 1113*37da2899SCharles.Forsyth parser->root.error = T1_Err_Invalid_File_Format; 1114*37da2899SCharles.Forsyth } 1115*37da2899SCharles.Forsyth } 1116*37da2899SCharles.Forsyth } 1117*37da2899SCharles.Forsyth 1118*37da2899SCharles.Forsyth 1119*37da2899SCharles.Forsyth static void parse_subrs(T1_Face face,T1_Loader loader)1120*37da2899SCharles.Forsyth parse_subrs( T1_Face face, 1121*37da2899SCharles.Forsyth T1_Loader loader ) 1122*37da2899SCharles.Forsyth { 1123*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 1124*37da2899SCharles.Forsyth PS_Table table = &loader->subrs; 1125*37da2899SCharles.Forsyth FT_Memory memory = parser->root.memory; 1126*37da2899SCharles.Forsyth FT_Error error; 1127*37da2899SCharles.Forsyth FT_Int n; 1128*37da2899SCharles.Forsyth 1129*37da2899SCharles.Forsyth PSAux_Service psaux = (PSAux_Service)face->psaux; 1130*37da2899SCharles.Forsyth 1131*37da2899SCharles.Forsyth 1132*37da2899SCharles.Forsyth if ( loader->num_subrs ) 1133*37da2899SCharles.Forsyth /* with synthetic fonts, it's possible we get here twice */ 1134*37da2899SCharles.Forsyth return; 1135*37da2899SCharles.Forsyth 1136*37da2899SCharles.Forsyth loader->num_subrs = (FT_Int)T1_ToInt( parser ); 1137*37da2899SCharles.Forsyth if ( parser->root.error ) 1138*37da2899SCharles.Forsyth return; 1139*37da2899SCharles.Forsyth 1140*37da2899SCharles.Forsyth /* position the parser right before the `dup' of the first subr */ 1141*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 1142*37da2899SCharles.Forsyth T1_Skip_Alpha( parser ); /* `array' */ 1143*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 1144*37da2899SCharles.Forsyth 1145*37da2899SCharles.Forsyth /* initialize subrs array */ 1146*37da2899SCharles.Forsyth error = psaux->ps_table_funcs->init( table, loader->num_subrs, memory ); 1147*37da2899SCharles.Forsyth if ( error ) 1148*37da2899SCharles.Forsyth goto Fail; 1149*37da2899SCharles.Forsyth 1150*37da2899SCharles.Forsyth /* the format is simple: */ 1151*37da2899SCharles.Forsyth /* */ 1152*37da2899SCharles.Forsyth /* `index' + binary data */ 1153*37da2899SCharles.Forsyth /* */ 1154*37da2899SCharles.Forsyth for ( n = 0; n < loader->num_subrs; n++ ) 1155*37da2899SCharles.Forsyth { 1156*37da2899SCharles.Forsyth FT_Long idx, size; 1157*37da2899SCharles.Forsyth FT_Byte* base; 1158*37da2899SCharles.Forsyth 1159*37da2899SCharles.Forsyth 1160*37da2899SCharles.Forsyth /* If the next token isn't `dup', we are also done. This */ 1161*37da2899SCharles.Forsyth /* happens when there are `holes' in the Subrs array. */ 1162*37da2899SCharles.Forsyth if ( ft_strncmp( (char*)parser->root.cursor, "dup", 3 ) != 0 ) 1163*37da2899SCharles.Forsyth break; 1164*37da2899SCharles.Forsyth 1165*37da2899SCharles.Forsyth idx = T1_ToInt( parser ); 1166*37da2899SCharles.Forsyth 1167*37da2899SCharles.Forsyth if ( !read_binary_data( parser, &size, &base ) ) 1168*37da2899SCharles.Forsyth return; 1169*37da2899SCharles.Forsyth 1170*37da2899SCharles.Forsyth /* The binary string is followed by one token, e.g. `NP' */ 1171*37da2899SCharles.Forsyth /* (bound to `noaccess put') or by two separate tokens: */ 1172*37da2899SCharles.Forsyth /* `noaccess' & `put'. We position the parser right */ 1173*37da2899SCharles.Forsyth /* before the next `dup', if any. */ 1174*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 1175*37da2899SCharles.Forsyth T1_Skip_Alpha( parser ); /* `NP' or `I' or `noaccess' */ 1176*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 1177*37da2899SCharles.Forsyth 1178*37da2899SCharles.Forsyth if ( ft_strncmp( (char*)parser->root.cursor, "put", 3 ) == 0 ) 1179*37da2899SCharles.Forsyth { 1180*37da2899SCharles.Forsyth T1_Skip_Alpha( parser ); /* skip `put' */ 1181*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 1182*37da2899SCharles.Forsyth } 1183*37da2899SCharles.Forsyth 1184*37da2899SCharles.Forsyth /* some fonts use a value of -1 for lenIV to indicate that */ 1185*37da2899SCharles.Forsyth /* the charstrings are unencoded */ 1186*37da2899SCharles.Forsyth /* */ 1187*37da2899SCharles.Forsyth /* thanks to Tom Kacvinsky for pointing this out */ 1188*37da2899SCharles.Forsyth /* */ 1189*37da2899SCharles.Forsyth if ( face->type1.private_dict.lenIV >= 0 ) 1190*37da2899SCharles.Forsyth { 1191*37da2899SCharles.Forsyth FT_Byte* temp; 1192*37da2899SCharles.Forsyth 1193*37da2899SCharles.Forsyth 1194*37da2899SCharles.Forsyth /* t1_decrypt() shouldn't write to base -- make temporary copy */ 1195*37da2899SCharles.Forsyth if ( FT_ALLOC( temp, size ) ) 1196*37da2899SCharles.Forsyth goto Fail; 1197*37da2899SCharles.Forsyth FT_MEM_COPY( temp, base, size ); 1198*37da2899SCharles.Forsyth psaux->t1_decrypt( temp, size, 4330 ); 1199*37da2899SCharles.Forsyth size -= face->type1.private_dict.lenIV; 1200*37da2899SCharles.Forsyth error = T1_Add_Table( table, idx, 1201*37da2899SCharles.Forsyth temp + face->type1.private_dict.lenIV, size ); 1202*37da2899SCharles.Forsyth FT_FREE( temp ); 1203*37da2899SCharles.Forsyth } 1204*37da2899SCharles.Forsyth else 1205*37da2899SCharles.Forsyth error = T1_Add_Table( table, idx, base, size ); 1206*37da2899SCharles.Forsyth if ( error ) 1207*37da2899SCharles.Forsyth goto Fail; 1208*37da2899SCharles.Forsyth } 1209*37da2899SCharles.Forsyth return; 1210*37da2899SCharles.Forsyth 1211*37da2899SCharles.Forsyth Fail: 1212*37da2899SCharles.Forsyth parser->root.error = error; 1213*37da2899SCharles.Forsyth } 1214*37da2899SCharles.Forsyth 1215*37da2899SCharles.Forsyth 1216*37da2899SCharles.Forsyth static void parse_charstrings(T1_Face face,T1_Loader loader)1217*37da2899SCharles.Forsyth parse_charstrings( T1_Face face, 1218*37da2899SCharles.Forsyth T1_Loader loader ) 1219*37da2899SCharles.Forsyth { 1220*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 1221*37da2899SCharles.Forsyth PS_Table code_table = &loader->charstrings; 1222*37da2899SCharles.Forsyth PS_Table name_table = &loader->glyph_names; 1223*37da2899SCharles.Forsyth PS_Table swap_table = &loader->swap_table; 1224*37da2899SCharles.Forsyth FT_Memory memory = parser->root.memory; 1225*37da2899SCharles.Forsyth FT_Error error; 1226*37da2899SCharles.Forsyth 1227*37da2899SCharles.Forsyth PSAux_Service psaux = (PSAux_Service)face->psaux; 1228*37da2899SCharles.Forsyth 1229*37da2899SCharles.Forsyth FT_Byte* cur; 1230*37da2899SCharles.Forsyth FT_Byte* limit = parser->root.limit; 1231*37da2899SCharles.Forsyth FT_Int n; 1232*37da2899SCharles.Forsyth FT_UInt notdef_index = 0; 1233*37da2899SCharles.Forsyth FT_Byte notdef_found = 0; 1234*37da2899SCharles.Forsyth 1235*37da2899SCharles.Forsyth 1236*37da2899SCharles.Forsyth if ( loader->num_glyphs ) 1237*37da2899SCharles.Forsyth /* with synthetic fonts, it's possible we get here twice */ 1238*37da2899SCharles.Forsyth return; 1239*37da2899SCharles.Forsyth 1240*37da2899SCharles.Forsyth loader->num_glyphs = (FT_Int)T1_ToInt( parser ); 1241*37da2899SCharles.Forsyth if ( parser->root.error ) 1242*37da2899SCharles.Forsyth return; 1243*37da2899SCharles.Forsyth 1244*37da2899SCharles.Forsyth /* initialize tables (leaving room for addition of .notdef, */ 1245*37da2899SCharles.Forsyth /* if necessary). */ 1246*37da2899SCharles.Forsyth 1247*37da2899SCharles.Forsyth error = psaux->ps_table_funcs->init( code_table, 1248*37da2899SCharles.Forsyth loader->num_glyphs + 1, 1249*37da2899SCharles.Forsyth memory ); 1250*37da2899SCharles.Forsyth if ( error ) 1251*37da2899SCharles.Forsyth goto Fail; 1252*37da2899SCharles.Forsyth 1253*37da2899SCharles.Forsyth error = psaux->ps_table_funcs->init( name_table, 1254*37da2899SCharles.Forsyth loader->num_glyphs + 1, 1255*37da2899SCharles.Forsyth memory ); 1256*37da2899SCharles.Forsyth if ( error ) 1257*37da2899SCharles.Forsyth goto Fail; 1258*37da2899SCharles.Forsyth 1259*37da2899SCharles.Forsyth /* Initialize table for swapping index notdef_index and */ 1260*37da2899SCharles.Forsyth /* index 0 names and codes (if necessary). */ 1261*37da2899SCharles.Forsyth 1262*37da2899SCharles.Forsyth error = psaux->ps_table_funcs->init( swap_table, 4, memory ); 1263*37da2899SCharles.Forsyth 1264*37da2899SCharles.Forsyth if ( error ) 1265*37da2899SCharles.Forsyth goto Fail; 1266*37da2899SCharles.Forsyth 1267*37da2899SCharles.Forsyth n = 0; 1268*37da2899SCharles.Forsyth 1269*37da2899SCharles.Forsyth for (;;) 1270*37da2899SCharles.Forsyth { 1271*37da2899SCharles.Forsyth FT_Long size; 1272*37da2899SCharles.Forsyth FT_Byte* base; 1273*37da2899SCharles.Forsyth 1274*37da2899SCharles.Forsyth 1275*37da2899SCharles.Forsyth /* the format is simple: */ 1276*37da2899SCharles.Forsyth /* `/glyphname' + binary data */ 1277*37da2899SCharles.Forsyth /* */ 1278*37da2899SCharles.Forsyth /* note that we stop when we find a `def' */ 1279*37da2899SCharles.Forsyth /* */ 1280*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 1281*37da2899SCharles.Forsyth 1282*37da2899SCharles.Forsyth cur = parser->root.cursor; 1283*37da2899SCharles.Forsyth if ( cur >= limit ) 1284*37da2899SCharles.Forsyth break; 1285*37da2899SCharles.Forsyth 1286*37da2899SCharles.Forsyth /* we stop when we find a `def' or `end' keyword */ 1287*37da2899SCharles.Forsyth if ( *cur == 'd' && 1288*37da2899SCharles.Forsyth cur + 3 < limit && 1289*37da2899SCharles.Forsyth cur[1] == 'e' && 1290*37da2899SCharles.Forsyth cur[2] == 'f' ) 1291*37da2899SCharles.Forsyth break; 1292*37da2899SCharles.Forsyth 1293*37da2899SCharles.Forsyth if ( *cur == 'e' && 1294*37da2899SCharles.Forsyth cur + 3 < limit && 1295*37da2899SCharles.Forsyth cur[1] == 'n' && 1296*37da2899SCharles.Forsyth cur[2] == 'd' ) 1297*37da2899SCharles.Forsyth break; 1298*37da2899SCharles.Forsyth 1299*37da2899SCharles.Forsyth if ( *cur != '/' ) 1300*37da2899SCharles.Forsyth T1_Skip_Alpha( parser ); 1301*37da2899SCharles.Forsyth else 1302*37da2899SCharles.Forsyth { 1303*37da2899SCharles.Forsyth FT_Byte* cur2 = cur + 1; 1304*37da2899SCharles.Forsyth FT_PtrDist len; 1305*37da2899SCharles.Forsyth 1306*37da2899SCharles.Forsyth 1307*37da2899SCharles.Forsyth while ( cur2 < limit && is_alpha( *cur2 ) ) 1308*37da2899SCharles.Forsyth cur2++; 1309*37da2899SCharles.Forsyth len = cur2 - cur - 1; 1310*37da2899SCharles.Forsyth 1311*37da2899SCharles.Forsyth error = T1_Add_Table( name_table, n, cur + 1, len + 1 ); 1312*37da2899SCharles.Forsyth if ( error ) 1313*37da2899SCharles.Forsyth goto Fail; 1314*37da2899SCharles.Forsyth 1315*37da2899SCharles.Forsyth /* add a trailing zero to the name table */ 1316*37da2899SCharles.Forsyth name_table->elements[n][len] = '\0'; 1317*37da2899SCharles.Forsyth 1318*37da2899SCharles.Forsyth /* record index of /.notdef */ 1319*37da2899SCharles.Forsyth if ( ft_strcmp( (const char*)".notdef", 1320*37da2899SCharles.Forsyth (const char*)(name_table->elements[n]) ) == 0 ) 1321*37da2899SCharles.Forsyth { 1322*37da2899SCharles.Forsyth notdef_index = n; 1323*37da2899SCharles.Forsyth notdef_found = 1; 1324*37da2899SCharles.Forsyth } 1325*37da2899SCharles.Forsyth 1326*37da2899SCharles.Forsyth parser->root.cursor = cur2; 1327*37da2899SCharles.Forsyth if ( !read_binary_data( parser, &size, &base ) ) 1328*37da2899SCharles.Forsyth return; 1329*37da2899SCharles.Forsyth 1330*37da2899SCharles.Forsyth if ( face->type1.private_dict.lenIV >= 0 ) 1331*37da2899SCharles.Forsyth { 1332*37da2899SCharles.Forsyth FT_Byte* temp; 1333*37da2899SCharles.Forsyth 1334*37da2899SCharles.Forsyth 1335*37da2899SCharles.Forsyth /* t1_decrypt() shouldn't write to base -- make temporary copy */ 1336*37da2899SCharles.Forsyth if ( FT_ALLOC( temp, size ) ) 1337*37da2899SCharles.Forsyth goto Fail; 1338*37da2899SCharles.Forsyth FT_MEM_COPY( temp, base, size ); 1339*37da2899SCharles.Forsyth psaux->t1_decrypt( temp, size, 4330 ); 1340*37da2899SCharles.Forsyth size -= face->type1.private_dict.lenIV; 1341*37da2899SCharles.Forsyth error = T1_Add_Table( code_table, n, 1342*37da2899SCharles.Forsyth temp + face->type1.private_dict.lenIV, size ); 1343*37da2899SCharles.Forsyth FT_FREE( temp ); 1344*37da2899SCharles.Forsyth } 1345*37da2899SCharles.Forsyth else 1346*37da2899SCharles.Forsyth error = T1_Add_Table( code_table, n, base, size ); 1347*37da2899SCharles.Forsyth if ( error ) 1348*37da2899SCharles.Forsyth goto Fail; 1349*37da2899SCharles.Forsyth 1350*37da2899SCharles.Forsyth n++; 1351*37da2899SCharles.Forsyth if ( n >= loader->num_glyphs ) 1352*37da2899SCharles.Forsyth break; 1353*37da2899SCharles.Forsyth } 1354*37da2899SCharles.Forsyth } 1355*37da2899SCharles.Forsyth 1356*37da2899SCharles.Forsyth loader->num_glyphs = n; 1357*37da2899SCharles.Forsyth 1358*37da2899SCharles.Forsyth /* if /.notdef is found but does not occupy index 0, do our magic. */ 1359*37da2899SCharles.Forsyth if ( ft_strcmp( (const char*)".notdef", 1360*37da2899SCharles.Forsyth (const char*)name_table->elements[0] ) && 1361*37da2899SCharles.Forsyth notdef_found ) 1362*37da2899SCharles.Forsyth { 1363*37da2899SCharles.Forsyth /* Swap glyph in index 0 with /.notdef glyph. First, add index 0 */ 1364*37da2899SCharles.Forsyth /* name and code entries to swap_table. Then place notdef_index name */ 1365*37da2899SCharles.Forsyth /* and code entries into swap_table. Then swap name and code */ 1366*37da2899SCharles.Forsyth /* entries at indices notdef_index and 0 using values stored in */ 1367*37da2899SCharles.Forsyth /* swap_table. */ 1368*37da2899SCharles.Forsyth 1369*37da2899SCharles.Forsyth /* Index 0 name */ 1370*37da2899SCharles.Forsyth error = T1_Add_Table( swap_table, 0, 1371*37da2899SCharles.Forsyth name_table->elements[0], 1372*37da2899SCharles.Forsyth name_table->lengths [0] ); 1373*37da2899SCharles.Forsyth if ( error ) 1374*37da2899SCharles.Forsyth goto Fail; 1375*37da2899SCharles.Forsyth 1376*37da2899SCharles.Forsyth /* Index 0 code */ 1377*37da2899SCharles.Forsyth error = T1_Add_Table( swap_table, 1, 1378*37da2899SCharles.Forsyth code_table->elements[0], 1379*37da2899SCharles.Forsyth code_table->lengths [0] ); 1380*37da2899SCharles.Forsyth if ( error ) 1381*37da2899SCharles.Forsyth goto Fail; 1382*37da2899SCharles.Forsyth 1383*37da2899SCharles.Forsyth /* Index notdef_index name */ 1384*37da2899SCharles.Forsyth error = T1_Add_Table( swap_table, 2, 1385*37da2899SCharles.Forsyth name_table->elements[notdef_index], 1386*37da2899SCharles.Forsyth name_table->lengths [notdef_index] ); 1387*37da2899SCharles.Forsyth if ( error ) 1388*37da2899SCharles.Forsyth goto Fail; 1389*37da2899SCharles.Forsyth 1390*37da2899SCharles.Forsyth /* Index notdef_index code */ 1391*37da2899SCharles.Forsyth error = T1_Add_Table( swap_table, 3, 1392*37da2899SCharles.Forsyth code_table->elements[notdef_index], 1393*37da2899SCharles.Forsyth code_table->lengths [notdef_index] ); 1394*37da2899SCharles.Forsyth if ( error ) 1395*37da2899SCharles.Forsyth goto Fail; 1396*37da2899SCharles.Forsyth 1397*37da2899SCharles.Forsyth error = T1_Add_Table( name_table, notdef_index, 1398*37da2899SCharles.Forsyth swap_table->elements[0], 1399*37da2899SCharles.Forsyth swap_table->lengths [0] ); 1400*37da2899SCharles.Forsyth if ( error ) 1401*37da2899SCharles.Forsyth goto Fail; 1402*37da2899SCharles.Forsyth 1403*37da2899SCharles.Forsyth error = T1_Add_Table( code_table, notdef_index, 1404*37da2899SCharles.Forsyth swap_table->elements[1], 1405*37da2899SCharles.Forsyth swap_table->lengths [1] ); 1406*37da2899SCharles.Forsyth if ( error ) 1407*37da2899SCharles.Forsyth goto Fail; 1408*37da2899SCharles.Forsyth 1409*37da2899SCharles.Forsyth error = T1_Add_Table( name_table, 0, 1410*37da2899SCharles.Forsyth swap_table->elements[2], 1411*37da2899SCharles.Forsyth swap_table->lengths [2] ); 1412*37da2899SCharles.Forsyth if ( error ) 1413*37da2899SCharles.Forsyth goto Fail; 1414*37da2899SCharles.Forsyth 1415*37da2899SCharles.Forsyth error = T1_Add_Table( code_table, 0, 1416*37da2899SCharles.Forsyth swap_table->elements[3], 1417*37da2899SCharles.Forsyth swap_table->lengths [3] ); 1418*37da2899SCharles.Forsyth if ( error ) 1419*37da2899SCharles.Forsyth goto Fail; 1420*37da2899SCharles.Forsyth 1421*37da2899SCharles.Forsyth } 1422*37da2899SCharles.Forsyth else if ( !notdef_found ) 1423*37da2899SCharles.Forsyth { 1424*37da2899SCharles.Forsyth /* notdef_index is already 0, or /.notdef is undefined in */ 1425*37da2899SCharles.Forsyth /* charstrings dictionary. Worry about /.notdef undefined. */ 1426*37da2899SCharles.Forsyth /* We take index 0 and add it to the end of the table(s) */ 1427*37da2899SCharles.Forsyth /* and add our own /.notdef glyph to index 0. */ 1428*37da2899SCharles.Forsyth 1429*37da2899SCharles.Forsyth /* 0 333 hsbw endchar */ 1430*37da2899SCharles.Forsyth FT_Byte notdef_glyph[] = {0x8B, 0xF7, 0xE1, 0x0D, 0x0E}; 1431*37da2899SCharles.Forsyth char* notdef_name = (char *)".notdef"; 1432*37da2899SCharles.Forsyth 1433*37da2899SCharles.Forsyth 1434*37da2899SCharles.Forsyth error = T1_Add_Table( swap_table, 0, 1435*37da2899SCharles.Forsyth name_table->elements[0], 1436*37da2899SCharles.Forsyth name_table->lengths [0] ); 1437*37da2899SCharles.Forsyth if ( error ) 1438*37da2899SCharles.Forsyth goto Fail; 1439*37da2899SCharles.Forsyth 1440*37da2899SCharles.Forsyth error = T1_Add_Table( swap_table, 1, 1441*37da2899SCharles.Forsyth code_table->elements[0], 1442*37da2899SCharles.Forsyth code_table->lengths [0] ); 1443*37da2899SCharles.Forsyth if ( error ) 1444*37da2899SCharles.Forsyth goto Fail; 1445*37da2899SCharles.Forsyth 1446*37da2899SCharles.Forsyth error = T1_Add_Table( name_table, 0, notdef_name, 8 ); 1447*37da2899SCharles.Forsyth if ( error ) 1448*37da2899SCharles.Forsyth goto Fail; 1449*37da2899SCharles.Forsyth 1450*37da2899SCharles.Forsyth error = T1_Add_Table( code_table, 0, notdef_glyph, 5 ); 1451*37da2899SCharles.Forsyth 1452*37da2899SCharles.Forsyth if ( error ) 1453*37da2899SCharles.Forsyth goto Fail; 1454*37da2899SCharles.Forsyth 1455*37da2899SCharles.Forsyth error = T1_Add_Table( name_table, n, 1456*37da2899SCharles.Forsyth swap_table->elements[0], 1457*37da2899SCharles.Forsyth swap_table->lengths [0] ); 1458*37da2899SCharles.Forsyth if ( error ) 1459*37da2899SCharles.Forsyth goto Fail; 1460*37da2899SCharles.Forsyth 1461*37da2899SCharles.Forsyth error = T1_Add_Table( code_table, n, 1462*37da2899SCharles.Forsyth swap_table->elements[1], 1463*37da2899SCharles.Forsyth swap_table->lengths [1] ); 1464*37da2899SCharles.Forsyth if ( error ) 1465*37da2899SCharles.Forsyth goto Fail; 1466*37da2899SCharles.Forsyth 1467*37da2899SCharles.Forsyth /* we added a glyph. */ 1468*37da2899SCharles.Forsyth loader->num_glyphs = n + 1; 1469*37da2899SCharles.Forsyth } 1470*37da2899SCharles.Forsyth 1471*37da2899SCharles.Forsyth return; 1472*37da2899SCharles.Forsyth 1473*37da2899SCharles.Forsyth Fail: 1474*37da2899SCharles.Forsyth parser->root.error = error; 1475*37da2899SCharles.Forsyth } 1476*37da2899SCharles.Forsyth 1477*37da2899SCharles.Forsyth 1478*37da2899SCharles.Forsyth static 1479*37da2899SCharles.Forsyth const T1_FieldRec t1_keywords[] = 1480*37da2899SCharles.Forsyth { 1481*37da2899SCharles.Forsyth 1482*37da2899SCharles.Forsyth #include "t1tokens.h" 1483*37da2899SCharles.Forsyth 1484*37da2899SCharles.Forsyth /* now add the special functions... */ 1485*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "FontName", parse_font_name ) 1486*37da2899SCharles.Forsyth #if 0 1487*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "FontBBox", parse_font_bbox ) 1488*37da2899SCharles.Forsyth #endif 1489*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "FontMatrix", parse_font_matrix ) 1490*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "Encoding", parse_encoding ) 1491*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "Subrs", parse_subrs ) 1492*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "CharStrings", parse_charstrings ) 1493*37da2899SCharles.Forsyth 1494*37da2899SCharles.Forsyth #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT 1495*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "BlendDesignPositions", parse_blend_design_positions ) 1496*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "BlendDesignMap", parse_blend_design_map ) 1497*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "BlendAxisTypes", parse_blend_axis_types ) 1498*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "WeightVector", parse_weight_vector ) 1499*37da2899SCharles.Forsyth T1_FIELD_CALLBACK( "shareddict", parse_shared_dict ) 1500*37da2899SCharles.Forsyth #endif 1501*37da2899SCharles.Forsyth 1502*37da2899SCharles.Forsyth { 0, T1_FIELD_LOCATION_CID_INFO, T1_FIELD_TYPE_NONE, 0, 0, 0, 0, 0 } 1503*37da2899SCharles.Forsyth }; 1504*37da2899SCharles.Forsyth 1505*37da2899SCharles.Forsyth 1506*37da2899SCharles.Forsyth static FT_Error parse_dict(T1_Face face,T1_Loader loader,FT_Byte * base,FT_Long size)1507*37da2899SCharles.Forsyth parse_dict( T1_Face face, 1508*37da2899SCharles.Forsyth T1_Loader loader, 1509*37da2899SCharles.Forsyth FT_Byte* base, 1510*37da2899SCharles.Forsyth FT_Long size ) 1511*37da2899SCharles.Forsyth { 1512*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 1513*37da2899SCharles.Forsyth 1514*37da2899SCharles.Forsyth 1515*37da2899SCharles.Forsyth parser->root.cursor = base; 1516*37da2899SCharles.Forsyth parser->root.limit = base + size; 1517*37da2899SCharles.Forsyth parser->root.error = 0; 1518*37da2899SCharles.Forsyth 1519*37da2899SCharles.Forsyth { 1520*37da2899SCharles.Forsyth FT_Byte* cur = base; 1521*37da2899SCharles.Forsyth FT_Byte* limit = cur + size; 1522*37da2899SCharles.Forsyth 1523*37da2899SCharles.Forsyth 1524*37da2899SCharles.Forsyth for ( ; cur < limit; cur++ ) 1525*37da2899SCharles.Forsyth { 1526*37da2899SCharles.Forsyth /* look for `FontDirectory', which causes problems on some fonts */ 1527*37da2899SCharles.Forsyth if ( *cur == 'F' && cur + 25 < limit && 1528*37da2899SCharles.Forsyth ft_strncmp( (char*)cur, "FontDirectory", 13 ) == 0 ) 1529*37da2899SCharles.Forsyth { 1530*37da2899SCharles.Forsyth FT_Byte* cur2; 1531*37da2899SCharles.Forsyth 1532*37da2899SCharles.Forsyth 1533*37da2899SCharles.Forsyth /* skip the `FontDirectory' keyword */ 1534*37da2899SCharles.Forsyth cur += 13; 1535*37da2899SCharles.Forsyth cur2 = cur; 1536*37da2899SCharles.Forsyth 1537*37da2899SCharles.Forsyth /* lookup the `known' keyword */ 1538*37da2899SCharles.Forsyth while ( cur < limit && *cur != 'k' && 1539*37da2899SCharles.Forsyth ft_strncmp( (char*)cur, "known", 5 ) ) 1540*37da2899SCharles.Forsyth cur++; 1541*37da2899SCharles.Forsyth 1542*37da2899SCharles.Forsyth if ( cur < limit ) 1543*37da2899SCharles.Forsyth { 1544*37da2899SCharles.Forsyth T1_TokenRec token; 1545*37da2899SCharles.Forsyth 1546*37da2899SCharles.Forsyth 1547*37da2899SCharles.Forsyth /* skip the `known' keyword and the token following it */ 1548*37da2899SCharles.Forsyth cur += 5; 1549*37da2899SCharles.Forsyth loader->parser.root.cursor = cur; 1550*37da2899SCharles.Forsyth T1_ToToken( &loader->parser, &token ); 1551*37da2899SCharles.Forsyth 1552*37da2899SCharles.Forsyth /* if the last token was an array, skip it! */ 1553*37da2899SCharles.Forsyth if ( token.type == T1_TOKEN_TYPE_ARRAY ) 1554*37da2899SCharles.Forsyth cur2 = parser->root.cursor; 1555*37da2899SCharles.Forsyth } 1556*37da2899SCharles.Forsyth cur = cur2; 1557*37da2899SCharles.Forsyth } 1558*37da2899SCharles.Forsyth /* look for immediates */ 1559*37da2899SCharles.Forsyth else if ( *cur == '/' && cur + 2 < limit ) 1560*37da2899SCharles.Forsyth { 1561*37da2899SCharles.Forsyth FT_Byte* cur2; 1562*37da2899SCharles.Forsyth FT_PtrDist len; 1563*37da2899SCharles.Forsyth 1564*37da2899SCharles.Forsyth 1565*37da2899SCharles.Forsyth cur++; 1566*37da2899SCharles.Forsyth cur2 = cur; 1567*37da2899SCharles.Forsyth while ( cur2 < limit && is_alpha( *cur2 ) ) 1568*37da2899SCharles.Forsyth cur2++; 1569*37da2899SCharles.Forsyth 1570*37da2899SCharles.Forsyth len = cur2 - cur; 1571*37da2899SCharles.Forsyth if ( len > 0 && len < 22 ) 1572*37da2899SCharles.Forsyth { 1573*37da2899SCharles.Forsyth { 1574*37da2899SCharles.Forsyth /* now, compare the immediate name to the keyword table */ 1575*37da2899SCharles.Forsyth T1_Field keyword = (T1_Field)t1_keywords; 1576*37da2899SCharles.Forsyth 1577*37da2899SCharles.Forsyth 1578*37da2899SCharles.Forsyth for (;;) 1579*37da2899SCharles.Forsyth { 1580*37da2899SCharles.Forsyth FT_Byte* name; 1581*37da2899SCharles.Forsyth 1582*37da2899SCharles.Forsyth 1583*37da2899SCharles.Forsyth name = (FT_Byte*)keyword->ident; 1584*37da2899SCharles.Forsyth if ( !name ) 1585*37da2899SCharles.Forsyth break; 1586*37da2899SCharles.Forsyth 1587*37da2899SCharles.Forsyth if ( cur[0] == name[0] && 1588*37da2899SCharles.Forsyth len == ft_strlen( (const char*)name ) ) 1589*37da2899SCharles.Forsyth { 1590*37da2899SCharles.Forsyth FT_PtrDist n; 1591*37da2899SCharles.Forsyth 1592*37da2899SCharles.Forsyth 1593*37da2899SCharles.Forsyth for ( n = 1; n < len; n++ ) 1594*37da2899SCharles.Forsyth if ( cur[n] != name[n] ) 1595*37da2899SCharles.Forsyth break; 1596*37da2899SCharles.Forsyth 1597*37da2899SCharles.Forsyth if ( n >= len ) 1598*37da2899SCharles.Forsyth { 1599*37da2899SCharles.Forsyth /* we found it -- run the parsing callback! */ 1600*37da2899SCharles.Forsyth parser->root.cursor = cur2; 1601*37da2899SCharles.Forsyth T1_Skip_Spaces( parser ); 1602*37da2899SCharles.Forsyth parser->root.error = t1_load_keyword( face, 1603*37da2899SCharles.Forsyth loader, 1604*37da2899SCharles.Forsyth keyword ); 1605*37da2899SCharles.Forsyth if ( parser->root.error ) 1606*37da2899SCharles.Forsyth return parser->root.error; 1607*37da2899SCharles.Forsyth 1608*37da2899SCharles.Forsyth cur = parser->root.cursor; 1609*37da2899SCharles.Forsyth break; 1610*37da2899SCharles.Forsyth } 1611*37da2899SCharles.Forsyth } 1612*37da2899SCharles.Forsyth keyword++; 1613*37da2899SCharles.Forsyth } 1614*37da2899SCharles.Forsyth } 1615*37da2899SCharles.Forsyth } 1616*37da2899SCharles.Forsyth } 1617*37da2899SCharles.Forsyth } 1618*37da2899SCharles.Forsyth } 1619*37da2899SCharles.Forsyth return parser->root.error; 1620*37da2899SCharles.Forsyth } 1621*37da2899SCharles.Forsyth 1622*37da2899SCharles.Forsyth 1623*37da2899SCharles.Forsyth static void t1_init_loader(T1_Loader loader,T1_Face face)1624*37da2899SCharles.Forsyth t1_init_loader( T1_Loader loader, 1625*37da2899SCharles.Forsyth T1_Face face ) 1626*37da2899SCharles.Forsyth { 1627*37da2899SCharles.Forsyth FT_UNUSED( face ); 1628*37da2899SCharles.Forsyth 1629*37da2899SCharles.Forsyth FT_MEM_ZERO( loader, sizeof ( *loader ) ); 1630*37da2899SCharles.Forsyth loader->num_glyphs = 0; 1631*37da2899SCharles.Forsyth loader->num_chars = 0; 1632*37da2899SCharles.Forsyth 1633*37da2899SCharles.Forsyth /* initialize the tables -- simply set their `init' field to 0 */ 1634*37da2899SCharles.Forsyth loader->encoding_table.init = 0; 1635*37da2899SCharles.Forsyth loader->charstrings.init = 0; 1636*37da2899SCharles.Forsyth loader->glyph_names.init = 0; 1637*37da2899SCharles.Forsyth loader->subrs.init = 0; 1638*37da2899SCharles.Forsyth loader->swap_table.init = 0; 1639*37da2899SCharles.Forsyth loader->fontdata = 0; 1640*37da2899SCharles.Forsyth } 1641*37da2899SCharles.Forsyth 1642*37da2899SCharles.Forsyth 1643*37da2899SCharles.Forsyth static void t1_done_loader(T1_Loader loader)1644*37da2899SCharles.Forsyth t1_done_loader( T1_Loader loader ) 1645*37da2899SCharles.Forsyth { 1646*37da2899SCharles.Forsyth T1_Parser parser = &loader->parser; 1647*37da2899SCharles.Forsyth 1648*37da2899SCharles.Forsyth 1649*37da2899SCharles.Forsyth /* finalize tables */ 1650*37da2899SCharles.Forsyth T1_Release_Table( &loader->encoding_table ); 1651*37da2899SCharles.Forsyth T1_Release_Table( &loader->charstrings ); 1652*37da2899SCharles.Forsyth T1_Release_Table( &loader->glyph_names ); 1653*37da2899SCharles.Forsyth T1_Release_Table( &loader->swap_table ); 1654*37da2899SCharles.Forsyth T1_Release_Table( &loader->subrs ); 1655*37da2899SCharles.Forsyth 1656*37da2899SCharles.Forsyth /* finalize parser */ 1657*37da2899SCharles.Forsyth T1_Finalize_Parser( parser ); 1658*37da2899SCharles.Forsyth } 1659*37da2899SCharles.Forsyth 1660*37da2899SCharles.Forsyth 1661*37da2899SCharles.Forsyth FT_LOCAL_DEF( FT_Error ) T1_Open_Face(T1_Face face)1662*37da2899SCharles.Forsyth T1_Open_Face( T1_Face face ) 1663*37da2899SCharles.Forsyth { 1664*37da2899SCharles.Forsyth T1_LoaderRec loader; 1665*37da2899SCharles.Forsyth T1_Parser parser; 1666*37da2899SCharles.Forsyth T1_Font type1 = &face->type1; 1667*37da2899SCharles.Forsyth FT_Error error; 1668*37da2899SCharles.Forsyth 1669*37da2899SCharles.Forsyth PSAux_Service psaux = (PSAux_Service)face->psaux; 1670*37da2899SCharles.Forsyth 1671*37da2899SCharles.Forsyth 1672*37da2899SCharles.Forsyth t1_init_loader( &loader, face ); 1673*37da2899SCharles.Forsyth 1674*37da2899SCharles.Forsyth /* default lenIV */ 1675*37da2899SCharles.Forsyth type1->private_dict.lenIV = 4; 1676*37da2899SCharles.Forsyth 1677*37da2899SCharles.Forsyth /* default blue fuzz, we put it there since 0 is a valid value */ 1678*37da2899SCharles.Forsyth type1->private_dict.blue_fuzz = 1; 1679*37da2899SCharles.Forsyth 1680*37da2899SCharles.Forsyth parser = &loader.parser; 1681*37da2899SCharles.Forsyth error = T1_New_Parser( parser, 1682*37da2899SCharles.Forsyth face->root.stream, 1683*37da2899SCharles.Forsyth face->root.memory, 1684*37da2899SCharles.Forsyth psaux ); 1685*37da2899SCharles.Forsyth if ( error ) 1686*37da2899SCharles.Forsyth goto Exit; 1687*37da2899SCharles.Forsyth 1688*37da2899SCharles.Forsyth error = parse_dict( face, &loader, parser->base_dict, parser->base_len ); 1689*37da2899SCharles.Forsyth if ( error ) 1690*37da2899SCharles.Forsyth goto Exit; 1691*37da2899SCharles.Forsyth 1692*37da2899SCharles.Forsyth error = T1_Get_Private_Dict( parser, psaux ); 1693*37da2899SCharles.Forsyth if ( error ) 1694*37da2899SCharles.Forsyth goto Exit; 1695*37da2899SCharles.Forsyth 1696*37da2899SCharles.Forsyth error = parse_dict( face, &loader, parser->private_dict, 1697*37da2899SCharles.Forsyth parser->private_len ); 1698*37da2899SCharles.Forsyth if ( error ) 1699*37da2899SCharles.Forsyth goto Exit; 1700*37da2899SCharles.Forsyth 1701*37da2899SCharles.Forsyth /* now, propagate the subrs, charstrings, and glyphnames tables */ 1702*37da2899SCharles.Forsyth /* to the Type1 data */ 1703*37da2899SCharles.Forsyth type1->num_glyphs = loader.num_glyphs; 1704*37da2899SCharles.Forsyth 1705*37da2899SCharles.Forsyth if ( loader.subrs.init ) 1706*37da2899SCharles.Forsyth { 1707*37da2899SCharles.Forsyth loader.subrs.init = 0; 1708*37da2899SCharles.Forsyth type1->num_subrs = loader.num_subrs; 1709*37da2899SCharles.Forsyth type1->subrs_block = loader.subrs.block; 1710*37da2899SCharles.Forsyth type1->subrs = loader.subrs.elements; 1711*37da2899SCharles.Forsyth type1->subrs_len = loader.subrs.lengths; 1712*37da2899SCharles.Forsyth } 1713*37da2899SCharles.Forsyth 1714*37da2899SCharles.Forsyth #ifdef FT_CONFIG_OPTION_INCREMENTAL 1715*37da2899SCharles.Forsyth if ( !face->root.internal->incremental_interface ) 1716*37da2899SCharles.Forsyth #endif 1717*37da2899SCharles.Forsyth if ( !loader.charstrings.init ) 1718*37da2899SCharles.Forsyth { 1719*37da2899SCharles.Forsyth FT_ERROR(( "T1_Open_Face: no charstrings array in face!\n" )); 1720*37da2899SCharles.Forsyth error = T1_Err_Invalid_File_Format; 1721*37da2899SCharles.Forsyth } 1722*37da2899SCharles.Forsyth 1723*37da2899SCharles.Forsyth loader.charstrings.init = 0; 1724*37da2899SCharles.Forsyth type1->charstrings_block = loader.charstrings.block; 1725*37da2899SCharles.Forsyth type1->charstrings = loader.charstrings.elements; 1726*37da2899SCharles.Forsyth type1->charstrings_len = loader.charstrings.lengths; 1727*37da2899SCharles.Forsyth 1728*37da2899SCharles.Forsyth /* we copy the glyph names `block' and `elements' fields; */ 1729*37da2899SCharles.Forsyth /* the `lengths' field must be released later */ 1730*37da2899SCharles.Forsyth type1->glyph_names_block = loader.glyph_names.block; 1731*37da2899SCharles.Forsyth type1->glyph_names = (FT_String**)loader.glyph_names.elements; 1732*37da2899SCharles.Forsyth loader.glyph_names.block = 0; 1733*37da2899SCharles.Forsyth loader.glyph_names.elements = 0; 1734*37da2899SCharles.Forsyth 1735*37da2899SCharles.Forsyth /* we must now build type1.encoding when we have a custom array */ 1736*37da2899SCharles.Forsyth if ( type1->encoding_type == T1_ENCODING_TYPE_ARRAY ) 1737*37da2899SCharles.Forsyth { 1738*37da2899SCharles.Forsyth FT_Int charcode, idx, min_char, max_char; 1739*37da2899SCharles.Forsyth FT_Byte* char_name; 1740*37da2899SCharles.Forsyth FT_Byte* glyph_name; 1741*37da2899SCharles.Forsyth 1742*37da2899SCharles.Forsyth 1743*37da2899SCharles.Forsyth /* OK, we do the following: for each element in the encoding */ 1744*37da2899SCharles.Forsyth /* table, look up the index of the glyph having the same name */ 1745*37da2899SCharles.Forsyth /* the index is then stored in type1.encoding.char_index, and */ 1746*37da2899SCharles.Forsyth /* a the name to type1.encoding.char_name */ 1747*37da2899SCharles.Forsyth 1748*37da2899SCharles.Forsyth min_char = +32000; 1749*37da2899SCharles.Forsyth max_char = -32000; 1750*37da2899SCharles.Forsyth 1751*37da2899SCharles.Forsyth charcode = 0; 1752*37da2899SCharles.Forsyth for ( ; charcode < loader.encoding_table.max_elems; charcode++ ) 1753*37da2899SCharles.Forsyth { 1754*37da2899SCharles.Forsyth type1->encoding.char_index[charcode] = 0; 1755*37da2899SCharles.Forsyth type1->encoding.char_name [charcode] = (char *)".notdef"; 1756*37da2899SCharles.Forsyth 1757*37da2899SCharles.Forsyth char_name = loader.encoding_table.elements[charcode]; 1758*37da2899SCharles.Forsyth if ( char_name ) 1759*37da2899SCharles.Forsyth for ( idx = 0; idx < type1->num_glyphs; idx++ ) 1760*37da2899SCharles.Forsyth { 1761*37da2899SCharles.Forsyth glyph_name = (FT_Byte*)type1->glyph_names[idx]; 1762*37da2899SCharles.Forsyth if ( ft_strcmp( (const char*)char_name, 1763*37da2899SCharles.Forsyth (const char*)glyph_name ) == 0 ) 1764*37da2899SCharles.Forsyth { 1765*37da2899SCharles.Forsyth type1->encoding.char_index[charcode] = (FT_UShort)idx; 1766*37da2899SCharles.Forsyth type1->encoding.char_name [charcode] = (char*)glyph_name; 1767*37da2899SCharles.Forsyth 1768*37da2899SCharles.Forsyth /* Change min/max encoded char only if glyph name is */ 1769*37da2899SCharles.Forsyth /* not /.notdef */ 1770*37da2899SCharles.Forsyth if ( ft_strcmp( (const char*)".notdef", 1771*37da2899SCharles.Forsyth (const char*)glyph_name ) != 0 ) 1772*37da2899SCharles.Forsyth { 1773*37da2899SCharles.Forsyth if ( charcode < min_char ) min_char = charcode; 1774*37da2899SCharles.Forsyth if ( charcode > max_char ) max_char = charcode; 1775*37da2899SCharles.Forsyth } 1776*37da2899SCharles.Forsyth break; 1777*37da2899SCharles.Forsyth } 1778*37da2899SCharles.Forsyth } 1779*37da2899SCharles.Forsyth } 1780*37da2899SCharles.Forsyth type1->encoding.code_first = min_char; 1781*37da2899SCharles.Forsyth type1->encoding.code_last = max_char; 1782*37da2899SCharles.Forsyth type1->encoding.num_chars = loader.num_chars; 1783*37da2899SCharles.Forsyth } 1784*37da2899SCharles.Forsyth 1785*37da2899SCharles.Forsyth Exit: 1786*37da2899SCharles.Forsyth t1_done_loader( &loader ); 1787*37da2899SCharles.Forsyth return error; 1788*37da2899SCharles.Forsyth } 1789*37da2899SCharles.Forsyth 1790*37da2899SCharles.Forsyth 1791*37da2899SCharles.Forsyth /* END */ 1792