/src/freetype/src/sfnt/ttmtx.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 468 lines · 289 code · 87 blank · 92 comment · 32 complexity · 7035918999254593220bf94aa94b9b7e MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* ttmtx.c */
  4. /* */
  5. /* Load the metrics tables common to TTF and OTF fonts (body). */
  6. /* */
  7. /* Copyright 2006-2009, 2011 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_STREAM_H
  20. #include FT_TRUETYPE_TAGS_H
  21. #include "ttmtx.h"
  22. #include "sferrors.h"
  23. /*************************************************************************/
  24. /* */
  25. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  26. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  27. /* messages during execution. */
  28. /* */
  29. #undef FT_COMPONENT
  30. #define FT_COMPONENT trace_ttmtx
  31. /*
  32. * Unfortunately, we can't enable our memory optimizations if
  33. * FT_CONFIG_OPTION_OLD_INTERNALS is defined. This is because at least
  34. * one rogue client (libXfont in the X.Org XServer) is directly accessing
  35. * the metrics.
  36. */
  37. /*************************************************************************/
  38. /* */
  39. /* <Function> */
  40. /* tt_face_load_hmtx */
  41. /* */
  42. /* <Description> */
  43. /* Load the `hmtx' or `vmtx' table into a face object. */
  44. /* */
  45. /* <Input> */
  46. /* face :: A handle to the target face object. */
  47. /* */
  48. /* stream :: The input stream. */
  49. /* */
  50. /* vertical :: A boolean flag. If set, load `vmtx'. */
  51. /* */
  52. /* <Return> */
  53. /* FreeType error code. 0 means success. */
  54. /* */
  55. #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
  56. FT_LOCAL_DEF( FT_Error )
  57. tt_face_load_hmtx( TT_Face face,
  58. FT_Stream stream,
  59. FT_Bool vertical )
  60. {
  61. FT_Error error;
  62. FT_ULong tag, table_size;
  63. FT_ULong* ptable_offset;
  64. FT_ULong* ptable_size;
  65. if ( vertical )
  66. {
  67. tag = TTAG_vmtx;
  68. ptable_offset = &face->vert_metrics_offset;
  69. ptable_size = &face->vert_metrics_size;
  70. }
  71. else
  72. {
  73. tag = TTAG_hmtx;
  74. ptable_offset = &face->horz_metrics_offset;
  75. ptable_size = &face->horz_metrics_size;
  76. }
  77. error = face->goto_table( face, tag, stream, &table_size );
  78. if ( error )
  79. goto Fail;
  80. *ptable_size = table_size;
  81. *ptable_offset = FT_STREAM_POS();
  82. Fail:
  83. return error;
  84. }
  85. #else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
  86. FT_LOCAL_DEF( FT_Error )
  87. tt_face_load_hmtx( TT_Face face,
  88. FT_Stream stream,
  89. FT_Bool vertical )
  90. {
  91. FT_Error error;
  92. FT_Memory memory = stream->memory;
  93. FT_ULong table_len;
  94. FT_Long num_shorts, num_longs, num_shorts_checked;
  95. TT_LongMetrics* longs;
  96. TT_ShortMetrics** shorts;
  97. FT_Byte* p;
  98. if ( vertical )
  99. {
  100. void* lm = &face->vertical.long_metrics;
  101. void** sm = &face->vertical.short_metrics;
  102. error = face->goto_table( face, TTAG_vmtx, stream, &table_len );
  103. if ( error )
  104. goto Fail;
  105. num_longs = face->vertical.number_Of_VMetrics;
  106. if ( (FT_ULong)num_longs > table_len / 4 )
  107. num_longs = (FT_Long)( table_len / 4 );
  108. face->vertical.number_Of_VMetrics = 0;
  109. longs = (TT_LongMetrics*)lm;
  110. shorts = (TT_ShortMetrics**)sm;
  111. }
  112. else
  113. {
  114. void* lm = &face->horizontal.long_metrics;
  115. void** sm = &face->horizontal.short_metrics;
  116. error = face->goto_table( face, TTAG_hmtx, stream, &table_len );
  117. if ( error )
  118. goto Fail;
  119. num_longs = face->horizontal.number_Of_HMetrics;
  120. if ( (FT_ULong)num_longs > table_len / 4 )
  121. num_longs = (FT_Long)( table_len / 4 );
  122. face->horizontal.number_Of_HMetrics = 0;
  123. longs = (TT_LongMetrics*)lm;
  124. shorts = (TT_ShortMetrics**)sm;
  125. }
  126. /* never trust derived values */
  127. num_shorts = face->max_profile.numGlyphs - num_longs;
  128. num_shorts_checked = ( table_len - num_longs * 4L ) / 2;
  129. if ( num_shorts < 0 )
  130. {
  131. FT_TRACE0(( "tt_face_load_hmtx:"
  132. " %cmtx has more metrics than glyphs.\n",
  133. vertical ? 'v' : 'h' ));
  134. /* Adobe simply ignores this problem. So we shall do the same. */
  135. #if 0
  136. error = vertical ? SFNT_Err_Invalid_Vert_Metrics
  137. : SFNT_Err_Invalid_Horiz_Metrics;
  138. goto Exit;
  139. #else
  140. num_shorts = 0;
  141. #endif
  142. }
  143. if ( FT_QNEW_ARRAY( *longs, num_longs ) ||
  144. FT_QNEW_ARRAY( *shorts, num_shorts ) )
  145. goto Fail;
  146. if ( FT_FRAME_ENTER( table_len ) )
  147. goto Fail;
  148. p = stream->cursor;
  149. {
  150. TT_LongMetrics cur = *longs;
  151. TT_LongMetrics limit = cur + num_longs;
  152. for ( ; cur < limit; cur++ )
  153. {
  154. cur->advance = FT_NEXT_USHORT( p );
  155. cur->bearing = FT_NEXT_SHORT( p );
  156. }
  157. }
  158. /* do we have an inconsistent number of metric values? */
  159. {
  160. TT_ShortMetrics* cur = *shorts;
  161. TT_ShortMetrics* limit = cur +
  162. FT_MIN( num_shorts, num_shorts_checked );
  163. for ( ; cur < limit; cur++ )
  164. *cur = FT_NEXT_SHORT( p );
  165. /* We fill up the missing left side bearings with the */
  166. /* last valid value. Since this will occur for buggy CJK */
  167. /* fonts usually only, nothing serious will happen. */
  168. if ( num_shorts > num_shorts_checked && num_shorts_checked > 0 )
  169. {
  170. FT_Short val = (*shorts)[num_shorts_checked - 1];
  171. limit = *shorts + num_shorts;
  172. for ( ; cur < limit; cur++ )
  173. *cur = val;
  174. }
  175. }
  176. FT_FRAME_EXIT();
  177. if ( vertical )
  178. face->vertical.number_Of_VMetrics = (FT_UShort)num_longs;
  179. else
  180. face->horizontal.number_Of_HMetrics = (FT_UShort)num_longs;
  181. Fail:
  182. return error;
  183. }
  184. #endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
  185. /*************************************************************************/
  186. /* */
  187. /* <Function> */
  188. /* tt_face_load_hhea */
  189. /* */
  190. /* <Description> */
  191. /* Load the `hhea' or 'vhea' table into a face object. */
  192. /* */
  193. /* <Input> */
  194. /* face :: A handle to the target face object. */
  195. /* */
  196. /* stream :: The input stream. */
  197. /* */
  198. /* vertical :: A boolean flag. If set, load `vhea'. */
  199. /* */
  200. /* <Return> */
  201. /* FreeType error code. 0 means success. */
  202. /* */
  203. FT_LOCAL_DEF( FT_Error )
  204. tt_face_load_hhea( TT_Face face,
  205. FT_Stream stream,
  206. FT_Bool vertical )
  207. {
  208. FT_Error error;
  209. TT_HoriHeader* header;
  210. const FT_Frame_Field metrics_header_fields[] =
  211. {
  212. #undef FT_STRUCTURE
  213. #define FT_STRUCTURE TT_HoriHeader
  214. FT_FRAME_START( 36 ),
  215. FT_FRAME_ULONG ( Version ),
  216. FT_FRAME_SHORT ( Ascender ),
  217. FT_FRAME_SHORT ( Descender ),
  218. FT_FRAME_SHORT ( Line_Gap ),
  219. FT_FRAME_USHORT( advance_Width_Max ),
  220. FT_FRAME_SHORT ( min_Left_Side_Bearing ),
  221. FT_FRAME_SHORT ( min_Right_Side_Bearing ),
  222. FT_FRAME_SHORT ( xMax_Extent ),
  223. FT_FRAME_SHORT ( caret_Slope_Rise ),
  224. FT_FRAME_SHORT ( caret_Slope_Run ),
  225. FT_FRAME_SHORT ( caret_Offset ),
  226. FT_FRAME_SHORT ( Reserved[0] ),
  227. FT_FRAME_SHORT ( Reserved[1] ),
  228. FT_FRAME_SHORT ( Reserved[2] ),
  229. FT_FRAME_SHORT ( Reserved[3] ),
  230. FT_FRAME_SHORT ( metric_Data_Format ),
  231. FT_FRAME_USHORT( number_Of_HMetrics ),
  232. FT_FRAME_END
  233. };
  234. if ( vertical )
  235. {
  236. void *v = &face->vertical;
  237. error = face->goto_table( face, TTAG_vhea, stream, 0 );
  238. if ( error )
  239. goto Fail;
  240. header = (TT_HoriHeader*)v;
  241. }
  242. else
  243. {
  244. error = face->goto_table( face, TTAG_hhea, stream, 0 );
  245. if ( error )
  246. goto Fail;
  247. header = &face->horizontal;
  248. }
  249. if ( FT_STREAM_READ_FIELDS( metrics_header_fields, header ) )
  250. goto Fail;
  251. FT_TRACE3(( "Ascender: %5d\n", header->Ascender ));
  252. FT_TRACE3(( "Descender: %5d\n", header->Descender ));
  253. FT_TRACE3(( "number_Of_Metrics: %5u\n", header->number_Of_HMetrics ));
  254. header->long_metrics = NULL;
  255. header->short_metrics = NULL;
  256. Fail:
  257. return error;
  258. }
  259. /*************************************************************************/
  260. /* */
  261. /* <Function> */
  262. /* tt_face_get_metrics */
  263. /* */
  264. /* <Description> */
  265. /* Returns the horizontal or vertical metrics in font units for a */
  266. /* given glyph. The metrics are the left side bearing (resp. top */
  267. /* side bearing) and advance width (resp. advance height). */
  268. /* */
  269. /* <Input> */
  270. /* header :: A pointer to either the horizontal or vertical metrics */
  271. /* structure. */
  272. /* */
  273. /* idx :: The glyph index. */
  274. /* */
  275. /* <Output> */
  276. /* bearing :: The bearing, either left side or top side. */
  277. /* */
  278. /* advance :: The advance width resp. advance height. */
  279. /* */
  280. #ifndef FT_CONFIG_OPTION_OLD_INTERNALS
  281. FT_LOCAL_DEF( FT_Error )
  282. tt_face_get_metrics( TT_Face face,
  283. FT_Bool vertical,
  284. FT_UInt gindex,
  285. FT_Short *abearing,
  286. FT_UShort *aadvance )
  287. {
  288. FT_Error error;
  289. FT_Stream stream = face->root.stream;
  290. TT_HoriHeader* header;
  291. FT_ULong table_pos, table_size, table_end;
  292. FT_UShort k;
  293. if ( vertical )
  294. {
  295. void* v = &face->vertical;
  296. header = (TT_HoriHeader*)v;
  297. table_pos = face->vert_metrics_offset;
  298. table_size = face->vert_metrics_size;
  299. }
  300. else
  301. {
  302. header = &face->horizontal;
  303. table_pos = face->horz_metrics_offset;
  304. table_size = face->horz_metrics_size;
  305. }
  306. table_end = table_pos + table_size;
  307. k = header->number_Of_HMetrics;
  308. if ( k > 0 )
  309. {
  310. if ( gindex < (FT_UInt)k )
  311. {
  312. table_pos += 4 * gindex;
  313. if ( table_pos + 4 > table_end )
  314. goto NoData;
  315. if ( FT_STREAM_SEEK( table_pos ) ||
  316. FT_READ_USHORT( *aadvance ) ||
  317. FT_READ_SHORT( *abearing ) )
  318. goto NoData;
  319. }
  320. else
  321. {
  322. table_pos += 4 * ( k - 1 );
  323. if ( table_pos + 4 > table_end )
  324. goto NoData;
  325. if ( FT_STREAM_SEEK( table_pos ) ||
  326. FT_READ_USHORT( *aadvance ) )
  327. goto NoData;
  328. table_pos += 4 + 2 * ( gindex - k );
  329. if ( table_pos + 2 > table_end )
  330. *abearing = 0;
  331. else
  332. {
  333. if ( !FT_STREAM_SEEK( table_pos ) )
  334. (void)FT_READ_SHORT( *abearing );
  335. }
  336. }
  337. }
  338. else
  339. {
  340. NoData:
  341. *abearing = 0;
  342. *aadvance = 0;
  343. }
  344. return SFNT_Err_Ok;
  345. }
  346. #else /* !FT_CONFIG_OPTION_OLD_INTERNALS */
  347. FT_LOCAL_DEF( FT_Error )
  348. tt_face_get_metrics( TT_Face face,
  349. FT_Bool vertical,
  350. FT_UInt gindex,
  351. FT_Short* abearing,
  352. FT_UShort* aadvance )
  353. {
  354. void* v = &face->vertical;
  355. void* h = &face->horizontal;
  356. TT_HoriHeader* header = vertical ? (TT_HoriHeader*)v
  357. : (TT_HoriHeader*)h;
  358. TT_LongMetrics longs_m;
  359. FT_UShort k = header->number_Of_HMetrics;
  360. if ( k == 0 ||
  361. !header->long_metrics ||
  362. gindex >= (FT_UInt)face->max_profile.numGlyphs )
  363. {
  364. *abearing = *aadvance = 0;
  365. return SFNT_Err_Ok;
  366. }
  367. if ( gindex < (FT_UInt)k )
  368. {
  369. longs_m = (TT_LongMetrics)header->long_metrics + gindex;
  370. *abearing = longs_m->bearing;
  371. *aadvance = longs_m->advance;
  372. }
  373. else
  374. {
  375. *abearing = ((TT_ShortMetrics*)header->short_metrics)[gindex - k];
  376. *aadvance = ((TT_LongMetrics)header->long_metrics)[k - 1].advance;
  377. }
  378. return SFNT_Err_Ok;
  379. }
  380. #endif /* !FT_CONFIG_OPTION_OLD_INTERNALS */
  381. /* END */