/src/freetype/src/type42/t42parse.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 1188 lines · 808 code · 243 blank · 137 comment · 176 complexity · 28658c5723a32a4b0af312672c0b066d MD5 · raw file

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