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