/src/freetype/src/gxvalid/gxvmort1.c

https://bitbucket.org/cabalistic/ogredeps/ · C · 259 lines · 163 code · 58 blank · 38 comment · 5 complexity · 09f0f8292d9cab813acc5c34292f28a7 MD5 · raw file

  1. /***************************************************************************/
  2. /* */
  3. /* gxvmort1.c */
  4. /* */
  5. /* TrueTypeGX/AAT mort table validation */
  6. /* body for type1 (Contextual Substitution) subtable. */
  7. /* */
  8. /* Copyright 2005, 2007 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 "gxvmort.h"
  26. /*************************************************************************/
  27. /* */
  28. /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
  29. /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
  30. /* messages during execution. */
  31. /* */
  32. #undef FT_COMPONENT
  33. #define FT_COMPONENT trace_gxvmort
  34. typedef struct GXV_mort_subtable_type1_StateOptRec_
  35. {
  36. FT_UShort substitutionTable;
  37. FT_UShort substitutionTable_length;
  38. } GXV_mort_subtable_type1_StateOptRec,
  39. *GXV_mort_subtable_type1_StateOptRecData;
  40. #define GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE \
  41. ( GXV_STATETABLE_HEADER_SIZE + 2 )
  42. static void
  43. gxv_mort_subtable_type1_substitutionTable_load( FT_Bytes table,
  44. FT_Bytes limit,
  45. GXV_Validator valid )
  46. {
  47. FT_Bytes p = table;
  48. GXV_mort_subtable_type1_StateOptRecData optdata =
  49. (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata;
  50. GXV_LIMIT_CHECK( 2 );
  51. optdata->substitutionTable = FT_NEXT_USHORT( p );
  52. }
  53. static void
  54. gxv_mort_subtable_type1_subtable_setup( FT_UShort table_size,
  55. FT_UShort classTable,
  56. FT_UShort stateArray,
  57. FT_UShort entryTable,
  58. FT_UShort* classTable_length_p,
  59. FT_UShort* stateArray_length_p,
  60. FT_UShort* entryTable_length_p,
  61. GXV_Validator valid )
  62. {
  63. FT_UShort o[4];
  64. FT_UShort *l[4];
  65. FT_UShort buff[5];
  66. GXV_mort_subtable_type1_StateOptRecData optdata =
  67. (GXV_mort_subtable_type1_StateOptRecData)valid->statetable.optdata;
  68. o[0] = classTable;
  69. o[1] = stateArray;
  70. o[2] = entryTable;
  71. o[3] = optdata->substitutionTable;
  72. l[0] = classTable_length_p;
  73. l[1] = stateArray_length_p;
  74. l[2] = entryTable_length_p;
  75. l[3] = &( optdata->substitutionTable_length );
  76. gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid );
  77. }
  78. static void
  79. gxv_mort_subtable_type1_offset_to_subst_validate(
  80. FT_Short wordOffset,
  81. const FT_String* tag,
  82. FT_Byte state,
  83. GXV_Validator valid )
  84. {
  85. FT_UShort substTable;
  86. FT_UShort substTable_limit;
  87. FT_UNUSED( tag );
  88. FT_UNUSED( state );
  89. substTable =
  90. ((GXV_mort_subtable_type1_StateOptRec *)
  91. (valid->statetable.optdata))->substitutionTable;
  92. substTable_limit =
  93. (FT_UShort)( substTable +
  94. ((GXV_mort_subtable_type1_StateOptRec *)
  95. (valid->statetable.optdata))->substitutionTable_length );
  96. valid->min_gid = (FT_UShort)( ( substTable - wordOffset * 2 ) / 2 );
  97. valid->max_gid = (FT_UShort)( ( substTable_limit - wordOffset * 2 ) / 2 );
  98. valid->max_gid = (FT_UShort)( FT_MAX( valid->max_gid,
  99. valid->face->num_glyphs ) );
  100. /* XXX: check range? */
  101. /* TODO: min_gid & max_gid comparison with ClassTable contents */
  102. }
  103. static void
  104. gxv_mort_subtable_type1_entry_validate(
  105. FT_Byte state,
  106. FT_UShort flags,
  107. GXV_StateTable_GlyphOffsetCPtr glyphOffset_p,
  108. FT_Bytes table,
  109. FT_Bytes limit,
  110. GXV_Validator valid )
  111. {
  112. #ifdef GXV_LOAD_UNUSED_VARS
  113. FT_UShort setMark;
  114. FT_UShort dontAdvance;
  115. #endif
  116. FT_UShort reserved;
  117. FT_Short markOffset;
  118. FT_Short currentOffset;
  119. FT_UNUSED( table );
  120. FT_UNUSED( limit );
  121. #ifdef GXV_LOAD_UNUSED_VARS
  122. setMark = (FT_UShort)( flags >> 15 );
  123. dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 );
  124. #endif
  125. reserved = (FT_Short)( flags & 0x3FFF );
  126. markOffset = (FT_Short)( glyphOffset_p->ul >> 16 );
  127. currentOffset = (FT_Short)( glyphOffset_p->ul );
  128. if ( 0 < reserved )
  129. {
  130. GXV_TRACE(( " non-zero bits found in reserved range\n" ));
  131. GXV_SET_ERR_IF_PARANOID( FT_INVALID_DATA );
  132. }
  133. gxv_mort_subtable_type1_offset_to_subst_validate( markOffset,
  134. "markOffset",
  135. state,
  136. valid );
  137. gxv_mort_subtable_type1_offset_to_subst_validate( currentOffset,
  138. "currentOffset",
  139. state,
  140. valid );
  141. }
  142. static void
  143. gxv_mort_subtable_type1_substTable_validate( FT_Bytes table,
  144. FT_Bytes limit,
  145. GXV_Validator valid )
  146. {
  147. FT_Bytes p = table;
  148. FT_UShort num_gids = (FT_UShort)(
  149. ((GXV_mort_subtable_type1_StateOptRec *)
  150. (valid->statetable.optdata))->substitutionTable_length / 2 );
  151. FT_UShort i;
  152. GXV_NAME_ENTER( "validating contents of substitutionTable" );
  153. for ( i = 0; i < num_gids ; i ++ )
  154. {
  155. FT_UShort dst_gid;
  156. GXV_LIMIT_CHECK( 2 );
  157. dst_gid = FT_NEXT_USHORT( p );
  158. if ( dst_gid >= 0xFFFFU )
  159. continue;
  160. if ( dst_gid < valid->min_gid || valid->max_gid < dst_gid )
  161. {
  162. GXV_TRACE(( "substTable include a strange gid[%d]=%d >"
  163. " out of define range (%d..%d)\n",
  164. i, dst_gid, valid->min_gid, valid->max_gid ));
  165. GXV_SET_ERR_IF_PARANOID( FT_INVALID_GLYPH_ID );
  166. }
  167. }
  168. GXV_EXIT;
  169. }
  170. /*
  171. * subtable for Contextual glyph substitution is a modified StateTable.
  172. * In addition to classTable, stateArray, and entryTable, the field
  173. * `substitutionTable' is added.
  174. */
  175. FT_LOCAL_DEF( void )
  176. gxv_mort_subtable_type1_validate( FT_Bytes table,
  177. FT_Bytes limit,
  178. GXV_Validator valid )
  179. {
  180. FT_Bytes p = table;
  181. GXV_mort_subtable_type1_StateOptRec st_rec;
  182. GXV_NAME_ENTER( "mort chain subtable type1 (Contextual Glyph Subst)" );
  183. GXV_LIMIT_CHECK( GXV_MORT_SUBTABLE_TYPE1_HEADER_SIZE );
  184. valid->statetable.optdata =
  185. &st_rec;
  186. valid->statetable.optdata_load_func =
  187. gxv_mort_subtable_type1_substitutionTable_load;
  188. valid->statetable.subtable_setup_func =
  189. gxv_mort_subtable_type1_subtable_setup;
  190. valid->statetable.entry_glyphoffset_fmt =
  191. GXV_GLYPHOFFSET_ULONG;
  192. valid->statetable.entry_validate_func =
  193. gxv_mort_subtable_type1_entry_validate;
  194. gxv_StateTable_validate( p, limit, valid );
  195. gxv_mort_subtable_type1_substTable_validate(
  196. table + st_rec.substitutionTable,
  197. table + st_rec.substitutionTable + st_rec.substitutionTable_length,
  198. valid );
  199. GXV_EXIT;
  200. }
  201. /* END */