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 318 #define TRICK_SFNT_ID_cvt 0 319 #define TRICK_SFNT_ID_fpgm 1 320 #define TRICK_SFNT_ID_prep 2 321 322 { /* MingLiU 1995 */ 323 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */ 324 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */ 325 { 0xA344A1EAUL, 0x000001E1UL } /* prep */ 326 }, 327 { /* MingLiU 1996- */ 328 { 0x05BCF058UL, 0x000002E4UL }, /* cvt */ 329 { 0x28233BF1UL, 0x000087C4UL }, /* fpgm */ 330 { 0xA344A1EBUL, 0x000001E1UL } /* prep */ 331 }, 332 { /* DFGothic-EB */ 333 { 0x12C3EBB2UL, 0x00000350UL }, /* cvt */ 334 { 0xB680EE64UL, 0x000087A7UL }, /* fpgm */ 335 { 0xCE939563UL, 0x00000758UL } /* prep */ 336 }, 337 { /* DFGyoSho-Lt */ 338 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ 339 { 0xCE5956E9UL, 0x0000BC85UL }, /* fpgm */ 340 { 0x8272F416UL, 0x00000045UL } /* prep */ 341 }, 342 { /* DFHei-Md-HK-BF */ 343 { 0x1257EB46UL, 0x00000350UL }, /* cvt */ 344 { 0xF699D160UL, 0x0000715FUL }, /* fpgm */ 345 { 0xD222F568UL, 0x000003BCUL } /* prep */ 346 }, 347 { /* DFHSGothic-W5 */ 348 { 0x1262EB4EUL, 0x00000350UL }, /* cvt */ 349 { 0xE86A5D64UL, 0x00007940UL }, /* fpgm */ 350 { 0x7850F729UL, 0x000005FFUL } /* prep */ 351 }, 352 { /* DFHSMincho-W3 */ 353 { 0x122DEB0AUL, 0x00000350UL }, /* cvt */ 354 { 0x3D16328AUL, 0x0000859BUL }, /* fpgm */ 355 { 0xA93FC33BUL, 0x000002CBUL } /* prep */ 356 }, 357 { /* DFHSMincho-W7 */ 358 { 0x125FEB26UL, 0x00000350UL }, /* cvt */ 359 { 0xA5ACC982UL, 0x00007EE1UL }, /* fpgm */ 360 { 0x90999196UL, 0x0000041FUL } /* prep */ 361 }, 362 { /* DFKaiShu */ 363 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ 364 { 0x5A30CA3BUL, 0x00009063UL }, /* fpgm */ 365 { 0x13A42602UL, 0x0000007EUL } /* prep */ 366 }, 367 { /* DFKaiShu, variant */ 368 { 0x11E5EAD4UL, 0x00000350UL }, /* cvt */ 369 { 0xA6E78C01UL, 0x00008998UL }, /* fpgm */ 370 { 0x13A42602UL, 0x0000007EUL } /* prep */ 371 }, 372 { /* DFKaiShu-Md-HK-BF */ 373 { 0x11E5EAD4UL, 0x00000360UL }, /* cvt */ 374 { 0x9DB282B2UL, 0x0000C06EUL }, /* fpgm */ 375 { 0x53E6D7CAUL, 0x00000082UL } /* prep */ 376 }, 377 { /* DFMing-Bd-HK-BF */ 378 { 0x1243EB18UL, 0x00000350UL }, /* cvt */ 379 { 0xBA0A8C30UL, 0x000074ADUL }, /* fpgm */ 380 { 0xF3D83409UL, 0x0000037BUL } /* prep */ 381 }, 382 { /* DLCLiShu */ 383 { 0x07DCF546UL, 0x00000308UL }, /* cvt */ 384 { 0x40FE7C90UL, 0x00008E2AUL }, /* fpgm */ 385 { 0x608174B5UL, 0x0000007AUL } /* prep */ 386 }, 387 { /* DLCHayBold */ 388 { 0xEB891238UL, 0x00000308UL }, /* cvt */ 389 { 0xD2E4DCD4UL, 0x0000676FUL }, /* fpgm */ 390 { 0x8EA5F293UL, 0x000003B8UL } /* prep */ 391 }, 392 { /* HuaTianKaiTi */ 393 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */ 394 { 0x9C9E48B8UL, 0x0000BEA2UL }, /* fpgm */ 395 { 0x70020112UL, 0x00000008UL } /* prep */ 396 }, 397 { /* HuaTianSongTi */ 398 { 0xFFFBFFFCUL, 0x00000008UL }, /* cvt */ 399 { 0x0A5A0483UL, 0x00017C39UL }, /* fpgm */ 400 { 0x70020112UL, 0x00000008UL } /* prep */ 401 }, 402 { /* NEC fadpop7.ttf */ 403 { 0x00000000UL, 0x00000000UL }, /* cvt */ 404 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */ 405 { 0xA39B58E3UL, 0x0000117CUL } /* prep */ 406 }, 407 { /* NEC fadrei5.ttf */ 408 { 0x00000000UL, 0x00000000UL }, /* cvt */ 409 { 0x33C41652UL, 0x000000E5UL }, /* fpgm */ 410 { 0x26D6C52AUL, 0x00000F6AUL } /* prep */ 411 }, 412 { /* NEC fangot7.ttf */ 413 { 0x00000000UL, 0x00000000UL }, /* cvt */ 414 { 0x6DB1651DUL, 0x0000019DUL }, /* fpgm */ 415 { 0x6C6E4B03UL, 0x00002492UL } /* prep */ 416 }, 417 { /* NEC fangyo5.ttf */ 418 { 0x00000000UL, 0x00000000UL }, /* cvt */ 419 { 0x40C92555UL, 0x000000E5UL }, /* fpgm */ 420 { 0xDE51FAD0UL, 0x0000117CUL } /* prep */ 421 }, 422 { /* NEC fankyo5.ttf */ 423 { 0x00000000UL, 0x00000000UL }, /* cvt */ 424 { 0x85E47664UL, 0x000000E5UL }, /* fpgm */ 425 { 0xA6C62831UL, 0x00001CAAUL } /* prep */ 426 }, 427 { /* NEC fanrgo5.ttf */ 428 { 0x00000000UL, 0x00000000UL }, /* cvt */ 429 { 0x2D891CFDUL, 0x0000019DUL }, /* fpgm */ 430 { 0xA0604633UL, 0x00001DE8UL } /* prep */ 431 }, 432 { /* NEC fangot5.ttc */ 433 { 0x00000000UL, 0x00000000UL }, /* cvt */ 434 { 0x40AA774CUL, 0x000001CBUL }, /* fpgm */ 435 { 0x9B5CAA96UL, 0x00001F9AUL } /* prep */ 436 }, 437 { /* NEC fanmin3.ttc */ 438 { 0x00000000UL, 0x00000000UL }, /* cvt */ 439 { 0x0D3DE9CBUL, 0x00000141UL }, /* fpgm */ 440 { 0xD4127766UL, 0x00002280UL } /* prep */ 441 }, 442 { /* NEC FA-Gothic, 1996 */ 443 { 0x00000000UL, 0x00000000UL }, /* cvt */ 444 { 0x4A692698UL, 0x000001F0UL }, /* fpgm */ 445 { 0x340D4346UL, 0x00001FCAUL } /* prep */ 446 }, 447 { /* NEC FA-Minchou, 1996 */ 448 { 0x00000000UL, 0x00000000UL }, /* cvt */ 449 { 0xCD34C604UL, 0x00000166UL }, /* fpgm */ 450 { 0x6CF31046UL, 0x000022B0UL } /* prep */ 451 }, 452 { /* NEC FA-RoundGothicB, 1996 */ 453 { 0x00000000UL, 0x00000000UL }, /* cvt */ 454 { 0x5DA75315UL, 0x0000019DUL }, /* fpgm */ 455 { 0x40745A5FUL, 0x000022E0UL } /* prep */ 456 }, 457 { /* NEC FA-RoundGothicM, 1996 */ 458 { 0x00000000UL, 0x00000000UL }, /* cvt */ 459 { 0xF055FC48UL, 0x000001C2UL }, /* fpgm */ 460 { 0x3900DED3UL, 0x00001E18UL } /* prep */ 461 }, 462 { /* MINGLI.TTF, 1992 */ 463 { 0x00170003UL, 0x00000060UL }, /* cvt */ 464 { 0xDBB4306EUL, 0x000058AAUL }, /* fpgm */ 465 { 0xD643482AUL, 0x00000035UL } /* prep */ 466 }, 467 { /* DFHei-Bd-WIN-HK-BF, issue #1087 */ 468 { 0x1269EB58UL, 0x00000350UL }, /* cvt */ 469 { 0x5CD5957AUL, 0x00006A4EUL }, /* fpgm */ 470 { 0xF758323AUL, 0x00000380UL } /* prep */ 471 }, 472 { /* DFMing-Md-WIN-HK-BF, issue #1087 */ 473 { 0x122FEB0BUL, 0x00000350UL }, /* cvt */ 474 { 0x7F10919AUL, 0x000070A9UL }, /* fpgm */ 475 { 0x7CD7E7B7UL, 0x0000025CUL } /* prep */ 476 } 477 }; 478 479 FT_ULong checksum; 480 int num_matched_ids[TRICK_SFNT_IDS_NUM_FACES]; 481 FT_Bool has_cvt, has_fpgm, has_prep; 482 FT_UShort i; 483 int j, k; 484 485 486 FT_MEM_SET( num_matched_ids, 0, 487 sizeof ( int ) * TRICK_SFNT_IDS_NUM_FACES ); 488 has_cvt = FALSE; 489 has_fpgm = FALSE; 490 has_prep = FALSE; 491 492 for ( i = 0; i < face->num_tables; i++ ) 493 { 494 checksum = 0; 495 496 switch( face->dir_tables[i].Tag ) 497 { 498 case TTAG_cvt: 499 k = TRICK_SFNT_ID_cvt; 500 has_cvt = TRUE; 501 break; 502 503 case TTAG_fpgm: 504 k = TRICK_SFNT_ID_fpgm; 505 has_fpgm = TRUE; 506 break; 507 508 case TTAG_prep: 509 k = TRICK_SFNT_ID_prep; 510 has_prep = TRUE; 511 break; 512 513 default: 514 continue; 515 } 516 517 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) 518 if ( face->dir_tables[i].Length == sfnt_id[j][k].Length ) 519 { 520 if ( !checksum ) 521 checksum = tt_get_sfnt_checksum( face, i ); 522 523 if ( sfnt_id[j][k].CheckSum == checksum ) 524 num_matched_ids[j]++; 525 526 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) 527 return TRUE; 528 } 529 } 530 531 for ( j = 0; j < TRICK_SFNT_IDS_NUM_FACES; j++ ) 532 { 533 if ( !has_cvt && !sfnt_id[j][TRICK_SFNT_ID_cvt].Length ) 534 num_matched_ids[j]++; 535 if ( !has_fpgm && !sfnt_id[j][TRICK_SFNT_ID_fpgm].Length ) 536 num_matched_ids[j]++; 537 if ( !has_prep && !sfnt_id[j][TRICK_SFNT_ID_prep].Length ) 538 num_matched_ids[j]++; 539 if ( num_matched_ids[j] == TRICK_SFNT_IDS_PER_FACE ) 540 return TRUE; 541 } 542 543 return FALSE; 544 } 545 546 547 static FT_Bool tt_check_trickyness(FT_Face face)548 tt_check_trickyness( FT_Face face ) 549 { 550 if ( !face ) 551 return FALSE; 552 553 /* For first, check the face name for quick check. */ 554 if ( face->family_name && 555 tt_check_trickyness_family( face->family_name ) ) 556 { 557 FT_TRACE3(( "found as a tricky font" 558 " by its family name: %s\n", face->family_name )); 559 return TRUE; 560 } 561 562 /* Type42 fonts may lack `name' tables, we thus try to identify */ 563 /* tricky fonts by checking the checksums of Type42-persistent */ 564 /* sfnt tables (`cvt', `fpgm', and `prep'). */ 565 if ( tt_check_trickyness_sfnt_ids( (TT_Face)face ) ) 566 { 567 FT_TRACE3(( "found as a tricky font" 568 " by its cvt/fpgm/prep table checksum\n" )); 569 return TRUE; 570 } 571 572 return FALSE; 573 } 574 575 #endif /* TT_USE_BYTECODE_INTERPRETER */ 576 577 578 /* Check whether `.notdef' is the only glyph in the `loca' table. */ 579 static FT_Bool tt_check_single_notdef(FT_Face ttface)580 tt_check_single_notdef( FT_Face ttface ) 581 { 582 FT_Bool result = FALSE; 583 584 TT_Face face = (TT_Face)ttface; 585 FT_ULong asize; 586 FT_ULong i; 587 FT_ULong glyph_index = 0; 588 FT_UInt count = 0; 589 590 591 for( i = 0; i < face->num_locations; i++ ) 592 { 593 tt_face_get_location( ttface, i, &asize ); 594 if ( asize > 0 ) 595 { 596 count += 1; 597 if ( count > 1 ) 598 break; 599 glyph_index = i; 600 } 601 } 602 603 /* Only have a single outline. */ 604 if ( count == 1 ) 605 { 606 if ( glyph_index == 0 ) 607 result = TRUE; 608 else 609 { 610 /* FIXME: Need to test glyphname == .notdef ? */ 611 FT_Error error; 612 char buf[8]; 613 614 615 error = FT_Get_Glyph_Name( ttface, glyph_index, buf, 8 ); 616 if ( !error && 617 buf[0] == '.' && !ft_strncmp( buf, ".notdef", 8 ) ) 618 result = TRUE; 619 } 620 } 621 622 return result; 623 } 624 625 626 /************************************************************************** 627 * 628 * @Function: 629 * tt_face_init 630 * 631 * @Description: 632 * Initialize a given TrueType face object. 633 * 634 * @Input: 635 * stream :: 636 * The source font stream. 637 * 638 * face_index :: 639 * The index of the TrueType font, if we are opening a 640 * collection, in bits 0-15. The numbered instance 641 * index~+~1 of a GX (sub)font, if applicable, in bits 642 * 16-30. 643 * 644 * num_params :: 645 * Number of additional generic parameters. Ignored. 646 * 647 * params :: 648 * Additional generic parameters. Ignored. 649 * 650 * @InOut: 651 * face :: 652 * The newly built face object. 653 * 654 * @Return: 655 * FreeType error code. 0 means success. 656 */ 657 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)658 tt_face_init( FT_Stream stream, 659 FT_Face ttface, /* TT_Face */ 660 FT_Int face_index, 661 FT_Int num_params, 662 FT_Parameter* params ) 663 { 664 FT_Error error; 665 FT_Library library; 666 SFNT_Service sfnt; 667 TT_Face face = (TT_Face)ttface; 668 669 670 FT_TRACE2(( "TTF driver\n" )); 671 672 library = ttface->driver->root.library; 673 674 sfnt = (SFNT_Service)FT_Get_Module_Interface( library, "sfnt" ); 675 if ( !sfnt ) 676 { 677 FT_ERROR(( "tt_face_init: cannot access `sfnt' module\n" )); 678 error = FT_THROW( Missing_Module ); 679 goto Exit; 680 } 681 682 /* create input stream from resource */ 683 if ( FT_STREAM_SEEK( 0 ) ) 684 goto Exit; 685 686 /* check that we have a valid TrueType file */ 687 FT_TRACE2(( " " )); 688 error = sfnt->init_face( stream, face, face_index, num_params, params ); 689 690 /* Stream may have changed. */ 691 stream = face->root.stream; 692 693 if ( error ) 694 goto Exit; 695 696 /* We must also be able to accept Mac/GX fonts, as well as OT ones. */ 697 /* The 0x00020000 tag is completely undocumented; some fonts from */ 698 /* Arphic made for Chinese Windows 3.1 have this. */ 699 if ( face->format_tag != 0x00010000L && /* MS fonts */ 700 face->format_tag != 0x00020000L && /* CJK fonts for Win 3.1 */ 701 face->format_tag != TTAG_true && /* Mac fonts */ 702 face->format_tag != TTAG_0xA5kbd && /* `Keyboard.dfont' (legacy Mac OS X) */ 703 face->format_tag != TTAG_0xA5lst ) /* `LastResort.dfont' (legacy Mac OS X) */ 704 { 705 FT_TRACE2(( " not a TTF font\n" )); 706 goto Bad_Format; 707 } 708 709 #ifdef TT_USE_BYTECODE_INTERPRETER 710 ttface->face_flags |= FT_FACE_FLAG_HINTER; 711 #endif 712 713 /* If we are performing a simple font format check, exit immediately. */ 714 if ( face_index < 0 ) 715 return FT_Err_Ok; 716 717 /* Load font directory */ 718 error = sfnt->load_face( stream, face, face_index, num_params, params ); 719 if ( error ) 720 goto Exit; 721 722 #ifdef TT_USE_BYTECODE_INTERPRETER 723 if ( tt_check_trickyness( ttface ) ) 724 ttface->face_flags |= FT_FACE_FLAG_TRICKY; 725 #endif 726 727 error = tt_face_load_hdmx( face, stream ); 728 if ( error ) 729 goto Exit; 730 731 if ( FT_IS_SCALABLE( ttface ) || 732 FT_HAS_SBIX( ttface ) ) 733 { 734 #ifdef FT_CONFIG_OPTION_INCREMENTAL 735 if ( !ttface->internal->incremental_interface ) 736 #endif 737 { 738 error = tt_face_load_loca( face, stream ); 739 740 /* having a (non-zero) `glyf' table without */ 741 /* a `loca' table is not valid */ 742 if ( face->glyf_len && FT_ERR_EQ( error, Table_Missing ) ) 743 goto Exit; 744 if ( error ) 745 goto Exit; 746 } 747 748 /* `fpgm', `cvt', and `prep' are optional */ 749 error = tt_face_load_cvt( face, stream ); 750 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 751 goto Exit; 752 753 error = tt_face_load_fpgm( face, stream ); 754 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 755 goto Exit; 756 757 error = tt_face_load_prep( face, stream ); 758 if ( error && FT_ERR_NEQ( error, Table_Missing ) ) 759 goto Exit; 760 761 /* Check the scalable flag based on `loca'. */ 762 #ifdef FT_CONFIG_OPTION_INCREMENTAL 763 if ( !ttface->internal->incremental_interface ) 764 #endif 765 { 766 if ( ttface->num_fixed_sizes && 767 face->glyph_locations && 768 tt_check_single_notdef( ttface ) ) 769 { 770 FT_TRACE5(( "tt_face_init:" 771 " Only the `.notdef' glyph has an outline.\n" )); 772 FT_TRACE5(( " " 773 " Resetting scalable flag to FALSE.\n" )); 774 775 ttface->face_flags &= ~FT_FACE_FLAG_SCALABLE; 776 } 777 } 778 } 779 780 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 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 = FT_Set_Named_Instance( ttface, instance_index ); 789 if ( error ) 790 goto Exit; 791 } 792 } 793 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */ 794 795 /* initialize standard glyph loading routines */ 796 TT_Init_Glyph_Loading( face ); 797 798 Exit: 799 return error; 800 801 Bad_Format: 802 error = FT_THROW( Unknown_File_Format ); 803 goto Exit; 804 } 805 806 807 /************************************************************************** 808 * 809 * @Function: 810 * tt_face_done 811 * 812 * @Description: 813 * Finalize a given face object. 814 * 815 * @Input: 816 * face :: 817 * A pointer to the face object to destroy. 818 */ 819 FT_LOCAL_DEF( void ) tt_face_done(FT_Face ttface)820 tt_face_done( FT_Face ttface ) /* TT_Face */ 821 { 822 TT_Face face = (TT_Face)ttface; 823 FT_Memory memory; 824 FT_Stream stream; 825 SFNT_Service sfnt; 826 827 828 if ( !face ) 829 return; 830 831 memory = ttface->memory; 832 stream = ttface->stream; 833 sfnt = (SFNT_Service)face->sfnt; 834 835 /* for `extended TrueType formats' (i.e. compressed versions) */ 836 if ( face->extra.finalizer ) 837 face->extra.finalizer( face->extra.data ); 838 839 if ( sfnt ) 840 sfnt->done_face( face ); 841 842 /* freeing the locations table */ 843 tt_face_done_loca( face ); 844 845 tt_face_free_hdmx( face ); 846 847 /* freeing the CVT */ 848 FT_FREE( face->cvt ); 849 face->cvt_size = 0; 850 851 /* freeing the programs */ 852 FT_FRAME_RELEASE( face->font_program ); 853 FT_FRAME_RELEASE( face->cvt_program ); 854 face->font_program_size = 0; 855 face->cvt_program_size = 0; 856 857 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT 858 tt_done_blend( ttface ); 859 face->blend = NULL; 860 #endif 861 } 862 863 864 /************************************************************************** 865 * 866 * SIZE FUNCTIONS 867 * 868 */ 869 870 #ifdef TT_USE_BYTECODE_INTERPRETER 871 872 /************************************************************************** 873 * 874 * @Function: 875 * tt_size_run_fpgm 876 * 877 * @Description: 878 * Run the font program. 879 * 880 * @Input: 881 * size :: 882 * A handle to the size object. 883 * 884 * pedantic :: 885 * Set if bytecode execution should be pedantic. 886 * 887 * @Return: 888 * FreeType error code. 0 means success. 889 */ 890 FT_LOCAL_DEF( FT_Error ) tt_size_run_fpgm(TT_Size size,FT_Bool pedantic)891 tt_size_run_fpgm( TT_Size size, 892 FT_Bool pedantic ) 893 { 894 TT_Face face = (TT_Face)size->root.face; 895 TT_ExecContext exec; 896 FT_Error error; 897 898 899 exec = size->context; 900 901 error = TT_Load_Context( exec, face, size ); 902 if ( error ) 903 return error; 904 905 exec->callTop = 0; 906 exec->top = 0; 907 908 exec->period = 64; 909 exec->phase = 0; 910 exec->threshold = 0; 911 912 exec->instruction_trap = FALSE; 913 exec->F_dot_P = 0x4000L; 914 915 exec->pedantic_hinting = pedantic; 916 917 { 918 FT_Size_Metrics* size_metrics = &exec->metrics; 919 TT_Size_Metrics* tt_metrics = &exec->tt_metrics; 920 921 922 size_metrics->x_ppem = 0; 923 size_metrics->y_ppem = 0; 924 size_metrics->x_scale = 0; 925 size_metrics->y_scale = 0; 926 927 tt_metrics->ppem = 0; 928 tt_metrics->scale = 0; 929 tt_metrics->ratio = 0x10000L; 930 } 931 932 /* allow font program execution */ 933 TT_Set_CodeRange( exec, 934 tt_coderange_font, 935 face->font_program, 936 (FT_Long)face->font_program_size ); 937 938 /* disable CVT and glyph programs coderange */ 939 TT_Clear_CodeRange( exec, tt_coderange_cvt ); 940 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 941 942 if ( face->font_program_size > 0 ) 943 { 944 TT_Goto_CodeRange( exec, tt_coderange_font, 0 ); 945 946 FT_TRACE4(( "Executing `fpgm' table.\n" )); 947 error = face->interpreter( exec ); 948 #ifdef FT_DEBUG_LEVEL_TRACE 949 if ( error ) 950 FT_TRACE4(( " interpretation failed with error code 0x%x\n", 951 error )); 952 #endif 953 } 954 else 955 error = FT_Err_Ok; 956 957 size->bytecode_ready = error; 958 959 if ( !error ) 960 TT_Save_Context( exec, size ); 961 962 return error; 963 } 964 965 966 /************************************************************************** 967 * 968 * @Function: 969 * tt_size_run_prep 970 * 971 * @Description: 972 * Run the control value program. 973 * 974 * @Input: 975 * size :: 976 * A handle to the size object. 977 * 978 * pedantic :: 979 * Set if bytecode execution should be pedantic. 980 * 981 * @Return: 982 * FreeType error code. 0 means success. 983 */ 984 FT_LOCAL_DEF( FT_Error ) tt_size_run_prep(TT_Size size,FT_Bool pedantic)985 tt_size_run_prep( TT_Size size, 986 FT_Bool pedantic ) 987 { 988 TT_Face face = (TT_Face)size->root.face; 989 TT_ExecContext exec; 990 FT_Error error; 991 FT_UInt i; 992 993 /* unscaled CVT values are already stored in 26.6 format */ 994 FT_Fixed scale = size->ttmetrics.scale >> 6; 995 996 997 /* Scale the cvt values to the new ppem. */ 998 /* By default, we use the y ppem value for scaling. */ 999 FT_TRACE6(( "CVT values:\n" )); 1000 for ( i = 0; i < size->cvt_size; i++ ) 1001 { 1002 size->cvt[i] = FT_MulFix( face->cvt[i], scale ); 1003 FT_TRACE6(( " %3d: %f (%f)\n", 1004 i, (double)face->cvt[i] / 64, (double)size->cvt[i] / 64 )); 1005 } 1006 FT_TRACE6(( "\n" )); 1007 1008 exec = size->context; 1009 1010 error = TT_Load_Context( exec, face, size ); 1011 if ( error ) 1012 return error; 1013 1014 exec->callTop = 0; 1015 exec->top = 0; 1016 1017 exec->instruction_trap = FALSE; 1018 1019 exec->pedantic_hinting = pedantic; 1020 1021 TT_Set_CodeRange( exec, 1022 tt_coderange_cvt, 1023 face->cvt_program, 1024 (FT_Long)face->cvt_program_size ); 1025 1026 TT_Clear_CodeRange( exec, tt_coderange_glyph ); 1027 1028 if ( face->cvt_program_size > 0 ) 1029 { 1030 TT_Goto_CodeRange( exec, tt_coderange_cvt, 0 ); 1031 1032 FT_TRACE4(( "Executing `prep' table.\n" )); 1033 error = face->interpreter( exec ); 1034 #ifdef FT_DEBUG_LEVEL_TRACE 1035 if ( error ) 1036 FT_TRACE4(( " interpretation failed with error code 0x%x\n", 1037 error )); 1038 #endif 1039 } 1040 else 1041 error = FT_Err_Ok; 1042 1043 size->cvt_ready = error; 1044 1045 /* UNDOCUMENTED! The MS rasterizer doesn't allow the following */ 1046 /* graphics state variables to be modified by the CVT program. */ 1047 1048 exec->GS.dualVector.x = 0x4000; 1049 exec->GS.dualVector.y = 0; 1050 exec->GS.projVector.x = 0x4000; 1051 exec->GS.projVector.y = 0x0; 1052 exec->GS.freeVector.x = 0x4000; 1053 exec->GS.freeVector.y = 0x0; 1054 1055 exec->GS.rp0 = 0; 1056 exec->GS.rp1 = 0; 1057 exec->GS.rp2 = 0; 1058 1059 exec->GS.gep0 = 1; 1060 exec->GS.gep1 = 1; 1061 exec->GS.gep2 = 1; 1062 1063 exec->GS.loop = 1; 1064 1065 /* save as default graphics state */ 1066 size->GS = exec->GS; 1067 1068 TT_Save_Context( exec, size ); 1069 1070 return error; 1071 } 1072 1073 1074 static void tt_size_done_bytecode(FT_Size ftsize)1075 tt_size_done_bytecode( FT_Size ftsize ) 1076 { 1077 TT_Size size = (TT_Size)ftsize; 1078 TT_Face face = (TT_Face)ftsize->face; 1079 FT_Memory memory = face->root.memory; 1080 1081 if ( size->context ) 1082 { 1083 TT_Done_Context( size->context ); 1084 size->context = NULL; 1085 } 1086 1087 FT_FREE( size->cvt ); 1088 size->cvt_size = 0; 1089 1090 /* free storage area */ 1091 FT_FREE( size->storage ); 1092 size->storage_size = 0; 1093 1094 /* twilight zone */ 1095 tt_glyphzone_done( &size->twilight ); 1096 1097 FT_FREE( size->function_defs ); 1098 FT_FREE( size->instruction_defs ); 1099 1100 size->num_function_defs = 0; 1101 size->max_function_defs = 0; 1102 size->num_instruction_defs = 0; 1103 size->max_instruction_defs = 0; 1104 1105 size->max_func = 0; 1106 size->max_ins = 0; 1107 1108 size->bytecode_ready = -1; 1109 size->cvt_ready = -1; 1110 } 1111 1112 1113 /* Initialize bytecode-related fields in the size object. */ 1114 /* We do this only if bytecode interpretation is really needed. */ 1115 static FT_Error tt_size_init_bytecode(FT_Size ftsize,FT_Bool pedantic)1116 tt_size_init_bytecode( FT_Size ftsize, 1117 FT_Bool pedantic ) 1118 { 1119 FT_Error error; 1120 TT_Size size = (TT_Size)ftsize; 1121 TT_Face face = (TT_Face)ftsize->face; 1122 FT_Memory memory = face->root.memory; 1123 1124 FT_UShort n_twilight; 1125 TT_MaxProfile* maxp = &face->max_profile; 1126 1127 1128 /* clean up bytecode related data */ 1129 FT_FREE( size->function_defs ); 1130 FT_FREE( size->instruction_defs ); 1131 FT_FREE( size->cvt ); 1132 FT_FREE( size->storage ); 1133 1134 if ( size->context ) 1135 TT_Done_Context( size->context ); 1136 tt_glyphzone_done( &size->twilight ); 1137 1138 size->bytecode_ready = -1; 1139 size->cvt_ready = -1; 1140 1141 size->context = TT_New_Context( (TT_Driver)face->root.driver ); 1142 1143 size->max_function_defs = maxp->maxFunctionDefs; 1144 size->max_instruction_defs = maxp->maxInstructionDefs; 1145 1146 size->num_function_defs = 0; 1147 size->num_instruction_defs = 0; 1148 1149 size->max_func = 0; 1150 size->max_ins = 0; 1151 1152 size->cvt_size = face->cvt_size; 1153 size->storage_size = maxp->maxStorage; 1154 1155 /* Set default metrics */ 1156 { 1157 TT_Size_Metrics* tt_metrics = &size->ttmetrics; 1158 1159 1160 tt_metrics->rotated = FALSE; 1161 tt_metrics->stretched = FALSE; 1162 1163 /* Set default engine compensation. Value 3 is not described */ 1164 /* in the OpenType specification (as of Mai 2019), but Greg */ 1165 /* says that MS handles it the same as `gray'. */ 1166 /* */ 1167 /* The Apple specification says that the compensation for */ 1168 /* `gray' is always zero. FreeType doesn't do any */ 1169 /* compensation at all. */ 1170 tt_metrics->compensations[0] = 0; /* gray */ 1171 tt_metrics->compensations[1] = 0; /* black */ 1172 tt_metrics->compensations[2] = 0; /* white */ 1173 tt_metrics->compensations[3] = 0; /* zero */ 1174 } 1175 1176 /* allocate function defs, instruction defs, cvt, and storage area */ 1177 if ( FT_NEW_ARRAY( size->function_defs, size->max_function_defs ) || 1178 FT_NEW_ARRAY( size->instruction_defs, size->max_instruction_defs ) || 1179 FT_NEW_ARRAY( size->cvt, size->cvt_size ) || 1180 FT_NEW_ARRAY( size->storage, size->storage_size ) ) 1181 goto Exit; 1182 1183 /* reserve twilight zone */ 1184 n_twilight = maxp->maxTwilightPoints; 1185 1186 /* there are 4 phantom points (do we need this?) */ 1187 n_twilight += 4; 1188 1189 error = tt_glyphzone_new( memory, n_twilight, 0, &size->twilight ); 1190 if ( error ) 1191 goto Exit; 1192 1193 size->twilight.n_points = n_twilight; 1194 1195 size->GS = tt_default_graphics_state; 1196 1197 /* set `face->interpreter' according to the debug hook present */ 1198 { 1199 FT_Library library = face->root.driver->root.library; 1200 1201 1202 face->interpreter = (TT_Interpreter) 1203 library->debug_hooks[FT_DEBUG_HOOK_TRUETYPE]; 1204 if ( !face->interpreter ) 1205 face->interpreter = (TT_Interpreter)TT_RunIns; 1206 } 1207 1208 /* Fine, now run the font program! */ 1209 1210 /* In case of an error while executing `fpgm', we intentionally don't */ 1211 /* clean up immediately – bugs in the `fpgm' are so fundamental that */ 1212 /* all following hinting calls should fail. Additionally, `fpgm' is */ 1213 /* to be executed just once; calling it again is completely useless */ 1214 /* and might even lead to extremely slow behaviour if it is malformed */ 1215 /* (containing an infinite loop, for example). */ 1216 error = tt_size_run_fpgm( size, pedantic ); 1217 return error; 1218 1219 Exit: 1220 if ( error ) 1221 tt_size_done_bytecode( ftsize ); 1222 1223 return error; 1224 } 1225 1226 1227 FT_LOCAL_DEF( FT_Error ) tt_size_ready_bytecode(TT_Size size,FT_Bool pedantic)1228 tt_size_ready_bytecode( TT_Size size, 1229 FT_Bool pedantic ) 1230 { 1231 FT_Error error = FT_Err_Ok; 1232 1233 1234 if ( size->bytecode_ready < 0 ) 1235 error = tt_size_init_bytecode( (FT_Size)size, pedantic ); 1236 else 1237 error = size->bytecode_ready; 1238 1239 if ( error ) 1240 goto Exit; 1241 1242 /* rescale CVT when needed */ 1243 if ( size->cvt_ready < 0 ) 1244 { 1245 FT_UShort i; 1246 1247 1248 /* all twilight points are originally zero */ 1249 for ( i = 0; i < size->twilight.n_points; i++ ) 1250 { 1251 size->twilight.org[i].x = 0; 1252 size->twilight.org[i].y = 0; 1253 size->twilight.cur[i].x = 0; 1254 size->twilight.cur[i].y = 0; 1255 } 1256 1257 /* clear storage area */ 1258 for ( i = 0; i < size->storage_size; i++ ) 1259 size->storage[i] = 0; 1260 1261 size->GS = tt_default_graphics_state; 1262 1263 error = tt_size_run_prep( size, pedantic ); 1264 } 1265 else 1266 error = size->cvt_ready; 1267 1268 Exit: 1269 return error; 1270 } 1271 1272 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1273 1274 1275 /************************************************************************** 1276 * 1277 * @Function: 1278 * tt_size_init 1279 * 1280 * @Description: 1281 * Initialize a new TrueType size object. 1282 * 1283 * @InOut: 1284 * size :: 1285 * A handle to the size object. 1286 * 1287 * @Return: 1288 * FreeType error code. 0 means success. 1289 */ 1290 FT_LOCAL_DEF( FT_Error ) tt_size_init(FT_Size ttsize)1291 tt_size_init( FT_Size ttsize ) /* TT_Size */ 1292 { 1293 TT_Size size = (TT_Size)ttsize; 1294 FT_Error error = FT_Err_Ok; 1295 1296 1297 #ifdef TT_USE_BYTECODE_INTERPRETER 1298 size->bytecode_ready = -1; 1299 size->cvt_ready = -1; 1300 #endif 1301 1302 size->ttmetrics.valid = FALSE; 1303 size->strike_index = 0xFFFFFFFFUL; 1304 1305 return error; 1306 } 1307 1308 1309 /************************************************************************** 1310 * 1311 * @Function: 1312 * tt_size_done 1313 * 1314 * @Description: 1315 * The TrueType size object finalizer. 1316 * 1317 * @Input: 1318 * size :: 1319 * A handle to the target size object. 1320 */ 1321 FT_LOCAL_DEF( void ) tt_size_done(FT_Size ttsize)1322 tt_size_done( FT_Size ttsize ) /* TT_Size */ 1323 { 1324 TT_Size size = (TT_Size)ttsize; 1325 1326 1327 #ifdef TT_USE_BYTECODE_INTERPRETER 1328 tt_size_done_bytecode( ttsize ); 1329 #endif 1330 1331 size->ttmetrics.valid = FALSE; 1332 } 1333 1334 1335 /************************************************************************** 1336 * 1337 * @Function: 1338 * tt_size_reset_height 1339 * 1340 * @Description: 1341 * Recompute a TrueType size's ascender, descender, and height 1342 * when resolutions and character dimensions have been changed. 1343 * Used for variation fonts as an iterator function. 1344 * 1345 * @Input: 1346 * ft_size :: 1347 * A handle to the target TT_Size object. This function will be called 1348 * through a `FT_Size_Reset_Func` pointer which takes `FT_Size`. This 1349 * function must take `FT_Size` as a result. The passed `FT_Size` is 1350 * expected to point to a `TT_Size`. 1351 */ 1352 FT_LOCAL_DEF( FT_Error ) tt_size_reset_height(FT_Size ft_size)1353 tt_size_reset_height( FT_Size ft_size ) 1354 { 1355 TT_Size size = (TT_Size)ft_size; 1356 TT_Face face = (TT_Face)size->root.face; 1357 FT_Size_Metrics* size_metrics = &size->hinted_metrics; 1358 1359 size->ttmetrics.valid = FALSE; 1360 1361 /* copy the result from base layer */ 1362 *size_metrics = size->root.metrics; 1363 1364 if ( size_metrics->x_ppem < 1 || size_metrics->y_ppem < 1 ) 1365 return FT_THROW( Invalid_PPem ); 1366 1367 /* This bit flag, if set, indicates that the ppems must be */ 1368 /* rounded to integers. Nearly all TrueType fonts have this bit */ 1369 /* set, as hinting won't work really well otherwise. */ 1370 /* */ 1371 if ( face->header.Flags & 8 ) 1372 { 1373 /* the TT spec always asks for ROUND, not FLOOR or CEIL */ 1374 size_metrics->ascender = FT_PIX_ROUND( 1375 FT_MulFix( face->root.ascender, 1376 size_metrics->y_scale ) ); 1377 size_metrics->descender = FT_PIX_ROUND( 1378 FT_MulFix( face->root.descender, 1379 size_metrics->y_scale ) ); 1380 size_metrics->height = FT_PIX_ROUND( 1381 FT_MulFix( face->root.height, 1382 size_metrics->y_scale ) ); 1383 } 1384 1385 size->ttmetrics.valid = TRUE; 1386 1387 return FT_Err_Ok; 1388 } 1389 1390 1391 /************************************************************************** 1392 * 1393 * @Function: 1394 * tt_size_reset 1395 * 1396 * @Description: 1397 * Reset a TrueType size when resolutions and character dimensions 1398 * have been changed. 1399 * 1400 * @Input: 1401 * size :: 1402 * A handle to the target size object. 1403 */ 1404 FT_LOCAL_DEF( FT_Error ) tt_size_reset(TT_Size size)1405 tt_size_reset( TT_Size size ) 1406 { 1407 FT_Error error; 1408 TT_Face face = (TT_Face)size->root.face; 1409 FT_Size_Metrics* size_metrics = &size->hinted_metrics; 1410 1411 1412 error = tt_size_reset_height( (FT_Size)size ); 1413 if ( error ) 1414 return error; 1415 1416 if ( face->header.Flags & 8 ) 1417 { 1418 /* base scaling values on integer ppem values, */ 1419 /* as mandated by the TrueType specification */ 1420 size_metrics->x_scale = FT_DivFix( size_metrics->x_ppem << 6, 1421 face->root.units_per_EM ); 1422 size_metrics->y_scale = FT_DivFix( size_metrics->y_ppem << 6, 1423 face->root.units_per_EM ); 1424 1425 size_metrics->max_advance = FT_PIX_ROUND( 1426 FT_MulFix( face->root.max_advance_width, 1427 size_metrics->x_scale ) ); 1428 } 1429 1430 /* compute new transformation */ 1431 if ( size_metrics->x_ppem >= size_metrics->y_ppem ) 1432 { 1433 size->ttmetrics.scale = size_metrics->x_scale; 1434 size->ttmetrics.ppem = size_metrics->x_ppem; 1435 size->ttmetrics.x_ratio = 0x10000L; 1436 size->ttmetrics.y_ratio = FT_DivFix( size_metrics->y_ppem, 1437 size_metrics->x_ppem ); 1438 } 1439 else 1440 { 1441 size->ttmetrics.scale = size_metrics->y_scale; 1442 size->ttmetrics.ppem = size_metrics->y_ppem; 1443 size->ttmetrics.x_ratio = FT_DivFix( size_metrics->x_ppem, 1444 size_metrics->y_ppem ); 1445 size->ttmetrics.y_ratio = 0x10000L; 1446 } 1447 1448 size->widthp = tt_face_get_device_metrics( face, size_metrics->x_ppem, 0 ); 1449 1450 size->metrics = size_metrics; 1451 1452 #ifdef TT_USE_BYTECODE_INTERPRETER 1453 size->cvt_ready = -1; 1454 #endif /* TT_USE_BYTECODE_INTERPRETER */ 1455 1456 return FT_Err_Ok; 1457 } 1458 1459 1460 /************************************************************************** 1461 * 1462 * @Function: 1463 * tt_driver_init 1464 * 1465 * @Description: 1466 * Initialize a given TrueType driver object. 1467 * 1468 * @Input: 1469 * driver :: 1470 * A handle to the target driver object. 1471 * 1472 * @Return: 1473 * FreeType error code. 0 means success. 1474 */ 1475 FT_LOCAL_DEF( FT_Error ) tt_driver_init(FT_Module ttdriver)1476 tt_driver_init( FT_Module ttdriver ) /* TT_Driver */ 1477 { 1478 1479 #ifdef TT_USE_BYTECODE_INTERPRETER 1480 1481 TT_Driver driver = (TT_Driver)ttdriver; 1482 1483 driver->interpreter_version = TT_INTERPRETER_VERSION_35; 1484 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL 1485 driver->interpreter_version = TT_INTERPRETER_VERSION_40; 1486 #endif 1487 1488 #else /* !TT_USE_BYTECODE_INTERPRETER */ 1489 1490 FT_UNUSED( ttdriver ); 1491 1492 #endif /* !TT_USE_BYTECODE_INTERPRETER */ 1493 1494 return FT_Err_Ok; 1495 } 1496 1497 1498 /************************************************************************** 1499 * 1500 * @Function: 1501 * tt_driver_done 1502 * 1503 * @Description: 1504 * Finalize a given TrueType driver. 1505 * 1506 * @Input: 1507 * driver :: 1508 * A handle to the target TrueType driver. 1509 */ 1510 FT_LOCAL_DEF( void ) tt_driver_done(FT_Module ttdriver)1511 tt_driver_done( FT_Module ttdriver ) /* TT_Driver */ 1512 { 1513 FT_UNUSED( ttdriver ); 1514 } 1515 1516 1517 /************************************************************************** 1518 * 1519 * @Function: 1520 * tt_slot_init 1521 * 1522 * @Description: 1523 * Initialize a new slot object. 1524 * 1525 * @InOut: 1526 * slot :: 1527 * A handle to the slot object. 1528 * 1529 * @Return: 1530 * FreeType error code. 0 means success. 1531 */ 1532 FT_LOCAL_DEF( FT_Error ) tt_slot_init(FT_GlyphSlot slot)1533 tt_slot_init( FT_GlyphSlot slot ) 1534 { 1535 return FT_GlyphLoader_CreateExtra( slot->internal->loader ); 1536 } 1537 1538 1539 /* END */ 1540