cffdrivr.c revision 41371e1e39c8528eb0c4bc40683c736e6683e60c
1/***************************************************************************/
2/*                                                                         */
3/*  cffdrivr.c                                                             */
4/*                                                                         */
5/*    OpenType font driver implementation (body).                          */
6/*                                                                         */
7/*  Copyright 1996-2012 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_FREETYPE_H
21#include FT_INTERNAL_DEBUG_H
22#include FT_INTERNAL_STREAM_H
23#include FT_INTERNAL_SFNT_H
24#include FT_SERVICE_CID_H
25#include FT_SERVICE_POSTSCRIPT_INFO_H
26#include FT_SERVICE_POSTSCRIPT_NAME_H
27#include FT_SERVICE_TT_CMAP_H
28
29#include "cffdrivr.h"
30#include "cffgload.h"
31#include "cffload.h"
32#include "cffcmap.h"
33#include "cffparse.h"
34
35#include "cfferrs.h"
36#include "cffpic.h"
37
38#include FT_SERVICE_XFREE86_NAME_H
39#include FT_SERVICE_GLYPH_DICT_H
40
41
42  /*************************************************************************/
43  /*                                                                       */
44  /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
45  /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
46  /* messages during execution.                                            */
47  /*                                                                       */
48#undef  FT_COMPONENT
49#define FT_COMPONENT  trace_cffdriver
50
51
52  /*************************************************************************/
53  /*************************************************************************/
54  /*************************************************************************/
55  /****                                                                 ****/
56  /****                                                                 ****/
57  /****                          F A C E S                              ****/
58  /****                                                                 ****/
59  /****                                                                 ****/
60  /*************************************************************************/
61  /*************************************************************************/
62  /*************************************************************************/
63
64
65#undef  PAIR_TAG
66#define PAIR_TAG( left, right )  ( ( (FT_ULong)left << 16 ) | \
67                                     (FT_ULong)right        )
68
69
70  /*************************************************************************/
71  /*                                                                       */
72  /* <Function>                                                            */
73  /*    cff_get_kerning                                                    */
74  /*                                                                       */
75  /* <Description>                                                         */
76  /*    A driver method used to return the kerning vector between two      */
77  /*    glyphs of the same face.                                           */
78  /*                                                                       */
79  /* <Input>                                                               */
80  /*    face        :: A handle to the source face object.                 */
81  /*                                                                       */
82  /*    left_glyph  :: The index of the left glyph in the kern pair.       */
83  /*                                                                       */
84  /*    right_glyph :: The index of the right glyph in the kern pair.      */
85  /*                                                                       */
86  /* <Output>                                                              */
87  /*    kerning     :: The kerning vector.  This is in font units for      */
88  /*                   scalable formats, and in pixels for fixed-sizes     */
89  /*                   formats.                                            */
90  /*                                                                       */
91  /* <Return>                                                              */
92  /*    FreeType error code.  0 means success.                             */
93  /*                                                                       */
94  /* <Note>                                                                */
95  /*    Only horizontal layouts (left-to-right & right-to-left) are        */
96  /*    supported by this function.  Other layouts, or more sophisticated  */
97  /*    kernings, are out of scope of this method (the basic driver        */
98  /*    interface is meant to be simple).                                  */
99  /*                                                                       */
100  /*    They can be implemented by format-specific interfaces.             */
101  /*                                                                       */
102  FT_CALLBACK_DEF( FT_Error )
103  cff_get_kerning( FT_Face     ttface,          /* TT_Face */
104                   FT_UInt     left_glyph,
105                   FT_UInt     right_glyph,
106                   FT_Vector*  kerning )
107  {
108    TT_Face       face = (TT_Face)ttface;
109    SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
110
111
112    kerning->x = 0;
113    kerning->y = 0;
114
115    if ( sfnt )
116      kerning->x = sfnt->get_kerning( face, left_glyph, right_glyph );
117
118    return CFF_Err_Ok;
119  }
120
121
122#undef PAIR_TAG
123
124
125  /*************************************************************************/
126  /*                                                                       */
127  /* <Function>                                                            */
128  /*    cff_glyph_load                                                     */
129  /*                                                                       */
130  /* <Description>                                                         */
131  /*    A driver method used to load a glyph within a given glyph slot.    */
132  /*                                                                       */
133  /* <Input>                                                               */
134  /*    slot        :: A handle to the target slot object where the glyph  */
135  /*                   will be loaded.                                     */
136  /*                                                                       */
137  /*    size        :: A handle to the source face size at which the glyph */
138  /*                   must be scaled, loaded, etc.                        */
139  /*                                                                       */
140  /*    glyph_index :: The index of the glyph in the font file.            */
141  /*                                                                       */
142  /*    load_flags  :: A flag indicating what to load for this glyph.  The */
143  /*                   FT_LOAD_??? constants can be used to control the    */
144  /*                   glyph loading process (e.g., whether the outline    */
145  /*                   should be scaled, whether to load bitmaps or not,   */
146  /*                   whether to hint the outline, etc).                  */
147  /*                                                                       */
148  /* <Return>                                                              */
149  /*    FreeType error code.  0 means success.                             */
150  /*                                                                       */
151  FT_CALLBACK_DEF( FT_Error )
152  cff_glyph_load( FT_GlyphSlot  cffslot,      /* CFF_GlyphSlot */
153                  FT_Size       cffsize,      /* CFF_Size      */
154                  FT_UInt       glyph_index,
155                  FT_Int32      load_flags )
156  {
157    FT_Error       error;
158    CFF_GlyphSlot  slot = (CFF_GlyphSlot)cffslot;
159    CFF_Size       size = (CFF_Size)cffsize;
160
161
162    if ( !slot )
163      return CFF_Err_Invalid_Slot_Handle;
164
165    /* check whether we want a scaled outline or bitmap */
166    if ( !size )
167      load_flags |= FT_LOAD_NO_SCALE | FT_LOAD_NO_HINTING;
168
169    /* reset the size object if necessary */
170    if ( load_flags & FT_LOAD_NO_SCALE )
171      size = NULL;
172
173    if ( size )
174    {
175      /* these two objects must have the same parent */
176      if ( cffsize->face != cffslot->face )
177        return CFF_Err_Invalid_Face_Handle;
178    }
179
180    /* now load the glyph outline if necessary */
181    error = cff_slot_load( slot, size, glyph_index, load_flags );
182
183    /* force drop-out mode to 2 - irrelevant now */
184    /* slot->outline.dropout_mode = 2; */
185
186    return error;
187  }
188
189
190  FT_CALLBACK_DEF( FT_Error )
191  cff_get_advances( FT_Face    face,
192                    FT_UInt    start,
193                    FT_UInt    count,
194                    FT_Int32   flags,
195                    FT_Fixed*  advances )
196  {
197    FT_UInt       nn;
198    FT_Error      error = CFF_Err_Ok;
199    FT_GlyphSlot  slot  = face->glyph;
200
201
202    flags |= (FT_UInt32)FT_LOAD_ADVANCE_ONLY;
203
204    for ( nn = 0; nn < count; nn++ )
205    {
206      error = cff_glyph_load( slot, face->size, start + nn, flags );
207      if ( error )
208        break;
209
210      advances[nn] = ( flags & FT_LOAD_VERTICAL_LAYOUT )
211                     ? slot->linearVertAdvance
212                     : slot->linearHoriAdvance;
213    }
214
215    return error;
216  }
217
218
219  /*
220   *  GLYPH DICT SERVICE
221   *
222   */
223
224  static FT_Error
225  cff_get_glyph_name( CFF_Face    face,
226                      FT_UInt     glyph_index,
227                      FT_Pointer  buffer,
228                      FT_UInt     buffer_max )
229  {
230    CFF_Font    font   = (CFF_Font)face->extra.data;
231    FT_String*  gname;
232    FT_UShort   sid;
233    FT_Error    error;
234
235
236    if ( !font->psnames )
237    {
238      FT_ERROR(( "cff_get_glyph_name:"
239                 " cannot get glyph name from CFF & CEF fonts\n"
240                 "                   "
241                 " without the `PSNames' module\n" ));
242      error = CFF_Err_Missing_Module;
243      goto Exit;
244    }
245
246    /* first, locate the sid in the charset table */
247    sid = font->charset.sids[glyph_index];
248
249    /* now, lookup the name itself */
250    gname = cff_index_get_sid_string( font, sid );
251
252    if ( gname )
253      FT_STRCPYN( buffer, gname, buffer_max );
254
255    error = CFF_Err_Ok;
256
257  Exit:
258    return error;
259  }
260
261
262  static FT_UInt
263  cff_get_name_index( CFF_Face    face,
264                      FT_String*  glyph_name )
265  {
266    CFF_Font            cff;
267    CFF_Charset         charset;
268    FT_Service_PsCMaps  psnames;
269    FT_String*          name;
270    FT_UShort           sid;
271    FT_UInt             i;
272
273
274    cff     = (CFF_FontRec *)face->extra.data;
275    charset = &cff->charset;
276
277    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
278    if ( !psnames )
279      return 0;
280
281    for ( i = 0; i < cff->num_glyphs; i++ )
282    {
283      sid = charset->sids[i];
284
285      if ( sid > 390 )
286        name = cff_index_get_string( cff, sid - 391 );
287      else
288        name = (FT_String *)psnames->adobe_std_strings( sid );
289
290      if ( !name )
291        continue;
292
293      if ( !ft_strcmp( glyph_name, name ) )
294        return i;
295    }
296
297    return 0;
298  }
299
300
301  FT_DEFINE_SERVICE_GLYPHDICTREC(cff_service_glyph_dict,
302    (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,
303    (FT_GlyphDict_NameIndexFunc)cff_get_name_index
304  )
305
306
307  /*
308   *  POSTSCRIPT INFO SERVICE
309   *
310   */
311
312  static FT_Int
313  cff_ps_has_glyph_names( FT_Face  face )
314  {
315    return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
316  }
317
318
319  static FT_Error
320  cff_ps_get_font_info( CFF_Face         face,
321                        PS_FontInfoRec*  afont_info )
322  {
323    CFF_Font  cff   = (CFF_Font)face->extra.data;
324    FT_Error  error = CFF_Err_Ok;
325
326
327    if ( cff && cff->font_info == NULL )
328    {
329      CFF_FontRecDict  dict   = &cff->top_font.font_dict;
330      PS_FontInfoRec  *font_info = NULL;
331      FT_Memory        memory = face->root.memory;
332
333
334      if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
335        goto Fail;
336
337      font_info->version     = cff_index_get_sid_string( cff,
338                                                         dict->version );
339      font_info->notice      = cff_index_get_sid_string( cff,
340                                                         dict->notice );
341      font_info->full_name   = cff_index_get_sid_string( cff,
342                                                         dict->full_name );
343      font_info->family_name = cff_index_get_sid_string( cff,
344                                                         dict->family_name );
345      font_info->weight      = cff_index_get_sid_string( cff,
346                                                         dict->weight );
347      font_info->italic_angle        = dict->italic_angle;
348      font_info->is_fixed_pitch      = dict->is_fixed_pitch;
349      font_info->underline_position  = (FT_Short)dict->underline_position;
350      font_info->underline_thickness = (FT_Short)dict->underline_thickness;
351
352      cff->font_info = font_info;
353    }
354
355    if ( cff )
356      *afont_info = *cff->font_info;
357
358  Fail:
359    return error;
360  }
361
362
363  FT_DEFINE_SERVICE_PSINFOREC(cff_service_ps_info,
364    (PS_GetFontInfoFunc)   cff_ps_get_font_info,
365    (PS_GetFontExtraFunc)  NULL,
366    (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
367    (PS_GetFontPrivateFunc)NULL,        /* unsupported with CFF fonts */
368    (PS_GetFontValueFunc)  NULL         /* not implemented            */
369  )
370
371
372  /*
373   *  POSTSCRIPT NAME SERVICE
374   *
375   */
376
377  static const char*
378  cff_get_ps_name( CFF_Face  face )
379  {
380    CFF_Font  cff = (CFF_Font)face->extra.data;
381
382
383    return (const char*)cff->font_name;
384  }
385
386
387  FT_DEFINE_SERVICE_PSFONTNAMEREC(cff_service_ps_name,
388    (FT_PsName_GetFunc)cff_get_ps_name
389  )
390
391
392  /*
393   * TT CMAP INFO
394   *
395   * If the charmap is a synthetic Unicode encoding cmap or
396   * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
397   * service defined in SFNT module.
398   *
399   * Otherwise call the service function in the sfnt module.
400   *
401   */
402  static FT_Error
403  cff_get_cmap_info( FT_CharMap    charmap,
404                     TT_CMapInfo  *cmap_info )
405  {
406    FT_CMap   cmap  = FT_CMAP( charmap );
407    FT_Error  error = CFF_Err_Ok;
408    FT_Face    face    = FT_CMAP_FACE( cmap );
409    FT_Library library = FT_FACE_LIBRARY( face );
410
411
412    cmap_info->language = 0;
413    cmap_info->format   = 0;
414
415    if ( cmap->clazz != &FT_CFF_CMAP_ENCODING_CLASS_REC_GET &&
416         cmap->clazz != &FT_CFF_CMAP_UNICODE_CLASS_REC_GET  )
417    {
418      FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
419      FT_Service_TTCMaps  service =
420        (FT_Service_TTCMaps)ft_module_get_service( sfnt,
421                                                   FT_SERVICE_ID_TT_CMAP );
422
423
424      if ( service && service->get_cmap_info )
425        error = service->get_cmap_info( charmap, cmap_info );
426    }
427
428    return error;
429  }
430
431
432  FT_DEFINE_SERVICE_TTCMAPSREC(cff_service_get_cmap_info,
433    (TT_CMap_Info_GetFunc)cff_get_cmap_info
434  )
435
436
437  /*
438   *  CID INFO SERVICE
439   *
440   */
441  static FT_Error
442  cff_get_ros( CFF_Face      face,
443               const char*  *registry,
444               const char*  *ordering,
445               FT_Int       *supplement )
446  {
447    FT_Error  error = CFF_Err_Ok;
448    CFF_Font  cff   = (CFF_Font)face->extra.data;
449
450
451    if ( cff )
452    {
453      CFF_FontRecDict  dict = &cff->top_font.font_dict;
454
455
456      if ( dict->cid_registry == 0xFFFFU )
457      {
458        error = CFF_Err_Invalid_Argument;
459        goto Fail;
460      }
461
462      if ( registry )
463      {
464        if ( cff->registry == NULL )
465          cff->registry = cff_index_get_sid_string( cff,
466                                                    dict->cid_registry );
467        *registry = cff->registry;
468      }
469
470      if ( ordering )
471      {
472        if ( cff->ordering == NULL )
473          cff->ordering = cff_index_get_sid_string( cff,
474                                                    dict->cid_ordering );
475        *ordering = cff->ordering;
476      }
477
478      /*
479       * XXX: According to Adobe TechNote #5176, the supplement in CFF
480       *      can be a real number. We truncate it to fit public API
481       *      since freetype-2.3.6.
482       */
483      if ( supplement )
484      {
485        if ( dict->cid_supplement < FT_INT_MIN ||
486             dict->cid_supplement > FT_INT_MAX )
487          FT_TRACE1(( "cff_get_ros: too large supplement %d is truncated\n",
488                      dict->cid_supplement ));
489        *supplement = (FT_Int)dict->cid_supplement;
490      }
491    }
492
493  Fail:
494    return error;
495  }
496
497
498  static FT_Error
499  cff_get_is_cid( CFF_Face  face,
500                  FT_Bool  *is_cid )
501  {
502    FT_Error  error = CFF_Err_Ok;
503    CFF_Font  cff   = (CFF_Font)face->extra.data;
504
505
506    *is_cid = 0;
507
508    if ( cff )
509    {
510      CFF_FontRecDict  dict = &cff->top_font.font_dict;
511
512
513      if ( dict->cid_registry != 0xFFFFU )
514        *is_cid = 1;
515    }
516
517    return error;
518  }
519
520
521  static FT_Error
522  cff_get_cid_from_glyph_index( CFF_Face  face,
523                                FT_UInt   glyph_index,
524                                FT_UInt  *cid )
525  {
526    FT_Error  error = CFF_Err_Ok;
527    CFF_Font  cff;
528
529
530    cff = (CFF_Font)face->extra.data;
531
532    if ( cff )
533    {
534      FT_UInt          c;
535      CFF_FontRecDict  dict = &cff->top_font.font_dict;
536
537
538      if ( dict->cid_registry == 0xFFFFU )
539      {
540        error = CFF_Err_Invalid_Argument;
541        goto Fail;
542      }
543
544      if ( glyph_index > cff->num_glyphs )
545      {
546        error = CFF_Err_Invalid_Argument;
547        goto Fail;
548      }
549
550      c = cff->charset.sids[glyph_index];
551
552      if ( cid )
553        *cid = c;
554    }
555
556  Fail:
557    return error;
558  }
559
560
561  FT_DEFINE_SERVICE_CIDREC(cff_service_cid_info,
562    (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
563    (FT_CID_GetIsInternallyCIDKeyedFunc)      cff_get_is_cid,
564    (FT_CID_GetCIDFromGlyphIndexFunc)         cff_get_cid_from_glyph_index
565  )
566
567
568  /*************************************************************************/
569  /*************************************************************************/
570  /*************************************************************************/
571  /****                                                                 ****/
572  /****                                                                 ****/
573  /****                D R I V E R  I N T E R F A C E                   ****/
574  /****                                                                 ****/
575  /****                                                                 ****/
576  /*************************************************************************/
577  /*************************************************************************/
578  /*************************************************************************/
579#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
580  FT_DEFINE_SERVICEDESCREC6(cff_services,
581    FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
582    FT_SERVICE_ID_POSTSCRIPT_INFO,      &FT_CFF_SERVICE_PS_INFO_GET,
583    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET,
584    FT_SERVICE_ID_GLYPH_DICT,           &FT_CFF_SERVICE_GLYPH_DICT_GET,
585    FT_SERVICE_ID_TT_CMAP,              &FT_CFF_SERVICE_GET_CMAP_INFO_GET,
586    FT_SERVICE_ID_CID,                  &FT_CFF_SERVICE_CID_INFO_GET
587  )
588#else
589  FT_DEFINE_SERVICEDESCREC5(cff_services,
590    FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF,
591    FT_SERVICE_ID_POSTSCRIPT_INFO,      &FT_CFF_SERVICE_PS_INFO_GET,
592    FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_CFF_SERVICE_PS_NAME_GET,
593    FT_SERVICE_ID_TT_CMAP,              &FT_CFF_SERVICE_GET_CMAP_INFO_GET,
594    FT_SERVICE_ID_CID,                  &FT_CFF_SERVICE_CID_INFO_GET
595  )
596#endif
597
598  FT_CALLBACK_DEF( FT_Module_Interface )
599  cff_get_interface( FT_Module    driver,       /* CFF_Driver */
600                     const char*  module_interface )
601  {
602    FT_Library           library;
603    FT_Module            sfnt;
604    FT_Module_Interface  result;
605
606
607    /* FT_CFF_SERVICES_GET derefers `library' in PIC mode */
608#ifdef FT_CONFIG_OPTION_PIC
609    if ( !driver )
610      return NULL;
611    library = driver->library;
612    if ( !library )
613      return NULL;
614#endif
615
616    result = ft_service_list_lookup( FT_CFF_SERVICES_GET, module_interface );
617    if ( result != NULL )
618      return result;
619
620    /* `driver' is not yet evaluated in non-PIC mode */
621#ifndef FT_CONFIG_OPTION_PIC
622    if ( !driver )
623      return NULL;
624    library = driver->library;
625    if ( !library )
626      return NULL;
627#endif
628
629    /* we pass our request to the `sfnt' module */
630    sfnt = FT_Get_Module( library, "sfnt" );
631
632    return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
633  }
634
635
636  /* The FT_DriverInterface structure is defined in ftdriver.h. */
637
638#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
639#define CFF_SIZE_SELECT cff_size_select
640#else
641#define CFF_SIZE_SELECT 0
642#endif
643
644  FT_DEFINE_DRIVER( cff_driver_class,
645
646      FT_MODULE_FONT_DRIVER       |
647      FT_MODULE_DRIVER_SCALABLE   |
648      FT_MODULE_DRIVER_HAS_HINTER,
649
650      sizeof ( CFF_DriverRec ),
651      "cff",
652      0x10000L,
653      0x20000L,
654
655      0,   /* module-specific interface */
656
657      cff_driver_init,
658      cff_driver_done,
659      cff_get_interface,
660
661    /* now the specific driver fields */
662    sizeof ( TT_FaceRec ),
663    sizeof ( CFF_SizeRec ),
664    sizeof ( CFF_GlyphSlotRec ),
665
666    cff_face_init,
667    cff_face_done,
668    cff_size_init,
669    cff_size_done,
670    cff_slot_init,
671    cff_slot_done,
672
673    ft_stub_set_char_sizes,  /* FT_CONFIG_OPTION_OLD_INTERNALS */
674    ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */
675
676    cff_glyph_load,
677
678    cff_get_kerning,
679    0,                       /* FT_Face_AttachFunc */
680    cff_get_advances,
681
682    cff_size_request,
683
684    CFF_SIZE_SELECT
685  )
686
687
688/* END */
689