/src/freetype/src/gxvalid/gxvkern.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 922 lines · 611 code · 212 blank · 99 comment · 58 complexity · faaf6e78d5a1e0d507a67e8954ddaa31 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* gxvkern.c */
  4. /* */
  5. /* TrueTypeGX/AAT kern table validation (body). */
  6. /* */
  7. /* Copyright 2004, 2005, 2006, 2007 */
  8. /* by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */
  9. /* David Turner, Robert Wilhelm, and Werner Lemberg. */
  10. /* */
  11. /* This file is part of the FreeType project, and may only be used, */
  12. /* modified, and distributed under the terms of the FreeType project */
  13. /* license, LICENSE.TXT. By continuing to use, modify, or distribute */
  14. /* this file you indicate that you have read the license and */
  15. /* understand and accept it fully. */
  16. /* */
  17. /***************************************************************************/
  18. /***************************************************************************/
  19. /* */
  20. /* gxvalid is derived from both gxlayout module and otvalid module. */
  21. /* Development of gxlayout is supported by the Information-technology */
  22. /* Promotion Agency(IPA), Japan. */
  23. /* */
  24. /***************************************************************************/
  25. #include "gxvalid.h"
  26. #include "gxvcommn.h"
  27. #include FT_SFNT_NAMES_H
  28. #include FT_SERVICE_GX_VALIDATE_H
  29. /*************************************************************************/
  30. /* */
  31. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  32. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  33. /* messages during execution. */
  34. /* */
  35. #undef FT_COMPONENT
  36. #define FT_COMPONENT trace_gxvkern
  37. /*************************************************************************/
  38. /*************************************************************************/
  39. /***** *****/
  40. /***** Data and Types *****/
  41. /***** *****/
  42. /*************************************************************************/
  43. /*************************************************************************/
  44. typedef enum GXV_kern_Version_
  45. {
  46. KERN_VERSION_CLASSIC = 0x0000,
  47. KERN_VERSION_NEW = 0x0001
  48. } GXV_kern_Version;
  49. typedef enum GXV_kern_Dialect_
  50. {
  51. KERN_DIALECT_UNKNOWN = 0,
  52. KERN_DIALECT_MS = FT_VALIDATE_MS,
  53. KERN_DIALECT_APPLE = FT_VALIDATE_APPLE,
  54. KERN_DIALECT_ANY = FT_VALIDATE_CKERN
  55. } GXV_kern_Dialect;
  56. typedef struct GXV_kern_DataRec_
  57. {
  58. GXV_kern_Version version;
  59. void *subtable_data;
  60. GXV_kern_Dialect dialect_request;
  61. } GXV_kern_DataRec, *GXV_kern_Data;
  62. #define GXV_KERN_DATA( field ) GXV_TABLE_DATA( kern, field )
  63. #define KERN_IS_CLASSIC( valid ) \
  64. ( KERN_VERSION_CLASSIC == GXV_KERN_DATA( version ) )
  65. #define KERN_IS_NEW( valid ) \
  66. ( KERN_VERSION_NEW == GXV_KERN_DATA( version ) )
  67. #define KERN_DIALECT( valid ) \
  68. GXV_KERN_DATA( dialect_request )
  69. #define KERN_ALLOWS_MS( valid ) \
  70. ( KERN_DIALECT( valid ) & KERN_DIALECT_MS )
  71. #define KERN_ALLOWS_APPLE( valid ) \
  72. ( KERN_DIALECT( valid ) & KERN_DIALECT_APPLE )
  73. #define GXV_KERN_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 4 )
  74. #define GXV_KERN_SUBTABLE_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 6 )
  75. /*************************************************************************/
  76. /*************************************************************************/
  77. /***** *****/
  78. /***** SUBTABLE VALIDATORS *****/
  79. /***** *****/
  80. /*************************************************************************/
  81. /*************************************************************************/
  82. /* ============================= format 0 ============================== */
  83. static void
  84. gxv_kern_subtable_fmt0_pairs_validate( FT_Bytes table,
  85. FT_Bytes limit,
  86. FT_UShort nPairs,
  87. GXV_Validator valid )
  88. {
  89. FT_Bytes p = table;
  90. FT_UShort i;
  91. FT_UShort last_gid_left = 0;
  92. FT_UShort last_gid_right = 0;
  93. FT_UNUSED( limit );
  94. GXV_NAME_ENTER( "kern format 0 pairs" );
  95. for ( i = 0; i < nPairs; i++ )
  96. {
  97. FT_UShort gid_left;
  98. FT_UShort gid_right;
  99. #ifdef GXV_LOAD_UNUSED_VARS
  100. FT_Short kernValue;
  101. #endif
  102. /* left */
  103. gid_left = FT_NEXT_USHORT( p );
  104. gxv_glyphid_validate( gid_left, valid );
  105. /* right */
  106. gid_right = FT_NEXT_USHORT( p );
  107. gxv_glyphid_validate( gid_right, valid );
  108. /* Pairs of left and right GIDs must be unique and sorted. */
  109. GXV_TRACE(( "left gid = %u, right gid = %u\n", gid_left, gid_right ));
  110. if ( gid_left == last_gid_left )
  111. {
  112. if ( last_gid_right < gid_right )
  113. last_gid_right = gid_right;
  114. else
  115. FT_INVALID_DATA;
  116. }
  117. else if ( last_gid_left < gid_left )
  118. {
  119. last_gid_left = gid_left;
  120. last_gid_right = gid_right;
  121. }
  122. else
  123. FT_INVALID_DATA;
  124. /* skip the kern value */
  125. #ifdef GXV_LOAD_UNUSED_VARS
  126. kernValue = FT_NEXT_SHORT( p );
  127. #else
  128. p += 2;
  129. #endif
  130. }
  131. GXV_EXIT;
  132. }
  133. static void
  134. gxv_kern_subtable_fmt0_validate( FT_Bytes table,
  135. FT_Bytes limit,
  136. GXV_Validator valid )
  137. {
  138. FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
  139. FT_UShort nPairs;
  140. FT_UShort unitSize;
  141. GXV_NAME_ENTER( "kern subtable format 0" );
  142. unitSize = 2 + 2 + 2;
  143. nPairs = 0;
  144. /* nPairs, searchRange, entrySelector, rangeShift */
  145. GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
  146. gxv_BinSrchHeader_validate( p, limit, &unitSize, &nPairs, valid );
  147. p += 2 + 2 + 2 + 2;
  148. gxv_kern_subtable_fmt0_pairs_validate( p, limit, nPairs, valid );
  149. GXV_EXIT;
  150. }
  151. /* ============================= format 1 ============================== */
  152. typedef struct GXV_kern_fmt1_StateOptRec_
  153. {
  154. FT_UShort valueTable;
  155. FT_UShort valueTable_length;
  156. } GXV_kern_fmt1_StateOptRec, *GXV_kern_fmt1_StateOptRecData;
  157. static void
  158. gxv_kern_subtable_fmt1_valueTable_load( FT_Bytes table,
  159. FT_Bytes limit,
  160. GXV_Validator valid )
  161. {
  162. FT_Bytes p = table;
  163. GXV_kern_fmt1_StateOptRecData optdata =
  164. (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
  165. GXV_LIMIT_CHECK( 2 );
  166. optdata->valueTable = FT_NEXT_USHORT( p );
  167. }
  168. /*
  169. * passed tables_size covers whole StateTable, including kern fmt1 header
  170. */
  171. static void
  172. gxv_kern_subtable_fmt1_subtable_setup( FT_UShort table_size,
  173. FT_UShort classTable,
  174. FT_UShort stateArray,
  175. FT_UShort entryTable,
  176. FT_UShort* classTable_length_p,
  177. FT_UShort* stateArray_length_p,
  178. FT_UShort* entryTable_length_p,
  179. GXV_Validator valid )
  180. {
  181. FT_UShort o[4];
  182. FT_UShort *l[4];
  183. FT_UShort buff[5];
  184. GXV_kern_fmt1_StateOptRecData optdata =
  185. (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
  186. o[0] = classTable;
  187. o[1] = stateArray;
  188. o[2] = entryTable;
  189. o[3] = optdata->valueTable;
  190. l[0] = classTable_length_p;
  191. l[1] = stateArray_length_p;
  192. l[2] = entryTable_length_p;
  193. l[3] = &(optdata->valueTable_length);
  194. gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
  195. }
  196. /*
  197. * passed table & limit are of whole StateTable, not including subtables
  198. */
  199. static void
  200. gxv_kern_subtable_fmt1_entry_validate(
  201. FT_Byte state,
  202. FT_UShort flags,
  203. GXV_StateTable_GlyphOffsetCPtr glyphOffset_p,
  204. FT_Bytes table,
  205. FT_Bytes limit,
  206. GXV_Validator valid )
  207. {
  208. #ifdef GXV_LOAD_UNUSED_VARS
  209. FT_UShort push;
  210. FT_UShort dontAdvance;
  211. #endif
  212. FT_UShort valueOffset;
  213. #ifdef GXV_LOAD_UNUSED_VARS
  214. FT_UShort kernAction;
  215. FT_UShort kernValue;
  216. #endif
  217. FT_UNUSED( state );
  218. FT_UNUSED( glyphOffset_p );
  219. #ifdef GXV_LOAD_UNUSED_VARS
  220. push = (FT_UShort)( ( flags >> 15 ) & 1 );
  221. dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
  222. #endif
  223. valueOffset = (FT_UShort)( flags & 0x3FFF );
  224. {
  225. GXV_kern_fmt1_StateOptRecData vt_rec =
  226. (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata;
  227. FT_Bytes p;
  228. if ( valueOffset < vt_rec->valueTable )
  229. FT_INVALID_OFFSET;
  230. p = table + valueOffset;
  231. limit = table + vt_rec->valueTable + vt_rec->valueTable_length;
  232. GXV_LIMIT_CHECK( 2 + 2 );
  233. #ifdef GXV_LOAD_UNUSED_VARS
  234. kernAction = FT_NEXT_USHORT( p );
  235. kernValue = FT_NEXT_USHORT( p );
  236. #else
  237. p += 4;
  238. #endif
  239. }
  240. }
  241. static void
  242. gxv_kern_subtable_fmt1_validate( FT_Bytes table,
  243. FT_Bytes limit,
  244. GXV_Validator valid )
  245. {
  246. FT_Bytes p = table;
  247. GXV_kern_fmt1_StateOptRec vt_rec;
  248. GXV_NAME_ENTER( "kern subtable format 1" );
  249. valid->statetable.optdata =
  250. &vt_rec;
  251. valid->statetable.optdata_load_func =
  252. gxv_kern_subtable_fmt1_valueTable_load;
  253. valid->statetable.subtable_setup_func =
  254. gxv_kern_subtable_fmt1_subtable_setup;
  255. valid->statetable.entry_glyphoffset_fmt =
  256. GXV_GLYPHOFFSET_NONE;
  257. valid->statetable.entry_validate_func =
  258. gxv_kern_subtable_fmt1_entry_validate;
  259. gxv_StateTable_validate( p, limit, valid );
  260. GXV_EXIT;
  261. }
  262. /* ================ Data for Class-Based Subtables 2, 3 ================ */
  263. typedef enum GXV_kern_ClassSpec_
  264. {
  265. GXV_KERN_CLS_L = 0,
  266. GXV_KERN_CLS_R
  267. } GXV_kern_ClassSpec;
  268. /* ============================= format 2 ============================== */
  269. /* ---------------------- format 2 specific data ----------------------- */
  270. typedef struct GXV_kern_subtable_fmt2_DataRec_
  271. {
  272. FT_UShort rowWidth;
  273. FT_UShort array;
  274. FT_UShort offset_min[2];
  275. FT_UShort offset_max[2];
  276. const FT_String* class_tag[2];
  277. GXV_odtect_Range odtect;
  278. } GXV_kern_subtable_fmt2_DataRec, *GXV_kern_subtable_fmt2_Data;
  279. #define GXV_KERN_FMT2_DATA( field ) \
  280. ( ( (GXV_kern_subtable_fmt2_DataRec *) \
  281. ( GXV_KERN_DATA( subtable_data ) ) )->field )
  282. /* -------------------------- utility functions ----------------------- */
  283. static void
  284. gxv_kern_subtable_fmt2_clstbl_validate( FT_Bytes table,
  285. FT_Bytes limit,
  286. GXV_kern_ClassSpec spec,
  287. GXV_Validator valid )
  288. {
  289. const FT_String* tag = GXV_KERN_FMT2_DATA( class_tag[spec] );
  290. GXV_odtect_Range odtect = GXV_KERN_FMT2_DATA( odtect );
  291. FT_Bytes p = table;
  292. FT_UShort firstGlyph;
  293. FT_UShort nGlyphs;
  294. GXV_NAME_ENTER( "kern format 2 classTable" );
  295. GXV_LIMIT_CHECK( 2 + 2 );
  296. firstGlyph = FT_NEXT_USHORT( p );
  297. nGlyphs = FT_NEXT_USHORT( p );
  298. GXV_TRACE(( " %s firstGlyph=%d, nGlyphs=%d\n",
  299. tag, firstGlyph, nGlyphs ));
  300. gxv_glyphid_validate( firstGlyph, valid );
  301. gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs - 1 ), valid );
  302. gxv_array_getlimits_ushort( p, p + ( 2 * nGlyphs ),
  303. &( GXV_KERN_FMT2_DATA( offset_min[spec] ) ),
  304. &( GXV_KERN_FMT2_DATA( offset_max[spec] ) ),
  305. valid );
  306. gxv_odtect_add_range( table, 2 * nGlyphs, tag, odtect );
  307. GXV_EXIT;
  308. }
  309. static void
  310. gxv_kern_subtable_fmt2_validate( FT_Bytes table,
  311. FT_Bytes limit,
  312. GXV_Validator valid )
  313. {
  314. GXV_ODTECT( 3, odtect );
  315. GXV_kern_subtable_fmt2_DataRec fmt2_rec =
  316. { 0, 0, { 0, 0 }, { 0, 0 }, { "leftClass", "rightClass" }, NULL };
  317. FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
  318. FT_UShort leftOffsetTable;
  319. FT_UShort rightOffsetTable;
  320. GXV_NAME_ENTER( "kern subtable format 2" );
  321. GXV_ODTECT_INIT( odtect );
  322. fmt2_rec.odtect = odtect;
  323. GXV_KERN_DATA( subtable_data ) = &fmt2_rec;
  324. GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 );
  325. GXV_KERN_FMT2_DATA( rowWidth ) = FT_NEXT_USHORT( p );
  326. leftOffsetTable = FT_NEXT_USHORT( p );
  327. rightOffsetTable = FT_NEXT_USHORT( p );
  328. GXV_KERN_FMT2_DATA( array ) = FT_NEXT_USHORT( p );
  329. GXV_TRACE(( "rowWidth = %d\n", GXV_KERN_FMT2_DATA( rowWidth ) ));
  330. GXV_LIMIT_CHECK( leftOffsetTable );
  331. GXV_LIMIT_CHECK( rightOffsetTable );
  332. GXV_LIMIT_CHECK( GXV_KERN_FMT2_DATA( array ) );
  333. gxv_kern_subtable_fmt2_clstbl_validate( table + leftOffsetTable, limit,
  334. GXV_KERN_CLS_L, valid );
  335. gxv_kern_subtable_fmt2_clstbl_validate( table + rightOffsetTable, limit,
  336. GXV_KERN_CLS_R, valid );
  337. if ( GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_L] ) +
  338. GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_R] )
  339. < GXV_KERN_FMT2_DATA( array ) )
  340. FT_INVALID_OFFSET;
  341. gxv_odtect_add_range( table + GXV_KERN_FMT2_DATA( array ),
  342. GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_L] )
  343. + GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_R] )
  344. - GXV_KERN_FMT2_DATA( array ),
  345. "array", odtect );
  346. gxv_odtect_validate( odtect, valid );
  347. GXV_EXIT;
  348. }
  349. /* ============================= format 3 ============================== */
  350. static void
  351. gxv_kern_subtable_fmt3_validate( FT_Bytes table,
  352. FT_Bytes limit,
  353. GXV_Validator valid )
  354. {
  355. FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE;
  356. FT_UShort glyphCount;
  357. FT_Byte kernValueCount;
  358. FT_Byte leftClassCount;
  359. FT_Byte rightClassCount;
  360. FT_Byte flags;
  361. GXV_NAME_ENTER( "kern subtable format 3" );
  362. GXV_LIMIT_CHECK( 2 + 1 + 1 + 1 + 1 );
  363. glyphCount = FT_NEXT_USHORT( p );
  364. kernValueCount = FT_NEXT_BYTE( p );
  365. leftClassCount = FT_NEXT_BYTE( p );
  366. rightClassCount = FT_NEXT_BYTE( p );
  367. flags = FT_NEXT_BYTE( p );
  368. if ( valid->face->num_glyphs != glyphCount )
  369. {
  370. GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n",
  371. valid->face->num_glyphs, glyphCount ));
  372. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  373. }
  374. if ( flags != 0 )
  375. GXV_TRACE(( "kern subtable fmt3 has nonzero value"
  376. " (%d) in unused flag\n", flags ));
  377. /*
  378. * just skip kernValue[kernValueCount]
  379. */
  380. GXV_LIMIT_CHECK( 2 * kernValueCount );
  381. p += 2 * kernValueCount;
  382. /*
  383. * check leftClass[gid] < leftClassCount
  384. */
  385. {
  386. FT_Byte min, max;
  387. GXV_LIMIT_CHECK( glyphCount );
  388. gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
  389. p += valid->subtable_length;
  390. if ( leftClassCount < max )
  391. FT_INVALID_DATA;
  392. }
  393. /*
  394. * check rightClass[gid] < rightClassCount
  395. */
  396. {
  397. FT_Byte min, max;
  398. GXV_LIMIT_CHECK( glyphCount );
  399. gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid );
  400. p += valid->subtable_length;
  401. if ( rightClassCount < max )
  402. FT_INVALID_DATA;
  403. }
  404. /*
  405. * check kernIndex[i, j] < kernValueCount
  406. */
  407. {
  408. FT_UShort i, j;
  409. for ( i = 0; i < leftClassCount; i++ )
  410. {
  411. for ( j = 0; j < rightClassCount; j++ )
  412. {
  413. GXV_LIMIT_CHECK( 1 );
  414. if ( kernValueCount < FT_NEXT_BYTE( p ) )
  415. FT_INVALID_OFFSET;
  416. }
  417. }
  418. }
  419. valid->subtable_length = p - table;
  420. GXV_EXIT;
  421. }
  422. static FT_Bool
  423. gxv_kern_coverage_new_apple_validate( FT_UShort coverage,
  424. FT_UShort* format,
  425. GXV_Validator valid )
  426. {
  427. /* new Apple-dialect */
  428. #ifdef GXV_LOAD_TRACE_VARS
  429. FT_Bool kernVertical;
  430. FT_Bool kernCrossStream;
  431. FT_Bool kernVariation;
  432. #endif
  433. FT_UNUSED( valid );
  434. /* reserved bits = 0 */
  435. if ( coverage & 0x1FFC )
  436. return FALSE;
  437. #ifdef GXV_LOAD_TRACE_VARS
  438. kernVertical = FT_BOOL( ( coverage >> 15 ) & 1 );
  439. kernCrossStream = FT_BOOL( ( coverage >> 14 ) & 1 );
  440. kernVariation = FT_BOOL( ( coverage >> 13 ) & 1 );
  441. #endif
  442. *format = (FT_UShort)( coverage & 0x0003 );
  443. GXV_TRACE(( "new Apple-dialect: "
  444. "horizontal=%d, cross-stream=%d, variation=%d, format=%d\n",
  445. !kernVertical, kernCrossStream, kernVariation, *format ));
  446. GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
  447. return TRUE;
  448. }
  449. static FT_Bool
  450. gxv_kern_coverage_classic_apple_validate( FT_UShort coverage,
  451. FT_UShort* format,
  452. GXV_Validator valid )
  453. {
  454. /* classic Apple-dialect */
  455. #ifdef GXV_LOAD_TRACE_VARS
  456. FT_Bool horizontal;
  457. FT_Bool cross_stream;
  458. #endif
  459. /* check expected flags, but don't check if MS-dialect is impossible */
  460. if ( !( coverage & 0xFD00 ) && KERN_ALLOWS_MS( valid ) )
  461. return FALSE;
  462. /* reserved bits = 0 */
  463. if ( coverage & 0x02FC )
  464. return FALSE;
  465. #ifdef GXV_LOAD_TRACE_VARS
  466. horizontal = FT_BOOL( ( coverage >> 15 ) & 1 );
  467. cross_stream = FT_BOOL( ( coverage >> 13 ) & 1 );
  468. #endif
  469. *format = (FT_UShort)( coverage & 0x0003 );
  470. GXV_TRACE(( "classic Apple-dialect: "
  471. "horizontal=%d, cross-stream=%d, format=%d\n",
  472. horizontal, cross_stream, *format ));
  473. /* format 1 requires GX State Machine, too new for classic */
  474. if ( *format == 1 )
  475. return FALSE;
  476. GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" ));
  477. return TRUE;
  478. }
  479. static FT_Bool
  480. gxv_kern_coverage_classic_microsoft_validate( FT_UShort coverage,
  481. FT_UShort* format,
  482. GXV_Validator valid )
  483. {
  484. /* classic Microsoft-dialect */
  485. #ifdef GXV_LOAD_TRACE_VARS
  486. FT_Bool horizontal;
  487. FT_Bool minimum;
  488. FT_Bool cross_stream;
  489. FT_Bool override;
  490. #endif
  491. FT_UNUSED( valid );
  492. /* reserved bits = 0 */
  493. if ( coverage & 0xFDF0 )
  494. return FALSE;
  495. #ifdef GXV_LOAD_TRACE_VARS
  496. horizontal = FT_BOOL( coverage & 1 );
  497. minimum = FT_BOOL( ( coverage >> 1 ) & 1 );
  498. cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 );
  499. override = FT_BOOL( ( coverage >> 3 ) & 1 );
  500. #endif
  501. *format = (FT_UShort)( ( coverage >> 8 ) & 0x0003 );
  502. GXV_TRACE(( "classic Microsoft-dialect: "
  503. "horizontal=%d, minimum=%d, cross-stream=%d, "
  504. "override=%d, format=%d\n",
  505. horizontal, minimum, cross_stream, override, *format ));
  506. if ( *format == 2 )
  507. GXV_TRACE((
  508. "kerning values in Microsoft format 2 subtable are ignored\n" ));
  509. return TRUE;
  510. }
  511. /*************************************************************************/
  512. /*************************************************************************/
  513. /***** *****/
  514. /***** MAIN *****/
  515. /***** *****/
  516. /*************************************************************************/
  517. /*************************************************************************/
  518. static GXV_kern_Dialect
  519. gxv_kern_coverage_validate( FT_UShort coverage,
  520. FT_UShort* format,
  521. GXV_Validator valid )
  522. {
  523. GXV_kern_Dialect result = KERN_DIALECT_UNKNOWN;
  524. GXV_NAME_ENTER( "validating coverage" );
  525. GXV_TRACE(( "interprete coverage 0x%04x by Apple style\n", coverage ));
  526. if ( KERN_IS_NEW( valid ) )
  527. {
  528. if ( gxv_kern_coverage_new_apple_validate( coverage,
  529. format,
  530. valid ) )
  531. {
  532. result = KERN_DIALECT_APPLE;
  533. goto Exit;
  534. }
  535. }
  536. if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_APPLE( valid ) )
  537. {
  538. if ( gxv_kern_coverage_classic_apple_validate( coverage,
  539. format,
  540. valid ) )
  541. {
  542. result = KERN_DIALECT_APPLE;
  543. goto Exit;
  544. }
  545. }
  546. if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_MS( valid ) )
  547. {
  548. if ( gxv_kern_coverage_classic_microsoft_validate( coverage,
  549. format,
  550. valid ) )
  551. {
  552. result = KERN_DIALECT_MS;
  553. goto Exit;
  554. }
  555. }
  556. GXV_TRACE(( "cannot interprete coverage, broken kern subtable\n" ));
  557. Exit:
  558. GXV_EXIT;
  559. return result;
  560. }
  561. static void
  562. gxv_kern_subtable_validate( FT_Bytes table,
  563. FT_Bytes limit,
  564. GXV_Validator valid )
  565. {
  566. FT_Bytes p = table;
  567. #ifdef GXV_LOAD_TRACE_VARS
  568. FT_UShort version = 0; /* MS only: subtable version, unused */
  569. #endif
  570. FT_ULong length; /* MS: 16bit, Apple: 32bit*/
  571. FT_UShort coverage;
  572. #ifdef GXV_LOAD_TRACE_VARS
  573. FT_UShort tupleIndex = 0; /* Apple only */
  574. #endif
  575. FT_UShort u16[2];
  576. FT_UShort format = 255; /* subtable format */
  577. GXV_NAME_ENTER( "kern subtable" );
  578. GXV_LIMIT_CHECK( 2 + 2 + 2 );
  579. u16[0] = FT_NEXT_USHORT( p ); /* Apple: length_hi MS: version */
  580. u16[1] = FT_NEXT_USHORT( p ); /* Apple: length_lo MS: length */
  581. coverage = FT_NEXT_USHORT( p );
  582. switch ( gxv_kern_coverage_validate( coverage, &format, valid ) )
  583. {
  584. case KERN_DIALECT_MS:
  585. #ifdef GXV_LOAD_TRACE_VARS
  586. version = u16[0];
  587. #endif
  588. length = u16[1];
  589. #ifdef GXV_LOAD_TRACE_VARS
  590. tupleIndex = 0;
  591. #endif
  592. GXV_TRACE(( "Subtable version = %d\n", version ));
  593. GXV_TRACE(( "Subtable length = %d\n", length ));
  594. break;
  595. case KERN_DIALECT_APPLE:
  596. #ifdef GXV_LOAD_TRACE_VARS
  597. version = 0;
  598. #endif
  599. length = ( u16[0] << 16 ) + u16[1];
  600. #ifdef GXV_LOAD_TRACE_VARS
  601. tupleIndex = 0;
  602. #endif
  603. GXV_TRACE(( "Subtable length = %d\n", length ));
  604. if ( KERN_IS_NEW( valid ) )
  605. {
  606. GXV_LIMIT_CHECK( 2 );
  607. #ifdef GXV_LOAD_TRACE_VARS
  608. tupleIndex = FT_NEXT_USHORT( p );
  609. #else
  610. p += 2;
  611. #endif
  612. GXV_TRACE(( "Subtable tupleIndex = %d\n", tupleIndex ));
  613. }
  614. break;
  615. default:
  616. length = u16[1];
  617. GXV_TRACE(( "cannot detect subtable dialect, "
  618. "just skip %d byte\n", length ));
  619. goto Exit;
  620. }
  621. /* formats 1, 2, 3 require the position of the start of this subtable */
  622. if ( format == 0 )
  623. gxv_kern_subtable_fmt0_validate( table, table + length, valid );
  624. else if ( format == 1 )
  625. gxv_kern_subtable_fmt1_validate( table, table + length, valid );
  626. else if ( format == 2 )
  627. gxv_kern_subtable_fmt2_validate( table, table + length, valid );
  628. else if ( format == 3 )
  629. gxv_kern_subtable_fmt3_validate( table, table + length, valid );
  630. else
  631. FT_INVALID_DATA;
  632. Exit:
  633. valid->subtable_length = length;
  634. GXV_EXIT;
  635. }
  636. /*************************************************************************/
  637. /*************************************************************************/
  638. /***** *****/
  639. /***** kern TABLE *****/
  640. /***** *****/
  641. /*************************************************************************/
  642. /*************************************************************************/
  643. static void
  644. gxv_kern_validate_generic( FT_Bytes table,
  645. FT_Face face,
  646. FT_Bool classic_only,
  647. GXV_kern_Dialect dialect_request,
  648. FT_Validator ftvalid )
  649. {
  650. GXV_ValidatorRec validrec;
  651. GXV_Validator valid = &validrec;
  652. GXV_kern_DataRec kernrec;
  653. GXV_kern_Data kern = &kernrec;
  654. FT_Bytes p = table;
  655. FT_Bytes limit = 0;
  656. FT_ULong nTables = 0;
  657. FT_UInt i;
  658. valid->root = ftvalid;
  659. valid->table_data = kern;
  660. valid->face = face;
  661. FT_TRACE3(( "validating `kern' table\n" ));
  662. GXV_INIT;
  663. KERN_DIALECT( valid ) = dialect_request;
  664. GXV_LIMIT_CHECK( 2 );
  665. GXV_KERN_DATA( version ) = (GXV_kern_Version)FT_NEXT_USHORT( p );
  666. GXV_TRACE(( "version 0x%04x (higher 16bit)\n",
  667. GXV_KERN_DATA( version ) ));
  668. if ( 0x0001 < GXV_KERN_DATA( version ) )
  669. FT_INVALID_FORMAT;
  670. else if ( KERN_IS_CLASSIC( valid ) )
  671. {
  672. GXV_LIMIT_CHECK( 2 );
  673. nTables = FT_NEXT_USHORT( p );
  674. }
  675. else if ( KERN_IS_NEW( valid ) )
  676. {
  677. if ( classic_only )
  678. FT_INVALID_FORMAT;
  679. if ( 0x0000 != FT_NEXT_USHORT( p ) )
  680. FT_INVALID_FORMAT;
  681. GXV_LIMIT_CHECK( 4 );
  682. nTables = FT_NEXT_ULONG( p );
  683. }
  684. for ( i = 0; i < nTables; i++ )
  685. {
  686. GXV_TRACE(( "validating subtable %d/%d\n", i, nTables ));
  687. /* p should be 32bit-aligned? */
  688. gxv_kern_subtable_validate( p, 0, valid );
  689. p += valid->subtable_length;
  690. }
  691. FT_TRACE4(( "\n" ));
  692. }
  693. FT_LOCAL_DEF( void )
  694. gxv_kern_validate( FT_Bytes table,
  695. FT_Face face,
  696. FT_Validator ftvalid )
  697. {
  698. gxv_kern_validate_generic( table, face, 0, KERN_DIALECT_ANY, ftvalid );
  699. }
  700. FT_LOCAL_DEF( void )
  701. gxv_kern_validate_classic( FT_Bytes table,
  702. FT_Face face,
  703. FT_Int dialect_flags,
  704. FT_Validator ftvalid )
  705. {
  706. GXV_kern_Dialect dialect_request;
  707. dialect_request = (GXV_kern_Dialect)dialect_flags;
  708. gxv_kern_validate_generic( table, face, 1, dialect_request, ftvalid );
  709. }
  710. /* END */