t42parse.c 28 KB

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