cffobjs.c revision f463818dd9146e11105c0572fb119e757eb47768
1/***************************************************************************/ 2/* */ 3/* cffobjs.c */ 4/* */ 5/* OpenType objects manager (body). */ 6/* */ 7/* Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007 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_CALC_H 22#include FT_INTERNAL_STREAM_H 23#include FT_ERRORS_H 24#include FT_TRUETYPE_IDS_H 25#include FT_TRUETYPE_TAGS_H 26#include FT_INTERNAL_SFNT_H 27#include FT_SERVICE_POSTSCRIPT_CMAPS_H 28#include FT_INTERNAL_POSTSCRIPT_HINTS_H 29#include "cffobjs.h" 30#include "cffload.h" 31#include "cffcmap.h" 32#include "cfferrs.h" 33 34 35 /*************************************************************************/ 36 /* */ 37 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */ 38 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */ 39 /* messages during execution. */ 40 /* */ 41#undef FT_COMPONENT 42#define FT_COMPONENT trace_cffobjs 43 44 45 /*************************************************************************/ 46 /* */ 47 /* SIZE FUNCTIONS */ 48 /* */ 49 /* Note that we store the global hints in the size's `internal' root */ 50 /* field. */ 51 /* */ 52 /*************************************************************************/ 53 54 55 static PSH_Globals_Funcs 56 cff_size_get_globals_funcs( CFF_Size size ) 57 { 58 CFF_Face face = (CFF_Face)size->root.face; 59 CFF_Font font = (CFF_FontRec *)face->extra.data; 60 PSHinter_Service pshinter = (PSHinter_Service)font->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 ) 73 cff_size_done( FT_Size cffsize ) /* CFF_Size */ 74 { 75 CFF_Size size = (CFF_Size)cffsize; 76 77 78 if ( cffsize->internal ) 79 { 80 PSH_Globals_Funcs funcs; 81 82 83 funcs = cff_size_get_globals_funcs( size ); 84 if ( funcs ) 85 funcs->destroy( (PSH_Globals)cffsize->internal ); 86 87 cffsize->internal = 0; 88 } 89 } 90 91 92 FT_LOCAL_DEF( FT_Error ) 93 cff_size_init( FT_Size cffsize ) /* CFF_Size */ 94 { 95 CFF_Size size = (CFF_Size)cffsize; 96 FT_Error error = CFF_Err_Ok; 97 PSH_Globals_Funcs funcs = cff_size_get_globals_funcs( size ); 98 99 100 if ( funcs ) 101 { 102 PSH_Globals globals; 103 CFF_Face face = (CFF_Face)cffsize->face; 104 CFF_Font font = (CFF_FontRec *)face->extra.data; 105 CFF_SubFont subfont = &font->top_font; 106 107 CFF_Private cpriv = &subfont->private_dict; 108 PS_PrivateRec priv; 109 110 111 /* IMPORTANT: The CFF and Type1 private dictionaries have */ 112 /* slightly different structures; we need to */ 113 /* synthetize a type1 dictionary on the fly here. */ 114 115 { 116 FT_UInt n, count; 117 118 119 FT_MEM_ZERO( &priv, sizeof ( priv ) ); 120 121 count = priv.num_blue_values = cpriv->num_blue_values; 122 for ( n = 0; n < count; n++ ) 123 priv.blue_values[n] = (FT_Short)cpriv->blue_values[n]; 124 125 count = priv.num_other_blues = cpriv->num_other_blues; 126 for ( n = 0; n < count; n++ ) 127 priv.other_blues[n] = (FT_Short)cpriv->other_blues[n]; 128 129 count = priv.num_family_blues = cpriv->num_family_blues; 130 for ( n = 0; n < count; n++ ) 131 priv.family_blues[n] = (FT_Short)cpriv->family_blues[n]; 132 133 count = priv.num_family_other_blues = cpriv->num_family_other_blues; 134 for ( n = 0; n < count; n++ ) 135 priv.family_other_blues[n] = (FT_Short)cpriv->family_other_blues[n]; 136 137 priv.blue_scale = cpriv->blue_scale; 138 priv.blue_shift = (FT_Int)cpriv->blue_shift; 139 priv.blue_fuzz = (FT_Int)cpriv->blue_fuzz; 140 141 priv.standard_width[0] = (FT_UShort)cpriv->standard_width; 142 priv.standard_height[0] = (FT_UShort)cpriv->standard_height; 143 144 count = priv.num_snap_widths = cpriv->num_snap_widths; 145 for ( n = 0; n < count; n++ ) 146 priv.snap_widths[n] = (FT_Short)cpriv->snap_widths[n]; 147 148 count = priv.num_snap_heights = cpriv->num_snap_heights; 149 for ( n = 0; n < count; n++ ) 150 priv.snap_heights[n] = (FT_Short)cpriv->snap_heights[n]; 151 152 priv.force_bold = cpriv->force_bold; 153 priv.language_group = cpriv->language_group; 154 priv.lenIV = cpriv->lenIV; 155 } 156 157 error = funcs->create( cffsize->face->memory, &priv, &globals ); 158 if ( !error ) 159 cffsize->internal = (FT_Size_Internal)(void*)globals; 160 } 161 162 size->strike_index = 0xFFFFFFFFUL; 163 164 return error; 165 } 166 167 168#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 169 170 FT_LOCAL_DEF( FT_Error ) 171 cff_size_select( FT_Size size, 172 FT_ULong strike_index ) 173 { 174 CFF_Size cffsize = (CFF_Size)size; 175 PSH_Globals_Funcs funcs; 176 177 178 cffsize->strike_index = strike_index; 179 180 FT_Select_Metrics( size->face, strike_index ); 181 182 funcs = cff_size_get_globals_funcs( cffsize ); 183 184 if ( funcs ) 185 funcs->set_scale( (PSH_Globals)size->internal, 186 size->metrics.x_scale, 187 size->metrics.y_scale, 188 0, 0 ); 189 190 return CFF_Err_Ok; 191 } 192 193#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 194 195 196 FT_LOCAL_DEF( FT_Error ) 197 cff_size_request( FT_Size size, 198 FT_Size_Request req ) 199 { 200 CFF_Size cffsize = (CFF_Size)size; 201 PSH_Globals_Funcs funcs; 202 203 204#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS 205 206 if ( FT_HAS_FIXED_SIZES( size->face ) ) 207 { 208 CFF_Face cffface = (CFF_Face)size->face; 209 SFNT_Service sfnt = (SFNT_Service)cffface->sfnt; 210 FT_ULong strike_index; 211 212 213 if ( sfnt->set_sbit_strike( cffface, req, &strike_index ) ) 214 cffsize->strike_index = 0xFFFFFFFFUL; 215 else 216 return cff_size_select( size, strike_index ); 217 } 218 219#endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */ 220 221 FT_Request_Metrics( size->face, req ); 222 223 funcs = cff_size_get_globals_funcs( cffsize ); 224 225 if ( funcs ) 226 funcs->set_scale( (PSH_Globals)size->internal, 227 size->metrics.x_scale, 228 size->metrics.y_scale, 229 0, 0 ); 230 231 return CFF_Err_Ok; 232 } 233 234 235 /*************************************************************************/ 236 /* */ 237 /* SLOT FUNCTIONS */ 238 /* */ 239 /*************************************************************************/ 240 241 FT_LOCAL_DEF( void ) 242 cff_slot_done( FT_GlyphSlot slot ) 243 { 244 slot->internal->glyph_hints = 0; 245 } 246 247 248 FT_LOCAL_DEF( FT_Error ) 249 cff_slot_init( FT_GlyphSlot slot ) 250 { 251 CFF_Face face = (CFF_Face)slot->face; 252 CFF_Font font = (CFF_FontRec *)face->extra.data; 253 PSHinter_Service pshinter = (PSHinter_Service)font->pshinter; 254 255 256 if ( pshinter ) 257 { 258 FT_Module module; 259 260 261 module = FT_Get_Module( slot->face->driver->root.library, 262 "pshinter" ); 263 if ( module ) 264 { 265 T2_Hints_Funcs funcs; 266 267 268 funcs = pshinter->get_t2_funcs( module ); 269 slot->internal->glyph_hints = (void*)funcs; 270 } 271 } 272 273 return 0; 274 } 275 276 277 /*************************************************************************/ 278 /* */ 279 /* FACE FUNCTIONS */ 280 /* */ 281 /*************************************************************************/ 282 283 static FT_String* 284 cff_strcpy( FT_Memory memory, 285 const FT_String* source ) 286 { 287 FT_Error error; 288 FT_String* result; 289 290 291 result = ft_mem_strdup( memory, source, &error ); 292 293 return result; 294 } 295 296 297 FT_LOCAL_DEF( FT_Error ) 298 cff_face_init( FT_Stream stream, 299 FT_Face cffface, /* CFF_Face */ 300 FT_Int face_index, 301 FT_Int num_params, 302 FT_Parameter* params ) 303 { 304 CFF_Face face = (CFF_Face)cffface; 305 FT_Error error; 306 SFNT_Service sfnt; 307 FT_Service_PsCMaps psnames; 308 PSHinter_Service pshinter; 309 FT_Bool pure_cff = 1; 310 FT_Bool sfnt_format = 0; 311 312 313#if 0 314 FT_FACE_FIND_GLOBAL_SERVICE( face, sfnt, SFNT ); 315 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_NAMES ); 316 FT_FACE_FIND_GLOBAL_SERVICE( face, pshinter, POSTSCRIPT_HINTER ); 317 318 if ( !sfnt ) 319 goto Bad_Format; 320#else 321 sfnt = (SFNT_Service)FT_Get_Module_Interface( 322 cffface->driver->root.library, "sfnt" ); 323 if ( !sfnt ) 324 goto Bad_Format; 325 326 FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS ); 327 328 pshinter = (PSHinter_Service)FT_Get_Module_Interface( 329 cffface->driver->root.library, "pshinter" ); 330#endif 331 332 /* create input stream from resource */ 333 if ( FT_STREAM_SEEK( 0 ) ) 334 goto Exit; 335 336 /* check whether we have a valid OpenType file */ 337 error = sfnt->init_face( stream, face, face_index, num_params, params ); 338 if ( !error ) 339 { 340 if ( face->format_tag != 0x4F54544FL ) /* `OTTO'; OpenType/CFF font */ 341 { 342 FT_TRACE2(( "[not a valid OpenType/CFF font]\n" )); 343 goto Bad_Format; 344 } 345 346 /* if we are performing a simple font format check, exit immediately */ 347 if ( face_index < 0 ) 348 return CFF_Err_Ok; 349 350 /* UNDOCUMENTED! A CFF in an SFNT can have only a single font. */ 351 if ( face_index > 0 ) 352 { 353 FT_ERROR(( "cff_face_init: invalid face index\n" )); 354 error = CFF_Err_Invalid_Argument; 355 goto Exit; 356 } 357 358 sfnt_format = 1; 359 360 /* now, the font can be either an OpenType/CFF font, or an SVG CEF */ 361 /* font; in the latter case it doesn't have a `head' table */ 362 error = face->goto_table( face, TTAG_head, stream, 0 ); 363 if ( !error ) 364 { 365 pure_cff = 0; 366 367 /* load font directory */ 368 error = sfnt->load_face( stream, face, 369 face_index, num_params, params ); 370 if ( error ) 371 goto Exit; 372 } 373 else 374 { 375 /* load the `cmap' table explicitly */ 376 error = sfnt->load_cmap( face, stream ); 377 if ( error ) 378 goto Exit; 379 380 /* XXX: we don't load the GPOS table, as OpenType Layout */ 381 /* support will be added later to a layout library on top of */ 382 /* FreeType 2 */ 383 } 384 385 /* now load the CFF part of the file */ 386 error = face->goto_table( face, TTAG_CFF, stream, 0 ); 387 if ( error ) 388 goto Exit; 389 } 390 else 391 { 392 /* rewind to start of file; we are going to load a pure-CFF font */ 393 if ( FT_STREAM_SEEK( 0 ) ) 394 goto Exit; 395 error = CFF_Err_Ok; 396 } 397 398 /* now load and parse the CFF table in the file */ 399 { 400 CFF_Font cff; 401 CFF_FontRecDict dict; 402 FT_Memory memory = cffface->memory; 403 FT_Int32 flags; 404 FT_UInt i; 405 406 407 if ( FT_NEW( cff ) ) 408 goto Exit; 409 410 face->extra.data = cff; 411 error = cff_font_load( stream, face_index, cff ); 412 if ( error ) 413 goto Exit; 414 415 cff->pshinter = pshinter; 416 cff->psnames = (void*)psnames; 417 418 /* Complement the root flags with some interesting information. */ 419 /* Note that this is only necessary for pure CFF and CEF fonts; */ 420 /* SFNT based fonts use the `name' table instead. */ 421 422 cffface->num_glyphs = cff->num_glyphs; 423 424 dict = &cff->top_font.font_dict; 425 426 /* we need the `PSNames' module for CFF and CEF formats */ 427 /* which aren't CID-keyed */ 428 if ( dict->cid_registry == 0xFFFFU && !psnames ) 429 { 430 FT_ERROR(( "cff_face_init:" )); 431 FT_ERROR(( " cannot open CFF & CEF fonts\n" )); 432 FT_ERROR(( " " )); 433 FT_ERROR(( " without the `PSNames' module\n" )); 434 goto Bad_Format; 435 } 436 437 if ( pure_cff ) 438 { 439 char* style_name = NULL; 440 441 442 /* set up num_faces */ 443 cffface->num_faces = cff->num_faces; 444 445 /* compute number of glyphs */ 446 if ( dict->cid_registry != 0xFFFFU ) 447 cffface->num_glyphs = dict->cid_count; 448 else 449 cffface->num_glyphs = cff->charstrings_index.count; 450 451 /* set global bbox, as well as EM size */ 452 cffface->bbox.xMin = dict->font_bbox.xMin >> 16; 453 cffface->bbox.yMin = dict->font_bbox.yMin >> 16; 454 cffface->bbox.xMax = ( dict->font_bbox.xMax + 0xFFFFU ) >> 16; 455 cffface->bbox.yMax = ( dict->font_bbox.yMax + 0xFFFFU ) >> 16; 456 457 if ( !dict->units_per_em ) 458 dict->units_per_em = 1000; 459 460 cffface->units_per_EM = dict->units_per_em; 461 462 cffface->ascender = (FT_Short)( cffface->bbox.yMax ); 463 cffface->descender = (FT_Short)( cffface->bbox.yMin ); 464 465 cffface->height = (FT_Short)( ( cffface->units_per_EM * 12 ) / 10 ); 466 if ( cffface->height < cffface->ascender - cffface->descender ) 467 cffface->height = (FT_Short)( cffface->ascender - cffface->descender ); 468 469 cffface->underline_position = 470 (FT_Short)( dict->underline_position >> 16 ); 471 cffface->underline_thickness = 472 (FT_Short)( dict->underline_thickness >> 16 ); 473 474 /* retrieve font family & style name */ 475 cffface->family_name = cff_index_get_name( &cff->name_index, 476 face_index ); 477 478 if ( cffface->family_name ) 479 { 480 char* full = cff_index_get_sid_string( &cff->string_index, 481 dict->full_name, 482 psnames ); 483 char* fullp = full; 484 char* family = cffface->family_name; 485 char* family_name = 0; 486 487 488 if ( dict->family_name ) 489 { 490 family_name = cff_index_get_sid_string( &cff->string_index, 491 dict->family_name, 492 psnames); 493 if ( family_name ) 494 family = family_name; 495 } 496 497 /* We try to extract the style name from the full name. */ 498 /* We need to ignore spaces and dashes during the search. */ 499 if ( full && family ) 500 { 501 while ( *fullp ) 502 { 503 /* skip common characters at the start of both strings */ 504 if ( *fullp == *family ) 505 { 506 family++; 507 fullp++; 508 continue; 509 } 510 511 /* ignore spaces and dashes in full name during comparison */ 512 if ( *fullp == ' ' || *fullp == '-' ) 513 { 514 fullp++; 515 continue; 516 } 517 518 /* ignore spaces and dashes in family name during comparison */ 519 if ( *family == ' ' || *family == '-' ) 520 { 521 family++; 522 continue; 523 } 524 525 if ( !*family && *fullp ) 526 { 527 /* The full name begins with the same characters as the */ 528 /* family name, with spaces and dashes removed. In this */ 529 /* case, the remaining string in `fullp' will be used as */ 530 /* the style name. */ 531 style_name = cff_strcpy( memory, fullp ); 532 } 533 break; 534 } 535 536 if ( family_name ) 537 FT_FREE( family_name ); 538 FT_FREE( full ); 539 } 540 } 541 else 542 { 543 char *cid_font_name = 544 cff_index_get_sid_string( &cff->string_index, 545 dict->cid_font_name, 546 psnames ); 547 548 549 /* do we have a `/FontName' for a CID-keyed font? */ 550 if ( cid_font_name ) 551 cffface->family_name = cid_font_name; 552 } 553 554 if ( style_name ) 555 cffface->style_name = style_name; 556 else 557 /* assume "Regular" style if we don't know better */ 558 cffface->style_name = cff_strcpy( memory, (char *)"Regular" ); 559 560 /*******************************************************************/ 561 /* */ 562 /* Compute face flags. */ 563 /* */ 564 flags = FT_FACE_FLAG_SCALABLE | /* scalable outlines */ 565 FT_FACE_FLAG_HORIZONTAL | /* horizontal data */ 566 FT_FACE_FLAG_HINTER; /* has native hinter */ 567 568 if ( sfnt_format ) 569 flags |= FT_FACE_FLAG_SFNT; 570 571 /* fixed width font? */ 572 if ( dict->is_fixed_pitch ) 573 flags |= FT_FACE_FLAG_FIXED_WIDTH; 574 575 /* XXX: WE DO NOT SUPPORT KERNING METRICS IN THE GPOS TABLE FOR NOW */ 576#if 0 577 /* kerning available? */ 578 if ( face->kern_pairs ) 579 flags |= FT_FACE_FLAG_KERNING; 580#endif 581 582 cffface->face_flags = flags; 583 584 /*******************************************************************/ 585 /* */ 586 /* Compute style flags. */ 587 /* */ 588 flags = 0; 589 590 if ( dict->italic_angle ) 591 flags |= FT_STYLE_FLAG_ITALIC; 592 593 { 594 char *weight = cff_index_get_sid_string( &cff->string_index, 595 dict->weight, 596 psnames ); 597 598 599 if ( weight ) 600 if ( !ft_strcmp( weight, "Bold" ) || 601 !ft_strcmp( weight, "Black" ) ) 602 flags |= FT_STYLE_FLAG_BOLD; 603 FT_FREE( weight ); 604 } 605 606 /* double check */ 607 if ( !(flags & FT_STYLE_FLAG_BOLD) && cffface->style_name ) 608 if ( !ft_strncmp( cffface->style_name, "Bold", 4 ) || 609 !ft_strncmp( cffface->style_name, "Black", 5 ) ) 610 flags |= FT_STYLE_FLAG_BOLD; 611 612 cffface->style_flags = flags; 613 } 614 else 615 { 616 if ( !dict->units_per_em ) 617 dict->units_per_em = face->root.units_per_EM; 618 } 619 620 /* handle font matrix settings in subfonts (if any) */ 621 for ( i = cff->num_subfonts; i > 0; i-- ) 622 { 623 CFF_FontRecDict sub = &cff->subfonts[i - 1]->font_dict; 624 CFF_FontRecDict top = &cff->top_font.font_dict; 625 626 627 if ( sub->units_per_em ) 628 { 629 FT_Matrix scale; 630 631 632 scale.xx = scale.yy = (FT_Fixed)FT_DivFix( top->units_per_em, 633 sub->units_per_em ); 634 scale.xy = scale.yx = 0; 635 636 FT_Matrix_Multiply( &scale, &sub->font_matrix ); 637 FT_Vector_Transform( &sub->font_offset, &scale ); 638 } 639 else 640 { 641 sub->font_matrix = top->font_matrix; 642 sub->font_offset = top->font_offset; 643 } 644 } 645 646#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES 647 /* CID-keyed CFF fonts don't have glyph names -- the SFNT loader */ 648 /* has unset this flag because of the 3.0 `post' table */ 649 if ( dict->cid_registry == 0xFFFFU ) 650 cffface->face_flags |= FT_FACE_FLAG_GLYPH_NAMES; 651#endif 652 653 /*******************************************************************/ 654 /* */ 655 /* Compute char maps. */ 656 /* */ 657 658 /* Try to synthetize a Unicode charmap if there is none available */ 659 /* already. If an OpenType font contains a Unicode "cmap", we */ 660 /* will use it, whatever be in the CFF part of the file. */ 661 { 662 FT_CharMapRec cmaprec; 663 FT_CharMap cmap; 664 FT_UInt nn; 665 CFF_Encoding encoding = &cff->encoding; 666 667 668 for ( nn = 0; nn < (FT_UInt)cffface->num_charmaps; nn++ ) 669 { 670 cmap = cffface->charmaps[nn]; 671 672 /* Windows Unicode (3,1)? */ 673 if ( cmap->platform_id == 3 && cmap->encoding_id == 1 ) 674 goto Skip_Unicode; 675 676 /* Deprecated Unicode platform id? */ 677 if ( cmap->platform_id == 0 ) 678 goto Skip_Unicode; /* Standard Unicode (deprecated) */ 679 } 680 681 /* since CID-keyed fonts don't contain glyph names, we can't */ 682 /* construct a cmap */ 683 if ( pure_cff && cff->top_font.font_dict.cid_registry != 0xFFFFU ) 684 goto Exit; 685 686 /* we didn't find a Unicode charmap -- synthetize one */ 687 cmaprec.face = cffface; 688 cmaprec.platform_id = 3; 689 cmaprec.encoding_id = 1; 690 cmaprec.encoding = FT_ENCODING_UNICODE; 691 692 nn = (FT_UInt)cffface->num_charmaps; 693 694 FT_CMap_New( &cff_cmap_unicode_class_rec, NULL, &cmaprec, NULL ); 695 696 /* if no Unicode charmap was previously selected, select this one */ 697 if ( cffface->charmap == NULL && nn != (FT_UInt)cffface->num_charmaps ) 698 cffface->charmap = cffface->charmaps[nn]; 699 700 Skip_Unicode: 701 if ( encoding->count > 0 ) 702 { 703 FT_CMap_Class clazz; 704 705 706 cmaprec.face = cffface; 707 cmaprec.platform_id = 7; /* Adobe platform id */ 708 709 if ( encoding->offset == 0 ) 710 { 711 cmaprec.encoding_id = TT_ADOBE_ID_STANDARD; 712 cmaprec.encoding = FT_ENCODING_ADOBE_STANDARD; 713 clazz = &cff_cmap_encoding_class_rec; 714 } 715 else if ( encoding->offset == 1 ) 716 { 717 cmaprec.encoding_id = TT_ADOBE_ID_EXPERT; 718 cmaprec.encoding = FT_ENCODING_ADOBE_EXPERT; 719 clazz = &cff_cmap_encoding_class_rec; 720 } 721 else 722 { 723 cmaprec.encoding_id = TT_ADOBE_ID_CUSTOM; 724 cmaprec.encoding = FT_ENCODING_ADOBE_CUSTOM; 725 clazz = &cff_cmap_encoding_class_rec; 726 } 727 728 FT_CMap_New( clazz, NULL, &cmaprec, NULL ); 729 } 730 } 731 } 732 733 Exit: 734 return error; 735 736 Bad_Format: 737 error = CFF_Err_Unknown_File_Format; 738 goto Exit; 739 } 740 741 742 FT_LOCAL_DEF( void ) 743 cff_face_done( FT_Face cffface ) /* CFF_Face */ 744 { 745 CFF_Face face = (CFF_Face)cffface; 746 FT_Memory memory = cffface->memory; 747 SFNT_Service sfnt = (SFNT_Service)face->sfnt; 748 749 750 if ( sfnt ) 751 sfnt->done_face( face ); 752 753 { 754 CFF_Font cff = (CFF_Font)face->extra.data; 755 756 757 if ( cff ) 758 { 759 cff_font_done( cff ); 760 FT_FREE( face->extra.data ); 761 } 762 } 763 } 764 765 766 FT_LOCAL_DEF( FT_Error ) 767 cff_driver_init( FT_Module module ) 768 { 769 FT_UNUSED( module ); 770 771 return CFF_Err_Ok; 772 } 773 774 775 FT_LOCAL_DEF( void ) 776 cff_driver_done( FT_Module module ) 777 { 778 FT_UNUSED( module ); 779 } 780 781 782/* END */ 783