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