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