• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 )
cff_get_kerning(FT_Face ttface,FT_UInt left_glyph,FT_UInt right_glyph,FT_Vector * kerning)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 )
Load_Glyph(FT_GlyphSlot cffslot,FT_Size cffsize,FT_UInt glyph_index,FT_Int32 load_flags)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 )
cff_get_advances(FT_Face face,FT_UInt start,FT_UInt count,FT_Int32 flags,FT_Fixed * advances)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
cff_get_glyph_name(CFF_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)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
cff_get_name_index(CFF_Face face,FT_String * glyph_name)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
cff_ps_has_glyph_names(FT_Face face)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
cff_ps_get_font_info(CFF_Face face,PS_FontInfoRec * afont_info)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*
cff_get_ps_name(CFF_Face face)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
cff_get_cmap_info(FT_CharMap charmap,TT_CMapInfo * cmap_info)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
cff_get_ros(CFF_Face face,const char ** registry,const char ** ordering,FT_Int * supplement)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
cff_get_is_cid(CFF_Face face,FT_Bool * is_cid)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
cff_get_cid_from_glyph_index(CFF_Face face,FT_UInt glyph_index,FT_UInt * cid)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 )
cff_get_interface(FT_Module driver,const char * 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