Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenttcmap.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ttcmap.c */ 00004 /* */ 00005 /* TrueType character mapping table (cmap) support (body). */ 00006 /* */ 00007 /* Copyright 2002, 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010 by */ 00008 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ 00009 /* */ 00010 /* This file is part of the FreeType project, and may only be used, */ 00011 /* modified, and distributed under the terms of the FreeType project */ 00012 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ 00013 /* this file you indicate that you have read the license and */ 00014 /* understand and accept it fully. */ 00015 /* */ 00016 /***************************************************************************/ 00017 00018 00019 #include <ft2build.h> 00020 #include FT_INTERNAL_DEBUG_H 00021 00022 #include "sferrors.h" /* must come before FT_INTERNAL_VALIDATE_H */ 00023 00024 #include FT_INTERNAL_VALIDATE_H 00025 #include FT_INTERNAL_STREAM_H 00026 #include "ttload.h" 00027 #include "ttcmap.h" 00028 #include "sfntpic.h" 00029 00030 00031 /*************************************************************************/ 00032 /* */ 00033 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00034 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00035 /* messages during execution. */ 00036 /* */ 00037 #undef FT_COMPONENT 00038 #define FT_COMPONENT trace_ttcmap 00039 00040 00041 #define TT_PEEK_SHORT FT_PEEK_SHORT 00042 #define TT_PEEK_USHORT FT_PEEK_USHORT 00043 #define TT_PEEK_UINT24 FT_PEEK_UOFF3 00044 #define TT_PEEK_LONG FT_PEEK_LONG 00045 #define TT_PEEK_ULONG FT_PEEK_ULONG 00046 00047 #define TT_NEXT_SHORT FT_NEXT_SHORT 00048 #define TT_NEXT_USHORT FT_NEXT_USHORT 00049 #define TT_NEXT_UINT24 FT_NEXT_UOFF3 00050 #define TT_NEXT_LONG FT_NEXT_LONG 00051 #define TT_NEXT_ULONG FT_NEXT_ULONG 00052 00053 00054 FT_CALLBACK_DEF( FT_Error ) 00055 tt_cmap_init( TT_CMap cmap, 00056 FT_Byte* table ) 00057 { 00058 cmap->data = table; 00059 return SFNT_Err_Ok; 00060 } 00061 00062 00063 /*************************************************************************/ 00064 /*************************************************************************/ 00065 /***** *****/ 00066 /***** FORMAT 0 *****/ 00067 /***** *****/ 00068 /*************************************************************************/ 00069 /*************************************************************************/ 00070 00071 /*************************************************************************/ 00072 /* */ 00073 /* TABLE OVERVIEW */ 00074 /* -------------- */ 00075 /* */ 00076 /* NAME OFFSET TYPE DESCRIPTION */ 00077 /* */ 00078 /* format 0 USHORT must be 0 */ 00079 /* length 2 USHORT table length in bytes */ 00080 /* language 4 USHORT Mac language code */ 00081 /* glyph_ids 6 BYTE[256] array of glyph indices */ 00082 /* 262 */ 00083 /* */ 00084 00085 #ifdef TT_CONFIG_CMAP_FORMAT_0 00086 00087 FT_CALLBACK_DEF( FT_Error ) 00088 tt_cmap0_validate( FT_Byte* table, 00089 FT_Validator valid ) 00090 { 00091 FT_Byte* p = table + 2; 00092 FT_UInt length = TT_NEXT_USHORT( p ); 00093 00094 00095 if ( table + length > valid->limit || length < 262 ) 00096 FT_INVALID_TOO_SHORT; 00097 00098 /* check glyph indices whenever necessary */ 00099 if ( valid->level >= FT_VALIDATE_TIGHT ) 00100 { 00101 FT_UInt n, idx; 00102 00103 00104 p = table + 6; 00105 for ( n = 0; n < 256; n++ ) 00106 { 00107 idx = *p++; 00108 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 00109 FT_INVALID_GLYPH_ID; 00110 } 00111 } 00112 00113 return SFNT_Err_Ok; 00114 } 00115 00116 00117 FT_CALLBACK_DEF( FT_UInt ) 00118 tt_cmap0_char_index( TT_CMap cmap, 00119 FT_UInt32 char_code ) 00120 { 00121 FT_Byte* table = cmap->data; 00122 00123 00124 return char_code < 256 ? table[6 + char_code] : 0; 00125 } 00126 00127 00128 FT_CALLBACK_DEF( FT_UInt32 ) 00129 tt_cmap0_char_next( TT_CMap cmap, 00130 FT_UInt32 *pchar_code ) 00131 { 00132 FT_Byte* table = cmap->data; 00133 FT_UInt32 charcode = *pchar_code; 00134 FT_UInt32 result = 0; 00135 FT_UInt gindex = 0; 00136 00137 00138 table += 6; /* go to glyph IDs */ 00139 while ( ++charcode < 256 ) 00140 { 00141 gindex = table[charcode]; 00142 if ( gindex != 0 ) 00143 { 00144 result = charcode; 00145 break; 00146 } 00147 } 00148 00149 *pchar_code = result; 00150 return gindex; 00151 } 00152 00153 00154 FT_CALLBACK_DEF( FT_Error ) 00155 tt_cmap0_get_info( TT_CMap cmap, 00156 TT_CMapInfo *cmap_info ) 00157 { 00158 FT_Byte* p = cmap->data + 4; 00159 00160 00161 cmap_info->format = 0; 00162 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 00163 00164 return SFNT_Err_Ok; 00165 } 00166 00167 00168 FT_DEFINE_TT_CMAP(tt_cmap0_class_rec, 00169 sizeof ( TT_CMapRec ), 00170 00171 (FT_CMap_InitFunc) tt_cmap_init, 00172 (FT_CMap_DoneFunc) NULL, 00173 (FT_CMap_CharIndexFunc)tt_cmap0_char_index, 00174 (FT_CMap_CharNextFunc) tt_cmap0_char_next, 00175 00176 NULL, NULL, NULL, NULL, NULL 00177 , 00178 0, 00179 (TT_CMap_ValidateFunc) tt_cmap0_validate, 00180 (TT_CMap_Info_GetFunc) tt_cmap0_get_info 00181 ) 00182 00183 #endif /* TT_CONFIG_CMAP_FORMAT_0 */ 00184 00185 00186 /*************************************************************************/ 00187 /*************************************************************************/ 00188 /***** *****/ 00189 /***** FORMAT 2 *****/ 00190 /***** *****/ 00191 /***** This is used for certain CJK encodings that encode text in a *****/ 00192 /***** mixed 8/16 bits encoding along the following lines: *****/ 00193 /***** *****/ 00194 /***** * Certain byte values correspond to an 8-bit character code *****/ 00195 /***** (typically in the range 0..127 for ASCII compatibility). *****/ 00196 /***** *****/ 00197 /***** * Certain byte values signal the first byte of a 2-byte *****/ 00198 /***** character code (but these values are also valid as the *****/ 00199 /***** second byte of a 2-byte character). *****/ 00200 /***** *****/ 00201 /***** The following charmap lookup and iteration functions all *****/ 00202 /***** assume that the value "charcode" correspond to following: *****/ 00203 /***** *****/ 00204 /***** - For one byte characters, "charcode" is simply the *****/ 00205 /***** character code. *****/ 00206 /***** *****/ 00207 /***** - For two byte characters, "charcode" is the 2-byte *****/ 00208 /***** character code in big endian format. More exactly: *****/ 00209 /***** *****/ 00210 /***** (charcode >> 8) is the first byte value *****/ 00211 /***** (charcode & 0xFF) is the second byte value *****/ 00212 /***** *****/ 00213 /***** Note that not all values of "charcode" are valid according *****/ 00214 /***** to these rules, and the function moderately check the *****/ 00215 /***** arguments. *****/ 00216 /***** *****/ 00217 /*************************************************************************/ 00218 /*************************************************************************/ 00219 00220 /*************************************************************************/ 00221 /* */ 00222 /* TABLE OVERVIEW */ 00223 /* -------------- */ 00224 /* */ 00225 /* NAME OFFSET TYPE DESCRIPTION */ 00226 /* */ 00227 /* format 0 USHORT must be 2 */ 00228 /* length 2 USHORT table length in bytes */ 00229 /* language 4 USHORT Mac language code */ 00230 /* keys 6 USHORT[256] sub-header keys */ 00231 /* subs 518 SUBHEAD[NSUBS] sub-headers array */ 00232 /* glyph_ids 518+NSUB*8 USHORT[] glyph ID array */ 00233 /* */ 00234 /* The `keys' table is used to map charcode high-bytes to sub-headers. */ 00235 /* The value of `NSUBS' is the number of sub-headers defined in the */ 00236 /* table and is computed by finding the maximum of the `keys' table. */ 00237 /* */ 00238 /* Note that for any n, `keys[n]' is a byte offset within the `subs' */ 00239 /* table, i.e., it is the corresponding sub-header index multiplied */ 00240 /* by 8. */ 00241 /* */ 00242 /* Each sub-header has the following format: */ 00243 /* */ 00244 /* NAME OFFSET TYPE DESCRIPTION */ 00245 /* */ 00246 /* first 0 USHORT first valid low-byte */ 00247 /* count 2 USHORT number of valid low-bytes */ 00248 /* delta 4 SHORT see below */ 00249 /* offset 6 USHORT see below */ 00250 /* */ 00251 /* A sub-header defines, for each high-byte, the range of valid */ 00252 /* low-bytes within the charmap. Note that the range defined by `first' */ 00253 /* and `count' must be completely included in the interval [0..255] */ 00254 /* according to the specification. */ 00255 /* */ 00256 /* If a character code is contained within a given sub-header, then */ 00257 /* mapping it to a glyph index is done as follows: */ 00258 /* */ 00259 /* * The value of `offset' is read. This is a _byte_ distance from the */ 00260 /* location of the `offset' field itself into a slice of the */ 00261 /* `glyph_ids' table. Let's call it `slice' (it is a USHORT[] too). */ 00262 /* */ 00263 /* * The value `slice[char.lo - first]' is read. If it is 0, there is */ 00264 /* no glyph for the charcode. Otherwise, the value of `delta' is */ 00265 /* added to it (modulo 65536) to form a new glyph index. */ 00266 /* */ 00267 /* It is up to the validation routine to check that all offsets fall */ 00268 /* within the glyph IDs table (and not within the `subs' table itself or */ 00269 /* outside of the CMap). */ 00270 /* */ 00271 00272 #ifdef TT_CONFIG_CMAP_FORMAT_2 00273 00274 FT_CALLBACK_DEF( FT_Error ) 00275 tt_cmap2_validate( FT_Byte* table, 00276 FT_Validator valid ) 00277 { 00278 FT_Byte* p = table + 2; /* skip format */ 00279 FT_UInt length = TT_PEEK_USHORT( p ); 00280 FT_UInt n, max_subs; 00281 FT_Byte* keys; /* keys table */ 00282 FT_Byte* subs; /* sub-headers */ 00283 FT_Byte* glyph_ids; /* glyph ID array */ 00284 00285 00286 if ( table + length > valid->limit || length < 6 + 512 ) 00287 FT_INVALID_TOO_SHORT; 00288 00289 keys = table + 6; 00290 00291 /* parse keys to compute sub-headers count */ 00292 p = keys; 00293 max_subs = 0; 00294 for ( n = 0; n < 256; n++ ) 00295 { 00296 FT_UInt idx = TT_NEXT_USHORT( p ); 00297 00298 00299 /* value must be multiple of 8 */ 00300 if ( valid->level >= FT_VALIDATE_PARANOID && ( idx & 7 ) != 0 ) 00301 FT_INVALID_DATA; 00302 00303 idx >>= 3; 00304 00305 if ( idx > max_subs ) 00306 max_subs = idx; 00307 } 00308 00309 FT_ASSERT( p == table + 518 ); 00310 00311 subs = p; 00312 glyph_ids = subs + (max_subs + 1) * 8; 00313 if ( glyph_ids > valid->limit ) 00314 FT_INVALID_TOO_SHORT; 00315 00316 /* parse sub-headers */ 00317 for ( n = 0; n <= max_subs; n++ ) 00318 { 00319 FT_UInt first_code, code_count, offset; 00320 FT_Int delta; 00321 FT_Byte* ids; 00322 00323 00324 first_code = TT_NEXT_USHORT( p ); 00325 code_count = TT_NEXT_USHORT( p ); 00326 delta = TT_NEXT_SHORT( p ); 00327 offset = TT_NEXT_USHORT( p ); 00328 00329 /* many Dynalab fonts have empty sub-headers */ 00330 if ( code_count == 0 ) 00331 continue; 00332 00333 /* check range within 0..255 */ 00334 if ( valid->level >= FT_VALIDATE_PARANOID ) 00335 { 00336 if ( first_code >= 256 || first_code + code_count > 256 ) 00337 FT_INVALID_DATA; 00338 } 00339 00340 /* check offset */ 00341 if ( offset != 0 ) 00342 { 00343 ids = p - 2 + offset; 00344 if ( ids < glyph_ids || ids + code_count*2 > table + length ) 00345 FT_INVALID_OFFSET; 00346 00347 /* check glyph IDs */ 00348 if ( valid->level >= FT_VALIDATE_TIGHT ) 00349 { 00350 FT_Byte* limit = p + code_count * 2; 00351 FT_UInt idx; 00352 00353 00354 for ( ; p < limit; ) 00355 { 00356 idx = TT_NEXT_USHORT( p ); 00357 if ( idx != 0 ) 00358 { 00359 idx = ( idx + delta ) & 0xFFFFU; 00360 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 00361 FT_INVALID_GLYPH_ID; 00362 } 00363 } 00364 } 00365 } 00366 } 00367 00368 return SFNT_Err_Ok; 00369 } 00370 00371 00372 /* return sub header corresponding to a given character code */ 00373 /* NULL on invalid charcode */ 00374 static FT_Byte* 00375 tt_cmap2_get_subheader( FT_Byte* table, 00376 FT_UInt32 char_code ) 00377 { 00378 FT_Byte* result = NULL; 00379 00380 00381 if ( char_code < 0x10000UL ) 00382 { 00383 FT_UInt char_lo = (FT_UInt)( char_code & 0xFF ); 00384 FT_UInt char_hi = (FT_UInt)( char_code >> 8 ); 00385 FT_Byte* p = table + 6; /* keys table */ 00386 FT_Byte* subs = table + 518; /* subheaders table */ 00387 FT_Byte* sub; 00388 00389 00390 if ( char_hi == 0 ) 00391 { 00392 /* an 8-bit character code -- we use subHeader 0 in this case */ 00393 /* to test whether the character code is in the charmap */ 00394 /* */ 00395 sub = subs; /* jump to first sub-header */ 00396 00397 /* check that the sub-header for this byte is 0, which */ 00398 /* indicates that it is really a valid one-byte value */ 00399 /* Otherwise, return 0 */ 00400 /* */ 00401 p += char_lo * 2; 00402 if ( TT_PEEK_USHORT( p ) != 0 ) 00403 goto Exit; 00404 } 00405 else 00406 { 00407 /* a 16-bit character code */ 00408 00409 /* jump to key entry */ 00410 p += char_hi * 2; 00411 /* jump to sub-header */ 00412 sub = subs + ( FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 8 ) ); 00413 00414 /* check that the high byte isn't a valid one-byte value */ 00415 if ( sub == subs ) 00416 goto Exit; 00417 } 00418 result = sub; 00419 } 00420 Exit: 00421 return result; 00422 } 00423 00424 00425 FT_CALLBACK_DEF( FT_UInt ) 00426 tt_cmap2_char_index( TT_CMap cmap, 00427 FT_UInt32 char_code ) 00428 { 00429 FT_Byte* table = cmap->data; 00430 FT_UInt result = 0; 00431 FT_Byte* subheader; 00432 00433 00434 subheader = tt_cmap2_get_subheader( table, char_code ); 00435 if ( subheader ) 00436 { 00437 FT_Byte* p = subheader; 00438 FT_UInt idx = (FT_UInt)(char_code & 0xFF); 00439 FT_UInt start, count; 00440 FT_Int delta; 00441 FT_UInt offset; 00442 00443 00444 start = TT_NEXT_USHORT( p ); 00445 count = TT_NEXT_USHORT( p ); 00446 delta = TT_NEXT_SHORT ( p ); 00447 offset = TT_PEEK_USHORT( p ); 00448 00449 idx -= start; 00450 if ( idx < count && offset != 0 ) 00451 { 00452 p += offset + 2 * idx; 00453 idx = TT_PEEK_USHORT( p ); 00454 00455 if ( idx != 0 ) 00456 result = (FT_UInt)( idx + delta ) & 0xFFFFU; 00457 } 00458 } 00459 return result; 00460 } 00461 00462 00463 FT_CALLBACK_DEF( FT_UInt32 ) 00464 tt_cmap2_char_next( TT_CMap cmap, 00465 FT_UInt32 *pcharcode ) 00466 { 00467 FT_Byte* table = cmap->data; 00468 FT_UInt gindex = 0; 00469 FT_UInt32 result = 0; 00470 FT_UInt32 charcode = *pcharcode + 1; 00471 FT_Byte* subheader; 00472 00473 00474 while ( charcode < 0x10000UL ) 00475 { 00476 subheader = tt_cmap2_get_subheader( table, charcode ); 00477 if ( subheader ) 00478 { 00479 FT_Byte* p = subheader; 00480 FT_UInt start = TT_NEXT_USHORT( p ); 00481 FT_UInt count = TT_NEXT_USHORT( p ); 00482 FT_Int delta = TT_NEXT_SHORT ( p ); 00483 FT_UInt offset = TT_PEEK_USHORT( p ); 00484 FT_UInt char_lo = (FT_UInt)( charcode & 0xFF ); 00485 FT_UInt pos, idx; 00486 00487 00488 if ( offset == 0 ) 00489 goto Next_SubHeader; 00490 00491 if ( char_lo < start ) 00492 { 00493 char_lo = start; 00494 pos = 0; 00495 } 00496 else 00497 pos = (FT_UInt)( char_lo - start ); 00498 00499 p += offset + pos * 2; 00500 charcode = FT_PAD_FLOOR( charcode, 256 ) + char_lo; 00501 00502 for ( ; pos < count; pos++, charcode++ ) 00503 { 00504 idx = TT_NEXT_USHORT( p ); 00505 00506 if ( idx != 0 ) 00507 { 00508 gindex = ( idx + delta ) & 0xFFFFU; 00509 if ( gindex != 0 ) 00510 { 00511 result = charcode; 00512 goto Exit; 00513 } 00514 } 00515 } 00516 } 00517 00518 /* jump to next sub-header, i.e. higher byte value */ 00519 Next_SubHeader: 00520 charcode = FT_PAD_FLOOR( charcode, 256 ) + 256; 00521 } 00522 00523 Exit: 00524 *pcharcode = result; 00525 00526 return gindex; 00527 } 00528 00529 00530 FT_CALLBACK_DEF( FT_Error ) 00531 tt_cmap2_get_info( TT_CMap cmap, 00532 TT_CMapInfo *cmap_info ) 00533 { 00534 FT_Byte* p = cmap->data + 4; 00535 00536 00537 cmap_info->format = 2; 00538 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 00539 00540 return SFNT_Err_Ok; 00541 } 00542 00543 00544 FT_DEFINE_TT_CMAP(tt_cmap2_class_rec, 00545 sizeof ( TT_CMapRec ), 00546 00547 (FT_CMap_InitFunc) tt_cmap_init, 00548 (FT_CMap_DoneFunc) NULL, 00549 (FT_CMap_CharIndexFunc)tt_cmap2_char_index, 00550 (FT_CMap_CharNextFunc) tt_cmap2_char_next, 00551 00552 NULL, NULL, NULL, NULL, NULL 00553 , 00554 2, 00555 (TT_CMap_ValidateFunc) tt_cmap2_validate, 00556 (TT_CMap_Info_GetFunc) tt_cmap2_get_info 00557 ) 00558 00559 #endif /* TT_CONFIG_CMAP_FORMAT_2 */ 00560 00561 00562 /*************************************************************************/ 00563 /*************************************************************************/ 00564 /***** *****/ 00565 /***** FORMAT 4 *****/ 00566 /***** *****/ 00567 /*************************************************************************/ 00568 /*************************************************************************/ 00569 00570 /*************************************************************************/ 00571 /* */ 00572 /* TABLE OVERVIEW */ 00573 /* -------------- */ 00574 /* */ 00575 /* NAME OFFSET TYPE DESCRIPTION */ 00576 /* */ 00577 /* format 0 USHORT must be 4 */ 00578 /* length 2 USHORT table length */ 00579 /* in bytes */ 00580 /* language 4 USHORT Mac language code */ 00581 /* */ 00582 /* segCountX2 6 USHORT 2*NUM_SEGS */ 00583 /* searchRange 8 USHORT 2*(1 << LOG_SEGS) */ 00584 /* entrySelector 10 USHORT LOG_SEGS */ 00585 /* rangeShift 12 USHORT segCountX2 - */ 00586 /* searchRange */ 00587 /* */ 00588 /* endCount 14 USHORT[NUM_SEGS] end charcode for */ 00589 /* each segment; last */ 00590 /* is 0xFFFF */ 00591 /* */ 00592 /* pad 14+NUM_SEGS*2 USHORT padding */ 00593 /* */ 00594 /* startCount 16+NUM_SEGS*2 USHORT[NUM_SEGS] first charcode for */ 00595 /* each segment */ 00596 /* */ 00597 /* idDelta 16+NUM_SEGS*4 SHORT[NUM_SEGS] delta for each */ 00598 /* segment */ 00599 /* idOffset 16+NUM_SEGS*6 SHORT[NUM_SEGS] range offset for */ 00600 /* each segment; can be */ 00601 /* zero */ 00602 /* */ 00603 /* glyphIds 16+NUM_SEGS*8 USHORT[] array of glyph ID */ 00604 /* ranges */ 00605 /* */ 00606 /* Character codes are modelled by a series of ordered (increasing) */ 00607 /* intervals called segments. Each segment has start and end codes, */ 00608 /* provided by the `startCount' and `endCount' arrays. Segments must */ 00609 /* not overlap, and the last segment should always contain the value */ 00610 /* 0xFFFF for `endCount'. */ 00611 /* */ 00612 /* The fields `searchRange', `entrySelector' and `rangeShift' are better */ 00613 /* ignored (they are traces of over-engineering in the TrueType */ 00614 /* specification). */ 00615 /* */ 00616 /* Each segment also has a signed `delta', as well as an optional offset */ 00617 /* within the `glyphIds' table. */ 00618 /* */ 00619 /* If a segment's idOffset is 0, the glyph index corresponding to any */ 00620 /* charcode within the segment is obtained by adding the value of */ 00621 /* `idDelta' directly to the charcode, modulo 65536. */ 00622 /* */ 00623 /* Otherwise, a glyph index is taken from the glyph IDs sub-array for */ 00624 /* the segment, and the value of `idDelta' is added to it. */ 00625 /* */ 00626 /* */ 00627 /* Finally, note that a lot of fonts contain an invalid last segment, */ 00628 /* where `start' and `end' are correctly set to 0xFFFF but both `delta' */ 00629 /* and `offset' are incorrect (e.g., `opens___.ttf' which comes with */ 00630 /* OpenOffice.org). We need special code to deal with them correctly. */ 00631 /* */ 00632 00633 #ifdef TT_CONFIG_CMAP_FORMAT_4 00634 00635 typedef struct TT_CMap4Rec_ 00636 { 00637 TT_CMapRec cmap; 00638 FT_UInt32 cur_charcode; /* current charcode */ 00639 FT_UInt cur_gindex; /* current glyph index */ 00640 00641 FT_UInt num_ranges; 00642 FT_UInt cur_range; 00643 FT_UInt cur_start; 00644 FT_UInt cur_end; 00645 FT_Int cur_delta; 00646 FT_Byte* cur_values; 00647 00648 } TT_CMap4Rec, *TT_CMap4; 00649 00650 00651 FT_CALLBACK_DEF( FT_Error ) 00652 tt_cmap4_init( TT_CMap4 cmap, 00653 FT_Byte* table ) 00654 { 00655 FT_Byte* p; 00656 00657 00658 cmap->cmap.data = table; 00659 00660 p = table + 6; 00661 cmap->num_ranges = FT_PEEK_USHORT( p ) >> 1; 00662 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; 00663 cmap->cur_gindex = 0; 00664 00665 return SFNT_Err_Ok; 00666 } 00667 00668 00669 static FT_Int 00670 tt_cmap4_set_range( TT_CMap4 cmap, 00671 FT_UInt range_index ) 00672 { 00673 FT_Byte* table = cmap->cmap.data; 00674 FT_Byte* p; 00675 FT_UInt num_ranges = cmap->num_ranges; 00676 00677 00678 while ( range_index < num_ranges ) 00679 { 00680 FT_UInt offset; 00681 00682 00683 p = table + 14 + range_index * 2; 00684 cmap->cur_end = FT_PEEK_USHORT( p ); 00685 00686 p += 2 + num_ranges * 2; 00687 cmap->cur_start = FT_PEEK_USHORT( p ); 00688 00689 p += num_ranges * 2; 00690 cmap->cur_delta = FT_PEEK_SHORT( p ); 00691 00692 p += num_ranges * 2; 00693 offset = FT_PEEK_USHORT( p ); 00694 00695 /* some fonts have an incorrect last segment; */ 00696 /* we have to catch it */ 00697 if ( range_index >= num_ranges - 1 && 00698 cmap->cur_start == 0xFFFFU && 00699 cmap->cur_end == 0xFFFFU ) 00700 { 00701 TT_Face face = (TT_Face)cmap->cmap.cmap.charmap.face; 00702 FT_Byte* limit = face->cmap_table + face->cmap_size; 00703 00704 00705 if ( offset && p + offset + 2 > limit ) 00706 { 00707 cmap->cur_delta = 1; 00708 offset = 0; 00709 } 00710 } 00711 00712 if ( offset != 0xFFFFU ) 00713 { 00714 cmap->cur_values = offset ? p + offset : NULL; 00715 cmap->cur_range = range_index; 00716 return 0; 00717 } 00718 00719 /* we skip empty segments */ 00720 range_index++; 00721 } 00722 00723 return -1; 00724 } 00725 00726 00727 /* search the index of the charcode next to cmap->cur_charcode; */ 00728 /* caller should call tt_cmap4_set_range with proper range */ 00729 /* before calling this function */ 00730 /* */ 00731 static void 00732 tt_cmap4_next( TT_CMap4 cmap ) 00733 { 00734 FT_UInt charcode; 00735 00736 00737 if ( cmap->cur_charcode >= 0xFFFFUL ) 00738 goto Fail; 00739 00740 charcode = (FT_UInt)cmap->cur_charcode + 1; 00741 00742 if ( charcode < cmap->cur_start ) 00743 charcode = cmap->cur_start; 00744 00745 for ( ;; ) 00746 { 00747 FT_Byte* values = cmap->cur_values; 00748 FT_UInt end = cmap->cur_end; 00749 FT_Int delta = cmap->cur_delta; 00750 00751 00752 if ( charcode <= end ) 00753 { 00754 if ( values ) 00755 { 00756 FT_Byte* p = values + 2 * ( charcode - cmap->cur_start ); 00757 00758 00759 do 00760 { 00761 FT_UInt gindex = FT_NEXT_USHORT( p ); 00762 00763 00764 if ( gindex != 0 ) 00765 { 00766 gindex = (FT_UInt)( ( gindex + delta ) & 0xFFFFU ); 00767 if ( gindex != 0 ) 00768 { 00769 cmap->cur_charcode = charcode; 00770 cmap->cur_gindex = gindex; 00771 return; 00772 } 00773 } 00774 } while ( ++charcode <= end ); 00775 } 00776 else 00777 { 00778 do 00779 { 00780 FT_UInt gindex = (FT_UInt)( ( charcode + delta ) & 0xFFFFU ); 00781 00782 00783 if ( gindex != 0 ) 00784 { 00785 cmap->cur_charcode = charcode; 00786 cmap->cur_gindex = gindex; 00787 return; 00788 } 00789 } while ( ++charcode <= end ); 00790 } 00791 } 00792 00793 /* we need to find another range */ 00794 if ( tt_cmap4_set_range( cmap, cmap->cur_range + 1 ) < 0 ) 00795 break; 00796 00797 if ( charcode < cmap->cur_start ) 00798 charcode = cmap->cur_start; 00799 } 00800 00801 Fail: 00802 cmap->cur_charcode = (FT_UInt32)0xFFFFFFFFUL; 00803 cmap->cur_gindex = 0; 00804 } 00805 00806 00807 FT_CALLBACK_DEF( FT_Error ) 00808 tt_cmap4_validate( FT_Byte* table, 00809 FT_Validator valid ) 00810 { 00811 FT_Byte* p = table + 2; /* skip format */ 00812 FT_UInt length = TT_NEXT_USHORT( p ); 00813 FT_Byte *ends, *starts, *offsets, *deltas, *glyph_ids; 00814 FT_UInt num_segs; 00815 FT_Error error = SFNT_Err_Ok; 00816 00817 00818 if ( length < 16 ) 00819 FT_INVALID_TOO_SHORT; 00820 00821 /* in certain fonts, the `length' field is invalid and goes */ 00822 /* out of bound. We try to correct this here... */ 00823 if ( table + length > valid->limit ) 00824 { 00825 if ( valid->level >= FT_VALIDATE_TIGHT ) 00826 FT_INVALID_TOO_SHORT; 00827 00828 length = (FT_UInt)( valid->limit - table ); 00829 } 00830 00831 p = table + 6; 00832 num_segs = TT_NEXT_USHORT( p ); /* read segCountX2 */ 00833 00834 if ( valid->level >= FT_VALIDATE_PARANOID ) 00835 { 00836 /* check that we have an even value here */ 00837 if ( num_segs & 1 ) 00838 FT_INVALID_DATA; 00839 } 00840 00841 num_segs /= 2; 00842 00843 if ( length < 16 + num_segs * 2 * 4 ) 00844 FT_INVALID_TOO_SHORT; 00845 00846 /* check the search parameters - even though we never use them */ 00847 /* */ 00848 if ( valid->level >= FT_VALIDATE_PARANOID ) 00849 { 00850 /* check the values of `searchRange', `entrySelector', `rangeShift' */ 00851 FT_UInt search_range = TT_NEXT_USHORT( p ); 00852 FT_UInt entry_selector = TT_NEXT_USHORT( p ); 00853 FT_UInt range_shift = TT_NEXT_USHORT( p ); 00854 00855 00856 if ( ( search_range | range_shift ) & 1 ) /* must be even values */ 00857 FT_INVALID_DATA; 00858 00859 search_range /= 2; 00860 range_shift /= 2; 00861 00862 /* `search range' is the greatest power of 2 that is <= num_segs */ 00863 00864 if ( search_range > num_segs || 00865 search_range * 2 < num_segs || 00866 search_range + range_shift != num_segs || 00867 search_range != ( 1U << entry_selector ) ) 00868 FT_INVALID_DATA; 00869 } 00870 00871 ends = table + 14; 00872 starts = table + 16 + num_segs * 2; 00873 deltas = starts + num_segs * 2; 00874 offsets = deltas + num_segs * 2; 00875 glyph_ids = offsets + num_segs * 2; 00876 00877 /* check last segment; its end count value must be 0xFFFF */ 00878 if ( valid->level >= FT_VALIDATE_PARANOID ) 00879 { 00880 p = ends + ( num_segs - 1 ) * 2; 00881 if ( TT_PEEK_USHORT( p ) != 0xFFFFU ) 00882 FT_INVALID_DATA; 00883 } 00884 00885 { 00886 FT_UInt start, end, offset, n; 00887 FT_UInt last_start = 0, last_end = 0; 00888 FT_Int delta; 00889 FT_Byte* p_start = starts; 00890 FT_Byte* p_end = ends; 00891 FT_Byte* p_delta = deltas; 00892 FT_Byte* p_offset = offsets; 00893 00894 00895 for ( n = 0; n < num_segs; n++ ) 00896 { 00897 p = p_offset; 00898 start = TT_NEXT_USHORT( p_start ); 00899 end = TT_NEXT_USHORT( p_end ); 00900 delta = TT_NEXT_SHORT( p_delta ); 00901 offset = TT_NEXT_USHORT( p_offset ); 00902 00903 if ( start > end ) 00904 FT_INVALID_DATA; 00905 00906 /* this test should be performed at default validation level; */ 00907 /* unfortunately, some popular Asian fonts have overlapping */ 00908 /* ranges in their charmaps */ 00909 /* */ 00910 if ( start <= last_end && n > 0 ) 00911 { 00912 if ( valid->level >= FT_VALIDATE_TIGHT ) 00913 FT_INVALID_DATA; 00914 else 00915 { 00916 /* allow overlapping segments, provided their start points */ 00917 /* and end points, respectively, are in ascending order */ 00918 /* */ 00919 if ( last_start > start || last_end > end ) 00920 error |= TT_CMAP_FLAG_UNSORTED; 00921 else 00922 error |= TT_CMAP_FLAG_OVERLAPPING; 00923 } 00924 } 00925 00926 if ( offset && offset != 0xFFFFU ) 00927 { 00928 p += offset; /* start of glyph ID array */ 00929 00930 /* check that we point within the glyph IDs table only */ 00931 if ( valid->level >= FT_VALIDATE_TIGHT ) 00932 { 00933 if ( p < glyph_ids || 00934 p + ( end - start + 1 ) * 2 > table + length ) 00935 FT_INVALID_DATA; 00936 } 00937 /* Some fonts handle the last segment incorrectly. In */ 00938 /* theory, 0xFFFF might point to an ordinary glyph -- */ 00939 /* a cmap 4 is versatile and could be used for any */ 00940 /* encoding, not only Unicode. However, reality shows */ 00941 /* that far too many fonts are sloppy and incorrectly */ 00942 /* set all fields but `start' and `end' for the last */ 00943 /* segment if it contains only a single character. */ 00944 /* */ 00945 /* We thus omit the test here, delaying it to the */ 00946 /* routines which actually access the cmap. */ 00947 else if ( n != num_segs - 1 || 00948 !( start == 0xFFFFU && end == 0xFFFFU ) ) 00949 { 00950 if ( p < glyph_ids || 00951 p + ( end - start + 1 ) * 2 > valid->limit ) 00952 FT_INVALID_DATA; 00953 } 00954 00955 /* check glyph indices within the segment range */ 00956 if ( valid->level >= FT_VALIDATE_TIGHT ) 00957 { 00958 FT_UInt i, idx; 00959 00960 00961 for ( i = start; i < end; i++ ) 00962 { 00963 idx = FT_NEXT_USHORT( p ); 00964 if ( idx != 0 ) 00965 { 00966 idx = (FT_UInt)( idx + delta ) & 0xFFFFU; 00967 00968 if ( idx >= TT_VALID_GLYPH_COUNT( valid ) ) 00969 FT_INVALID_GLYPH_ID; 00970 } 00971 } 00972 } 00973 } 00974 else if ( offset == 0xFFFFU ) 00975 { 00976 /* some fonts (erroneously?) use a range offset of 0xFFFF */ 00977 /* to mean missing glyph in cmap table */ 00978 /* */ 00979 if ( valid->level >= FT_VALIDATE_PARANOID || 00980 n != num_segs - 1 || 00981 !( start == 0xFFFFU && end == 0xFFFFU ) ) 00982 FT_INVALID_DATA; 00983 } 00984 00985 last_start = start; 00986 last_end = end; 00987 } 00988 } 00989 00990 return error; 00991 } 00992 00993 00994 static FT_UInt 00995 tt_cmap4_char_map_linear( TT_CMap cmap, 00996 FT_UInt32* pcharcode, 00997 FT_Bool next ) 00998 { 00999 FT_UInt num_segs2, start, end, offset; 01000 FT_Int delta; 01001 FT_UInt i, num_segs; 01002 FT_UInt32 charcode = *pcharcode; 01003 FT_UInt gindex = 0; 01004 FT_Byte* p; 01005 01006 01007 p = cmap->data + 6; 01008 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); 01009 01010 num_segs = num_segs2 >> 1; 01011 01012 if ( !num_segs ) 01013 return 0; 01014 01015 if ( next ) 01016 charcode++; 01017 01018 /* linear search */ 01019 for ( ; charcode <= 0xFFFFU; charcode++ ) 01020 { 01021 FT_Byte* q; 01022 01023 01024 p = cmap->data + 14; /* ends table */ 01025 q = cmap->data + 16 + num_segs2; /* starts table */ 01026 01027 for ( i = 0; i < num_segs; i++ ) 01028 { 01029 end = TT_NEXT_USHORT( p ); 01030 start = TT_NEXT_USHORT( q ); 01031 01032 if ( charcode >= start && charcode <= end ) 01033 { 01034 p = q - 2 + num_segs2; 01035 delta = TT_PEEK_SHORT( p ); 01036 p += num_segs2; 01037 offset = TT_PEEK_USHORT( p ); 01038 01039 /* some fonts have an incorrect last segment; */ 01040 /* we have to catch it */ 01041 if ( i >= num_segs - 1 && 01042 start == 0xFFFFU && end == 0xFFFFU ) 01043 { 01044 TT_Face face = (TT_Face)cmap->cmap.charmap.face; 01045 FT_Byte* limit = face->cmap_table + face->cmap_size; 01046 01047 01048 if ( offset && p + offset + 2 > limit ) 01049 { 01050 delta = 1; 01051 offset = 0; 01052 } 01053 } 01054 01055 if ( offset == 0xFFFFU ) 01056 continue; 01057 01058 if ( offset ) 01059 { 01060 p += offset + ( charcode - start ) * 2; 01061 gindex = TT_PEEK_USHORT( p ); 01062 if ( gindex != 0 ) 01063 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; 01064 } 01065 else 01066 gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; 01067 01068 break; 01069 } 01070 } 01071 01072 if ( !next || gindex ) 01073 break; 01074 } 01075 01076 if ( next && gindex ) 01077 *pcharcode = charcode; 01078 01079 return gindex; 01080 } 01081 01082 01083 static FT_UInt 01084 tt_cmap4_char_map_binary( TT_CMap cmap, 01085 FT_UInt32* pcharcode, 01086 FT_Bool next ) 01087 { 01088 FT_UInt num_segs2, start, end, offset; 01089 FT_Int delta; 01090 FT_UInt max, min, mid, num_segs; 01091 FT_UInt charcode = (FT_UInt)*pcharcode; 01092 FT_UInt gindex = 0; 01093 FT_Byte* p; 01094 01095 01096 p = cmap->data + 6; 01097 num_segs2 = FT_PAD_FLOOR( TT_PEEK_USHORT( p ), 2 ); 01098 01099 if ( !num_segs2 ) 01100 return 0; 01101 01102 num_segs = num_segs2 >> 1; 01103 01104 /* make compiler happy */ 01105 mid = num_segs; 01106 end = 0xFFFFU; 01107 01108 if ( next ) 01109 charcode++; 01110 01111 min = 0; 01112 max = num_segs; 01113 01114 /* binary search */ 01115 while ( min < max ) 01116 { 01117 mid = ( min + max ) >> 1; 01118 p = cmap->data + 14 + mid * 2; 01119 end = TT_PEEK_USHORT( p ); 01120 p += 2 + num_segs2; 01121 start = TT_PEEK_USHORT( p ); 01122 01123 if ( charcode < start ) 01124 max = mid; 01125 else if ( charcode > end ) 01126 min = mid + 1; 01127 else 01128 { 01129 p += num_segs2; 01130 delta = TT_PEEK_SHORT( p ); 01131 p += num_segs2; 01132 offset = TT_PEEK_USHORT( p ); 01133 01134 /* some fonts have an incorrect last segment; */ 01135 /* we have to catch it */ 01136 if ( mid >= num_segs - 1 && 01137 start == 0xFFFFU && end == 0xFFFFU ) 01138 { 01139 TT_Face face = (TT_Face)cmap->cmap.charmap.face; 01140 FT_Byte* limit = face->cmap_table + face->cmap_size; 01141 01142 01143 if ( offset && p + offset + 2 > limit ) 01144 { 01145 delta = 1; 01146 offset = 0; 01147 } 01148 } 01149 01150 /* search the first segment containing `charcode' */ 01151 if ( cmap->flags & TT_CMAP_FLAG_OVERLAPPING ) 01152 { 01153 FT_UInt i; 01154 01155 01156 /* call the current segment `max' */ 01157 max = mid; 01158 01159 if ( offset == 0xFFFFU ) 01160 mid = max + 1; 01161 01162 /* search in segments before the current segment */ 01163 for ( i = max ; i > 0; i-- ) 01164 { 01165 FT_UInt prev_end; 01166 FT_Byte* old_p; 01167 01168 01169 old_p = p; 01170 p = cmap->data + 14 + ( i - 1 ) * 2; 01171 prev_end = TT_PEEK_USHORT( p ); 01172 01173 if ( charcode > prev_end ) 01174 { 01175 p = old_p; 01176 break; 01177 } 01178 01179 end = prev_end; 01180 p += 2 + num_segs2; 01181 start = TT_PEEK_USHORT( p ); 01182 p += num_segs2; 01183 delta = TT_PEEK_SHORT( p ); 01184 p += num_segs2; 01185 offset = TT_PEEK_USHORT( p ); 01186 01187 if ( offset != 0xFFFFU ) 01188 mid = i - 1; 01189 } 01190 01191 /* no luck */ 01192 if ( mid == max + 1 ) 01193 { 01194 if ( i != max ) 01195 { 01196 p = cmap->data + 14 + max * 2; 01197 end = TT_PEEK_USHORT( p ); 01198 p += 2 + num_segs2; 01199 start = TT_PEEK_USHORT( p ); 01200 p += num_segs2; 01201 delta = TT_PEEK_SHORT( p ); 01202 p += num_segs2; 01203 offset = TT_PEEK_USHORT( p ); 01204 } 01205 01206 mid = max; 01207 01208 /* search in segments after the current segment */ 01209 for ( i = max + 1; i < num_segs; i++ ) 01210 { 01211 FT_UInt next_end, next_start; 01212 01213 01214 p = cmap->data + 14 + i * 2; 01215 next_end = TT_PEEK_USHORT( p ); 01216 p += 2 + num_segs2; 01217 next_start = TT_PEEK_USHORT( p ); 01218 01219 if ( charcode < next_start ) 01220 break; 01221 01222 end = next_end; 01223 start = next_start; 01224 p += num_segs2; 01225 delta = TT_PEEK_SHORT( p ); 01226 p += num_segs2; 01227 offset = TT_PEEK_USHORT( p ); 01228 01229 if ( offset != 0xFFFFU ) 01230 mid = i; 01231 } 01232 i--; 01233 01234 /* still no luck */ 01235 if ( mid == max ) 01236 { 01237 mid = i; 01238 01239 break; 01240 } 01241 } 01242 01243 /* end, start, delta, and offset are for the i'th segment */ 01244 if ( mid != i ) 01245 { 01246 p = cmap->data + 14 + mid * 2; 01247 end = TT_PEEK_USHORT( p ); 01248 p += 2 + num_segs2; 01249 start = TT_PEEK_USHORT( p ); 01250 p += num_segs2; 01251 delta = TT_PEEK_SHORT( p ); 01252 p += num_segs2; 01253 offset = TT_PEEK_USHORT( p ); 01254 } 01255 } 01256 else 01257 { 01258 if ( offset == 0xFFFFU ) 01259 break; 01260 } 01261 01262 if ( offset ) 01263 { 01264 p += offset + ( charcode - start ) * 2; 01265 gindex = TT_PEEK_USHORT( p ); 01266 if ( gindex != 0 ) 01267 gindex = (FT_UInt)( gindex + delta ) & 0xFFFFU; 01268 } 01269 else 01270 gindex = (FT_UInt)( charcode + delta ) & 0xFFFFU; 01271 01272 break; 01273 } 01274 } 01275 01276 if ( next ) 01277 { 01278 TT_CMap4 cmap4 = (TT_CMap4)cmap; 01279 01280 01281 /* if `charcode' is not in any segment, then `mid' is */ 01282 /* the segment nearest to `charcode' */ 01283 /* */ 01284 01285 if ( charcode > end ) 01286 { 01287 mid++; 01288 if ( mid == num_segs ) 01289 return 0; 01290 } 01291 01292 if ( tt_cmap4_set_range( cmap4, mid ) ) 01293 { 01294 if ( gindex ) 01295 *pcharcode = charcode; 01296 } 01297 else 01298 { 01299 cmap4->cur_charcode = charcode; 01300 01301 if ( gindex ) 01302 cmap4->cur_gindex = gindex; 01303 else 01304 { 01305 cmap4->cur_charcode = charcode; 01306 tt_cmap4_next( cmap4 ); 01307 gindex = cmap4->cur_gindex; 01308 } 01309 01310 if ( gindex ) 01311 *pcharcode = cmap4->cur_charcode; 01312 } 01313 } 01314 01315 return gindex; 01316 } 01317 01318 01319 FT_CALLBACK_DEF( FT_UInt ) 01320 tt_cmap4_char_index( TT_CMap cmap, 01321 FT_UInt32 char_code ) 01322 { 01323 if ( char_code >= 0x10000UL ) 01324 return 0; 01325 01326 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) 01327 return tt_cmap4_char_map_linear( cmap, &char_code, 0 ); 01328 else 01329 return tt_cmap4_char_map_binary( cmap, &char_code, 0 ); 01330 } 01331 01332 01333 FT_CALLBACK_DEF( FT_UInt32 ) 01334 tt_cmap4_char_next( TT_CMap cmap, 01335 FT_UInt32 *pchar_code ) 01336 { 01337 FT_UInt gindex; 01338 01339 01340 if ( *pchar_code >= 0xFFFFU ) 01341 return 0; 01342 01343 if ( cmap->flags & TT_CMAP_FLAG_UNSORTED ) 01344 gindex = tt_cmap4_char_map_linear( cmap, pchar_code, 1 ); 01345 else 01346 { 01347 TT_CMap4 cmap4 = (TT_CMap4)cmap; 01348 01349 01350 /* no need to search */ 01351 if ( *pchar_code == cmap4->cur_charcode ) 01352 { 01353 tt_cmap4_next( cmap4 ); 01354 gindex = cmap4->cur_gindex; 01355 if ( gindex ) 01356 *pchar_code = cmap4->cur_charcode; 01357 } 01358 else 01359 gindex = tt_cmap4_char_map_binary( cmap, pchar_code, 1 ); 01360 } 01361 01362 return gindex; 01363 } 01364 01365 01366 FT_CALLBACK_DEF( FT_Error ) 01367 tt_cmap4_get_info( TT_CMap cmap, 01368 TT_CMapInfo *cmap_info ) 01369 { 01370 FT_Byte* p = cmap->data + 4; 01371 01372 01373 cmap_info->format = 4; 01374 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 01375 01376 return SFNT_Err_Ok; 01377 } 01378 01379 01380 FT_DEFINE_TT_CMAP(tt_cmap4_class_rec, 01381 sizeof ( TT_CMap4Rec ), 01382 (FT_CMap_InitFunc) tt_cmap4_init, 01383 (FT_CMap_DoneFunc) NULL, 01384 (FT_CMap_CharIndexFunc)tt_cmap4_char_index, 01385 (FT_CMap_CharNextFunc) tt_cmap4_char_next, 01386 01387 NULL, NULL, NULL, NULL, NULL 01388 , 01389 4, 01390 (TT_CMap_ValidateFunc) tt_cmap4_validate, 01391 (TT_CMap_Info_GetFunc) tt_cmap4_get_info 01392 ) 01393 01394 #endif /* TT_CONFIG_CMAP_FORMAT_4 */ 01395 01396 01397 /*************************************************************************/ 01398 /*************************************************************************/ 01399 /***** *****/ 01400 /***** FORMAT 6 *****/ 01401 /***** *****/ 01402 /*************************************************************************/ 01403 /*************************************************************************/ 01404 01405 /*************************************************************************/ 01406 /* */ 01407 /* TABLE OVERVIEW */ 01408 /* -------------- */ 01409 /* */ 01410 /* NAME OFFSET TYPE DESCRIPTION */ 01411 /* */ 01412 /* format 0 USHORT must be 4 */ 01413 /* length 2 USHORT table length in bytes */ 01414 /* language 4 USHORT Mac language code */ 01415 /* */ 01416 /* first 6 USHORT first segment code */ 01417 /* count 8 USHORT segment size in chars */ 01418 /* glyphIds 10 USHORT[count] glyph IDs */ 01419 /* */ 01420 /* A very simplified segment mapping. */ 01421 /* */ 01422 01423 #ifdef TT_CONFIG_CMAP_FORMAT_6 01424 01425 FT_CALLBACK_DEF( FT_Error ) 01426 tt_cmap6_validate( FT_Byte* table, 01427 FT_Validator valid ) 01428 { 01429 FT_Byte* p; 01430 FT_UInt length, count; 01431 01432 01433 if ( table + 10 > valid->limit ) 01434 FT_INVALID_TOO_SHORT; 01435 01436 p = table + 2; 01437 length = TT_NEXT_USHORT( p ); 01438 01439 p = table + 8; /* skip language and start index */ 01440 count = TT_NEXT_USHORT( p ); 01441 01442 if ( table + length > valid->limit || length < 10 + count * 2 ) 01443 FT_INVALID_TOO_SHORT; 01444 01445 /* check glyph indices */ 01446 if ( valid->level >= FT_VALIDATE_TIGHT ) 01447 { 01448 FT_UInt gindex; 01449 01450 01451 for ( ; count > 0; count-- ) 01452 { 01453 gindex = TT_NEXT_USHORT( p ); 01454 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 01455 FT_INVALID_GLYPH_ID; 01456 } 01457 } 01458 01459 return SFNT_Err_Ok; 01460 } 01461 01462 01463 FT_CALLBACK_DEF( FT_UInt ) 01464 tt_cmap6_char_index( TT_CMap cmap, 01465 FT_UInt32 char_code ) 01466 { 01467 FT_Byte* table = cmap->data; 01468 FT_UInt result = 0; 01469 FT_Byte* p = table + 6; 01470 FT_UInt start = TT_NEXT_USHORT( p ); 01471 FT_UInt count = TT_NEXT_USHORT( p ); 01472 FT_UInt idx = (FT_UInt)( char_code - start ); 01473 01474 01475 if ( idx < count ) 01476 { 01477 p += 2 * idx; 01478 result = TT_PEEK_USHORT( p ); 01479 } 01480 return result; 01481 } 01482 01483 01484 FT_CALLBACK_DEF( FT_UInt32 ) 01485 tt_cmap6_char_next( TT_CMap cmap, 01486 FT_UInt32 *pchar_code ) 01487 { 01488 FT_Byte* table = cmap->data; 01489 FT_UInt32 result = 0; 01490 FT_UInt32 char_code = *pchar_code + 1; 01491 FT_UInt gindex = 0; 01492 01493 FT_Byte* p = table + 6; 01494 FT_UInt start = TT_NEXT_USHORT( p ); 01495 FT_UInt count = TT_NEXT_USHORT( p ); 01496 FT_UInt idx; 01497 01498 01499 if ( char_code >= 0x10000UL ) 01500 goto Exit; 01501 01502 if ( char_code < start ) 01503 char_code = start; 01504 01505 idx = (FT_UInt)( char_code - start ); 01506 p += 2 * idx; 01507 01508 for ( ; idx < count; idx++ ) 01509 { 01510 gindex = TT_NEXT_USHORT( p ); 01511 if ( gindex != 0 ) 01512 { 01513 result = char_code; 01514 break; 01515 } 01516 char_code++; 01517 } 01518 01519 Exit: 01520 *pchar_code = result; 01521 return gindex; 01522 } 01523 01524 01525 FT_CALLBACK_DEF( FT_Error ) 01526 tt_cmap6_get_info( TT_CMap cmap, 01527 TT_CMapInfo *cmap_info ) 01528 { 01529 FT_Byte* p = cmap->data + 4; 01530 01531 01532 cmap_info->format = 6; 01533 cmap_info->language = (FT_ULong)TT_PEEK_USHORT( p ); 01534 01535 return SFNT_Err_Ok; 01536 } 01537 01538 01539 FT_DEFINE_TT_CMAP(tt_cmap6_class_rec, 01540 sizeof ( TT_CMapRec ), 01541 01542 (FT_CMap_InitFunc) tt_cmap_init, 01543 (FT_CMap_DoneFunc) NULL, 01544 (FT_CMap_CharIndexFunc)tt_cmap6_char_index, 01545 (FT_CMap_CharNextFunc) tt_cmap6_char_next, 01546 01547 NULL, NULL, NULL, NULL, NULL 01548 , 01549 6, 01550 (TT_CMap_ValidateFunc) tt_cmap6_validate, 01551 (TT_CMap_Info_GetFunc) tt_cmap6_get_info 01552 ) 01553 01554 #endif /* TT_CONFIG_CMAP_FORMAT_6 */ 01555 01556 01557 /*************************************************************************/ 01558 /*************************************************************************/ 01559 /***** *****/ 01560 /***** FORMAT 8 *****/ 01561 /***** *****/ 01562 /***** It is hard to completely understand what the OpenType spec *****/ 01563 /***** says about this format, but here is my conclusion. *****/ 01564 /***** *****/ 01565 /***** The purpose of this format is to easily map UTF-16 text to *****/ 01566 /***** glyph indices. Basically, the `char_code' must be in one of *****/ 01567 /***** the following formats: *****/ 01568 /***** *****/ 01569 /***** - A 16-bit value that isn't part of the Unicode Surrogates *****/ 01570 /***** Area (i.e. U+D800-U+DFFF). *****/ 01571 /***** *****/ 01572 /***** - A 32-bit value, made of two surrogate values, i.e.. if *****/ 01573 /***** `char_code = (char_hi << 16) | char_lo', then both *****/ 01574 /***** `char_hi' and `char_lo' must be in the Surrogates Area. *****/ 01575 /***** Area. *****/ 01576 /***** *****/ 01577 /***** The `is32' table embedded in the charmap indicates whether a *****/ 01578 /***** given 16-bit value is in the surrogates area or not. *****/ 01579 /***** *****/ 01580 /***** So, for any given `char_code', we can assert the following: *****/ 01581 /***** *****/ 01582 /***** If `char_hi == 0' then we must have `is32[char_lo] == 0'. *****/ 01583 /***** *****/ 01584 /***** If `char_hi != 0' then we must have both *****/ 01585 /***** `is32[char_hi] != 0' and `is32[char_lo] != 0'. *****/ 01586 /***** *****/ 01587 /*************************************************************************/ 01588 /*************************************************************************/ 01589 01590 /*************************************************************************/ 01591 /* */ 01592 /* TABLE OVERVIEW */ 01593 /* -------------- */ 01594 /* */ 01595 /* NAME OFFSET TYPE DESCRIPTION */ 01596 /* */ 01597 /* format 0 USHORT must be 8 */ 01598 /* reserved 2 USHORT reserved */ 01599 /* length 4 ULONG length in bytes */ 01600 /* language 8 ULONG Mac language code */ 01601 /* is32 12 BYTE[8192] 32-bitness bitmap */ 01602 /* count 8204 ULONG number of groups */ 01603 /* */ 01604 /* This header is followed by `count' groups of the following format: */ 01605 /* */ 01606 /* start 0 ULONG first charcode */ 01607 /* end 4 ULONG last charcode */ 01608 /* startId 8 ULONG start glyph ID for the group */ 01609 /* */ 01610 01611 #ifdef TT_CONFIG_CMAP_FORMAT_8 01612 01613 FT_CALLBACK_DEF( FT_Error ) 01614 tt_cmap8_validate( FT_Byte* table, 01615 FT_Validator valid ) 01616 { 01617 FT_Byte* p = table + 4; 01618 FT_Byte* is32; 01619 FT_UInt32 length; 01620 FT_UInt32 num_groups; 01621 01622 01623 if ( table + 16 + 8192 > valid->limit ) 01624 FT_INVALID_TOO_SHORT; 01625 01626 length = TT_NEXT_ULONG( p ); 01627 if ( length > (FT_UInt32)( valid->limit - table ) || length < 8192 + 16 ) 01628 FT_INVALID_TOO_SHORT; 01629 01630 is32 = table + 12; 01631 p = is32 + 8192; /* skip `is32' array */ 01632 num_groups = TT_NEXT_ULONG( p ); 01633 01634 if ( p + num_groups * 12 > valid->limit ) 01635 FT_INVALID_TOO_SHORT; 01636 01637 /* check groups, they must be in increasing order */ 01638 { 01639 FT_UInt32 n, start, end, start_id, count, last = 0; 01640 01641 01642 for ( n = 0; n < num_groups; n++ ) 01643 { 01644 FT_UInt hi, lo; 01645 01646 01647 start = TT_NEXT_ULONG( p ); 01648 end = TT_NEXT_ULONG( p ); 01649 start_id = TT_NEXT_ULONG( p ); 01650 01651 if ( start > end ) 01652 FT_INVALID_DATA; 01653 01654 if ( n > 0 && start <= last ) 01655 FT_INVALID_DATA; 01656 01657 if ( valid->level >= FT_VALIDATE_TIGHT ) 01658 { 01659 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 01660 FT_INVALID_GLYPH_ID; 01661 01662 count = (FT_UInt32)( end - start + 1 ); 01663 01664 if ( start & ~0xFFFFU ) 01665 { 01666 /* start_hi != 0; check that is32[i] is 1 for each i in */ 01667 /* the `hi' and `lo' of the range [start..end] */ 01668 for ( ; count > 0; count--, start++ ) 01669 { 01670 hi = (FT_UInt)( start >> 16 ); 01671 lo = (FT_UInt)( start & 0xFFFFU ); 01672 01673 if ( (is32[hi >> 3] & ( 0x80 >> ( hi & 7 ) ) ) == 0 ) 01674 FT_INVALID_DATA; 01675 01676 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) == 0 ) 01677 FT_INVALID_DATA; 01678 } 01679 } 01680 else 01681 { 01682 /* start_hi == 0; check that is32[i] is 0 for each i in */ 01683 /* the range [start..end] */ 01684 01685 /* end_hi cannot be != 0! */ 01686 if ( end & ~0xFFFFU ) 01687 FT_INVALID_DATA; 01688 01689 for ( ; count > 0; count--, start++ ) 01690 { 01691 lo = (FT_UInt)( start & 0xFFFFU ); 01692 01693 if ( (is32[lo >> 3] & ( 0x80 >> ( lo & 7 ) ) ) != 0 ) 01694 FT_INVALID_DATA; 01695 } 01696 } 01697 } 01698 01699 last = end; 01700 } 01701 } 01702 01703 return SFNT_Err_Ok; 01704 } 01705 01706 01707 FT_CALLBACK_DEF( FT_UInt ) 01708 tt_cmap8_char_index( TT_CMap cmap, 01709 FT_UInt32 char_code ) 01710 { 01711 FT_Byte* table = cmap->data; 01712 FT_UInt result = 0; 01713 FT_Byte* p = table + 8204; 01714 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 01715 FT_UInt32 start, end, start_id; 01716 01717 01718 for ( ; num_groups > 0; num_groups-- ) 01719 { 01720 start = TT_NEXT_ULONG( p ); 01721 end = TT_NEXT_ULONG( p ); 01722 start_id = TT_NEXT_ULONG( p ); 01723 01724 if ( char_code < start ) 01725 break; 01726 01727 if ( char_code <= end ) 01728 { 01729 result = (FT_UInt)( start_id + char_code - start ); 01730 break; 01731 } 01732 } 01733 return result; 01734 } 01735 01736 01737 FT_CALLBACK_DEF( FT_UInt32 ) 01738 tt_cmap8_char_next( TT_CMap cmap, 01739 FT_UInt32 *pchar_code ) 01740 { 01741 FT_UInt32 result = 0; 01742 FT_UInt32 char_code = *pchar_code + 1; 01743 FT_UInt gindex = 0; 01744 FT_Byte* table = cmap->data; 01745 FT_Byte* p = table + 8204; 01746 FT_UInt32 num_groups = TT_NEXT_ULONG( p ); 01747 FT_UInt32 start, end, start_id; 01748 01749 01750 p = table + 8208; 01751 01752 for ( ; num_groups > 0; num_groups-- ) 01753 { 01754 start = TT_NEXT_ULONG( p ); 01755 end = TT_NEXT_ULONG( p ); 01756 start_id = TT_NEXT_ULONG( p ); 01757 01758 if ( char_code < start ) 01759 char_code = start; 01760 01761 if ( char_code <= end ) 01762 { 01763 gindex = (FT_UInt)( char_code - start + start_id ); 01764 if ( gindex != 0 ) 01765 { 01766 result = char_code; 01767 goto Exit; 01768 } 01769 } 01770 } 01771 01772 Exit: 01773 *pchar_code = result; 01774 return gindex; 01775 } 01776 01777 01778 FT_CALLBACK_DEF( FT_Error ) 01779 tt_cmap8_get_info( TT_CMap cmap, 01780 TT_CMapInfo *cmap_info ) 01781 { 01782 FT_Byte* p = cmap->data + 8; 01783 01784 01785 cmap_info->format = 8; 01786 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 01787 01788 return SFNT_Err_Ok; 01789 } 01790 01791 01792 FT_DEFINE_TT_CMAP(tt_cmap8_class_rec, 01793 sizeof ( TT_CMapRec ), 01794 01795 (FT_CMap_InitFunc) tt_cmap_init, 01796 (FT_CMap_DoneFunc) NULL, 01797 (FT_CMap_CharIndexFunc)tt_cmap8_char_index, 01798 (FT_CMap_CharNextFunc) tt_cmap8_char_next, 01799 01800 NULL, NULL, NULL, NULL, NULL 01801 , 01802 8, 01803 (TT_CMap_ValidateFunc) tt_cmap8_validate, 01804 (TT_CMap_Info_GetFunc) tt_cmap8_get_info 01805 ) 01806 01807 #endif /* TT_CONFIG_CMAP_FORMAT_8 */ 01808 01809 01810 /*************************************************************************/ 01811 /*************************************************************************/ 01812 /***** *****/ 01813 /***** FORMAT 10 *****/ 01814 /***** *****/ 01815 /*************************************************************************/ 01816 /*************************************************************************/ 01817 01818 /*************************************************************************/ 01819 /* */ 01820 /* TABLE OVERVIEW */ 01821 /* -------------- */ 01822 /* */ 01823 /* NAME OFFSET TYPE DESCRIPTION */ 01824 /* */ 01825 /* format 0 USHORT must be 10 */ 01826 /* reserved 2 USHORT reserved */ 01827 /* length 4 ULONG length in bytes */ 01828 /* language 8 ULONG Mac language code */ 01829 /* */ 01830 /* start 12 ULONG first char in range */ 01831 /* count 16 ULONG number of chars in range */ 01832 /* glyphIds 20 USHORT[count] glyph indices covered */ 01833 /* */ 01834 01835 #ifdef TT_CONFIG_CMAP_FORMAT_10 01836 01837 FT_CALLBACK_DEF( FT_Error ) 01838 tt_cmap10_validate( FT_Byte* table, 01839 FT_Validator valid ) 01840 { 01841 FT_Byte* p = table + 4; 01842 FT_ULong length, count; 01843 01844 01845 if ( table + 20 > valid->limit ) 01846 FT_INVALID_TOO_SHORT; 01847 01848 length = TT_NEXT_ULONG( p ); 01849 p = table + 16; 01850 count = TT_NEXT_ULONG( p ); 01851 01852 if ( length > (FT_ULong)( valid->limit - table ) || 01853 length < 20 + count * 2 ) 01854 FT_INVALID_TOO_SHORT; 01855 01856 /* check glyph indices */ 01857 if ( valid->level >= FT_VALIDATE_TIGHT ) 01858 { 01859 FT_UInt gindex; 01860 01861 01862 for ( ; count > 0; count-- ) 01863 { 01864 gindex = TT_NEXT_USHORT( p ); 01865 if ( gindex >= TT_VALID_GLYPH_COUNT( valid ) ) 01866 FT_INVALID_GLYPH_ID; 01867 } 01868 } 01869 01870 return SFNT_Err_Ok; 01871 } 01872 01873 01874 FT_CALLBACK_DEF( FT_UInt ) 01875 tt_cmap10_char_index( TT_CMap cmap, 01876 FT_UInt32 char_code ) 01877 { 01878 FT_Byte* table = cmap->data; 01879 FT_UInt result = 0; 01880 FT_Byte* p = table + 12; 01881 FT_UInt32 start = TT_NEXT_ULONG( p ); 01882 FT_UInt32 count = TT_NEXT_ULONG( p ); 01883 FT_UInt32 idx = (FT_ULong)( char_code - start ); 01884 01885 01886 if ( idx < count ) 01887 { 01888 p += 2 * idx; 01889 result = TT_PEEK_USHORT( p ); 01890 } 01891 return result; 01892 } 01893 01894 01895 FT_CALLBACK_DEF( FT_UInt32 ) 01896 tt_cmap10_char_next( TT_CMap cmap, 01897 FT_UInt32 *pchar_code ) 01898 { 01899 FT_Byte* table = cmap->data; 01900 FT_UInt32 char_code = *pchar_code + 1; 01901 FT_UInt gindex = 0; 01902 FT_Byte* p = table + 12; 01903 FT_UInt32 start = TT_NEXT_ULONG( p ); 01904 FT_UInt32 count = TT_NEXT_ULONG( p ); 01905 FT_UInt32 idx; 01906 01907 01908 if ( char_code < start ) 01909 char_code = start; 01910 01911 idx = (FT_UInt32)( char_code - start ); 01912 p += 2 * idx; 01913 01914 for ( ; idx < count; idx++ ) 01915 { 01916 gindex = TT_NEXT_USHORT( p ); 01917 if ( gindex != 0 ) 01918 break; 01919 char_code++; 01920 } 01921 01922 *pchar_code = char_code; 01923 return gindex; 01924 } 01925 01926 01927 FT_CALLBACK_DEF( FT_Error ) 01928 tt_cmap10_get_info( TT_CMap cmap, 01929 TT_CMapInfo *cmap_info ) 01930 { 01931 FT_Byte* p = cmap->data + 8; 01932 01933 01934 cmap_info->format = 10; 01935 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 01936 01937 return SFNT_Err_Ok; 01938 } 01939 01940 01941 FT_DEFINE_TT_CMAP(tt_cmap10_class_rec, 01942 sizeof ( TT_CMapRec ), 01943 01944 (FT_CMap_InitFunc) tt_cmap_init, 01945 (FT_CMap_DoneFunc) NULL, 01946 (FT_CMap_CharIndexFunc)tt_cmap10_char_index, 01947 (FT_CMap_CharNextFunc) tt_cmap10_char_next, 01948 01949 NULL, NULL, NULL, NULL, NULL 01950 , 01951 10, 01952 (TT_CMap_ValidateFunc) tt_cmap10_validate, 01953 (TT_CMap_Info_GetFunc) tt_cmap10_get_info 01954 ) 01955 01956 #endif /* TT_CONFIG_CMAP_FORMAT_10 */ 01957 01958 01959 /*************************************************************************/ 01960 /*************************************************************************/ 01961 /***** *****/ 01962 /***** FORMAT 12 *****/ 01963 /***** *****/ 01964 /*************************************************************************/ 01965 /*************************************************************************/ 01966 01967 /*************************************************************************/ 01968 /* */ 01969 /* TABLE OVERVIEW */ 01970 /* -------------- */ 01971 /* */ 01972 /* NAME OFFSET TYPE DESCRIPTION */ 01973 /* */ 01974 /* format 0 USHORT must be 12 */ 01975 /* reserved 2 USHORT reserved */ 01976 /* length 4 ULONG length in bytes */ 01977 /* language 8 ULONG Mac language code */ 01978 /* count 12 ULONG number of groups */ 01979 /* 16 */ 01980 /* */ 01981 /* This header is followed by `count' groups of the following format: */ 01982 /* */ 01983 /* start 0 ULONG first charcode */ 01984 /* end 4 ULONG last charcode */ 01985 /* startId 8 ULONG start glyph ID for the group */ 01986 /* */ 01987 01988 #ifdef TT_CONFIG_CMAP_FORMAT_12 01989 01990 typedef struct TT_CMap12Rec_ 01991 { 01992 TT_CMapRec cmap; 01993 FT_Bool valid; 01994 FT_ULong cur_charcode; 01995 FT_UInt cur_gindex; 01996 FT_ULong cur_group; 01997 FT_ULong num_groups; 01998 01999 } TT_CMap12Rec, *TT_CMap12; 02000 02001 02002 FT_CALLBACK_DEF( FT_Error ) 02003 tt_cmap12_init( TT_CMap12 cmap, 02004 FT_Byte* table ) 02005 { 02006 cmap->cmap.data = table; 02007 02008 table += 12; 02009 cmap->num_groups = FT_PEEK_ULONG( table ); 02010 02011 cmap->valid = 0; 02012 02013 return SFNT_Err_Ok; 02014 } 02015 02016 02017 FT_CALLBACK_DEF( FT_Error ) 02018 tt_cmap12_validate( FT_Byte* table, 02019 FT_Validator valid ) 02020 { 02021 FT_Byte* p; 02022 FT_ULong length; 02023 FT_ULong num_groups; 02024 02025 02026 if ( table + 16 > valid->limit ) 02027 FT_INVALID_TOO_SHORT; 02028 02029 p = table + 4; 02030 length = TT_NEXT_ULONG( p ); 02031 02032 p = table + 12; 02033 num_groups = TT_NEXT_ULONG( p ); 02034 02035 if ( length > (FT_ULong)( valid->limit - table ) || 02036 length < 16 + 12 * num_groups ) 02037 FT_INVALID_TOO_SHORT; 02038 02039 /* check groups, they must be in increasing order */ 02040 { 02041 FT_ULong n, start, end, start_id, last = 0; 02042 02043 02044 for ( n = 0; n < num_groups; n++ ) 02045 { 02046 start = TT_NEXT_ULONG( p ); 02047 end = TT_NEXT_ULONG( p ); 02048 start_id = TT_NEXT_ULONG( p ); 02049 02050 if ( start > end ) 02051 FT_INVALID_DATA; 02052 02053 if ( n > 0 && start <= last ) 02054 FT_INVALID_DATA; 02055 02056 if ( valid->level >= FT_VALIDATE_TIGHT ) 02057 { 02058 if ( start_id + end - start >= TT_VALID_GLYPH_COUNT( valid ) ) 02059 FT_INVALID_GLYPH_ID; 02060 } 02061 02062 last = end; 02063 } 02064 } 02065 02066 return SFNT_Err_Ok; 02067 } 02068 02069 02070 /* search the index of the charcode next to cmap->cur_charcode */ 02071 /* cmap->cur_group should be set up properly by caller */ 02072 /* */ 02073 static void 02074 tt_cmap12_next( TT_CMap12 cmap ) 02075 { 02076 FT_Byte* p; 02077 FT_ULong start, end, start_id, char_code; 02078 FT_ULong n; 02079 FT_UInt gindex; 02080 02081 02082 if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) 02083 goto Fail; 02084 02085 char_code = cmap->cur_charcode + 1; 02086 02087 n = cmap->cur_group; 02088 02089 for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) 02090 { 02091 p = cmap->cmap.data + 16 + 12 * n; 02092 start = TT_NEXT_ULONG( p ); 02093 end = TT_NEXT_ULONG( p ); 02094 start_id = TT_PEEK_ULONG( p ); 02095 02096 if ( char_code < start ) 02097 char_code = start; 02098 02099 for ( ; char_code <= end; char_code++ ) 02100 { 02101 gindex = (FT_UInt)( start_id + char_code - start ); 02102 02103 if ( gindex ) 02104 { 02105 cmap->cur_charcode = char_code;; 02106 cmap->cur_gindex = gindex; 02107 cmap->cur_group = n; 02108 02109 return; 02110 } 02111 } 02112 } 02113 02114 Fail: 02115 cmap->valid = 0; 02116 } 02117 02118 02119 static FT_UInt 02120 tt_cmap12_char_map_binary( TT_CMap cmap, 02121 FT_UInt32* pchar_code, 02122 FT_Bool next ) 02123 { 02124 FT_UInt gindex = 0; 02125 FT_Byte* p = cmap->data + 12; 02126 FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 02127 FT_UInt32 char_code = *pchar_code; 02128 FT_UInt32 start, end, start_id; 02129 FT_UInt32 max, min, mid; 02130 02131 02132 if ( !num_groups ) 02133 return 0; 02134 02135 /* make compiler happy */ 02136 mid = num_groups; 02137 end = 0xFFFFFFFFUL; 02138 02139 if ( next ) 02140 char_code++; 02141 02142 min = 0; 02143 max = num_groups; 02144 02145 /* binary search */ 02146 while ( min < max ) 02147 { 02148 mid = ( min + max ) >> 1; 02149 p = cmap->data + 16 + 12 * mid; 02150 02151 start = TT_NEXT_ULONG( p ); 02152 end = TT_NEXT_ULONG( p ); 02153 02154 if ( char_code < start ) 02155 max = mid; 02156 else if ( char_code > end ) 02157 min = mid + 1; 02158 else 02159 { 02160 start_id = TT_PEEK_ULONG( p ); 02161 gindex = (FT_UInt)( start_id + char_code - start ); 02162 02163 break; 02164 } 02165 } 02166 02167 if ( next ) 02168 { 02169 TT_CMap12 cmap12 = (TT_CMap12)cmap; 02170 02171 02172 /* if `char_code' is not in any group, then `mid' is */ 02173 /* the group nearest to `char_code' */ 02174 /* */ 02175 02176 if ( char_code > end ) 02177 { 02178 mid++; 02179 if ( mid == num_groups ) 02180 return 0; 02181 } 02182 02183 cmap12->valid = 1; 02184 cmap12->cur_charcode = char_code; 02185 cmap12->cur_group = mid; 02186 02187 if ( !gindex ) 02188 { 02189 tt_cmap12_next( cmap12 ); 02190 02191 if ( cmap12->valid ) 02192 gindex = cmap12->cur_gindex; 02193 } 02194 else 02195 cmap12->cur_gindex = gindex; 02196 02197 if ( gindex ) 02198 *pchar_code = cmap12->cur_charcode; 02199 } 02200 02201 return gindex; 02202 } 02203 02204 02205 FT_CALLBACK_DEF( FT_UInt ) 02206 tt_cmap12_char_index( TT_CMap cmap, 02207 FT_UInt32 char_code ) 02208 { 02209 return tt_cmap12_char_map_binary( cmap, &char_code, 0 ); 02210 } 02211 02212 02213 FT_CALLBACK_DEF( FT_UInt32 ) 02214 tt_cmap12_char_next( TT_CMap cmap, 02215 FT_UInt32 *pchar_code ) 02216 { 02217 TT_CMap12 cmap12 = (TT_CMap12)cmap; 02218 FT_ULong gindex; 02219 02220 02221 if ( cmap12->cur_charcode >= 0xFFFFFFFFUL ) 02222 return 0; 02223 02224 /* no need to search */ 02225 if ( cmap12->valid && cmap12->cur_charcode == *pchar_code ) 02226 { 02227 tt_cmap12_next( cmap12 ); 02228 if ( cmap12->valid ) 02229 { 02230 gindex = cmap12->cur_gindex; 02231 02232 /* XXX: check cur_charcode overflow is expected */ 02233 if ( gindex ) 02234 *pchar_code = (FT_UInt32)cmap12->cur_charcode; 02235 } 02236 else 02237 gindex = 0; 02238 } 02239 else 02240 gindex = tt_cmap12_char_map_binary( cmap, pchar_code, 1 ); 02241 02242 /* XXX: check gindex overflow is expected */ 02243 return (FT_UInt32)gindex; 02244 } 02245 02246 02247 FT_CALLBACK_DEF( FT_Error ) 02248 tt_cmap12_get_info( TT_CMap cmap, 02249 TT_CMapInfo *cmap_info ) 02250 { 02251 FT_Byte* p = cmap->data + 8; 02252 02253 02254 cmap_info->format = 12; 02255 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 02256 02257 return SFNT_Err_Ok; 02258 } 02259 02260 02261 FT_DEFINE_TT_CMAP(tt_cmap12_class_rec, 02262 sizeof ( TT_CMap12Rec ), 02263 02264 (FT_CMap_InitFunc) tt_cmap12_init, 02265 (FT_CMap_DoneFunc) NULL, 02266 (FT_CMap_CharIndexFunc)tt_cmap12_char_index, 02267 (FT_CMap_CharNextFunc) tt_cmap12_char_next, 02268 02269 NULL, NULL, NULL, NULL, NULL 02270 , 02271 12, 02272 (TT_CMap_ValidateFunc) tt_cmap12_validate, 02273 (TT_CMap_Info_GetFunc) tt_cmap12_get_info 02274 ) 02275 02276 #endif /* TT_CONFIG_CMAP_FORMAT_12 */ 02277 02278 02279 /*************************************************************************/ 02280 /*************************************************************************/ 02281 /***** *****/ 02282 /***** FORMAT 13 *****/ 02283 /***** *****/ 02284 /*************************************************************************/ 02285 /*************************************************************************/ 02286 02287 /*************************************************************************/ 02288 /* */ 02289 /* TABLE OVERVIEW */ 02290 /* -------------- */ 02291 /* */ 02292 /* NAME OFFSET TYPE DESCRIPTION */ 02293 /* */ 02294 /* format 0 USHORT must be 13 */ 02295 /* reserved 2 USHORT reserved */ 02296 /* length 4 ULONG length in bytes */ 02297 /* language 8 ULONG Mac language code */ 02298 /* count 12 ULONG number of groups */ 02299 /* 16 */ 02300 /* */ 02301 /* This header is followed by `count' groups of the following format: */ 02302 /* */ 02303 /* start 0 ULONG first charcode */ 02304 /* end 4 ULONG last charcode */ 02305 /* glyphId 8 ULONG glyph ID for the whole group */ 02306 /* */ 02307 02308 #ifdef TT_CONFIG_CMAP_FORMAT_13 02309 02310 typedef struct TT_CMap13Rec_ 02311 { 02312 TT_CMapRec cmap; 02313 FT_Bool valid; 02314 FT_ULong cur_charcode; 02315 FT_UInt cur_gindex; 02316 FT_ULong cur_group; 02317 FT_ULong num_groups; 02318 02319 } TT_CMap13Rec, *TT_CMap13; 02320 02321 02322 FT_CALLBACK_DEF( FT_Error ) 02323 tt_cmap13_init( TT_CMap13 cmap, 02324 FT_Byte* table ) 02325 { 02326 cmap->cmap.data = table; 02327 02328 table += 12; 02329 cmap->num_groups = FT_PEEK_ULONG( table ); 02330 02331 cmap->valid = 0; 02332 02333 return SFNT_Err_Ok; 02334 } 02335 02336 02337 FT_CALLBACK_DEF( FT_Error ) 02338 tt_cmap13_validate( FT_Byte* table, 02339 FT_Validator valid ) 02340 { 02341 FT_Byte* p; 02342 FT_ULong length; 02343 FT_ULong num_groups; 02344 02345 02346 if ( table + 16 > valid->limit ) 02347 FT_INVALID_TOO_SHORT; 02348 02349 p = table + 4; 02350 length = TT_NEXT_ULONG( p ); 02351 02352 p = table + 12; 02353 num_groups = TT_NEXT_ULONG( p ); 02354 02355 if ( length > (FT_ULong)( valid->limit - table ) || 02356 length < 16 + 12 * num_groups ) 02357 FT_INVALID_TOO_SHORT; 02358 02359 /* check groups, they must be in increasing order */ 02360 { 02361 FT_ULong n, start, end, glyph_id, last = 0; 02362 02363 02364 for ( n = 0; n < num_groups; n++ ) 02365 { 02366 start = TT_NEXT_ULONG( p ); 02367 end = TT_NEXT_ULONG( p ); 02368 glyph_id = TT_NEXT_ULONG( p ); 02369 02370 if ( start > end ) 02371 FT_INVALID_DATA; 02372 02373 if ( n > 0 && start <= last ) 02374 FT_INVALID_DATA; 02375 02376 if ( valid->level >= FT_VALIDATE_TIGHT ) 02377 { 02378 if ( glyph_id >= TT_VALID_GLYPH_COUNT( valid ) ) 02379 FT_INVALID_GLYPH_ID; 02380 } 02381 02382 last = end; 02383 } 02384 } 02385 02386 return SFNT_Err_Ok; 02387 } 02388 02389 02390 /* search the index of the charcode next to cmap->cur_charcode */ 02391 /* cmap->cur_group should be set up properly by caller */ 02392 /* */ 02393 static void 02394 tt_cmap13_next( TT_CMap13 cmap ) 02395 { 02396 FT_Byte* p; 02397 FT_ULong start, end, glyph_id, char_code; 02398 FT_ULong n; 02399 FT_UInt gindex; 02400 02401 02402 if ( cmap->cur_charcode >= 0xFFFFFFFFUL ) 02403 goto Fail; 02404 02405 char_code = cmap->cur_charcode + 1; 02406 02407 n = cmap->cur_group; 02408 02409 for ( n = cmap->cur_group; n < cmap->num_groups; n++ ) 02410 { 02411 p = cmap->cmap.data + 16 + 12 * n; 02412 start = TT_NEXT_ULONG( p ); 02413 end = TT_NEXT_ULONG( p ); 02414 glyph_id = TT_PEEK_ULONG( p ); 02415 02416 if ( char_code < start ) 02417 char_code = start; 02418 02419 if ( char_code <= end ) 02420 { 02421 gindex = (FT_UInt)glyph_id; 02422 02423 if ( gindex ) 02424 { 02425 cmap->cur_charcode = char_code;; 02426 cmap->cur_gindex = gindex; 02427 cmap->cur_group = n; 02428 02429 return; 02430 } 02431 } 02432 } 02433 02434 Fail: 02435 cmap->valid = 0; 02436 } 02437 02438 02439 static FT_UInt 02440 tt_cmap13_char_map_binary( TT_CMap cmap, 02441 FT_UInt32* pchar_code, 02442 FT_Bool next ) 02443 { 02444 FT_UInt gindex = 0; 02445 FT_Byte* p = cmap->data + 12; 02446 FT_UInt32 num_groups = TT_PEEK_ULONG( p ); 02447 FT_UInt32 char_code = *pchar_code; 02448 FT_UInt32 start, end; 02449 FT_UInt32 max, min, mid; 02450 02451 02452 if ( !num_groups ) 02453 return 0; 02454 02455 /* make compiler happy */ 02456 mid = num_groups; 02457 end = 0xFFFFFFFFUL; 02458 02459 if ( next ) 02460 char_code++; 02461 02462 min = 0; 02463 max = num_groups; 02464 02465 /* binary search */ 02466 while ( min < max ) 02467 { 02468 mid = ( min + max ) >> 1; 02469 p = cmap->data + 16 + 12 * mid; 02470 02471 start = TT_NEXT_ULONG( p ); 02472 end = TT_NEXT_ULONG( p ); 02473 02474 if ( char_code < start ) 02475 max = mid; 02476 else if ( char_code > end ) 02477 min = mid + 1; 02478 else 02479 { 02480 gindex = (FT_UInt)TT_PEEK_ULONG( p ); 02481 02482 break; 02483 } 02484 } 02485 02486 if ( next ) 02487 { 02488 TT_CMap13 cmap13 = (TT_CMap13)cmap; 02489 02490 02491 /* if `char_code' is not in any group, then `mid' is */ 02492 /* the group nearest to `char_code' */ 02493 /* */ 02494 02495 if ( char_code > end ) 02496 { 02497 mid++; 02498 if ( mid == num_groups ) 02499 return 0; 02500 } 02501 02502 cmap13->valid = 1; 02503 cmap13->cur_charcode = char_code; 02504 cmap13->cur_group = mid; 02505 02506 if ( !gindex ) 02507 { 02508 tt_cmap13_next( cmap13 ); 02509 02510 if ( cmap13->valid ) 02511 gindex = cmap13->cur_gindex; 02512 } 02513 else 02514 cmap13->cur_gindex = gindex; 02515 02516 if ( gindex ) 02517 *pchar_code = cmap13->cur_charcode; 02518 } 02519 02520 return gindex; 02521 } 02522 02523 02524 FT_CALLBACK_DEF( FT_UInt ) 02525 tt_cmap13_char_index( TT_CMap cmap, 02526 FT_UInt32 char_code ) 02527 { 02528 return tt_cmap13_char_map_binary( cmap, &char_code, 0 ); 02529 } 02530 02531 02532 FT_CALLBACK_DEF( FT_UInt32 ) 02533 tt_cmap13_char_next( TT_CMap cmap, 02534 FT_UInt32 *pchar_code ) 02535 { 02536 TT_CMap13 cmap13 = (TT_CMap13)cmap; 02537 FT_UInt gindex; 02538 02539 02540 if ( cmap13->cur_charcode >= 0xFFFFFFFFUL ) 02541 return 0; 02542 02543 /* no need to search */ 02544 if ( cmap13->valid && cmap13->cur_charcode == *pchar_code ) 02545 { 02546 tt_cmap13_next( cmap13 ); 02547 if ( cmap13->valid ) 02548 { 02549 gindex = cmap13->cur_gindex; 02550 if ( gindex ) 02551 *pchar_code = cmap13->cur_charcode; 02552 } 02553 else 02554 gindex = 0; 02555 } 02556 else 02557 gindex = tt_cmap13_char_map_binary( cmap, pchar_code, 1 ); 02558 02559 return gindex; 02560 } 02561 02562 02563 FT_CALLBACK_DEF( FT_Error ) 02564 tt_cmap13_get_info( TT_CMap cmap, 02565 TT_CMapInfo *cmap_info ) 02566 { 02567 FT_Byte* p = cmap->data + 8; 02568 02569 02570 cmap_info->format = 13; 02571 cmap_info->language = (FT_ULong)TT_PEEK_ULONG( p ); 02572 02573 return SFNT_Err_Ok; 02574 } 02575 02576 02577 FT_DEFINE_TT_CMAP(tt_cmap13_class_rec, 02578 sizeof ( TT_CMap13Rec ), 02579 02580 (FT_CMap_InitFunc) tt_cmap13_init, 02581 (FT_CMap_DoneFunc) NULL, 02582 (FT_CMap_CharIndexFunc)tt_cmap13_char_index, 02583 (FT_CMap_CharNextFunc) tt_cmap13_char_next, 02584 02585 NULL, NULL, NULL, NULL, NULL 02586 , 02587 13, 02588 (TT_CMap_ValidateFunc) tt_cmap13_validate, 02589 (TT_CMap_Info_GetFunc) tt_cmap13_get_info 02590 ) 02591 02592 #endif /* TT_CONFIG_CMAP_FORMAT_13 */ 02593 02594 02595 /*************************************************************************/ 02596 /*************************************************************************/ 02597 /***** *****/ 02598 /***** FORMAT 14 *****/ 02599 /***** *****/ 02600 /*************************************************************************/ 02601 /*************************************************************************/ 02602 02603 /*************************************************************************/ 02604 /* */ 02605 /* TABLE OVERVIEW */ 02606 /* -------------- */ 02607 /* */ 02608 /* NAME OFFSET TYPE DESCRIPTION */ 02609 /* */ 02610 /* format 0 USHORT must be 14 */ 02611 /* length 2 ULONG table length in bytes */ 02612 /* numSelector 6 ULONG number of variation sel. records */ 02613 /* */ 02614 /* Followed by numSelector records, each of which looks like */ 02615 /* */ 02616 /* varSelector 0 UINT24 Unicode codepoint of sel. */ 02617 /* defaultOff 3 ULONG offset to a default UVS table */ 02618 /* describing any variants to be found in */ 02619 /* the normal Unicode subtable. */ 02620 /* nonDefOff 7 ULONG offset to a non-default UVS table */ 02621 /* describing any variants not in the */ 02622 /* standard cmap, with GIDs here */ 02623 /* (either offset may be 0 NULL) */ 02624 /* */ 02625 /* Selectors are sorted by code point. */ 02626 /* */ 02627 /* A default Unicode Variation Selector (UVS) subtable is just a list of */ 02628 /* ranges of code points which are to be found in the standard cmap. No */ 02629 /* glyph IDs (GIDs) here. */ 02630 /* */ 02631 /* numRanges 0 ULONG number of ranges following */ 02632 /* */ 02633 /* A range looks like */ 02634 /* */ 02635 /* uniStart 0 UINT24 code point of the first character in */ 02636 /* this range */ 02637 /* additionalCnt 3 UBYTE count of additional characters in this */ 02638 /* range (zero means a range of a single */ 02639 /* character) */ 02640 /* */ 02641 /* Ranges are sorted by `uniStart'. */ 02642 /* */ 02643 /* A non-default Unicode Variation Selector (UVS) subtable is a list of */ 02644 /* mappings from codepoint to GID. */ 02645 /* */ 02646 /* numMappings 0 ULONG number of mappings */ 02647 /* */ 02648 /* A range looks like */ 02649 /* */ 02650 /* uniStart 0 UINT24 code point of the first character in */ 02651 /* this range */ 02652 /* GID 3 USHORT and its GID */ 02653 /* */ 02654 /* Ranges are sorted by `uniStart'. */ 02655 02656 #ifdef TT_CONFIG_CMAP_FORMAT_14 02657 02658 typedef struct TT_CMap14Rec_ 02659 { 02660 TT_CMapRec cmap; 02661 FT_ULong num_selectors; 02662 02663 /* This array is used to store the results of various 02664 * cmap 14 query functions. The data is overwritten 02665 * on each call to these functions. 02666 */ 02667 FT_UInt32 max_results; 02668 FT_UInt32* results; 02669 FT_Memory memory; 02670 02671 } TT_CMap14Rec, *TT_CMap14; 02672 02673 02674 FT_CALLBACK_DEF( void ) 02675 tt_cmap14_done( TT_CMap14 cmap ) 02676 { 02677 FT_Memory memory = cmap->memory; 02678 02679 02680 cmap->max_results = 0; 02681 if ( memory != NULL && cmap->results != NULL ) 02682 FT_FREE( cmap->results ); 02683 } 02684 02685 02686 static FT_Error 02687 tt_cmap14_ensure( TT_CMap14 cmap, 02688 FT_UInt32 num_results, 02689 FT_Memory memory ) 02690 { 02691 FT_UInt32 old_max = cmap->max_results; 02692 FT_Error error = SFNT_Err_Ok; 02693 02694 02695 if ( num_results > cmap->max_results ) 02696 { 02697 cmap->memory = memory; 02698 02699 if ( FT_QRENEW_ARRAY( cmap->results, old_max, num_results ) ) 02700 return error; 02701 02702 cmap->max_results = num_results; 02703 } 02704 02705 return error; 02706 } 02707 02708 02709 FT_CALLBACK_DEF( FT_Error ) 02710 tt_cmap14_init( TT_CMap14 cmap, 02711 FT_Byte* table ) 02712 { 02713 cmap->cmap.data = table; 02714 02715 table += 6; 02716 cmap->num_selectors = FT_PEEK_ULONG( table ); 02717 cmap->max_results = 0; 02718 cmap->results = NULL; 02719 02720 return SFNT_Err_Ok; 02721 } 02722 02723 02724 FT_CALLBACK_DEF( FT_Error ) 02725 tt_cmap14_validate( FT_Byte* table, 02726 FT_Validator valid ) 02727 { 02728 FT_Byte* p = table + 2; 02729 FT_ULong length = TT_NEXT_ULONG( p ); 02730 FT_ULong num_selectors = TT_NEXT_ULONG( p ); 02731 02732 02733 if ( length > (FT_ULong)( valid->limit - table ) || 02734 length < 10 + 11 * num_selectors ) 02735 FT_INVALID_TOO_SHORT; 02736 02737 /* check selectors, they must be in increasing order */ 02738 { 02739 /* we start lastVarSel at 1 because a variant selector value of 0 02740 * isn't valid. 02741 */ 02742 FT_ULong n, lastVarSel = 1; 02743 02744 02745 for ( n = 0; n < num_selectors; n++ ) 02746 { 02747 FT_ULong varSel = TT_NEXT_UINT24( p ); 02748 FT_ULong defOff = TT_NEXT_ULONG( p ); 02749 FT_ULong nondefOff = TT_NEXT_ULONG( p ); 02750 02751 02752 if ( defOff >= length || nondefOff >= length ) 02753 FT_INVALID_TOO_SHORT; 02754 02755 if ( varSel < lastVarSel ) 02756 FT_INVALID_DATA; 02757 02758 lastVarSel = varSel + 1; 02759 02760 /* check the default table (these glyphs should be reached */ 02761 /* through the normal Unicode cmap, no GIDs, just check order) */ 02762 if ( defOff != 0 ) 02763 { 02764 FT_Byte* defp = table + defOff; 02765 FT_ULong numRanges = TT_NEXT_ULONG( defp ); 02766 FT_ULong i; 02767 FT_ULong lastBase = 0; 02768 02769 02770 if ( defp + numRanges * 4 > valid->limit ) 02771 FT_INVALID_TOO_SHORT; 02772 02773 for ( i = 0; i < numRanges; ++i ) 02774 { 02775 FT_ULong base = TT_NEXT_UINT24( defp ); 02776 FT_ULong cnt = FT_NEXT_BYTE( defp ); 02777 02778 02779 if ( base + cnt >= 0x110000UL ) /* end of Unicode */ 02780 FT_INVALID_DATA; 02781 02782 if ( base < lastBase ) 02783 FT_INVALID_DATA; 02784 02785 lastBase = base + cnt + 1U; 02786 } 02787 } 02788 02789 /* and the non-default table (these glyphs are specified here) */ 02790 if ( nondefOff != 0 ) 02791 { 02792 FT_Byte* ndp = table + nondefOff; 02793 FT_ULong numMappings = TT_NEXT_ULONG( ndp ); 02794 FT_ULong i, lastUni = 0; 02795 02796 02797 if ( numMappings * 4 > (FT_ULong)( valid->limit - ndp ) ) 02798 FT_INVALID_TOO_SHORT; 02799 02800 for ( i = 0; i < numMappings; ++i ) 02801 { 02802 FT_ULong uni = TT_NEXT_UINT24( ndp ); 02803 FT_ULong gid = TT_NEXT_USHORT( ndp ); 02804 02805 02806 if ( uni >= 0x110000UL ) /* end of Unicode */ 02807 FT_INVALID_DATA; 02808 02809 if ( uni < lastUni ) 02810 FT_INVALID_DATA; 02811 02812 lastUni = uni + 1U; 02813 02814 if ( valid->level >= FT_VALIDATE_TIGHT && 02815 gid >= TT_VALID_GLYPH_COUNT( valid ) ) 02816 FT_INVALID_GLYPH_ID; 02817 } 02818 } 02819 } 02820 } 02821 02822 return SFNT_Err_Ok; 02823 } 02824 02825 02826 FT_CALLBACK_DEF( FT_UInt ) 02827 tt_cmap14_char_index( TT_CMap cmap, 02828 FT_UInt32 char_code ) 02829 { 02830 FT_UNUSED( cmap ); 02831 FT_UNUSED( char_code ); 02832 02833 /* This can't happen */ 02834 return 0; 02835 } 02836 02837 02838 FT_CALLBACK_DEF( FT_UInt32 ) 02839 tt_cmap14_char_next( TT_CMap cmap, 02840 FT_UInt32 *pchar_code ) 02841 { 02842 FT_UNUSED( cmap ); 02843 02844 /* This can't happen */ 02845 *pchar_code = 0; 02846 return 0; 02847 } 02848 02849 02850 FT_CALLBACK_DEF( FT_Error ) 02851 tt_cmap14_get_info( TT_CMap cmap, 02852 TT_CMapInfo *cmap_info ) 02853 { 02854 FT_UNUSED( cmap ); 02855 02856 cmap_info->format = 14; 02857 /* subtable 14 does not define a language field */ 02858 cmap_info->language = 0xFFFFFFFFUL; 02859 02860 return SFNT_Err_Ok; 02861 } 02862 02863 02864 static FT_UInt 02865 tt_cmap14_char_map_def_binary( FT_Byte *base, 02866 FT_UInt32 char_code ) 02867 { 02868 FT_UInt32 numRanges = TT_PEEK_ULONG( base ); 02869 FT_UInt32 max, min; 02870 02871 02872 min = 0; 02873 max = numRanges; 02874 02875 base += 4; 02876 02877 /* binary search */ 02878 while ( min < max ) 02879 { 02880 FT_UInt32 mid = ( min + max ) >> 1; 02881 FT_Byte* p = base + 4 * mid; 02882 FT_ULong start = TT_NEXT_UINT24( p ); 02883 FT_UInt cnt = FT_NEXT_BYTE( p ); 02884 02885 02886 if ( char_code < start ) 02887 max = mid; 02888 else if ( char_code > start+cnt ) 02889 min = mid + 1; 02890 else 02891 return TRUE; 02892 } 02893 02894 return FALSE; 02895 } 02896 02897 02898 static FT_UInt 02899 tt_cmap14_char_map_nondef_binary( FT_Byte *base, 02900 FT_UInt32 char_code ) 02901 { 02902 FT_UInt32 numMappings = TT_PEEK_ULONG( base ); 02903 FT_UInt32 max, min; 02904 02905 02906 min = 0; 02907 max = numMappings; 02908 02909 base += 4; 02910 02911 /* binary search */ 02912 while ( min < max ) 02913 { 02914 FT_UInt32 mid = ( min + max ) >> 1; 02915 FT_Byte* p = base + 5 * mid; 02916 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 02917 02918 02919 if ( char_code < uni ) 02920 max = mid; 02921 else if ( char_code > uni ) 02922 min = mid + 1; 02923 else 02924 return TT_PEEK_USHORT( p ); 02925 } 02926 02927 return 0; 02928 } 02929 02930 02931 static FT_Byte* 02932 tt_cmap14_find_variant( FT_Byte *base, 02933 FT_UInt32 variantCode ) 02934 { 02935 FT_UInt32 numVar = TT_PEEK_ULONG( base ); 02936 FT_UInt32 max, min; 02937 02938 02939 min = 0; 02940 max = numVar; 02941 02942 base += 4; 02943 02944 /* binary search */ 02945 while ( min < max ) 02946 { 02947 FT_UInt32 mid = ( min + max ) >> 1; 02948 FT_Byte* p = base + 11 * mid; 02949 FT_ULong varSel = TT_NEXT_UINT24( p ); 02950 02951 02952 if ( variantCode < varSel ) 02953 max = mid; 02954 else if ( variantCode > varSel ) 02955 min = mid + 1; 02956 else 02957 return p; 02958 } 02959 02960 return NULL; 02961 } 02962 02963 02964 FT_CALLBACK_DEF( FT_UInt ) 02965 tt_cmap14_char_var_index( TT_CMap cmap, 02966 TT_CMap ucmap, 02967 FT_UInt32 charcode, 02968 FT_UInt32 variantSelector) 02969 { 02970 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 02971 FT_ULong defOff; 02972 FT_ULong nondefOff; 02973 02974 02975 if ( !p ) 02976 return 0; 02977 02978 defOff = TT_NEXT_ULONG( p ); 02979 nondefOff = TT_PEEK_ULONG( p ); 02980 02981 if ( defOff != 0 && 02982 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 02983 { 02984 /* This is the default variant of this charcode. GID not stored */ 02985 /* here; stored in the normal Unicode charmap instead. */ 02986 return ucmap->cmap.clazz->char_index( &ucmap->cmap, charcode ); 02987 } 02988 02989 if ( nondefOff != 0 ) 02990 return tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 02991 charcode ); 02992 02993 return 0; 02994 } 02995 02996 02997 FT_CALLBACK_DEF( FT_Int ) 02998 tt_cmap14_char_var_isdefault( TT_CMap cmap, 02999 FT_UInt32 charcode, 03000 FT_UInt32 variantSelector ) 03001 { 03002 FT_Byte* p = tt_cmap14_find_variant( cmap->data + 6, variantSelector ); 03003 FT_ULong defOff; 03004 FT_ULong nondefOff; 03005 03006 03007 if ( !p ) 03008 return -1; 03009 03010 defOff = TT_NEXT_ULONG( p ); 03011 nondefOff = TT_NEXT_ULONG( p ); 03012 03013 if ( defOff != 0 && 03014 tt_cmap14_char_map_def_binary( cmap->data + defOff, charcode ) ) 03015 return 1; 03016 03017 if ( nondefOff != 0 && 03018 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 03019 charcode ) != 0 ) 03020 return 0; 03021 03022 return -1; 03023 } 03024 03025 03026 FT_CALLBACK_DEF( FT_UInt32* ) 03027 tt_cmap14_variants( TT_CMap cmap, 03028 FT_Memory memory ) 03029 { 03030 TT_CMap14 cmap14 = (TT_CMap14)cmap; 03031 FT_UInt32 count = cmap14->num_selectors; 03032 FT_Byte* p = cmap->data + 10; 03033 FT_UInt32* result; 03034 FT_UInt32 i; 03035 03036 03037 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 03038 return NULL; 03039 03040 result = cmap14->results; 03041 for ( i = 0; i < count; ++i ) 03042 { 03043 result[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 03044 p += 8; 03045 } 03046 result[i] = 0; 03047 03048 return result; 03049 } 03050 03051 03052 FT_CALLBACK_DEF( FT_UInt32 * ) 03053 tt_cmap14_char_variants( TT_CMap cmap, 03054 FT_Memory memory, 03055 FT_UInt32 charCode ) 03056 { 03057 TT_CMap14 cmap14 = (TT_CMap14) cmap; 03058 FT_UInt32 count = cmap14->num_selectors; 03059 FT_Byte* p = cmap->data + 10; 03060 FT_UInt32* q; 03061 03062 03063 if ( tt_cmap14_ensure( cmap14, ( count + 1 ), memory ) ) 03064 return NULL; 03065 03066 for ( q = cmap14->results; count > 0; --count ) 03067 { 03068 FT_UInt32 varSel = TT_NEXT_UINT24( p ); 03069 FT_ULong defOff = TT_NEXT_ULONG( p ); 03070 FT_ULong nondefOff = TT_NEXT_ULONG( p ); 03071 03072 03073 if ( ( defOff != 0 && 03074 tt_cmap14_char_map_def_binary( cmap->data + defOff, 03075 charCode ) ) || 03076 ( nondefOff != 0 && 03077 tt_cmap14_char_map_nondef_binary( cmap->data + nondefOff, 03078 charCode ) != 0 ) ) 03079 { 03080 q[0] = varSel; 03081 q++; 03082 } 03083 } 03084 q[0] = 0; 03085 03086 return cmap14->results; 03087 } 03088 03089 03090 static FT_UInt 03091 tt_cmap14_def_char_count( FT_Byte *p ) 03092 { 03093 FT_UInt32 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 03094 FT_UInt tot = 0; 03095 03096 03097 p += 3; /* point to the first `cnt' field */ 03098 for ( ; numRanges > 0; numRanges-- ) 03099 { 03100 tot += 1 + p[0]; 03101 p += 4; 03102 } 03103 03104 return tot; 03105 } 03106 03107 03108 static FT_UInt32* 03109 tt_cmap14_get_def_chars( TT_CMap cmap, 03110 FT_Byte* p, 03111 FT_Memory memory ) 03112 { 03113 TT_CMap14 cmap14 = (TT_CMap14) cmap; 03114 FT_UInt32 numRanges; 03115 FT_UInt cnt; 03116 FT_UInt32* q; 03117 03118 03119 cnt = tt_cmap14_def_char_count( p ); 03120 numRanges = (FT_UInt32)TT_NEXT_ULONG( p ); 03121 03122 if ( tt_cmap14_ensure( cmap14, ( cnt + 1 ), memory ) ) 03123 return NULL; 03124 03125 for ( q = cmap14->results; numRanges > 0; --numRanges ) 03126 { 03127 FT_UInt32 uni = (FT_UInt32)TT_NEXT_UINT24( p ); 03128 03129 03130 cnt = FT_NEXT_BYTE( p ) + 1; 03131 do 03132 { 03133 q[0] = uni; 03134 uni += 1; 03135 q += 1; 03136 } while ( --cnt != 0 ); 03137 } 03138 q[0] = 0; 03139 03140 return cmap14->results; 03141 } 03142 03143 03144 static FT_UInt32* 03145 tt_cmap14_get_nondef_chars( TT_CMap cmap, 03146 FT_Byte *p, 03147 FT_Memory memory ) 03148 { 03149 TT_CMap14 cmap14 = (TT_CMap14) cmap; 03150 FT_UInt32 numMappings; 03151 FT_UInt i; 03152 FT_UInt32 *ret; 03153 03154 03155 numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 03156 03157 if ( tt_cmap14_ensure( cmap14, ( numMappings + 1 ), memory ) ) 03158 return NULL; 03159 03160 ret = cmap14->results; 03161 for ( i = 0; i < numMappings; ++i ) 03162 { 03163 ret[i] = (FT_UInt32)TT_NEXT_UINT24( p ); 03164 p += 2; 03165 } 03166 ret[i] = 0; 03167 03168 return ret; 03169 } 03170 03171 03172 FT_CALLBACK_DEF( FT_UInt32 * ) 03173 tt_cmap14_variant_chars( TT_CMap cmap, 03174 FT_Memory memory, 03175 FT_UInt32 variantSelector ) 03176 { 03177 FT_Byte *p = tt_cmap14_find_variant( cmap->data + 6, 03178 variantSelector ); 03179 FT_UInt32 *ret; 03180 FT_Int i; 03181 FT_ULong defOff; 03182 FT_ULong nondefOff; 03183 03184 03185 if ( !p ) 03186 return NULL; 03187 03188 defOff = TT_NEXT_ULONG( p ); 03189 nondefOff = TT_NEXT_ULONG( p ); 03190 03191 if ( defOff == 0 && nondefOff == 0 ) 03192 return NULL; 03193 03194 if ( defOff == 0 ) 03195 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 03196 memory ); 03197 else if ( nondefOff == 0 ) 03198 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 03199 memory ); 03200 else 03201 { 03202 /* Both a default and a non-default glyph set? That's probably not */ 03203 /* good font design, but the spec allows for it... */ 03204 TT_CMap14 cmap14 = (TT_CMap14) cmap; 03205 FT_UInt32 numRanges; 03206 FT_UInt32 numMappings; 03207 FT_UInt32 duni; 03208 FT_UInt32 dcnt; 03209 FT_UInt32 nuni; 03210 FT_Byte* dp; 03211 FT_UInt di, ni, k; 03212 03213 03214 p = cmap->data + nondefOff; 03215 dp = cmap->data + defOff; 03216 03217 numMappings = (FT_UInt32)TT_NEXT_ULONG( p ); 03218 dcnt = tt_cmap14_def_char_count( dp ); 03219 numRanges = (FT_UInt32)TT_NEXT_ULONG( dp ); 03220 03221 if ( numMappings == 0 ) 03222 return tt_cmap14_get_def_chars( cmap, cmap->data + defOff, 03223 memory ); 03224 if ( dcnt == 0 ) 03225 return tt_cmap14_get_nondef_chars( cmap, cmap->data + nondefOff, 03226 memory ); 03227 03228 if ( tt_cmap14_ensure( cmap14, ( dcnt + numMappings + 1 ), memory ) ) 03229 return NULL; 03230 03231 ret = cmap14->results; 03232 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 03233 dcnt = FT_NEXT_BYTE( dp ); 03234 di = 1; 03235 nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 03236 p += 2; 03237 ni = 1; 03238 i = 0; 03239 03240 for ( ;; ) 03241 { 03242 if ( nuni > duni + dcnt ) 03243 { 03244 for ( k = 0; k <= dcnt; ++k ) 03245 ret[i++] = duni + k; 03246 03247 ++di; 03248 03249 if ( di > numRanges ) 03250 break; 03251 03252 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 03253 dcnt = FT_NEXT_BYTE( dp ); 03254 } 03255 else 03256 { 03257 if ( nuni < duni ) 03258 ret[i++] = nuni; 03259 /* If it is within the default range then ignore it -- */ 03260 /* that should not have happened */ 03261 ++ni; 03262 if ( ni > numMappings ) 03263 break; 03264 03265 nuni = (FT_UInt32)TT_NEXT_UINT24( p ); 03266 p += 2; 03267 } 03268 } 03269 03270 if ( ni <= numMappings ) 03271 { 03272 /* If we get here then we have run out of all default ranges. */ 03273 /* We have read one non-default mapping which we haven't stored */ 03274 /* and there may be others that need to be read. */ 03275 ret[i++] = nuni; 03276 while ( ni < numMappings ) 03277 { 03278 ret[i++] = (FT_UInt32)TT_NEXT_UINT24( p ); 03279 p += 2; 03280 ++ni; 03281 } 03282 } 03283 else if ( di <= numRanges ) 03284 { 03285 /* If we get here then we have run out of all non-default */ 03286 /* mappings. We have read one default range which we haven't */ 03287 /* stored and there may be others that need to be read. */ 03288 for ( k = 0; k <= dcnt; ++k ) 03289 ret[i++] = duni + k; 03290 03291 while ( di < numRanges ) 03292 { 03293 duni = (FT_UInt32)TT_NEXT_UINT24( dp ); 03294 dcnt = FT_NEXT_BYTE( dp ); 03295 03296 for ( k = 0; k <= dcnt; ++k ) 03297 ret[i++] = duni + k; 03298 ++di; 03299 } 03300 } 03301 03302 ret[i] = 0; 03303 03304 return ret; 03305 } 03306 } 03307 03308 03309 FT_DEFINE_TT_CMAP(tt_cmap14_class_rec, 03310 sizeof ( TT_CMap14Rec ), 03311 03312 (FT_CMap_InitFunc) tt_cmap14_init, 03313 (FT_CMap_DoneFunc) tt_cmap14_done, 03314 (FT_CMap_CharIndexFunc)tt_cmap14_char_index, 03315 (FT_CMap_CharNextFunc) tt_cmap14_char_next, 03316 03317 /* Format 14 extension functions */ 03318 (FT_CMap_CharVarIndexFunc) tt_cmap14_char_var_index, 03319 (FT_CMap_CharVarIsDefaultFunc)tt_cmap14_char_var_isdefault, 03320 (FT_CMap_VariantListFunc) tt_cmap14_variants, 03321 (FT_CMap_CharVariantListFunc) tt_cmap14_char_variants, 03322 (FT_CMap_VariantCharListFunc) tt_cmap14_variant_chars 03323 , 03324 14, 03325 (TT_CMap_ValidateFunc)tt_cmap14_validate, 03326 (TT_CMap_Info_GetFunc)tt_cmap14_get_info 03327 ) 03328 03329 #endif /* TT_CONFIG_CMAP_FORMAT_14 */ 03330 03331 03332 #ifndef FT_CONFIG_OPTION_PIC 03333 03334 static const TT_CMap_Class tt_cmap_classes[] = 03335 { 03336 #define TTCMAPCITEM(a) &a, 03337 #include "ttcmapc.h" 03338 NULL, 03339 }; 03340 03341 #else /*FT_CONFIG_OPTION_PIC*/ 03342 03343 void FT_Destroy_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class* clazz) 03344 { 03345 FT_Memory memory = library->memory; 03346 if ( clazz ) 03347 FT_FREE( clazz ); 03348 } 03349 03350 FT_Error FT_Create_Class_tt_cmap_classes(FT_Library library, TT_CMap_Class** output_class) 03351 { 03352 TT_CMap_Class* clazz; 03353 TT_CMap_ClassRec* recs; 03354 FT_Error error; 03355 FT_Memory memory = library->memory; 03356 int i = 0; 03357 03358 #define TTCMAPCITEM(a) i++; 03359 #include "ttcmapc.h" 03360 03361 /* allocate enough space for both the pointers +terminator and the class instances */ 03362 if ( FT_ALLOC( clazz, sizeof(*clazz)*(i+1)+sizeof(TT_CMap_ClassRec)*i ) ) 03363 return error; 03364 03365 /* the location of the class instances follows the array of pointers */ 03366 recs = (TT_CMap_ClassRec*) (((char*)clazz)+(sizeof(*clazz)*(i+1))); 03367 i=0; 03368 03369 #undef TTCMAPCITEM 03370 #define TTCMAPCITEM(a) \ 03371 FT_Init_Class_##a(&recs[i]); \ 03372 clazz[i] = &recs[i]; \ 03373 i++; 03374 #include "ttcmapc.h" 03375 03376 clazz[i] = NULL; 03377 03378 *output_class = clazz; 03379 return SFNT_Err_Ok; 03380 } 03381 03382 #endif /*FT_CONFIG_OPTION_PIC*/ 03383 03384 03385 /* parse the `cmap' table and build the corresponding TT_CMap objects */ 03386 /* in the current face */ 03387 /* */ 03388 FT_LOCAL_DEF( FT_Error ) 03389 tt_face_build_cmaps( TT_Face face ) 03390 { 03391 FT_Byte* table = face->cmap_table; 03392 FT_Byte* limit = table + face->cmap_size; 03393 FT_UInt volatile num_cmaps; 03394 FT_Byte* volatile p = table; 03395 FT_Library library = FT_FACE_LIBRARY( face ); 03396 03397 FT_UNUSED( library ); 03398 03399 03400 if ( !p || p + 4 > limit ) 03401 return SFNT_Err_Invalid_Table; 03402 03403 /* only recognize format 0 */ 03404 if ( TT_NEXT_USHORT( p ) != 0 ) 03405 { 03406 p -= 2; 03407 FT_ERROR(( "tt_face_build_cmaps:" 03408 " unsupported `cmap' table format = %d\n", 03409 TT_PEEK_USHORT( p ) )); 03410 return SFNT_Err_Invalid_Table; 03411 } 03412 03413 num_cmaps = TT_NEXT_USHORT( p ); 03414 #ifdef FT_MAX_CHARMAP_CACHEABLE 03415 if ( num_cmaps > FT_MAX_CHARMAP_CACHEABLE ) 03416 FT_ERROR(( "tt_face_build_cmaps: too many cmap subtables(%d) " 03417 "subtable#%d and later are loaded but cannot be searched\n", 03418 num_cmaps, FT_MAX_CHARMAP_CACHEABLE + 1 )); 03419 #endif 03420 03421 for ( ; num_cmaps > 0 && p + 8 <= limit; num_cmaps-- ) 03422 { 03423 FT_CharMapRec charmap; 03424 FT_UInt32 offset; 03425 03426 03427 charmap.platform_id = TT_NEXT_USHORT( p ); 03428 charmap.encoding_id = TT_NEXT_USHORT( p ); 03429 charmap.face = FT_FACE( face ); 03430 charmap.encoding = FT_ENCODING_NONE; /* will be filled later */ 03431 offset = TT_NEXT_ULONG( p ); 03432 03433 if ( offset && offset <= face->cmap_size - 2 ) 03434 { 03435 FT_Byte* volatile cmap = table + offset; 03436 volatile FT_UInt format = TT_PEEK_USHORT( cmap ); 03437 const TT_CMap_Class* volatile pclazz = FT_TT_CMAP_CLASSES_GET; 03438 TT_CMap_Class volatile clazz; 03439 03440 03441 for ( ; *pclazz; pclazz++ ) 03442 { 03443 clazz = *pclazz; 03444 if ( clazz->format == format ) 03445 { 03446 volatile TT_ValidatorRec valid; 03447 volatile FT_Error error = SFNT_Err_Ok; 03448 03449 03450 ft_validator_init( FT_VALIDATOR( &valid ), cmap, limit, 03451 FT_VALIDATE_DEFAULT ); 03452 03453 valid.num_glyphs = (FT_UInt)face->max_profile.numGlyphs; 03454 03455 if ( ft_setjmp( 03456 *((ft_jmp_buf*)&FT_VALIDATOR( &valid )->jump_buffer) ) == 0 ) 03457 { 03458 /* validate this cmap sub-table */ 03459 error = clazz->validate( cmap, FT_VALIDATOR( &valid ) ); 03460 } 03461 03462 if ( valid.validator.error == 0 ) 03463 { 03464 FT_CMap ttcmap; 03465 03466 03467 /* It might make sense to store the single variation selector */ 03468 /* cmap somewhere special. But it would have to be in the */ 03469 /* public FT_FaceRec, and we can't change that. */ 03470 03471 if ( !FT_CMap_New( (FT_CMap_Class)clazz, 03472 cmap, &charmap, &ttcmap ) ) 03473 { 03474 /* it is simpler to directly set `flags' than adding */ 03475 /* a parameter to FT_CMap_New */ 03476 ((TT_CMap)ttcmap)->flags = (FT_Int)error; 03477 } 03478 } 03479 else 03480 { 03481 FT_TRACE0(( "tt_face_build_cmaps:" 03482 " broken cmap sub-table ignored\n" )); 03483 } 03484 break; 03485 } 03486 } 03487 03488 if ( *pclazz == NULL ) 03489 { 03490 FT_TRACE0(( "tt_face_build_cmaps:" 03491 " unsupported cmap sub-table ignored\n" )); 03492 } 03493 } 03494 } 03495 03496 return SFNT_Err_Ok; 03497 } 03498 03499 03500 FT_LOCAL( FT_Error ) 03501 tt_get_cmap_info( FT_CharMap charmap, 03502 TT_CMapInfo *cmap_info ) 03503 { 03504 FT_CMap cmap = (FT_CMap)charmap; 03505 TT_CMap_Class clazz = (TT_CMap_Class)cmap->clazz; 03506 03507 03508 return clazz->get_cmap_info( charmap, cmap_info ); 03509 } 03510 03511 03512 /* END */ Generated on Sun May 27 2012 04:34:01 for ReactOS by
1.7.6.1
|