1 /***************************************************************************/ 2 /* */ 3 /* cidobjs.c */ 4 /* */ 5 /* CID objects manager (body). */ 6 /* */ 7 /* Copyright 1996-2018 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 FT_INTERNAL_DEBUG_H 21 #include FT_INTERNAL_STREAM_H 22 23 #include "cidgload.h" 24 #include "cidload.h" 25 26 #include FT_SERVICE_POSTSCRIPT_CMAPS_H 27 #include FT_INTERNAL_POSTSCRIPT_AUX_H 28 #include FT_INTERNAL_POSTSCRIPT_HINTS_H 29 #include FT_DRIVER_H 30 31 #include "ciderrs.h" 32 33 34 /*************************************************************************/ 35 /* */ 36 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 37 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 38 /* messages during execution. */ 39 /* */ 40 #undef FT_COMPONENT 41 #define FT_COMPONENT trace_cidobjs 42 43 44 /*************************************************************************/ 45 /* */ 46 /* SLOT FUNCTIONS */ 47 /* */ 48 /*************************************************************************/ 49 50 FT_LOCAL_DEF( void ) cid_slot_done(FT_GlyphSlot slot)51 cid_slot_done( FT_GlyphSlot slot ) 52 { 53 slot->internal->glyph_hints = NULL; 54 } 55 56 57 FT_LOCAL_DEF( FT_Error ) cid_slot_init(FT_GlyphSlot slot)58 cid_slot_init( FT_GlyphSlot slot ) 59 { 60 CID_Face face; 61 PSHinter_Service pshinter; 62 63 64 face = (CID_Face)slot->face; 65 pshinter = (PSHinter_Service)face->pshinter; 66 67 if ( pshinter ) 68 { 69 FT_Module module; 70 71 72 module = FT_Get_Module( slot->face->driver->root.library, 73 "pshinter" ); 74 if ( module ) 75 { 76 T1_Hints_Funcs funcs; 77 78 79 funcs = pshinter->get_t1_funcs( module ); 80 slot->internal->glyph_hints = (void*)funcs; 81 } 82 } 83 84 return 0; 85 } 86 87 88 /*************************************************************************/ 89 /* */ 90 /* SIZE FUNCTIONS */ 91 /* */ 92 /*************************************************************************/ 93 94 95 static PSH_Globals_Funcs cid_size_get_globals_funcs(CID_Size size)96 cid_size_get_globals_funcs( CID_Size size ) 97 { 98 CID_Face face = (CID_Face)size->root.face; 99 PSHinter_Service pshinter = (PSHinter_Service)face->pshinter; 100 FT_Module module; 101 102 103 module = FT_Get_Module( size->root.face->driver->root.library, 104 "pshinter" ); 105 return ( module && pshinter && pshinter->get_globals_funcs ) 106 ? pshinter->get_globals_funcs( module ) 107 : 0; 108 } 109 110 111 FT_LOCAL_DEF( void ) cid_size_done(FT_Size cidsize)112 cid_size_done( FT_Size cidsize ) /* CID_Size */ 113 { 114 CID_Size size = (CID_Size)cidsize; 115 116 117 if ( cidsize->internal->module_data ) 118 { 119 PSH_Globals_Funcs funcs; 120 121 122 funcs = cid_size_get_globals_funcs( size ); 123 if ( funcs ) 124 funcs->destroy( (PSH_Globals)cidsize->internal->module_data ); 125 126 cidsize->internal->module_data = NULL; 127 } 128 } 129 130 131 FT_LOCAL_DEF( FT_Error ) cid_size_init(FT_Size cidsize)132 cid_size_init( FT_Size cidsize ) /* CID_Size */ 133 { 134 CID_Size size = (CID_Size)cidsize; 135 FT_Error error = FT_Err_Ok; 136 PSH_Globals_Funcs funcs = cid_size_get_globals_funcs( size ); 137 138 139 if ( funcs ) 140 { 141 PSH_Globals globals; 142 CID_Face face = (CID_Face)cidsize->face; 143 CID_FaceDict dict = face->cid.font_dicts + face->root.face_index; 144 PS_Private priv = &dict->private_dict; 145 146 147 error = funcs->create( cidsize->face->memory, priv, &globals ); 148 if ( !error ) 149 cidsize->internal->module_data = globals; 150 } 151 152 return error; 153 } 154 155 156 FT_LOCAL( FT_Error ) cid_size_request(FT_Size size,FT_Size_Request req)157 cid_size_request( FT_Size size, 158 FT_Size_Request req ) 159 { 160 PSH_Globals_Funcs funcs; 161 162 163 FT_Request_Metrics( size->face, req ); 164 165 funcs = cid_size_get_globals_funcs( (CID_Size)size ); 166 167 if ( funcs ) 168 funcs->set_scale( (PSH_Globals)size->internal->module_data, 169 size->metrics.x_scale, 170 size->metrics.y_scale, 171 0, 0 ); 172 173 return FT_Err_Ok; 174 } 175 176 177 /*************************************************************************/ 178 /* */ 179 /* FACE FUNCTIONS */ 180 /* */ 181 /*************************************************************************/ 182 183 /*************************************************************************/ 184 /* */ 185 /* <Function> */ 186 /* cid_face_done */ 187 /* */ 188 /* <Description> */ 189 /* Finalizes a given face object. */ 190 /* */ 191 /* <Input> */ 192 /* face :: A pointer to the face object to destroy. */ 193 /* */ 194 FT_LOCAL_DEF( void ) cid_face_done(FT_Face cidface)195 cid_face_done( FT_Face cidface ) /* CID_Face */ 196 { 197 CID_Face face = (CID_Face)cidface; 198 FT_Memory memory; 199 CID_FaceInfo cid; 200 PS_FontInfo info; 201 202 203 if ( !face ) 204 return; 205 206 cid = &face->cid; 207 info = &cid->font_info; 208 memory = cidface->memory; 209 210 /* release subrs */ 211 if ( face->subrs ) 212 { 213 FT_Int n; 214 215 216 for ( n = 0; n < cid->num_dicts; n++ ) 217 { 218 CID_Subrs subr = face->subrs + n; 219 220 221 if ( subr->code ) 222 { 223 FT_FREE( subr->code[0] ); 224 FT_FREE( subr->code ); 225 } 226 } 227 228 FT_FREE( face->subrs ); 229 } 230 231 /* release FontInfo strings */ 232 FT_FREE( info->version ); 233 FT_FREE( info->notice ); 234 FT_FREE( info->full_name ); 235 FT_FREE( info->family_name ); 236 FT_FREE( info->weight ); 237 238 /* release font dictionaries */ 239 FT_FREE( cid->font_dicts ); 240 cid->num_dicts = 0; 241 242 /* release other strings */ 243 FT_FREE( cid->cid_font_name ); 244 FT_FREE( cid->registry ); 245 FT_FREE( cid->ordering ); 246 247 cidface->family_name = NULL; 248 cidface->style_name = NULL; 249 250 FT_FREE( face->binary_data ); 251 FT_FREE( face->cid_stream ); 252 } 253 254 255 /*************************************************************************/ 256 /* */ 257 /* <Function> */ 258 /* cid_face_init */ 259 /* */ 260 /* <Description> */ 261 /* Initializes a given CID face object. */ 262 /* */ 263 /* <Input> */ 264 /* stream :: The source font stream. */ 265 /* */ 266 /* face_index :: The index of the font face in the resource. */ 267 /* */ 268 /* num_params :: Number of additional generic parameters. Ignored. */ 269 /* */ 270 /* params :: Additional generic parameters. Ignored. */ 271 /* */ 272 /* <InOut> */ 273 /* face :: The newly built face object. */ 274 /* */ 275 /* <Return> */ 276 /* FreeType error code. 0 means success. */ 277 /* */ 278 FT_LOCAL_DEF( FT_Error ) cid_face_init(FT_Stream stream,FT_Face cidface,FT_Int face_index,FT_Int num_params,FT_Parameter * params)279 cid_face_init( FT_Stream stream, 280 FT_Face cidface, /* CID_Face */ 281 FT_Int face_index, 282 FT_Int num_params, 283 FT_Parameter* params ) 284 { 285 CID_Face face = (CID_Face)cidface; 286 FT_Error error; 287 PSAux_Service psaux; 288 PSHinter_Service pshinter; 289 290 FT_UNUSED( num_params ); 291 FT_UNUSED( params ); 292 FT_UNUSED( stream ); 293 294 295 cidface->num_faces = 1; 296 297 psaux = (PSAux_Service)face->psaux; 298 if ( !psaux ) 299 { 300 psaux = (PSAux_Service)FT_Get_Module_Interface( 301 FT_FACE_LIBRARY( face ), "psaux" ); 302 303 if ( !psaux ) 304 { 305 FT_ERROR(( "cid_face_init: cannot access `psaux' module\n" )); 306 error = FT_THROW( Missing_Module ); 307 goto Exit; 308 } 309 310 face->psaux = psaux; 311 } 312 313 pshinter = (PSHinter_Service)face->pshinter; 314 if ( !pshinter ) 315 { 316 pshinter = (PSHinter_Service)FT_Get_Module_Interface( 317 FT_FACE_LIBRARY( face ), "pshinter" ); 318 319 face->pshinter = pshinter; 320 } 321 322 FT_TRACE2(( "CID driver\n" )); 323 324 /* open the tokenizer; this will also check the font format */ 325 if ( FT_STREAM_SEEK( 0 ) ) 326 goto Exit; 327 328 error = cid_face_open( face, face_index ); 329 if ( error ) 330 goto Exit; 331 332 /* if we just wanted to check the format, leave successfully now */ 333 if ( face_index < 0 ) 334 goto Exit; 335 336 /* check the face index */ 337 /* XXX: handle CID fonts with more than a single face */ 338 if ( ( face_index & 0xFFFF ) != 0 ) 339 { 340 FT_ERROR(( "cid_face_init: invalid face index\n" )); 341 error = FT_THROW( Invalid_Argument ); 342 goto Exit; 343 } 344 345 /* now load the font program into the face object */ 346 347 /* initialize the face object fields */ 348 349 /* set up root face fields */ 350 { 351 CID_FaceInfo cid = &face->cid; 352 PS_FontInfo info = &cid->font_info; 353 354 355 cidface->num_glyphs = (FT_Long)cid->cid_count; 356 cidface->num_charmaps = 0; 357 358 cidface->face_index = face_index & 0xFFFF; 359 360 cidface->face_flags |= FT_FACE_FLAG_SCALABLE | /* scalable outlines */ 361 FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ 362 FT_FACE_FLAG_HINTER; /* has native hinter */ 363 364 if ( info->is_fixed_pitch ) 365 cidface->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 366 367 /* XXX: TODO: add kerning with .afm support */ 368 369 /* get style name -- be careful, some broken fonts only */ 370 /* have a /FontName dictionary entry! */ 371 cidface->family_name = info->family_name; 372 /* assume "Regular" style if we don't know better */ 373 cidface->style_name = (char *)"Regular"; 374 if ( cidface->family_name ) 375 { 376 char* full = info->full_name; 377 char* family = cidface->family_name; 378 379 380 if ( full ) 381 { 382 while ( *full ) 383 { 384 if ( *full == *family ) 385 { 386 family++; 387 full++; 388 } 389 else 390 { 391 if ( *full == ' ' || *full == '-' ) 392 full++; 393 else if ( *family == ' ' || *family == '-' ) 394 family++; 395 else 396 { 397 if ( !*family ) 398 cidface->style_name = full; 399 break; 400 } 401 } 402 } 403 } 404 } 405 else 406 { 407 /* do we have a `/FontName'? */ 408 if ( cid->cid_font_name ) 409 cidface->family_name = cid->cid_font_name; 410 } 411 412 /* compute style flags */ 413 cidface->style_flags = 0; 414 if ( info->italic_angle ) 415 cidface->style_flags |= FT_STYLE_FLAG_ITALIC; 416 if ( info->weight ) 417 { 418 if ( !ft_strcmp( info->weight, "Bold" ) || 419 !ft_strcmp( info->weight, "Black" ) ) 420 cidface->style_flags |= FT_STYLE_FLAG_BOLD; 421 } 422 423 /* no embedded bitmap support */ 424 cidface->num_fixed_sizes = 0; 425 cidface->available_sizes = NULL; 426 427 cidface->bbox.xMin = cid->font_bbox.xMin >> 16; 428 cidface->bbox.yMin = cid->font_bbox.yMin >> 16; 429 /* no `U' suffix here to 0xFFFF! */ 430 cidface->bbox.xMax = ( cid->font_bbox.xMax + 0xFFFF ) >> 16; 431 cidface->bbox.yMax = ( cid->font_bbox.yMax + 0xFFFF ) >> 16; 432 433 if ( !cidface->units_per_EM ) 434 cidface->units_per_EM = 1000; 435 436 cidface->ascender = (FT_Short)( cidface->bbox.yMax ); 437 cidface->descender = (FT_Short)( cidface->bbox.yMin ); 438 439 cidface->height = (FT_Short)( ( cidface->units_per_EM * 12 ) / 10 ); 440 if ( cidface->height < cidface->ascender - cidface->descender ) 441 cidface->height = (FT_Short)( cidface->ascender - cidface->descender ); 442 443 cidface->underline_position = (FT_Short)info->underline_position; 444 cidface->underline_thickness = (FT_Short)info->underline_thickness; 445 } 446 447 Exit: 448 return error; 449 } 450 451 452 /*************************************************************************/ 453 /* */ 454 /* <Function> */ 455 /* cid_driver_init */ 456 /* */ 457 /* <Description> */ 458 /* Initializes a given CID driver object. */ 459 /* */ 460 /* <Input> */ 461 /* driver :: A handle to the target driver object. */ 462 /* */ 463 /* <Return> */ 464 /* FreeType error code. 0 means success. */ 465 /* */ 466 FT_LOCAL_DEF( FT_Error ) cid_driver_init(FT_Module module)467 cid_driver_init( FT_Module module ) 468 { 469 PS_Driver driver = (PS_Driver)module; 470 471 FT_UInt32 seed; 472 473 474 /* set default property values, cf. `ftt1drv.h' */ 475 #ifdef T1_CONFIG_OPTION_OLD_ENGINE 476 driver->hinting_engine = FT_HINTING_FREETYPE; 477 #else 478 driver->hinting_engine = FT_HINTING_ADOBE; 479 #endif 480 481 driver->no_stem_darkening = TRUE; 482 483 driver->darken_params[0] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X1; 484 driver->darken_params[1] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y1; 485 driver->darken_params[2] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X2; 486 driver->darken_params[3] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y2; 487 driver->darken_params[4] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X3; 488 driver->darken_params[5] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y3; 489 driver->darken_params[6] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_X4; 490 driver->darken_params[7] = CFF_CONFIG_OPTION_DARKENING_PARAMETER_Y4; 491 492 /* compute random seed from some memory addresses */ 493 seed = (FT_UInt32)( (FT_Offset)(char*)&seed ^ 494 (FT_Offset)(char*)&module ^ 495 (FT_Offset)(char*)module->memory ); 496 seed = seed ^ ( seed >> 10 ) ^ ( seed >> 20 ); 497 498 driver->random_seed = (FT_Int32)seed; 499 if ( driver->random_seed < 0 ) 500 driver->random_seed = -driver->random_seed; 501 else if ( driver->random_seed == 0 ) 502 driver->random_seed = 123456789; 503 504 return FT_Err_Ok; 505 } 506 507 508 /*************************************************************************/ 509 /* */ 510 /* <Function> */ 511 /* cid_driver_done */ 512 /* */ 513 /* <Description> */ 514 /* Finalizes a given CID driver. */ 515 /* */ 516 /* <Input> */ 517 /* driver :: A handle to the target CID driver. */ 518 /* */ 519 FT_LOCAL_DEF( void ) cid_driver_done(FT_Module driver)520 cid_driver_done( FT_Module driver ) 521 { 522 FT_UNUSED( driver ); 523 } 524 525 526 /* END */ 527