1 /**************************************************************************** 2 * 3 * ttobjs.c 4 * 5 * Objects manager (body). 6 * 7 * Copyright (C) 1996-2021 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 <freetype/internal/ftdebug.h> 20 #include <freetype/internal/ftstream.h> 21 #include <freetype/tttags.h> 22 #include <freetype/internal/sfnt.h> 23 #include <freetype/ftdriver.h> 24 25 #include "ttgload.h" 26 #include "ttpload.h" 27 28 #include "tterrors.h" 29 30 #ifdef TT_USE_BYTECODE_INTERPRETER 31 #include "ttinterp.h" 32 #endif 33 34 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 35 #include "ttgxvar.h" 36 #endif 37 38 /************************************************************************** 39 * 40 * The macro FT_COMPONENT is used in trace mode. It is an implicit 41 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 42 * messages during execution. 43 */ 44 #undef FT_COMPONENT 45 #define FT_COMPONENT ttobjs 46 47 48 #ifdef TT_USE_BYTECODE_INTERPRETER 49 50 /************************************************************************** 51 * 52 * GLYPH ZONE FUNCTIONS 53 * 54 */ 55 56 57 /************************************************************************** 58 * 59 * @Function: 60 * tt_glyphzone_done 61 * 62 * @Description: 63 * Deallocate a glyph zone. 64 * 65 * @Input: 66 * zone :: 67 * A pointer to the target glyph zone. 68 */ 69 FT_LOCAL_DEF( void ) tt_glyphzone_done(TT_GlyphZone zone)70 tt_glyphzone_done( TT_GlyphZone zone ) 71 { 72 FT_Memory memory = zone->memory; 73 74 75 if ( memory ) 76 { 77 FT_FREE( zone->contours ); 78 FT_FREE( zone->tags ); 79 FT_FREE( zone->cur ); 80 FT_FREE( zone->org ); 81 FT_FREE( zone->orus ); 82 83 zone->max_points = zone->n_points = 0; 84 zone->max_contours = zone->n_contours = 0; 85 zone->memory = NULL; 86 } 87 } 88 89 90 /************************************************************************** 91 * 92 * @Function: 93 * tt_glyphzone_new 94 * 95 * @Description: 96 * Allocate a new glyph zone. 97 * 98 * @Input: 99 * memory :: 100 * A handle to the current memory object. 101 * 102 * maxPoints :: 103 * The capacity of glyph zone in points. 104 * 105 * maxContours :: 106 * The capacity of glyph zone in contours. 107 * 108 * @Output: 109 * zone :: 110 * A pointer to the target glyph zone record. 111 * 112 * @Return: 113 * FreeType error code. 0 means success. 114 */ 115 FT_LOCAL_DEF( FT_Error ) tt_glyphzone_new(FT_Memory memory,FT_UShort maxPoints,FT_Short maxContours,TT_GlyphZone zone)116 tt_glyphzone_new( FT_Memory memory, 117 FT_UShort maxPoints, 118 FT_Short maxContours, 119 TT_GlyphZone zone ) 120 { 121 FT_Error error; 122 123 124 FT_ZERO( zone ); 125 zone->memory = memory; 126 127 if ( FT_NEW_ARRAY( zone->org, maxPoints ) || 128 FT_NEW_ARRAY( zone->cur, maxPoints ) || 129 FT_NEW_ARRAY( zone->orus, maxPoints ) || 130 FT_NEW_ARRAY( zone->tags, maxPoints ) || 131 FT_NEW_ARRAY( zone->contours, maxContours ) ) 132 { 133 tt_glyphzone_done( zone ); 134 } 135 else 136 { 137 zone->max_points = maxPoints; 138 zone->max_contours = maxContours; 139 } 140 141 return error; 142 } 143 144 145 /* 146 * Fonts embedded in PDFs are made unique by prepending randomization 147 * prefixes to their names: as defined in Section 5.5.3, 'Font Subsets', 148 * of the PDF Reference, they consist of 6 uppercase letters followed by 149 * the `+` sign. For safety, we do not skip prefixes violating this rule. 150 */ 151 152 static const FT_String* tt_skip_pdffont_random_tag(const FT_String * name)153 tt_skip_pdffont_random_tag( const FT_String* name ) 154 { 155 unsigned int i; 156 157 158 if ( ft_strlen( name ) < 8 || name[6] != '+' ) 159 return name; 160 161 for ( i = 0; i < 6; i++ ) 162 if ( !ft_isupper( name[i] ) ) 163 return name; 164 165 FT_TRACE7(( "name without randomization tag: %s\n", name + 7 )); 166 return name + 7; 167 } 168 169 170 /* Compare the face with a list of well-known `tricky' fonts. */ 171 /* This list shall be expanded as we find more of them. */ 172 173 static FT_Bool tt_check_trickyness_family(const FT_String * name)174 tt_check_trickyness_family( const FT_String* name ) 175 { 176 177 #define TRICK_NAMES_MAX_CHARACTERS 19 178 #define TRICK_NAMES_COUNT 20 179 180 static const char trick_names[TRICK_NAMES_COUNT] 181 [TRICK_NAMES_MAX_CHARACTERS + 1] = 182 { 183 /* 184 PostScript names are given in brackets if they differ from the 185 family name. The version numbers, together with the copyright or 186 release year data, are taken from fonts available to the 187 developers. 188 189 Note that later versions of the fonts might be no longer tricky; 190 for example, `MingLiU' version 7.00 (file `mingliu.ttc' from 191 Windows 7) is an ordinary TTC with non-tricky subfonts. 192 */ 193 194 "cpop", /* dftt-p7.ttf; version 1.00, 1992 [DLJGyShoMedium] */ 195 "DFGirl-W6-WIN-BF", /* dftt-h6.ttf; version 1.00, 1993 */ 196 "DFGothic-EB", /* DynaLab Inc. 1992-1995 */ 197 "DFGyoSho-Lt", /* DynaLab Inc. 1992-1995 */ 198 "DFHei", /* DynaLab Inc. 1992-1995 [DFHei-Bd-WIN-HK-BF] */ 199 /* covers "DFHei-Md-HK-BF", maybe DynaLab Inc. */ 200 201 "DFHSGothic-W5", /* DynaLab Inc. 1992-1995 */ 202 "DFHSMincho-W3", /* DynaLab Inc. 1992-1995 */ 203 "DFHSMincho-W7", /* DynaLab Inc. 1992-1995 */ 204 "DFKaiSho-SB", /* dfkaisb.ttf */ 205 "DFKaiShu", /* covers "DFKaiShu-Md-HK-BF", maybe DynaLab Inc. */ 206 "DFKai-SB", /* kaiu.ttf; version 3.00, 1998 [DFKaiShu-SB-Estd-BF] */ 207 208 "DFMing", /* DynaLab Inc. 1992-1995 [DFMing-Md-WIN-HK-BF] */ 209 /* covers "DFMing-Bd-HK-BF", maybe DynaLab Inc. */ 210 211 "DLC", /* dftt-m7.ttf; version 1.00, 1993 [DLCMingBold] */ 212 /* dftt-f5.ttf; version 1.00, 1993 [DLCFongSung] */ 213 /* covers following */ 214 /* "DLCHayMedium", dftt-b5.ttf; version 1.00, 1993 */ 215 /* "DLCHayBold", dftt-b7.ttf; version 1.00, 1993 */ 216 /* "DLCKaiMedium", dftt-k5.ttf; version 1.00, 1992 */ 217 /* "DLCLiShu", dftt-l5.ttf; version 1.00, 1992 */ 218 /* "DLCRoundBold", dftt-r7.ttf; version 1.00, 1993 */ 219 220 "HuaTianKaiTi?", /* htkt2.ttf */ 221 "HuaTianSongTi?", /* htst3.ttf */ 222 "Ming(for ISO10646)", /* hkscsiic.ttf; version 0.12, 2007 [Ming] */ 223 /* iicore.ttf; version 0.07, 2007 [Ming] */ 224 "MingLiU", /* mingliu.ttf */ 225 /* mingliu.ttc; version 3.21, 2001 */ 226 "MingMedium", /* dftt-m5.ttf; version 1.00, 1993 [DLCMingMedium] */ 227 "PMingLiU", /* mingliu.ttc; version 3.21, 2001 */ 228 "MingLi43", /* mingli.ttf; version 1.00, 1992 */ 229 }; 230 231 int nn; 232 const FT_String* name_without_tag; 233 234 235 name_without_tag = tt_skip_pdffont_random_tag( name ); 236 for ( nn = 0; nn < TRICK_NAMES_COUNT; nn++ ) 237 if ( ft_strstr( name_without_tag, trick_names[nn] ) ) 238 return TRUE; 239 240 return FALSE; 241 } 242 243 244 /* XXX: This function should be in the `sfnt' module. */ 245 246 /* Some PDF generators clear the checksums in the TrueType header table. */ 247 /* For example, Quartz ContextPDF clears all entries, or Bullzip PDF */ 248 /* Printer clears the entries for subsetted subtables. We thus have to */ 249 /* recalculate the checksums where necessary. */ 250 251 static FT_UInt32 tt_synth_sfnt_checksum(FT_Stream stream,FT_ULong length)252 tt_synth_sfnt_checksum( FT_Stream stream, 253 FT_ULong length ) 254 { 255 FT_Error error; 256 FT_UInt32 checksum = 0; 257 FT_UInt i; 258 259 260 if ( FT_FRAME_ENTER( length ) ) 261 return 0; 262 263 for ( ; length > 3; length -= 4 ) 264 checksum += (FT_UInt32)FT_GET_ULONG(); 265 266 for ( i = 3; length > 0; length--, i-- ) 267 checksum += (FT_UInt32)FT_GET_BYTE() << ( i * 8 ); 268 269 FT_FRAME_EXIT(); 270 271 return checksum; 272 } 273 274 275 /* XXX: This function should be in the `sfnt' module. */ 276 277 static FT_ULong tt_get_sfnt_checksum(TT_Face face,FT_UShort i)278 tt_get_sfnt_checksum( TT_Face face, 279 FT_UShort i ) 280 { 281 #if 0 /* if we believe the written value, use following part. */ 282 if ( face->dir_tables[i].CheckSum ) 283 return face->dir_tables[i].CheckSum; 284 #endif 285 286 if ( !face->goto_table ) 287 return 0; 288 289 if ( face->goto_table( face, 290 face->dir_tables[i].Tag, 291 face->root.stream, 292 NULL ) ) 293 return 0; 294 295 return (FT_ULong)tt_synth_sfnt_checksum( face->root.stream, 296 face->dir_tables[i].Length ); 297 } 298 299 300 typedef struct tt_sfnt_id_rec_ 301 { 302 FT_ULong CheckSum; 303 FT_ULong Length; 304 305 } tt_sfnt_id_rec; 306 307 308 static FT_Bool tt_check_trickyness_sfnt_ids(TT_Face face)309 tt_check_trickyness_sfnt_ids( TT_Face face ) 310 { 311 #define TRICK_SFNT_IDS_PER_FACE 3 312 #define TRICK_SFNT_IDS_NUM_FACES 31 313 314 static const tt_sfnt_id_rec sfnt_id[TRICK_SFNT_IDS_NUM_FACES] 315 [TRICK_SFNT_IDS_PER_FACE] = { 316 317 #define TRICK_SFNT_ID_cvt 0 318 #define TRICK_SFNT_ID_fpgm 1 319 #define TRICK_SFNT_ID_prep 2 320 321 { /* MingLiU 1995 */ 322 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */ 323 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */ 324 { 0xA344A1EAUL, 0x000001E1UL } /* prep */ 325 }, 326 { /* MingLiU 1996- */ 327 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */ 328 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */ 329 { 0xA344A1EBUL, 0x000001E1UL } /* prep */ 330 }, 331 { /* DFGothic-EB */ 332 { 0x12C3EBB2UL, 0x00000350UL }, /* cvt */ 333 { 0xB680EE64UL, 0x000087A7UL }, /* fpgm */ 334 { 0xCE939563UL, 0x00000758UL } /* prep */ 335 }, 336 { /* DFGyoSho-Lt */ 337 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ 338 { 0xCE5956E9UL, 0x0000BC85UL }, /* fpgm */ 339 { 0x8272F416UL, 0x00000045UL } /* prep */ 340 }, 341 { /* DFHei-Md-HK-BF */ 342 { 0x1257EB46UL, 0x00000350UL }, /* cvt */ 343 { 0xF699D160UL, 0x0000715FUL }, /* fpgm */ 344 { 0xD222F568UL, 0x000003BCUL } /* prep */ 345 }, 346 { /* DFHSGothic-W5 */ 347 { 0x1262EB4EUL, 0x00000350UL }, /* cvt */ 348 { 0xE86A5D64UL, 0x00007940UL }, /* fpgm */ 349 { 0x7850F729UL, 0x000005FFUL } /* prep */ 350 }, 351 { /* DFHSMincho-W3 */ 352 { 0x122DEB0AUL, 0x00000350UL }, /* cvt */ 353 { 0x3D16328AUL, 0x0000859BUL }, /* fpgm */ 354 { 0xA93FC33BUL, 0x000002CBUL } /* prep */ 355 }, 356 { /* DFHSMincho-W7 */ 357 { 0x125FEB26UL, 0x00000350UL }, /* cvt */ 358 { 0xA5ACC982UL, 0x00007EE1UL }, /* fpgm */ 359 { 0x90999196UL, 0x0000041FUL } /* prep */ 360 }, 361 { /* DFKaiShu */ 362 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ 363 { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */ 364 { 0x13A42602UL, 0x0000007EUL } /* prep */ 365 }, 366 { /* DFKaiShu, variant */ 367 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ 368 { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */ 369 { 0x13A42602UL, 0x0000007EUL } /* prep */ 370 }, 371 { /* DFKaiShu-Md-HK-BF */ 372 { 0x11E5EAD4UL, 0x00000360UL }, /* cvt */ 373 { 0x9DB282B2UL, 0x0000C06EUL }, /* fpgm */ 374 { 0x53E6D7CAUL, 0x00000082UL } /* prep */ 375 }, 376 { /* DFMing-Bd-HK-BF */ 377 { 0x1243EB18UL, 0x00000350UL }, /* cvt */ 378 { 0xBA0A8C30UL, 0x000074ADUL }, /* fpgm */ 379 { 0xF3D83409UL, 0x0000037BUL } /* prep */ 380 }, 381 { /* DLCLiShu */ 382 { 0x07DCF546UL, 0x00000308UL }, /* cvt */ 383 { 0x40FE7C90UL, 0x00008E2AUL }, /* fpgm */ 384 { 0x608174B5UL, 0x0000007AUL } /* prep */ 385 }, 386 { /* DLCHayBold */ 387 { 0xEB891238UL, 0x00000308UL }, /* cvt */ 388 { 0xD2E4DCD4UL, 0x0000676FUL }, /* fpgm */ 389 { 0x8EA5F293UL, 0x000003B8UL } /* prep */ 390 }, 391 { /* HuaTianKaiTi */ 392 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */ 393 { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */ 394 { 0x70020112UL, 0x00000008UL } /* prep */ 395 }, 396 { /* HuaTianSongTi */ 397 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */ 398 { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */ 399 { 0x70020112UL, 0x00000008UL } /* prep */ 400 }, 401 { /* NEC fadpop7.ttf */ 402 { 0x00000000UL, 0x00000000UL }, /* cvt */ 403 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */ 404 { 0xA39B58E3UL, 0x0000117CUL } /* prep */ 405 }, 406 { /* NEC fadrei5.ttf */ 407 { 0x00000000UL, 0x00000000UL }, /* cvt */ 408 { 0x33C41652UL, 0x000000E5UL }, /* fpgm */ 409 { 0x26D6C52AUL, 0x00000F6AUL } /* prep */ 410 }, 411 { /* NEC fangot7.ttf */ 412 { 0x00000000UL, 0x00000000UL }, /* cvt */ 413 { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */ 414 { 0x6C6E4B03UL, 0x00002492UL } /* prep */ 415 }, 416 { /* NEC fangyo5.ttf */ 417 { 0x00000000UL, 0x00000000UL }, /* cvt */ 418 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */ 419 { 0xDE51FAD0UL, 0x0000117CUL } /* prep */ 420 }, 421 { /* NEC fankyo5.ttf */ 422 { 0x00000000UL, 0x00000000UL }, /* cvt */ 423 { 0x85E47664UL, 0x000000E5UL }, /* fpgm */ 424 { 0xA6C62831UL, 0x00001CAAUL } /* prep */ 425 }, 426 { /* NEC fanrgo5.ttf */ 427 { 0x00000000UL, 0x00000000UL }, /* cvt */ 428 { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */ 429 { 0xA0604633UL, 0x00001DE8UL } /* prep */ 430 }, 431 { /* NEC fangot5.ttc */ 432 { 0x00000000UL, 0x00000000UL }, /* cvt */ 433 { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */ 434 { 0x9B5CAA96UL, 0x00001F9AUL } /* prep */ 435 }, 436 { /* NEC fanmin3.ttc */ 437 { 0x00000000UL, 0x00000000UL }, /* cvt */ 438 { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */ 439 { 0xD4127766UL, 0x00002280UL } /* prep */ 440 }, 441 { /* NEC FA-Gothic, 1996 */ 442 { 0x00000000UL, 0x00000000UL }, /* cvt */ 443 { 0x4A692698UL, 0x000001F0UL }, /* fpgm */ 444 { 0x340D4346UL, 0x00001FCAUL } /* prep */ 445 }, 446 { /* NEC FA-Minchou, 1996 */ 447 { 0x00000000UL, 0x00000000UL }, /* cvt */ 448 { 0xCD34C604UL, 0x00000166UL }, /* fpgm */ 449 { 0x6CF31046UL, 0x000022B0UL } /* prep */ 450 }, 451 { /* NEC FA-RoundGothicB, 1996 */ 452 { 0x00000000UL, 0x00000000UL }, /* cvt */ 453 { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */ 454 { 0x40745A5FUL, 0x000022E0UL } /* prep */ 455 }, 456 { /* NEC FA-RoundGothicM, 1996 */ 457 { 0x00000000UL, 0x00000000UL }, /* cvt */ 458 { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */ 459 { 0x3900DED3UL, 0x00001E18UL } /* prep */ 460 }, 461 { /* MINGLI.TTF, 1992 */ 462 { 0x00170003UL, 0x00000060UL }, /* cvt */ 463 { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */ 464 { 0xD643482AUL, 0x00000035UL } /* prep */ 465 }, 466 { /* DFHei-Bd-WIN-HK-BF, issue #1087 */ 467 { 0x1269EB58UL, 0x00000350UL }, /* cvt */ 468 { 0x5CD5957AUL, 0x00006A4EUL }, /* fpgm */ 469 { 0xF758323AUL, 0x00000380UL } /* prep */ 470 }, 471 { /* DFMing-Md-WIN-HK-BF, issue #1087 */ 472 { 0x122FEB0BUL, 0x00000350UL }, /* cvt */ 473 { 0x7F10919AUL, 0x000070A9UL }, /* fpgm */ 474 { 0x7CD7E7B7UL, 0x0000025CUL } /* prep */ 475 } 476 }; 477 478 FT_ULong checksum; 479 int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES]; 480 FT_Bool has_cvt, has_fpgm, has_prep; 481 FT_UShort i; 482 int j, k; 483 484 485 FT_MEM_SET( num_matched_ids, 0, 486 sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES ); 487 has_cvt = FALSE; 488 has_fpgm = FALSE; 489 has_prep = FALSE; 490 491 for ( i = 0; i < face->num_tables; i++ ) 492 { 493 checksum = 0; 494 495 switch( face->dir_tables[i].Tag ) 496 { 497 case TTAG_cvt: 498 k = TRICK_SFNT_ID_cvt; 499 has_cvt = TRUE; 500 break; 501 502 case TTAG_fpgm: 503 k = TRICK_SFNT_ID_fpgm; 504 has_fpgm = TRUE; 505 break; 506 507 case TTAG_prep: 508 k = TRICK_SFNT_ID_prep; 509 has_prep = TRUE; 510 break; 511 512 default: 513 continue; 514 } 515 516 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) 517 if ( face->dir_tables[i].Length == sfnt_id[j][k].Length ) 518 { 519 if ( !checksum ) 520 checksum = tt_get_sfnt_checksum( face, i ); 521 522 if ( sfnt_id[j][k].CheckSum == checksum ) 523 num_matched_ids[j]++; 524 525 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) 526 return TRUE; 527 } 528 } 529 530 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) 531 { 532 if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length ) 533 num_matched_ids[j]++; 534 if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length ) 535 num_matched_ids[j]++; 536 if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length ) 537 num_matched_ids[j]++; 538 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) 539 return TRUE; 540 } 541 542 return FALSE; 543 } 544 545 546 static FT_Bool tt_check_trickyness(FT_Face face)547 tt_check_trickyness( FT_Face face ) 548 { 549 if ( !face ) 550 return FALSE; 551 552 /* For first, check the face name for quick check. */ 553 if ( face->family_name && 554 tt_check_trickyness_family( face->family_name ) ) 555 { 556 FT_TRACE3(( "found as a tricky font" 557 " by its family name: %s\n", face->family_name )); 558 return TRUE; 559 } 560 561 /* Type42 fonts may lack `name' tables, we thus try to identify */ 562 /* tricky fonts by checking the checksums of Type42-persistent */ 563 /* sfnt tables (`cvt', `fpgm', and `prep'). */ 564 if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) ) 565 { 566 FT_TRACE3(( "found as a tricky font" 567 " by its cvt/fpgm/prep table checksum\n" )); 568 return TRUE; 569 } 570 571 return FALSE; 572 } 573 574 #endif /* TT_USE_BYTECODE_INTERPRETER */ 575 576 577 /* Check whether `.notdef' is the only glyph in the `loca' table. */ 578 static FT_Bool tt_check_single_notdef(FT_Face ttface)579 tt_check_single_notdef( FT_Face ttface ) 580 { 581 FT_Bool result = FALSE; 582 583 TT_Face face = (TT_Face)ttface; 584 FT_UInt asize; 585 FT_ULong i; 586 FT_ULong glyph_index = 0; 587 FT_UInt count = 0; 588 589 590 for( i = 0; i < face->num_locations; i++ ) 591 { 592 tt_face_get_location( face, i, &asize ); 593 if ( asize > 0 ) 594 { 595 count += 1; 596 if ( count > 1 ) 597 break; 598 glyph_index = i; 599 } 600 } 601 602 /* Only have a single outline. */ 603 if ( count == 1 ) 604 { 605 if ( glyph_index == 0 ) 606 result = TRUE; 607 else 608 { 609 /* FIXME: Need to test glyphname == .notdef ? */ 610 FT_Error error; 611 char buf[8]; 612 613 614 error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 ); 615 if ( !error && 616 buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) ) 617 result = TRUE; 618 } 619 } 620 621 return result; 622 } 623 624 625 /************************************************************************** 626 * 627 * @Function: 628 * tt_face_init 629 * 630 * @Description: 631 * Initialize a given TrueType face object. 632 * 633 * @Input: 634 * stream :: 635 * The source font stream. 636 * 637 * face_index :: 638 * The index of the TrueType font, if we are opening a 639 * collection, in bits 0-15. The numbered instance 640 * index~+~1 of a GX (sub)font, if applicable, in bits 641 * 16-30. 642 * 643 * num_params :: 644 * Number of additional generic parameters. Ignored. 645 * 646 * params :: 647 * Additional generic parameters. Ignored. 648 * 649 * @InOut: 650 * face :: 651 * The newly built face object. 652 * 653 * @Return: 654 * FreeType error code. 0 means success. 655 */ 656 FT_LOCAL_DEF( FT_Error ) tt_face_init(FT_Stream stream,FT_Face ttface,FT_Int face_index,FT_Int num_params,FT_Parameter * params)657 tt_face_init( FT_Stream stream, 658 FT_Face ttface, /* TT_Face */ 659 FT_Int face_index, 660 FT_Int num_params, 661 FT_Parameter* params ) 662 { 663 FT_Error error; 664 FT_Library library; 665 SFNT_Service sfnt; 666 TT_Face face = (TT_Face)ttface; 667 668 669 FT_TRACE2(( "TTF driver\n" )); 670 671 library = ttface->driver->root.library; 672 673 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); 674 if ( !sfnt ) 675 { 676 FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" )); 677 error = FT_THROW( Missing_Module ); 678 goto Exit; 679 } 680 681 /* create input stream from resource */ 682 if ( FT_STREAM_SEEK( 0 ) ) 683 goto Exit; 684 685 /* check that we have a valid TrueType file */ 686 FT_TRACE2(( " " )); 687 error = sfnt->init_face( stream, face, face_index, num_params, params ); 688 689 /* Stream may have changed. */ 690 stream = face->root.stream; 691 692 if ( error ) 693 goto Exit; 694 695 /* We must also be able to accept Mac/GX fonts, as well as OT ones. */ 696 /* The 0x00020000 tag is completely undocumented; some fonts from */ 697 /* Arphic made for Chinese Windows 3.1 have this. */ 698 if ( face->format_tag != 0x00010000L && /* MS fonts */ 699 face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ 700 face->format_tag != TTAG_true && /* Mac fonts */ 701 face->format_tag != TTAG_0xA5kbd && /* `Keyboard.dfont' (legacy Mac OS X) */ 702 face->format_tag != TTAG_0xA5lst ) /* `LastResort.dfont' (legacy Mac OS X) */ 703 { 704 FT_TRACE2(( " not a TTF font\n" )); 705 goto Bad_Format; 706 } 707 708 #ifdef TT_USE_BYTECODE_INTERPRETER 709 ttface->face_flags |= FT_FACE_FLAG_HINTER; 710 #endif 711 712 /* If we are performing a simple font format check, exit immediately. */ 713 if ( face_index < 0 ) 714 return FT_Err_Ok; 715 716 /* Load font directory */ 717 error = sfnt->load_face( stream, face, face_index, num_params, params ); 718 if ( error ) 719 goto Exit; 720 721 #ifdef TT_USE_BYTECODE_INTERPRETER 722 if ( tt_check_trickyness( ttface ) ) 723 ttface->face_flags |= FT_FACE_FLAG_TRICKY; 724 #endif 725 726 error = tt_face_load_hdmx( face, stream ); 727 if ( error ) 728 goto Exit; 729 730 if ( FT_IS_SCALABLE( ttface ) ) 731 { 732 #ifdef FT_CONFIG_OPTION_INCREMENTAL 733 if ( !ttface->internal->incremental_interface ) 734 #endif 735 { 736 error = tt_face_load_loca( face, stream ); 737 738 /* having a (non-zero) `glyf' table without */ 739 /* a `loca' table is not valid */ 740 if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) ) 741 goto Exit; 742 if ( error ) 743 goto Exit; 744 } 745 746 /* `fpgm', `cvt', and `prep' are optional */ 747 error = tt_face_load_cvt( face, stream ); 748 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 749 goto Exit; 750 751 error = tt_face_load_fpgm( face, stream ); 752 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 753 goto Exit; 754 755 error = tt_face_load_prep( face, stream ); 756 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 757 goto Exit; 758 759 /* Check the scalable flag based on `loca'. */ 760 #ifdef FT_CONFIG_OPTION_INCREMENTAL 761 if ( !ttface->internal->incremental_interface ) 762 #endif 763 { 764 if ( ttface->num_fixed_sizes && 765 face->glyph_locations && 766 tt_check_single_notdef( ttface ) ) 767 { 768 FT_TRACE5(( "tt_face_init:" 769 " Only the `.notdef' glyph has an outline.\n" )); 770 FT_TRACE5(( " " 771 " Resetting scalable flag to FALSE.\n" )); 772 773 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; 774 } 775 } 776 } 777 778 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 779 780 { 781 FT_UInt instance_index = (FT_UInt)face_index >> 16; 782 783 784 if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && 785 instance_index > 0 ) 786 { 787 error = TT_Set_Named_Instance( face, instance_index ); 788 if ( error ) 789 goto Exit; 790 791 tt_apply_mvar( face ); 792 } 793 } 794 795 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 796 797 /* initialize standard glyph loading routines */ 798 TT_Init_Glyph_Loading( face ); 799 800 Exit: 801 return error; 802 803 Bad_Format: 804 error = FT_THROW( Unknown_File_Format ); 805 goto Exit; 806 } 807 808 809 /************************************************************************** 810 * 811 * @Function: 812 * tt_face_done 813 * 814 * @Description: 815 * Finalize a given face object. 816 * 817 * @Input: 818 * face :: 819 * A pointer to the face object to destroy. 820 */ 821 FT_LOCAL_DEF( void ) tt_face_done(FT_Face ttface)822 tt_face_done( FT_Face ttface ) /* TT_Face */ 823 { 824 TT_Face face = (TT_Face)ttface; 825 FT_Memory memory; 826 FT_Stream stream; 827 SFNT_Service sfnt; 828 829 830 if ( !face ) 831 return; 832 833 memory = ttface->memory; 834 stream = ttface->stream; 835 sfnt = (SFNT_Service)face->sfnt; 836 837 /* for `extended TrueType formats' (i.e. compressed versions) */ 838 if ( face->extra.finalizer ) 839 face->extra.finalizer( face->extra.data ); 840 841 if ( sfnt ) 842 sfnt->done_face( face ); 843 844 /* freeing the locations table */ 845 tt_face_done_loca( face ); 846 847 tt_face_free_hdmx( face ); 848 849 /* freeing the CVT */ 850 FT_FREE( face->cvt ); 851 face->cvt_size = 0; 852 853 /* freeing the programs */ 854 FT_FRAME_RELEASE( face->font_program ); 855 FT_FRAME_RELEASE( face->cvt_program ); 856 face->font_program_size = 0; 857 face->cvt_program_size = 0; 858 859 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 860 tt_done_blend( face ); 861 face->blend = NULL; 862 #endif 863 } 864 865 866 /************************************************************************** 867 * 868 * SIZE FUNCTIONS 869 * 870 */ 871 872 #ifdef TT_USE_BYTECODE_INTERPRETER 873 874 /************************************************************************** 875 * 876 * @Function: 877 * tt_size_run_fpgm 878 * 879 * @Description: 880 * Run the font program. 881 * 882 * @Input: 883 * size :: 884 * A handle to the size object. 885 * 886 * pedantic :: 887 * Set if bytecode execution should be pedantic. 888 * 889 * @Return: 890 * FreeType error code. 0 means success. 891 */ 892 FT_LOCAL_DEF( FT_Error ) tt_size_run_fpgm(TT_Size size,FT_Bool pedantic)893 tt_size_run_fpgm( TT_Size size, 894 FT_Bool pedantic ) 895 { 896 TT_Face face = (TT_Face)size->root.face; 897 TT_ExecContext exec; 898 FT_Error error; 899 900 901 exec = size->context; 902 903 error = TT_Load_Context( exec, face, size ); 904 if ( error ) 905 return error; 906 907 exec->callTop = 0; 908 exec->top = 0; 909 910 exec->period = 64; 911 exec->phase = 0; 912 exec->threshold = 0; 913 914 exec->instruction_trap = FALSE; 915 exec->F_dot_P = 0x4000L; 916 917 exec->pedantic_hinting = pedantic; 918 919 { 920 FT_Size_Metrics* size_metrics = &exec->metrics; 921 TT_Size_Metrics* tt_metrics = &exec->tt_metrics; 922 923 924 size_metrics->x_ppem = 0; 925 size_metrics->y_ppem = 0; 926 size_metrics->x_scale = 0; 927 size_metrics->y_scale = 0; 928 929 tt_metrics->ppem = 0; 930 tt_metrics->scale = 0; 931 tt_metrics->ratio = 0x10000L; 932 } 933 934 /* allow font program execution */ 935 TT_Set_CodeRange( exec, 936 tt_coderange_font, 937 face->font_program, 938 (FT_Long)face->font_program_size ); 939 940 /* disable CVT and glyph programs coderange */ 941 TT_Clear_CodeRange( exec, tt_coderange_cvt ); 942 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 943 944 if ( face->font_program_size > 0 ) 945 { 946 TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); 947 948 FT_TRACE4(( "Executing `fpgm' table.\n" )); 949 error = face->interpreter( exec ); 950 #ifdef FT_DEBUG_LEVEL_TRACE 951 if ( error ) 952 FT_TRACE4(( " interpretation failed with error code 0x%x\n", 953 error )); 954 #endif 955 } 956 else 957 error = FT_Err_Ok; 958 959 size->bytecode_ready = error; 960 961 if ( !error ) 962 TT_Save_Context( exec, size ); 963 964 return error; 965 } 966 967 968 /************************************************************************** 969 * 970 * @Function: 971 * tt_size_run_prep 972 * 973 * @Description: 974 * Run the control value program. 975 * 976 * @Input: 977 * size :: 978 * A handle to the size object. 979 * 980 * pedantic :: 981 * Set if bytecode execution should be pedantic. 982 * 983 * @Return: 984 * FreeType error code. 0 means success. 985 */ 986 FT_LOCAL_DEF( FT_Error ) tt_size_run_prep(TT_Size size,FT_Bool pedantic)987 tt_size_run_prep( TT_Size size, 988 FT_Bool pedantic ) 989 { 990 TT_Face face = (TT_Face)size->root.face; 991 TT_ExecContext exec; 992 FT_Error error; 993 FT_UInt i; 994 995 /* unscaled CVT values are already stored in 26.6 format */ 996 FT_Fixed scale = size->ttmetrics.scale >> 6; 997 998 999 /* Scale the cvt values to the new ppem. */ 1000 /* By default, we use the y ppem value for scaling. */ 1001 FT_TRACE6(( "CVT values:\n" )); 1002 for ( i = 0; i < size->cvt_size; i++ ) 1003 { 1004 size->cvt[i] = FT_MulFix( face->cvt[i], scale ); 1005 FT_TRACE6(( " %3d: %f (%f)\n", 1006 i, face->cvt[i] / 64.0, size->cvt[i] / 64.0 )); 1007 } 1008 FT_TRACE6(( "\n" )); 1009 1010 exec = size->context; 1011 1012 error = TT_Load_Context( exec, face, size ); 1013 if ( error ) 1014 return error; 1015 1016 exec->callTop = 0; 1017 exec->top = 0; 1018 1019 exec->instruction_trap = FALSE; 1020 1021 exec->pedantic_hinting = pedantic; 1022 1023 TT_Set_CodeRange( exec, 1024 tt_coderange_cvt, 1025 face->cvt_program, 1026 (FT_Long)face->cvt_program_size ); 1027 1028 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 1029 1030 if ( face->cvt_program_size > 0 ) 1031 { 1032 TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); 1033 1034 FT_TRACE4(( "Executing `prep' table.\n" )); 1035 error = face->interpreter( exec ); 1036 #ifdef FT_DEBUG_LEVEL_TRACE 1037 if ( error ) 1038 FT_TRACE4(( " interpretation failed with error code 0x%x\n", 1039 error )); 1040 #endif 1041 } 1042 else 1043 error = FT_Err_Ok; 1044 1045 size->cvt_ready = error; 1046 1047 /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ 1048 /* graphics state variables to be modified by the CVT program. */ 1049 1050 exec->GS.dualVector.x = 0x4000; 1051 exec->GS.dualVector.y = 0; 1052 exec->GS.projVector.x = 0x4000; 1053 exec->GS.projVector.y = 0x0; 1054 exec->GS.freeVector.x = 0x4000; 1055 exec->GS.freeVector.y = 0x0; 1056 1057 exec->GS.rp0 = 0; 1058 exec->GS.rp1 = 0; 1059 exec->GS.rp2 = 0; 1060 1061 exec->GS.gep0 = 1; 1062 exec->GS.gep1 = 1; 1063 exec->GS.gep2 = 1; 1064 1065 exec->GS.loop = 1; 1066 1067 /* save as default graphics state */ 1068 size->GS = exec->GS; 1069 1070 TT_Save_Context( exec, size ); 1071 1072 return error; 1073 } 1074 1075 1076 static void tt_size_done_bytecode(FT_Size ftsize)1077 tt_size_done_bytecode( FT_Size ftsize ) 1078 { 1079 TT_Size size = (TT_Size)ftsize; 1080 TT_Face face = (TT_Face)ftsize->face; 1081 FT_Memory memory = face->root.memory; 1082 1083 if ( size->context ) 1084 { 1085 TT_Done_Context( size->context ); 1086 size->context = NULL; 1087 } 1088 1089 FT_FREE( size->cvt ); 1090 size->cvt_size = 0; 1091 1092 /* free storage area */ 1093 FT_FREE( size->storage ); 1094 size->storage_size = 0; 1095 1096 /* twilight zone */ 1097 tt_glyphzone_done( &size->twilight ); 1098 1099 FT_FREE( size->function_defs ); 1100 FT_FREE( size->instruction_defs ); 1101 1102 size->num_function_defs = 0; 1103 size->max_function_defs = 0; 1104 size->num_instruction_defs = 0; 1105 size->max_instruction_defs = 0; 1106 1107 size->max_func = 0; 1108 size->max_ins = 0; 1109 1110 size->bytecode_ready = -1; 1111 size->cvt_ready = -1; 1112 } 1113 1114 1115 /* Initialize bytecode-related fields in the size object. */ 1116 /* We do this only if bytecode interpretation is really needed. */ 1117 static FT_Error tt_size_init_bytecode(FT_Size ftsize,FT_Bool pedantic)1118 tt_size_init_bytecode( FT_Size ftsize, 1119 FT_Bool pedantic ) 1120 { 1121 FT_Error error; 1122 TT_Size size = (TT_Size)ftsize; 1123 TT_Face face = (TT_Face)ftsize->face; 1124 FT_Memory memory = face->root.memory; 1125 1126 FT_UShort n_twilight; 1127 TT_MaxProfile* maxp = &face->max_profile; 1128 1129 1130 /* clean up bytecode related data */ 1131 FT_FREE( size->function_defs ); 1132 FT_FREE( size->instruction_defs ); 1133 FT_FREE( size->cvt ); 1134 FT_FREE( size->storage ); 1135 1136 if ( size->context ) 1137 TT_Done_Context( size->context ); 1138 tt_glyphzone_done( &size->twilight ); 1139 1140 size->bytecode_ready = -1; 1141 size->cvt_ready = -1; 1142 1143 size->context = TT_New_Context( (TT_Driver)face->root.driver ); 1144 1145 size->max_function_defs = maxp->maxFunctionDefs; 1146 size->max_instruction_defs = maxp->maxInstructionDefs; 1147 1148 size->num_function_defs = 0; 1149 size->num_instruction_defs = 0; 1150 1151 size->max_func = 0; 1152 size->max_ins = 0; 1153 1154 size->cvt_size = face->cvt_size; 1155 size->storage_size = maxp->maxStorage; 1156 1157 /* Set default metrics */ 1158 { 1159 TT_Size_Metrics* tt_metrics = &size->ttmetrics; 1160 1161 1162 tt_metrics->rotated = FALSE; 1163 tt_metrics->stretched = FALSE; 1164 1165 /* Set default engine compensation. Value 3 is not described */ 1166 /* in the OpenType specification (as of Mai 2019), but Greg */ 1167 /* says that MS handles it the same as `gray'. */ 1168 /* */ 1169 /* The Apple specification says that the compensation for */ 1170 /* `gray' is always zero. FreeType doesn't do any */ 1171 /* compensation at all. */ 1172 tt_metrics->compensations[0] = 0; /* gray */ 1173 tt_metrics->compensations[1] = 0; /* black */ 1174 tt_metrics->compensations[2] = 0; /* white */ 1175 tt_metrics->compensations[3] = 0; /* zero */ 1176 } 1177 1178 /* allocate function defs, instruction defs, cvt, and storage area */ 1179 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || 1180 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || 1181 FT_NEW_ARRAY( size->cvt, size->cvt_size ) || 1182 FT_NEW_ARRAY( size->storage, size->storage_size ) ) 1183 goto Exit; 1184 1185 /* reserve twilight zone */ 1186 n_twilight = maxp->maxTwilightPoints; 1187 1188 /* there are 4 phantom points (do we need this?) */ 1189 n_twilight += 4; 1190 1191 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); 1192 if ( error ) 1193 goto Exit; 1194 1195 size->twilight.n_points = n_twilight; 1196 1197 size->GS = tt_default_graphics_state; 1198 1199 /* set `face->interpreter' according to the debug hook present */ 1200 { 1201 FT_Library library = face->root.driver->root.library; 1202 1203 1204 face->interpreter = (TT_Interpreter) 1205 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; 1206 if ( !face->interpreter ) 1207 face->interpreter = (TT_Interpreter)TT_RunIns; 1208 } 1209 1210 /* Fine, now run the font program! */ 1211 1212 /* In case of an error while executing `fpgm', we intentionally don't */ 1213 /* clean up immediately – bugs in the `fpgm' are so fundamental that */ 1214 /* all following hinting calls should fail. Additionally, `fpgm' is */ 1215 /* to be executed just once; calling it again is completely useless */ 1216 /* and might even lead to extremely slow behaviour if it is malformed */ 1217 /* (containing an infinite loop, for example). */ 1218 error = tt_size_run_fpgm( size, pedantic ); 1219 return error; 1220 1221 Exit: 1222 if ( error ) 1223 tt_size_done_bytecode( ftsize ); 1224 1225 return error; 1226 } 1227 1228 1229 FT_LOCAL_DEF( FT_Error ) tt_size_ready_bytecode(TT_Size size,FT_Bool pedantic)1230 tt_size_ready_bytecode( TT_Size size, 1231 FT_Bool pedantic ) 1232 { 1233 FT_Error error = FT_Err_Ok; 1234 1235 1236 if ( size->bytecode_ready < 0 ) 1237 error = tt_size_init_bytecode( (FT_Size)size, pedantic ); 1238 else 1239 error = size->bytecode_ready; 1240 1241 if ( error ) 1242 goto Exit; 1243 1244 /* rescale CVT when needed */ 1245 if ( size->cvt_ready < 0 ) 1246 { 1247 FT_UShort i; 1248 1249 1250 /* all twilight points are originally zero */ 1251 for ( i = 0; i < size->twilight.n_points; i++ ) 1252 { 1253 size->twilight.org[i].x = 0; 1254 size->twilight.org[i].y = 0; 1255 size->twilight.cur[i].x = 0; 1256 size->twilight.cur[i].y = 0; 1257 } 1258 1259 /* clear storage area */ 1260 for ( i = 0; i < size->storage_size; i++ ) 1261 size->storage[i] = 0; 1262 1263 size->GS = tt_default_graphics_state; 1264 1265 error = tt_size_run_prep( size, pedantic ); 1266 } 1267 else 1268 error = size->cvt_ready; 1269 1270 Exit: 1271 return error; 1272 } 1273 1274 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1275 1276 1277 /************************************************************************** 1278 * 1279 * @Function: 1280 * tt_size_init 1281 * 1282 * @Description: 1283 * Initialize a new TrueType size object. 1284 * 1285 * @InOut: 1286 * size :: 1287 * A handle to the size object. 1288 * 1289 * @Return: 1290 * FreeType error code. 0 means success. 1291 */ 1292 FT_LOCAL_DEF( FT_Error ) tt_size_init(FT_Size ttsize)1293 tt_size_init( FT_Size ttsize ) /* TT_Size */ 1294 { 1295 TT_Size size = (TT_Size)ttsize; 1296 FT_Error error = FT_Err_Ok; 1297 1298 1299 #ifdef TT_USE_BYTECODE_INTERPRETER 1300 size->bytecode_ready = -1; 1301 size->cvt_ready = -1; 1302 #endif 1303 1304 size->ttmetrics.valid = FALSE; 1305 size->strike_index = 0xFFFFFFFFUL; 1306 1307 return error; 1308 } 1309 1310 1311 /************************************************************************** 1312 * 1313 * @Function: 1314 * tt_size_done 1315 * 1316 * @Description: 1317 * The TrueType size object finalizer. 1318 * 1319 * @Input: 1320 * size :: 1321 * A handle to the target size object. 1322 */ 1323 FT_LOCAL_DEF( void ) tt_size_done(FT_Size ttsize)1324 tt_size_done( FT_Size ttsize ) /* TT_Size */ 1325 { 1326 TT_Size size = (TT_Size)ttsize; 1327 1328 1329 #ifdef TT_USE_BYTECODE_INTERPRETER 1330 tt_size_done_bytecode( ttsize ); 1331 #endif 1332 1333 size->ttmetrics.valid = FALSE; 1334 } 1335 1336 1337 /************************************************************************** 1338 * 1339 * @Function: 1340 * tt_size_reset 1341 * 1342 * @Description: 1343 * Reset a TrueType size when resolutions and character dimensions 1344 * have been changed. 1345 * 1346 * @Input: 1347 * size :: 1348 * A handle to the target size object. 1349 * 1350 * only_height :: 1351 * Only recompute ascender, descender, and height; 1352 * this flag is used for variation fonts where 1353 * `tt_size_reset' is used as an iterator function. 1354 */ 1355 FT_LOCAL_DEF( FT_Error ) tt_size_reset(TT_Size size,FT_Bool only_height)1356 tt_size_reset( TT_Size size, 1357 FT_Bool only_height ) 1358 { 1359 TT_Face face; 1360 FT_Size_Metrics* size_metrics; 1361 1362 1363 face = (TT_Face)size->root.face; 1364 1365 /* nothing to do for CFF2 */ 1366 if ( face->is_cff2 ) 1367 return FT_Err_Ok; 1368 1369 size->ttmetrics.valid = FALSE; 1370 1371 size_metrics = &size->hinted_metrics; 1372 1373 /* copy the result from base layer */ 1374 *size_metrics = size->root.metrics; 1375 1376 if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 ) 1377 return FT_THROW( Invalid_PPem ); 1378 1379 /* This bit flag, if set, indicates that the ppems must be */ 1380 /* rounded to integers. Nearly all TrueType fonts have this bit */ 1381 /* set, as hinting won't work really well otherwise. */ 1382 /* */ 1383 if ( face->header.Flags & 8 ) 1384 { 1385 /* the TT spec always asks for ROUND, not FLOOR or CEIL */ 1386 size_metrics->ascender = FT_PIX_ROUND( 1387 FT_MulFix( face->root.ascender, 1388 size_metrics->y_scale ) ); 1389 size_metrics->descender = FT_PIX_ROUND( 1390 FT_MulFix( face->root.descender, 1391 size_metrics->y_scale ) ); 1392 size_metrics->height = FT_PIX_ROUND( 1393 FT_MulFix( face->root.height, 1394 size_metrics->y_scale ) ); 1395 } 1396 1397 size->ttmetrics.valid = TRUE; 1398 1399 if ( only_height ) 1400 { 1401 /* we must not recompute the scaling values here since */ 1402 /* `tt_size_reset' was already called (with only_height = 0) */ 1403 return FT_Err_Ok; 1404 } 1405 1406 if ( face->header.Flags & 8 ) 1407 { 1408 /* base scaling values on integer ppem values, */ 1409 /* as mandated by the TrueType specification */ 1410 size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6, 1411 face->root.units_per_EM ); 1412 size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6, 1413 face->root.units_per_EM ); 1414 1415 size_metrics->max_advance = FT_PIX_ROUND( 1416 FT_MulFix( face->root.max_advance_width, 1417 size_metrics->x_scale ) ); 1418 } 1419 1420 /* compute new transformation */ 1421 if ( size_metrics->x_ppem >= size_metrics->y_ppem ) 1422 { 1423 size->ttmetrics.scale = size_metrics->x_scale; 1424 size->ttmetrics.ppem = size_metrics->x_ppem; 1425 size->ttmetrics.x_ratio = 0x10000L; 1426 size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem, 1427 size_metrics->x_ppem ); 1428 } 1429 else 1430 { 1431 size->ttmetrics.scale = size_metrics->y_scale; 1432 size->ttmetrics.ppem = size_metrics->y_ppem; 1433 size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem, 1434 size_metrics->y_ppem ); 1435 size->ttmetrics.y_ratio = 0x10000L; 1436 } 1437 1438 size->metrics = size_metrics; 1439 1440 #ifdef TT_USE_BYTECODE_INTERPRETER 1441 size->cvt_ready = -1; 1442 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1443 1444 return FT_Err_Ok; 1445 } 1446 1447 1448 /************************************************************************** 1449 * 1450 * @Function: 1451 * tt_driver_init 1452 * 1453 * @Description: 1454 * Initialize a given TrueType driver object. 1455 * 1456 * @Input: 1457 * driver :: 1458 * A handle to the target driver object. 1459 * 1460 * @Return: 1461 * FreeType error code. 0 means success. 1462 */ 1463 FT_LOCAL_DEF( FT_Error ) tt_driver_init(FT_Module ttdriver)1464 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ 1465 { 1466 1467 #ifdef TT_USE_BYTECODE_INTERPRETER 1468 1469 TT_Driver driver = (TT_Driver)ttdriver; 1470 1471 driver->interpreter_version = TT_INTERPRETER_VERSION_35; 1472 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY 1473 driver->interpreter_version = TT_INTERPRETER_VERSION_38; 1474 #endif 1475 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 1476 driver->interpreter_version = TT_INTERPRETER_VERSION_40; 1477 #endif 1478 1479 #else /* !TT_USE_BYTECODE_INTERPRETER */ 1480 1481 FT_UNUSED( ttdriver ); 1482 1483 #endif /* !TT_USE_BYTECODE_INTERPRETER */ 1484 1485 return FT_Err_Ok; 1486 } 1487 1488 1489 /************************************************************************** 1490 * 1491 * @Function: 1492 * tt_driver_done 1493 * 1494 * @Description: 1495 * Finalize a given TrueType driver. 1496 * 1497 * @Input: 1498 * driver :: 1499 * A handle to the target TrueType driver. 1500 */ 1501 FT_LOCAL_DEF( void ) tt_driver_done(FT_Module ttdriver)1502 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ 1503 { 1504 FT_UNUSED( ttdriver ); 1505 } 1506 1507 1508 /************************************************************************** 1509 * 1510 * @Function: 1511 * tt_slot_init 1512 * 1513 * @Description: 1514 * Initialize a new slot object. 1515 * 1516 * @InOut: 1517 * slot :: 1518 * A handle to the slot object. 1519 * 1520 * @Return: 1521 * FreeType error code. 0 means success. 1522 */ 1523 FT_LOCAL_DEF( FT_Error ) tt_slot_init(FT_GlyphSlot slot)1524 tt_slot_init( FT_GlyphSlot slot ) 1525 { 1526 return FT_GlyphLoader_CreateExtra( slot->internal->loader ); 1527 } 1528 1529 1530 /* END */ 1531