cffdrivr.c revision 77f63d23f7d380b0ff02c18fd6a154ab9063128a
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_TRUETYPE_IDS_H
25#include FT_SERVICE_CID_H
26#include FT_SERVICE_POSTSCRIPT_CMAPS_H
27#include FT_SERVICE_POSTSCRIPT_INFO_H
28#include FT_SERVICE_POSTSCRIPT_NAME_H
29#include FT_SERVICE_TT_CMAP_H
30
31#include "cffdrivr.h"
32#include "cffgload.h"
33#include "cffload.h"
34#include "cffcmap.h"
35
36#include "cfferrs.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  /*    Load_Glyph                                                         */
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  Load_Glyph( 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_LOAD_ADVANCE_ONLY;
203
204    for ( nn = 0; nn < count; nn++ )
205    {
206      error = Load_Glyph( 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_Memory           memory = FT_FACE_MEMORY( face );
232    FT_String*          gname;
233    FT_UShort           sid;
234    FT_Service_PsCMaps  psnames;
235    FT_Error            error;
236
237
238    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
239    if ( !psnames )
240    {
241      FT_ERROR(( "cff_get_glyph_name:" ));
242      FT_ERROR(( " cannot get glyph name from CFF & CEF fonts\n" ));
243      FT_ERROR(( "                   " ));
244      FT_ERROR(( " without the `PSNames' module\n" ));
245      error = CFF_Err_Unknown_File_Format;
246      goto Exit;
247    }
248
249    /* first, locate the sid in the charset table */
250    sid = font->charset.sids[glyph_index];
251
252    /* now, lookup the name itself */
253    gname = cff_index_get_sid_string( &font->string_index, sid, psnames );
254
255    if ( gname )
256      FT_STRCPYN( buffer, gname, buffer_max );
257
258    FT_FREE( gname );
259    error = CFF_Err_Ok;
260
261  Exit:
262    return error;
263  }
264
265
266  static FT_UInt
267  cff_get_name_index( CFF_Face    face,
268                      FT_String*  glyph_name )
269  {
270    CFF_Font            cff;
271    CFF_Charset         charset;
272    FT_Service_PsCMaps  psnames;
273    FT_Memory           memory = FT_FACE_MEMORY( face );
274    FT_String*          name;
275    FT_UShort           sid;
276    FT_UInt             i;
277    FT_Int              result;
278
279
280    cff     = (CFF_FontRec *)face->extra.data;
281    charset = &cff->charset;
282
283    FT_FACE_FIND_GLOBAL_SERVICE( face, psnames, POSTSCRIPT_CMAPS );
284    if ( !psnames )
285      return 0;
286
287    for ( i = 0; i < cff->num_glyphs; i++ )
288    {
289      sid = charset->sids[i];
290
291      if ( sid > 390 )
292        name = cff_index_get_name( &cff->string_index, sid - 391 );
293      else
294        name = (FT_String *)psnames->adobe_std_strings( sid );
295
296      if ( !name )
297        continue;
298
299      result = ft_strcmp( glyph_name, name );
300
301      if ( sid > 390 )
302        FT_FREE( name );
303
304      if ( !result )
305        return i;
306    }
307
308    return 0;
309  }
310
311
312  static const FT_Service_GlyphDictRec  cff_service_glyph_dict =
313  {
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  static const FT_Service_PsInfoRec  cff_service_ps_info =
382  {
383    (PS_GetFontInfoFunc)   cff_ps_get_font_info,
384    (PS_GetFontExtraFunc)  NULL,
385    (PS_HasGlyphNamesFunc) cff_ps_has_glyph_names,
386    (PS_GetFontPrivateFunc)NULL         /* unsupported with CFF fonts */
387  };
388
389
390  /*
391   *  POSTSCRIPT NAME SERVICE
392   *
393   */
394
395  static const char*
396  cff_get_ps_name( CFF_Face  face )
397  {
398    CFF_Font  cff = (CFF_Font)face->extra.data;
399
400
401    return (const char*)cff->font_name;
402  }
403
404
405  static const FT_Service_PsFontNameRec  cff_service_ps_name =
406  {
407    (FT_PsName_GetFunc)cff_get_ps_name
408  };
409
410
411  /*
412   * TT CMAP INFO
413   *
414   * If the charmap is a synthetic Unicode encoding cmap or
415   * a Type 1 standard (or expert) encoding cmap, hide TT CMAP INFO
416   * service defined in SFNT module.
417   *
418   * Otherwise call the service function in the sfnt module.
419   *
420   */
421  static FT_Error
422  cff_get_cmap_info( FT_CharMap    charmap,
423                     TT_CMapInfo  *cmap_info )
424  {
425    FT_CMap   cmap  = FT_CMAP( charmap );
426    FT_Error  error = CFF_Err_Ok;
427
428
429    cmap_info->language = 0;
430    cmap_info->format   = 0;
431
432    if ( cmap->clazz != &cff_cmap_encoding_class_rec &&
433         cmap->clazz != &cff_cmap_unicode_class_rec  )
434    {
435      FT_Face             face    = FT_CMAP_FACE( cmap );
436      FT_Library          library = FT_FACE_LIBRARY( face );
437      FT_Module           sfnt    = FT_Get_Module( library, "sfnt" );
438      FT_Service_TTCMaps  service =
439        (FT_Service_TTCMaps)ft_module_get_service( sfnt,
440                                                   FT_SERVICE_ID_TT_CMAP );
441
442
443      if ( service && service->get_cmap_info )
444        error = service->get_cmap_info( charmap, cmap_info );
445    }
446
447    return error;
448  }
449
450
451  static const FT_Service_TTCMapsRec  cff_service_get_cmap_info =
452  {
453    (TT_CMap_Info_GetFunc)cff_get_cmap_info
454  };
455
456
457  /*
458   *  CID INFO SERVICE
459   *
460   */
461  static FT_Error
462  cff_get_ros( CFF_Face      face,
463               const char*  *registry,
464               const char*  *ordering,
465               FT_Int       *supplement )
466  {
467    FT_Error  error = CFF_Err_Ok;
468    CFF_Font  cff   = (CFF_Font)face->extra.data;
469
470
471    if ( cff )
472    {
473      CFF_FontRecDict     dict    = &cff->top_font.font_dict;
474      FT_Service_PsCMaps  psnames = (FT_Service_PsCMaps)cff->psnames;
475
476
477      if ( dict->cid_registry == 0xFFFFU )
478      {
479        error = CFF_Err_Invalid_Argument;
480        goto Fail;
481      }
482
483      if ( registry )
484      {
485        if ( cff->registry == NULL )
486          cff->registry = cff_index_get_sid_string( &cff->string_index,
487                                                    dict->cid_registry,
488                                                    psnames );
489        *registry = cff->registry;
490      }
491
492      if ( ordering )
493      {
494        if ( cff->ordering == NULL )
495          cff->ordering = cff_index_get_sid_string( &cff->string_index,
496                                                    dict->cid_ordering,
497                                                    psnames );
498        *ordering = cff->ordering;
499      }
500
501      if ( supplement )
502        *supplement = dict->cid_supplement;
503    }
504
505  Fail:
506    return error;
507  }
508
509
510  static FT_Error
511  cff_get_is_cid( CFF_Face  face,
512                  FT_Bool  *is_cid )
513  {
514    FT_Error  error = CFF_Err_Ok;
515    CFF_Font  cff   = (CFF_Font)face->extra.data;
516
517
518    *is_cid = 0;
519
520    if ( cff )
521    {
522      CFF_FontRecDict  dict = &cff->top_font.font_dict;
523
524
525      if ( dict->cid_registry != 0xFFFFU )
526        *is_cid = 1;
527    }
528
529    return error;
530  }
531
532
533  static FT_Error
534  cff_get_cid_from_glyph_index( CFF_Face  face,
535                                FT_UInt   glyph_index,
536                                FT_UInt  *cid )
537  {
538    FT_Error  error = CFF_Err_Ok;
539    CFF_Font  cff;
540
541
542    cff = (CFF_Font)face->extra.data;
543
544    if ( cff )
545    {
546      FT_UInt          c;
547      CFF_FontRecDict  dict = &cff->top_font.font_dict;
548
549
550      if ( dict->cid_registry == 0xFFFFU )
551      {
552        error = CFF_Err_Invalid_Argument;
553        goto Fail;
554      }
555
556      if ( glyph_index > cff->num_glyphs )
557      {
558        error = CFF_Err_Invalid_Argument;
559        goto Fail;
560      }
561
562      c = cff->charset.sids[glyph_index];
563
564      if ( cid )
565        *cid = c;
566    }
567
568  Fail:
569    return error;
570  }
571
572
573  static const FT_Service_CIDRec  cff_service_cid_info =
574  {
575    (FT_CID_GetRegistryOrderingSupplementFunc)cff_get_ros,
576    (FT_CID_GetIsInternallyCIDKeyedFunc)      cff_get_is_cid,
577    (FT_CID_GetCIDFromGlyphIndexFunc)         cff_get_cid_from_glyph_index
578  };
579
580
581  /*************************************************************************/
582  /*************************************************************************/
583  /*************************************************************************/
584  /****                                                                 ****/
585  /****                                                                 ****/
586  /****                D R I V E R  I N T E R F A C E                   ****/
587  /****                                                                 ****/
588  /****                                                                 ****/
589  /*************************************************************************/
590  /*************************************************************************/
591  /*************************************************************************/
592
593  static const FT_ServiceDescRec  cff_services[] =
594  {
595    { FT_SERVICE_ID_XF86_NAME,            FT_XF86_FORMAT_CFF },
596    { FT_SERVICE_ID_POSTSCRIPT_INFO,      &cff_service_ps_info },
597    { FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &cff_service_ps_name },
598#ifndef FT_CONFIG_OPTION_NO_GLYPH_NAMES
599    { FT_SERVICE_ID_GLYPH_DICT,           &cff_service_glyph_dict },
600#endif
601    { FT_SERVICE_ID_TT_CMAP,              &cff_service_get_cmap_info },
602    { FT_SERVICE_ID_CID,                  &cff_service_cid_info },
603    { NULL, NULL }
604  };
605
606
607  FT_CALLBACK_DEF( FT_Module_Interface )
608  cff_get_interface( FT_Module    driver,       /* CFF_Driver */
609                     const char*  module_interface )
610  {
611    FT_Module            sfnt;
612    FT_Module_Interface  result;
613
614
615    result = ft_service_list_lookup( cff_services, module_interface );
616    if ( result != NULL )
617      return  result;
618
619    /* we pass our request to the `sfnt' module */
620    sfnt = FT_Get_Module( driver->library, "sfnt" );
621
622    return sfnt ? sfnt->clazz->get_interface( sfnt, module_interface ) : 0;
623  }
624
625
626  /* The FT_DriverInterface structure is defined in ftdriver.h. */
627
628  FT_CALLBACK_TABLE_DEF
629  const FT_Driver_ClassRec  cff_driver_class =
630  {
631    /* begin with the FT_Module_Class fields */
632    {
633      FT_MODULE_FONT_DRIVER       |
634      FT_MODULE_DRIVER_SCALABLE   |
635      FT_MODULE_DRIVER_HAS_HINTER,
636
637      sizeof( CFF_DriverRec ),
638      "cff",
639      0x10000L,
640      0x20000L,
641
642      0,   /* module-specific interface */
643
644      cff_driver_init,
645      cff_driver_done,
646      cff_get_interface,
647    },
648
649    /* now the specific driver fields */
650    sizeof( TT_FaceRec ),
651    sizeof( CFF_SizeRec ),
652    sizeof( CFF_GlyphSlotRec ),
653
654    cff_face_init,
655    cff_face_done,
656    cff_size_init,
657    cff_size_done,
658    cff_slot_init,
659    cff_slot_done,
660
661#ifdef FT_CONFIG_OPTION_OLD_INTERNALS
662    ft_stub_set_char_sizes,
663    ft_stub_set_pixel_sizes,
664#endif
665
666    Load_Glyph,
667
668    cff_get_kerning,
669    0,                      /* FT_Face_AttachFunc      */
670    cff_get_advances,       /* FT_Face_GetAdvancesFunc */
671
672    cff_size_request,
673
674#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
675    cff_size_select
676#else
677    0                       /* FT_Size_SelectFunc      */
678#endif
679  };
680
681
682/* END */
683