• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /***************************************************************************/
2 /*                                                                         */
3 /*  sfdriver.c                                                             */
4 /*                                                                         */
5 /*    High-level SFNT driver interface (body).                             */
6 /*                                                                         */
7 /*  Copyright 1996-2001, 2002, 2003, 2004, 2005, 2006, 2007, 2009, 2010 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_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_SFNT_H
22 #include FT_INTERNAL_OBJECTS_H
23 
24 #include "sfdriver.h"
25 #include "ttload.h"
26 #include "sfobjs.h"
27 #include "sfntpic.h"
28 
29 #include "sferrors.h"
30 
31 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
32 #include "ttsbit.h"
33 #endif
34 
35 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
36 #include "ttpost.h"
37 #endif
38 
39 #ifdef TT_CONFIG_OPTION_BDF
40 #include "ttbdf.h"
41 #include FT_SERVICE_BDF_H
42 #endif
43 
44 #include "ttcmap.h"
45 #include "ttkern.h"
46 #include "ttmtx.h"
47 
48 #include FT_SERVICE_GLYPH_DICT_H
49 #include FT_SERVICE_POSTSCRIPT_NAME_H
50 #include FT_SERVICE_SFNT_H
51 #include FT_SERVICE_TT_CMAP_H
52 
53   /*************************************************************************/
54   /*                                                                       */
55   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
56   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
57   /* messages during execution.                                            */
58   /*                                                                       */
59 #undef  FT_COMPONENT
60 #define FT_COMPONENT  trace_sfdriver
61 
62 
63  /*
64   *  SFNT TABLE SERVICE
65   *
66   */
67 
68   static void*
get_sfnt_table(TT_Face face,FT_Sfnt_Tag tag)69   get_sfnt_table( TT_Face      face,
70                   FT_Sfnt_Tag  tag )
71   {
72     void*  table;
73 
74 
75     switch ( tag )
76     {
77     case ft_sfnt_head:
78       table = &face->header;
79       break;
80 
81     case ft_sfnt_hhea:
82       table = &face->horizontal;
83       break;
84 
85     case ft_sfnt_vhea:
86       table = face->vertical_info ? &face->vertical : 0;
87       break;
88 
89     case ft_sfnt_os2:
90       table = face->os2.version == 0xFFFFU ? 0 : &face->os2;
91       break;
92 
93     case ft_sfnt_post:
94       table = &face->postscript;
95       break;
96 
97     case ft_sfnt_maxp:
98       table = &face->max_profile;
99       break;
100 
101     case ft_sfnt_pclt:
102       table = face->pclt.Version ? &face->pclt : 0;
103       break;
104 
105     default:
106       table = 0;
107     }
108 
109     return table;
110   }
111 
112 
113   static FT_Error
sfnt_table_info(TT_Face face,FT_UInt idx,FT_ULong * tag,FT_ULong * offset,FT_ULong * length)114   sfnt_table_info( TT_Face    face,
115                    FT_UInt    idx,
116                    FT_ULong  *tag,
117                    FT_ULong  *offset,
118                    FT_ULong  *length )
119   {
120     if ( !tag || !offset || !length )
121       return SFNT_Err_Invalid_Argument;
122 
123     if ( idx >= face->num_tables )
124       return SFNT_Err_Table_Missing;
125 
126     *tag    = face->dir_tables[idx].Tag;
127     *offset = face->dir_tables[idx].Offset;
128     *length = face->dir_tables[idx].Length;
129 
130     return SFNT_Err_Ok;
131   }
132 
133 
134   FT_DEFINE_SERVICE_SFNT_TABLEREC(sfnt_service_sfnt_table,
135     (FT_SFNT_TableLoadFunc)tt_face_load_any,
136     (FT_SFNT_TableGetFunc) get_sfnt_table,
137     (FT_SFNT_TableInfoFunc)sfnt_table_info
138   )
139 
140 
141 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
142 
143  /*
144   *  GLYPH DICT SERVICE
145   *
146   */
147 
148   static FT_Error
sfnt_get_glyph_name(TT_Face face,FT_UInt glyph_index,FT_Pointer buffer,FT_UInt buffer_max)149   sfnt_get_glyph_name( TT_Face     face,
150                        FT_UInt     glyph_index,
151                        FT_Pointer  buffer,
152                        FT_UInt     buffer_max )
153   {
154     FT_String*  gname;
155     FT_Error    error;
156 
157 
158     error = tt_face_get_ps_name( face, glyph_index, &gname );
159     if ( !error )
160       FT_STRCPYN( buffer, gname, buffer_max );
161 
162     return error;
163   }
164 
165 
166   static FT_UInt
sfnt_get_name_index(TT_Face face,FT_String * glyph_name)167   sfnt_get_name_index( TT_Face     face,
168                        FT_String*  glyph_name )
169   {
170     FT_Face   root = &face->root;
171     FT_UInt   i, max_gid = FT_UINT_MAX;
172 
173 
174     if ( root->num_glyphs < 0 )
175       return 0;
176     else if ( ( FT_ULong ) root->num_glyphs < FT_UINT_MAX )
177       max_gid = ( FT_UInt ) root->num_glyphs;
178     else
179       FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n",
180          FT_UINT_MAX, root->num_glyphs ));
181 
182     for ( i = 0; i < max_gid; i++ )
183     {
184       FT_String*  gname;
185       FT_Error    error = tt_face_get_ps_name( face, i, &gname );
186 
187 
188       if ( error )
189         continue;
190 
191       if ( !ft_strcmp( glyph_name, gname ) )
192         return i;
193     }
194 
195     return 0;
196   }
197 
198 
199   FT_DEFINE_SERVICE_GLYPHDICTREC(sfnt_service_glyph_dict,
200     (FT_GlyphDict_GetNameFunc)  sfnt_get_glyph_name,
201     (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index
202   )
203 
204 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
205 
206 
207  /*
208   *  POSTSCRIPT NAME SERVICE
209   *
210   */
211 
212   static const char*
sfnt_get_ps_name(TT_Face face)213   sfnt_get_ps_name( TT_Face  face )
214   {
215     FT_Int       n, found_win, found_apple;
216     const char*  result = NULL;
217 
218 
219     /* shouldn't happen, but just in case to avoid memory leaks */
220     if ( face->postscript_name )
221       return face->postscript_name;
222 
223     /* scan the name table to see whether we have a Postscript name here, */
224     /* either in Macintosh or Windows platform encodings                  */
225     found_win   = -1;
226     found_apple = -1;
227 
228     for ( n = 0; n < face->num_names; n++ )
229     {
230       TT_NameEntryRec*  name = face->name_table.names + n;
231 
232 
233       if ( name->nameID == 6 && name->stringLength > 0 )
234       {
235         if ( name->platformID == 3     &&
236              name->encodingID == 1     &&
237              name->languageID == 0x409 )
238           found_win = n;
239 
240         if ( name->platformID == 1 &&
241              name->encodingID == 0 &&
242              name->languageID == 0 )
243           found_apple = n;
244       }
245     }
246 
247     if ( found_win != -1 )
248     {
249       FT_Memory         memory = face->root.memory;
250       TT_NameEntryRec*  name   = face->name_table.names + found_win;
251       FT_UInt           len    = name->stringLength / 2;
252       FT_Error          error  = SFNT_Err_Ok;
253 
254       FT_UNUSED( error );
255 
256 
257       if ( !FT_ALLOC( result, name->stringLength + 1 ) )
258       {
259         FT_Stream   stream = face->name_table.stream;
260         FT_String*  r      = (FT_String*)result;
261         FT_Byte*    p      = (FT_Byte*)name->string;
262 
263 
264         if ( FT_STREAM_SEEK( name->stringOffset ) ||
265              FT_FRAME_ENTER( name->stringLength ) )
266         {
267           FT_FREE( result );
268           name->stringLength = 0;
269           name->stringOffset = 0;
270           FT_FREE( name->string );
271 
272           goto Exit;
273         }
274 
275         p = (FT_Byte*)stream->cursor;
276 
277         for ( ; len > 0; len--, p += 2 )
278         {
279           if ( p[0] == 0 && p[1] >= 32 && p[1] < 128 )
280             *r++ = p[1];
281         }
282         *r = '\0';
283 
284         FT_FRAME_EXIT();
285       }
286       goto Exit;
287     }
288 
289     if ( found_apple != -1 )
290     {
291       FT_Memory         memory = face->root.memory;
292       TT_NameEntryRec*  name   = face->name_table.names + found_apple;
293       FT_UInt           len    = name->stringLength;
294       FT_Error          error  = SFNT_Err_Ok;
295 
296       FT_UNUSED( error );
297 
298 
299       if ( !FT_ALLOC( result, len + 1 ) )
300       {
301         FT_Stream  stream = face->name_table.stream;
302 
303 
304         if ( FT_STREAM_SEEK( name->stringOffset ) ||
305              FT_STREAM_READ( result, len )        )
306         {
307           name->stringOffset = 0;
308           name->stringLength = 0;
309           FT_FREE( name->string );
310           FT_FREE( result );
311           goto Exit;
312         }
313         ((char*)result)[len] = '\0';
314       }
315     }
316 
317   Exit:
318     face->postscript_name = result;
319     return result;
320   }
321 
322   FT_DEFINE_SERVICE_PSFONTNAMEREC(sfnt_service_ps_name,
323     (FT_PsName_GetFunc)sfnt_get_ps_name
324   )
325 
326 
327   /*
328    *  TT CMAP INFO
329    */
330   FT_DEFINE_SERVICE_TTCMAPSREC(tt_service_get_cmap_info,
331     (TT_CMap_Info_GetFunc)tt_get_cmap_info
332   )
333 
334 
335 #ifdef TT_CONFIG_OPTION_BDF
336 
337   static FT_Error
sfnt_get_charset_id(TT_Face face,const char ** acharset_encoding,const char ** acharset_registry)338   sfnt_get_charset_id( TT_Face       face,
339                        const char*  *acharset_encoding,
340                        const char*  *acharset_registry )
341   {
342     BDF_PropertyRec  encoding, registry;
343     FT_Error         error;
344 
345 
346     /* XXX: I don't know whether this is correct, since
347      *      tt_face_find_bdf_prop only returns something correct if we have
348      *      previously selected a size that is listed in the BDF table.
349      *      Should we change the BDF table format to include single offsets
350      *      for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
351      */
352     error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", &registry );
353     if ( !error )
354     {
355       error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
356       if ( !error )
357       {
358         if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
359              encoding.type == BDF_PROPERTY_TYPE_ATOM )
360         {
361           *acharset_encoding = encoding.u.atom;
362           *acharset_registry = registry.u.atom;
363         }
364         else
365           error = SFNT_Err_Invalid_Argument;
366       }
367     }
368 
369     return error;
370   }
371 
372 
373   FT_DEFINE_SERVICE_BDFRec(sfnt_service_bdf,
374     (FT_BDF_GetCharsetIdFunc) sfnt_get_charset_id,
375     (FT_BDF_GetPropertyFunc)  tt_face_find_bdf_prop
376   )
377 
378 #endif /* TT_CONFIG_OPTION_BDF */
379 
380 
381   /*
382    *  SERVICE LIST
383    */
384 
385 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
386   FT_DEFINE_SERVICEDESCREC5(sfnt_services,
387     FT_SERVICE_ID_SFNT_TABLE,           &FT_SFNT_SERVICE_SFNT_TABLE_GET,
388     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,
389     FT_SERVICE_ID_GLYPH_DICT,           &FT_SFNT_SERVICE_GLYPH_DICT_GET,
390     FT_SERVICE_ID_BDF,                  &FT_SFNT_SERVICE_BDF_GET,
391     FT_SERVICE_ID_TT_CMAP,              &FT_TT_SERVICE_GET_CMAP_INFO_GET
392   )
393 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
394   FT_DEFINE_SERVICEDESCREC4(sfnt_services,
395     FT_SERVICE_ID_SFNT_TABLE,           &FT_SFNT_SERVICE_SFNT_TABLE_GET,
396     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,
397     FT_SERVICE_ID_GLYPH_DICT,           &FT_SFNT_SERVICE_GLYPH_DICT_GET,
398     FT_SERVICE_ID_TT_CMAP,              &FT_TT_SERVICE_GET_CMAP_INFO_GET
399   )
400 #elif defined TT_CONFIG_OPTION_BDF
401   FT_DEFINE_SERVICEDESCREC4(sfnt_services,
402     FT_SERVICE_ID_SFNT_TABLE,           &FT_SFNT_SERVICE_SFNT_TABLE_GET,
403     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,
404     FT_SERVICE_ID_BDF,                  &FT_SFNT_SERVICE_BDF_GET,
405     FT_SERVICE_ID_TT_CMAP,              &FT_TT_SERVICE_GET_CMAP_INFO_GET
406   )
407 #else
408   FT_DEFINE_SERVICEDESCREC3(sfnt_services,
409     FT_SERVICE_ID_SFNT_TABLE,           &FT_SFNT_SERVICE_SFNT_TABLE_GET,
410     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &FT_SFNT_SERVICE_PS_NAME_GET,
411     FT_SERVICE_ID_TT_CMAP,              &FT_TT_SERVICE_GET_CMAP_INFO_GET
412   )
413 #endif
414 
415 
FT_CALLBACK_DEF(FT_Module_Interface)416   FT_CALLBACK_DEF( FT_Module_Interface )
417   sfnt_get_interface( FT_Module    module,
418                       const char*  module_interface )
419   {
420     FT_UNUSED( module );
421 
422     return ft_service_list_lookup( FT_SFNT_SERVICES_GET, module_interface );
423   }
424 
425 
426 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
427 
428   FT_CALLBACK_DEF( FT_Error )
tt_face_load_sfnt_header_stub(TT_Face face,FT_Stream stream,FT_Long face_index,SFNT_Header header)429   tt_face_load_sfnt_header_stub( TT_Face      face,
430                                  FT_Stream    stream,
431                                  FT_Long      face_index,
432                                  SFNT_Header  header )
433   {
434     FT_UNUSED( face );
435     FT_UNUSED( stream );
436     FT_UNUSED( face_index );
437     FT_UNUSED( header );
438 
439     return SFNT_Err_Unimplemented_Feature;
440   }
441 
442 
443   FT_CALLBACK_DEF( FT_Error )
tt_face_load_directory_stub(TT_Face face,FT_Stream stream,SFNT_Header header)444   tt_face_load_directory_stub( TT_Face      face,
445                                FT_Stream    stream,
446                                SFNT_Header  header )
447   {
448     FT_UNUSED( face );
449     FT_UNUSED( stream );
450     FT_UNUSED( header );
451 
452     return SFNT_Err_Unimplemented_Feature;
453   }
454 
455 
456   FT_CALLBACK_DEF( FT_Error )
tt_face_load_hdmx_stub(TT_Face face,FT_Stream stream)457   tt_face_load_hdmx_stub( TT_Face    face,
458                           FT_Stream  stream )
459   {
460     FT_UNUSED( face );
461     FT_UNUSED( stream );
462 
463     return SFNT_Err_Unimplemented_Feature;
464   }
465 
466 
467   FT_CALLBACK_DEF( void )
tt_face_free_hdmx_stub(TT_Face face)468   tt_face_free_hdmx_stub( TT_Face  face )
469   {
470     FT_UNUSED( face );
471   }
472 
473 
474   FT_CALLBACK_DEF( FT_Error )
tt_face_set_sbit_strike_stub(TT_Face face,FT_UInt x_ppem,FT_UInt y_ppem,FT_ULong * astrike_index)475   tt_face_set_sbit_strike_stub( TT_Face    face,
476                                 FT_UInt    x_ppem,
477                                 FT_UInt    y_ppem,
478                                 FT_ULong*  astrike_index )
479   {
480     /*
481      * We simply forge a FT_Size_Request and call the real function
482      * that does all the work.
483      *
484      * This stub might be called by libXfont in the X.Org Xserver,
485      * compiled against version 2.1.8 or newer.
486      */
487 
488     FT_Size_RequestRec  req;
489 
490 
491     req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
492     req.width          = (FT_F26Dot6)x_ppem;
493     req.height         = (FT_F26Dot6)y_ppem;
494     req.horiResolution = 0;
495     req.vertResolution = 0;
496 
497     *astrike_index = 0x7FFFFFFFUL;
498 
499     return tt_face_set_sbit_strike( face, &req, astrike_index );
500   }
501 
502 
503   FT_CALLBACK_DEF( FT_Error )
tt_face_load_sbit_stub(TT_Face face,FT_Stream stream)504   tt_face_load_sbit_stub( TT_Face    face,
505                           FT_Stream  stream )
506   {
507     FT_UNUSED( face );
508     FT_UNUSED( stream );
509 
510     /*
511      *  This function was originally implemented to load the sbit table.
512      *  However, it has been replaced by `tt_face_load_eblc', and this stub
513      *  is only there for some rogue clients which would want to call it
514      *  directly (which doesn't make much sense).
515      */
516     return SFNT_Err_Unimplemented_Feature;
517   }
518 
519 
520   FT_CALLBACK_DEF( void )
tt_face_free_sbit_stub(TT_Face face)521   tt_face_free_sbit_stub( TT_Face  face )
522   {
523     /* nothing to do in this stub */
524     FT_UNUSED( face );
525   }
526 
527 
528   FT_CALLBACK_DEF( FT_Error )
tt_face_load_charmap_stub(TT_Face face,void * cmap,FT_Stream input)529   tt_face_load_charmap_stub( TT_Face    face,
530                              void*      cmap,
531                              FT_Stream  input )
532   {
533     FT_UNUSED( face );
534     FT_UNUSED( cmap );
535     FT_UNUSED( input );
536 
537     return SFNT_Err_Unimplemented_Feature;
538   }
539 
540 
541   FT_CALLBACK_DEF( FT_Error )
tt_face_free_charmap_stub(TT_Face face,void * cmap)542   tt_face_free_charmap_stub( TT_Face  face,
543                              void*    cmap )
544   {
545     FT_UNUSED( face );
546     FT_UNUSED( cmap );
547 
548     return SFNT_Err_Ok;
549   }
550 
551 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
552 
553 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
554 #define PUT_EMBEDDED_BITMAPS(a) a
555 #else
556 #define PUT_EMBEDDED_BITMAPS(a) 0
557 #endif
558 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
559 #define PUT_PS_NAMES(a) a
560 #else
561 #define PUT_PS_NAMES(a) 0
562 #endif
563 
564   FT_DEFINE_SFNT_INTERFACE(sfnt_interface,
565     tt_face_goto_table,
566 
567     sfnt_init_face,
568     sfnt_load_face,
569     sfnt_done_face,
570     sfnt_get_interface,
571 
572     tt_face_load_any,
573 
574     tt_face_load_sfnt_header_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
575     tt_face_load_directory_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
576 
577     tt_face_load_head,
578     tt_face_load_hhea,
579     tt_face_load_cmap,
580     tt_face_load_maxp,
581     tt_face_load_os2,
582     tt_face_load_post,
583 
584     tt_face_load_name,
585     tt_face_free_name,
586 
587     tt_face_load_hdmx_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
588     tt_face_free_hdmx_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
589 
590     tt_face_load_kern,
591     tt_face_load_gasp,
592     tt_face_load_pclt,
593 
594     /* see `ttload.h' */
595     PUT_EMBEDDED_BITMAPS(tt_face_load_bhed),
596 
597     tt_face_set_sbit_strike_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
598     tt_face_load_sbit_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
599 
600     tt_find_sbit_image, /* FT_CONFIG_OPTION_OLD_INTERNALS */
601     tt_load_sbit_metrics, /* FT_CONFIG_OPTION_OLD_INTERNALS */
602 
603     PUT_EMBEDDED_BITMAPS(tt_face_load_sbit_image),
604 
605     tt_face_free_sbit_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
606 
607     /* see `ttpost.h' */
608     PUT_PS_NAMES(tt_face_get_ps_name),
609     PUT_PS_NAMES(tt_face_free_ps_names),
610 
611     tt_face_load_charmap_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
612     tt_face_free_charmap_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
613 
614     /* since version 2.1.8 */
615 
616     tt_face_get_kerning,
617 
618     /* since version 2.2 */
619 
620     tt_face_load_font_dir,
621     tt_face_load_hmtx,
622 
623     /* see `ttsbit.h' and `sfnt.h' */
624     PUT_EMBEDDED_BITMAPS(tt_face_load_eblc),
625     PUT_EMBEDDED_BITMAPS(tt_face_free_eblc),
626 
627     PUT_EMBEDDED_BITMAPS(tt_face_set_sbit_strike),
628     PUT_EMBEDDED_BITMAPS(tt_face_load_strike_metrics),
629 
630     tt_face_get_metrics
631   )
632 
633 
634   FT_DEFINE_MODULE(sfnt_module_class,
635 
636     0,  /* not a font driver or renderer */
637     sizeof( FT_ModuleRec ),
638 
639     "sfnt",     /* driver name                            */
640     0x10000L,   /* driver version 1.0                     */
641     0x20000L,   /* driver requires FreeType 2.0 or higher */
642 
643     (const void*)&FT_SFNT_INTERFACE_GET,  /* module specific interface */
644 
645     (FT_Module_Constructor)0,
646     (FT_Module_Destructor) 0,
647     (FT_Module_Requester)  sfnt_get_interface
648   )
649 
650 
651 /* END */
652