/src/freetype/src/truetype/ttpload.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 599 lines · 330 code · 125 blank · 144 comment · 51 complexity · 70dba1db87618755ccccf6ef1bef3a52 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* ttpload.c */
  4. /* */
  5. /* TrueType-specific tables loader (body). */
  6. /* */
  7. /* Copyright 1996-2002, 2004-2012 by */
  8. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  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 <ft2build.h>
  18. #include FT_INTERNAL_DEBUG_H
  19. #include FT_INTERNAL_OBJECTS_H
  20. #include FT_INTERNAL_STREAM_H
  21. #include FT_TRUETYPE_TAGS_H
  22. #include "ttpload.h"
  23. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  24. #include "ttgxvar.h"
  25. #endif
  26. #include "tterrors.h"
  27. /*************************************************************************/
  28. /* */
  29. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  30. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  31. /* messages during execution. */
  32. /* */
  33. #undef FT_COMPONENT
  34. #define FT_COMPONENT trace_ttpload
  35. /*************************************************************************/
  36. /* */
  37. /* <Function> */
  38. /* tt_face_load_loca */
  39. /* */
  40. /* <Description> */
  41. /* Load the locations table. */
  42. /* */
  43. /* <InOut> */
  44. /* face :: A handle to the target face object. */
  45. /* */
  46. /* <Input> */
  47. /* stream :: The input stream. */
  48. /* */
  49. /* <Return> */
  50. /* FreeType error code. 0 means success. */
  51. /* */
  52. FT_LOCAL_DEF( FT_Error )
  53. tt_face_load_loca( TT_Face face,
  54. FT_Stream stream )
  55. {
  56. FT_Error error;
  57. FT_ULong table_len;
  58. FT_Int shift;
  59. /* we need the size of the `glyf' table for malformed `loca' tables */
  60. error = face->goto_table( face, TTAG_glyf, stream, &face->glyf_len );
  61. /* it is possible that a font doesn't have a glyf table at all */
  62. /* or its size is zero */
  63. if ( error == TT_Err_Table_Missing )
  64. face->glyf_len = 0;
  65. else if ( error )
  66. goto Exit;
  67. FT_TRACE2(( "Locations " ));
  68. error = face->goto_table( face, TTAG_loca, stream, &table_len );
  69. if ( error )
  70. {
  71. error = TT_Err_Locations_Missing;
  72. goto Exit;
  73. }
  74. if ( face->header.Index_To_Loc_Format != 0 )
  75. {
  76. shift = 2;
  77. if ( table_len >= 0x40000L )
  78. {
  79. FT_TRACE2(( "table too large\n" ));
  80. error = TT_Err_Invalid_Table;
  81. goto Exit;
  82. }
  83. face->num_locations = table_len >> shift;
  84. }
  85. else
  86. {
  87. shift = 1;
  88. if ( table_len >= 0x20000L )
  89. {
  90. FT_TRACE2(( "table too large\n" ));
  91. error = TT_Err_Invalid_Table;
  92. goto Exit;
  93. }
  94. face->num_locations = table_len >> shift;
  95. }
  96. if ( face->num_locations != (FT_ULong)face->root.num_glyphs + 1 )
  97. {
  98. FT_TRACE2(( "glyph count mismatch! loca: %d, maxp: %d\n",
  99. face->num_locations - 1, face->root.num_glyphs ));
  100. /* we only handle the case where `maxp' gives a larger value */
  101. if ( face->num_locations <= (FT_ULong)face->root.num_glyphs )
  102. {
  103. FT_Long new_loca_len =
  104. ( (FT_Long)( face->root.num_glyphs ) + 1 ) << shift;
  105. TT_Table entry = face->dir_tables;
  106. TT_Table limit = entry + face->num_tables;
  107. FT_Long pos = FT_Stream_Pos( stream );
  108. FT_Long dist = 0x7FFFFFFFL;
  109. /* compute the distance to next table in font file */
  110. for ( ; entry < limit; entry++ )
  111. {
  112. FT_Long diff = entry->Offset - pos;
  113. if ( diff > 0 && diff < dist )
  114. dist = diff;
  115. }
  116. if ( entry == limit )
  117. {
  118. /* `loca' is the last table */
  119. dist = stream->size - pos;
  120. }
  121. if ( new_loca_len <= dist )
  122. {
  123. face->num_locations = face->root.num_glyphs + 1;
  124. table_len = new_loca_len;
  125. FT_TRACE2(( "adjusting num_locations to %d\n",
  126. face->num_locations ));
  127. }
  128. }
  129. }
  130. /*
  131. * Extract the frame. We don't need to decompress it since
  132. * we are able to parse it directly.
  133. */
  134. if ( FT_FRAME_EXTRACT( table_len, face->glyph_locations ) )
  135. goto Exit;
  136. FT_TRACE2(( "loaded\n" ));
  137. Exit:
  138. return error;
  139. }
  140. FT_LOCAL_DEF( FT_ULong )
  141. tt_face_get_location( TT_Face face,
  142. FT_UInt gindex,
  143. FT_UInt *asize )
  144. {
  145. FT_ULong pos1, pos2;
  146. FT_Byte* p;
  147. FT_Byte* p_limit;
  148. pos1 = pos2 = 0;
  149. if ( gindex < face->num_locations )
  150. {
  151. if ( face->header.Index_To_Loc_Format != 0 )
  152. {
  153. p = face->glyph_locations + gindex * 4;
  154. p_limit = face->glyph_locations + face->num_locations * 4;
  155. pos1 = FT_NEXT_ULONG( p );
  156. pos2 = pos1;
  157. if ( p + 4 <= p_limit )
  158. pos2 = FT_NEXT_ULONG( p );
  159. }
  160. else
  161. {
  162. p = face->glyph_locations + gindex * 2;
  163. p_limit = face->glyph_locations + face->num_locations * 2;
  164. pos1 = FT_NEXT_USHORT( p );
  165. pos2 = pos1;
  166. if ( p + 2 <= p_limit )
  167. pos2 = FT_NEXT_USHORT( p );
  168. pos1 <<= 1;
  169. pos2 <<= 1;
  170. }
  171. }
  172. /* Check broken location data */
  173. if ( pos1 > face->glyf_len )
  174. {
  175. FT_TRACE1(( "tt_face_get_location:"
  176. " too large offset=0x%08lx found for gid=0x%04lx,"
  177. " exceeding the end of glyf table (0x%08lx)\n",
  178. pos1, gindex, face->glyf_len ));
  179. *asize = 0;
  180. return 0;
  181. }
  182. if ( pos2 > face->glyf_len )
  183. {
  184. FT_TRACE1(( "tt_face_get_location:"
  185. " too large offset=0x%08lx found for gid=0x%04lx,"
  186. " truncate at the end of glyf table (0x%08lx)\n",
  187. pos2, gindex + 1, face->glyf_len ));
  188. pos2 = face->glyf_len;
  189. }
  190. /* The `loca' table must be ordered; it refers to the length of */
  191. /* an entry as the difference between the current and the next */
  192. /* position. However, there do exist (malformed) fonts which */
  193. /* don't obey this rule, so we are only able to provide an */
  194. /* upper bound for the size. */
  195. /* */
  196. /* We get (intentionally) a wrong, non-zero result in case the */
  197. /* `glyf' table is missing. */
  198. if ( pos2 >= pos1 )
  199. *asize = (FT_UInt)( pos2 - pos1 );
  200. else
  201. *asize = (FT_UInt)( face->glyf_len - pos1 );
  202. return pos1;
  203. }
  204. FT_LOCAL_DEF( void )
  205. tt_face_done_loca( TT_Face face )
  206. {
  207. FT_Stream stream = face->root.stream;
  208. FT_FRAME_RELEASE( face->glyph_locations );
  209. face->num_locations = 0;
  210. }
  211. /*************************************************************************/
  212. /* */
  213. /* <Function> */
  214. /* tt_face_load_cvt */
  215. /* */
  216. /* <Description> */
  217. /* Load the control value table into a face object. */
  218. /* */
  219. /* <InOut> */
  220. /* face :: A handle to the target face object. */
  221. /* */
  222. /* <Input> */
  223. /* stream :: A handle to the input stream. */
  224. /* */
  225. /* <Return> */
  226. /* FreeType error code. 0 means success. */
  227. /* */
  228. FT_LOCAL_DEF( FT_Error )
  229. tt_face_load_cvt( TT_Face face,
  230. FT_Stream stream )
  231. {
  232. #ifdef TT_USE_BYTECODE_INTERPRETER
  233. FT_Error error;
  234. FT_Memory memory = stream->memory;
  235. FT_ULong table_len;
  236. FT_TRACE2(( "CVT " ));
  237. error = face->goto_table( face, TTAG_cvt, stream, &table_len );
  238. if ( error )
  239. {
  240. FT_TRACE2(( "is missing\n" ));
  241. face->cvt_size = 0;
  242. face->cvt = NULL;
  243. error = TT_Err_Ok;
  244. goto Exit;
  245. }
  246. face->cvt_size = table_len / 2;
  247. if ( FT_NEW_ARRAY( face->cvt, face->cvt_size ) )
  248. goto Exit;
  249. if ( FT_FRAME_ENTER( face->cvt_size * 2L ) )
  250. goto Exit;
  251. {
  252. FT_Short* cur = face->cvt;
  253. FT_Short* limit = cur + face->cvt_size;
  254. for ( ; cur < limit; cur++ )
  255. *cur = FT_GET_SHORT();
  256. }
  257. FT_FRAME_EXIT();
  258. FT_TRACE2(( "loaded\n" ));
  259. #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
  260. if ( face->doblend )
  261. error = tt_face_vary_cvt( face, stream );
  262. #endif
  263. Exit:
  264. return error;
  265. #else /* !TT_USE_BYTECODE_INTERPRETER */
  266. FT_UNUSED( face );
  267. FT_UNUSED( stream );
  268. return TT_Err_Ok;
  269. #endif
  270. }
  271. /*************************************************************************/
  272. /* */
  273. /* <Function> */
  274. /* tt_face_load_fpgm */
  275. /* */
  276. /* <Description> */
  277. /* Load the font program. */
  278. /* */
  279. /* <InOut> */
  280. /* face :: A handle to the target face object. */
  281. /* */
  282. /* <Input> */
  283. /* stream :: A handle to the input stream. */
  284. /* */
  285. /* <Return> */
  286. /* FreeType error code. 0 means success. */
  287. /* */
  288. FT_LOCAL_DEF( FT_Error )
  289. tt_face_load_fpgm( TT_Face face,
  290. FT_Stream stream )
  291. {
  292. #ifdef TT_USE_BYTECODE_INTERPRETER
  293. FT_Error error;
  294. FT_ULong table_len;
  295. FT_TRACE2(( "Font program " ));
  296. /* The font program is optional */
  297. error = face->goto_table( face, TTAG_fpgm, stream, &table_len );
  298. if ( error )
  299. {
  300. face->font_program = NULL;
  301. face->font_program_size = 0;
  302. error = TT_Err_Ok;
  303. FT_TRACE2(( "is missing\n" ));
  304. }
  305. else
  306. {
  307. face->font_program_size = table_len;
  308. if ( FT_FRAME_EXTRACT( table_len, face->font_program ) )
  309. goto Exit;
  310. FT_TRACE2(( "loaded, %12d bytes\n", face->font_program_size ));
  311. }
  312. Exit:
  313. return error;
  314. #else /* !TT_USE_BYTECODE_INTERPRETER */
  315. FT_UNUSED( face );
  316. FT_UNUSED( stream );
  317. return TT_Err_Ok;
  318. #endif
  319. }
  320. /*************************************************************************/
  321. /* */
  322. /* <Function> */
  323. /* tt_face_load_prep */
  324. /* */
  325. /* <Description> */
  326. /* Load the cvt program. */
  327. /* */
  328. /* <InOut> */
  329. /* face :: A handle to the target face object. */
  330. /* */
  331. /* <Input> */
  332. /* stream :: A handle to the input stream. */
  333. /* */
  334. /* <Return> */
  335. /* FreeType error code. 0 means success. */
  336. /* */
  337. FT_LOCAL_DEF( FT_Error )
  338. tt_face_load_prep( TT_Face face,
  339. FT_Stream stream )
  340. {
  341. #ifdef TT_USE_BYTECODE_INTERPRETER
  342. FT_Error error;
  343. FT_ULong table_len;
  344. FT_TRACE2(( "Prep program " ));
  345. error = face->goto_table( face, TTAG_prep, stream, &table_len );
  346. if ( error )
  347. {
  348. face->cvt_program = NULL;
  349. face->cvt_program_size = 0;
  350. error = TT_Err_Ok;
  351. FT_TRACE2(( "is missing\n" ));
  352. }
  353. else
  354. {
  355. face->cvt_program_size = table_len;
  356. if ( FT_FRAME_EXTRACT( table_len, face->cvt_program ) )
  357. goto Exit;
  358. FT_TRACE2(( "loaded, %12d bytes\n", face->cvt_program_size ));
  359. }
  360. Exit:
  361. return error;
  362. #else /* !TT_USE_BYTECODE_INTERPRETER */
  363. FT_UNUSED( face );
  364. FT_UNUSED( stream );
  365. return TT_Err_Ok;
  366. #endif
  367. }
  368. /*************************************************************************/
  369. /* */
  370. /* <Function> */
  371. /* tt_face_load_hdmx */
  372. /* */
  373. /* <Description> */
  374. /* Load the `hdmx' table into the face object. */
  375. /* */
  376. /* <Input> */
  377. /* face :: A handle to the target face object. */
  378. /* */
  379. /* stream :: A handle to the input stream. */
  380. /* */
  381. /* <Return> */
  382. /* FreeType error code. 0 means success. */
  383. /* */
  384. FT_LOCAL_DEF( FT_Error )
  385. tt_face_load_hdmx( TT_Face face,
  386. FT_Stream stream )
  387. {
  388. FT_Error error;
  389. FT_Memory memory = stream->memory;
  390. FT_UInt version, nn, num_records;
  391. FT_ULong table_size, record_size;
  392. FT_Byte* p;
  393. FT_Byte* limit;
  394. /* this table is optional */
  395. error = face->goto_table( face, TTAG_hdmx, stream, &table_size );
  396. if ( error || table_size < 8 )
  397. return TT_Err_Ok;
  398. if ( FT_FRAME_EXTRACT( table_size, face->hdmx_table ) )
  399. goto Exit;
  400. p = face->hdmx_table;
  401. limit = p + table_size;
  402. version = FT_NEXT_USHORT( p );
  403. num_records = FT_NEXT_USHORT( p );
  404. record_size = FT_NEXT_ULONG( p );
  405. /* The maximum number of bytes in an hdmx device record is the */
  406. /* maximum number of glyphs + 2; this is 0xFFFF + 2; this is */
  407. /* the reason why `record_size' is a long (which we read as */
  408. /* unsigned long for convenience). In practice, two bytes */
  409. /* sufficient to hold the size value. */
  410. /* */
  411. /* There are at least two fonts, HANNOM-A and HANNOM-B version */
  412. /* 2.0 (2005), which get this wrong: The upper two bytes of */
  413. /* the size value are set to 0xFF instead of 0x00. We catch */
  414. /* and fix this. */
  415. if ( record_size >= 0xFFFF0000UL )
  416. record_size &= 0xFFFFU;
  417. /* The limit for `num_records' is a heuristic value. */
  418. if ( version != 0 || num_records > 255 || record_size > 0x10001L )
  419. {
  420. error = TT_Err_Invalid_File_Format;
  421. goto Fail;
  422. }
  423. if ( FT_NEW_ARRAY( face->hdmx_record_sizes, num_records ) )
  424. goto Fail;
  425. for ( nn = 0; nn < num_records; nn++ )
  426. {
  427. if ( p + record_size > limit )
  428. break;
  429. face->hdmx_record_sizes[nn] = p[0];
  430. p += record_size;
  431. }
  432. face->hdmx_record_count = nn;
  433. face->hdmx_table_size = table_size;
  434. face->hdmx_record_size = record_size;
  435. Exit:
  436. return error;
  437. Fail:
  438. FT_FRAME_RELEASE( face->hdmx_table );
  439. face->hdmx_table_size = 0;
  440. goto Exit;
  441. }
  442. FT_LOCAL_DEF( void )
  443. tt_face_free_hdmx( TT_Face face )
  444. {
  445. FT_Stream stream = face->root.stream;
  446. FT_Memory memory = stream->memory;
  447. FT_FREE( face->hdmx_record_sizes );
  448. FT_FRAME_RELEASE( face->hdmx_table );
  449. }
  450. /*************************************************************************/
  451. /* */
  452. /* Return the advance width table for a given pixel size if it is found */
  453. /* in the font's `hdmx' table (if any). */
  454. /* */
  455. FT_LOCAL_DEF( FT_Byte* )
  456. tt_face_get_device_metrics( TT_Face face,
  457. FT_UInt ppem,
  458. FT_UInt gindex )
  459. {
  460. FT_UInt nn;
  461. FT_Byte* result = NULL;
  462. FT_ULong record_size = face->hdmx_record_size;
  463. FT_Byte* record = face->hdmx_table + 8;
  464. for ( nn = 0; nn < face->hdmx_record_count; nn++ )
  465. if ( face->hdmx_record_sizes[nn] == ppem )
  466. {
  467. gindex += 2;
  468. if ( gindex < record_size )
  469. result = record + nn * record_size + gindex;
  470. break;
  471. }
  472. return result;
  473. }
  474. /* END */