1 /***************************************************************************/ 2 /* */ 3 /* t1objs.c */ 4 /* */ 5 /* Type 1 objects manager (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 FT_INTERNAL_DEBUG_H 21 #include FT_INTERNAL_STREAM_H 22 23 #include "t1gload.h" 24 #include "t1load.h" 25 26 #include "t1errors.h" 27 28 #ifndef T1_CONFIG_OPTION_NO_AFM 29 #include "t1afm.h" 30 #endif 31 32 #include FT_INTERNAL_POSTSCRIPT_NAMES_H 33 #include FT_INTERNAL_POSTSCRIPT_AUX_H 34 35 36 /*************************************************************************/ 37 /* */ 38 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 39 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 40 /* messages during execution. */ 41 /* */ 42 #undef FT_COMPONENT 43 #define FT_COMPONENT trace_t1objs 44 45 46 /*************************************************************************/ 47 /* */ 48 /* SIZE FUNCTIONS */ 49 /* */ 50 /* note that we store the global hints in the size's "internal" root */ 51 /* field */ 52 /* */ 53 /*************************************************************************/ 54 55 56 static PSH_Globals_Funcs T1_Size_Get_Globals_Funcs(T1_Size size)57 T1_Size_Get_Globals_Funcs( T1_Size size ) 58 { 59 T1_Face face = (T1_Face)size->root.face; 60 PSHinter_Service pshinter = (PSHinter_Service)face->pshinter; 61 FT_Module module; 62 63 64 module = FT_Get_Module( size->root.face->driver->root.library, 65 "pshinter" ); 66 return ( module && pshinter && pshinter->get_globals_funcs ) 67 ? pshinter->get_globals_funcs( module ) 68 : 0 ; 69 } 70 71 72 FT_LOCAL_DEF( void ) T1_Size_Done(T1_Size size)73 T1_Size_Done( T1_Size size ) 74 { 75 if ( size->root.internal ) 76 { 77 PSH_Globals_Funcs funcs; 78 79 80 funcs = T1_Size_Get_Globals_Funcs( size ); 81 if ( funcs ) 82 funcs->destroy( (PSH_Globals)size->root.internal ); 83 84 size->root.internal = 0; 85 } 86 } 87 88 89 FT_LOCAL_DEF( FT_Error ) T1_Size_Init(T1_Size size)90 T1_Size_Init( T1_Size size ) 91 { 92 FT_Error error = 0; 93 PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); 94 95 96 if ( funcs ) 97 { 98 PSH_Globals globals; 99 T1_Face face = (T1_Face)size->root.face; 100 101 102 error = funcs->create( size->root.face->memory, 103 &face->type1.private_dict, &globals ); 104 if ( !error ) 105 size->root.internal = (FT_Size_Internal)(void*)globals; 106 } 107 108 return error; 109 } 110 111 112 FT_LOCAL_DEF( FT_Error ) T1_Size_Reset(T1_Size size)113 T1_Size_Reset( T1_Size size ) 114 { 115 PSH_Globals_Funcs funcs = T1_Size_Get_Globals_Funcs( size ); 116 FT_Error error = 0; 117 118 119 if ( funcs ) 120 error = funcs->set_scale( (PSH_Globals)size->root.internal, 121 size->root.metrics.x_scale, 122 size->root.metrics.y_scale, 123 0, 0 ); 124 return error; 125 } 126 127 128 /*************************************************************************/ 129 /* */ 130 /* SLOT FUNCTIONS */ 131 /* */ 132 /*************************************************************************/ 133 134 FT_LOCAL_DEF( void ) T1_GlyphSlot_Done(T1_GlyphSlot slot)135 T1_GlyphSlot_Done( T1_GlyphSlot slot ) 136 { 137 slot->root.internal->glyph_hints = 0; 138 } 139 140 141 FT_LOCAL_DEF( FT_Error ) T1_GlyphSlot_Init(T1_GlyphSlot slot)142 T1_GlyphSlot_Init( T1_GlyphSlot slot ) 143 { 144 T1_Face face; 145 PSHinter_Service pshinter; 146 147 148 face = (T1_Face)slot->root.face; 149 pshinter = (PSHinter_Service)face->pshinter; 150 151 if ( pshinter ) 152 { 153 FT_Module module; 154 155 156 module = FT_Get_Module( slot->root.face->driver->root.library, "pshinter" ); 157 if (module) 158 { 159 T1_Hints_Funcs funcs; 160 161 funcs = pshinter->get_t1_funcs( module ); 162 slot->root.internal->glyph_hints = (void*)funcs; 163 } 164 } 165 return 0; 166 } 167 168 169 /*************************************************************************/ 170 /* */ 171 /* FACE FUNCTIONS */ 172 /* */ 173 /*************************************************************************/ 174 175 176 /*************************************************************************/ 177 /* */ 178 /* <Function> */ 179 /* T1_Face_Done */ 180 /* */ 181 /* <Description> */ 182 /* The face object destructor. */ 183 /* */ 184 /* <Input> */ 185 /* face :: A typeless pointer to the face object to destroy. */ 186 /* */ 187 FT_LOCAL_DEF( void ) T1_Face_Done(T1_Face face)188 T1_Face_Done( T1_Face face ) 189 { 190 FT_Memory memory; 191 T1_Font type1 = &face->type1; 192 193 194 if ( face ) 195 { 196 memory = face->root.memory; 197 198 #ifndef T1_CONFIG_OPTION_NO_MM_SUPPORT 199 /* release multiple masters information */ 200 T1_Done_Blend( face ); 201 face->blend = 0; 202 #endif 203 204 /* release font info strings */ 205 { 206 PS_FontInfo info = &type1->font_info; 207 208 209 FT_FREE( info->version ); 210 FT_FREE( info->notice ); 211 FT_FREE( info->full_name ); 212 FT_FREE( info->family_name ); 213 FT_FREE( info->weight ); 214 } 215 216 /* release top dictionary */ 217 FT_FREE( type1->charstrings_len ); 218 FT_FREE( type1->charstrings ); 219 FT_FREE( type1->glyph_names ); 220 221 FT_FREE( type1->subrs ); 222 FT_FREE( type1->subrs_len ); 223 224 FT_FREE( type1->subrs_block ); 225 FT_FREE( type1->charstrings_block ); 226 FT_FREE( type1->glyph_names_block ); 227 228 FT_FREE( type1->encoding.char_index ); 229 FT_FREE( type1->encoding.char_name ); 230 FT_FREE( type1->font_name ); 231 232 #ifndef T1_CONFIG_OPTION_NO_AFM 233 /* release afm data if present */ 234 if ( face->afm_data ) 235 T1_Done_AFM( memory, (T1_AFM*)face->afm_data ); 236 #endif 237 238 /* release unicode map, if any */ 239 FT_FREE( face->unicode_map.maps ); 240 face->unicode_map.num_maps = 0; 241 242 face->root.family_name = 0; 243 face->root.style_name = 0; 244 } 245 } 246 247 248 /*************************************************************************/ 249 /* */ 250 /* <Function> */ 251 /* T1_Face_Init */ 252 /* */ 253 /* <Description> */ 254 /* The face object constructor. */ 255 /* */ 256 /* <Input> */ 257 /* stream :: input stream where to load font data. */ 258 /* */ 259 /* face_index :: The index of the font face in the resource. */ 260 /* */ 261 /* num_params :: Number of additional generic parameters. Ignored. */ 262 /* */ 263 /* params :: Additional generic parameters. Ignored. */ 264 /* */ 265 /* <InOut> */ 266 /* face :: The face record to build. */ 267 /* */ 268 /* <Return> */ 269 /* FreeType error code. 0 means success. */ 270 /* */ 271 FT_LOCAL_DEF( FT_Error ) T1_Face_Init(FT_Stream stream,T1_Face face,FT_Int face_index,FT_Int num_params,FT_Parameter * params)272 T1_Face_Init( FT_Stream stream, 273 T1_Face face, 274 FT_Int face_index, 275 FT_Int num_params, 276 FT_Parameter* params ) 277 { 278 FT_Error error; 279 PSNames_Service psnames; 280 PSAux_Service psaux; 281 PSHinter_Service pshinter; 282 283 FT_UNUSED( num_params ); 284 FT_UNUSED( params ); 285 FT_UNUSED( face_index ); 286 FT_UNUSED( stream ); 287 288 289 face->root.num_faces = 1; 290 291 face->psnames = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), 292 "psnames" ); 293 psnames = (PSNames_Service)face->psnames; 294 295 face->psaux = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), 296 "psaux" ); 297 psaux = (PSAux_Service)face->psaux; 298 299 face->pshinter = FT_Get_Module_Interface( FT_FACE_LIBRARY( face ), 300 "pshinter" ); 301 pshinter = (PSHinter_Service)face->pshinter; 302 303 /* open the tokenizer, this will also check the font format */ 304 error = T1_Open_Face( face ); 305 if ( error ) 306 goto Exit; 307 308 /* if we just wanted to check the format, leave successfully now */ 309 if ( face_index < 0 ) 310 goto Exit; 311 312 /* check the face index */ 313 if ( face_index != 0 ) 314 { 315 FT_ERROR(( "T1_Face_Init: invalid face index\n" )); 316 error = T1_Err_Invalid_Argument; 317 goto Exit; 318 } 319 320 /* Now, load the font program into the face object */ 321 322 /* Init the face object fields */ 323 /* Now set up root face fields */ 324 { 325 FT_Face root = (FT_Face)&face->root; 326 327 328 root->num_glyphs = face->type1.num_glyphs; 329 root->face_index = face_index; 330 331 root->face_flags = FT_FACE_FLAG_SCALABLE; 332 root->face_flags |= FT_FACE_FLAG_HORIZONTAL; 333 root->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; 334 335 if ( face->type1.font_info.is_fixed_pitch ) 336 root->face_flags |= FT_FACE_FLAG_FIXED_WIDTH; 337 338 if ( face->blend ) 339 root->face_flags |= FT_FACE_FLAG_MULTIPLE_MASTERS; 340 341 /* XXX: TODO -- add kerning with .afm support */ 342 343 /* get style name -- be careful, some broken fonts only */ 344 /* have a `/FontName' dictionary entry! */ 345 root->family_name = face->type1.font_info.family_name; 346 if ( root->family_name ) 347 { 348 char* full = face->type1.font_info.full_name; 349 char* family = root->family_name; 350 351 352 if ( full ) 353 { 354 while ( *family && *full == *family ) 355 { 356 family++; 357 full++; 358 } 359 360 root->style_name = ( *full == ' ' ? full + 1 361 : (char *)"Regular" ); 362 } 363 else 364 root->style_name = (char *)"Regular"; 365 } 366 else 367 { 368 /* do we have a `/FontName'? */ 369 if ( face->type1.font_name ) 370 { 371 root->family_name = face->type1.font_name; 372 root->style_name = (char *)"Regular"; 373 } 374 } 375 376 /* compute style flags */ 377 root->style_flags = 0; 378 if ( face->type1.font_info.italic_angle ) 379 root->style_flags |= FT_STYLE_FLAG_ITALIC; 380 if ( face->type1.font_info.weight ) 381 { 382 if ( !ft_strcmp( face->type1.font_info.weight, "Bold" ) || 383 !ft_strcmp( face->type1.font_info.weight, "Black" ) ) 384 root->style_flags |= FT_STYLE_FLAG_BOLD; 385 } 386 387 /* no embedded bitmap support */ 388 root->num_fixed_sizes = 0; 389 root->available_sizes = 0; 390 391 root->bbox.xMin = face->type1.font_bbox.xMin >> 16; 392 root->bbox.yMin = face->type1.font_bbox.yMin >> 16; 393 root->bbox.xMax = ( face->type1.font_bbox.xMax + 0xFFFFU ) >> 16; 394 root->bbox.yMax = ( face->type1.font_bbox.yMax + 0xFFFFU ) >> 16; 395 396 /* Set units_per_EM if we didn't set it in parse_font_matrix. */ 397 if ( !root->units_per_EM ) 398 root->units_per_EM = 1000; 399 400 root->ascender = (FT_Short)( root->bbox.yMax ); 401 root->descender = (FT_Short)( root->bbox.yMin ); 402 root->height = (FT_Short)( 403 ( ( root->ascender - root->descender ) * 12 ) / 10 ); 404 405 /* now compute the maximum advance width */ 406 root->max_advance_width = 407 (FT_Short)( root->bbox.xMax ); 408 { 409 FT_Int max_advance; 410 411 412 error = T1_Compute_Max_Advance( face, &max_advance ); 413 414 /* in case of error, keep the standard width */ 415 if ( !error ) 416 root->max_advance_width = (FT_Short)max_advance; 417 else 418 error = 0; /* clear error */ 419 } 420 421 root->max_advance_height = root->height; 422 423 root->underline_position = face->type1.font_info.underline_position; 424 root->underline_thickness = face->type1.font_info.underline_thickness; 425 426 root->internal->max_points = 0; 427 root->internal->max_contours = 0; 428 } 429 430 { 431 FT_Face root = &face->root; 432 433 434 if ( psnames && psaux ) 435 { 436 FT_CharMapRec charmap; 437 T1_CMap_Classes cmap_classes = psaux->t1_cmap_classes; 438 FT_CMap_Class clazz; 439 440 441 charmap.face = root; 442 443 /* first of all, try to synthetize a Unicode charmap */ 444 charmap.platform_id = 3; 445 charmap.encoding_id = 1; 446 charmap.encoding = FT_ENCODING_UNICODE; 447 448 FT_CMap_New( cmap_classes->unicode, NULL, &charmap, NULL ); 449 450 /* now, generate an Adobe Standard encoding when appropriate */ 451 charmap.platform_id = 7; 452 clazz = NULL; 453 454 switch ( face->type1.encoding_type ) 455 { 456 case T1_ENCODING_TYPE_STANDARD: 457 charmap.encoding = FT_ENCODING_ADOBE_STANDARD; 458 charmap.encoding_id = 0; 459 clazz = cmap_classes->standard; 460 break; 461 462 case T1_ENCODING_TYPE_EXPERT: 463 charmap.encoding = FT_ENCODING_ADOBE_EXPERT; 464 charmap.encoding_id = 1; 465 clazz = cmap_classes->expert; 466 break; 467 468 case T1_ENCODING_TYPE_ARRAY: 469 charmap.encoding = FT_ENCODING_ADOBE_CUSTOM; 470 charmap.encoding_id = 2; 471 clazz = cmap_classes->custom; 472 break; 473 474 case T1_ENCODING_TYPE_ISOLATIN1: 475 charmap.encoding = FT_ENCODING_ADOBE_LATIN_1; 476 charmap.encoding_id = 3; 477 clazz = cmap_classes->unicode; 478 break; 479 480 default: 481 ; 482 } 483 484 if ( clazz ) 485 FT_CMap_New( clazz, NULL, &charmap, NULL ); 486 487 #if 0 488 /* Select default charmap */ 489 if (root->num_charmaps) 490 root->charmap = root->charmaps[0]; 491 #endif 492 } 493 } 494 495 Exit: 496 return error; 497 } 498 499 500 /*************************************************************************/ 501 /* */ 502 /* <Function> */ 503 /* T1_Driver_Init */ 504 /* */ 505 /* <Description> */ 506 /* Initializes a given Type 1 driver object. */ 507 /* */ 508 /* <Input> */ 509 /* driver :: A handle to the target driver object. */ 510 /* */ 511 /* <Return> */ 512 /* FreeType error code. 0 means success. */ 513 /* */ 514 FT_LOCAL_DEF( FT_Error ) T1_Driver_Init(T1_Driver driver)515 T1_Driver_Init( T1_Driver driver ) 516 { 517 FT_UNUSED( driver ); 518 519 return T1_Err_Ok; 520 } 521 522 523 /*************************************************************************/ 524 /* */ 525 /* <Function> */ 526 /* T1_Driver_Done */ 527 /* */ 528 /* <Description> */ 529 /* Finalizes a given Type 1 driver. */ 530 /* */ 531 /* <Input> */ 532 /* driver :: A handle to the target Type 1 driver. */ 533 /* */ 534 FT_LOCAL_DEF( void ) T1_Driver_Done(T1_Driver driver)535 T1_Driver_Done( T1_Driver driver ) 536 { 537 FT_UNUSED( driver ); 538 } 539 540 541 /* END */ 542