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