1 /***************************************************************************/ 2 /* */ 3 /* otvjstf.c */ 4 /* */ 5 /* OpenType JSTF table validation (body). */ 6 /* */ 7 /* Copyright 2004-2018 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 18 19 #include "otvalid.h" 20 #include "otvcommn.h" 21 #include "otvgpos.h" 22 23 24 /*************************************************************************/ 25 /* */ 26 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 27 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 28 /* messages during execution. */ 29 /* */ 30 #undef FT_COMPONENT 31 #define FT_COMPONENT trace_otvjstf 32 33 34 #define JstfPriorityFunc otv_JstfPriority_validate 35 #define JstfLookupFunc otv_GPOS_subtable_validate 36 37 /* uses otvalid->extra1 (GSUB lookup count) */ 38 /* uses otvalid->extra2 (GPOS lookup count) */ 39 /* sets otvalid->extra1 (counter) */ 40 41 static void otv_JstfPriority_validate(FT_Bytes table,OTV_Validator otvalid)42 otv_JstfPriority_validate( FT_Bytes table, 43 OTV_Validator otvalid ) 44 { 45 FT_Bytes p = table; 46 FT_UInt table_size; 47 FT_UInt gsub_lookup_count, gpos_lookup_count; 48 49 OTV_OPTIONAL_TABLE( ShrinkageEnableGSUB ); 50 OTV_OPTIONAL_TABLE( ShrinkageDisableGSUB ); 51 OTV_OPTIONAL_TABLE( ShrinkageEnableGPOS ); 52 OTV_OPTIONAL_TABLE( ShrinkageDisableGPOS ); 53 OTV_OPTIONAL_TABLE( ExtensionEnableGSUB ); 54 OTV_OPTIONAL_TABLE( ExtensionDisableGSUB ); 55 OTV_OPTIONAL_TABLE( ExtensionEnableGPOS ); 56 OTV_OPTIONAL_TABLE( ExtensionDisableGPOS ); 57 OTV_OPTIONAL_TABLE( ShrinkageJstfMax ); 58 OTV_OPTIONAL_TABLE( ExtensionJstfMax ); 59 60 61 OTV_ENTER; 62 OTV_TRACE(( "JstfPriority table\n" )); 63 64 OTV_LIMIT_CHECK( 20 ); 65 66 gsub_lookup_count = otvalid->extra1; 67 gpos_lookup_count = otvalid->extra2; 68 69 table_size = 20; 70 71 otvalid->extra1 = gsub_lookup_count; 72 73 OTV_OPTIONAL_OFFSET( ShrinkageEnableGSUB ); 74 OTV_SIZE_CHECK( ShrinkageEnableGSUB ); 75 if ( ShrinkageEnableGSUB ) 76 otv_x_ux( table + ShrinkageEnableGSUB, otvalid ); 77 78 OTV_OPTIONAL_OFFSET( ShrinkageDisableGSUB ); 79 OTV_SIZE_CHECK( ShrinkageDisableGSUB ); 80 if ( ShrinkageDisableGSUB ) 81 otv_x_ux( table + ShrinkageDisableGSUB, otvalid ); 82 83 otvalid->extra1 = gpos_lookup_count; 84 85 OTV_OPTIONAL_OFFSET( ShrinkageEnableGPOS ); 86 OTV_SIZE_CHECK( ShrinkageEnableGPOS ); 87 if ( ShrinkageEnableGPOS ) 88 otv_x_ux( table + ShrinkageEnableGPOS, otvalid ); 89 90 OTV_OPTIONAL_OFFSET( ShrinkageDisableGPOS ); 91 OTV_SIZE_CHECK( ShrinkageDisableGPOS ); 92 if ( ShrinkageDisableGPOS ) 93 otv_x_ux( table + ShrinkageDisableGPOS, otvalid ); 94 95 OTV_OPTIONAL_OFFSET( ShrinkageJstfMax ); 96 OTV_SIZE_CHECK( ShrinkageJstfMax ); 97 if ( ShrinkageJstfMax ) 98 { 99 /* XXX: check lookup types? */ 100 OTV_NEST2( JstfMax, JstfLookup ); 101 OTV_RUN( table + ShrinkageJstfMax, otvalid ); 102 } 103 104 otvalid->extra1 = gsub_lookup_count; 105 106 OTV_OPTIONAL_OFFSET( ExtensionEnableGSUB ); 107 OTV_SIZE_CHECK( ExtensionEnableGSUB ); 108 if ( ExtensionEnableGSUB ) 109 otv_x_ux( table + ExtensionEnableGSUB, otvalid ); 110 111 OTV_OPTIONAL_OFFSET( ExtensionDisableGSUB ); 112 OTV_SIZE_CHECK( ExtensionDisableGSUB ); 113 if ( ExtensionDisableGSUB ) 114 otv_x_ux( table + ExtensionDisableGSUB, otvalid ); 115 116 otvalid->extra1 = gpos_lookup_count; 117 118 OTV_OPTIONAL_OFFSET( ExtensionEnableGPOS ); 119 OTV_SIZE_CHECK( ExtensionEnableGPOS ); 120 if ( ExtensionEnableGPOS ) 121 otv_x_ux( table + ExtensionEnableGPOS, otvalid ); 122 123 OTV_OPTIONAL_OFFSET( ExtensionDisableGPOS ); 124 OTV_SIZE_CHECK( ExtensionDisableGPOS ); 125 if ( ExtensionDisableGPOS ) 126 otv_x_ux( table + ExtensionDisableGPOS, otvalid ); 127 128 OTV_OPTIONAL_OFFSET( ExtensionJstfMax ); 129 OTV_SIZE_CHECK( ExtensionJstfMax ); 130 if ( ExtensionJstfMax ) 131 { 132 /* XXX: check lookup types? */ 133 OTV_NEST2( JstfMax, JstfLookup ); 134 OTV_RUN( table + ExtensionJstfMax, otvalid ); 135 } 136 137 otvalid->extra1 = gsub_lookup_count; 138 otvalid->extra2 = gpos_lookup_count; 139 140 OTV_EXIT; 141 } 142 143 144 /* sets otvalid->extra (glyph count) */ 145 /* sets otvalid->func1 (otv_JstfPriority_validate) */ 146 147 static void otv_JstfScript_validate(FT_Bytes table,OTV_Validator otvalid)148 otv_JstfScript_validate( FT_Bytes table, 149 OTV_Validator otvalid ) 150 { 151 FT_Bytes p = table; 152 FT_UInt table_size; 153 FT_UInt JstfLangSysCount; 154 155 OTV_OPTIONAL_TABLE( ExtGlyph ); 156 OTV_OPTIONAL_TABLE( DefJstfLangSys ); 157 158 159 OTV_NAME_ENTER( "JstfScript" ); 160 161 OTV_LIMIT_CHECK( 6 ); 162 OTV_OPTIONAL_OFFSET( ExtGlyph ); 163 OTV_OPTIONAL_OFFSET( DefJstfLangSys ); 164 JstfLangSysCount = FT_NEXT_USHORT( p ); 165 166 OTV_TRACE(( " (JstfLangSysCount = %d)\n", JstfLangSysCount )); 167 168 table_size = JstfLangSysCount * 6 + 6; 169 170 OTV_SIZE_CHECK( ExtGlyph ); 171 if ( ExtGlyph ) 172 { 173 otvalid->extra1 = otvalid->glyph_count; 174 OTV_NEST1( ExtenderGlyph ); 175 OTV_RUN( table + ExtGlyph, otvalid ); 176 } 177 178 OTV_SIZE_CHECK( DefJstfLangSys ); 179 if ( DefJstfLangSys ) 180 { 181 OTV_NEST2( JstfLangSys, JstfPriority ); 182 OTV_RUN( table + DefJstfLangSys, otvalid ); 183 } 184 185 OTV_LIMIT_CHECK( 6 * JstfLangSysCount ); 186 187 /* JstfLangSysRecord */ 188 OTV_NEST2( JstfLangSys, JstfPriority ); 189 for ( ; JstfLangSysCount > 0; JstfLangSysCount-- ) 190 { 191 p += 4; /* skip JstfLangSysTag */ 192 193 OTV_RUN( table + FT_NEXT_USHORT( p ), otvalid ); 194 } 195 196 OTV_EXIT; 197 } 198 199 200 /* sets otvalid->extra1 (GSUB lookup count) */ 201 /* sets otvalid->extra2 (GPOS lookup count) */ 202 /* sets otvalid->glyph_count */ 203 204 FT_LOCAL_DEF( void ) otv_JSTF_validate(FT_Bytes table,FT_Bytes gsub,FT_Bytes gpos,FT_UInt glyph_count,FT_Validator ftvalid)205 otv_JSTF_validate( FT_Bytes table, 206 FT_Bytes gsub, 207 FT_Bytes gpos, 208 FT_UInt glyph_count, 209 FT_Validator ftvalid ) 210 { 211 OTV_ValidatorRec otvalidrec; 212 OTV_Validator otvalid = &otvalidrec; 213 FT_Bytes p = table; 214 FT_UInt JstfScriptCount; 215 216 217 otvalid->root = ftvalid; 218 219 220 FT_TRACE3(( "validating JSTF table\n" )); 221 OTV_INIT; 222 223 OTV_LIMIT_CHECK( 6 ); 224 225 if ( FT_NEXT_ULONG( p ) != 0x10000UL ) /* Version */ 226 FT_INVALID_FORMAT; 227 228 JstfScriptCount = FT_NEXT_USHORT( p ); 229 230 FT_TRACE3(( " (JstfScriptCount = %d)\n", JstfScriptCount )); 231 232 OTV_LIMIT_CHECK( JstfScriptCount * 6 ); 233 234 if ( gsub ) 235 otvalid->extra1 = otv_GSUBGPOS_get_Lookup_count( gsub ); 236 else 237 otvalid->extra1 = 0; 238 239 if ( gpos ) 240 otvalid->extra2 = otv_GSUBGPOS_get_Lookup_count( gpos ); 241 else 242 otvalid->extra2 = 0; 243 244 otvalid->glyph_count = glyph_count; 245 246 /* JstfScriptRecord */ 247 for ( ; JstfScriptCount > 0; JstfScriptCount-- ) 248 { 249 p += 4; /* skip JstfScriptTag */ 250 251 /* JstfScript */ 252 otv_JstfScript_validate( table + FT_NEXT_USHORT( p ), otvalid ); 253 } 254 255 FT_TRACE4(( "\n" )); 256 } 257 258 259 /* END */ 260