| OLD | NEW |
| (Empty) |
| 1 /***************************************************************************/ | |
| 2 /* */ | |
| 3 /* sfobjs.c */ | |
| 4 /* */ | |
| 5 /* SFNT object management (base). */ | |
| 6 /* */ | |
| 7 /* Copyright 1996-2008, 2010-2013 by */ | |
| 8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */ | |
| 9 /* */ | |
| 10 /* This file is part of the FreeType project, and may only be used, */ | |
| 11 /* modified, and distributed under the terms of the FreeType project */ | |
| 12 /* license, LICENSE.TXT. By continuing to use, modify, or distribute */ | |
| 13 /* this file you indicate that you have read the license and */ | |
| 14 /* understand and accept it fully. */ | |
| 15 /* */ | |
| 16 /***************************************************************************/ | |
| 17 | |
| 18 | |
| 19 #include "../../include/ft2build.h" | |
| 20 #include "sfobjs.h" | |
| 21 #include "ttload.h" | |
| 22 #include "ttcmap.h" | |
| 23 #include "ttkern.h" | |
| 24 #include "../../include/freetype/internal/sfnt.h" | |
| 25 #include "../../include/freetype/internal/ftdebug.h" | |
| 26 #include "../../include/freetype/ttnameid.h" | |
| 27 #include "../../include/freetype/tttags.h" | |
| 28 #include "../../include/freetype/internal/services/svpscmap.h" | |
| 29 #include "../../include/freetype/ftsnames.h" | |
| 30 #include "sferrors.h" | |
| 31 | |
| 32 #ifdef TT_CONFIG_OPTION_BDF | |
| 33 #include "ttbdf.h" | |
| 34 #endif | |
| 35 | |
| 36 | |
| 37 /*************************************************************************/ | |
| 38 /* */ | |
| 39 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ | |
| 40 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ | |
| 41 /* messages during execution. */ | |
| 42 /* */ | |
| 43 #undef FT_COMPONENT | |
| 44 #define FT_COMPONENT trace_sfobjs | |
| 45 | |
| 46 | |
| 47 | |
| 48 /* convert a UTF-16 name entry to ASCII */ | |
| 49 static FT_String* | |
| 50 tt_name_entry_ascii_from_utf16( TT_NameEntry entry, | |
| 51 FT_Memory memory ) | |
| 52 { | |
| 53 FT_String* string = NULL; | |
| 54 FT_UInt len, code, n; | |
| 55 FT_Byte* read = (FT_Byte*)entry->string; | |
| 56 FT_Error error; | |
| 57 | |
| 58 | |
| 59 len = (FT_UInt)entry->stringLength / 2; | |
| 60 | |
| 61 if ( FT_NEW_ARRAY( string, len + 1 ) ) | |
| 62 return NULL; | |
| 63 | |
| 64 for ( n = 0; n < len; n++ ) | |
| 65 { | |
| 66 code = FT_NEXT_USHORT( read ); | |
| 67 | |
| 68 if ( code == 0 ) | |
| 69 break; | |
| 70 | |
| 71 if (code > 255) /*Johnson 2010-10-09, #TESTDOC:0000042_QUT20005_5.pdf.*/ | |
| 72 code = code>>8&0x00ff; | |
| 73 if ( code < 32 || code > 127 ) | |
| 74 code = '?'; | |
| 75 | |
| 76 string[n] = (char)code; | |
| 77 } | |
| 78 | |
| 79 string[n] = 0; | |
| 80 | |
| 81 return string; | |
| 82 } | |
| 83 | |
| 84 | |
| 85 /* convert an Apple Roman or symbol name entry to ASCII */ | |
| 86 static FT_String* | |
| 87 tt_name_entry_ascii_from_other( TT_NameEntry entry, | |
| 88 FT_Memory memory ) | |
| 89 { | |
| 90 FT_String* string = NULL; | |
| 91 FT_UInt len, code, n; | |
| 92 FT_Byte* read = (FT_Byte*)entry->string; | |
| 93 FT_Error error; | |
| 94 | |
| 95 | |
| 96 len = (FT_UInt)entry->stringLength; | |
| 97 | |
| 98 if ( FT_NEW_ARRAY( string, len + 1 ) ) | |
| 99 return NULL; | |
| 100 | |
| 101 for ( n = 0; n < len; n++ ) | |
| 102 { | |
| 103 code = *read++; | |
| 104 | |
| 105 if ( code == 0 ) | |
| 106 break; | |
| 107 | |
| 108 if ( code < 32 || code > 127 ) | |
| 109 code = '?'; | |
| 110 | |
| 111 string[n] = (char)code; | |
| 112 } | |
| 113 | |
| 114 string[n] = 0; | |
| 115 | |
| 116 return string; | |
| 117 } | |
| 118 | |
| 119 | |
| 120 typedef FT_String* (*TT_NameEntry_ConvertFunc)( TT_NameEntry entry, | |
| 121 FT_Memory memory ); | |
| 122 | |
| 123 | |
| 124 /*************************************************************************/ | |
| 125 /* */ | |
| 126 /* <Function> */ | |
| 127 /* tt_face_get_name */ | |
| 128 /* */ | |
| 129 /* <Description> */ | |
| 130 /* Returns a given ENGLISH name record in ASCII. */ | |
| 131 /* */ | |
| 132 /* <Input> */ | |
| 133 /* face :: A handle to the source face object. */ | |
| 134 /* */ | |
| 135 /* nameid :: The name id of the name record to return. */ | |
| 136 /* */ | |
| 137 /* <InOut> */ | |
| 138 /* name :: The address of a string pointer. NULL if no name is */ | |
| 139 /* present. */ | |
| 140 /* */ | |
| 141 /* <Return> */ | |
| 142 /* FreeType error code. 0 means success. */ | |
| 143 /* */ | |
| 144 static FT_Error | |
| 145 tt_face_get_name( TT_Face face, | |
| 146 FT_UShort nameid, | |
| 147 FT_String** name ) | |
| 148 { | |
| 149 FT_Memory memory = face->root.memory; | |
| 150 FT_Error error = FT_Err_Ok; | |
| 151 FT_String* result = NULL; | |
| 152 FT_UShort n; | |
| 153 TT_NameEntryRec* rec; | |
| 154 FT_Int found_apple = -1; | |
| 155 FT_Int found_apple_roman = -1; | |
| 156 FT_Int found_apple_english = -1; | |
| 157 FT_Int found_win = -1; | |
| 158 FT_Int found_unicode = -1; | |
| 159 | |
| 160 FT_Bool is_english = 0; | |
| 161 | |
| 162 TT_NameEntry_ConvertFunc convert; | |
| 163 | |
| 164 | |
| 165 FT_ASSERT( name ); | |
| 166 | |
| 167 rec = face->name_table.names; | |
| 168 for ( n = 0; n < face->num_names; n++, rec++ ) | |
| 169 { | |
| 170 /* According to the OpenType 1.3 specification, only Microsoft or */ | |
| 171 /* Apple platform IDs might be used in the `name' table. The */ | |
| 172 /* `Unicode' platform is reserved for the `cmap' table, and the */ | |
| 173 /* `ISO' one is deprecated. */ | |
| 174 /* */ | |
| 175 /* However, the Apple TrueType specification doesn't say the same */ | |
| 176 /* thing and goes to suggest that all Unicode `name' table entries */ | |
| 177 /* should be coded in UTF-16 (in big-endian format I suppose). */ | |
| 178 /* */ | |
| 179 if ( rec->nameID == nameid && rec->stringLength > 0 ) | |
| 180 { | |
| 181 switch ( rec->platformID ) | |
| 182 { | |
| 183 case TT_PLATFORM_APPLE_UNICODE: | |
| 184 case TT_PLATFORM_ISO: | |
| 185 /* there is `languageID' to check there. We should use this */ | |
| 186 /* field only as a last solution when nothing else is */ | |
| 187 /* available. */ | |
| 188 /* */ | |
| 189 found_unicode = n; | |
| 190 break; | |
| 191 | |
| 192 case TT_PLATFORM_MACINTOSH: | |
| 193 /* This is a bit special because some fonts will use either */ | |
| 194 /* an English language id, or a Roman encoding id, to indicate */ | |
| 195 /* the English version of its font name. */ | |
| 196 /* */ | |
| 197 if ( rec->languageID == TT_MAC_LANGID_ENGLISH ) | |
| 198 found_apple_english = n; | |
| 199 else if ( rec->encodingID == TT_MAC_ID_ROMAN ) | |
| 200 found_apple_roman = n; | |
| 201 break; | |
| 202 | |
| 203 case TT_PLATFORM_MICROSOFT: | |
| 204 /* we only take a non-English name when there is nothing */ | |
| 205 /* else available in the font */ | |
| 206 /* */ | |
| 207 if ( found_win == -1 || ( rec->languageID & 0x3FF ) == 0x009 ) | |
| 208 { | |
| 209 switch ( rec->encodingID ) | |
| 210 { | |
| 211 case TT_MS_ID_SYMBOL_CS: | |
| 212 case TT_MS_ID_UNICODE_CS: | |
| 213 case TT_MS_ID_UCS_4: | |
| 214 is_english = FT_BOOL( ( rec->languageID & 0x3FF ) == 0x009 ); | |
| 215 found_win = n; | |
| 216 break; | |
| 217 | |
| 218 default: | |
| 219 ; | |
| 220 } | |
| 221 } | |
| 222 break; | |
| 223 | |
| 224 default: | |
| 225 ; | |
| 226 } | |
| 227 } | |
| 228 } | |
| 229 | |
| 230 found_apple = found_apple_roman; | |
| 231 if ( found_apple_english >= 0 ) | |
| 232 found_apple = found_apple_english; | |
| 233 | |
| 234 /* some fonts contain invalid Unicode or Macintosh formatted entries; */ | |
| 235 /* we will thus favor names encoded in Windows formats if available */ | |
| 236 /* (provided it is an English name) */ | |
| 237 /* */ | |
| 238 convert = NULL; | |
| 239 if ( found_win >= 0 && !( found_apple >= 0 && !is_english ) ) | |
| 240 { | |
| 241 rec = face->name_table.names + found_win; | |
| 242 switch ( rec->encodingID ) | |
| 243 { | |
| 244 /* all Unicode strings are encoded using UTF-16BE */ | |
| 245 case TT_MS_ID_UNICODE_CS: | |
| 246 case TT_MS_ID_SYMBOL_CS: | |
| 247 convert = tt_name_entry_ascii_from_utf16; | |
| 248 break; | |
| 249 | |
| 250 case TT_MS_ID_UCS_4: | |
| 251 /* Apparently, if this value is found in a name table entry, it is */ | |
| 252 /* documented as `full Unicode repertoire'. Experience with the */ | |
| 253 /* MsGothic font shipped with Windows Vista shows that this really */ | |
| 254 /* means UTF-16 encoded names (UCS-4 values are only used within */ | |
| 255 /* charmaps). */ | |
| 256 convert = tt_name_entry_ascii_from_utf16; | |
| 257 break; | |
| 258 | |
| 259 default: | |
| 260 ; | |
| 261 } | |
| 262 } | |
| 263 else if ( found_apple >= 0 ) | |
| 264 { | |
| 265 rec = face->name_table.names + found_apple; | |
| 266 convert = tt_name_entry_ascii_from_other; | |
| 267 } | |
| 268 else if ( found_unicode >= 0 ) | |
| 269 { | |
| 270 rec = face->name_table.names + found_unicode; | |
| 271 convert = tt_name_entry_ascii_from_utf16; | |
| 272 } | |
| 273 | |
| 274 if ( rec && convert ) | |
| 275 { | |
| 276 if ( rec->string == NULL ) | |
| 277 { | |
| 278 FT_Stream stream = face->name_table.stream; | |
| 279 | |
| 280 | |
| 281 if ( FT_QNEW_ARRAY ( rec->string, rec->stringLength ) || | |
| 282 FT_STREAM_SEEK( rec->stringOffset ) || | |
| 283 FT_STREAM_READ( rec->string, rec->stringLength ) ) | |
| 284 { | |
| 285 FT_FREE( rec->string ); | |
| 286 rec->stringLength = 0; | |
| 287 result = NULL; | |
| 288 goto Exit; | |
| 289 } | |
| 290 } | |
| 291 | |
| 292 result = convert( rec, memory ); | |
| 293 } | |
| 294 | |
| 295 Exit: | |
| 296 *name = result; | |
| 297 return error; | |
| 298 } | |
| 299 | |
| 300 | |
| 301 static FT_Encoding | |
| 302 sfnt_find_encoding( int platform_id, | |
| 303 int encoding_id ) | |
| 304 { | |
| 305 typedef struct TEncoding_ | |
| 306 { | |
| 307 int platform_id; | |
| 308 int encoding_id; | |
| 309 FT_Encoding encoding; | |
| 310 | |
| 311 } TEncoding; | |
| 312 | |
| 313 static | |
| 314 const TEncoding tt_encodings[] = | |
| 315 { | |
| 316 { TT_PLATFORM_ISO, -1, FT_ENCODING_UNICODE }, | |
| 317 | |
| 318 { TT_PLATFORM_APPLE_UNICODE, -1, FT_ENCODING_UNICODE }, | |
| 319 | |
| 320 { TT_PLATFORM_MACINTOSH, TT_MAC_ID_ROMAN, FT_ENCODING_APPLE_ROMAN
}, | |
| 321 | |
| 322 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SYMBOL_CS, FT_ENCODING_MS_SYMBOL }, | |
| 323 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UCS_4, FT_ENCODING_UNICODE }, | |
| 324 { TT_PLATFORM_MICROSOFT, TT_MS_ID_UNICODE_CS, FT_ENCODING_UNICODE }, | |
| 325 { TT_PLATFORM_MICROSOFT, TT_MS_ID_SJIS, FT_ENCODING_SJIS }, | |
| 326 { TT_PLATFORM_MICROSOFT, TT_MS_ID_GB2312, FT_ENCODING_GB2312 }, | |
| 327 { TT_PLATFORM_MICROSOFT, TT_MS_ID_BIG_5, FT_ENCODING_BIG5 }, | |
| 328 { TT_PLATFORM_MICROSOFT, TT_MS_ID_WANSUNG, FT_ENCODING_WANSUNG }, | |
| 329 { TT_PLATFORM_MICROSOFT, TT_MS_ID_JOHAB, FT_ENCODING_JOHAB } | |
| 330 }; | |
| 331 | |
| 332 const TEncoding *cur, *limit; | |
| 333 | |
| 334 | |
| 335 cur = tt_encodings; | |
| 336 limit = cur + sizeof ( tt_encodings ) / sizeof ( tt_encodings[0] ); | |
| 337 | |
| 338 for ( ; cur < limit; cur++ ) | |
| 339 { | |
| 340 if ( cur->platform_id == platform_id ) | |
| 341 { | |
| 342 if ( cur->encoding_id == encoding_id || | |
| 343 cur->encoding_id == -1 ) | |
| 344 return cur->encoding; | |
| 345 } | |
| 346 } | |
| 347 | |
| 348 return FT_ENCODING_NONE; | |
| 349 } | |
| 350 | |
| 351 | |
| 352 /* Fill in face->ttc_header. If the font is not a TTC, it is */ | |
| 353 /* synthesized into a TTC with one offset table. */ | |
| 354 static FT_Error | |
| 355 sfnt_open_font( FT_Stream stream, | |
| 356 TT_Face face ) | |
| 357 { | |
| 358 FT_Memory memory = stream->memory; | |
| 359 FT_Error error; | |
| 360 FT_ULong tag, offset; | |
| 361 | |
| 362 static const FT_Frame_Field ttc_header_fields[] = | |
| 363 { | |
| 364 #undef FT_STRUCTURE | |
| 365 #define FT_STRUCTURE TTC_HeaderRec | |
| 366 | |
| 367 FT_FRAME_START( 8 ), | |
| 368 FT_FRAME_LONG( version ), | |
| 369 FT_FRAME_LONG( count ), /* this is ULong in the specs */ | |
| 370 FT_FRAME_END | |
| 371 }; | |
| 372 | |
| 373 | |
| 374 face->ttc_header.tag = 0; | |
| 375 face->ttc_header.version = 0; | |
| 376 face->ttc_header.count = 0; | |
| 377 | |
| 378 offset = FT_STREAM_POS(); | |
| 379 | |
| 380 if ( FT_READ_ULONG( tag ) ) | |
| 381 return error; | |
| 382 | |
| 383 if ( tag != 0x00010000UL && | |
| 384 tag != TTAG_ttcf && | |
| 385 tag != TTAG_OTTO && | |
| 386 tag != TTAG_true && | |
| 387 tag != TTAG_typ1 && | |
| 388 tag != 0x00020000UL ) | |
| 389 { | |
| 390 FT_TRACE2(( " not a font using the SFNT container format\n" )); | |
| 391 return FT_THROW( Unknown_File_Format ); | |
| 392 } | |
| 393 | |
| 394 face->ttc_header.tag = TTAG_ttcf; | |
| 395 | |
| 396 if ( tag == TTAG_ttcf ) | |
| 397 { | |
| 398 FT_Int n; | |
| 399 | |
| 400 | |
| 401 FT_TRACE3(( "sfnt_open_font: file is a collection\n" )); | |
| 402 | |
| 403 if ( FT_STREAM_READ_FIELDS( ttc_header_fields, &face->ttc_header ) ) | |
| 404 return error; | |
| 405 | |
| 406 if ( face->ttc_header.count == 0 ) | |
| 407 return FT_THROW( Invalid_Table ); | |
| 408 | |
| 409 /* a rough size estimate: let's conservatively assume that there */ | |
| 410 /* is just a single table info in each subfont header (12 + 16*1 = */ | |
| 411 /* 28 bytes), thus we have (at least) `12 + 4*count' bytes for the */ | |
| 412 /* size of the TTC header plus `28*count' bytes for all subfont */ | |
| 413 /* headers */ | |
| 414 if ( (FT_ULong)face->ttc_header.count > stream->size / ( 28 + 4 ) ) | |
| 415 return FT_THROW( Array_Too_Large ); | |
| 416 | |
| 417 /* now read the offsets of each font in the file */ | |
| 418 if ( FT_NEW_ARRAY( face->ttc_header.offsets, face->ttc_header.count ) ) | |
| 419 return error; | |
| 420 | |
| 421 if ( FT_FRAME_ENTER( face->ttc_header.count * 4L ) ) | |
| 422 return error; | |
| 423 | |
| 424 for ( n = 0; n < face->ttc_header.count; n++ ) | |
| 425 face->ttc_header.offsets[n] = FT_GET_ULONG(); | |
| 426 | |
| 427 FT_FRAME_EXIT(); | |
| 428 } | |
| 429 else | |
| 430 { | |
| 431 FT_TRACE3(( "sfnt_open_font: synthesize TTC\n" )); | |
| 432 | |
| 433 face->ttc_header.version = 1 << 16; | |
| 434 face->ttc_header.count = 1; | |
| 435 | |
| 436 if ( FT_NEW( face->ttc_header.offsets ) ) | |
| 437 return error; | |
| 438 | |
| 439 face->ttc_header.offsets[0] = offset; | |
| 440 } | |
| 441 | |
| 442 return error; | |
| 443 } | |
| 444 | |
| 445 | |
| 446 FT_LOCAL_DEF( FT_Error ) | |
| 447 sfnt_init_face( FT_Stream stream, | |
| 448 TT_Face face, | |
| 449 FT_Int face_index, | |
| 450 FT_Int num_params, | |
| 451 FT_Parameter* params ) | |
| 452 { | |
| 453 FT_Error error; | |
| 454 FT_Library library = face->root.driver->root.library; | |
| 455 SFNT_Service sfnt; | |
| 456 | |
| 457 | |
| 458 /* for now, parameters are unused */ | |
| 459 FT_UNUSED( num_params ); | |
| 460 FT_UNUSED( params ); | |
| 461 | |
| 462 | |
| 463 sfnt = (SFNT_Service)face->sfnt; | |
| 464 if ( !sfnt ) | |
| 465 { | |
| 466 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); | |
| 467 if ( !sfnt ) | |
| 468 { | |
| 469 FT_ERROR(( "sfnt_init_face: cannot access `sfnt' module\n" )); | |
| 470 return FT_THROW( Missing_Module ); | |
| 471 } | |
| 472 | |
| 473 face->sfnt = sfnt; | |
| 474 face->goto_table = sfnt->goto_table; | |
| 475 } | |
| 476 | |
| 477 FT_FACE_FIND_GLOBAL_SERVICE( face, face->psnames, POSTSCRIPT_CMAPS ); | |
| 478 | |
| 479 FT_TRACE2(( "SFNT driver\n" )); | |
| 480 | |
| 481 error = sfnt_open_font( stream, face ); | |
| 482 if ( error ) | |
| 483 return error; | |
| 484 | |
| 485 FT_TRACE2(( "sfnt_init_face: %08p, %ld\n", face, face_index )); | |
| 486 | |
| 487 if ( face_index < 0 ) | |
| 488 face_index = 0; | |
| 489 | |
| 490 if ( face_index >= face->ttc_header.count ) | |
| 491 return FT_THROW( Invalid_Argument ); | |
| 492 | |
| 493 if ( FT_STREAM_SEEK( face->ttc_header.offsets[face_index] ) ) | |
| 494 return error; | |
| 495 | |
| 496 /* check that we have a valid TrueType file */ | |
| 497 error = sfnt->load_font_dir( face, stream ); | |
| 498 if ( error ) | |
| 499 return error; | |
| 500 | |
| 501 face->root.num_faces = face->ttc_header.count; | |
| 502 face->root.face_index = face_index; | |
| 503 | |
| 504 return error; | |
| 505 } | |
| 506 | |
| 507 | |
| 508 #define LOAD_( x ) \ | |
| 509 do { \ | |
| 510 FT_TRACE2(( "`" #x "' " )); \ | |
| 511 FT_TRACE3(( "-->\n" )); \ | |
| 512 \ | |
| 513 error = sfnt->load_ ## x( face, stream ); \ | |
| 514 \ | |
| 515 FT_TRACE2(( "%s\n", ( !error ) \ | |
| 516 ? "loaded" \ | |
| 517 : FT_ERR_EQ( error, Table_Missing ) \ | |
| 518 ? "missing" \ | |
| 519 : "failed to load" )); \ | |
| 520 FT_TRACE3(( "\n" )); \ | |
| 521 } while ( 0 ) | |
| 522 | |
| 523 #define LOADM_( x, vertical ) \ | |
| 524 do { \ | |
| 525 FT_TRACE2(( "`%s" #x "' ", \ | |
| 526 vertical ? "vertical " : "" )); \ | |
| 527 FT_TRACE3(( "-->\n" )); \ | |
| 528 \ | |
| 529 error = sfnt->load_ ## x( face, stream, vertical ); \ | |
| 530 \ | |
| 531 FT_TRACE2(( "%s\n", ( !error ) \ | |
| 532 ? "loaded" \ | |
| 533 : FT_ERR_EQ( error, Table_Missing ) \ | |
| 534 ? "missing" \ | |
| 535 : "failed to load" )); \ | |
| 536 FT_TRACE3(( "\n" )); \ | |
| 537 } while ( 0 ) | |
| 538 | |
| 539 #define GET_NAME( id, field ) \ | |
| 540 do { \ | |
| 541 error = tt_face_get_name( face, TT_NAME_ID_ ## id, field ); \ | |
| 542 if ( error ) \ | |
| 543 goto Exit; \ | |
| 544 } while ( 0 ) | |
| 545 | |
| 546 | |
| 547 FT_LOCAL_DEF( FT_Error ) | |
| 548 sfnt_load_face( FT_Stream stream, | |
| 549 TT_Face face, | |
| 550 FT_Int face_index, | |
| 551 FT_Int num_params, | |
| 552 FT_Parameter* params ) | |
| 553 { | |
| 554 FT_Error error; | |
| 555 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES | |
| 556 FT_Error psnames_error; | |
| 557 #endif | |
| 558 FT_Bool has_outline; | |
| 559 FT_Bool is_apple_sbit; | |
| 560 FT_Bool ignore_preferred_family = FALSE; | |
| 561 FT_Bool ignore_preferred_subfamily = FALSE; | |
| 562 | |
| 563 SFNT_Service sfnt = (SFNT_Service)face->sfnt; | |
| 564 | |
| 565 FT_UNUSED( face_index ); | |
| 566 | |
| 567 | |
| 568 /* Check parameters */ | |
| 569 | |
| 570 { | |
| 571 FT_Int i; | |
| 572 | |
| 573 | |
| 574 for ( i = 0; i < num_params; i++ ) | |
| 575 { | |
| 576 if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_FAMILY ) | |
| 577 ignore_preferred_family = TRUE; | |
| 578 else if ( params[i].tag == FT_PARAM_TAG_IGNORE_PREFERRED_SUBFAMILY ) | |
| 579 ignore_preferred_subfamily = TRUE; | |
| 580 } | |
| 581 } | |
| 582 | |
| 583 /* Load tables */ | |
| 584 | |
| 585 /* We now support two SFNT-based bitmapped font formats. They */ | |
| 586 /* are recognized easily as they do not include a `glyf' */ | |
| 587 /* table. */ | |
| 588 /* */ | |
| 589 /* The first format comes from Apple, and uses a table named */ | |
| 590 /* `bhed' instead of `head' to store the font header (using */ | |
| 591 /* the same format). It also doesn't include horizontal and */ | |
| 592 /* vertical metrics tables (i.e. `hhea' and `vhea' tables are */ | |
| 593 /* missing). */ | |
| 594 /* */ | |
| 595 /* The other format comes from Microsoft, and is used with */ | |
| 596 /* WinCE/PocketPC. It looks like a standard TTF, except that */ | |
| 597 /* it doesn't contain outlines. */ | |
| 598 /* */ | |
| 599 | |
| 600 FT_TRACE2(( "sfnt_load_face: %08p\n\n", face )); | |
| 601 | |
| 602 /* do we have outlines in there? */ | |
| 603 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 604 has_outline = FT_BOOL( face->root.internal->incremental_interface != 0 || | |
| 605 tt_face_lookup_table( face, TTAG_glyf ) != 0 || | |
| 606 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); | |
| 607 #else | |
| 608 has_outline = FT_BOOL( tt_face_lookup_table( face, TTAG_glyf ) != 0 || | |
| 609 tt_face_lookup_table( face, TTAG_CFF ) != 0 ); | |
| 610 #endif | |
| 611 | |
| 612 is_apple_sbit = 0; | |
| 613 | |
| 614 /* if this font doesn't contain outlines, we try to load */ | |
| 615 /* a `bhed' table */ | |
| 616 if ( !has_outline && sfnt->load_bhed ) | |
| 617 { | |
| 618 LOAD_( bhed ); | |
| 619 is_apple_sbit = FT_BOOL( !error ); | |
| 620 } | |
| 621 | |
| 622 /* load the font header (`head' table) if this isn't an Apple */ | |
| 623 /* sbit font file */ | |
| 624 if ( !is_apple_sbit ) | |
| 625 { | |
| 626 LOAD_( head ); | |
| 627 if ( error ) | |
| 628 goto Exit; | |
| 629 } | |
| 630 | |
| 631 if ( face->header.Units_Per_EM == 0 ) | |
| 632 { | |
| 633 error = FT_THROW( Invalid_Table ); | |
| 634 | |
| 635 goto Exit; | |
| 636 } | |
| 637 | |
| 638 /* the following tables are often not present in embedded TrueType */ | |
| 639 /* fonts within PDF documents, so don't check for them. */ | |
| 640 LOAD_( maxp ); | |
| 641 LOAD_( cmap ); | |
| 642 | |
| 643 /* the following tables are optional in PCL fonts -- */ | |
| 644 /* don't check for errors */ | |
| 645 LOAD_( name ); | |
| 646 LOAD_( post ); | |
| 647 | |
| 648 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES | |
| 649 psnames_error = error; | |
| 650 #endif | |
| 651 | |
| 652 /* do not load the metrics headers and tables if this is an Apple */ | |
| 653 /* sbit font file */ | |
| 654 if ( !is_apple_sbit ) | |
| 655 { | |
| 656 /* load the `hhea' and `hmtx' tables */ | |
| 657 LOADM_( hhea, 0 ); | |
| 658 if ( !error ) | |
| 659 { | |
| 660 LOADM_( hmtx, 0 ); | |
| 661 if ( FT_ERR_EQ( error, Table_Missing ) ) | |
| 662 { | |
| 663 error = FT_THROW( Hmtx_Table_Missing ); | |
| 664 | |
| 665 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 666 /* If this is an incrementally loaded font and there are */ | |
| 667 /* overriding metrics, tolerate a missing `hmtx' table. */ | |
| 668 if ( face->root.internal->incremental_interface && | |
| 669 face->root.internal->incremental_interface->funcs-> | |
| 670 get_glyph_metrics ) | |
| 671 { | |
| 672 face->horizontal.number_Of_HMetrics = 0; | |
| 673 error = FT_Err_Ok; | |
| 674 } | |
| 675 #endif | |
| 676 } | |
| 677 } | |
| 678 else if ( FT_ERR_EQ( error, Table_Missing ) ) | |
| 679 { | |
| 680 /* No `hhea' table necessary for SFNT Mac fonts. */ | |
| 681 if ( face->format_tag == TTAG_true ) | |
| 682 { | |
| 683 FT_TRACE2(( "This is an SFNT Mac font.\n" )); | |
| 684 | |
| 685 has_outline = 0; | |
| 686 error = FT_Err_Ok; | |
| 687 } | |
| 688 else | |
| 689 { | |
| 690 error = FT_THROW( Horiz_Header_Missing ); | |
| 691 | |
| 692 #ifdef FT_CONFIG_OPTION_INCREMENTAL | |
| 693 /* If this is an incrementally loaded font and there are */ | |
| 694 /* overriding metrics, tolerate a missing `hhea' table. */ | |
| 695 if ( face->root.internal->incremental_interface && | |
| 696 face->root.internal->incremental_interface->funcs-> | |
| 697 get_glyph_metrics ) | |
| 698 { | |
| 699 face->horizontal.number_Of_HMetrics = 0; | |
| 700 error = FT_Err_Ok; | |
| 701 } | |
| 702 #endif | |
| 703 | |
| 704 } | |
| 705 } | |
| 706 | |
| 707 if ( error ) | |
| 708 goto Exit; | |
| 709 | |
| 710 /* try to load the `vhea' and `vmtx' tables */ | |
| 711 LOADM_( hhea, 1 ); | |
| 712 if ( !error ) | |
| 713 { | |
| 714 LOADM_( hmtx, 1 ); | |
| 715 if ( !error ) | |
| 716 face->vertical_info = 1; | |
| 717 } | |
| 718 | |
| 719 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) | |
| 720 goto Exit; | |
| 721 | |
| 722 LOAD_( os2 ); | |
| 723 if ( error ) | |
| 724 { | |
| 725 /* we treat the table as missing if there are any errors */ | |
| 726 face->os2.version = 0xFFFFU; | |
| 727 } | |
| 728 } | |
| 729 | |
| 730 /* the optional tables */ | |
| 731 | |
| 732 /* embedded bitmap support */ | |
| 733 if ( sfnt->load_eblc ) | |
| 734 { | |
| 735 LOAD_( eblc ); | |
| 736 if ( error ) | |
| 737 { | |
| 738 /* a font which contains neither bitmaps nor outlines is */ | |
| 739 /* still valid (although rather useless in most cases); */ | |
| 740 /* however, you can find such stripped fonts in PDFs */ | |
| 741 if ( FT_ERR_EQ( error, Table_Missing ) ) | |
| 742 error = FT_Err_Ok; | |
| 743 else | |
| 744 goto Exit; | |
| 745 } | |
| 746 } | |
| 747 | |
| 748 LOAD_( pclt ); | |
| 749 if ( error ) | |
| 750 { | |
| 751 if ( FT_ERR_NEQ( error, Table_Missing ) ) | |
| 752 goto Exit; | |
| 753 | |
| 754 face->pclt.Version = 0; | |
| 755 } | |
| 756 | |
| 757 /* consider the kerning and gasp tables as optional */ | |
| 758 LOAD_( gasp ); | |
| 759 LOAD_( kern ); | |
| 760 | |
| 761 face->root.num_glyphs = face->max_profile.numGlyphs; | |
| 762 | |
| 763 /* Bit 8 of the `fsSelection' field in the `OS/2' table denotes */ | |
| 764 /* a WWS-only font face. `WWS' stands for `weight', width', and */ | |
| 765 /* `slope', a term used by Microsoft's Windows Presentation */ | |
| 766 /* Foundation (WPF). This flag has been introduced in version */ | |
| 767 /* 1.5 of the OpenType specification (May 2008). */ | |
| 768 | |
| 769 face->root.family_name = NULL; | |
| 770 face->root.style_name = NULL; | |
| 771 if ( face->os2.version != 0xFFFFU && face->os2.fsSelection & 256 ) | |
| 772 { | |
| 773 if ( !ignore_preferred_family ) | |
| 774 GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); | |
| 775 if ( !face->root.family_name ) | |
| 776 GET_NAME( FONT_FAMILY, &face->root.family_name ); | |
| 777 | |
| 778 if ( !ignore_preferred_subfamily ) | |
| 779 GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); | |
| 780 if ( !face->root.style_name ) | |
| 781 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); | |
| 782 } | |
| 783 else | |
| 784 { | |
| 785 GET_NAME( WWS_FAMILY, &face->root.family_name ); | |
| 786 if ( !face->root.family_name && !ignore_preferred_family ) | |
| 787 GET_NAME( PREFERRED_FAMILY, &face->root.family_name ); | |
| 788 if ( !face->root.family_name ) | |
| 789 GET_NAME( FONT_FAMILY, &face->root.family_name ); | |
| 790 | |
| 791 GET_NAME( WWS_SUBFAMILY, &face->root.style_name ); | |
| 792 if ( !face->root.style_name && !ignore_preferred_subfamily ) | |
| 793 GET_NAME( PREFERRED_SUBFAMILY, &face->root.style_name ); | |
| 794 if ( !face->root.style_name ) | |
| 795 GET_NAME( FONT_SUBFAMILY, &face->root.style_name ); | |
| 796 } | |
| 797 | |
| 798 /* now set up root fields */ | |
| 799 { | |
| 800 FT_Face root = &face->root; | |
| 801 FT_Long flags = root->face_flags; | |
| 802 | |
| 803 | |
| 804 /*********************************************************************/ | |
| 805 /* */ | |
| 806 /* Compute face flags. */ | |
| 807 /* */ | |
| 808 if ( has_outline == TRUE ) | |
| 809 flags |= FT_FACE_FLAG_SCALABLE; /* scalable outlines */ | |
| 810 | |
| 811 /* The sfnt driver only supports bitmap fonts natively, thus we */ | |
| 812 /* don't set FT_FACE_FLAG_HINTER. */ | |
| 813 flags |= FT_FACE_FLAG_SFNT | /* SFNT file format */ | |
| 814 FT_FACE_FLAG_HORIZONTAL; /* horizontal data */ | |
| 815 | |
| 816 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES | |
| 817 if ( !psnames_error && | |
| 818 face->postscript.FormatType != 0x00030000L ) | |
| 819 flags |= FT_FACE_FLAG_GLYPH_NAMES; | |
| 820 #endif | |
| 821 | |
| 822 /* fixed width font? */ | |
| 823 if ( face->postscript.isFixedPitch ) | |
| 824 flags |= FT_FACE_FLAG_FIXED_WIDTH; | |
| 825 | |
| 826 /* vertical information? */ | |
| 827 if ( face->vertical_info ) | |
| 828 flags |= FT_FACE_FLAG_VERTICAL; | |
| 829 | |
| 830 /* kerning available ? */ | |
| 831 if ( TT_FACE_HAS_KERNING( face ) ) | |
| 832 flags |= FT_FACE_FLAG_KERNING; | |
| 833 | |
| 834 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT | |
| 835 /* Don't bother to load the tables unless somebody asks for them. */ | |
| 836 /* No need to do work which will (probably) not be used. */ | |
| 837 if ( tt_face_lookup_table( face, TTAG_glyf ) != 0 && | |
| 838 tt_face_lookup_table( face, TTAG_fvar ) != 0 && | |
| 839 tt_face_lookup_table( face, TTAG_gvar ) != 0 ) | |
| 840 flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; | |
| 841 #endif | |
| 842 | |
| 843 root->face_flags = flags; | |
| 844 | |
| 845 /*********************************************************************/ | |
| 846 /* */ | |
| 847 /* Compute style flags. */ | |
| 848 /* */ | |
| 849 | |
| 850 flags = 0; | |
| 851 if ( has_outline == TRUE && face->os2.version != 0xFFFFU ) | |
| 852 { | |
| 853 /* We have an OS/2 table; use the `fsSelection' field. Bit 9 */ | |
| 854 /* indicates an oblique font face. This flag has been */ | |
| 855 /* introduced in version 1.5 of the OpenType specification. */ | |
| 856 | |
| 857 if ( face->os2.fsSelection & 512 ) /* bit 9 */ | |
| 858 flags |= FT_STYLE_FLAG_ITALIC; | |
| 859 else if ( face->os2.fsSelection & 1 ) /* bit 0 */ | |
| 860 flags |= FT_STYLE_FLAG_ITALIC; | |
| 861 | |
| 862 if ( face->os2.fsSelection & 32 ) /* bit 5 */ | |
| 863 flags |= FT_STYLE_FLAG_BOLD; | |
| 864 } | |
| 865 else | |
| 866 { | |
| 867 /* this is an old Mac font, use the header field */ | |
| 868 | |
| 869 if ( face->header.Mac_Style & 1 ) | |
| 870 flags |= FT_STYLE_FLAG_BOLD; | |
| 871 | |
| 872 if ( face->header.Mac_Style & 2 ) | |
| 873 flags |= FT_STYLE_FLAG_ITALIC; | |
| 874 } | |
| 875 | |
| 876 root->style_flags = flags; | |
| 877 | |
| 878 /*********************************************************************/ | |
| 879 /* */ | |
| 880 /* Polish the charmaps. */ | |
| 881 /* */ | |
| 882 /* Try to set the charmap encoding according to the platform & */ | |
| 883 /* encoding ID of each charmap. */ | |
| 884 /* */ | |
| 885 | |
| 886 tt_face_build_cmaps( face ); /* ignore errors */ | |
| 887 | |
| 888 | |
| 889 /* set the encoding fields */ | |
| 890 { | |
| 891 FT_Int m; | |
| 892 | |
| 893 | |
| 894 for ( m = 0; m < root->num_charmaps; m++ ) | |
| 895 { | |
| 896 FT_CharMap charmap = root->charmaps[m]; | |
| 897 | |
| 898 | |
| 899 charmap->encoding = sfnt_find_encoding( charmap->platform_id, | |
| 900 charmap->encoding_id ); | |
| 901 | |
| 902 #if 0 | |
| 903 if ( root->charmap == NULL && | |
| 904 charmap->encoding == FT_ENCODING_UNICODE ) | |
| 905 { | |
| 906 /* set 'root->charmap' to the first Unicode encoding we find */ | |
| 907 root->charmap = charmap; | |
| 908 } | |
| 909 #endif | |
| 910 } | |
| 911 } | |
| 912 | |
| 913 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS | |
| 914 | |
| 915 /* | |
| 916 * Now allocate the root array of FT_Bitmap_Size records and | |
| 917 * populate them. Unfortunately, it isn't possible to indicate bit | |
| 918 * depths in the FT_Bitmap_Size record. This is a design error. | |
| 919 */ | |
| 920 { | |
| 921 FT_UInt i, count; | |
| 922 | |
| 923 | |
| 924 count = face->sbit_num_strikes; | |
| 925 | |
| 926 if ( count > 0 ) | |
| 927 { | |
| 928 FT_Memory memory = face->root.stream->memory; | |
| 929 FT_UShort em_size = face->header.Units_Per_EM; | |
| 930 FT_Short avgwidth = face->os2.xAvgCharWidth; | |
| 931 FT_Size_Metrics metrics; | |
| 932 | |
| 933 | |
| 934 if ( em_size == 0 || face->os2.version == 0xFFFFU ) | |
| 935 { | |
| 936 avgwidth = 0; | |
| 937 em_size = 1; | |
| 938 } | |
| 939 | |
| 940 if ( FT_NEW_ARRAY( root->available_sizes, count ) ) | |
| 941 goto Exit; | |
| 942 | |
| 943 for ( i = 0; i < count; i++ ) | |
| 944 { | |
| 945 FT_Bitmap_Size* bsize = root->available_sizes + i; | |
| 946 | |
| 947 | |
| 948 error = sfnt->load_strike_metrics( face, i, &metrics ); | |
| 949 if ( error ) | |
| 950 goto Exit; | |
| 951 | |
| 952 bsize->height = (FT_Short)( metrics.height >> 6 ); | |
| 953 bsize->width = (FT_Short)( | |
| 954 ( avgwidth * metrics.x_ppem + em_size / 2 ) / em_size ); | |
| 955 | |
| 956 bsize->x_ppem = metrics.x_ppem << 6; | |
| 957 bsize->y_ppem = metrics.y_ppem << 6; | |
| 958 | |
| 959 /* assume 72dpi */ | |
| 960 bsize->size = metrics.y_ppem << 6; | |
| 961 } | |
| 962 | |
| 963 root->face_flags |= FT_FACE_FLAG_FIXED_SIZES; | |
| 964 root->num_fixed_sizes = (FT_Int)count; | |
| 965 } | |
| 966 } | |
| 967 | |
| 968 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ | |
| 969 | |
| 970 /* a font with no bitmaps and no outlines is scalable; */ | |
| 971 /* it has only empty glyphs then */ | |
| 972 if ( !FT_HAS_FIXED_SIZES( root ) && !FT_IS_SCALABLE( root ) ) | |
| 973 root->face_flags |= FT_FACE_FLAG_SCALABLE; | |
| 974 | |
| 975 | |
| 976 /*********************************************************************/ | |
| 977 /* */ | |
| 978 /* Set up metrics. */ | |
| 979 /* */ | |
| 980 if ( FT_IS_SCALABLE( root ) ) | |
| 981 { | |
| 982 /* XXX What about if outline header is missing */ | |
| 983 /* (e.g. sfnt wrapped bitmap)? */ | |
| 984 root->bbox.xMin = face->header.xMin; | |
| 985 root->bbox.yMin = face->header.yMin; | |
| 986 root->bbox.xMax = face->header.xMax; | |
| 987 root->bbox.yMax = face->header.yMax; | |
| 988 root->units_per_EM = face->header.Units_Per_EM; | |
| 989 | |
| 990 | |
| 991 /* XXX: Computing the ascender/descender/height is very different */ | |
| 992 /* from what the specification tells you. Apparently, we */ | |
| 993 /* must be careful because */ | |
| 994 /* */ | |
| 995 /* - not all fonts have an OS/2 table; in this case, we take */ | |
| 996 /* the values in the horizontal header. However, these */ | |
| 997 /* values very often are not reliable. */ | |
| 998 /* */ | |
| 999 /* - otherwise, the correct typographic values are in the */ | |
| 1000 /* sTypoAscender, sTypoDescender & sTypoLineGap fields. */ | |
| 1001 /* */ | |
| 1002 /* However, certain fonts have these fields set to 0. */ | |
| 1003 /* Rather, they have usWinAscent & usWinDescent correctly */ | |
| 1004 /* set (but with different values). */ | |
| 1005 /* */ | |
| 1006 /* As an example, Arial Narrow is implemented through four */ | |
| 1007 /* files ARIALN.TTF, ARIALNI.TTF, ARIALNB.TTF & ARIALNBI.TTF */ | |
| 1008 /* */ | |
| 1009 /* Strangely, all fonts have the same values in their */ | |
| 1010 /* sTypoXXX fields, except ARIALNB which sets them to 0. */ | |
| 1011 /* */ | |
| 1012 /* On the other hand, they all have different */ | |
| 1013 /* usWinAscent/Descent values -- as a conclusion, the OS/2 */ | |
| 1014 /* table cannot be used to compute the text height reliably! */ | |
| 1015 /* */ | |
| 1016 | |
| 1017 /* The ascender and descender are taken from the `hhea' table. */ | |
| 1018 /* If zero, they are taken from the `OS/2' table. */ | |
| 1019 | |
| 1020 root->ascender = face->horizontal.Ascender; | |
| 1021 root->descender = face->horizontal.Descender; | |
| 1022 | |
| 1023 root->height = (FT_Short)( root->ascender - root->descender + | |
| 1024 face->horizontal.Line_Gap ); | |
| 1025 | |
| 1026 if ( !( root->ascender || root->descender ) ) | |
| 1027 { | |
| 1028 if ( face->os2.version != 0xFFFFU ) | |
| 1029 { | |
| 1030 if ( face->os2.sTypoAscender || face->os2.sTypoDescender ) | |
| 1031 { | |
| 1032 root->ascender = face->os2.sTypoAscender; | |
| 1033 root->descender = face->os2.sTypoDescender; | |
| 1034 | |
| 1035 root->height = (FT_Short)( root->ascender - root->descender + | |
| 1036 face->os2.sTypoLineGap ); | |
| 1037 } | |
| 1038 else | |
| 1039 { | |
| 1040 root->ascender = (FT_Short)face->os2.usWinAscent; | |
| 1041 root->descender = -(FT_Short)face->os2.usWinDescent; | |
| 1042 | |
| 1043 root->height = (FT_UShort)( root->ascender - root->descender ); | |
| 1044 } | |
| 1045 } | |
| 1046 } | |
| 1047 | |
| 1048 root->max_advance_width = face->horizontal.advance_Width_Max; | |
| 1049 root->max_advance_height = (FT_Short)( face->vertical_info | |
| 1050 ? face->vertical.advance_Height_Max | |
| 1051 : root->height ); | |
| 1052 | |
| 1053 /* See http://www.microsoft.com/OpenType/OTSpec/post.htm -- */ | |
| 1054 /* Adjust underline position from top edge to centre of */ | |
| 1055 /* stroke to convert TrueType meaning to FreeType meaning. */ | |
| 1056 root->underline_position = face->postscript.underlinePosition - | |
| 1057 face->postscript.underlineThickness / 2; | |
| 1058 root->underline_thickness = face->postscript.underlineThickness; | |
| 1059 } | |
| 1060 | |
| 1061 } | |
| 1062 | |
| 1063 Exit: | |
| 1064 FT_TRACE2(( "sfnt_load_face: done\n" )); | |
| 1065 | |
| 1066 return error; | |
| 1067 } | |
| 1068 | |
| 1069 | |
| 1070 #undef LOAD_ | |
| 1071 #undef LOADM_ | |
| 1072 #undef GET_NAME | |
| 1073 | |
| 1074 | |
| 1075 FT_LOCAL_DEF( void ) | |
| 1076 sfnt_done_face( TT_Face face ) | |
| 1077 { | |
| 1078 FT_Memory memory; | |
| 1079 SFNT_Service sfnt; | |
| 1080 | |
| 1081 | |
| 1082 if ( !face ) | |
| 1083 return; | |
| 1084 | |
| 1085 memory = face->root.memory; | |
| 1086 sfnt = (SFNT_Service)face->sfnt; | |
| 1087 | |
| 1088 if ( sfnt ) | |
| 1089 { | |
| 1090 /* destroy the postscript names table if it is loaded */ | |
| 1091 if ( sfnt->free_psnames ) | |
| 1092 sfnt->free_psnames( face ); | |
| 1093 | |
| 1094 /* destroy the embedded bitmaps table if it is loaded */ | |
| 1095 if ( sfnt->free_eblc ) | |
| 1096 sfnt->free_eblc( face ); | |
| 1097 } | |
| 1098 | |
| 1099 #ifdef TT_CONFIG_OPTION_BDF | |
| 1100 /* freeing the embedded BDF properties */ | |
| 1101 tt_face_free_bdf_props( face ); | |
| 1102 #endif | |
| 1103 | |
| 1104 /* freeing the kerning table */ | |
| 1105 tt_face_done_kern( face ); | |
| 1106 | |
| 1107 /* freeing the collection table */ | |
| 1108 FT_FREE( face->ttc_header.offsets ); | |
| 1109 face->ttc_header.count = 0; | |
| 1110 | |
| 1111 /* freeing table directory */ | |
| 1112 FT_FREE( face->dir_tables ); | |
| 1113 face->num_tables = 0; | |
| 1114 | |
| 1115 { | |
| 1116 FT_Stream stream = FT_FACE_STREAM( face ); | |
| 1117 | |
| 1118 | |
| 1119 /* simply release the 'cmap' table frame */ | |
| 1120 FT_FRAME_RELEASE( face->cmap_table ); | |
| 1121 face->cmap_size = 0; | |
| 1122 } | |
| 1123 | |
| 1124 /* freeing the horizontal metrics */ | |
| 1125 { | |
| 1126 FT_Stream stream = FT_FACE_STREAM( face ); | |
| 1127 | |
| 1128 | |
| 1129 FT_FRAME_RELEASE( face->horz_metrics ); | |
| 1130 FT_FRAME_RELEASE( face->vert_metrics ); | |
| 1131 face->horz_metrics_size = 0; | |
| 1132 face->vert_metrics_size = 0; | |
| 1133 } | |
| 1134 | |
| 1135 /* freeing the vertical ones, if any */ | |
| 1136 if ( face->vertical_info ) | |
| 1137 { | |
| 1138 FT_FREE( face->vertical.long_metrics ); | |
| 1139 FT_FREE( face->vertical.short_metrics ); | |
| 1140 face->vertical_info = 0; | |
| 1141 } | |
| 1142 | |
| 1143 /* freeing the gasp table */ | |
| 1144 FT_FREE( face->gasp.gaspRanges ); | |
| 1145 face->gasp.numRanges = 0; | |
| 1146 | |
| 1147 /* freeing the name table */ | |
| 1148 if ( sfnt ) | |
| 1149 sfnt->free_name( face ); | |
| 1150 | |
| 1151 /* freeing family and style name */ | |
| 1152 FT_FREE( face->root.family_name ); | |
| 1153 FT_FREE( face->root.style_name ); | |
| 1154 | |
| 1155 /* freeing sbit size table */ | |
| 1156 FT_FREE( face->root.available_sizes ); | |
| 1157 face->root.num_fixed_sizes = 0; | |
| 1158 | |
| 1159 FT_FREE( face->postscript_name ); | |
| 1160 | |
| 1161 face->sfnt = 0; | |
| 1162 } | |
| 1163 | |
| 1164 | |
| 1165 /* END */ | |
| OLD | NEW |