Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygengxvkern.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* gxvkern.c */ 00004 /* */ 00005 /* TrueTypeGX/AAT kern table validation (body). */ 00006 /* */ 00007 /* Copyright 2004, 2005, 2006, 2007 */ 00008 /* by suzuki toshiya, Masatake YAMATO, Red Hat K.K., */ 00009 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00010 /* */ 00011 /* This file is part of the FreeType project, and may only be used, */ 00012 /* modified, and distributed under the terms of the FreeType project */ 00013 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00014 /* this file you indicate that you have read the license and */ 00015 /* understand and accept it fully. */ 00016 /* */ 00017 /***************************************************************************/ 00018 00019 /***************************************************************************/ 00020 /* */ 00021 /* gxvalid is derived from both gxlayout module and otvalid module. */ 00022 /* Development of gxlayout is supported by the Information-technology */ 00023 /* Promotion Agency(IPA), Japan. */ 00024 /* */ 00025 /***************************************************************************/ 00026 00027 00028 #include "gxvalid.h" 00029 #include "gxvcommn.h" 00030 00031 #include FT_SFNT_NAMES_H 00032 #include FT_SERVICE_GX_VALIDATE_H 00033 00034 00035 /*************************************************************************/ 00036 /* */ 00037 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00038 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00039 /* messages during execution. */ 00040 /* */ 00041 #undef FT_COMPONENT 00042 #define FT_COMPONENT trace_gxvkern 00043 00044 00045 /*************************************************************************/ 00046 /*************************************************************************/ 00047 /***** *****/ 00048 /***** Data and Types *****/ 00049 /***** *****/ 00050 /*************************************************************************/ 00051 /*************************************************************************/ 00052 00053 typedef enum GXV_kern_Version_ 00054 { 00055 KERN_VERSION_CLASSIC = 0x0000, 00056 KERN_VERSION_NEW = 0x0001 00057 00058 } GXV_kern_Version; 00059 00060 00061 typedef enum GXV_kern_Dialect_ 00062 { 00063 KERN_DIALECT_UNKNOWN = 0, 00064 KERN_DIALECT_MS = FT_VALIDATE_MS, 00065 KERN_DIALECT_APPLE = FT_VALIDATE_APPLE, 00066 KERN_DIALECT_ANY = FT_VALIDATE_CKERN 00067 00068 } GXV_kern_Dialect; 00069 00070 00071 typedef struct GXV_kern_DataRec_ 00072 { 00073 GXV_kern_Version version; 00074 void *subtable_data; 00075 GXV_kern_Dialect dialect_request; 00076 00077 } GXV_kern_DataRec, *GXV_kern_Data; 00078 00079 00080 #define GXV_KERN_DATA( field ) GXV_TABLE_DATA( kern, field ) 00081 00082 #define KERN_IS_CLASSIC( valid ) \ 00083 ( KERN_VERSION_CLASSIC == GXV_KERN_DATA( version ) ) 00084 #define KERN_IS_NEW( valid ) \ 00085 ( KERN_VERSION_NEW == GXV_KERN_DATA( version ) ) 00086 00087 #define KERN_DIALECT( valid ) \ 00088 GXV_KERN_DATA( dialect_request ) 00089 #define KERN_ALLOWS_MS( valid ) \ 00090 ( KERN_DIALECT( valid ) & KERN_DIALECT_MS ) 00091 #define KERN_ALLOWS_APPLE( valid ) \ 00092 ( KERN_DIALECT( valid ) & KERN_DIALECT_APPLE ) 00093 00094 #define GXV_KERN_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 4 ) 00095 #define GXV_KERN_SUBTABLE_HEADER_SIZE ( KERN_IS_NEW( valid ) ? 8 : 6 ) 00096 00097 00098 /*************************************************************************/ 00099 /*************************************************************************/ 00100 /***** *****/ 00101 /***** SUBTABLE VALIDATORS *****/ 00102 /***** *****/ 00103 /*************************************************************************/ 00104 /*************************************************************************/ 00105 00106 00107 /* ============================= format 0 ============================== */ 00108 00109 static void 00110 gxv_kern_subtable_fmt0_pairs_validate( FT_Bytes table, 00111 FT_Bytes limit, 00112 FT_UShort nPairs, 00113 GXV_Validator valid ) 00114 { 00115 FT_Bytes p = table; 00116 FT_UShort i; 00117 00118 FT_UShort last_gid_left = 0; 00119 FT_UShort last_gid_right = 0; 00120 00121 FT_UNUSED( limit ); 00122 00123 00124 GXV_NAME_ENTER( "kern format 0 pairs" ); 00125 00126 for ( i = 0; i < nPairs; i++ ) 00127 { 00128 FT_UShort gid_left; 00129 FT_UShort gid_right; 00130 FT_Short kernValue; 00131 00132 00133 /* left */ 00134 gid_left = FT_NEXT_USHORT( p ); 00135 gxv_glyphid_validate( gid_left, valid ); 00136 00137 /* right */ 00138 gid_right = FT_NEXT_USHORT( p ); 00139 gxv_glyphid_validate( gid_right, valid ); 00140 00141 /* Pairs of left and right GIDs must be unique and sorted. */ 00142 GXV_TRACE(( "left gid = %u, right gid = %u\n", gid_left, gid_right )); 00143 if ( gid_left == last_gid_left ) 00144 { 00145 if ( last_gid_right < gid_right ) 00146 last_gid_right = gid_right; 00147 else 00148 FT_INVALID_DATA; 00149 } 00150 else if ( last_gid_left < gid_left ) 00151 { 00152 last_gid_left = gid_left; 00153 last_gid_right = gid_right; 00154 } 00155 else 00156 FT_INVALID_DATA; 00157 00158 /* skip the kern value */ 00159 kernValue = FT_NEXT_SHORT( p ); 00160 } 00161 00162 GXV_EXIT; 00163 } 00164 00165 static void 00166 gxv_kern_subtable_fmt0_validate( FT_Bytes table, 00167 FT_Bytes limit, 00168 GXV_Validator valid ) 00169 { 00170 FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE; 00171 00172 FT_UShort nPairs; 00173 FT_UShort unitSize; 00174 00175 00176 GXV_NAME_ENTER( "kern subtable format 0" ); 00177 00178 unitSize = 2 + 2 + 2; 00179 nPairs = 0; 00180 00181 /* nPairs, searchRange, entrySelector, rangeShift */ 00182 GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 ); 00183 gxv_BinSrchHeader_validate( p, limit, &unitSize, &nPairs, valid ); 00184 p += 2 + 2 + 2 + 2; 00185 00186 gxv_kern_subtable_fmt0_pairs_validate( p, limit, nPairs, valid ); 00187 00188 GXV_EXIT; 00189 } 00190 00191 00192 /* ============================= format 1 ============================== */ 00193 00194 00195 typedef struct GXV_kern_fmt1_StateOptRec_ 00196 { 00197 FT_UShort valueTable; 00198 FT_UShort valueTable_length; 00199 00200 } GXV_kern_fmt1_StateOptRec, *GXV_kern_fmt1_StateOptRecData; 00201 00202 00203 static void 00204 gxv_kern_subtable_fmt1_valueTable_load( FT_Bytes table, 00205 FT_Bytes limit, 00206 GXV_Validator valid ) 00207 { 00208 FT_Bytes p = table; 00209 GXV_kern_fmt1_StateOptRecData optdata = 00210 (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata; 00211 00212 00213 GXV_LIMIT_CHECK( 2 ); 00214 optdata->valueTable = FT_NEXT_USHORT( p ); 00215 } 00216 00217 00218 /* 00219 * passed tables_size covers whole StateTable, including kern fmt1 header 00220 */ 00221 static void 00222 gxv_kern_subtable_fmt1_subtable_setup( FT_UShort table_size, 00223 FT_UShort classTable, 00224 FT_UShort stateArray, 00225 FT_UShort entryTable, 00226 FT_UShort* classTable_length_p, 00227 FT_UShort* stateArray_length_p, 00228 FT_UShort* entryTable_length_p, 00229 GXV_Validator valid ) 00230 { 00231 FT_UShort o[4]; 00232 FT_UShort *l[4]; 00233 FT_UShort buff[5]; 00234 00235 GXV_kern_fmt1_StateOptRecData optdata = 00236 (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata; 00237 00238 00239 o[0] = classTable; 00240 o[1] = stateArray; 00241 o[2] = entryTable; 00242 o[3] = optdata->valueTable; 00243 l[0] = classTable_length_p; 00244 l[1] = stateArray_length_p; 00245 l[2] = entryTable_length_p; 00246 l[3] = &(optdata->valueTable_length); 00247 00248 gxv_set_length_by_ushort_offset( o, l, buff, 4, table_size, valid ); 00249 } 00250 00251 00252 /* 00253 * passed table & limit are of whole StateTable, not including subtables 00254 */ 00255 static void 00256 gxv_kern_subtable_fmt1_entry_validate( 00257 FT_Byte state, 00258 FT_UShort flags, 00259 GXV_StateTable_GlyphOffsetCPtr glyphOffset_p, 00260 FT_Bytes table, 00261 FT_Bytes limit, 00262 GXV_Validator valid ) 00263 { 00264 FT_UShort push; 00265 FT_UShort dontAdvance; 00266 FT_UShort valueOffset; 00267 FT_UShort kernAction; 00268 FT_UShort kernValue; 00269 00270 FT_UNUSED( state ); 00271 FT_UNUSED( glyphOffset_p ); 00272 00273 00274 push = (FT_UShort)( ( flags >> 15 ) & 1 ); 00275 dontAdvance = (FT_UShort)( ( flags >> 14 ) & 1 ); 00276 valueOffset = (FT_UShort)( flags & 0x3FFF ); 00277 00278 { 00279 GXV_kern_fmt1_StateOptRecData vt_rec = 00280 (GXV_kern_fmt1_StateOptRecData)valid->statetable.optdata; 00281 FT_Bytes p; 00282 00283 00284 if ( valueOffset < vt_rec->valueTable ) 00285 FT_INVALID_OFFSET; 00286 00287 p = table + valueOffset; 00288 limit = table + vt_rec->valueTable + vt_rec->valueTable_length; 00289 00290 GXV_LIMIT_CHECK( 2 + 2 ); 00291 kernAction = FT_NEXT_USHORT( p ); 00292 kernValue = FT_NEXT_USHORT( p ); 00293 } 00294 } 00295 00296 00297 static void 00298 gxv_kern_subtable_fmt1_validate( FT_Bytes table, 00299 FT_Bytes limit, 00300 GXV_Validator valid ) 00301 { 00302 FT_Bytes p = table; 00303 GXV_kern_fmt1_StateOptRec vt_rec; 00304 00305 00306 GXV_NAME_ENTER( "kern subtable format 1" ); 00307 00308 valid->statetable.optdata = 00309 &vt_rec; 00310 valid->statetable.optdata_load_func = 00311 gxv_kern_subtable_fmt1_valueTable_load; 00312 valid->statetable.subtable_setup_func = 00313 gxv_kern_subtable_fmt1_subtable_setup; 00314 valid->statetable.entry_glyphoffset_fmt = 00315 GXV_GLYPHOFFSET_NONE; 00316 valid->statetable.entry_validate_func = 00317 gxv_kern_subtable_fmt1_entry_validate; 00318 00319 gxv_StateTable_validate( p, limit, valid ); 00320 00321 GXV_EXIT; 00322 } 00323 00324 00325 /* ================ Data for Class-Based Subtables 2, 3 ================ */ 00326 00327 typedef enum GXV_kern_ClassSpec_ 00328 { 00329 GXV_KERN_CLS_L = 0, 00330 GXV_KERN_CLS_R 00331 00332 } GXV_kern_ClassSpec; 00333 00334 00335 /* ============================= format 2 ============================== */ 00336 00337 /* ---------------------- format 2 specific data ----------------------- */ 00338 00339 typedef struct GXV_kern_subtable_fmt2_DataRec_ 00340 { 00341 FT_UShort rowWidth; 00342 FT_UShort array; 00343 FT_UShort offset_min[2]; 00344 FT_UShort offset_max[2]; 00345 const FT_String* class_tag[2]; 00346 GXV_odtect_Range odtect; 00347 00348 } GXV_kern_subtable_fmt2_DataRec, *GXV_kern_subtable_fmt2_Data; 00349 00350 00351 #define GXV_KERN_FMT2_DATA( field ) \ 00352 ( ( (GXV_kern_subtable_fmt2_DataRec *) \ 00353 ( GXV_KERN_DATA( subtable_data ) ) )->field ) 00354 00355 00356 /* -------------------------- utility functions ----------------------- */ 00357 00358 static void 00359 gxv_kern_subtable_fmt2_clstbl_validate( FT_Bytes table, 00360 FT_Bytes limit, 00361 GXV_kern_ClassSpec spec, 00362 GXV_Validator valid ) 00363 { 00364 const FT_String* tag = GXV_KERN_FMT2_DATA( class_tag[spec] ); 00365 GXV_odtect_Range odtect = GXV_KERN_FMT2_DATA( odtect ); 00366 00367 FT_Bytes p = table; 00368 FT_UShort firstGlyph; 00369 FT_UShort nGlyphs; 00370 00371 00372 GXV_NAME_ENTER( "kern format 2 classTable" ); 00373 00374 GXV_LIMIT_CHECK( 2 + 2 ); 00375 firstGlyph = FT_NEXT_USHORT( p ); 00376 nGlyphs = FT_NEXT_USHORT( p ); 00377 GXV_TRACE(( " %s firstGlyph=%d, nGlyphs=%d\n", 00378 tag, firstGlyph, nGlyphs )); 00379 00380 gxv_glyphid_validate( firstGlyph, valid ); 00381 gxv_glyphid_validate( (FT_UShort)( firstGlyph + nGlyphs - 1 ), valid ); 00382 00383 gxv_array_getlimits_ushort( p, p + ( 2 * nGlyphs ), 00384 &( GXV_KERN_FMT2_DATA( offset_min[spec] ) ), 00385 &( GXV_KERN_FMT2_DATA( offset_max[spec] ) ), 00386 valid ); 00387 00388 gxv_odtect_add_range( table, 2 * nGlyphs, tag, odtect ); 00389 00390 GXV_EXIT; 00391 } 00392 00393 00394 static void 00395 gxv_kern_subtable_fmt2_validate( FT_Bytes table, 00396 FT_Bytes limit, 00397 GXV_Validator valid ) 00398 { 00399 GXV_ODTECT( 3, odtect ); 00400 GXV_kern_subtable_fmt2_DataRec fmt2_rec = 00401 { 0, 0, { 0, 0 }, { 0, 0 }, { "leftClass", "rightClass" }, NULL }; 00402 00403 FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE; 00404 FT_UShort leftOffsetTable; 00405 FT_UShort rightOffsetTable; 00406 00407 00408 GXV_NAME_ENTER( "kern subtable format 2" ); 00409 00410 GXV_ODTECT_INIT( odtect ); 00411 fmt2_rec.odtect = odtect; 00412 GXV_KERN_DATA( subtable_data ) = &fmt2_rec; 00413 00414 GXV_LIMIT_CHECK( 2 + 2 + 2 + 2 ); 00415 GXV_KERN_FMT2_DATA( rowWidth ) = FT_NEXT_USHORT( p ); 00416 leftOffsetTable = FT_NEXT_USHORT( p ); 00417 rightOffsetTable = FT_NEXT_USHORT( p ); 00418 GXV_KERN_FMT2_DATA( array ) = FT_NEXT_USHORT( p ); 00419 00420 GXV_TRACE(( "rowWidth = %d\n", GXV_KERN_FMT2_DATA( rowWidth ) )); 00421 00422 00423 GXV_LIMIT_CHECK( leftOffsetTable ); 00424 GXV_LIMIT_CHECK( rightOffsetTable ); 00425 GXV_LIMIT_CHECK( GXV_KERN_FMT2_DATA( array ) ); 00426 00427 gxv_kern_subtable_fmt2_clstbl_validate( table + leftOffsetTable, limit, 00428 GXV_KERN_CLS_L, valid ); 00429 00430 gxv_kern_subtable_fmt2_clstbl_validate( table + rightOffsetTable, limit, 00431 GXV_KERN_CLS_R, valid ); 00432 00433 if ( GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_L] ) + 00434 GXV_KERN_FMT2_DATA( offset_min[GXV_KERN_CLS_R] ) 00435 < GXV_KERN_FMT2_DATA( array ) ) 00436 FT_INVALID_OFFSET; 00437 00438 gxv_odtect_add_range( table + GXV_KERN_FMT2_DATA( array ), 00439 GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_L] ) 00440 + GXV_KERN_FMT2_DATA( offset_max[GXV_KERN_CLS_R] ) 00441 - GXV_KERN_FMT2_DATA( array ), 00442 "array", odtect ); 00443 00444 gxv_odtect_validate( odtect, valid ); 00445 00446 GXV_EXIT; 00447 } 00448 00449 00450 /* ============================= format 3 ============================== */ 00451 00452 static void 00453 gxv_kern_subtable_fmt3_validate( FT_Bytes table, 00454 FT_Bytes limit, 00455 GXV_Validator valid ) 00456 { 00457 FT_Bytes p = table + GXV_KERN_SUBTABLE_HEADER_SIZE; 00458 FT_UShort glyphCount; 00459 FT_Byte kernValueCount; 00460 FT_Byte leftClassCount; 00461 FT_Byte rightClassCount; 00462 FT_Byte flags; 00463 00464 00465 GXV_NAME_ENTER( "kern subtable format 3" ); 00466 00467 GXV_LIMIT_CHECK( 2 + 1 + 1 + 1 + 1 ); 00468 glyphCount = FT_NEXT_USHORT( p ); 00469 kernValueCount = FT_NEXT_BYTE( p ); 00470 leftClassCount = FT_NEXT_BYTE( p ); 00471 rightClassCount = FT_NEXT_BYTE( p ); 00472 flags = FT_NEXT_BYTE( p ); 00473 00474 if ( valid->face->num_glyphs != glyphCount ) 00475 { 00476 GXV_TRACE(( "maxGID=%d, but glyphCount=%d\n", 00477 valid->face->num_glyphs, glyphCount )); 00478 if ( valid->root->level >= FT_VALIDATE_PARANOID ) 00479 FT_INVALID_GLYPH_ID; 00480 } 00481 00482 /* 00483 * just skip kernValue[kernValueCount] 00484 */ 00485 GXV_LIMIT_CHECK( 2 * kernValueCount ); 00486 p += 2 * kernValueCount; 00487 00488 /* 00489 * check leftClass[gid] < leftClassCount 00490 */ 00491 { 00492 FT_Byte min, max; 00493 00494 00495 GXV_LIMIT_CHECK( glyphCount ); 00496 gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid ); 00497 p += valid->subtable_length; 00498 00499 if ( leftClassCount < max ) 00500 FT_INVALID_DATA; 00501 } 00502 00503 /* 00504 * check rightClass[gid] < rightClassCount 00505 */ 00506 { 00507 FT_Byte min, max; 00508 00509 00510 GXV_LIMIT_CHECK( glyphCount ); 00511 gxv_array_getlimits_byte( p, p + glyphCount, &min, &max, valid ); 00512 p += valid->subtable_length; 00513 00514 if ( rightClassCount < max ) 00515 FT_INVALID_DATA; 00516 } 00517 00518 /* 00519 * check kernIndex[i, j] < kernValueCount 00520 */ 00521 { 00522 FT_UShort i, j; 00523 00524 00525 for ( i = 0; i < leftClassCount; i++ ) 00526 { 00527 for ( j = 0; j < rightClassCount; j++ ) 00528 { 00529 GXV_LIMIT_CHECK( 1 ); 00530 if ( kernValueCount < FT_NEXT_BYTE( p ) ) 00531 FT_INVALID_OFFSET; 00532 } 00533 } 00534 } 00535 00536 valid->subtable_length = p - table; 00537 00538 GXV_EXIT; 00539 } 00540 00541 00542 static FT_Bool 00543 gxv_kern_coverage_new_apple_validate( FT_UShort coverage, 00544 FT_UShort* format, 00545 GXV_Validator valid ) 00546 { 00547 /* new Apple-dialect */ 00548 FT_Bool kernVertical; 00549 FT_Bool kernCrossStream; 00550 FT_Bool kernVariation; 00551 00552 FT_UNUSED( valid ); 00553 00554 00555 /* reserved bits = 0 */ 00556 if ( coverage & 0x1FFC ) 00557 return 0; 00558 00559 kernVertical = FT_BOOL( ( coverage >> 15 ) & 1 ); 00560 kernCrossStream = FT_BOOL( ( coverage >> 14 ) & 1 ); 00561 kernVariation = FT_BOOL( ( coverage >> 13 ) & 1 ); 00562 00563 *format = (FT_UShort)( coverage & 0x0003 ); 00564 00565 GXV_TRACE(( "new Apple-dialect: " 00566 "horizontal=%d, cross-stream=%d, variation=%d, format=%d\n", 00567 !kernVertical, kernCrossStream, kernVariation, *format )); 00568 00569 GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" )); 00570 00571 return 1; 00572 } 00573 00574 00575 static FT_Bool 00576 gxv_kern_coverage_classic_apple_validate( FT_UShort coverage, 00577 FT_UShort* format, 00578 GXV_Validator valid ) 00579 { 00580 /* classic Apple-dialect */ 00581 FT_Bool horizontal; 00582 FT_Bool cross_stream; 00583 00584 00585 /* check expected flags, but don't check if MS-dialect is impossible */ 00586 if ( !( coverage & 0xFD00 ) && KERN_ALLOWS_MS( valid ) ) 00587 return 0; 00588 00589 /* reserved bits = 0 */ 00590 if ( coverage & 0x02FC ) 00591 return 0; 00592 00593 horizontal = FT_BOOL( ( coverage >> 15 ) & 1 ); 00594 cross_stream = FT_BOOL( ( coverage >> 13 ) & 1 ); 00595 00596 *format = (FT_UShort)( coverage & 0x0003 ); 00597 00598 GXV_TRACE(( "classic Apple-dialect: " 00599 "horizontal=%d, cross-stream=%d, format=%d\n", 00600 horizontal, cross_stream, *format )); 00601 00602 /* format 1 requires GX State Machine, too new for classic */ 00603 if ( *format == 1 ) 00604 return 0; 00605 00606 GXV_TRACE(( "kerning values in Apple format subtable are ignored\n" )); 00607 00608 return 1; 00609 } 00610 00611 00612 static FT_Bool 00613 gxv_kern_coverage_classic_microsoft_validate( FT_UShort coverage, 00614 FT_UShort* format, 00615 GXV_Validator valid ) 00616 { 00617 /* classic Microsoft-dialect */ 00618 FT_Bool horizontal; 00619 FT_Bool minimum; 00620 FT_Bool cross_stream; 00621 FT_Bool override; 00622 00623 FT_UNUSED( valid ); 00624 00625 00626 /* reserved bits = 0 */ 00627 if ( coverage & 0xFDF0 ) 00628 return 0; 00629 00630 horizontal = FT_BOOL( coverage & 1 ); 00631 minimum = FT_BOOL( ( coverage >> 1 ) & 1 ); 00632 cross_stream = FT_BOOL( ( coverage >> 2 ) & 1 ); 00633 override = FT_BOOL( ( coverage >> 3 ) & 1 ); 00634 00635 *format = (FT_UShort)( ( coverage >> 8 ) & 0x0003 ); 00636 00637 GXV_TRACE(( "classic Microsoft-dialect: " 00638 "horizontal=%d, minimum=%d, cross-stream=%d, " 00639 "override=%d, format=%d\n", 00640 horizontal, minimum, cross_stream, override, *format )); 00641 00642 if ( *format == 2 ) 00643 GXV_TRACE(( 00644 "kerning values in Microsoft format 2 subtable are ignored\n" )); 00645 00646 return 1; 00647 } 00648 00649 00650 /*************************************************************************/ 00651 /*************************************************************************/ 00652 /***** *****/ 00653 /***** MAIN *****/ 00654 /***** *****/ 00655 /*************************************************************************/ 00656 /*************************************************************************/ 00657 00658 static GXV_kern_Dialect 00659 gxv_kern_coverage_validate( FT_UShort coverage, 00660 FT_UShort* format, 00661 GXV_Validator valid ) 00662 { 00663 GXV_kern_Dialect result = KERN_DIALECT_UNKNOWN; 00664 00665 00666 GXV_NAME_ENTER( "validating coverage" ); 00667 00668 GXV_TRACE(( "interprete coverage 0x%04x by Apple style\n", coverage )); 00669 00670 if ( KERN_IS_NEW( valid ) ) 00671 { 00672 if ( gxv_kern_coverage_new_apple_validate( coverage, 00673 format, 00674 valid ) ) 00675 { 00676 result = KERN_DIALECT_APPLE; 00677 goto Exit; 00678 } 00679 } 00680 00681 if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_APPLE( valid ) ) 00682 { 00683 if ( gxv_kern_coverage_classic_apple_validate( coverage, 00684 format, 00685 valid ) ) 00686 { 00687 result = KERN_DIALECT_APPLE; 00688 goto Exit; 00689 } 00690 } 00691 00692 if ( KERN_IS_CLASSIC( valid ) && KERN_ALLOWS_MS( valid ) ) 00693 { 00694 if ( gxv_kern_coverage_classic_microsoft_validate( coverage, 00695 format, 00696 valid ) ) 00697 { 00698 result = KERN_DIALECT_MS; 00699 goto Exit; 00700 } 00701 } 00702 00703 GXV_TRACE(( "cannot interprete coverage, broken kern subtable\n" )); 00704 00705 Exit: 00706 GXV_EXIT; 00707 return result; 00708 } 00709 00710 00711 static void 00712 gxv_kern_subtable_validate( FT_Bytes table, 00713 FT_Bytes limit, 00714 GXV_Validator valid ) 00715 { 00716 FT_Bytes p = table; 00717 FT_UShort version = 0; /* MS only: subtable version, unused */ 00718 FT_ULong length; /* MS: 16bit, Apple: 32bit*/ 00719 FT_UShort coverage; 00720 FT_UShort tupleIndex = 0; /* Apple only */ 00721 FT_UShort u16[2]; 00722 FT_UShort format = 255; /* subtable format */ 00723 00724 00725 GXV_NAME_ENTER( "kern subtable" ); 00726 00727 GXV_LIMIT_CHECK( 2 + 2 + 2 ); 00728 u16[0] = FT_NEXT_USHORT( p ); /* Apple: length_hi MS: version */ 00729 u16[1] = FT_NEXT_USHORT( p ); /* Apple: length_lo MS: length */ 00730 coverage = FT_NEXT_USHORT( p ); 00731 00732 switch ( gxv_kern_coverage_validate( coverage, &format, valid ) ) 00733 { 00734 case KERN_DIALECT_MS: 00735 version = u16[0]; 00736 length = u16[1]; 00737 tupleIndex = 0; 00738 GXV_TRACE(( "Subtable version = %d\n", version )); 00739 GXV_TRACE(( "Subtable length = %d\n", length )); 00740 break; 00741 00742 case KERN_DIALECT_APPLE: 00743 version = 0; 00744 length = ( u16[0] << 16 ) + u16[1]; 00745 tupleIndex = 0; 00746 GXV_TRACE(( "Subtable length = %d\n", length )); 00747 00748 if ( KERN_IS_NEW( valid ) ) 00749 { 00750 GXV_LIMIT_CHECK( 2 ); 00751 tupleIndex = FT_NEXT_USHORT( p ); 00752 GXV_TRACE(( "Subtable tupleIndex = %d\n", tupleIndex )); 00753 } 00754 break; 00755 00756 default: 00757 length = u16[1]; 00758 GXV_TRACE(( "cannot detect subtable dialect, " 00759 "just skip %d byte\n", length )); 00760 goto Exit; 00761 } 00762 00763 /* formats 1, 2, 3 require the position of the start of this subtable */ 00764 if ( format == 0 ) 00765 gxv_kern_subtable_fmt0_validate( table, table + length, valid ); 00766 else if ( format == 1 ) 00767 gxv_kern_subtable_fmt1_validate( table, table + length, valid ); 00768 else if ( format == 2 ) 00769 gxv_kern_subtable_fmt2_validate( table, table + length, valid ); 00770 else if ( format == 3 ) 00771 gxv_kern_subtable_fmt3_validate( table, table + length, valid ); 00772 else 00773 FT_INVALID_DATA; 00774 00775 Exit: 00776 valid->subtable_length = length; 00777 GXV_EXIT; 00778 } 00779 00780 00781 /*************************************************************************/ 00782 /*************************************************************************/ 00783 /***** *****/ 00784 /***** kern TABLE *****/ 00785 /***** *****/ 00786 /*************************************************************************/ 00787 /*************************************************************************/ 00788 00789 static void 00790 gxv_kern_validate_generic( FT_Bytes table, 00791 FT_Face face, 00792 FT_Bool classic_only, 00793 GXV_kern_Dialect dialect_request, 00794 FT_Validator ftvalid ) 00795 { 00796 GXV_ValidatorRec validrec; 00797 GXV_Validator valid = &validrec; 00798 00799 GXV_kern_DataRec kernrec; 00800 GXV_kern_Data kern = &kernrec; 00801 00802 FT_Bytes p = table; 00803 FT_Bytes limit = 0; 00804 00805 FT_ULong nTables = 0; 00806 FT_UInt i; 00807 00808 00809 valid->root = ftvalid; 00810 valid->table_data = kern; 00811 valid->face = face; 00812 00813 FT_TRACE3(( "validating `kern' table\n" )); 00814 GXV_INIT; 00815 KERN_DIALECT( valid ) = dialect_request; 00816 00817 GXV_LIMIT_CHECK( 2 ); 00818 GXV_KERN_DATA( version ) = (GXV_kern_Version)FT_NEXT_USHORT( p ); 00819 GXV_TRACE(( "version 0x%04x (higher 16bit)\n", 00820 GXV_KERN_DATA( version ) )); 00821 00822 if ( 0x0001 < GXV_KERN_DATA( version ) ) 00823 FT_INVALID_FORMAT; 00824 else if ( KERN_IS_CLASSIC( valid ) ) 00825 { 00826 GXV_LIMIT_CHECK( 2 ); 00827 nTables = FT_NEXT_USHORT( p ); 00828 } 00829 else if ( KERN_IS_NEW( valid ) ) 00830 { 00831 if ( classic_only ) 00832 FT_INVALID_FORMAT; 00833 00834 if ( 0x0000 != FT_NEXT_USHORT( p ) ) 00835 FT_INVALID_FORMAT; 00836 00837 GXV_LIMIT_CHECK( 4 ); 00838 nTables = FT_NEXT_ULONG( p ); 00839 } 00840 00841 for ( i = 0; i < nTables; i++ ) 00842 { 00843 GXV_TRACE(( "validating subtable %d/%d\n", i, nTables )); 00844 /* p should be 32bit-aligned? */ 00845 gxv_kern_subtable_validate( p, 0, valid ); 00846 p += valid->subtable_length; 00847 } 00848 00849 FT_TRACE4(( "\n" )); 00850 } 00851 00852 00853 FT_LOCAL_DEF( void ) 00854 gxv_kern_validate( FT_Bytes table, 00855 FT_Face face, 00856 FT_Validator ftvalid ) 00857 { 00858 gxv_kern_validate_generic( table, face, 0, KERN_DIALECT_ANY, ftvalid ); 00859 } 00860 00861 00862 FT_LOCAL_DEF( void ) 00863 gxv_kern_validate_classic( FT_Bytes table, 00864 FT_Face face, 00865 FT_Int dialect_flags, 00866 FT_Validator ftvalid ) 00867 { 00868 GXV_kern_Dialect dialect_request; 00869 00870 00871 dialect_request = (GXV_kern_Dialect)dialect_flags; 00872 gxv_kern_validate_generic( table, face, 1, dialect_request, ftvalid ); 00873 } 00874 00875 00876 /* END */ Generated on Sat May 26 2012 04:32:44 for ReactOS by
1.7.6.1
|