/src/freetype/src/sfnt/ttload.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 1267 lines · 734 code · 199 blank · 334 comment · 90 complexity · d241bfcb8b0b47a2a6de87710b65552d MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* ttload.c */
  4. /* */
  5. /* Load the basic TrueType tables, i.e., tables that can be either in */
  6. /* TTF or OTF fonts (body). */
  7. /* */
  8. /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, */
  9. /* 2010 by */
  10. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  11. /* */
  12. /* This file is part of the FreeType project, and may only be used, */
  13. /* modified, and distributed under the terms of the FreeType project */
  14. /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
  15. /* this file you indicate that you have read the license and */
  16. /* understand and accept it fully. */
  17. /* */
  18. /***************************************************************************/
  19. #include <ft2build.h>
  20. #include FT_INTERNAL_DEBUG_H
  21. #include FT_INTERNAL_STREAM_H
  22. #include FT_TRUETYPE_TAGS_H
  23. #include "ttload.h"
  24. #include "sferrors.h"
  25. /*************************************************************************/
  26. /* */
  27. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  28. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  29. /* messages during execution. */
  30. /* */
  31. #undef FT_COMPONENT
  32. #define FT_COMPONENT trace_ttload
  33. /*************************************************************************/
  34. /* */
  35. /* <Function> */
  36. /* tt_face_lookup_table */
  37. /* */
  38. /* <Description> */
  39. /* Looks for a TrueType table by name. */
  40. /* */
  41. /* <Input> */
  42. /* face :: A face object handle. */
  43. /* */
  44. /* tag :: The searched tag. */
  45. /* */
  46. /* <Return> */
  47. /* A pointer to the table directory entry. 0 if not found. */
  48. /* */
  49. FT_LOCAL_DEF( TT_Table )
  50. tt_face_lookup_table( TT_Face face,
  51. FT_ULong tag )
  52. {
  53. TT_Table entry;
  54. TT_Table limit;
  55. #ifdef FT_DEBUG_LEVEL_TRACE
  56. FT_Bool zero_length = FALSE;
  57. #endif
  58. FT_TRACE4(( "tt_face_lookup_table: %08p, `%c%c%c%c' -- ",
  59. face,
  60. (FT_Char)( tag >> 24 ),
  61. (FT_Char)( tag >> 16 ),
  62. (FT_Char)( tag >> 8 ),
  63. (FT_Char)( tag ) ));
  64. entry = face->dir_tables;
  65. limit = entry + face->num_tables;
  66. for ( ; entry < limit; entry++ )
  67. {
  68. /* For compatibility with Windows, we consider */
  69. /* zero-length tables the same as missing tables. */
  70. if ( entry->Tag == tag )
  71. {
  72. if ( entry->Length != 0 )
  73. {
  74. FT_TRACE4(( "found table.\n" ));
  75. return entry;
  76. }
  77. #ifdef FT_DEBUG_LEVEL_TRACE
  78. zero_length = TRUE;
  79. #endif
  80. }
  81. }
  82. #ifdef FT_DEBUG_LEVEL_TRACE
  83. if ( zero_length )
  84. FT_TRACE4(( "ignoring empty table\n" ));
  85. else
  86. FT_TRACE4(( "could not find table\n" ));
  87. #endif
  88. return NULL;
  89. }
  90. /*************************************************************************/
  91. /* */
  92. /* <Function> */
  93. /* tt_face_goto_table */
  94. /* */
  95. /* <Description> */
  96. /* Looks for a TrueType table by name, then seek a stream to it. */
  97. /* */
  98. /* <Input> */
  99. /* face :: A face object handle. */
  100. /* */
  101. /* tag :: The searched tag. */
  102. /* */
  103. /* stream :: The stream to seek when the table is found. */
  104. /* */
  105. /* <Output> */
  106. /* length :: The length of the table if found, undefined otherwise. */
  107. /* */
  108. /* <Return> */
  109. /* FreeType error code. 0 means success. */
  110. /* */
  111. FT_LOCAL_DEF( FT_Error )
  112. tt_face_goto_table( TT_Face face,
  113. FT_ULong tag,
  114. FT_Stream stream,
  115. FT_ULong* length )
  116. {
  117. TT_Table table;
  118. FT_Error error;
  119. table = tt_face_lookup_table( face, tag );
  120. if ( table )
  121. {
  122. if ( length )
  123. *length = table->Length;
  124. if ( FT_STREAM_SEEK( table->Offset ) )
  125. goto Exit;
  126. }
  127. else
  128. error = SFNT_Err_Table_Missing;
  129. Exit:
  130. return error;
  131. }
  132. /* Here, we */
  133. /* */
  134. /* - check that `num_tables' is valid (and adjust it if necessary) */
  135. /* */
  136. /* - look for a `head' table, check its size, and parse it to check */
  137. /* whether its `magic' field is correctly set */
  138. /* */
  139. /* - errors (except errors returned by stream handling) */
  140. /* */
  141. /* SFNT_Err_Unknown_File_Format: */
  142. /* no table is defined in directory, it is not sfnt-wrapped */
  143. /* data */
  144. /* SFNT_Err_Table_Missing: */
  145. /* table directory is valid, but essential tables */
  146. /* (head/bhed/SING) are missing */
  147. /* */
  148. static FT_Error
  149. check_table_dir( SFNT_Header sfnt,
  150. FT_Stream stream )
  151. {
  152. FT_Error error;
  153. FT_UShort nn, valid_entries = 0;
  154. FT_UInt has_head = 0, has_sing = 0, has_meta = 0;
  155. FT_ULong offset = sfnt->offset + 12;
  156. static const FT_Frame_Field table_dir_entry_fields[] =
  157. {
  158. #undef FT_STRUCTURE
  159. #define FT_STRUCTURE TT_TableRec
  160. FT_FRAME_START( 16 ),
  161. FT_FRAME_ULONG( Tag ),
  162. FT_FRAME_ULONG( CheckSum ),
  163. FT_FRAME_ULONG( Offset ),
  164. FT_FRAME_ULONG( Length ),
  165. FT_FRAME_END
  166. };
  167. if ( FT_STREAM_SEEK( offset ) )
  168. goto Exit;
  169. for ( nn = 0; nn < sfnt->num_tables; nn++ )
  170. {
  171. TT_TableRec table;
  172. if ( FT_STREAM_READ_FIELDS( table_dir_entry_fields, &table ) )
  173. {
  174. nn--;
  175. FT_TRACE2(( "check_table_dir:"
  176. " can read only %d table%s in font (instead of %d)\n",
  177. nn, nn == 1 ? "" : "s", sfnt->num_tables ));
  178. sfnt->num_tables = nn;
  179. break;
  180. }
  181. /* we ignore invalid tables */
  182. if ( table.Offset + table.Length > stream->size )
  183. {
  184. FT_TRACE2(( "check_table_dir: table entry %d invalid\n", nn ));
  185. continue;
  186. }
  187. else
  188. valid_entries++;
  189. if ( table.Tag == TTAG_head || table.Tag == TTAG_bhed )
  190. {
  191. FT_UInt32 magic;
  192. #ifndef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  193. if ( table.Tag == TTAG_head )
  194. #endif
  195. has_head = 1;
  196. /*
  197. * The table length should be 0x36, but certain font tools make it
  198. * 0x38, so we will just check that it is greater.
  199. *
  200. * Note that according to the specification, the table must be
  201. * padded to 32-bit lengths, but this doesn't apply to the value of
  202. * its `Length' field!
  203. *
  204. */
  205. if ( table.Length < 0x36 )
  206. {
  207. FT_TRACE2(( "check_table_dir: `head' table too small\n" ));
  208. error = SFNT_Err_Table_Missing;
  209. goto Exit;
  210. }
  211. if ( FT_STREAM_SEEK( table.Offset + 12 ) ||
  212. FT_READ_ULONG( magic ) )
  213. goto Exit;
  214. if ( magic != 0x5F0F3CF5UL )
  215. {
  216. FT_TRACE2(( "check_table_dir:"
  217. " no magic number found in `head' table\n"));
  218. error = SFNT_Err_Table_Missing;
  219. goto Exit;
  220. }
  221. if ( FT_STREAM_SEEK( offset + ( nn + 1 ) * 16 ) )
  222. goto Exit;
  223. }
  224. else if ( table.Tag == TTAG_SING )
  225. has_sing = 1;
  226. else if ( table.Tag == TTAG_META )
  227. has_meta = 1;
  228. }
  229. sfnt->num_tables = valid_entries;
  230. if ( sfnt->num_tables == 0 )
  231. {
  232. FT_TRACE2(( "check_table_dir: no tables found\n" ));
  233. error = SFNT_Err_Unknown_File_Format;
  234. goto Exit;
  235. }
  236. /* if `sing' and `meta' tables are present, there is no `head' table */
  237. if ( has_head || ( has_sing && has_meta ) )
  238. {
  239. error = SFNT_Err_Ok;
  240. goto Exit;
  241. }
  242. else
  243. {
  244. FT_TRACE2(( "check_table_dir:" ));
  245. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  246. FT_TRACE2(( " neither `head', `bhed', nor `sing' table found\n" ));
  247. #else
  248. FT_TRACE2(( " neither `head' nor `sing' table found\n" ));
  249. #endif
  250. error = SFNT_Err_Table_Missing;
  251. }
  252. Exit:
  253. return error;
  254. }
  255. /*************************************************************************/
  256. /* */
  257. /* <Function> */
  258. /* tt_face_load_font_dir */
  259. /* */
  260. /* <Description> */
  261. /* Loads the header of a SFNT font file. */
  262. /* */
  263. /* <Input> */
  264. /* face :: A handle to the target face object. */
  265. /* */
  266. /* stream :: The input stream. */
  267. /* */
  268. /* <Output> */
  269. /* sfnt :: The SFNT header. */
  270. /* */
  271. /* <Return> */
  272. /* FreeType error code. 0 means success. */
  273. /* */
  274. /* <Note> */
  275. /* The stream cursor must be at the beginning of the font directory. */
  276. /* */
  277. FT_LOCAL_DEF( FT_Error )
  278. tt_face_load_font_dir( TT_Face face,
  279. FT_Stream stream )
  280. {
  281. SFNT_HeaderRec sfnt;
  282. FT_Error error;
  283. FT_Memory memory = stream->memory;
  284. TT_TableRec* entry;
  285. FT_Int nn;
  286. static const FT_Frame_Field offset_table_fields[] =
  287. {
  288. #undef FT_STRUCTURE
  289. #define FT_STRUCTURE SFNT_HeaderRec
  290. FT_FRAME_START( 8 ),
  291. FT_FRAME_USHORT( num_tables ),
  292. FT_FRAME_USHORT( search_range ),
  293. FT_FRAME_USHORT( entry_selector ),
  294. FT_FRAME_USHORT( range_shift ),
  295. FT_FRAME_END
  296. };
  297. FT_TRACE2(( "tt_face_load_font_dir: %08p\n", face ));
  298. /* read the offset table */
  299. sfnt.offset = FT_STREAM_POS();
  300. if ( FT_READ_ULONG( sfnt.format_tag ) ||
  301. FT_STREAM_READ_FIELDS( offset_table_fields, &sfnt ) )
  302. goto Exit;
  303. /* many fonts don't have these fields set correctly */
  304. #if 0
  305. if ( sfnt.search_range != 1 << ( sfnt.entry_selector + 4 ) ||
  306. sfnt.search_range + sfnt.range_shift != sfnt.num_tables << 4 )
  307. return SFNT_Err_Unknown_File_Format;
  308. #endif
  309. /* load the table directory */
  310. FT_TRACE2(( "-- Number of tables: %10u\n", sfnt.num_tables ));
  311. FT_TRACE2(( "-- Format version: 0x%08lx\n", sfnt.format_tag ));
  312. /* check first */
  313. error = check_table_dir( &sfnt, stream );
  314. if ( error )
  315. {
  316. FT_TRACE2(( "tt_face_load_font_dir:"
  317. " invalid table directory for TrueType\n" ));
  318. goto Exit;
  319. }
  320. face->num_tables = sfnt.num_tables;
  321. face->format_tag = sfnt.format_tag;
  322. if ( FT_QNEW_ARRAY( face->dir_tables, face->num_tables ) )
  323. goto Exit;
  324. if ( FT_STREAM_SEEK( sfnt.offset + 12 ) ||
  325. FT_FRAME_ENTER( face->num_tables * 16L ) )
  326. goto Exit;
  327. entry = face->dir_tables;
  328. FT_TRACE2(( "\n"
  329. " tag offset length checksum\n"
  330. " ----------------------------------\n" ));
  331. for ( nn = 0; nn < sfnt.num_tables; nn++ )
  332. {
  333. entry->Tag = FT_GET_TAG4();
  334. entry->CheckSum = FT_GET_ULONG();
  335. entry->Offset = FT_GET_LONG();
  336. entry->Length = FT_GET_LONG();
  337. /* ignore invalid tables */
  338. if ( entry->Offset + entry->Length > stream->size )
  339. continue;
  340. else
  341. {
  342. FT_TRACE2(( " %c%c%c%c %08lx %08lx %08lx\n",
  343. (FT_Char)( entry->Tag >> 24 ),
  344. (FT_Char)( entry->Tag >> 16 ),
  345. (FT_Char)( entry->Tag >> 8 ),
  346. (FT_Char)( entry->Tag ),
  347. entry->Offset,
  348. entry->Length,
  349. entry->CheckSum ));
  350. entry++;
  351. }
  352. }
  353. FT_FRAME_EXIT();
  354. FT_TRACE2(( "table directory loaded\n\n" ));
  355. Exit:
  356. return error;
  357. }
  358. /*************************************************************************/
  359. /* */
  360. /* <Function> */
  361. /* tt_face_load_any */
  362. /* */
  363. /* <Description> */
  364. /* Loads any font table into client memory. */
  365. /* */
  366. /* <Input> */
  367. /* face :: The face object to look for. */
  368. /* */
  369. /* tag :: The tag of table to load. Use the value 0 if you want */
  370. /* to access the whole font file, else set this parameter */
  371. /* to a valid TrueType table tag that you can forge with */
  372. /* the MAKE_TT_TAG macro. */
  373. /* */
  374. /* offset :: The starting offset in the table (or the file if */
  375. /* tag == 0). */
  376. /* */
  377. /* length :: The address of the decision variable: */
  378. /* */
  379. /* If length == NULL: */
  380. /* Loads the whole table. Returns an error if */
  381. /* `offset' == 0! */
  382. /* */
  383. /* If *length == 0: */
  384. /* Exits immediately; returning the length of the given */
  385. /* table or of the font file, depending on the value of */
  386. /* `tag'. */
  387. /* */
  388. /* If *length != 0: */
  389. /* Loads the next `length' bytes of table or font, */
  390. /* starting at offset `offset' (in table or font too). */
  391. /* */
  392. /* <Output> */
  393. /* buffer :: The address of target buffer. */
  394. /* */
  395. /* <Return> */
  396. /* FreeType error code. 0 means success. */
  397. /* */
  398. FT_LOCAL_DEF( FT_Error )
  399. tt_face_load_any( TT_Face face,
  400. FT_ULong tag,
  401. FT_Long offset,
  402. FT_Byte* buffer,
  403. FT_ULong* length )
  404. {
  405. FT_Error error;
  406. FT_Stream stream;
  407. TT_Table table;
  408. FT_ULong size;
  409. if ( tag != 0 )
  410. {
  411. /* look for tag in font directory */
  412. table = tt_face_lookup_table( face, tag );
  413. if ( !table )
  414. {
  415. error = SFNT_Err_Table_Missing;
  416. goto Exit;
  417. }
  418. offset += table->Offset;
  419. size = table->Length;
  420. }
  421. else
  422. /* tag == 0 -- the user wants to access the font file directly */
  423. size = face->root.stream->size;
  424. if ( length && *length == 0 )
  425. {
  426. *length = size;
  427. return SFNT_Err_Ok;
  428. }
  429. if ( length )
  430. size = *length;
  431. stream = face->root.stream;
  432. /* the `if' is syntactic sugar for picky compilers */
  433. if ( FT_STREAM_READ_AT( offset, buffer, size ) )
  434. goto Exit;
  435. Exit:
  436. return error;
  437. }
  438. /*************************************************************************/
  439. /* */
  440. /* <Function> */
  441. /* tt_face_load_generic_header */
  442. /* */
  443. /* <Description> */
  444. /* Loads the TrueType table `head' or `bhed'. */
  445. /* */
  446. /* <Input> */
  447. /* face :: A handle to the target face object. */
  448. /* */
  449. /* stream :: The input stream. */
  450. /* */
  451. /* <Return> */
  452. /* FreeType error code. 0 means success. */
  453. /* */
  454. static FT_Error
  455. tt_face_load_generic_header( TT_Face face,
  456. FT_Stream stream,
  457. FT_ULong tag )
  458. {
  459. FT_Error error;
  460. TT_Header* header;
  461. static const FT_Frame_Field header_fields[] =
  462. {
  463. #undef FT_STRUCTURE
  464. #define FT_STRUCTURE TT_Header
  465. FT_FRAME_START( 54 ),
  466. FT_FRAME_ULONG ( Table_Version ),
  467. FT_FRAME_ULONG ( Font_Revision ),
  468. FT_FRAME_LONG ( CheckSum_Adjust ),
  469. FT_FRAME_LONG ( Magic_Number ),
  470. FT_FRAME_USHORT( Flags ),
  471. FT_FRAME_USHORT( Units_Per_EM ),
  472. FT_FRAME_LONG ( Created[0] ),
  473. FT_FRAME_LONG ( Created[1] ),
  474. FT_FRAME_LONG ( Modified[0] ),
  475. FT_FRAME_LONG ( Modified[1] ),
  476. FT_FRAME_SHORT ( xMin ),
  477. FT_FRAME_SHORT ( yMin ),
  478. FT_FRAME_SHORT ( xMax ),
  479. FT_FRAME_SHORT ( yMax ),
  480. FT_FRAME_USHORT( Mac_Style ),
  481. FT_FRAME_USHORT( Lowest_Rec_PPEM ),
  482. FT_FRAME_SHORT ( Font_Direction ),
  483. FT_FRAME_SHORT ( Index_To_Loc_Format ),
  484. FT_FRAME_SHORT ( Glyph_Data_Format ),
  485. FT_FRAME_END
  486. };
  487. error = face->goto_table( face, tag, stream, 0 );
  488. if ( error )
  489. goto Exit;
  490. header = &face->header;
  491. if ( FT_STREAM_READ_FIELDS( header_fields, header ) )
  492. goto Exit;
  493. FT_TRACE3(( "Units per EM: %4u\n", header->Units_Per_EM ));
  494. FT_TRACE3(( "IndexToLoc: %4d\n", header->Index_To_Loc_Format ));
  495. Exit:
  496. return error;
  497. }
  498. FT_LOCAL_DEF( FT_Error )
  499. tt_face_load_head( TT_Face face,
  500. FT_Stream stream )
  501. {
  502. return tt_face_load_generic_header( face, stream, TTAG_head );
  503. }
  504. #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
  505. FT_LOCAL_DEF( FT_Error )
  506. tt_face_load_bhed( TT_Face face,
  507. FT_Stream stream )
  508. {
  509. return tt_face_load_generic_header( face, stream, TTAG_bhed );
  510. }
  511. #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
  512. /*************************************************************************/
  513. /* */
  514. /* <Function> */
  515. /* tt_face_load_max_profile */
  516. /* */
  517. /* <Description> */
  518. /* Loads the maximum profile into a face object. */
  519. /* */
  520. /* <Input> */
  521. /* face :: A handle to the target face object. */
  522. /* */
  523. /* stream :: The input stream. */
  524. /* */
  525. /* <Return> */
  526. /* FreeType error code. 0 means success. */
  527. /* */
  528. FT_LOCAL_DEF( FT_Error )
  529. tt_face_load_maxp( TT_Face face,
  530. FT_Stream stream )
  531. {
  532. FT_Error error;
  533. TT_MaxProfile* maxProfile = &face->max_profile;
  534. const FT_Frame_Field maxp_fields[] =
  535. {
  536. #undef FT_STRUCTURE
  537. #define FT_STRUCTURE TT_MaxProfile
  538. FT_FRAME_START( 6 ),
  539. FT_FRAME_LONG ( version ),
  540. FT_FRAME_USHORT( numGlyphs ),
  541. FT_FRAME_END
  542. };
  543. const FT_Frame_Field maxp_fields_extra[] =
  544. {
  545. FT_FRAME_START( 26 ),
  546. FT_FRAME_USHORT( maxPoints ),
  547. FT_FRAME_USHORT( maxContours ),
  548. FT_FRAME_USHORT( maxCompositePoints ),
  549. FT_FRAME_USHORT( maxCompositeContours ),
  550. FT_FRAME_USHORT( maxZones ),
  551. FT_FRAME_USHORT( maxTwilightPoints ),
  552. FT_FRAME_USHORT( maxStorage ),
  553. FT_FRAME_USHORT( maxFunctionDefs ),
  554. FT_FRAME_USHORT( maxInstructionDefs ),
  555. FT_FRAME_USHORT( maxStackElements ),
  556. FT_FRAME_USHORT( maxSizeOfInstructions ),
  557. FT_FRAME_USHORT( maxComponentElements ),
  558. FT_FRAME_USHORT( maxComponentDepth ),
  559. FT_FRAME_END
  560. };
  561. error = face->goto_table( face, TTAG_maxp, stream, 0 );
  562. if ( error )
  563. goto Exit;
  564. if ( FT_STREAM_READ_FIELDS( maxp_fields, maxProfile ) )
  565. goto Exit;
  566. maxProfile->maxPoints = 0;
  567. maxProfile->maxContours = 0;
  568. maxProfile->maxCompositePoints = 0;
  569. maxProfile->maxCompositeContours = 0;
  570. maxProfile->maxZones = 0;
  571. maxProfile->maxTwilightPoints = 0;
  572. maxProfile->maxStorage = 0;
  573. maxProfile->maxFunctionDefs = 0;
  574. maxProfile->maxInstructionDefs = 0;
  575. maxProfile->maxStackElements = 0;
  576. maxProfile->maxSizeOfInstructions = 0;
  577. maxProfile->maxComponentElements = 0;
  578. maxProfile->maxComponentDepth = 0;
  579. if ( maxProfile->version >= 0x10000L )
  580. {
  581. if ( FT_STREAM_READ_FIELDS( maxp_fields_extra, maxProfile ) )
  582. goto Exit;
  583. /* XXX: an adjustment that is necessary to load certain */
  584. /* broken fonts like `Keystrokes MT' :-( */
  585. /* */
  586. /* We allocate 64 function entries by default when */
  587. /* the maxFunctionDefs value is smaller. */
  588. if ( maxProfile->maxFunctionDefs < 64 )
  589. maxProfile->maxFunctionDefs = 64;
  590. /* we add 4 phantom points later */
  591. if ( maxProfile->maxTwilightPoints > ( 0xFFFFU - 4 ) )
  592. {
  593. FT_TRACE0(( "tt_face_load_maxp:"
  594. " too much twilight points in `maxp' table;\n"
  595. " "
  596. " some glyphs might be rendered incorrectly\n" ));
  597. maxProfile->maxTwilightPoints = 0xFFFFU - 4;
  598. }
  599. /* we arbitrarily limit recursion to avoid stack exhaustion */
  600. if ( maxProfile->maxComponentDepth > 100 )
  601. {
  602. FT_TRACE0(( "tt_face_load_maxp:"
  603. " abnormally large component depth (%d) set to 100\n",
  604. maxProfile->maxComponentDepth ));
  605. maxProfile->maxComponentDepth = 100;
  606. }
  607. }
  608. FT_TRACE3(( "numGlyphs: %u\n", maxProfile->numGlyphs ));
  609. Exit:
  610. return error;
  611. }
  612. /*************************************************************************/
  613. /* */
  614. /* <Function> */
  615. /* tt_face_load_names */
  616. /* */
  617. /* <Description> */
  618. /* Loads the name records. */
  619. /* */
  620. /* <Input> */
  621. /* face :: A handle to the target face object. */
  622. /* */
  623. /* stream :: The input stream. */
  624. /* */
  625. /* <Return> */
  626. /* FreeType error code. 0 means success. */
  627. /* */
  628. FT_LOCAL_DEF( FT_Error )
  629. tt_face_load_name( TT_Face face,
  630. FT_Stream stream )
  631. {
  632. FT_Error error;
  633. FT_Memory memory = stream->memory;
  634. FT_ULong table_pos, table_len;
  635. FT_ULong storage_start, storage_limit;
  636. FT_UInt count;
  637. TT_NameTable table;
  638. static const FT_Frame_Field name_table_fields[] =
  639. {
  640. #undef FT_STRUCTURE
  641. #define FT_STRUCTURE TT_NameTableRec
  642. FT_FRAME_START( 6 ),
  643. FT_FRAME_USHORT( format ),
  644. FT_FRAME_USHORT( numNameRecords ),
  645. FT_FRAME_USHORT( storageOffset ),
  646. FT_FRAME_END
  647. };
  648. static const FT_Frame_Field name_record_fields[] =
  649. {
  650. #undef FT_STRUCTURE
  651. #define FT_STRUCTURE TT_NameEntryRec
  652. /* no FT_FRAME_START */
  653. FT_FRAME_USHORT( platformID ),
  654. FT_FRAME_USHORT( encodingID ),
  655. FT_FRAME_USHORT( languageID ),
  656. FT_FRAME_USHORT( nameID ),
  657. FT_FRAME_USHORT( stringLength ),
  658. FT_FRAME_USHORT( stringOffset ),
  659. FT_FRAME_END
  660. };
  661. table = &face->name_table;
  662. table->stream = stream;
  663. error = face->goto_table( face, TTAG_name, stream, &table_len );
  664. if ( error )
  665. goto Exit;
  666. table_pos = FT_STREAM_POS();
  667. if ( FT_STREAM_READ_FIELDS( name_table_fields, table ) )
  668. goto Exit;
  669. /* Some popular Asian fonts have an invalid `storageOffset' value */
  670. /* (it should be at least "6 + 12*num_names"). However, the string */
  671. /* offsets, computed as "storageOffset + entry->stringOffset", are */
  672. /* valid pointers within the name table... */
  673. /* */
  674. /* We thus can't check `storageOffset' right now. */
  675. /* */
  676. storage_start = table_pos + 6 + 12*table->numNameRecords;
  677. storage_limit = table_pos + table_len;
  678. if ( storage_start > storage_limit )
  679. {
  680. FT_ERROR(( "tt_face_load_name: invalid `name' table\n" ));
  681. error = SFNT_Err_Name_Table_Missing;
  682. goto Exit;
  683. }
  684. /* Allocate the array of name records. */
  685. count = table->numNameRecords;
  686. table->numNameRecords = 0;
  687. if ( FT_NEW_ARRAY( table->names, count ) ||
  688. FT_FRAME_ENTER( count * 12 ) )
  689. goto Exit;
  690. /* Load the name records and determine how much storage is needed */
  691. /* to hold the strings themselves. */
  692. {
  693. TT_NameEntryRec* entry = table->names;
  694. for ( ; count > 0; count-- )
  695. {
  696. if ( FT_STREAM_READ_FIELDS( name_record_fields, entry ) )
  697. continue;
  698. /* check that the name is not empty */
  699. if ( entry->stringLength == 0 )
  700. continue;
  701. /* check that the name string is within the table */
  702. entry->stringOffset += table_pos + table->storageOffset;
  703. if ( entry->stringOffset < storage_start ||
  704. entry->stringOffset + entry->stringLength > storage_limit )
  705. {
  706. /* invalid entry - ignore it */
  707. entry->stringOffset = 0;
  708. entry->stringLength = 0;
  709. continue;
  710. }
  711. entry++;
  712. }
  713. table->numNameRecords = (FT_UInt)( entry - table->names );
  714. }
  715. FT_FRAME_EXIT();
  716. /* everything went well, update face->num_names */
  717. face->num_names = (FT_UShort) table->numNameRecords;
  718. Exit:
  719. return error;
  720. }
  721. /*************************************************************************/
  722. /* */
  723. /* <Function> */
  724. /* tt_face_free_names */
  725. /* */
  726. /* <Description> */
  727. /* Frees the name records. */
  728. /* */
  729. /* <Input> */
  730. /* face :: A handle to the target face object. */
  731. /* */
  732. FT_LOCAL_DEF( void )
  733. tt_face_free_name( TT_Face face )
  734. {
  735. FT_Memory memory = face->root.driver->root.memory;
  736. TT_NameTable table = &face->name_table;
  737. TT_NameEntry entry = table->names;
  738. FT_UInt count = table->numNameRecords;
  739. if ( table->names )
  740. {
  741. for ( ; count > 0; count--, entry++ )
  742. {
  743. FT_FREE( entry->string );
  744. entry->stringLength = 0;
  745. }
  746. /* free strings table */
  747. FT_FREE( table->names );
  748. }
  749. table->numNameRecords = 0;
  750. table->format = 0;
  751. table->storageOffset = 0;
  752. }
  753. /*************************************************************************/
  754. /* */
  755. /* <Function> */
  756. /* tt_face_load_cmap */
  757. /* */
  758. /* <Description> */
  759. /* Loads the cmap directory in a face object. The cmaps themselves */
  760. /* are loaded on demand in the `ttcmap.c' module. */
  761. /* */
  762. /* <Input> */
  763. /* face :: A handle to the target face object. */
  764. /* */
  765. /* stream :: A handle to the input stream. */
  766. /* */
  767. /* <Return> */
  768. /* FreeType error code. 0 means success. */
  769. /* */
  770. FT_LOCAL_DEF( FT_Error )
  771. tt_face_load_cmap( TT_Face face,
  772. FT_Stream stream )
  773. {
  774. FT_Error error;
  775. error = face->goto_table( face, TTAG_cmap, stream, &face->cmap_size );
  776. if ( error )
  777. goto Exit;
  778. if ( FT_FRAME_EXTRACT( face->cmap_size, face->cmap_table ) )
  779. face->cmap_size = 0;
  780. Exit:
  781. return error;
  782. }
  783. /*************************************************************************/
  784. /* */
  785. /* <Function> */
  786. /* tt_face_load_os2 */
  787. /* */
  788. /* <Description> */
  789. /* Loads the OS2 table. */
  790. /* */
  791. /* <Input> */
  792. /* face :: A handle to the target face object. */
  793. /* */
  794. /* stream :: A handle to the input stream. */
  795. /* */
  796. /* <Return> */
  797. /* FreeType error code. 0 means success. */
  798. /* */
  799. FT_LOCAL_DEF( FT_Error )
  800. tt_face_load_os2( TT_Face face,
  801. FT_Stream stream )
  802. {
  803. FT_Error error;
  804. TT_OS2* os2;
  805. const FT_Frame_Field os2_fields[] =
  806. {
  807. #undef FT_STRUCTURE
  808. #define FT_STRUCTURE TT_OS2
  809. FT_FRAME_START( 78 ),
  810. FT_FRAME_USHORT( version ),
  811. FT_FRAME_SHORT ( xAvgCharWidth ),
  812. FT_FRAME_USHORT( usWeightClass ),
  813. FT_FRAME_USHORT( usWidthClass ),
  814. FT_FRAME_SHORT ( fsType ),
  815. FT_FRAME_SHORT ( ySubscriptXSize ),
  816. FT_FRAME_SHORT ( ySubscriptYSize ),
  817. FT_FRAME_SHORT ( ySubscriptXOffset ),
  818. FT_FRAME_SHORT ( ySubscriptYOffset ),
  819. FT_FRAME_SHORT ( ySuperscriptXSize ),
  820. FT_FRAME_SHORT ( ySuperscriptYSize ),
  821. FT_FRAME_SHORT ( ySuperscriptXOffset ),
  822. FT_FRAME_SHORT ( ySuperscriptYOffset ),
  823. FT_FRAME_SHORT ( yStrikeoutSize ),
  824. FT_FRAME_SHORT ( yStrikeoutPosition ),
  825. FT_FRAME_SHORT ( sFamilyClass ),
  826. FT_FRAME_BYTE ( panose[0] ),
  827. FT_FRAME_BYTE ( panose[1] ),
  828. FT_FRAME_BYTE ( panose[2] ),
  829. FT_FRAME_BYTE ( panose[3] ),
  830. FT_FRAME_BYTE ( panose[4] ),
  831. FT_FRAME_BYTE ( panose[5] ),
  832. FT_FRAME_BYTE ( panose[6] ),
  833. FT_FRAME_BYTE ( panose[7] ),
  834. FT_FRAME_BYTE ( panose[8] ),
  835. FT_FRAME_BYTE ( panose[9] ),
  836. FT_FRAME_ULONG ( ulUnicodeRange1 ),
  837. FT_FRAME_ULONG ( ulUnicodeRange2 ),
  838. FT_FRAME_ULONG ( ulUnicodeRange3 ),
  839. FT_FRAME_ULONG ( ulUnicodeRange4 ),
  840. FT_FRAME_BYTE ( achVendID[0] ),
  841. FT_FRAME_BYTE ( achVendID[1] ),
  842. FT_FRAME_BYTE ( achVendID[2] ),
  843. FT_FRAME_BYTE ( achVendID[3] ),
  844. FT_FRAME_USHORT( fsSelection ),
  845. FT_FRAME_USHORT( usFirstCharIndex ),
  846. FT_FRAME_USHORT( usLastCharIndex ),
  847. FT_FRAME_SHORT ( sTypoAscender ),
  848. FT_FRAME_SHORT ( sTypoDescender ),
  849. FT_FRAME_SHORT ( sTypoLineGap ),
  850. FT_FRAME_USHORT( usWinAscent ),
  851. FT_FRAME_USHORT( usWinDescent ),
  852. FT_FRAME_END
  853. };
  854. const FT_Frame_Field os2_fields_extra[] =
  855. {
  856. FT_FRAME_START( 8 ),
  857. FT_FRAME_ULONG( ulCodePageRange1 ),
  858. FT_FRAME_ULONG( ulCodePageRange2 ),
  859. FT_FRAME_END
  860. };
  861. const FT_Frame_Field os2_fields_extra2[] =
  862. {
  863. FT_FRAME_START( 10 ),
  864. FT_FRAME_SHORT ( sxHeight ),
  865. FT_FRAME_SHORT ( sCapHeight ),
  866. FT_FRAME_USHORT( usDefaultChar ),
  867. FT_FRAME_USHORT( usBreakChar ),
  868. FT_FRAME_USHORT( usMaxContext ),
  869. FT_FRAME_END
  870. };
  871. /* We now support old Mac fonts where the OS/2 table doesn't */
  872. /* exist. Simply put, we set the `version' field to 0xFFFF */
  873. /* and test this value each time we need to access the table. */
  874. error = face->goto_table( face, TTAG_OS2, stream, 0 );
  875. if ( error )
  876. goto Exit;
  877. os2 = &face->os2;
  878. if ( FT_STREAM_READ_FIELDS( os2_fields, os2 ) )
  879. goto Exit;
  880. os2->ulCodePageRange1 = 0;
  881. os2->ulCodePageRange2 = 0;
  882. os2->sxHeight = 0;
  883. os2->sCapHeight = 0;
  884. os2->usDefaultChar = 0;
  885. os2->usBreakChar = 0;
  886. os2->usMaxContext = 0;
  887. if ( os2->version >= 0x0001 )
  888. {
  889. /* only version 1 tables */
  890. if ( FT_STREAM_READ_FIELDS( os2_fields_extra, os2 ) )
  891. goto Exit;
  892. if ( os2->version >= 0x0002 )
  893. {
  894. /* only version 2 tables */
  895. if ( FT_STREAM_READ_FIELDS( os2_fields_extra2, os2 ) )
  896. goto Exit;
  897. }
  898. }
  899. FT_TRACE3(( "sTypoAscender: %4d\n", os2->sTypoAscender ));
  900. FT_TRACE3(( "sTypoDescender: %4d\n", os2->sTypoDescender ));
  901. FT_TRACE3(( "usWinAscent: %4u\n", os2->usWinAscent ));
  902. FT_TRACE3(( "usWinDescent: %4u\n", os2->usWinDescent ));
  903. FT_TRACE3(( "fsSelection: 0x%2x\n", os2->fsSelection ));
  904. Exit:
  905. return error;
  906. }
  907. /*************************************************************************/
  908. /* */
  909. /* <Function> */
  910. /* tt_face_load_postscript */
  911. /* */
  912. /* <Description> */
  913. /* Loads the Postscript table. */
  914. /* */
  915. /* <Input> */
  916. /* face :: A handle to the target face object. */
  917. /* */
  918. /* stream :: A handle to the input stream. */
  919. /* */
  920. /* <Return> */
  921. /* FreeType error code. 0 means success. */
  922. /* */
  923. FT_LOCAL_DEF( FT_Error )
  924. tt_face_load_post( TT_Face face,
  925. FT_Stream stream )
  926. {
  927. FT_Error error;
  928. TT_Postscript* post = &face->postscript;
  929. static const FT_Frame_Field post_fields[] =
  930. {
  931. #undef FT_STRUCTURE
  932. #define FT_STRUCTURE TT_Postscript
  933. FT_FRAME_START( 32 ),
  934. FT_FRAME_ULONG( FormatType ),
  935. FT_FRAME_ULONG( italicAngle ),
  936. FT_FRAME_SHORT( underlinePosition ),
  937. FT_FRAME_SHORT( underlineThickness ),
  938. FT_FRAME_ULONG( isFixedPitch ),
  939. FT_FRAME_ULONG( minMemType42 ),
  940. FT_FRAME_ULONG( maxMemType42 ),
  941. FT_FRAME_ULONG( minMemType1 ),
  942. FT_FRAME_ULONG( maxMemType1 ),
  943. FT_FRAME_END
  944. };
  945. error = face->goto_table( face, TTAG_post, stream, 0 );
  946. if ( error )
  947. return error;
  948. if ( FT_STREAM_READ_FIELDS( post_fields, post ) )
  949. return error;
  950. /* we don't load the glyph names, we do that in another */
  951. /* module (ttpost). */
  952. FT_TRACE3(( "FormatType: 0x%x\n", post->FormatType ));
  953. FT_TRACE3(( "isFixedPitch: %s\n", post->isFixedPitch
  954. ? " yes" : " no" ));
  955. return SFNT_Err_Ok;
  956. }
  957. /*************************************************************************/
  958. /* */
  959. /* <Function> */
  960. /* tt_face_load_pclt */
  961. /* */
  962. /* <Description> */
  963. /* Loads the PCL 5 Table. */
  964. /* */
  965. /* <Input> */
  966. /* face :: A handle to the target face object. */
  967. /* */
  968. /* stream :: A handle to the input stream. */
  969. /* */
  970. /* <Return> */
  971. /* FreeType error code. 0 means success. */
  972. /* */
  973. FT_LOCAL_DEF( FT_Error )
  974. tt_face_load_pclt( TT_Face face,
  975. FT_Stream stream )
  976. {
  977. static const FT_Frame_Field pclt_fields[] =
  978. {
  979. #undef FT_STRUCTURE
  980. #define FT_STRUCTURE TT_PCLT
  981. FT_FRAME_START( 54 ),
  982. FT_FRAME_ULONG ( Version ),
  983. FT_FRAME_ULONG ( FontNumber ),
  984. FT_FRAME_USHORT( Pitch ),
  985. FT_FRAME_USHORT( xHeight ),
  986. FT_FRAME_USHORT( Style ),
  987. FT_FRAME_USHORT( TypeFamily ),
  988. FT_FRAME_USHORT( CapHeight ),
  989. FT_FRAME_BYTES ( TypeFace, 16 ),
  990. FT_FRAME_BYTES ( CharacterComplement, 8 ),
  991. FT_FRAME_BYTES ( FileName, 6 ),
  992. FT_FRAME_CHAR ( StrokeWeight ),
  993. FT_FRAME_CHAR ( WidthType ),
  994. FT_FRAME_BYTE ( SerifStyle ),
  995. FT_FRAME_BYTE ( Reserved ),
  996. FT_FRAME_END
  997. };
  998. FT_Error error;
  999. TT_PCLT* pclt = &face->pclt;
  1000. /* optional table */
  1001. error = face->goto_table( face, TTAG_PCLT, stream, 0 );
  1002. if ( error )
  1003. goto Exit;
  1004. if ( FT_STREAM_READ_FIELDS( pclt_fields, pclt ) )
  1005. goto Exit;
  1006. Exit:
  1007. return error;
  1008. }
  1009. /*************************************************************************/
  1010. /* */
  1011. /* <Function> */
  1012. /* tt_face_load_gasp */
  1013. /* */
  1014. /* <Description> */
  1015. /* Loads the `gasp' table into a face object. */
  1016. /* */
  1017. /* <Input> */
  1018. /* face :: A handle to the target face object. */
  1019. /* */
  1020. /* stream :: The input stream. */
  1021. /* */
  1022. /* <Return> */
  1023. /* FreeType error code. 0 means success. */
  1024. /* */
  1025. FT_LOCAL_DEF( FT_Error )
  1026. tt_face_load_gasp( TT_Face face,
  1027. FT_Stream stream )
  1028. {
  1029. FT_Error error;
  1030. FT_Memory memory = stream->memory;
  1031. FT_UInt j,num_ranges;
  1032. TT_GaspRange gaspranges = NULL;
  1033. /* the gasp table is optional */
  1034. error = face->goto_table( face, TTAG_gasp, stream, 0 );
  1035. if ( error )
  1036. goto Exit;
  1037. if ( FT_FRAME_ENTER( 4L ) )
  1038. goto Exit;
  1039. face->gasp.version = FT_GET_USHORT();
  1040. face->gasp.numRanges = FT_GET_USHORT();
  1041. FT_FRAME_EXIT();
  1042. /* only support versions 0 and 1 of the table */
  1043. if ( face->gasp.version >= 2 )
  1044. {
  1045. face->gasp.numRanges = 0;
  1046. error = SFNT_Err_Invalid_Table;
  1047. goto Exit;
  1048. }
  1049. num_ranges = face->gasp.numRanges;
  1050. FT_TRACE3(( "numRanges: %u\n", num_ranges ));
  1051. if ( FT_QNEW_ARRAY( gaspranges, num_ranges ) ||
  1052. FT_FRAME_ENTER( num_ranges * 4L ) )
  1053. goto Exit;
  1054. face->gasp.gaspRanges = gaspranges;
  1055. for ( j = 0; j < num_ranges; j++ )
  1056. {
  1057. gaspranges[j].maxPPEM = FT_GET_USHORT();
  1058. gaspranges[j].gaspFlag = FT_GET_USHORT();
  1059. FT_TRACE3(( "gaspRange %d: rangeMaxPPEM %5d, rangeGaspBehavior 0x%x\n",
  1060. j,
  1061. gaspranges[j].maxPPEM,
  1062. gaspranges[j].gaspFlag ));
  1063. }
  1064. FT_FRAME_EXIT();
  1065. Exit:
  1066. return error;
  1067. }
  1068. /* END */