1 /**************************************************************************** 2 * 3 * ttobjs.c 4 * 5 * Objects manager (body). 6 * 7 * Copyright (C) 1996-2023 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 FT_HAS_SBIX( ttface ) ) 732 { 733 #ifdef FT_CONFIG_OPTION_INCREMENTAL 734 if ( !ttface->internal->incremental_interface ) 735 #endif 736 { 737 error = tt_face_load_loca( face, stream ); 738 739 /* having a (non-zero) `glyf' table without */ 740 /* a `loca' table is not valid */ 741 if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) ) 742 goto Exit; 743 if ( error ) 744 goto Exit; 745 } 746 747 /* `fpgm', `cvt', and `prep' are optional */ 748 error = tt_face_load_cvt( face, stream ); 749 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 750 goto Exit; 751 752 error = tt_face_load_fpgm( face, stream ); 753 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 754 goto Exit; 755 756 error = tt_face_load_prep( face, stream ); 757 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 758 goto Exit; 759 760 /* Check the scalable flag based on `loca'. */ 761 #ifdef FT_CONFIG_OPTION_INCREMENTAL 762 if ( !ttface->internal->incremental_interface ) 763 #endif 764 { 765 if ( ttface->num_fixed_sizes && 766 face->glyph_locations && 767 tt_check_single_notdef( ttface ) ) 768 { 769 FT_TRACE5(( "tt_face_init:" 770 " Only the `.notdef' glyph has an outline.\n" )); 771 FT_TRACE5(( " " 772 " Resetting scalable flag to FALSE.\n" )); 773 774 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; 775 } 776 } 777 } 778 779 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 780 781 { 782 FT_UInt instance_index = (FT_UInt)face_index >> 16; 783 784 785 if ( FT_HAS_MULTIPLE_MASTERS( ttface ) && 786 instance_index > 0 ) 787 { 788 error = TT_Set_Named_Instance( face, instance_index ); 789 if ( error ) 790 goto Exit; 791 792 tt_apply_mvar( face ); 793 } 794 } 795 796 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 797 798 /* initialize standard glyph loading routines */ 799 TT_Init_Glyph_Loading( face ); 800 801 Exit: 802 return error; 803 804 Bad_Format: 805 error = FT_THROW( Unknown_File_Format ); 806 goto Exit; 807 } 808 809 810 /************************************************************************** 811 * 812 * @Function: 813 * tt_face_done 814 * 815 * @Description: 816 * Finalize a given face object. 817 * 818 * @Input: 819 * face :: 820 * A pointer to the face object to destroy. 821 */ 822 FT_LOCAL_DEF( void ) tt_face_done(FT_Face ttface)823 tt_face_done( FT_Face ttface ) /* TT_Face */ 824 { 825 TT_Face face = (TT_Face)ttface; 826 FT_Memory memory; 827 FT_Stream stream; 828 SFNT_Service sfnt; 829 830 831 if ( !face ) 832 return; 833 834 memory = ttface->memory; 835 stream = ttface->stream; 836 sfnt = (SFNT_Service)face->sfnt; 837 838 /* for `extended TrueType formats' (i.e. compressed versions) */ 839 if ( face->extra.finalizer ) 840 face->extra.finalizer( face->extra.data ); 841 842 if ( sfnt ) 843 sfnt->done_face( face ); 844 845 /* freeing the locations table */ 846 tt_face_done_loca( face ); 847 848 tt_face_free_hdmx( face ); 849 850 /* freeing the CVT */ 851 FT_FREE( face->cvt ); 852 face->cvt_size = 0; 853 854 /* freeing the programs */ 855 FT_FRAME_RELEASE( face->font_program ); 856 FT_FRAME_RELEASE( face->cvt_program ); 857 face->font_program_size = 0; 858 face->cvt_program_size = 0; 859 860 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 861 tt_done_blend( face ); 862 face->blend = NULL; 863 #endif 864 } 865 866 867 /************************************************************************** 868 * 869 * SIZE FUNCTIONS 870 * 871 */ 872 873 #ifdef TT_USE_BYTECODE_INTERPRETER 874 875 /************************************************************************** 876 * 877 * @Function: 878 * tt_size_run_fpgm 879 * 880 * @Description: 881 * Run the font program. 882 * 883 * @Input: 884 * size :: 885 * A handle to the size object. 886 * 887 * pedantic :: 888 * Set if bytecode execution should be pedantic. 889 * 890 * @Return: 891 * FreeType error code. 0 means success. 892 */ 893 FT_LOCAL_DEF( FT_Error ) tt_size_run_fpgm(TT_Size size,FT_Bool pedantic)894 tt_size_run_fpgm( TT_Size size, 895 FT_Bool pedantic ) 896 { 897 TT_Face face = (TT_Face)size->root.face; 898 TT_ExecContext exec; 899 FT_Error error; 900 901 902 exec = size->context; 903 904 error = TT_Load_Context( exec, face, size ); 905 if ( error ) 906 return error; 907 908 exec->callTop = 0; 909 exec->top = 0; 910 911 exec->period = 64; 912 exec->phase = 0; 913 exec->threshold = 0; 914 915 exec->instruction_trap = FALSE; 916 exec->F_dot_P = 0x4000L; 917 918 exec->pedantic_hinting = pedantic; 919 920 { 921 FT_Size_Metrics* size_metrics = &exec->metrics; 922 TT_Size_Metrics* tt_metrics = &exec->tt_metrics; 923 924 925 size_metrics->x_ppem = 0; 926 size_metrics->y_ppem = 0; 927 size_metrics->x_scale = 0; 928 size_metrics->y_scale = 0; 929 930 tt_metrics->ppem = 0; 931 tt_metrics->scale = 0; 932 tt_metrics->ratio = 0x10000L; 933 } 934 935 /* allow font program execution */ 936 TT_Set_CodeRange( exec, 937 tt_coderange_font, 938 face->font_program, 939 (FT_Long)face->font_program_size ); 940 941 /* disable CVT and glyph programs coderange */ 942 TT_Clear_CodeRange( exec, tt_coderange_cvt ); 943 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 944 945 if ( face->font_program_size > 0 ) 946 { 947 TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); 948 949 FT_TRACE4(( "Executing `fpgm' table.\n" )); 950 error = face->interpreter( exec ); 951 #ifdef FT_DEBUG_LEVEL_TRACE 952 if ( error ) 953 FT_TRACE4(( " interpretation failed with error code 0x%x\n", 954 error )); 955 #endif 956 } 957 else 958 error = FT_Err_Ok; 959 960 size->bytecode_ready = error; 961 962 if ( !error ) 963 TT_Save_Context( exec, size ); 964 965 return error; 966 } 967 968 969 /************************************************************************** 970 * 971 * @Function: 972 * tt_size_run_prep 973 * 974 * @Description: 975 * Run the control value program. 976 * 977 * @Input: 978 * size :: 979 * A handle to the size object. 980 * 981 * pedantic :: 982 * Set if bytecode execution should be pedantic. 983 * 984 * @Return: 985 * FreeType error code. 0 means success. 986 */ 987 FT_LOCAL_DEF( FT_Error ) tt_size_run_prep(TT_Size size,FT_Bool pedantic)988 tt_size_run_prep( TT_Size size, 989 FT_Bool pedantic ) 990 { 991 TT_Face face = (TT_Face)size->root.face; 992 TT_ExecContext exec; 993 FT_Error error; 994 FT_UInt i; 995 996 /* unscaled CVT values are already stored in 26.6 format */ 997 FT_Fixed scale = size->ttmetrics.scale >> 6; 998 999 1000 /* Scale the cvt values to the new ppem. */ 1001 /* By default, we use the y ppem value for scaling. */ 1002 FT_TRACE6(( "CVT values:\n" )); 1003 for ( i = 0; i < size->cvt_size; i++ ) 1004 { 1005 size->cvt[i] = FT_MulFix( face->cvt[i], scale ); 1006 FT_TRACE6(( " %3d: %f (%f)\n", 1007 i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 )); 1008 } 1009 FT_TRACE6(( "\n" )); 1010 1011 exec = size->context; 1012 1013 error = TT_Load_Context( exec, face, size ); 1014 if ( error ) 1015 return error; 1016 1017 exec->callTop = 0; 1018 exec->top = 0; 1019 1020 exec->instruction_trap = FALSE; 1021 1022 exec->pedantic_hinting = pedantic; 1023 1024 TT_Set_CodeRange( exec, 1025 tt_coderange_cvt, 1026 face->cvt_program, 1027 (FT_Long)face->cvt_program_size ); 1028 1029 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 1030 1031 if ( face->cvt_program_size > 0 ) 1032 { 1033 TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); 1034 1035 FT_TRACE4(( "Executing `prep' table.\n" )); 1036 error = face->interpreter( exec ); 1037 #ifdef FT_DEBUG_LEVEL_TRACE 1038 if ( error ) 1039 FT_TRACE4(( " interpretation failed with error code 0x%x\n", 1040 error )); 1041 #endif 1042 } 1043 else 1044 error = FT_Err_Ok; 1045 1046 size->cvt_ready = error; 1047 1048 /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ 1049 /* graphics state variables to be modified by the CVT program. */ 1050 1051 exec->GS.dualVector.x = 0x4000; 1052 exec->GS.dualVector.y = 0; 1053 exec->GS.projVector.x = 0x4000; 1054 exec->GS.projVector.y = 0x0; 1055 exec->GS.freeVector.x = 0x4000; 1056 exec->GS.freeVector.y = 0x0; 1057 1058 exec->GS.rp0 = 0; 1059 exec->GS.rp1 = 0; 1060 exec->GS.rp2 = 0; 1061 1062 exec->GS.gep0 = 1; 1063 exec->GS.gep1 = 1; 1064 exec->GS.gep2 = 1; 1065 1066 exec->GS.loop = 1; 1067 1068 /* save as default graphics state */ 1069 size->GS = exec->GS; 1070 1071 TT_Save_Context( exec, size ); 1072 1073 return error; 1074 } 1075 1076 1077 static void tt_size_done_bytecode(FT_Size ftsize)1078 tt_size_done_bytecode( FT_Size ftsize ) 1079 { 1080 TT_Size size = (TT_Size)ftsize; 1081 TT_Face face = (TT_Face)ftsize->face; 1082 FT_Memory memory = face->root.memory; 1083 1084 if ( size->context ) 1085 { 1086 TT_Done_Context( size->context ); 1087 size->context = NULL; 1088 } 1089 1090 FT_FREE( size->cvt ); 1091 size->cvt_size = 0; 1092 1093 /* free storage area */ 1094 FT_FREE( size->storage ); 1095 size->storage_size = 0; 1096 1097 /* twilight zone */ 1098 tt_glyphzone_done( &size->twilight ); 1099 1100 FT_FREE( size->function_defs ); 1101 FT_FREE( size->instruction_defs ); 1102 1103 size->num_function_defs = 0; 1104 size->max_function_defs = 0; 1105 size->num_instruction_defs = 0; 1106 size->max_instruction_defs = 0; 1107 1108 size->max_func = 0; 1109 size->max_ins = 0; 1110 1111 size->bytecode_ready = -1; 1112 size->cvt_ready = -1; 1113 } 1114 1115 1116 /* Initialize bytecode-related fields in the size object. */ 1117 /* We do this only if bytecode interpretation is really needed. */ 1118 static FT_Error tt_size_init_bytecode(FT_Size ftsize,FT_Bool pedantic)1119 tt_size_init_bytecode( FT_Size ftsize, 1120 FT_Bool pedantic ) 1121 { 1122 FT_Error error; 1123 TT_Size size = (TT_Size)ftsize; 1124 TT_Face face = (TT_Face)ftsize->face; 1125 FT_Memory memory = face->root.memory; 1126 1127 FT_UShort n_twilight; 1128 TT_MaxProfile* maxp = &face->max_profile; 1129 1130 1131 /* clean up bytecode related data */ 1132 FT_FREE( size->function_defs ); 1133 FT_FREE( size->instruction_defs ); 1134 FT_FREE( size->cvt ); 1135 FT_FREE( size->storage ); 1136 1137 if ( size->context ) 1138 TT_Done_Context( size->context ); 1139 tt_glyphzone_done( &size->twilight ); 1140 1141 size->bytecode_ready = -1; 1142 size->cvt_ready = -1; 1143 1144 size->context = TT_New_Context( (TT_Driver)face->root.driver ); 1145 1146 size->max_function_defs = maxp->maxFunctionDefs; 1147 size->max_instruction_defs = maxp->maxInstructionDefs; 1148 1149 size->num_function_defs = 0; 1150 size->num_instruction_defs = 0; 1151 1152 size->max_func = 0; 1153 size->max_ins = 0; 1154 1155 size->cvt_size = face->cvt_size; 1156 size->storage_size = maxp->maxStorage; 1157 1158 /* Set default metrics */ 1159 { 1160 TT_Size_Metrics* tt_metrics = &size->ttmetrics; 1161 1162 1163 tt_metrics->rotated = FALSE; 1164 tt_metrics->stretched = FALSE; 1165 1166 /* Set default engine compensation. Value 3 is not described */ 1167 /* in the OpenType specification (as of Mai 2019), but Greg */ 1168 /* says that MS handles it the same as `gray'. */ 1169 /* */ 1170 /* The Apple specification says that the compensation for */ 1171 /* `gray' is always zero. FreeType doesn't do any */ 1172 /* compensation at all. */ 1173 tt_metrics->compensations[0] = 0; /* gray */ 1174 tt_metrics->compensations[1] = 0; /* black */ 1175 tt_metrics->compensations[2] = 0; /* white */ 1176 tt_metrics->compensations[3] = 0; /* zero */ 1177 } 1178 1179 /* allocate function defs, instruction defs, cvt, and storage area */ 1180 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || 1181 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || 1182 FT_NEW_ARRAY( size->cvt, size->cvt_size ) || 1183 FT_NEW_ARRAY( size->storage, size->storage_size ) ) 1184 goto Exit; 1185 1186 /* reserve twilight zone */ 1187 n_twilight = maxp->maxTwilightPoints; 1188 1189 /* there are 4 phantom points (do we need this?) */ 1190 n_twilight += 4; 1191 1192 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); 1193 if ( error ) 1194 goto Exit; 1195 1196 size->twilight.n_points = n_twilight; 1197 1198 size->GS = tt_default_graphics_state; 1199 1200 /* set `face->interpreter' according to the debug hook present */ 1201 { 1202 FT_Library library = face->root.driver->root.library; 1203 1204 1205 face->interpreter = (TT_Interpreter) 1206 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; 1207 if ( !face->interpreter ) 1208 face->interpreter = (TT_Interpreter)TT_RunIns; 1209 } 1210 1211 /* Fine, now run the font program! */ 1212 1213 /* In case of an error while executing `fpgm', we intentionally don't */ 1214 /* clean up immediately – bugs in the `fpgm' are so fundamental that */ 1215 /* all following hinting calls should fail. Additionally, `fpgm' is */ 1216 /* to be executed just once; calling it again is completely useless */ 1217 /* and might even lead to extremely slow behaviour if it is malformed */ 1218 /* (containing an infinite loop, for example). */ 1219 error = tt_size_run_fpgm( size, pedantic ); 1220 return error; 1221 1222 Exit: 1223 if ( error ) 1224 tt_size_done_bytecode( ftsize ); 1225 1226 return error; 1227 } 1228 1229 1230 FT_LOCAL_DEF( FT_Error ) tt_size_ready_bytecode(TT_Size size,FT_Bool pedantic)1231 tt_size_ready_bytecode( TT_Size size, 1232 FT_Bool pedantic ) 1233 { 1234 FT_Error error = FT_Err_Ok; 1235 1236 1237 if ( size->bytecode_ready < 0 ) 1238 error = tt_size_init_bytecode( (FT_Size)size, pedantic ); 1239 else 1240 error = size->bytecode_ready; 1241 1242 if ( error ) 1243 goto Exit; 1244 1245 /* rescale CVT when needed */ 1246 if ( size->cvt_ready < 0 ) 1247 { 1248 FT_UShort i; 1249 1250 1251 /* all twilight points are originally zero */ 1252 for ( i = 0; i < size->twilight.n_points; i++ ) 1253 { 1254 size->twilight.org[i].x = 0; 1255 size->twilight.org[i].y = 0; 1256 size->twilight.cur[i].x = 0; 1257 size->twilight.cur[i].y = 0; 1258 } 1259 1260 /* clear storage area */ 1261 for ( i = 0; i < size->storage_size; i++ ) 1262 size->storage[i] = 0; 1263 1264 size->GS = tt_default_graphics_state; 1265 1266 error = tt_size_run_prep( size, pedantic ); 1267 } 1268 else 1269 error = size->cvt_ready; 1270 1271 Exit: 1272 return error; 1273 } 1274 1275 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1276 1277 1278 /************************************************************************** 1279 * 1280 * @Function: 1281 * tt_size_init 1282 * 1283 * @Description: 1284 * Initialize a new TrueType size object. 1285 * 1286 * @InOut: 1287 * size :: 1288 * A handle to the size object. 1289 * 1290 * @Return: 1291 * FreeType error code. 0 means success. 1292 */ 1293 FT_LOCAL_DEF( FT_Error ) tt_size_init(FT_Size ttsize)1294 tt_size_init( FT_Size ttsize ) /* TT_Size */ 1295 { 1296 TT_Size size = (TT_Size)ttsize; 1297 FT_Error error = FT_Err_Ok; 1298 1299 1300 #ifdef TT_USE_BYTECODE_INTERPRETER 1301 size->bytecode_ready = -1; 1302 size->cvt_ready = -1; 1303 #endif 1304 1305 size->ttmetrics.valid = FALSE; 1306 size->strike_index = 0xFFFFFFFFUL; 1307 1308 return error; 1309 } 1310 1311 1312 /************************************************************************** 1313 * 1314 * @Function: 1315 * tt_size_done 1316 * 1317 * @Description: 1318 * The TrueType size object finalizer. 1319 * 1320 * @Input: 1321 * size :: 1322 * A handle to the target size object. 1323 */ 1324 FT_LOCAL_DEF( void ) tt_size_done(FT_Size ttsize)1325 tt_size_done( FT_Size ttsize ) /* TT_Size */ 1326 { 1327 TT_Size size = (TT_Size)ttsize; 1328 1329 1330 #ifdef TT_USE_BYTECODE_INTERPRETER 1331 tt_size_done_bytecode( ttsize ); 1332 #endif 1333 1334 size->ttmetrics.valid = FALSE; 1335 } 1336 1337 1338 /************************************************************************** 1339 * 1340 * @Function: 1341 * tt_size_reset_height 1342 * 1343 * @Description: 1344 * Recompute a TrueType size's ascender, descender, and height 1345 * when resolutions and character dimensions have been changed. 1346 * Used for variation fonts as an iterator function. 1347 * 1348 * @Input: 1349 * ft_size :: 1350 * A handle to the target TT_Size object. This function will be called 1351 * through a `FT_Size_Reset_Func` pointer which takes `FT_Size`. This 1352 * function must take `FT_Size` as a result. The passed `FT_Size` is 1353 * expected to point to a `TT_Size`. 1354 */ 1355 FT_LOCAL_DEF( FT_Error ) tt_size_reset_height(FT_Size ft_size)1356 tt_size_reset_height( FT_Size ft_size ) 1357 { 1358 TT_Size size = (TT_Size)ft_size; 1359 TT_Face face = (TT_Face)size->root.face; 1360 FT_Size_Metrics* size_metrics = &size->hinted_metrics; 1361 1362 size->ttmetrics.valid = FALSE; 1363 1364 /* copy the result from base layer */ 1365 *size_metrics = size->root.metrics; 1366 1367 if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 ) 1368 return FT_THROW( Invalid_PPem ); 1369 1370 /* This bit flag, if set, indicates that the ppems must be */ 1371 /* rounded to integers. Nearly all TrueType fonts have this bit */ 1372 /* set, as hinting won't work really well otherwise. */ 1373 /* */ 1374 if ( face->header.Flags & 8 ) 1375 { 1376 /* the TT spec always asks for ROUND, not FLOOR or CEIL */ 1377 size_metrics->ascender = FT_PIX_ROUND( 1378 FT_MulFix( face->root.ascender, 1379 size_metrics->y_scale ) ); 1380 size_metrics->descender = FT_PIX_ROUND( 1381 FT_MulFix( face->root.descender, 1382 size_metrics->y_scale ) ); 1383 size_metrics->height = FT_PIX_ROUND( 1384 FT_MulFix( face->root.height, 1385 size_metrics->y_scale ) ); 1386 } 1387 1388 size->ttmetrics.valid = TRUE; 1389 1390 return FT_Err_Ok; 1391 } 1392 1393 1394 /************************************************************************** 1395 * 1396 * @Function: 1397 * tt_size_reset 1398 * 1399 * @Description: 1400 * Reset a TrueType size when resolutions and character dimensions 1401 * have been changed. 1402 * 1403 * @Input: 1404 * size :: 1405 * A handle to the target size object. 1406 */ 1407 FT_LOCAL_DEF( FT_Error ) tt_size_reset(TT_Size size)1408 tt_size_reset( TT_Size size ) 1409 { 1410 FT_Error error; 1411 TT_Face face = (TT_Face)size->root.face; 1412 FT_Size_Metrics* size_metrics = &size->hinted_metrics; 1413 1414 1415 error = tt_size_reset_height( (FT_Size)size ); 1416 if ( error ) 1417 return error; 1418 1419 if ( face->header.Flags & 8 ) 1420 { 1421 /* base scaling values on integer ppem values, */ 1422 /* as mandated by the TrueType specification */ 1423 size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6, 1424 face->root.units_per_EM ); 1425 size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6, 1426 face->root.units_per_EM ); 1427 1428 size_metrics->max_advance = FT_PIX_ROUND( 1429 FT_MulFix( face->root.max_advance_width, 1430 size_metrics->x_scale ) ); 1431 } 1432 1433 /* compute new transformation */ 1434 if ( size_metrics->x_ppem >= size_metrics->y_ppem ) 1435 { 1436 size->ttmetrics.scale = size_metrics->x_scale; 1437 size->ttmetrics.ppem = size_metrics->x_ppem; 1438 size->ttmetrics.x_ratio = 0x10000L; 1439 size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem, 1440 size_metrics->x_ppem ); 1441 } 1442 else 1443 { 1444 size->ttmetrics.scale = size_metrics->y_scale; 1445 size->ttmetrics.ppem = size_metrics->y_ppem; 1446 size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem, 1447 size_metrics->y_ppem ); 1448 size->ttmetrics.y_ratio = 0x10000L; 1449 } 1450 1451 size->widthp = tt_face_get_device_metrics( face, size_metrics->x_ppem, 0 ); 1452 1453 size->metrics = size_metrics; 1454 1455 #ifdef TT_USE_BYTECODE_INTERPRETER 1456 size->cvt_ready = -1; 1457 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1458 1459 return FT_Err_Ok; 1460 } 1461 1462 1463 /************************************************************************** 1464 * 1465 * @Function: 1466 * tt_driver_init 1467 * 1468 * @Description: 1469 * Initialize a given TrueType driver object. 1470 * 1471 * @Input: 1472 * driver :: 1473 * A handle to the target driver object. 1474 * 1475 * @Return: 1476 * FreeType error code. 0 means success. 1477 */ 1478 FT_LOCAL_DEF( FT_Error ) tt_driver_init(FT_Module ttdriver)1479 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ 1480 { 1481 1482 #ifdef TT_USE_BYTECODE_INTERPRETER 1483 1484 TT_Driver driver = (TT_Driver)ttdriver; 1485 1486 driver->interpreter_version = TT_INTERPRETER_VERSION_35; 1487 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_INFINALITY 1488 driver->interpreter_version = TT_INTERPRETER_VERSION_38; 1489 #endif 1490 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 1491 driver->interpreter_version = TT_INTERPRETER_VERSION_40; 1492 #endif 1493 1494 #else /* !TT_USE_BYTECODE_INTERPRETER */ 1495 1496 FT_UNUSED( ttdriver ); 1497 1498 #endif /* !TT_USE_BYTECODE_INTERPRETER */ 1499 1500 return FT_Err_Ok; 1501 } 1502 1503 1504 /************************************************************************** 1505 * 1506 * @Function: 1507 * tt_driver_done 1508 * 1509 * @Description: 1510 * Finalize a given TrueType driver. 1511 * 1512 * @Input: 1513 * driver :: 1514 * A handle to the target TrueType driver. 1515 */ 1516 FT_LOCAL_DEF( void ) tt_driver_done(FT_Module ttdriver)1517 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ 1518 { 1519 FT_UNUSED( ttdriver ); 1520 } 1521 1522 1523 /************************************************************************** 1524 * 1525 * @Function: 1526 * tt_slot_init 1527 * 1528 * @Description: 1529 * Initialize a new slot object. 1530 * 1531 * @InOut: 1532 * slot :: 1533 * A handle to the slot object. 1534 * 1535 * @Return: 1536 * FreeType error code. 0 means success. 1537 */ 1538 FT_LOCAL_DEF( FT_Error ) tt_slot_init(FT_GlyphSlot slot)1539 tt_slot_init( FT_GlyphSlot slot ) 1540 { 1541 return FT_GlyphLoader_CreateExtra( slot->internal->loader ); 1542 } 1543 1544 1545 /* END */ 1546