| 1 | /**************************************************************************** |
| 2 | * |
| 3 | * gxvcommn.h |
| 4 | * |
| 5 | * TrueTypeGX/AAT common tables validation (specification). |
| 6 | * |
| 7 | * Copyright (C) 2004-2023 by |
| 8 | * 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 | * |
| 21 | * gxvalid is derived from both gxlayout module and otvalid module. |
| 22 | * Development of gxlayout is supported by the Information-technology |
| 23 | * Promotion Agency(IPA), Japan. |
| 24 | * |
| 25 | */ |
| 26 | |
| 27 | |
| 28 | /* |
| 29 | * keywords in variable naming |
| 30 | * --------------------------- |
| 31 | * table: Of type FT_Bytes, pointing to the start of this table/subtable. |
| 32 | * limit: Of type FT_Bytes, pointing to the end of this table/subtable, |
| 33 | * including padding for alignment. |
| 34 | * offset: Of type FT_UInt, the number of octets from the start to target. |
| 35 | * length: Of type FT_UInt, the number of octets from the start to the |
| 36 | * end in this table/subtable, including padding for alignment. |
| 37 | * |
| 38 | * _MIN, _MAX: Should be added to the tail of macros, as INT_MIN, etc. |
| 39 | */ |
| 40 | |
| 41 | |
| 42 | #ifndef GXVCOMMN_H_ |
| 43 | #define GXVCOMMN_H_ |
| 44 | |
| 45 | |
| 46 | #include "gxvalid.h" |
| 47 | #include <freetype/internal/ftdebug.h> |
| 48 | #include <freetype/ftsnames.h> |
| 49 | |
| 50 | |
| 51 | FT_BEGIN_HEADER |
| 52 | |
| 53 | |
| 54 | /* some variables are not evaluated or only used in trace */ |
| 55 | |
| 56 | #ifdef FT_DEBUG_LEVEL_TRACE |
| 57 | #define GXV_LOAD_TRACE_VARS |
| 58 | #else |
| 59 | #undef GXV_LOAD_TRACE_VARS |
| 60 | #endif |
| 61 | |
| 62 | #undef GXV_LOAD_UNUSED_VARS /* debug purpose */ |
| 63 | |
| 64 | #define IS_PARANOID_VALIDATION \ |
| 65 | ( gxvalid->root->level >= FT_VALIDATE_PARANOID ) |
| 66 | #define GXV_SET_ERR_IF_PARANOID( err ) \ |
| 67 | do { if ( IS_PARANOID_VALIDATION ) ( err ); } while ( 0 ) |
| 68 | |
| 69 | |
| 70 | /*************************************************************************/ |
| 71 | /*************************************************************************/ |
| 72 | /***** *****/ |
| 73 | /***** VALIDATION *****/ |
| 74 | /***** *****/ |
| 75 | /*************************************************************************/ |
| 76 | /*************************************************************************/ |
| 77 | |
| 78 | typedef struct GXV_ValidatorRec_* GXV_Validator; |
| 79 | |
| 80 | |
| 81 | #define DUMMY_LIMIT 0 |
| 82 | |
| 83 | typedef void |
| 84 | (*GXV_Validate_Func)( FT_Bytes table, |
| 85 | FT_Bytes limit, |
| 86 | GXV_Validator gxvalid ); |
| 87 | |
| 88 | |
| 89 | /* ====================== LookupTable Validator ======================== */ |
| 90 | |
| 91 | typedef union GXV_LookupValueDesc_ |
| 92 | { |
| 93 | FT_UShort u; |
| 94 | FT_Short s; |
| 95 | |
| 96 | } GXV_LookupValueDesc; |
| 97 | |
| 98 | typedef const GXV_LookupValueDesc* GXV_LookupValueCPtr; |
| 99 | |
| 100 | typedef enum GXV_LookupValue_SignSpec_ |
| 101 | { |
| 102 | GXV_LOOKUPVALUE_UNSIGNED = 0, |
| 103 | GXV_LOOKUPVALUE_SIGNED |
| 104 | |
| 105 | } GXV_LookupValue_SignSpec; |
| 106 | |
| 107 | |
| 108 | typedef void |
| 109 | (*GXV_Lookup_Value_Validate_Func)( FT_UShort glyph, |
| 110 | GXV_LookupValueCPtr value_p, |
| 111 | GXV_Validator gxvalid ); |
| 112 | |
| 113 | typedef GXV_LookupValueDesc |
| 114 | (*GXV_Lookup_Fmt4_Transit_Func)( FT_UShort relative_gindex, |
| 115 | GXV_LookupValueCPtr base_value_p, |
| 116 | FT_Bytes lookuptbl_limit, |
| 117 | GXV_Validator gxvalid ); |
| 118 | |
| 119 | |
| 120 | /* ====================== StateTable Validator ========================= */ |
| 121 | |
| 122 | typedef enum GXV_GlyphOffset_Format_ |
| 123 | { |
| 124 | GXV_GLYPHOFFSET_NONE = -1, |
| 125 | GXV_GLYPHOFFSET_UCHAR = 2, |
| 126 | GXV_GLYPHOFFSET_CHAR, |
| 127 | GXV_GLYPHOFFSET_USHORT = 4, |
| 128 | GXV_GLYPHOFFSET_SHORT, |
| 129 | GXV_GLYPHOFFSET_ULONG = 8, |
| 130 | GXV_GLYPHOFFSET_LONG |
| 131 | |
| 132 | } GXV_GlyphOffset_Format; |
| 133 | |
| 134 | |
| 135 | #define GXV_GLYPHOFFSET_FMT( table ) \ |
| 136 | ( gxvalid->table.entry_glyphoffset_fmt ) |
| 137 | |
| 138 | #define GXV_GLYPHOFFSET_SIZE( table ) \ |
| 139 | ( gxvalid->table.entry_glyphoffset_fmt / 2 ) |
| 140 | |
| 141 | |
| 142 | /* ----------------------- 16bit StateTable ---------------------------- */ |
| 143 | |
| 144 | typedef union GXV_StateTable_GlyphOffsetDesc_ |
| 145 | { |
| 146 | FT_Byte uc; |
| 147 | FT_UShort u; /* same as GXV_LookupValueDesc */ |
| 148 | FT_ULong ul; |
| 149 | FT_Char c; |
| 150 | FT_Short s; /* same as GXV_LookupValueDesc */ |
| 151 | FT_Long l; |
| 152 | |
| 153 | } GXV_StateTable_GlyphOffsetDesc; |
| 154 | |
| 155 | typedef const GXV_StateTable_GlyphOffsetDesc* GXV_StateTable_GlyphOffsetCPtr; |
| 156 | |
| 157 | typedef void |
| 158 | (*GXV_StateTable_Subtable_Setup_Func)( FT_UShort table_size, |
| 159 | FT_UShort classTable, |
| 160 | FT_UShort stateArray, |
| 161 | FT_UShort entryTable, |
| 162 | FT_UShort* classTable_length_p, |
| 163 | FT_UShort* stateArray_length_p, |
| 164 | FT_UShort* entryTable_length_p, |
| 165 | GXV_Validator gxvalid ); |
| 166 | |
| 167 | typedef void |
| 168 | (*GXV_StateTable_Entry_Validate_Func)( |
| 169 | FT_Byte state, |
| 170 | FT_UShort flags, |
| 171 | GXV_StateTable_GlyphOffsetCPtr glyphOffset_p, |
| 172 | FT_Bytes statetable_table, |
| 173 | FT_Bytes statetable_limit, |
| 174 | GXV_Validator gxvalid ); |
| 175 | |
| 176 | typedef void |
| 177 | (*GXV_StateTable_OptData_Load_Func)( FT_Bytes table, |
| 178 | FT_Bytes limit, |
| 179 | GXV_Validator gxvalid ); |
| 180 | |
| 181 | typedef struct GXV_StateTable_ValidatorRec_ |
| 182 | { |
| 183 | GXV_GlyphOffset_Format entry_glyphoffset_fmt; |
| 184 | void* optdata; |
| 185 | |
| 186 | GXV_StateTable_Subtable_Setup_Func subtable_setup_func; |
| 187 | GXV_StateTable_Entry_Validate_Func entry_validate_func; |
| 188 | GXV_StateTable_OptData_Load_Func optdata_load_func; |
| 189 | |
| 190 | } GXV_StateTable_ValidatorRec, *GXV_StateTable_ValidatorRecData; |
| 191 | |
| 192 | |
| 193 | /* ---------------------- 32bit XStateTable ---------------------------- */ |
| 194 | |
| 195 | typedef GXV_StateTable_GlyphOffsetDesc GXV_XStateTable_GlyphOffsetDesc; |
| 196 | |
| 197 | typedef const GXV_XStateTable_GlyphOffsetDesc* GXV_XStateTable_GlyphOffsetCPtr; |
| 198 | |
| 199 | typedef void |
| 200 | (*GXV_XStateTable_Subtable_Setup_Func)( FT_ULong table_size, |
| 201 | FT_ULong classTable, |
| 202 | FT_ULong stateArray, |
| 203 | FT_ULong entryTable, |
| 204 | FT_ULong* classTable_length_p, |
| 205 | FT_ULong* stateArray_length_p, |
| 206 | FT_ULong* entryTable_length_p, |
| 207 | GXV_Validator gxvalid ); |
| 208 | |
| 209 | typedef void |
| 210 | (*GXV_XStateTable_Entry_Validate_Func)( |
| 211 | FT_UShort state, |
| 212 | FT_UShort flags, |
| 213 | GXV_StateTable_GlyphOffsetCPtr glyphOffset_p, |
| 214 | FT_Bytes xstatetable_table, |
| 215 | FT_Bytes xstatetable_limit, |
| 216 | GXV_Validator gxvalid ); |
| 217 | |
| 218 | |
| 219 | typedef GXV_StateTable_OptData_Load_Func GXV_XStateTable_OptData_Load_Func; |
| 220 | |
| 221 | |
| 222 | typedef struct GXV_XStateTable_ValidatorRec_ |
| 223 | { |
| 224 | int entry_glyphoffset_fmt; |
| 225 | void* optdata; |
| 226 | |
| 227 | GXV_XStateTable_Subtable_Setup_Func subtable_setup_func; |
| 228 | GXV_XStateTable_Entry_Validate_Func entry_validate_func; |
| 229 | GXV_XStateTable_OptData_Load_Func optdata_load_func; |
| 230 | |
| 231 | FT_ULong nClasses; |
| 232 | FT_UShort maxClassID; |
| 233 | |
| 234 | } GXV_XStateTable_ValidatorRec, *GXV_XStateTable_ValidatorRecData; |
| 235 | |
| 236 | |
| 237 | /* ===================================================================== */ |
| 238 | |
| 239 | typedef struct GXV_ValidatorRec_ |
| 240 | { |
| 241 | FT_Validator root; |
| 242 | |
| 243 | FT_Face face; |
| 244 | void* table_data; |
| 245 | |
| 246 | FT_ULong subtable_length; |
| 247 | |
| 248 | GXV_LookupValue_SignSpec lookupval_sign; |
| 249 | GXV_Lookup_Value_Validate_Func lookupval_func; |
| 250 | GXV_Lookup_Fmt4_Transit_Func lookupfmt4_trans; |
| 251 | FT_Bytes lookuptbl_head; |
| 252 | |
| 253 | FT_UShort min_gid; |
| 254 | FT_UShort max_gid; |
| 255 | |
| 256 | GXV_StateTable_ValidatorRec statetable; |
| 257 | GXV_XStateTable_ValidatorRec xstatetable; |
| 258 | |
| 259 | #ifdef FT_DEBUG_LEVEL_TRACE |
| 260 | FT_UInt debug_indent; |
| 261 | const FT_String* debug_function_name[3]; |
| 262 | #endif |
| 263 | |
| 264 | } GXV_ValidatorRec; |
| 265 | |
| 266 | |
| 267 | #define GXV_TABLE_DATA( tag, field ) \ |
| 268 | ( ( (GXV_ ## tag ## _Data)gxvalid->table_data )->field ) |
| 269 | |
| 270 | #undef FT_INVALID_ |
| 271 | #define FT_INVALID_( _error ) \ |
| 272 | ft_validator_error( gxvalid->root, FT_THROW( _error ) ) |
| 273 | |
| 274 | #define GXV_LIMIT_CHECK( _count ) \ |
| 275 | FT_BEGIN_STMNT \ |
| 276 | if ( p + _count > ( limit? limit : gxvalid->root->limit ) ) \ |
| 277 | FT_INVALID_TOO_SHORT; \ |
| 278 | FT_END_STMNT |
| 279 | |
| 280 | |
| 281 | #ifdef FT_DEBUG_LEVEL_TRACE |
| 282 | |
| 283 | #define GXV_INIT gxvalid->debug_indent = 0 |
| 284 | |
| 285 | #define GXV_NAME_ENTER( name ) \ |
| 286 | FT_BEGIN_STMNT \ |
| 287 | gxvalid->debug_indent += 2; \ |
| 288 | FT_TRACE4(( "%*.s", gxvalid->debug_indent, "" )); \ |
| 289 | FT_TRACE4(( "%s table\n", name )); \ |
| 290 | FT_END_STMNT |
| 291 | |
| 292 | #define GXV_EXIT gxvalid->debug_indent -= 2 |
| 293 | |
| 294 | #define GXV_TRACE( s ) \ |
| 295 | FT_BEGIN_STMNT \ |
| 296 | FT_TRACE4(( "%*.s", gxvalid->debug_indent, "" )); \ |
| 297 | FT_TRACE4( s ); \ |
| 298 | FT_END_STMNT |
| 299 | |
| 300 | #else /* !FT_DEBUG_LEVEL_TRACE */ |
| 301 | |
| 302 | #define GXV_INIT do { } while ( 0 ) |
| 303 | #define GXV_NAME_ENTER( name ) do { } while ( 0 ) |
| 304 | #define GXV_EXIT do { } while ( 0 ) |
| 305 | |
| 306 | #define GXV_TRACE( s ) do { } while ( 0 ) |
| 307 | |
| 308 | #endif /* !FT_DEBUG_LEVEL_TRACE */ |
| 309 | |
| 310 | |
| 311 | /*************************************************************************/ |
| 312 | /*************************************************************************/ |
| 313 | /***** *****/ |
| 314 | /***** 32bit alignment checking *****/ |
| 315 | /***** *****/ |
| 316 | /*************************************************************************/ |
| 317 | /*************************************************************************/ |
| 318 | |
| 319 | #define GXV_32BIT_ALIGNMENT_VALIDATE( a ) \ |
| 320 | FT_BEGIN_STMNT \ |
| 321 | { \ |
| 322 | if ( (a) & 3 ) \ |
| 323 | FT_INVALID_OFFSET; \ |
| 324 | } \ |
| 325 | FT_END_STMNT |
| 326 | |
| 327 | |
| 328 | /*************************************************************************/ |
| 329 | /*************************************************************************/ |
| 330 | /***** *****/ |
| 331 | /***** Dumping Binary Data *****/ |
| 332 | /***** *****/ |
| 333 | /*************************************************************************/ |
| 334 | /*************************************************************************/ |
| 335 | |
| 336 | #define GXV_TRACE_HEXDUMP( p, len ) \ |
| 337 | FT_BEGIN_STMNT \ |
| 338 | { \ |
| 339 | FT_Bytes b; \ |
| 340 | \ |
| 341 | \ |
| 342 | for ( b = p; b < (FT_Bytes)p + len; b++ ) \ |
| 343 | FT_TRACE1(("\\x%02x", *b)); \ |
| 344 | } \ |
| 345 | FT_END_STMNT |
| 346 | |
| 347 | #define GXV_TRACE_HEXDUMP_C( p, len ) \ |
| 348 | FT_BEGIN_STMNT \ |
| 349 | { \ |
| 350 | FT_Bytes b; \ |
| 351 | \ |
| 352 | \ |
| 353 | for ( b = p; b < (FT_Bytes)p + len; b++ ) \ |
| 354 | if ( 0x40 < *b && *b < 0x7E ) \ |
| 355 | FT_TRACE1(("%c", *b)); \ |
| 356 | else \ |
| 357 | FT_TRACE1(("\\x%02x", *b)); \ |
| 358 | } \ |
| 359 | FT_END_STMNT |
| 360 | |
| 361 | #define GXV_TRACE_HEXDUMP_SFNTNAME( n ) \ |
| 362 | GXV_TRACE_HEXDUMP( n.string, n.string_len ) |
| 363 | |
| 364 | |
| 365 | /*************************************************************************/ |
| 366 | /*************************************************************************/ |
| 367 | /***** *****/ |
| 368 | /***** LOOKUP TABLE *****/ |
| 369 | /***** *****/ |
| 370 | /*************************************************************************/ |
| 371 | /*************************************************************************/ |
| 372 | |
| 373 | FT_LOCAL( void ) |
| 374 | ( FT_Bytes p, |
| 375 | FT_Bytes limit, |
| 376 | FT_UShort* unitSize_p, |
| 377 | FT_UShort* nUnits_p, |
| 378 | GXV_Validator gxvalid ); |
| 379 | |
| 380 | FT_LOCAL( void ) |
| 381 | gxv_LookupTable_validate( FT_Bytes table, |
| 382 | FT_Bytes limit, |
| 383 | GXV_Validator gxvalid ); |
| 384 | |
| 385 | |
| 386 | /*************************************************************************/ |
| 387 | /*************************************************************************/ |
| 388 | /***** *****/ |
| 389 | /***** Glyph ID *****/ |
| 390 | /***** *****/ |
| 391 | /*************************************************************************/ |
| 392 | /*************************************************************************/ |
| 393 | |
| 394 | FT_LOCAL( FT_Int ) |
| 395 | gxv_glyphid_validate( FT_UShort gid, |
| 396 | GXV_Validator gxvalid ); |
| 397 | |
| 398 | |
| 399 | /*************************************************************************/ |
| 400 | /*************************************************************************/ |
| 401 | /***** *****/ |
| 402 | /***** CONTROL POINT *****/ |
| 403 | /***** *****/ |
| 404 | /*************************************************************************/ |
| 405 | /*************************************************************************/ |
| 406 | |
| 407 | FT_LOCAL( void ) |
| 408 | gxv_ctlPoint_validate( FT_UShort gid, |
| 409 | FT_UShort ctl_point, |
| 410 | GXV_Validator gxvalid ); |
| 411 | |
| 412 | |
| 413 | /*************************************************************************/ |
| 414 | /*************************************************************************/ |
| 415 | /***** *****/ |
| 416 | /***** SFNT NAME *****/ |
| 417 | /***** *****/ |
| 418 | /*************************************************************************/ |
| 419 | /*************************************************************************/ |
| 420 | |
| 421 | FT_LOCAL( void ) |
| 422 | gxv_sfntName_validate( FT_UShort name_index, |
| 423 | FT_UShort min_index, |
| 424 | FT_UShort max_index, |
| 425 | GXV_Validator gxvalid ); |
| 426 | |
| 427 | |
| 428 | /*************************************************************************/ |
| 429 | /*************************************************************************/ |
| 430 | /***** *****/ |
| 431 | /***** STATE TABLE *****/ |
| 432 | /***** *****/ |
| 433 | /*************************************************************************/ |
| 434 | /*************************************************************************/ |
| 435 | |
| 436 | FT_LOCAL( void ) |
| 437 | gxv_StateTable_subtable_setup( FT_UShort table_size, |
| 438 | FT_UShort classTable, |
| 439 | FT_UShort stateArray, |
| 440 | FT_UShort entryTable, |
| 441 | FT_UShort* classTable_length_p, |
| 442 | FT_UShort* stateArray_length_p, |
| 443 | FT_UShort* entryTable_length_p, |
| 444 | GXV_Validator gxvalid ); |
| 445 | |
| 446 | FT_LOCAL( void ) |
| 447 | gxv_XStateTable_subtable_setup( FT_ULong table_size, |
| 448 | FT_ULong classTable, |
| 449 | FT_ULong stateArray, |
| 450 | FT_ULong entryTable, |
| 451 | FT_ULong* classTable_length_p, |
| 452 | FT_ULong* stateArray_length_p, |
| 453 | FT_ULong* entryTable_length_p, |
| 454 | GXV_Validator gxvalid ); |
| 455 | |
| 456 | FT_LOCAL( void ) |
| 457 | gxv_StateTable_validate( FT_Bytes table, |
| 458 | FT_Bytes limit, |
| 459 | GXV_Validator gxvalid ); |
| 460 | |
| 461 | FT_LOCAL( void ) |
| 462 | gxv_XStateTable_validate( FT_Bytes table, |
| 463 | FT_Bytes limit, |
| 464 | GXV_Validator gxvalid ); |
| 465 | |
| 466 | |
| 467 | /*************************************************************************/ |
| 468 | /*************************************************************************/ |
| 469 | /***** *****/ |
| 470 | /***** UTILITY MACROS AND FUNCTIONS *****/ |
| 471 | /***** *****/ |
| 472 | /*************************************************************************/ |
| 473 | /*************************************************************************/ |
| 474 | |
| 475 | FT_LOCAL( void ) |
| 476 | gxv_array_getlimits_byte( FT_Bytes table, |
| 477 | FT_Bytes limit, |
| 478 | FT_Byte* min, |
| 479 | FT_Byte* max, |
| 480 | GXV_Validator gxvalid ); |
| 481 | |
| 482 | FT_LOCAL( void ) |
| 483 | gxv_array_getlimits_ushort( FT_Bytes table, |
| 484 | FT_Bytes limit, |
| 485 | FT_UShort* min, |
| 486 | FT_UShort* max, |
| 487 | GXV_Validator gxvalid ); |
| 488 | |
| 489 | FT_LOCAL( void ) |
| 490 | gxv_set_length_by_ushort_offset( FT_UShort* offset, |
| 491 | FT_UShort** length, |
| 492 | FT_UShort* buff, |
| 493 | FT_UInt nmemb, |
| 494 | FT_UShort limit, |
| 495 | GXV_Validator gxvalid ); |
| 496 | |
| 497 | FT_LOCAL( void ) |
| 498 | gxv_set_length_by_ulong_offset( FT_ULong* offset, |
| 499 | FT_ULong** length, |
| 500 | FT_ULong* buff, |
| 501 | FT_UInt nmemb, |
| 502 | FT_ULong limit, |
| 503 | GXV_Validator gxvalid); |
| 504 | |
| 505 | |
| 506 | #define GXV_SUBTABLE_OFFSET_CHECK( _offset ) \ |
| 507 | FT_BEGIN_STMNT \ |
| 508 | if ( (_offset) > gxvalid->subtable_length ) \ |
| 509 | FT_INVALID_OFFSET; \ |
| 510 | FT_END_STMNT |
| 511 | |
| 512 | #define GXV_SUBTABLE_LIMIT_CHECK( _count ) \ |
| 513 | FT_BEGIN_STMNT \ |
| 514 | if ( ( p + (_count) - gxvalid->subtable_start ) > \ |
| 515 | gxvalid->subtable_length ) \ |
| 516 | FT_INVALID_TOO_SHORT; \ |
| 517 | FT_END_STMNT |
| 518 | |
| 519 | #define GXV_USHORT_TO_SHORT( _us ) \ |
| 520 | ( ( 0x8000U < ( _us ) ) ? ( ( _us ) - 0x8000U ) : ( _us ) ) |
| 521 | |
| 522 | #define ( 2 + 2 + 2 + 2 ) |
| 523 | #define GXV_STATETABLE_HEADER_SIZE |
| 524 | |
| 525 | #define ( 4 + 4 + 4 + 4 ) |
| 526 | #define GXV_XSTATETABLE_HEADER_SIZE |
| 527 | |
| 528 | |
| 529 | /*************************************************************************/ |
| 530 | /*************************************************************************/ |
| 531 | /***** *****/ |
| 532 | /***** Table overlapping *****/ |
| 533 | /***** *****/ |
| 534 | /*************************************************************************/ |
| 535 | /*************************************************************************/ |
| 536 | |
| 537 | typedef struct GXV_odtect_DataRec_ |
| 538 | { |
| 539 | FT_Bytes start; |
| 540 | FT_ULong length; |
| 541 | FT_String* name; |
| 542 | |
| 543 | } GXV_odtect_DataRec, *GXV_odtect_Data; |
| 544 | |
| 545 | typedef struct GXV_odtect_RangeRec_ |
| 546 | { |
| 547 | FT_UInt nRanges; |
| 548 | GXV_odtect_Data range; |
| 549 | |
| 550 | } GXV_odtect_RangeRec, *GXV_odtect_Range; |
| 551 | |
| 552 | |
| 553 | FT_LOCAL( void ) |
| 554 | gxv_odtect_add_range( FT_Bytes start, |
| 555 | FT_ULong length, |
| 556 | const FT_String* name, |
| 557 | GXV_odtect_Range odtect ); |
| 558 | |
| 559 | FT_LOCAL( void ) |
| 560 | gxv_odtect_validate( GXV_odtect_Range odtect, |
| 561 | GXV_Validator gxvalid ); |
| 562 | |
| 563 | |
| 564 | #define GXV_ODTECT( n, odtect ) \ |
| 565 | GXV_odtect_DataRec odtect ## _range[n]; \ |
| 566 | GXV_odtect_RangeRec odtect ## _rec = { 0, NULL }; \ |
| 567 | GXV_odtect_Range odtect = NULL |
| 568 | |
| 569 | #define GXV_ODTECT_INIT( odtect ) \ |
| 570 | FT_BEGIN_STMNT \ |
| 571 | odtect ## _rec.nRanges = 0; \ |
| 572 | odtect ## _rec.range = odtect ## _range; \ |
| 573 | odtect = & odtect ## _rec; \ |
| 574 | FT_END_STMNT |
| 575 | |
| 576 | |
| 577 | /* */ |
| 578 | |
| 579 | FT_END_HEADER |
| 580 | |
| 581 | #endif /* GXVCOMMN_H_ */ |
| 582 | |
| 583 | |
| 584 | /* END */ |
| 585 | |