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