/modules/freetype2/src/gxvalid/gxvjust.c

http://github.com/zpao/v8monkey · C · 630 lines · 415 code · 157 blank · 58 comment · 36 complexity · 986d0ed33f31ba9accd598191122bfa9 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* gxvjust.c */
  4. /* */
  5. /* TrueTypeGX/AAT just table validation (body). */
  6. /* */
  7. /* Copyright 2005 by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
  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. /***************************************************************************/
  18. /* */
  19. /* gxvalid is derived from both gxlayout module and otvalid module. */
  20. /* Development of gxlayout is supported by the Information-technology */
  21. /* Promotion Agency(IPA), Japan. */
  22. /* */
  23. /***************************************************************************/
  24. #include "gxvalid.h"
  25. #include "gxvcommn.h"
  26. #include FT_SFNT_NAMES_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_gxvjust
  35. /*
  36. * referred `just' table format specification:
  37. * http://developer.apple.com/fonts/TTRefMan/RM06/Chap6just.html
  38. * last updated 2000.
  39. * ----------------------------------------------
  40. * [JUST HEADER]: GXV_JUST_HEADER_SIZE
  41. * version (fixed: 32bit) = 0x00010000
  42. * format (uint16: 16bit) = 0 is only defined (2000)
  43. * horizOffset (uint16: 16bit)
  44. * vertOffset (uint16: 16bit)
  45. * ----------------------------------------------
  46. */
  47. typedef struct GXV_just_DataRec_
  48. {
  49. FT_UShort wdc_offset_max;
  50. FT_UShort wdc_offset_min;
  51. FT_UShort pc_offset_max;
  52. FT_UShort pc_offset_min;
  53. } GXV_just_DataRec, *GXV_just_Data;
  54. #define GXV_JUST_DATA( a ) GXV_TABLE_DATA( just, a )
  55. static void
  56. gxv_just_wdp_entry_validate( FT_Bytes table,
  57. FT_Bytes limit,
  58. GXV_Validator valid )
  59. {
  60. FT_Bytes p = table;
  61. FT_ULong justClass;
  62. FT_Fixed beforeGrowLimit;
  63. FT_Fixed beforeShrinkGrowLimit;
  64. FT_Fixed afterGrowLimit;
  65. FT_Fixed afterShrinkGrowLimit;
  66. FT_UShort growFlags;
  67. FT_UShort shrinkFlags;
  68. GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 + 4 + 2 + 2 );
  69. justClass = FT_NEXT_ULONG( p );
  70. beforeGrowLimit = FT_NEXT_ULONG( p );
  71. beforeShrinkGrowLimit = FT_NEXT_ULONG( p );
  72. afterGrowLimit = FT_NEXT_ULONG( p );
  73. afterShrinkGrowLimit = FT_NEXT_ULONG( p );
  74. growFlags = FT_NEXT_USHORT( p );
  75. shrinkFlags = FT_NEXT_USHORT( p );
  76. /* TODO: decode flags for human readability */
  77. valid->subtable_length = p - table;
  78. }
  79. static void
  80. gxv_just_wdc_entry_validate( FT_Bytes table,
  81. FT_Bytes limit,
  82. GXV_Validator valid )
  83. {
  84. FT_Bytes p = table;
  85. FT_ULong count, i;
  86. GXV_LIMIT_CHECK( 4 );
  87. count = FT_NEXT_ULONG( p );
  88. for ( i = 0; i < count; i++ )
  89. {
  90. GXV_TRACE(( "validating wdc pair %d/%d\n", i + 1, count ));
  91. gxv_just_wdp_entry_validate( p, limit, valid );
  92. p += valid->subtable_length;
  93. }
  94. valid->subtable_length = p - table;
  95. }
  96. static void
  97. gxv_just_widthDeltaClusters_validate( FT_Bytes table,
  98. FT_Bytes limit,
  99. GXV_Validator valid )
  100. {
  101. FT_Bytes p = table ;
  102. FT_Bytes wdc_end = table + GXV_JUST_DATA( wdc_offset_max );
  103. FT_UInt i;
  104. GXV_NAME_ENTER( "just justDeltaClusters" );
  105. if ( limit <= wdc_end )
  106. FT_INVALID_OFFSET;
  107. for ( i = 0; p <= wdc_end; i++ )
  108. {
  109. gxv_just_wdc_entry_validate( p, limit, valid );
  110. p += valid->subtable_length;
  111. }
  112. valid->subtable_length = p - table;
  113. GXV_EXIT;
  114. }
  115. static void
  116. gxv_just_actSubrecord_type0_validate( FT_Bytes table,
  117. FT_Bytes limit,
  118. GXV_Validator valid )
  119. {
  120. FT_Bytes p = table;
  121. FT_Fixed lowerLimit;
  122. FT_Fixed upperLimit;
  123. FT_UShort order;
  124. FT_UShort decomposedCount;
  125. FT_UInt i;
  126. GXV_LIMIT_CHECK( 4 + 4 + 2 + 2 );
  127. lowerLimit = FT_NEXT_ULONG( p );
  128. upperLimit = FT_NEXT_ULONG( p );
  129. order = FT_NEXT_USHORT( p );
  130. decomposedCount = FT_NEXT_USHORT( p );
  131. for ( i = 0; i < decomposedCount; i++ )
  132. {
  133. FT_UShort glyphs;
  134. GXV_LIMIT_CHECK( 2 );
  135. glyphs = FT_NEXT_USHORT( p );
  136. }
  137. valid->subtable_length = p - table;
  138. }
  139. static void
  140. gxv_just_actSubrecord_type1_validate( FT_Bytes table,
  141. FT_Bytes limit,
  142. GXV_Validator valid )
  143. {
  144. FT_Bytes p = table;
  145. FT_UShort addGlyph;
  146. GXV_LIMIT_CHECK( 2 );
  147. addGlyph = FT_NEXT_USHORT( p );
  148. valid->subtable_length = p - table;
  149. }
  150. static void
  151. gxv_just_actSubrecord_type2_validate( FT_Bytes table,
  152. FT_Bytes limit,
  153. GXV_Validator valid )
  154. {
  155. FT_Bytes p = table;
  156. FT_Fixed substThreshhold; /* Apple misspelled "Threshhold" */
  157. FT_UShort addGlyph;
  158. FT_UShort substGlyph;
  159. GXV_LIMIT_CHECK( 4 + 2 + 2 );
  160. substThreshhold = FT_NEXT_ULONG( p );
  161. addGlyph = FT_NEXT_USHORT( p );
  162. substGlyph = FT_NEXT_USHORT( p );
  163. valid->subtable_length = p - table;
  164. }
  165. static void
  166. gxv_just_actSubrecord_type4_validate( FT_Bytes table,
  167. FT_Bytes limit,
  168. GXV_Validator valid )
  169. {
  170. FT_Bytes p = table;
  171. FT_ULong variantsAxis;
  172. FT_Fixed minimumLimit;
  173. FT_Fixed noStretchValue;
  174. FT_Fixed maximumLimit;
  175. GXV_LIMIT_CHECK( 4 + 4 + 4 + 4 );
  176. variantsAxis = FT_NEXT_ULONG( p );
  177. minimumLimit = FT_NEXT_ULONG( p );
  178. noStretchValue = FT_NEXT_ULONG( p );
  179. maximumLimit = FT_NEXT_ULONG( p );
  180. valid->subtable_length = p - table;
  181. }
  182. static void
  183. gxv_just_actSubrecord_type5_validate( FT_Bytes table,
  184. FT_Bytes limit,
  185. GXV_Validator valid )
  186. {
  187. FT_Bytes p = table;
  188. FT_UShort flags;
  189. FT_UShort glyph;
  190. GXV_LIMIT_CHECK( 2 + 2 );
  191. flags = FT_NEXT_USHORT( p );
  192. glyph = FT_NEXT_USHORT( p );
  193. valid->subtable_length = p - table;
  194. }
  195. /* parse single actSubrecord */
  196. static void
  197. gxv_just_actSubrecord_validate( FT_Bytes table,
  198. FT_Bytes limit,
  199. GXV_Validator valid )
  200. {
  201. FT_Bytes p = table;
  202. FT_UShort actionClass;
  203. FT_UShort actionType;
  204. FT_ULong actionLength;
  205. GXV_NAME_ENTER( "just actSubrecord" );
  206. GXV_LIMIT_CHECK( 2 + 2 + 4 );
  207. actionClass = FT_NEXT_USHORT( p );
  208. actionType = FT_NEXT_USHORT( p );
  209. actionLength = FT_NEXT_ULONG( p );
  210. if ( actionType == 0 )
  211. gxv_just_actSubrecord_type0_validate( p, limit, valid );
  212. else if ( actionType == 1 )
  213. gxv_just_actSubrecord_type1_validate( p, limit, valid );
  214. else if ( actionType == 2 )
  215. gxv_just_actSubrecord_type2_validate( p, limit, valid );
  216. else if ( actionType == 3 )
  217. ; /* Stretch glyph action: no actionData */
  218. else if ( actionType == 4 )
  219. gxv_just_actSubrecord_type4_validate( p, limit, valid );
  220. else if ( actionType == 5 )
  221. gxv_just_actSubrecord_type5_validate( p, limit, valid );
  222. else
  223. FT_INVALID_DATA;
  224. valid->subtable_length = actionLength;
  225. GXV_EXIT;
  226. }
  227. static void
  228. gxv_just_pcActionRecord_validate( FT_Bytes table,
  229. FT_Bytes limit,
  230. GXV_Validator valid )
  231. {
  232. FT_Bytes p = table;
  233. FT_ULong actionCount;
  234. FT_ULong i;
  235. GXV_LIMIT_CHECK( 4 );
  236. actionCount = FT_NEXT_ULONG( p );
  237. GXV_TRACE(( "actionCount = %d\n", actionCount ));
  238. for ( i = 0; i < actionCount; i++ )
  239. {
  240. gxv_just_actSubrecord_validate( p, limit, valid );
  241. p += valid->subtable_length;
  242. }
  243. valid->subtable_length = p - table;
  244. GXV_EXIT;
  245. }
  246. static void
  247. gxv_just_pcTable_LookupValue_entry_validate( FT_UShort glyph,
  248. GXV_LookupValueCPtr value_p,
  249. GXV_Validator valid )
  250. {
  251. FT_UNUSED( glyph );
  252. if ( value_p->u > GXV_JUST_DATA( pc_offset_max ) )
  253. GXV_JUST_DATA( pc_offset_max ) = value_p->u;
  254. if ( value_p->u < GXV_JUST_DATA( pc_offset_max ) )
  255. GXV_JUST_DATA( pc_offset_min ) = value_p->u;
  256. }
  257. static void
  258. gxv_just_pcLookupTable_validate( FT_Bytes table,
  259. FT_Bytes limit,
  260. GXV_Validator valid )
  261. {
  262. FT_Bytes p = table;
  263. GXV_NAME_ENTER( "just pcLookupTable" );
  264. GXV_JUST_DATA( pc_offset_max ) = 0x0000;
  265. GXV_JUST_DATA( pc_offset_min ) = 0xFFFFU;
  266. valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
  267. valid->lookupval_func = gxv_just_pcTable_LookupValue_entry_validate;
  268. gxv_LookupTable_validate( p, limit, valid );
  269. /* subtable_length is set by gxv_LookupTable_validate() */
  270. GXV_EXIT;
  271. }
  272. static void
  273. gxv_just_postcompTable_validate( FT_Bytes table,
  274. FT_Bytes limit,
  275. GXV_Validator valid )
  276. {
  277. FT_Bytes p = table;
  278. GXV_NAME_ENTER( "just postcompTable" );
  279. gxv_just_pcLookupTable_validate( p, limit, valid );
  280. p += valid->subtable_length;
  281. gxv_just_pcActionRecord_validate( p, limit, valid );
  282. p += valid->subtable_length;
  283. valid->subtable_length = p - table;
  284. GXV_EXIT;
  285. }
  286. static void
  287. gxv_just_classTable_entry_validate(
  288. FT_Byte state,
  289. FT_UShort flags,
  290. GXV_StateTable_GlyphOffsetCPtr glyphOffset_p,
  291. FT_Bytes table,
  292. FT_Bytes limit,
  293. GXV_Validator valid )
  294. {
  295. FT_UShort setMark;
  296. FT_UShort dontAdvance;
  297. FT_UShort markClass;
  298. FT_UShort currentClass;
  299. FT_UNUSED( state );
  300. FT_UNUSED( glyphOffset_p );
  301. FT_UNUSED( table );
  302. FT_UNUSED( limit );
  303. FT_UNUSED( valid );
  304. setMark = (FT_UShort)( ( flags >> 15 ) & 1 );
  305. dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
  306. markClass = (FT_UShort)( ( flags >> 7 ) & 0x7F );
  307. currentClass = (FT_UShort)( flags & 0x7F );
  308. /* TODO: validate markClass & currentClass */
  309. }
  310. static void
  311. gxv_just_justClassTable_validate ( FT_Bytes table,
  312. FT_Bytes limit,
  313. GXV_Validator valid )
  314. {
  315. FT_Bytes p = table;
  316. FT_UShort length;
  317. FT_UShort coverage;
  318. FT_ULong subFeatureFlags;
  319. GXV_NAME_ENTER( "just justClassTable" );
  320. GXV_LIMIT_CHECK( 2 + 2 + 4 );
  321. length = FT_NEXT_USHORT( p );
  322. coverage = FT_NEXT_USHORT( p );
  323. subFeatureFlags = FT_NEXT_ULONG( p );
  324. GXV_TRACE(( " justClassTable: coverage = 0x%04x (%s)",
  325. coverage,
  326. ( 0x4000 & coverage ) == 0 ? "ascending" : "descending" ));
  327. valid->statetable.optdata = NULL;
  328. valid->statetable.optdata_load_func = NULL;
  329. valid->statetable.subtable_setup_func = NULL;
  330. valid->statetable.entry_glyphoffset_fmt = GXV_GLYPHOFFSET_NONE;
  331. valid->statetable.entry_validate_func =
  332. gxv_just_classTable_entry_validate;
  333. gxv_StateTable_validate( p, table + length, valid );
  334. /* subtable_length is set by gxv_LookupTable_validate() */
  335. GXV_EXIT;
  336. }
  337. static void
  338. gxv_just_wdcTable_LookupValue_validate( FT_UShort glyph,
  339. GXV_LookupValueCPtr value_p,
  340. GXV_Validator valid )
  341. {
  342. FT_UNUSED( glyph );
  343. if ( value_p->u > GXV_JUST_DATA( wdc_offset_max ) )
  344. GXV_JUST_DATA( wdc_offset_max ) = value_p->u;
  345. if ( value_p->u < GXV_JUST_DATA( wdc_offset_min ) )
  346. GXV_JUST_DATA( wdc_offset_min ) = value_p->u;
  347. }
  348. static void
  349. gxv_just_justData_lookuptable_validate( FT_Bytes table,
  350. FT_Bytes limit,
  351. GXV_Validator valid )
  352. {
  353. FT_Bytes p = table;
  354. GXV_JUST_DATA( wdc_offset_max ) = 0x0000;
  355. GXV_JUST_DATA( wdc_offset_min ) = 0xFFFFU;
  356. valid->lookupval_sign = GXV_LOOKUPVALUE_UNSIGNED;
  357. valid->lookupval_func = gxv_just_wdcTable_LookupValue_validate;
  358. gxv_LookupTable_validate( p, limit, valid );
  359. /* subtable_length is set by gxv_LookupTable_validate() */
  360. GXV_EXIT;
  361. }
  362. /*
  363. * gxv_just_justData_validate() parses and validates horizData, vertData.
  364. */
  365. static void
  366. gxv_just_justData_validate( FT_Bytes table,
  367. FT_Bytes limit,
  368. GXV_Validator valid )
  369. {
  370. /*
  371. * following 3 offsets are measured from the start of `just'
  372. * (which table points to), not justData
  373. */
  374. FT_UShort justClassTableOffset;
  375. FT_UShort wdcTableOffset;
  376. FT_UShort pcTableOffset;
  377. FT_Bytes p = table;
  378. GXV_ODTECT( 4, odtect );
  379. GXV_NAME_ENTER( "just justData" );
  380. GXV_ODTECT_INIT( odtect );
  381. GXV_LIMIT_CHECK( 2 + 2 + 2 );
  382. justClassTableOffset = FT_NEXT_USHORT( p );
  383. wdcTableOffset = FT_NEXT_USHORT( p );
  384. pcTableOffset = FT_NEXT_USHORT( p );
  385. GXV_TRACE(( " (justClassTableOffset = 0x%04x)\n", justClassTableOffset ));
  386. GXV_TRACE(( " (wdcTableOffset = 0x%04x)\n", wdcTableOffset ));
  387. GXV_TRACE(( " (pcTableOffset = 0x%04x)\n", pcTableOffset ));
  388. gxv_just_justData_lookuptable_validate( p, limit, valid );
  389. gxv_odtect_add_range( p, valid->subtable_length,
  390. "just_LookupTable", odtect );
  391. if ( wdcTableOffset )
  392. {
  393. gxv_just_widthDeltaClusters_validate(
  394. valid->root->base + wdcTableOffset, limit, valid );
  395. gxv_odtect_add_range( valid->root->base + wdcTableOffset,
  396. valid->subtable_length, "just_wdcTable", odtect );
  397. }
  398. if ( pcTableOffset )
  399. {
  400. gxv_just_postcompTable_validate( valid->root->base + pcTableOffset,
  401. limit, valid );
  402. gxv_odtect_add_range( valid->root->base + pcTableOffset,
  403. valid->subtable_length, "just_pcTable", odtect );
  404. }
  405. if ( justClassTableOffset )
  406. {
  407. gxv_just_justClassTable_validate(
  408. valid->root->base + justClassTableOffset, limit, valid );
  409. gxv_odtect_add_range( valid->root->base + justClassTableOffset,
  410. valid->subtable_length, "just_justClassTable",
  411. odtect );
  412. }
  413. gxv_odtect_validate( odtect, valid );
  414. GXV_EXIT;
  415. }
  416. FT_LOCAL_DEF( void )
  417. gxv_just_validate( FT_Bytes table,
  418. FT_Face face,
  419. FT_Validator ftvalid )
  420. {
  421. FT_Bytes p = table;
  422. FT_Bytes limit = 0;
  423. FT_Offset table_size;
  424. GXV_ValidatorRec validrec;
  425. GXV_Validator valid = &validrec;
  426. GXV_just_DataRec justrec;
  427. GXV_just_Data just = &justrec;
  428. FT_ULong version;
  429. FT_UShort format;
  430. FT_UShort horizOffset;
  431. FT_UShort vertOffset;
  432. GXV_ODTECT( 3, odtect );
  433. GXV_ODTECT_INIT( odtect );
  434. valid->root = ftvalid;
  435. valid->table_data = just;
  436. valid->face = face;
  437. FT_TRACE3(( "validating `just' table\n" ));
  438. GXV_INIT;
  439. limit = valid->root->limit;
  440. table_size = limit - table;
  441. GXV_LIMIT_CHECK( 4 + 2 + 2 + 2 );
  442. version = FT_NEXT_ULONG( p );
  443. format = FT_NEXT_USHORT( p );
  444. horizOffset = FT_NEXT_USHORT( p );
  445. vertOffset = FT_NEXT_USHORT( p );
  446. gxv_odtect_add_range( table, p - table, "just header", odtect );
  447. /* Version 1.0 (always:2000) */
  448. GXV_TRACE(( " (version = 0x%08x)\n", version ));
  449. if ( version != 0x00010000UL )
  450. FT_INVALID_FORMAT;
  451. /* format 0 (always:2000) */
  452. GXV_TRACE(( " (format = 0x%04x)\n", format ));
  453. if ( format != 0x0000 )
  454. FT_INVALID_FORMAT;
  455. GXV_TRACE(( " (horizOffset = %d)\n", horizOffset ));
  456. GXV_TRACE(( " (vertOffset = %d)\n", vertOffset ));
  457. /* validate justData */
  458. if ( 0 < horizOffset )
  459. {
  460. gxv_just_justData_validate( table + horizOffset, limit, valid );
  461. gxv_odtect_add_range( table + horizOffset, valid->subtable_length,
  462. "horizJustData", odtect );
  463. }
  464. if ( 0 < vertOffset )
  465. {
  466. gxv_just_justData_validate( table + vertOffset, limit, valid );
  467. gxv_odtect_add_range( table + vertOffset, valid->subtable_length,
  468. "vertJustData", odtect );
  469. }
  470. gxv_odtect_validate( odtect, valid );
  471. FT_TRACE4(( "\n" ));
  472. }
  473. /* END */