cffdrivr.c revision aeb407daf3711a10a27f3bc2223c5eb05158076e
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,   */
8/*            2010 by                                                      */
9/*  David Turner, Robert Wilhelm, and Werner Lemberg.                      */
10/*                                                                         */
11/*  This file is part of the FreeType project, and may only be used,       */
12/*  modified, and distributed under the terms of the FreeType project      */
13/*  license, LICENSE.TXT.  By continuing to use, modify, or distribute     */
14/*  this file you indicate that you have read the license and              */
15/*  understand and accept it fully.                                        */
16/*                                                                         */
17/***************************************************************************/
18
19
20#include <ft2build.h>
21#include FT_FREETYPE_H
22#include FT_INTERNAL_DEBUG_H
23#include FT_INTERNAL_STREAM_H
24#include FT_INTERNAL_SFNT_H
25#include FT_SERVICE_CID_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_String*  gname;
233    FT_UShort   sid;
234    FT_Error    error;
235
236
237    if ( !font->psnames )
238    {
239      FT_ERROR(( "cff_get_glyph_name:"
240                 " cannot get glyph name from CFF & CEF fonts\n"
241                 "                   "
242                 " without the `PSNames' module\n" ));
243      error = CFF_Err_Unknown_File_Format;
244      goto Exit;
245    }
246
247    /* first, locate the sid in the charset table */
248    sid = font->charset.sids[glyph_index];
249
250    /* now, lookup the name itself */
251    gname = cff_index_get_sid_string( font, sid );
252
253    if ( gname )
254      FT_STRCPYN( buffer, gname, buffer_max );
255
256    error = CFF_Err_Ok;
257
258  Exit:
259    return error;
260  }
261
262
263  static FT_UInt
264  cff_get_name_index( CFF_Face    face,
265                      FT_String*  glyph_name )
266  {
267    CFF_Font            cff;
268    CFF_Charset         charset;
269    FT_Service_PsCMaps  psnames;
270    FT_String*          name;
271    FT_UShort           sid;
272    FT_UInt             i;
273
274
275    cff     = (CFF_FontRec *)face->extra.data;
276    charset = &cff->charset;
277
278    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
279    if ( !psnames )
280      return 0;
281
282    for ( i = 0; i < cff->num_glyphs; i++ )
283    {
284      sid = charset->sids[i];
285
286      if ( sid > 390 )
287        name = cff_index_get_string( cff, sid - 391 );
288      else
289        name = (FT_String *)psnames->adobe_std_strings( sid );
290
291      if ( !name )
292        continue;
293
294      if ( !ft_strcmp( glyph_name, name ) )
295        return i;
296    }
297
298    return 0;
299  }
300
301
302  FT_DEFINE_SERVICE_GLYPHDICTREC(cff_service_glyph_dict,
303    (FT_GlyphDict_GetNameFunc)  cff_get_glyph_name,
304    (FT_GlyphDict_NameIndexFunc)cff_get_name_index
305  )
306
307
308  /*
309   *  POSTSCRIPT INFO SERVICE
310   *
311   */
312
313  static FT_Int
314  cff_ps_has_glyph_names( FT_Face  face )
315  {
316    return ( face->face_flags & FT_FACE_FLAG_GLYPH_NAMES ) > 0;
317  }
318
319
320  static FT_Error
321  cff_ps_get_font_info( CFF_Face         face,
322                        PS_FontInfoRec*  afont_info )
323  {
324    CFF_Font  cff   = (CFF_Font)face->extra.data;
325    FT_Error  error = CFF_Err_Ok;
326
327
328    if ( cff && cff->font_info == NULL )
329    {
330      CFF_FontRecDict  dict   = &cff->top_font.font_dict;
331      PS_FontInfoRec  *font_info = NULL;
332      FT_Memory        memory = face->root.memory;
333
334
335      if ( FT_ALLOC( font_info, sizeof ( *font_info ) ) )
336        goto Fail;
337
338      font_info->version     = cff_index_get_sid_string( cff,
339                                                         dict->version );
340      font_info->notice      = cff_index_get_sid_string( cff,
341                                                         dict->notice );
342      font_info->full_name   = cff_index_get_sid_string( cff,
343                                                         dict->full_name );
344      font_info->family_name = cff_index_get_sid_string( cff,
345                                                         dict->family_name );
346      font_info->weight      = cff_index_get_sid_string( cff,
347                                                         dict->weight );
348      font_info->italic_angle        = dict->italic_angle;
349      font_info->is_fixed_pitch      = dict->is_fixed_pitch;
350      font_info->underline_position  = (FT_Short)dict->underline_position;
351      font_info->underline_thickness = (FT_Short)dict->underline_thickness;
352
353      cff->font_info = font_info;
354    }
355
356    if ( cff )
357      *afont_info = *cff->font_info;
358
359  Fail:
360    return error;
361  }
362
363
364  FT_DEFINE_SERVICE_PSINFOREC(cff_service_ps_info,
365    (PS_GetFontInfoFunc)   cff_ps_get_font_info,
366    (PS_GetFontExtraFunc)  NULL,
367    (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
368    (PS_GetFontPrivateFunc)NULL         /* unsupported with CFF fonts */
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_Module            sfnt;
603    FT_Module_Interface  result;
604
605
606    result = ft_service_list_lookup( FT_CFF_SERVICES_GET, module_interface );
607    if ( result != NULL )
608      return  result;
609
610    if ( !driver )
611      return NULL;
612
613    /* we pass our request to the `sfnt' module */
614    sfnt = FT_Get_Module( driver->library, "sfnt" );
615
616    return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
617  }
618
619
620  /* The FT_DriverInterface structure is defined in ftdriver.h. */
621
622#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
623#define CFF_SIZE_SELECT cff_size_select
624#else
625#define CFF_SIZE_SELECT 0
626#endif
627
628  FT_DEFINE_DRIVER(cff_driver_class,
629      FT_MODULE_FONT_DRIVER       |
630      FT_MODULE_DRIVER_SCALABLE   |
631      FT_MODULE_DRIVER_HAS_HINTER,
632
633      sizeof( CFF_DriverRec ),
634      "cff",
635      0x10000L,
636      0x20000L,
637
638      0,   /* module-specific interface */
639
640      cff_driver_init,
641      cff_driver_done,
642      cff_get_interface,
643
644    /* now the specific driver fields */
645    sizeof( TT_FaceRec ),
646    sizeof( CFF_SizeRec ),
647    sizeof( CFF_GlyphSlotRec ),
648
649    cff_face_init,
650    cff_face_done,
651    cff_size_init,
652    cff_size_done,
653    cff_slot_init,
654    cff_slot_done,
655
656    ft_stub_set_char_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */
657    ft_stub_set_pixel_sizes, /* FT_CONFIG_OPTION_OLD_INTERNALS */
658
659    Load_Glyph,
660
661    cff_get_kerning,
662    0,                      /* FT_Face_AttachFunc      */
663    cff_get_advances,       /* FT_Face_GetAdvancesFunc */
664
665    cff_size_request,
666
667    CFF_SIZE_SELECT
668  )
669
670
671/* END */
672