t1gload.c (20377B)
1 /**************************************************************************** 2 * 3 * t1gload.c 4 * 5 * Type 1 Glyph Loader (body). 6 * 7 * Copyright (C) 1996-2025 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 "t1gload.h" 20 #include <freetype/internal/ftcalc.h> 21 #include <freetype/internal/ftdebug.h> 22 #include <freetype/internal/ftstream.h> 23 #include <freetype/ftoutln.h> 24 #include <freetype/internal/psaux.h> 25 #include <freetype/internal/cfftypes.h> 26 #include <freetype/ftdriver.h> 27 28 #include "t1errors.h" 29 30 31 /************************************************************************** 32 * 33 * The macro FT_COMPONENT is used in trace mode. It is an implicit 34 * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log 35 * messages during execution. 36 */ 37 #undef FT_COMPONENT 38 #define FT_COMPONENT t1gload 39 40 41 static FT_Error 42 T1_Parse_Glyph_And_Get_Char_String( T1_Decoder decoder, 43 FT_UInt glyph_index, 44 FT_Data* char_string, 45 FT_Bool* force_scaling ) 46 { 47 T1_Face face = (T1_Face)decoder->builder.face; 48 T1_Font type1 = &face->type1; 49 FT_Error error = FT_Err_Ok; 50 51 PSAux_Service psaux = (PSAux_Service)face->psaux; 52 const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; 53 PS_Decoder psdecoder; 54 55 #ifdef FT_CONFIG_OPTION_INCREMENTAL 56 FT_Incremental_InterfaceRec *inc = 57 face->root.internal->incremental_interface; 58 #endif 59 60 #ifdef T1_CONFIG_OPTION_OLD_ENGINE 61 PS_Driver driver = (PS_Driver)FT_FACE_DRIVER( face ); 62 #endif 63 64 65 decoder->font_matrix = type1->font_matrix; 66 decoder->font_offset = type1->font_offset; 67 68 #ifdef FT_CONFIG_OPTION_INCREMENTAL 69 70 /* For incremental fonts get the character data using the */ 71 /* callback function. */ 72 if ( inc ) 73 { 74 /* So `free_glyph_data` knows whether to free it. */ 75 char_string->pointer = NULL; 76 77 error = inc->funcs->get_glyph_data( inc->object, 78 glyph_index, char_string ); 79 } 80 else 81 82 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 83 84 /* For ordinary fonts get the character data stored in the face record. */ 85 { 86 char_string->pointer = type1->charstrings[glyph_index]; 87 char_string->length = type1->charstrings_len[glyph_index]; 88 } 89 90 if ( !error ) 91 { 92 /* choose which renderer to use */ 93 #ifdef T1_CONFIG_OPTION_OLD_ENGINE 94 if ( driver->hinting_engine == FT_HINTING_FREETYPE || 95 decoder->builder.metrics_only ) 96 error = decoder_funcs->parse_charstrings_old( 97 decoder, 98 (FT_Byte*)char_string->pointer, 99 (FT_UInt)char_string->length ); 100 #else 101 if ( decoder->builder.metrics_only ) 102 error = decoder_funcs->parse_metrics( 103 decoder, 104 (FT_Byte*)char_string->pointer, 105 (FT_UInt)char_string->length ); 106 #endif 107 else 108 { 109 CFF_SubFontRec subfont; 110 111 112 psaux->ps_decoder_init( &psdecoder, decoder, TRUE ); 113 114 psaux->t1_make_subfont( FT_FACE( face ), 115 &face->type1.private_dict, &subfont ); 116 psdecoder.current_subfont = &subfont; 117 118 error = decoder_funcs->parse_charstrings( 119 &psdecoder, 120 (FT_Byte*)char_string->pointer, 121 (FT_ULong)char_string->length ); 122 123 /* Adobe's engine uses 16.16 numbers everywhere; */ 124 /* as a consequence, glyphs larger than 2000ppem get rejected */ 125 if ( FT_ERR_EQ( error, Glyph_Too_Big ) ) 126 { 127 /* this time, we retry unhinted and scale up the glyph later on */ 128 /* (the engine uses and sets the hardcoded value 0x10000 / 64 = */ 129 /* 0x400 for both `x_scale' and `y_scale' in this case) */ 130 ((T1_GlyphSlot)decoder->builder.glyph)->hint = FALSE; 131 132 *force_scaling = TRUE; 133 134 error = decoder_funcs->parse_charstrings( 135 &psdecoder, 136 (FT_Byte*)char_string->pointer, 137 (FT_ULong)char_string->length ); 138 } 139 } 140 } 141 142 #ifdef FT_CONFIG_OPTION_INCREMENTAL 143 144 /* Incremental fonts can optionally override the metrics. */ 145 if ( !error && inc && inc->funcs->get_glyph_metrics ) 146 { 147 FT_Incremental_MetricsRec metrics; 148 149 150 metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); 151 metrics.bearing_y = 0; 152 metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); 153 metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y ); 154 155 error = inc->funcs->get_glyph_metrics( inc->object, 156 glyph_index, FALSE, &metrics ); 157 158 decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); 159 decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); 160 decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v ); 161 } 162 163 if ( error && inc ) 164 inc->funcs->free_glyph_data( inc->object, char_string ); 165 166 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 167 168 return error; 169 } 170 171 172 FT_CALLBACK_DEF( FT_Error ) 173 T1_Parse_Glyph( T1_Decoder decoder, 174 FT_UInt glyph_index ) 175 { 176 FT_Data glyph_data; 177 FT_Bool force_scaling = FALSE; 178 FT_Error error = T1_Parse_Glyph_And_Get_Char_String( 179 decoder, glyph_index, &glyph_data, 180 &force_scaling ); 181 182 183 #ifdef FT_CONFIG_OPTION_INCREMENTAL 184 185 if ( !error ) 186 { 187 T1_Face face = (T1_Face)decoder->builder.face; 188 189 190 if ( face->root.internal->incremental_interface ) 191 face->root.internal->incremental_interface->funcs->free_glyph_data( 192 face->root.internal->incremental_interface->object, 193 &glyph_data ); 194 } 195 196 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 197 198 return error; 199 } 200 201 202 /*************************************************************************/ 203 /*************************************************************************/ 204 /*************************************************************************/ 205 /********** *********/ 206 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ 207 /********** *********/ 208 /********** The following code is in charge of computing *********/ 209 /********** the maximum advance width of the font. It *********/ 210 /********** quickly processes each glyph charstring to *********/ 211 /********** extract the value from either a `sbw' or `seac' *********/ 212 /********** operator. *********/ 213 /********** *********/ 214 /*************************************************************************/ 215 /*************************************************************************/ 216 /*************************************************************************/ 217 218 219 FT_LOCAL_DEF( FT_Error ) 220 T1_Compute_Max_Advance( T1_Face face, 221 FT_Pos* max_advance ) 222 { 223 FT_Error error; 224 T1_DecoderRec decoder; 225 FT_Int glyph_index; 226 T1_Font type1 = &face->type1; 227 PSAux_Service psaux = (PSAux_Service)face->psaux; 228 229 230 FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); 231 232 *max_advance = 0; 233 234 /* initialize load decoder */ 235 error = psaux->t1_decoder_funcs->init( &decoder, 236 (FT_Face)face, 237 0, /* size */ 238 0, /* glyph slot */ 239 (FT_Byte**)type1->glyph_names, 240 face->blend, 241 0, 242 FT_RENDER_MODE_NORMAL, 243 T1_Parse_Glyph ); 244 if ( error ) 245 return error; 246 247 decoder.builder.metrics_only = 1; 248 decoder.builder.load_points = 0; 249 250 decoder.num_subrs = type1->num_subrs; 251 decoder.subrs = type1->subrs; 252 decoder.subrs_len = type1->subrs_len; 253 decoder.subrs_hash = type1->subrs_hash; 254 255 decoder.buildchar = face->buildchar; 256 decoder.len_buildchar = face->len_buildchar; 257 258 *max_advance = 0; 259 260 FT_TRACE6(( "T1_Compute_Max_Advance:\n" )); 261 262 /* for each glyph, parse the glyph charstring and extract */ 263 /* the advance width */ 264 for ( glyph_index = 0; glyph_index < type1->num_glyphs; glyph_index++ ) 265 { 266 /* now get load the unscaled outline */ 267 (void)T1_Parse_Glyph( &decoder, (FT_UInt)glyph_index ); 268 if ( glyph_index == 0 || decoder.builder.advance.x > *max_advance ) 269 *max_advance = decoder.builder.advance.x; 270 271 /* ignore the error if one occurred - skip to next glyph */ 272 } 273 274 FT_TRACE6(( "T1_Compute_Max_Advance: max advance: %f\n", 275 (double)*max_advance / 65536 )); 276 277 psaux->t1_decoder_funcs->done( &decoder ); 278 279 return FT_Err_Ok; 280 } 281 282 283 FT_LOCAL_DEF( FT_Error ) 284 T1_Get_Advances( FT_Face t1face, /* T1_Face */ 285 FT_UInt first, 286 FT_UInt count, 287 FT_Int32 load_flags, 288 FT_Fixed* advances ) 289 { 290 T1_Face face = (T1_Face)t1face; 291 T1_DecoderRec decoder; 292 T1_Font type1 = &face->type1; 293 PSAux_Service psaux = (PSAux_Service)face->psaux; 294 FT_UInt nn; 295 FT_Error error; 296 297 298 FT_TRACE5(( "T1_Get_Advances:\n" )); 299 300 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 301 { 302 for ( nn = 0; nn < count; nn++ ) 303 { 304 advances[nn] = 0; 305 306 FT_TRACE5(( " idx %u: advance height 0 font units\n", 307 first + nn )); 308 } 309 310 return FT_Err_Ok; 311 } 312 313 error = psaux->t1_decoder_funcs->init( &decoder, 314 (FT_Face)face, 315 0, /* size */ 316 0, /* glyph slot */ 317 (FT_Byte**)type1->glyph_names, 318 face->blend, 319 0, 320 FT_RENDER_MODE_NORMAL, 321 T1_Parse_Glyph ); 322 if ( error ) 323 return error; 324 325 decoder.builder.metrics_only = 1; 326 decoder.builder.load_points = 0; 327 328 decoder.num_subrs = type1->num_subrs; 329 decoder.subrs = type1->subrs; 330 decoder.subrs_len = type1->subrs_len; 331 decoder.subrs_hash = type1->subrs_hash; 332 333 decoder.buildchar = face->buildchar; 334 decoder.len_buildchar = face->len_buildchar; 335 336 for ( nn = 0; nn < count; nn++ ) 337 { 338 error = T1_Parse_Glyph( &decoder, first + nn ); 339 if ( !error ) 340 advances[nn] = FIXED_TO_INT( decoder.builder.advance.x ); 341 else 342 advances[nn] = 0; 343 344 FT_TRACE5(( " idx %u: advance width %ld font unit%s\n", 345 first + nn, 346 advances[nn], 347 advances[nn] == 1 ? "" : "s" )); 348 } 349 350 return FT_Err_Ok; 351 } 352 353 354 FT_LOCAL_DEF( FT_Error ) 355 T1_Load_Glyph( FT_GlyphSlot t1glyph, /* T1_GlyphSlot */ 356 FT_Size t1size, /* T1_Size */ 357 FT_UInt glyph_index, 358 FT_Int32 load_flags ) 359 { 360 T1_GlyphSlot glyph = (T1_GlyphSlot)t1glyph; 361 FT_Error error; 362 T1_DecoderRec decoder; 363 T1_Face face = (T1_Face)t1glyph->face; 364 FT_Bool hinting; 365 FT_Bool scaled; 366 FT_Bool force_scaling = FALSE; 367 T1_Font type1 = &face->type1; 368 PSAux_Service psaux = (PSAux_Service)face->psaux; 369 const T1_Decoder_Funcs decoder_funcs = psaux->t1_decoder_funcs; 370 371 FT_Matrix font_matrix; 372 FT_Vector font_offset; 373 FT_Data glyph_data; 374 FT_Bool must_finish_decoder = FALSE; 375 #ifdef FT_CONFIG_OPTION_INCREMENTAL 376 FT_Bool glyph_data_loaded = 0; 377 #endif 378 379 380 #ifdef FT_CONFIG_OPTION_INCREMENTAL 381 if ( glyph_index >= (FT_UInt)face->root.num_glyphs && 382 !face->root.internal->incremental_interface ) 383 #else 384 if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) 385 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 386 { 387 error = FT_THROW( Invalid_Argument ); 388 goto Exit; 389 } 390 391 FT_TRACE1(( "T1_Load_Glyph: glyph index %u\n", glyph_index )); 392 393 FT_ASSERT( ( face->len_buildchar == 0 ) == ( face->buildchar == NULL ) ); 394 395 if ( load_flags & FT_LOAD_NO_RECURSE ) 396 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 397 398 if ( t1size ) 399 { 400 glyph->x_scale = t1size->metrics.x_scale; 401 glyph->y_scale = t1size->metrics.y_scale; 402 } 403 else 404 { 405 glyph->x_scale = 0x10000L; 406 glyph->y_scale = 0x10000L; 407 } 408 409 hinting = FT_BOOL( !( load_flags & FT_LOAD_NO_SCALE ) && 410 !( load_flags & FT_LOAD_NO_HINTING ) ); 411 scaled = FT_BOOL( !( load_flags & FT_LOAD_NO_SCALE ) ); 412 413 glyph->hint = hinting; 414 glyph->scaled = scaled; 415 416 error = decoder_funcs->init( &decoder, 417 t1glyph->face, 418 t1size, 419 t1glyph, 420 (FT_Byte**)type1->glyph_names, 421 face->blend, 422 hinting, 423 FT_LOAD_TARGET_MODE( load_flags ), 424 T1_Parse_Glyph ); 425 if ( error ) 426 goto Exit; 427 428 must_finish_decoder = TRUE; 429 430 decoder.builder.no_recurse = FT_BOOL( load_flags & FT_LOAD_NO_RECURSE ); 431 432 decoder.num_subrs = type1->num_subrs; 433 decoder.subrs = type1->subrs; 434 decoder.subrs_len = type1->subrs_len; 435 decoder.subrs_hash = type1->subrs_hash; 436 437 decoder.buildchar = face->buildchar; 438 decoder.len_buildchar = face->len_buildchar; 439 440 /* now load the unscaled outline */ 441 error = T1_Parse_Glyph_And_Get_Char_String( &decoder, glyph_index, 442 &glyph_data, 443 &force_scaling ); 444 if ( error ) 445 goto Exit; 446 #ifdef FT_CONFIG_OPTION_INCREMENTAL 447 glyph_data_loaded = 1; 448 #endif 449 450 hinting = glyph->hint; 451 font_matrix = decoder.font_matrix; 452 font_offset = decoder.font_offset; 453 454 /* save new glyph tables */ 455 decoder_funcs->done( &decoder ); 456 457 must_finish_decoder = FALSE; 458 459 if ( !error ) 460 { 461 /* now, set the metrics -- this is rather simple, as */ 462 /* the left side bearing is the xMin, and the top side */ 463 /* bearing the yMax; for composite glyphs, return only */ 464 /* left side bearing and advance width */ 465 if ( load_flags & FT_LOAD_NO_RECURSE ) 466 { 467 FT_Slot_Internal internal = t1glyph->internal; 468 469 470 t1glyph->metrics.horiBearingX = 471 FIXED_TO_INT( decoder.builder.left_bearing.x ); 472 t1glyph->metrics.horiAdvance = 473 FIXED_TO_INT( decoder.builder.advance.x ); 474 475 internal->glyph_matrix = font_matrix; 476 internal->glyph_delta = font_offset; 477 internal->glyph_transformed = 1; 478 } 479 else 480 { 481 FT_BBox cbox; 482 FT_Glyph_Metrics* metrics = &t1glyph->metrics; 483 484 485 t1glyph->format = FT_GLYPH_FORMAT_OUTLINE; 486 487 t1glyph->outline.flags &= FT_OUTLINE_OWNER; 488 t1glyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; 489 if ( t1size && t1size->metrics.y_ppem < 24 ) 490 t1glyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; 491 492 /* copy the _unscaled_ advance width */ 493 metrics->horiAdvance = 494 FIXED_TO_INT( decoder.builder.advance.x ); 495 t1glyph->linearHoriAdvance = 496 FIXED_TO_INT( decoder.builder.advance.x ); 497 t1glyph->internal->glyph_transformed = 0; 498 499 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 500 { 501 /* make up vertical ones */ 502 metrics->vertAdvance = ( face->type1.font_bbox.yMax - 503 face->type1.font_bbox.yMin ) >> 16; 504 t1glyph->linearVertAdvance = metrics->vertAdvance; 505 } 506 else 507 { 508 metrics->vertAdvance = 509 FIXED_TO_INT( decoder.builder.advance.y ); 510 t1glyph->linearVertAdvance = 511 FIXED_TO_INT( decoder.builder.advance.y ); 512 } 513 514 #if 1 515 /* apply the font matrix, if any */ 516 if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || 517 font_matrix.xy != 0 || font_matrix.yx != 0 ) 518 { 519 FT_Outline_Transform( &t1glyph->outline, &font_matrix ); 520 521 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, 522 font_matrix.xx ); 523 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, 524 font_matrix.yy ); 525 } 526 527 if ( font_offset.x || font_offset.y ) 528 { 529 FT_Outline_Translate( &t1glyph->outline, 530 font_offset.x, 531 font_offset.y ); 532 533 metrics->horiAdvance += font_offset.x; 534 metrics->vertAdvance += font_offset.y; 535 } 536 #endif 537 538 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 || force_scaling ) 539 { 540 /* scale the outline and the metrics */ 541 FT_Int n; 542 FT_Outline* cur = decoder.builder.base; 543 FT_Vector* vec = cur->points; 544 FT_Fixed x_scale = glyph->x_scale; 545 FT_Fixed y_scale = glyph->y_scale; 546 547 548 /* First of all, scale the points, if we are not hinting */ 549 if ( !hinting || !decoder.builder.hints_funcs ) 550 for ( n = cur->n_points; n > 0; n--, vec++ ) 551 { 552 vec->x = FT_MulFix( vec->x, x_scale ); 553 vec->y = FT_MulFix( vec->y, y_scale ); 554 } 555 556 /* Then scale the metrics */ 557 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 558 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 559 } 560 561 /* compute the other metrics */ 562 FT_Outline_Get_CBox( &t1glyph->outline, &cbox ); 563 564 metrics->width = cbox.xMax - cbox.xMin; 565 metrics->height = cbox.yMax - cbox.yMin; 566 567 metrics->horiBearingX = cbox.xMin; 568 metrics->horiBearingY = cbox.yMax; 569 570 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 571 { 572 /* make up vertical ones */ 573 ft_synthesize_vertical_metrics( metrics, 574 metrics->vertAdvance ); 575 } 576 } 577 578 /* Set control data to the glyph charstrings. Note that this is */ 579 /* _not_ zero-terminated. */ 580 t1glyph->control_data = (FT_Byte*)glyph_data.pointer; 581 t1glyph->control_len = glyph_data.length; 582 } 583 584 585 Exit: 586 587 #ifdef FT_CONFIG_OPTION_INCREMENTAL 588 if ( glyph_data_loaded && face->root.internal->incremental_interface ) 589 { 590 face->root.internal->incremental_interface->funcs->free_glyph_data( 591 face->root.internal->incremental_interface->object, 592 &glyph_data ); 593 594 /* Set the control data to null - it is no longer available if */ 595 /* loaded incrementally. */ 596 t1glyph->control_data = NULL; 597 t1glyph->control_len = 0; 598 } 599 #endif 600 601 if ( must_finish_decoder ) 602 decoder_funcs->done( &decoder ); 603 604 return error; 605 } 606 607 608 /* END */