Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygensfobjs.c
Go to the documentation of this file.
00001 /***************************************************************************/ 00002 /* */ 00003 /* sfobjs.c */ 00004 /* */ 00005 /* SFNT object management (base). */ 00006 /* */ 00007 /* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2008, 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 "sfobjs.h" 00021 #include "ttload.h" 00022 #include "ttcmap.h" 00023 #include "ttkern.h" 00024 #include FT_INTERNAL_SFNT_H 00025 #include FT_INTERNAL_DEBUG_H 00026 #include FT_TRUETYPE_IDS_H 00027 #include FT_TRUETYPE_TAGS_H 00028 #include FT_SERVICE_POSTSCRIPT_CMAPS_H 00029 #include FT_SFNT_NAMES_H 00030 #include "sferrors.h" 00031 00032 #ifdef TT_CONFIG_OPTION_BDF 00033 #include "ttbdf.h" 00034 #endif 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_sfobjs 00045 00046 00047 00048 /* convert a UTF-16 name entry to ASCII */ 00049 static FT_String* 00050 tt_name_entry_ascii_from_utf16( TT_NameEntry entry, 00051 FT_Memory memory ) 00052 { 00053 FT_String* string = NULL; 00054 FT_UInt len, code, n; 00055 FT_Byte* read = (FT_Byte*)entry->string; 00056 FT_Error error; 00057 00058 00059 len = (FT_UInt)entry->stringLength / 2; 00060 00061 if ( FT_NEW_ARRAY( string, len + 1 ) ) 00062 return NULL; 00063 00064 for ( n = 0; n < len; n++ ) 00065 { 00066 code = FT_NEXT_USHORT( read ); 00067 if ( code < 32 || code > 127 ) 00068 code = '?'; 00069 00070 string[n] = (char)code; 00071 } 00072 00073 string[len] = 0; 00074 00075 return string; 00076 } 00077 00078 00079 /* convert an Apple Roman or symbol name entry to ASCII */ 00080 static FT_String* 00081 tt_name_entry_ascii_from_other( TT_NameEntry entry, 00082 FT_Memory memory ) 00083 { 00084 FT_String* string = NULL; 00085 FT_UInt len, code, n; 00086 FT_Byte* read = (FT_Byte*)entry->string; 00087 FT_Error error; 00088 00089 00090 len = (FT_UInt)entry->stringLength; 00091 00092 if ( FT_NEW_ARRAY( string, len + 1 ) ) 00093 return NULL; 00094 00095 for ( n = 0; n < len; n++ ) 00096 { 00097 code = *read++; 00098 if ( code < 32 || code > 127 ) 00099 code = '?'; 00100 00101 string[n] = (char)code; 00102 } 00103 00104 string[len] = 0; 00105 00106 return string; 00107 } 00108 00109 00110 typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, 00111 FT_Memory memory ); 00112 00113 00114 /*************************************************************************/ 00115 /* */ 00116 /* <Function> */ 00117 /* tt_face_get_name */ 00118 /* */ 00119 /* <Description> */ 00120 /* Returns a given ENGLISH name record in ASCII. */ 00121 /* */ 00122 /* <Input> */ 00123 /* face :: A handle to the source face object. */ 00124 /* */ 00125 /* nameid :: The name id of the name record to return. */ 00126 /* */ 00127 /* <InOut> */ 00128 /* name :: The address of a string pointer. NULL if no name is */ 00129 /* present. */ 00130 /* */ 00131 /* <Return> */ 00132 /* FreeType error code. 0 means success. */ 00133 /* */ 00134 static FT_Error 00135 tt_face_get_name( TT_Face face, 00136 FT_UShort nameid, 00137 FT_String** name ) 00138 { 00139 FT_Memory memory = face->root.memory; 00140 FT_Error error = SFNT_Err_Ok; 00141 FT_String* result = NULL; 00142 FT_UShort n; 00143 TT_NameEntryRec* rec; 00144 FT_Int found_apple = -1; 00145 FT_Int found_apple_roman = -1; 00146 FT_Int found_apple_english = -1; 00147 FT_Int found_win = -1; 00148 FT_Int found_unicode = -1; 00149 00150 FT_Bool is_english = 0; 00151 00152 TT_NameEntry_ConvertFunc convert; 00153 00154 00155 FT_ASSERT( name ); 00156 00157 rec = face->name_table.names; 00158 for ( n = 0; n < face->num_names; n++, rec++ ) 00159 { 00160 /* According to the OpenType 1.3 specification, only Microsoft or */ 00161 /* Apple platform IDs might be used in the `name' table. The */ 00162 /* `Unicode' platform is reserved for the `cmap' table, and the */ 00163 /* `ISO' one is deprecated. */ 00164 /* */ 00165 /* However, the Apple TrueType specification doesn't say the same */ 00166 /* thing and goes to suggest that all Unicode `name' table entries */ 00167 /* should be coded in UTF-16 (in big-endian format I suppose). */ 00168 /* */ 00169 if ( rec->nameID == nameid && rec->stringLength > 0 ) 00170 { 00171 switch ( rec->platformID ) 00172 { 00173 case TT_PLATFORM_APPLE_UNICODE: 00174 case TT_PLATFORM_ISO: 00175 /* there is `languageID' to check there. We should use this */ 00176 /* field only as a last solution when nothing else is */ 00177 /* available. */ 00178 /* */ 00179 found_unicode = n; 00180 break; 00181 00182 case TT_PLATFORM_MACINTOSH: 00183 /* This is a bit special because some fonts will use either */ 00184 /* an English language id, or a Roman encoding id, to indicate */ 00185 /* the English version of its font name. */ 00186 /* */ 00187 if ( rec->languageID == TT_MAC_LANGID_ENGLISH ) 00188 found_apple_english = n; 00189 else if ( rec->encodingID == TT_MAC_ID_ROMAN ) 00190 found_apple_roman = n; 00191 break; 00192 00193 case TT_PLATFORM_MICROSOFT: 00194 /* we only take a non-English name when there is nothing */ 00195 /* else available in the font */ 00196 /* */ 00197 if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 ) 00198 { 00199 switch ( rec->encodingID ) 00200 { 00201 case TT_MS_ID_SYMBOL_CS: 00202 case TT_MS_ID_UNICODE_CS: 00203 case TT_MS_ID_UCS_4: 00204 is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 ); 00205 found_win = n; 00206 break; 00207 00208 default: 00209 ; 00210 } 00211 } 00212 break; 00213 00214 default: 00215 ; 00216 } 00217 } 00218 } 00219 00220 found_apple = found_apple_roman; 00221 if ( found_apple_english >= 0 ) 00222 found_apple = found_apple_english; 00223 00224 /* some fonts contain invalid Unicode or Macintosh formatted entries; */ 00225 /* we will thus favor names encoded in Windows formats if available */ 00226 /* (provided it is an English name) */ 00227 /* */ 00228 convert = NULL; 00229 if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) ) 00230 { 00231 rec = face->name_table.names + found_win; 00232 switch ( rec->encodingID ) 00233 { 00234 /* all Unicode strings are encoded using UTF-16BE */ 00235 case TT_MS_ID_UNICODE_CS: 00236 case TT_MS_ID_SYMBOL_CS: 00237 convert = tt_name_entry_ascii_from_utf16; 00238 break; 00239 00240 case TT_MS_ID_UCS_4: 00241 /* Apparently, if this value is found in a name table entry, it is */ 00242 /* documented as `full Unicode repertoire'. Experience with the */ 00243 /* MsGothic font shipped with Windows Vista shows that this really */ 00244 /* means UTF-16 encoded names (UCS-4 values are only used within */ 00245 /* charmaps). */ 00246 convert = tt_name_entry_ascii_from_utf16; 00247 break; 00248 00249 default: 00250 ; 00251 } 00252 } 00253 else if ( found_apple >= 0 ) 00254 { 00255 rec = face->name_table.names + found_apple; 00256 convert = tt_name_entry_ascii_from_other; 00257 } 00258 else if ( found_unicode >= 0 ) 00259 { 00260 rec = face->name_table.names + found_unicode; 00261 convert = tt_name_entry_ascii_from_utf16; 00262 } 00263 00264 if ( rec && convert ) 00265 { 00266 if ( rec->string == NULL ) 00267 { 00268 FT_Stream stream = face->name_table.stream; 00269 00270 00271 if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) || 00272 FT_STREAM_SEEK( rec->stringOffset ) || 00273 FT_STREAM_READ( rec->string, rec->stringLength ) ) 00274 { 00275 FT_FREE( rec->string ); 00276 rec->stringLength = 0; 00277 result = NULL; 00278 goto Exit; 00279 } 00280 } 00281 00282 result = convert( rec, memory ); 00283 } 00284 00285 Exit: 00286 *name = result; 00287 return error; 00288 } 00289 00290 00291 static FT_Encoding 00292 sfnt_find_encoding( int platform_id, 00293 int encoding_id ) 00294 { 00295 typedef struct TEncoding_ 00296 { 00297 int platform_id; 00298 int encoding_id; 00299 FT_Encoding encoding; 00300 00301 } TEncoding; 00302 00303 static 00304 const TEncoding tt_encodings[] = 00305 { 00306 { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE }, 00307 00308 { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE }, 00309 00310 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN }, 00311 00312 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL }, 00313 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, 00314 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, 00315 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, 00316 { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 }, 00317 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, 00318 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, 00319 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } 00320 }; 00321 00322 const TEncoding *cur, *limit; 00323 00324 00325 cur = tt_encodings; 00326 limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); 00327 00328 for ( ; cur < limit; cur++ ) 00329 { 00330 if ( cur->platform_id == platform_id ) 00331 { 00332 if ( cur->encoding_id == encoding_id || 00333 cur->encoding_id == -1 ) 00334 return cur->encoding; 00335 } 00336 } 00337 00338 return FT_ENCODING_NONE; 00339 } 00340 00341 00342 /* Fill in face->ttc_header. If the font is not a TTC, it is */ 00343 /* synthesized into a TTC with one offset table. */ 00344 static FT_Error 00345 sfnt_open_font( FT_Stream stream, 00346 TT_Face face ) 00347 { 00348 FT_Memory memory = stream->memory; 00349 FT_Error error; 00350 FT_ULong tag, offset; 00351 00352 static const FT_Frame_Field ttc_header_fields[] = 00353 { 00354 #undef FT_STRUCTURE 00355 #define FT_STRUCTURE TTC_HeaderRec 00356 00357 FT_FRAME_START( 8 ), 00358 FT_FRAME_LONG( version ), 00359 FT_FRAME_LONG( count ), 00360 FT_FRAME_END 00361 }; 00362 00363 00364 face->ttc_header.tag = 0; 00365 face->ttc_header.version = 0; 00366 face->ttc_header.count = 0; 00367 00368 offset = FT_STREAM_POS(); 00369 00370 if ( FT_READ_ULONG( tag ) ) 00371 return error; 00372 00373 if ( tag != 0x00010000UL && 00374 tag != TTAG_ttcf && 00375 tag != TTAG_OTTO && 00376 tag != TTAG_true && 00377 tag != TTAG_typ1 && 00378 tag != 0x00020000UL ) 00379 return SFNT_Err_Unknown_File_Format; 00380 00381 face->ttc_header.tag = TTAG_ttcf; 00382 00383 if ( tag == TTAG_ttcf ) 00384 { 00385 FT_Int n; 00386 00387 00388 FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); 00389 00390 if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) 00391 return error; 00392 00393 /* now read the offsets of each font in the file */ 00394 if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) 00395 return error; 00396 00397 if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) 00398 return error; 00399 00400 for ( n = 0; n < face->ttc_header.count; n++ ) 00401 face->ttc_header.offsets[n] = FT_GET_ULONG(); 00402 00403 FT_FRAME_EXIT(); 00404 } 00405 else 00406 { 00407 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); 00408 00409 face->ttc_header.version = 1 << 16; 00410 face->ttc_header.count = 1; 00411 00412 if ( FT_NEW( face->ttc_header.offsets ) ) 00413 return error; 00414 00415 face->ttc_header.offsets[0] = offset; 00416 } 00417 00418 return error; 00419 } 00420 00421 00422 FT_LOCAL_DEF( FT_Error ) 00423 sfnt_init_face( FT_Stream stream, 00424 TT_Face face, 00425 FT_Int face_index, 00426 FT_Int num_params, 00427 FT_Parameter* params ) 00428 { 00429 FT_Error error; 00430 FT_Library library = face->root.driver->root.library; 00431 SFNT_Service sfnt; 00432 00433 00434 /* for now, parameters are unused */ 00435 FT_UNUSED( num_params ); 00436 FT_UNUSED( params ); 00437 00438 00439 sfnt = (SFNT_Service)face->sfnt; 00440 if ( !sfnt ) 00441 { 00442 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); 00443 if ( !sfnt ) 00444 return SFNT_Err_Invalid_File_Format; 00445 00446 face->sfnt = sfnt; 00447 face->goto_table = sfnt->goto_table; 00448 } 00449 00450 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); 00451 00452 error = sfnt_open_font( stream, face ); 00453 if ( error ) 00454 return error; 00455 00456 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index )); 00457 00458 if ( face_index < 0 ) 00459 face_index = 0; 00460 00461 if ( face_index >= face->ttc_header.count ) 00462 return SFNT_Err_Invalid_Argument; 00463 00464 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) 00465 return error; 00466 00467 /* check that we have a valid TrueType file */ 00468 error = sfnt->load_font_dir( face, stream ); 00469 if ( error ) 00470 return error; 00471 00472 face->root.num_faces = face->ttc_header.count; 00473 face->root.face_index = face_index; 00474 00475 return error; 00476 } 00477 00478 00479 #define LOAD_( x ) \ 00480 do { \ 00481 FT_TRACE2(( "`" #x "' " )); \ 00482 FT_TRACE3(( "-->\n" )); \ 00483 \ 00484 error = sfnt->load_##x( face, stream ); \ 00485 \ 00486 FT_TRACE2(( "%s\n", ( !error ) \ 00487 ? "loaded" \ 00488 : ( error == SFNT_Err_Table_Missing ) \ 00489 ? "missing" \ 00490 : "failed to load" )); \ 00491 FT_TRACE3(( "\n" )); \ 00492 } while ( 0 ) 00493 00494 #define LOADM_( x, vertical ) \ 00495 do { \ 00496 FT_TRACE2(( "`%s" #x "' ", \ 00497 vertical ? "vertical " : "" )); \ 00498 FT_TRACE3(( "-->\n" )); \ 00499 \ 00500 error = sfnt->load_##x( face, stream, vertical ); \ 00501 \ 00502 FT_TRACE2(( "%s\n", ( !error ) \ 00503 ? "loaded" \ 00504 : ( error == SFNT_Err_Table_Missing ) \ 00505 ? "missing" \ 00506 : "failed to load" )); \ 00507 FT_TRACE3(( "\n" )); \ 00508 } while ( 0 ) 00509 00510 #define GET_NAME( id, field ) \ 00511 do { \ 00512 error = tt_face_get_name( face, TT_NAME_ID_##id, field ); \ 00513 if ( error ) \ 00514 goto Exit; \ 00515 } while ( 0 ) 00516 00517 00518 FT_LOCAL_DEF( FT_Error ) 00519 sfnt_load_face( FT_Stream stream, 00520 TT_Face face, 00521 FT_Int face_index, 00522 FT_Int num_params, 00523 FT_Parameter* params ) 00524 { 00525 FT_Error error; 00526 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 00527 FT_Error psnames_error; 00528 #endif 00529 FT_Bool has_outline; 00530 FT_Bool is_apple_sbit; 00531 FT_Bool ignore_preferred_family = FALSE; 00532 FT_Bool ignore_preferred_subfamily = FALSE; 00533 00534 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 00535 00536 FT_UNUSED( face_index ); 00537 00538 /* Check parameters */ 00539 00540 { 00541 FT_Int i; 00542 00543 00544 for ( i = 0; i < num_params; i++ ) 00545 { 00546 if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY ) 00547 ignore_preferred_family = TRUE; 00548 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY ) 00549 ignore_preferred_subfamily = TRUE; 00550 } 00551 } 00552 00553 /* Load tables */ 00554 00555 /* We now support two SFNT-based bitmapped font formats. They */ 00556 /* are recognized easily as they do not include a `glyf' */ 00557 /* table. */ 00558 /* */ 00559 /* The first format comes from Apple, and uses a table named */ 00560 /* `bhed' instead of `head' to store the font header (using */ 00561 /* the same format). It also doesn't include horizontal and */ 00562 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ 00563 /* missing). */ 00564 /* */ 00565 /* The other format comes from Microsoft, and is used with */ 00566 /* WinCE/PocketPC. It looks like a standard TTF, except that */ 00567 /* it doesn't contain outlines. */ 00568 /* */ 00569 00570 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face )); 00571 00572 /* do we have outlines in there? */ 00573 #ifdef FT_CONFIG_OPTION_INCREMENTAL 00574 has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || 00575 tt_face_lookup_table( face, TTAG_glyf ) != 0 || 00576 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); 00577 #else 00578 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || 00579 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); 00580 #endif 00581 00582 is_apple_sbit = 0; 00583 00584 /* if this font doesn't contain outlines, we try to load */ 00585 /* a `bhed' table */ 00586 if ( !has_outline && sfnt->load_bhed ) 00587 { 00588 LOAD_( bhed ); 00589 is_apple_sbit = FT_BOOL( !error ); 00590 } 00591 00592 /* load the font header (`head' table) if this isn't an Apple */ 00593 /* sbit font file */ 00594 if ( !is_apple_sbit ) 00595 { 00596 LOAD_( head ); 00597 if ( error ) 00598 goto Exit; 00599 } 00600 00601 if ( face->header.Units_Per_EM == 0 ) 00602 { 00603 error = SFNT_Err_Invalid_Table; 00604 00605 goto Exit; 00606 } 00607 00608 /* the following tables are often not present in embedded TrueType */ 00609 /* fonts within PDF documents, so don't check for them. */ 00610 LOAD_( maxp ); 00611 LOAD_( cmap ); 00612 00613 /* the following tables are optional in PCL fonts -- */ 00614 /* don't check for errors */ 00615 LOAD_( name ); 00616 LOAD_( post ); 00617 00618 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 00619 psnames_error = error; 00620 #endif 00621 00622 /* do not load the metrics headers and tables if this is an Apple */ 00623 /* sbit font file */ 00624 if ( !is_apple_sbit ) 00625 { 00626 /* load the `hhea' and `hmtx' tables */ 00627 LOADM_( hhea, 0 ); 00628 if ( !error ) 00629 { 00630 LOADM_( hmtx, 0 ); 00631 if ( error == SFNT_Err_Table_Missing ) 00632 { 00633 error = SFNT_Err_Hmtx_Table_Missing; 00634 00635 #ifdef FT_CONFIG_OPTION_INCREMENTAL 00636 /* If this is an incrementally loaded font and there are */ 00637 /* overriding metrics, tolerate a missing `hmtx' table. */ 00638 if ( face->root.internal->incremental_interface && 00639 face->root.internal->incremental_interface->funcs-> 00640 get_glyph_metrics ) 00641 { 00642 face->horizontal.number_Of_HMetrics = 0; 00643 error = SFNT_Err_Ok; 00644 } 00645 #endif 00646 } 00647 } 00648 else if ( error == SFNT_Err_Table_Missing ) 00649 { 00650 /* No `hhea' table necessary for SFNT Mac fonts. */ 00651 if ( face->format_tag == TTAG_true ) 00652 { 00653 FT_TRACE2(( "This is an SFNT Mac font.\n" )); 00654 has_outline = 0; 00655 error = SFNT_Err_Ok; 00656 } 00657 else 00658 { 00659 error = SFNT_Err_Horiz_Header_Missing; 00660 00661 #ifdef FT_CONFIG_OPTION_INCREMENTAL 00662 /* If this is an incrementally loaded font and there are */ 00663 /* overriding metrics, tolerate a missing `hhea' table. */ 00664 if ( face->root.internal->incremental_interface && 00665 face->root.internal->incremental_interface->funcs-> 00666 get_glyph_metrics ) 00667 { 00668 face->horizontal.number_Of_HMetrics = 0; 00669 error = SFNT_Err_Ok; 00670 } 00671 #endif 00672 00673 } 00674 } 00675 00676 if ( error ) 00677 goto Exit; 00678 00679 /* try to load the `vhea' and `vmtx' tables */ 00680 LOADM_( hhea, 1 ); 00681 if ( !error ) 00682 { 00683 LOADM_( hmtx, 1 ); 00684 if ( !error ) 00685 face->vertical_info = 1; 00686 } 00687 00688 if ( error && error != SFNT_Err_Table_Missing ) 00689 goto Exit; 00690 00691 LOAD_( os2 ); 00692 if ( error ) 00693 { 00694 /* we treat the table as missing if there are any errors */ 00695 face->os2.version = 0xFFFFU; 00696 } 00697 } 00698 00699 /* the optional tables */ 00700 00701 /* embedded bitmap support */ 00702 if ( sfnt->load_eblc ) 00703 { 00704 LOAD_( eblc ); 00705 if ( error ) 00706 { 00707 /* a font which contains neither bitmaps nor outlines is */ 00708 /* still valid (although rather useless in most cases); */ 00709 /* however, you can find such stripped fonts in PDFs */ 00710 if ( error == SFNT_Err_Table_Missing ) 00711 error = SFNT_Err_Ok; 00712 else 00713 goto Exit; 00714 } 00715 } 00716 00717 LOAD_( pclt ); 00718 if ( error ) 00719 { 00720 if ( error != SFNT_Err_Table_Missing ) 00721 goto Exit; 00722 00723 face->pclt.Version = 0; 00724 } 00725 00726 /* consider the kerning and gasp tables as optional */ 00727 LOAD_( gasp ); 00728 LOAD_( kern ); 00729 00730 face->root.num_glyphs = face->max_profile.numGlyphs; 00731 00732 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ 00733 /* a WWS-only font face. `WWS' stands for `weight', width', and */ 00734 /* `slope', a term used by Microsoft's Windows Presentation */ 00735 /* Foundation (WPF). This flag has been introduced in version */ 00736 /* 1.5 of the OpenType specification (May 2008). */ 00737 00738 face->root.family_name = NULL; 00739 face->root.style_name = NULL; 00740 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) 00741 { 00742 if ( !ignore_preferred_family ) 00743 GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); 00744 if ( !face->root.family_name ) 00745 GET_NAME( FONT_FAMILY, &face->root.family_name ); 00746 00747 if ( !ignore_preferred_subfamily ) 00748 GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); 00749 if ( !face->root.style_name ) 00750 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 00751 } 00752 else 00753 { 00754 GET_NAME( WWS_FAMILY, &face->root.family_name ); 00755 if ( !face->root.family_name && !ignore_preferred_family ) 00756 GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); 00757 if ( !face->root.family_name ) 00758 GET_NAME( FONT_FAMILY, &face->root.family_name ); 00759 00760 GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); 00761 if ( !face->root.style_name && !ignore_preferred_subfamily ) 00762 GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); 00763 if ( !face->root.style_name ) 00764 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); 00765 } 00766 00767 /* now set up root fields */ 00768 { 00769 FT_Face root = &face->root; 00770 FT_Long flags = root->face_flags; 00771 00772 00773 /*********************************************************************/ 00774 /* */ 00775 /* Compute face flags. */ 00776 /* */ 00777 if ( has_outline == TRUE ) 00778 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ 00779 00780 /* The sfnt driver only supports bitmap fonts natively, thus we */ 00781 /* don't set FT_FACE_FLAG_HINTER. */ 00782 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ 00783 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ 00784 00785 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES 00786 if ( psnames_error == SFNT_Err_Ok && 00787 face->postscript.FormatType != 0x00030000L ) 00788 flags |= FT_FACE_FLAG_GLYPH_NAMES; 00789 #endif 00790 00791 /* fixed width font? */ 00792 if ( face->postscript.isFixedPitch ) 00793 flags |= FT_FACE_FLAG_FIXED_WIDTH; 00794 00795 /* vertical information? */ 00796 if ( face->vertical_info ) 00797 flags |= FT_FACE_FLAG_VERTICAL; 00798 00799 /* kerning available ? */ 00800 if ( TT_FACE_HAS_KERNING( face ) ) 00801 flags |= FT_FACE_FLAG_KERNING; 00802 00803 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 00804 /* Don't bother to load the tables unless somebody asks for them. */ 00805 /* No need to do work which will (probably) not be used. */ 00806 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && 00807 tt_face_lookup_table( face, TTAG_fvar ) != 0 && 00808 tt_face_lookup_table( face, TTAG_gvar ) != 0 ) 00809 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 00810 #endif 00811 00812 root->face_flags = flags; 00813 00814 /*********************************************************************/ 00815 /* */ 00816 /* Compute style flags. */ 00817 /* */ 00818 00819 flags = 0; 00820 if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) 00821 { 00822 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ 00823 /* indicates an oblique font face. This flag has been */ 00824 /* introduced in version 1.5 of the OpenType specification. */ 00825 00826 if ( face->os2.fsSelection & 512 ) /* bit 9 */ 00827 flags |= FT_STYLE_FLAG_ITALIC; 00828 else if ( face->os2.fsSelection & 1 ) /* bit 0 */ 00829 flags |= FT_STYLE_FLAG_ITALIC; 00830 00831 if ( face->os2.fsSelection & 32 ) /* bit 5 */ 00832 flags |= FT_STYLE_FLAG_BOLD; 00833 } 00834 else 00835 { 00836 /* this is an old Mac font, use the header field */ 00837 00838 if ( face->header.Mac_Style & 1 ) 00839 flags |= FT_STYLE_FLAG_BOLD; 00840 00841 if ( face->header.Mac_Style & 2 ) 00842 flags |= FT_STYLE_FLAG_ITALIC; 00843 } 00844 00845 root->style_flags = flags; 00846 00847 /*********************************************************************/ 00848 /* */ 00849 /* Polish the charmaps. */ 00850 /* */ 00851 /* Try to set the charmap encoding according to the platform & */ 00852 /* encoding ID of each charmap. */ 00853 /* */ 00854 00855 tt_face_build_cmaps( face ); /* ignore errors */ 00856 00857 00858 /* set the encoding fields */ 00859 { 00860 FT_Int m; 00861 00862 00863 for ( m = 0; m < root->num_charmaps; m++ ) 00864 { 00865 FT_CharMap charmap = root->charmaps[m]; 00866 00867 00868 charmap->encoding = sfnt_find_encoding( charmap->platform_id, 00869 charmap->encoding_id ); 00870 00871 #if 0 00872 if ( root->charmap == NULL && 00873 charmap->encoding == FT_ENCODING_UNICODE ) 00874 { 00875 /* set 'root->charmap' to the first Unicode encoding we find */ 00876 root->charmap = charmap; 00877 } 00878 #endif 00879 } 00880 } 00881 00882 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 00883 00884 /* 00885 * Now allocate the root array of FT_Bitmap_Size records and 00886 * populate them. Unfortunately, it isn't possible to indicate bit 00887 * depths in the FT_Bitmap_Size record. This is a design error. 00888 */ 00889 { 00890 FT_UInt i, count; 00891 00892 00893 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS 00894 count = face->sbit_num_strikes; 00895 #else 00896 count = (FT_UInt)face->num_sbit_strikes; 00897 #endif 00898 00899 if ( count > 0 ) 00900 { 00901 FT_Memory memory = face->root.stream->memory; 00902 FT_UShort em_size = face->header.Units_Per_EM; 00903 FT_Short avgwidth = face->os2.xAvgCharWidth; 00904 FT_Size_Metrics metrics; 00905 00906 00907 if ( em_size == 0 || face->os2.version == 0xFFFFU ) 00908 { 00909 avgwidth = 0; 00910 em_size = 1; 00911 } 00912 00913 if ( FT_NEW_ARRAY( root->available_sizes, count ) ) 00914 goto Exit; 00915 00916 for ( i = 0; i < count; i++ ) 00917 { 00918 FT_Bitmap_Size* bsize = root->available_sizes + i; 00919 00920 00921 error = sfnt->load_strike_metrics( face, i, &metrics ); 00922 if ( error ) 00923 goto Exit; 00924 00925 bsize->height = (FT_Short)( metrics.height >> 6 ); 00926 bsize->width = (FT_Short)( 00927 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); 00928 00929 bsize->x_ppem = metrics.x_ppem << 6; 00930 bsize->y_ppem = metrics.y_ppem << 6; 00931 00932 /* assume 72dpi */ 00933 bsize->size = metrics.y_ppem << 6; 00934 } 00935 00936 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; 00937 root->num_fixed_sizes = (FT_Int)count; 00938 } 00939 } 00940 00941 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 00942 00943 /* a font with no bitmaps and no outlines is scalable; */ 00944 /* it has only empty glyphs then */ 00945 if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) 00946 root->face_flags |= FT_FACE_FLAG_SCALABLE; 00947 00948 00949 /*********************************************************************/ 00950 /* */ 00951 /* Set up metrics. */ 00952 /* */ 00953 if ( FT_IS_SCALABLE( root ) ) 00954 { 00955 /* XXX What about if outline header is missing */ 00956 /* (e.g. sfnt wrapped bitmap)? */ 00957 root->bbox.xMin = face->header.xMin; 00958 root->bbox.yMin = face->header.yMin; 00959 root->bbox.xMax = face->header.xMax; 00960 root->bbox.yMax = face->header.yMax; 00961 root->units_per_EM = face->header.Units_Per_EM; 00962 00963 00964 /* XXX: Computing the ascender/descender/height is very different */ 00965 /* from what the specification tells you. Apparently, we */ 00966 /* must be careful because */ 00967 /* */ 00968 /* - not all fonts have an OS/2 table; in this case, we take */ 00969 /* the values in the horizontal header. However, these */ 00970 /* values very often are not reliable. */ 00971 /* */ 00972 /* - otherwise, the correct typographic values are in the */ 00973 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ 00974 /* */ 00975 /* However, certain fonts have these fields set to 0. */ 00976 /* Rather, they have usWinAscent & usWinDescent correctly */ 00977 /* set (but with different values). */ 00978 /* */ 00979 /* As an example, Arial Narrow is implemented through four */ 00980 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ 00981 /* */ 00982 /* Strangely, all fonts have the same values in their */ 00983 /* sTypoXXX fields, except ARIALNB which sets them to 0. */ 00984 /* */ 00985 /* On the other hand, they all have different */ 00986 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ 00987 /* table cannot be used to compute the text height reliably! */ 00988 /* */ 00989 00990 /* The ascender/descender/height are computed from the OS/2 table */ 00991 /* when found. Otherwise, they're taken from the horizontal */ 00992 /* header. */ 00993 /* */ 00994 00995 root->ascender = face->horizontal.Ascender; 00996 root->descender = face->horizontal.Descender; 00997 00998 root->height = (FT_Short)( root->ascender - root->descender + 00999 face->horizontal.Line_Gap ); 01000 01001 #if 0 01002 /* if the line_gap is 0, we add an extra 15% to the text height -- */ 01003 /* this computation is based on various versions of Times New Roman */ 01004 if ( face->horizontal.Line_Gap == 0 ) 01005 root->height = (FT_Short)( ( root->height * 115 + 50 ) / 100 ); 01006 #endif /* 0 */ 01007 01008 #if 0 01009 /* some fonts have the OS/2 "sTypoAscender", "sTypoDescender" & */ 01010 /* "sTypoLineGap" fields set to 0, like ARIALNB.TTF */ 01011 if ( face->os2.version != 0xFFFFU && root->ascender ) 01012 { 01013 FT_Int height; 01014 01015 01016 root->ascender = face->os2.sTypoAscender; 01017 root->descender = -face->os2.sTypoDescender; 01018 01019 height = root->ascender + root->descender + face->os2.sTypoLineGap; 01020 if ( height > root->height ) 01021 root->height = height; 01022 } 01023 #endif /* 0 */ 01024 01025 root->max_advance_width = face->horizontal.advance_Width_Max; 01026 root->max_advance_height = (FT_Short)( face->vertical_info 01027 ? face->vertical.advance_Height_Max 01028 : root->height ); 01029 01030 /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ 01031 /* Adjust underline position from top edge to centre of */ 01032 /* stroke to convert TrueType meaning to FreeType meaning. */ 01033 root->underline_position = face->postscript.underlinePosition - 01034 face->postscript.underlineThickness / 2; 01035 root->underline_thickness = face->postscript.underlineThickness; 01036 } 01037 01038 } 01039 01040 Exit: 01041 FT_TRACE2(( "sfnt_load_face: done\n" )); 01042 01043 return error; 01044 } 01045 01046 01047 #undef LOAD_ 01048 #undef LOADM_ 01049 #undef GET_NAME 01050 01051 01052 FT_LOCAL_DEF( void ) 01053 sfnt_done_face( TT_Face face ) 01054 { 01055 FT_Memory memory; 01056 SFNT_Service sfnt; 01057 01058 01059 if ( !face ) 01060 return; 01061 01062 memory = face->root.memory; 01063 sfnt = (SFNT_Service)face->sfnt; 01064 01065 if ( sfnt ) 01066 { 01067 /* destroy the postscript names table if it is loaded */ 01068 if ( sfnt->free_psnames ) 01069 sfnt->free_psnames( face ); 01070 01071 /* destroy the embedded bitmaps table if it is loaded */ 01072 if ( sfnt->free_eblc ) 01073 sfnt->free_eblc( face ); 01074 } 01075 01076 #ifdef TT_CONFIG_OPTION_BDF 01077 /* freeing the embedded BDF properties */ 01078 tt_face_free_bdf_props( face ); 01079 #endif 01080 01081 /* freeing the kerning table */ 01082 tt_face_done_kern( face ); 01083 01084 /* freeing the collection table */ 01085 FT_FREE( face->ttc_header.offsets ); 01086 face->ttc_header.count = 0; 01087 01088 /* freeing table directory */ 01089 FT_FREE( face->dir_tables ); 01090 face->num_tables = 0; 01091 01092 { 01093 FT_Stream stream = FT_FACE_STREAM( face ); 01094 01095 01096 /* simply release the 'cmap' table frame */ 01097 FT_FRAME_RELEASE( face->cmap_table ); 01098 face->cmap_size = 0; 01099 } 01100 01101 /* freeing the horizontal metrics */ 01102 #ifndef FT_CONFIG_OPTION_OLD_INTERNALS 01103 { 01104 FT_Stream stream = FT_FACE_STREAM( face ); 01105 01106 01107 FT_FRAME_RELEASE( face->horz_metrics ); 01108 FT_FRAME_RELEASE( face->vert_metrics ); 01109 face->horz_metrics_size = 0; 01110 face->vert_metrics_size = 0; 01111 } 01112 #else 01113 FT_FREE( face->horizontal.long_metrics ); 01114 FT_FREE( face->horizontal.short_metrics ); 01115 #endif 01116 01117 /* freeing the vertical ones, if any */ 01118 if ( face->vertical_info ) 01119 { 01120 FT_FREE( face->vertical.long_metrics ); 01121 FT_FREE( face->vertical.short_metrics ); 01122 face->vertical_info = 0; 01123 } 01124 01125 /* freeing the gasp table */ 01126 FT_FREE( face->gasp.gaspRanges ); 01127 face->gasp.numRanges = 0; 01128 01129 /* freeing the name table */ 01130 if ( sfnt ) 01131 sfnt->free_name( face ); 01132 01133 /* freeing family and style name */ 01134 FT_FREE( face->root.family_name ); 01135 FT_FREE( face->root.style_name ); 01136 01137 /* freeing sbit size table */ 01138 FT_FREE( face->root.available_sizes ); 01139 face->root.num_fixed_sizes = 0; 01140 01141 FT_FREE( face->postscript_name ); 01142 01143 face->sfnt = 0; 01144 } 01145 01146 01147 /* END */ Generated on Sat May 26 2012 04:32:55 for ReactOS by
1.7.6.1
|