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