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