Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygenttpost.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* ttpost.c */ 00004 /* */ 00005 /* Postcript name table processing for TrueType and OpenType fonts */ 00006 /* (body). */ 00007 /* */ 00008 /* Copyright 1996-2001, 2002, 2003, 2006, 2007, 2008, 2009, 2010 by */ 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 /* The post table is not completely loaded by the core engine. This */ 00022 /* file loads the missing PS glyph names and implements an API to access */ 00023 /* them. */ 00024 /* */ 00025 /*************************************************************************/ 00026 00027 00028 #include <ft2build.h> 00029 #include FT_INTERNAL_DEBUG_H 00030 #include FT_INTERNAL_STREAM_H 00031 #include FT_TRUETYPE_TAGS_H 00032 #include "ttpost.h" 00033 00034 #include "sferrors.h" 00035 00036 00037 /*************************************************************************/ 00038 /* */ 00039 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 00040 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 00041 /* messages during execution. */ 00042 /* */ 00043 #undef FT_COMPONENT 00044 #define FT_COMPONENT trace_ttpost 00045 00046 00047 /* If this configuration macro is defined, we rely on the `PSNames' */ 00048 /* module to grab the glyph names. */ 00049 00050 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 00051 00052 00053 #include FT_SERVICE_POSTSCRIPT_CMAPS_H 00054 00055 #define MAC_NAME( x ) ( (FT_String*)psnames->macintosh_name( x ) ) 00056 00057 00058 #else /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 00059 00060 00061 /* Otherwise, we ignore the `PSNames' module, and provide our own */ 00062 /* table of Mac names. Thus, it is possible to build a version of */ 00063 /* FreeType without the Type 1 driver & PSNames module. */ 00064 00065 #define MAC_NAME( x ) ( (FT_String*)tt_post_default_names[x] ) 00066 00067 /* the 258 default Mac PS glyph names */ 00068 00069 static const FT_String* const tt_post_default_names[258] = 00070 { 00071 /* 0 */ 00072 ".notdef", ".null", "CR", "space", "exclam", 00073 "quotedbl", "numbersign", "dollar", "percent", "ampersand", 00074 /* 10 */ 00075 "quotesingle", "parenleft", "parenright", "asterisk", "plus", 00076 "comma", "hyphen", "period", "slash", "zero", 00077 /* 20 */ 00078 "one", "two", "three", "four", "five", 00079 "six", "seven", "eight", "nine", "colon", 00080 /* 30 */ 00081 "semicolon", "less", "equal", "greater", "question", 00082 "at", "A", "B", "C", "D", 00083 /* 40 */ 00084 "E", "F", "G", "H", "I", 00085 "J", "K", "L", "M", "N", 00086 /* 50 */ 00087 "O", "P", "Q", "R", "S", 00088 "T", "U", "V", "W", "X", 00089 /* 60 */ 00090 "Y", "Z", "bracketleft", "backslash", "bracketright", 00091 "asciicircum", "underscore", "grave", "a", "b", 00092 /* 70 */ 00093 "c", "d", "e", "f", "g", 00094 "h", "i", "j", "k", "l", 00095 /* 80 */ 00096 "m", "n", "o", "p", "q", 00097 "r", "s", "t", "u", "v", 00098 /* 90 */ 00099 "w", "x", "y", "z", "braceleft", 00100 "bar", "braceright", "asciitilde", "Adieresis", "Aring", 00101 /* 100 */ 00102 "Ccedilla", "Eacute", "Ntilde", "Odieresis", "Udieresis", 00103 "aacute", "agrave", "acircumflex", "adieresis", "atilde", 00104 /* 110 */ 00105 "aring", "ccedilla", "eacute", "egrave", "ecircumflex", 00106 "edieresis", "iacute", "igrave", "icircumflex", "idieresis", 00107 /* 120 */ 00108 "ntilde", "oacute", "ograve", "ocircumflex", "odieresis", 00109 "otilde", "uacute", "ugrave", "ucircumflex", "udieresis", 00110 /* 130 */ 00111 "dagger", "degree", "cent", "sterling", "section", 00112 "bullet", "paragraph", "germandbls", "registered", "copyright", 00113 /* 140 */ 00114 "trademark", "acute", "dieresis", "notequal", "AE", 00115 "Oslash", "infinity", "plusminus", "lessequal", "greaterequal", 00116 /* 150 */ 00117 "yen", "mu", "partialdiff", "summation", "product", 00118 "pi", "integral", "ordfeminine", "ordmasculine", "Omega", 00119 /* 160 */ 00120 "ae", "oslash", "questiondown", "exclamdown", "logicalnot", 00121 "radical", "florin", "approxequal", "Delta", "guillemotleft", 00122 /* 170 */ 00123 "guillemotright", "ellipsis", "nbspace", "Agrave", "Atilde", 00124 "Otilde", "OE", "oe", "endash", "emdash", 00125 /* 180 */ 00126 "quotedblleft", "quotedblright", "quoteleft", "quoteright", "divide", 00127 "lozenge", "ydieresis", "Ydieresis", "fraction", "currency", 00128 /* 190 */ 00129 "guilsinglleft", "guilsinglright", "fi", "fl", "daggerdbl", 00130 "periodcentered", "quotesinglbase", "quotedblbase", "perthousand", "Acircumflex", 00131 /* 200 */ 00132 "Ecircumflex", "Aacute", "Edieresis", "Egrave", "Iacute", 00133 "Icircumflex", "Idieresis", "Igrave", "Oacute", "Ocircumflex", 00134 /* 210 */ 00135 "apple", "Ograve", "Uacute", "Ucircumflex", "Ugrave", 00136 "dotlessi", "circumflex", "tilde", "macron", "breve", 00137 /* 220 */ 00138 "dotaccent", "ring", "cedilla", "hungarumlaut", "ogonek", 00139 "caron", "Lslash", "lslash", "Scaron", "scaron", 00140 /* 230 */ 00141 "Zcaron", "zcaron", "brokenbar", "Eth", "eth", 00142 "Yacute", "yacute", "Thorn", "thorn", "minus", 00143 /* 240 */ 00144 "multiply", "onesuperior", "twosuperior", "threesuperior", "onehalf", 00145 "onequarter", "threequarters", "franc", "Gbreve", "gbreve", 00146 /* 250 */ 00147 "Idot", "Scedilla", "scedilla", "Cacute", "cacute", 00148 "Ccaron", "ccaron", "dmacron", 00149 }; 00150 00151 00152 #endif /* FT_CONFIG_OPTION_POSTSCRIPT_NAMES */ 00153 00154 00155 static FT_Error 00156 load_format_20( TT_Face face, 00157 FT_Stream stream, 00158 FT_Long post_limit ) 00159 { 00160 FT_Memory memory = stream->memory; 00161 FT_Error error; 00162 00163 FT_Int num_glyphs; 00164 FT_UShort num_names; 00165 00166 FT_UShort* glyph_indices = 0; 00167 FT_Char** name_strings = 0; 00168 00169 00170 if ( FT_READ_USHORT( num_glyphs ) ) 00171 goto Exit; 00172 00173 /* UNDOCUMENTED! The number of glyphs in this table can be smaller */ 00174 /* than the value in the maxp table (cf. cyberbit.ttf). */ 00175 00176 /* There already exist fonts which have more than 32768 glyph names */ 00177 /* in this table, so the test for this threshold has been dropped. */ 00178 00179 if ( num_glyphs > face->max_profile.numGlyphs ) 00180 { 00181 error = SFNT_Err_Invalid_File_Format; 00182 goto Exit; 00183 } 00184 00185 /* load the indices */ 00186 { 00187 FT_Int n; 00188 00189 00190 if ( FT_NEW_ARRAY ( glyph_indices, num_glyphs ) || 00191 FT_FRAME_ENTER( num_glyphs * 2L ) ) 00192 goto Fail; 00193 00194 for ( n = 0; n < num_glyphs; n++ ) 00195 glyph_indices[n] = FT_GET_USHORT(); 00196 00197 FT_FRAME_EXIT(); 00198 } 00199 00200 /* compute number of names stored in table */ 00201 { 00202 FT_Int n; 00203 00204 00205 num_names = 0; 00206 00207 for ( n = 0; n < num_glyphs; n++ ) 00208 { 00209 FT_Int idx; 00210 00211 00212 idx = glyph_indices[n]; 00213 if ( idx >= 258 ) 00214 { 00215 idx -= 257; 00216 if ( idx > num_names ) 00217 num_names = (FT_UShort)idx; 00218 } 00219 } 00220 } 00221 00222 /* now load the name strings */ 00223 { 00224 FT_UShort n; 00225 00226 00227 if ( FT_NEW_ARRAY( name_strings, num_names ) ) 00228 goto Fail; 00229 00230 for ( n = 0; n < num_names; n++ ) 00231 { 00232 FT_UInt len; 00233 00234 00235 if ( FT_STREAM_POS() >= post_limit ) 00236 break; 00237 else 00238 { 00239 FT_TRACE6(( "load_format_20: %d byte left in post table\n", 00240 post_limit - FT_STREAM_POS() )); 00241 00242 if ( FT_READ_BYTE( len ) ) 00243 goto Fail1; 00244 } 00245 00246 if ( (FT_Int)len > post_limit || 00247 FT_STREAM_POS() > post_limit - (FT_Int)len ) 00248 { 00249 FT_ERROR(( "load_format_20:" 00250 " exceeding string length (%d)," 00251 " truncating at end of post table (%d byte left)\n", 00252 len, post_limit - FT_STREAM_POS() )); 00253 len = FT_MAX( 0, post_limit - FT_STREAM_POS() ); 00254 } 00255 00256 if ( FT_NEW_ARRAY( name_strings[n], len + 1 ) || 00257 FT_STREAM_READ( name_strings[n], len ) ) 00258 goto Fail1; 00259 00260 name_strings[n][len] = '\0'; 00261 } 00262 00263 if ( n < num_names ) 00264 { 00265 FT_ERROR(( "load_format_20:" 00266 " all entries in post table are already parsed," 00267 " using NULL names for gid %d - %d\n", 00268 n, num_names - 1 )); 00269 for ( ; n < num_names; n++ ) 00270 if ( FT_NEW_ARRAY( name_strings[n], 1 ) ) 00271 goto Fail1; 00272 else 00273 name_strings[n][0] = '\0'; 00274 } 00275 } 00276 00277 /* all right, set table fields and exit successfully */ 00278 { 00279 TT_Post_20 table = &face->postscript_names.names.format_20; 00280 00281 00282 table->num_glyphs = (FT_UShort)num_glyphs; 00283 table->num_names = (FT_UShort)num_names; 00284 table->glyph_indices = glyph_indices; 00285 table->glyph_names = name_strings; 00286 } 00287 return SFNT_Err_Ok; 00288 00289 Fail1: 00290 { 00291 FT_UShort n; 00292 00293 00294 for ( n = 0; n < num_names; n++ ) 00295 FT_FREE( name_strings[n] ); 00296 } 00297 00298 Fail: 00299 FT_FREE( name_strings ); 00300 FT_FREE( glyph_indices ); 00301 00302 Exit: 00303 return error; 00304 } 00305 00306 00307 static FT_Error 00308 load_format_25( TT_Face face, 00309 FT_Stream stream, 00310 FT_Long post_limit ) 00311 { 00312 FT_Memory memory = stream->memory; 00313 FT_Error error; 00314 00315 FT_Int num_glyphs; 00316 FT_Char* offset_table = 0; 00317 00318 FT_UNUSED( post_limit ); 00319 00320 00321 /* UNDOCUMENTED! This value appears only in the Apple TT specs. */ 00322 if ( FT_READ_USHORT( num_glyphs ) ) 00323 goto Exit; 00324 00325 /* check the number of glyphs */ 00326 if ( num_glyphs > face->max_profile.numGlyphs || num_glyphs > 258 ) 00327 { 00328 error = SFNT_Err_Invalid_File_Format; 00329 goto Exit; 00330 } 00331 00332 if ( FT_NEW_ARRAY( offset_table, num_glyphs ) || 00333 FT_STREAM_READ( offset_table, num_glyphs ) ) 00334 goto Fail; 00335 00336 /* now check the offset table */ 00337 { 00338 FT_Int n; 00339 00340 00341 for ( n = 0; n < num_glyphs; n++ ) 00342 { 00343 FT_Long idx = (FT_Long)n + offset_table[n]; 00344 00345 00346 if ( idx < 0 || idx > num_glyphs ) 00347 { 00348 error = SFNT_Err_Invalid_File_Format; 00349 goto Fail; 00350 } 00351 } 00352 } 00353 00354 /* OK, set table fields and exit successfully */ 00355 { 00356 TT_Post_25 table = &face->postscript_names.names.format_25; 00357 00358 00359 table->num_glyphs = (FT_UShort)num_glyphs; 00360 table->offsets = offset_table; 00361 } 00362 00363 return SFNT_Err_Ok; 00364 00365 Fail: 00366 FT_FREE( offset_table ); 00367 00368 Exit: 00369 return error; 00370 } 00371 00372 00373 static FT_Error 00374 load_post_names( TT_Face face ) 00375 { 00376 FT_Stream stream; 00377 FT_Error error; 00378 FT_Fixed format; 00379 FT_ULong post_len; 00380 FT_Long post_limit; 00381 00382 00383 /* get a stream for the face's resource */ 00384 stream = face->root.stream; 00385 00386 /* seek to the beginning of the PS names table */ 00387 error = face->goto_table( face, TTAG_post, stream, &post_len ); 00388 if ( error ) 00389 goto Exit; 00390 00391 post_limit = FT_STREAM_POS() + post_len; 00392 00393 format = face->postscript.FormatType; 00394 00395 /* go to beginning of subtable */ 00396 if ( FT_STREAM_SKIP( 32 ) ) 00397 goto Exit; 00398 00399 /* now read postscript table */ 00400 if ( format == 0x00020000L ) 00401 error = load_format_20( face, stream, post_limit ); 00402 else if ( format == 0x00028000L ) 00403 error = load_format_25( face, stream, post_limit ); 00404 else 00405 error = SFNT_Err_Invalid_File_Format; 00406 00407 face->postscript_names.loaded = 1; 00408 00409 Exit: 00410 return error; 00411 } 00412 00413 00414 FT_LOCAL_DEF( void ) 00415 tt_face_free_ps_names( TT_Face face ) 00416 { 00417 FT_Memory memory = face->root.memory; 00418 TT_Post_Names names = &face->postscript_names; 00419 FT_Fixed format; 00420 00421 00422 if ( names->loaded ) 00423 { 00424 format = face->postscript.FormatType; 00425 00426 if ( format == 0x00020000L ) 00427 { 00428 TT_Post_20 table = &names->names.format_20; 00429 FT_UShort n; 00430 00431 00432 FT_FREE( table->glyph_indices ); 00433 table->num_glyphs = 0; 00434 00435 for ( n = 0; n < table->num_names; n++ ) 00436 FT_FREE( table->glyph_names[n] ); 00437 00438 FT_FREE( table->glyph_names ); 00439 table->num_names = 0; 00440 } 00441 else if ( format == 0x00028000L ) 00442 { 00443 TT_Post_25 table = &names->names.format_25; 00444 00445 00446 FT_FREE( table->offsets ); 00447 table->num_glyphs = 0; 00448 } 00449 } 00450 names->loaded = 0; 00451 } 00452 00453 00454 /*************************************************************************/ 00455 /* */ 00456 /* <Function> */ 00457 /* tt_face_get_ps_name */ 00458 /* */ 00459 /* <Description> */ 00460 /* Get the PostScript glyph name of a glyph. */ 00461 /* */ 00462 /* <Input> */ 00463 /* face :: A handle to the parent face. */ 00464 /* */ 00465 /* idx :: The glyph index. */ 00466 /* */ 00467 /* <InOut> */ 00468 /* PSname :: The address of a string pointer. Will be NULL in case */ 00469 /* of error, otherwise it is a pointer to the glyph name. */ 00470 /* */ 00471 /* You must not modify the returned string! */ 00472 /* */ 00473 /* <Output> */ 00474 /* FreeType error code. 0 means success. */ 00475 /* */ 00476 FT_LOCAL_DEF( FT_Error ) 00477 tt_face_get_ps_name( TT_Face face, 00478 FT_UInt idx, 00479 FT_String** PSname ) 00480 { 00481 FT_Error error; 00482 TT_Post_Names names; 00483 FT_Fixed format; 00484 00485 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 00486 FT_Service_PsCMaps psnames; 00487 #endif 00488 00489 00490 if ( !face ) 00491 return SFNT_Err_Invalid_Face_Handle; 00492 00493 if ( idx >= (FT_UInt)face->max_profile.numGlyphs ) 00494 return SFNT_Err_Invalid_Glyph_Index; 00495 00496 #ifdef FT_CONFIG_OPTION_POSTSCRIPT_NAMES 00497 psnames = (FT_Service_PsCMaps)face->psnames; 00498 if ( !psnames ) 00499 return SFNT_Err_Unimplemented_Feature; 00500 #endif 00501 00502 names = &face->postscript_names; 00503 00504 /* `.notdef' by default */ 00505 *PSname = MAC_NAME( 0 ); 00506 00507 format = face->postscript.FormatType; 00508 00509 if ( format == 0x00010000L ) 00510 { 00511 if ( idx < 258 ) /* paranoid checking */ 00512 *PSname = MAC_NAME( idx ); 00513 } 00514 else if ( format == 0x00020000L ) 00515 { 00516 TT_Post_20 table = &names->names.format_20; 00517 00518 00519 if ( !names->loaded ) 00520 { 00521 error = load_post_names( face ); 00522 if ( error ) 00523 goto End; 00524 } 00525 00526 if ( idx < (FT_UInt)table->num_glyphs ) 00527 { 00528 FT_UShort name_index = table->glyph_indices[idx]; 00529 00530 00531 if ( name_index < 258 ) 00532 *PSname = MAC_NAME( name_index ); 00533 else 00534 *PSname = (FT_String*)table->glyph_names[name_index - 258]; 00535 } 00536 } 00537 else if ( format == 0x00028000L ) 00538 { 00539 TT_Post_25 table = &names->names.format_25; 00540 00541 00542 if ( !names->loaded ) 00543 { 00544 error = load_post_names( face ); 00545 if ( error ) 00546 goto End; 00547 } 00548 00549 if ( idx < (FT_UInt)table->num_glyphs ) /* paranoid checking */ 00550 { 00551 idx += table->offsets[idx]; 00552 *PSname = MAC_NAME( idx ); 00553 } 00554 } 00555 00556 /* nothing to do for format == 0x00030000L */ 00557 00558 End: 00559 return SFNT_Err_Ok; 00560 } 00561 00562 00563 /* END */ Generated on Sun May 27 2012 04:34:02 for ReactOS by
1.7.6.1
|