1 /***************************************************************************/ 2 /* */ 3 /* cidgload.c */ 4 /* */ 5 /* CID-keyed Type1 Glyph Loader (body). */ 6 /* */ 7 /* Copyright 1996-2015 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 <ft2build.h> 20 #include "cidload.h" 21 #include "cidgload.h" 22 #include FT_INTERNAL_DEBUG_H 23 #include FT_INTERNAL_STREAM_H 24 #include FT_OUTLINE_H 25 #include FT_INTERNAL_CALC_H 26 27 #include "ciderrs.h" 28 29 30 /*************************************************************************/ 31 /* */ 32 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 33 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 34 /* messages during execution. */ 35 /* */ 36 #undef FT_COMPONENT 37 #define FT_COMPONENT trace_cidgload 38 39 40 FT_CALLBACK_DEF( FT_Error ) 41 cid_load_glyph( T1_Decoder decoder, 42 FT_UInt glyph_index ) 43 { 44 CID_Face face = (CID_Face)decoder->builder.face; 45 CID_FaceInfo cid = &face->cid; 46 FT_Byte* p; 47 FT_ULong fd_select; 48 FT_Stream stream = face->cid_stream; 49 FT_Error error = FT_Err_Ok; 50 FT_Byte* charstring = NULL; 51 FT_Memory memory = face->root.memory; 52 FT_ULong glyph_length = 0; 53 PSAux_Service psaux = (PSAux_Service)face->psaux; 54 55 #ifdef FT_CONFIG_OPTION_INCREMENTAL 56 FT_Incremental_InterfaceRec *inc = 57 face->root.internal->incremental_interface; 58 #endif 59 60 61 FT_TRACE1(( "cid_load_glyph: glyph index %d\n", glyph_index )); 62 63 #ifdef FT_CONFIG_OPTION_INCREMENTAL 64 65 /* For incremental fonts get the character data using */ 66 /* the callback function. */ 67 if ( inc ) 68 { 69 FT_Data glyph_data; 70 71 72 error = inc->funcs->get_glyph_data( inc->object, 73 glyph_index, &glyph_data ); 74 if ( error ) 75 goto Exit; 76 77 p = (FT_Byte*)glyph_data.pointer; 78 fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); 79 80 if ( glyph_data.length != 0 ) 81 { 82 glyph_length = (FT_ULong)( glyph_data.length - cid->fd_bytes ); 83 (void)FT_ALLOC( charstring, glyph_length ); 84 if ( !error ) 85 ft_memcpy( charstring, glyph_data.pointer + cid->fd_bytes, 86 glyph_length ); 87 } 88 89 inc->funcs->free_glyph_data( inc->object, &glyph_data ); 90 91 if ( error ) 92 goto Exit; 93 } 94 95 else 96 97 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 98 99 /* For ordinary fonts read the CID font dictionary index */ 100 /* and charstring offset from the CIDMap. */ 101 { 102 FT_UInt entry_len = (FT_UInt)( cid->fd_bytes + cid->gd_bytes ); 103 FT_ULong off1; 104 105 106 if ( FT_STREAM_SEEK( cid->data_offset + cid->cidmap_offset + 107 glyph_index * entry_len ) || 108 FT_FRAME_ENTER( 2 * entry_len ) ) 109 goto Exit; 110 111 p = (FT_Byte*)stream->cursor; 112 fd_select = cid_get_offset( &p, (FT_Byte)cid->fd_bytes ); 113 off1 = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ); 114 p += cid->fd_bytes; 115 glyph_length = cid_get_offset( &p, (FT_Byte)cid->gd_bytes ) - off1; 116 FT_FRAME_EXIT(); 117 118 if ( fd_select >= (FT_ULong)cid->num_dicts ) 119 { 120 error = FT_THROW( Invalid_Offset ); 121 goto Exit; 122 } 123 if ( glyph_length == 0 ) 124 goto Exit; 125 if ( FT_ALLOC( charstring, glyph_length ) ) 126 goto Exit; 127 if ( FT_STREAM_READ_AT( cid->data_offset + off1, 128 charstring, glyph_length ) ) 129 goto Exit; 130 } 131 132 /* Now set up the subrs array and parse the charstrings. */ 133 { 134 CID_FaceDict dict; 135 CID_Subrs cid_subrs = face->subrs + fd_select; 136 FT_UInt cs_offset; 137 138 139 /* Set up subrs */ 140 decoder->num_subrs = cid_subrs->num_subrs; 141 decoder->subrs = cid_subrs->code; 142 decoder->subrs_len = 0; 143 144 /* Set up font matrix */ 145 dict = cid->font_dicts + fd_select; 146 147 decoder->font_matrix = dict->font_matrix; 148 decoder->font_offset = dict->font_offset; 149 decoder->lenIV = dict->private_dict.lenIV; 150 151 /* Decode the charstring. */ 152 153 /* Adjustment for seed bytes. */ 154 cs_offset = decoder->lenIV >= 0 ? (FT_UInt)decoder->lenIV : 0; 155 156 /* Decrypt only if lenIV >= 0. */ 157 if ( decoder->lenIV >= 0 ) 158 psaux->t1_decrypt( charstring, glyph_length, 4330 ); 159 160 error = decoder->funcs.parse_charstrings( 161 decoder, charstring + cs_offset, 162 glyph_length - cs_offset ); 163 } 164 165 FT_FREE( charstring ); 166 167 #ifdef FT_CONFIG_OPTION_INCREMENTAL 168 169 /* Incremental fonts can optionally override the metrics. */ 170 if ( !error && inc && inc->funcs->get_glyph_metrics ) 171 { 172 FT_Incremental_MetricsRec metrics; 173 174 175 metrics.bearing_x = FIXED_TO_INT( decoder->builder.left_bearing.x ); 176 metrics.bearing_y = 0; 177 metrics.advance = FIXED_TO_INT( decoder->builder.advance.x ); 178 metrics.advance_v = FIXED_TO_INT( decoder->builder.advance.y ); 179 180 error = inc->funcs->get_glyph_metrics( inc->object, 181 glyph_index, FALSE, &metrics ); 182 183 decoder->builder.left_bearing.x = INT_TO_FIXED( metrics.bearing_x ); 184 decoder->builder.advance.x = INT_TO_FIXED( metrics.advance ); 185 decoder->builder.advance.y = INT_TO_FIXED( metrics.advance_v ); 186 } 187 188 #endif /* FT_CONFIG_OPTION_INCREMENTAL */ 189 190 Exit: 191 return error; 192 } 193 194 195 #if 0 196 197 198 /*************************************************************************/ 199 /*************************************************************************/ 200 /*************************************************************************/ 201 /********** *********/ 202 /********** *********/ 203 /********** COMPUTE THE MAXIMUM ADVANCE WIDTH *********/ 204 /********** *********/ 205 /********** The following code is in charge of computing *********/ 206 /********** the maximum advance width of the font. It *********/ 207 /********** quickly processes each glyph charstring to *********/ 208 /********** extract the value from either a `sbw' or `seac' *********/ 209 /********** operator. *********/ 210 /********** *********/ 211 /*************************************************************************/ 212 /*************************************************************************/ 213 /*************************************************************************/ 214 215 216 FT_LOCAL_DEF( FT_Error ) 217 cid_face_compute_max_advance( CID_Face face, 218 FT_Int* max_advance ) 219 { 220 FT_Error error; 221 T1_DecoderRec decoder; 222 FT_Int glyph_index; 223 224 PSAux_Service psaux = (PSAux_Service)face->psaux; 225 226 227 *max_advance = 0; 228 229 /* Initialize load decoder */ 230 error = psaux->t1_decoder_funcs->init( &decoder, 231 (FT_Face)face, 232 0, /* size */ 233 0, /* glyph slot */ 234 0, /* glyph names! XXX */ 235 0, /* blend == 0 */ 236 0, /* hinting == 0 */ 237 cid_load_glyph ); 238 if ( error ) 239 return error; 240 241 /* TODO: initialize decoder.len_buildchar and decoder.buildchar */ 242 /* if we ever support CID-keyed multiple master fonts */ 243 244 decoder.builder.metrics_only = 1; 245 decoder.builder.load_points = 0; 246 247 /* for each glyph, parse the glyph charstring and extract */ 248 /* the advance width */ 249 for ( glyph_index = 0; glyph_index < face->root.num_glyphs; 250 glyph_index++ ) 251 { 252 /* now get load the unscaled outline */ 253 error = cid_load_glyph( &decoder, glyph_index ); 254 /* ignore the error if one occurred - skip to next glyph */ 255 } 256 257 *max_advance = FIXED_TO_INT( decoder.builder.advance.x ); 258 259 psaux->t1_decoder_funcs->done( &decoder ); 260 261 return FT_Err_Ok; 262 } 263 264 265 #endif /* 0 */ 266 267 268 FT_LOCAL_DEF( FT_Error ) 269 cid_slot_load_glyph( FT_GlyphSlot cidglyph, /* CID_GlyphSlot */ 270 FT_Size cidsize, /* CID_Size */ 271 FT_UInt glyph_index, 272 FT_Int32 load_flags ) 273 { 274 CID_GlyphSlot glyph = (CID_GlyphSlot)cidglyph; 275 FT_Error error; 276 T1_DecoderRec decoder; 277 CID_Face face = (CID_Face)cidglyph->face; 278 FT_Bool hinting; 279 280 PSAux_Service psaux = (PSAux_Service)face->psaux; 281 FT_Matrix font_matrix; 282 FT_Vector font_offset; 283 284 285 if ( glyph_index >= (FT_UInt)face->root.num_glyphs ) 286 { 287 error = FT_THROW( Invalid_Argument ); 288 goto Exit; 289 } 290 291 if ( load_flags & FT_LOAD_NO_RECURSE ) 292 load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING; 293 294 glyph->x_scale = cidsize->metrics.x_scale; 295 glyph->y_scale = cidsize->metrics.y_scale; 296 297 cidglyph->outline.n_points = 0; 298 cidglyph->outline.n_contours = 0; 299 300 hinting = FT_BOOL( ( load_flags & FT_LOAD_NO_SCALE ) == 0 && 301 ( load_flags & FT_LOAD_NO_HINTING ) == 0 ); 302 303 cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; 304 305 error = psaux->t1_decoder_funcs->init( &decoder, 306 cidglyph->face, 307 cidsize, 308 cidglyph, 309 0, /* glyph names -- XXX */ 310 0, /* blend == 0 */ 311 hinting, 312 FT_LOAD_TARGET_MODE( load_flags ), 313 cid_load_glyph ); 314 if ( error ) 315 goto Exit; 316 317 /* TODO: initialize decoder.len_buildchar and decoder.buildchar */ 318 /* if we ever support CID-keyed multiple master fonts */ 319 320 /* set up the decoder */ 321 decoder.builder.no_recurse = FT_BOOL( 322 ( ( load_flags & FT_LOAD_NO_RECURSE ) != 0 ) ); 323 324 error = cid_load_glyph( &decoder, glyph_index ); 325 if ( error ) 326 goto Exit; 327 328 font_matrix = decoder.font_matrix; 329 font_offset = decoder.font_offset; 330 331 /* save new glyph tables */ 332 psaux->t1_decoder_funcs->done( &decoder ); 333 334 /* now set the metrics -- this is rather simple, as */ 335 /* the left side bearing is the xMin, and the top side */ 336 /* bearing the yMax */ 337 cidglyph->outline.flags &= FT_OUTLINE_OWNER; 338 cidglyph->outline.flags |= FT_OUTLINE_REVERSE_FILL; 339 340 /* for composite glyphs, return only left side bearing and */ 341 /* advance width */ 342 if ( load_flags & FT_LOAD_NO_RECURSE ) 343 { 344 FT_Slot_Internal internal = cidglyph->internal; 345 346 347 cidglyph->metrics.horiBearingX = 348 FIXED_TO_INT( decoder.builder.left_bearing.x ); 349 cidglyph->metrics.horiAdvance = 350 FIXED_TO_INT( decoder.builder.advance.x ); 351 352 internal->glyph_matrix = font_matrix; 353 internal->glyph_delta = font_offset; 354 internal->glyph_transformed = 1; 355 } 356 else 357 { 358 FT_BBox cbox; 359 FT_Glyph_Metrics* metrics = &cidglyph->metrics; 360 361 362 /* copy the _unscaled_ advance width */ 363 metrics->horiAdvance = 364 FIXED_TO_INT( decoder.builder.advance.x ); 365 cidglyph->linearHoriAdvance = 366 FIXED_TO_INT( decoder.builder.advance.x ); 367 cidglyph->internal->glyph_transformed = 0; 368 369 /* make up vertical ones */ 370 metrics->vertAdvance = ( face->cid.font_bbox.yMax - 371 face->cid.font_bbox.yMin ) >> 16; 372 cidglyph->linearVertAdvance = metrics->vertAdvance; 373 374 cidglyph->format = FT_GLYPH_FORMAT_OUTLINE; 375 376 if ( cidsize->metrics.y_ppem < 24 ) 377 cidglyph->outline.flags |= FT_OUTLINE_HIGH_PRECISION; 378 379 /* apply the font matrix, if any */ 380 if ( font_matrix.xx != 0x10000L || font_matrix.yy != 0x10000L || 381 font_matrix.xy != 0 || font_matrix.yx != 0 ) 382 { 383 FT_Outline_Transform( &cidglyph->outline, &font_matrix ); 384 385 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, 386 font_matrix.xx ); 387 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, 388 font_matrix.yy ); 389 } 390 391 if ( font_offset.x || font_offset.y ) 392 { 393 FT_Outline_Translate( &cidglyph->outline, 394 font_offset.x, 395 font_offset.y ); 396 397 metrics->horiAdvance += font_offset.x; 398 metrics->vertAdvance += font_offset.y; 399 } 400 401 if ( ( load_flags & FT_LOAD_NO_SCALE ) == 0 ) 402 { 403 /* scale the outline and the metrics */ 404 FT_Int n; 405 FT_Outline* cur = decoder.builder.base; 406 FT_Vector* vec = cur->points; 407 FT_Fixed x_scale = glyph->x_scale; 408 FT_Fixed y_scale = glyph->y_scale; 409 410 411 /* First of all, scale the points */ 412 if ( !hinting || !decoder.builder.hints_funcs ) 413 for ( n = cur->n_points; n > 0; n--, vec++ ) 414 { 415 vec->x = FT_MulFix( vec->x, x_scale ); 416 vec->y = FT_MulFix( vec->y, y_scale ); 417 } 418 419 /* Then scale the metrics */ 420 metrics->horiAdvance = FT_MulFix( metrics->horiAdvance, x_scale ); 421 metrics->vertAdvance = FT_MulFix( metrics->vertAdvance, y_scale ); 422 } 423 424 /* compute the other metrics */ 425 FT_Outline_Get_CBox( &cidglyph->outline, &cbox ); 426 427 metrics->width = cbox.xMax - cbox.xMin; 428 metrics->height = cbox.yMax - cbox.yMin; 429 430 metrics->horiBearingX = cbox.xMin; 431 metrics->horiBearingY = cbox.yMax; 432 433 if ( load_flags & FT_LOAD_VERTICAL_LAYOUT ) 434 { 435 /* make up vertical ones */ 436 ft_synthesize_vertical_metrics( metrics, 437 metrics->vertAdvance ); 438 } 439 } 440 441 Exit: 442 return error; 443 } 444 445 446 /* END */ 447