1d157b7e9d61b5449d2bf31187505fadd6eaea3a
[platform/framework/web/crosswalk.git] / src / third_party / freetype2 / src / src / sfnt / sfdriver.c
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_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*
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
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
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
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*
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
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 = FT_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
416   FT_CALLBACK_DEF( FT_Module_Interface )
417   sfnt_get_interface( FT_Module    module,
418                       const char*  module_interface )
419   {
420     FT_Library           library = module->library;
421     FT_UNUSED(library);
422     FT_UNUSED( module );
423
424     return ft_service_list_lookup( FT_SFNT_SERVICES_GET, module_interface );
425   }
426
427
428 #ifdef FT_CONFIG_OPTION_OLD_INTERNALS
429
430   FT_CALLBACK_DEF( FT_Error )
431   tt_face_load_sfnt_header_stub( TT_Face      face,
432                                  FT_Stream    stream,
433                                  FT_Long      face_index,
434                                  SFNT_Header  header )
435   {
436     FT_UNUSED( face );
437     FT_UNUSED( stream );
438     FT_UNUSED( face_index );
439     FT_UNUSED( header );
440
441     return FT_Err_Unimplemented_Feature;
442   }
443
444
445   FT_CALLBACK_DEF( FT_Error )
446   tt_face_load_directory_stub( TT_Face      face,
447                                FT_Stream    stream,
448                                SFNT_Header  header )
449   {
450     FT_UNUSED( face );
451     FT_UNUSED( stream );
452     FT_UNUSED( header );
453
454     return FT_Err_Unimplemented_Feature;
455   }
456
457
458   FT_CALLBACK_DEF( FT_Error )
459   tt_face_load_hdmx_stub( TT_Face    face,
460                           FT_Stream  stream )
461   {
462     FT_UNUSED( face );
463     FT_UNUSED( stream );
464
465     return FT_Err_Unimplemented_Feature;
466   }
467
468
469   FT_CALLBACK_DEF( void )
470   tt_face_free_hdmx_stub( TT_Face  face )
471   {
472     FT_UNUSED( face );
473   }
474
475
476   FT_CALLBACK_DEF( FT_Error )
477   tt_face_set_sbit_strike_stub( TT_Face    face,
478                                 FT_UInt    x_ppem,
479                                 FT_UInt    y_ppem,
480                                 FT_ULong*  astrike_index )
481   {
482     /*
483      * We simply forge a FT_Size_Request and call the real function
484      * that does all the work.
485      *
486      * This stub might be called by libXfont in the X.Org Xserver,
487      * compiled against version 2.1.8 or newer.
488      */
489
490     FT_Size_RequestRec  req;
491
492
493     req.type           = FT_SIZE_REQUEST_TYPE_NOMINAL;
494     req.width          = (FT_F26Dot6)x_ppem;
495     req.height         = (FT_F26Dot6)y_ppem;
496     req.horiResolution = 0;
497     req.vertResolution = 0;
498
499     *astrike_index = 0x7FFFFFFFUL;
500
501     return tt_face_set_sbit_strike( face, &req, astrike_index );
502   }
503
504
505   FT_CALLBACK_DEF( FT_Error )
506   tt_face_load_sbit_stub( TT_Face    face,
507                           FT_Stream  stream )
508   {
509     FT_UNUSED( face );
510     FT_UNUSED( stream );
511
512     /*
513      *  This function was originally implemented to load the sbit table.
514      *  However, it has been replaced by `tt_face_load_eblc', and this stub
515      *  is only there for some rogue clients which would want to call it
516      *  directly (which doesn't make much sense).
517      */
518     return FT_Err_Unimplemented_Feature;
519   }
520
521
522   FT_CALLBACK_DEF( void )
523   tt_face_free_sbit_stub( TT_Face  face )
524   {
525     /* nothing to do in this stub */
526     FT_UNUSED( face );
527   }
528
529
530   FT_CALLBACK_DEF( FT_Error )
531   tt_face_load_charmap_stub( TT_Face    face,
532                              void*      cmap,
533                              FT_Stream  input )
534   {
535     FT_UNUSED( face );
536     FT_UNUSED( cmap );
537     FT_UNUSED( input );
538
539     return FT_Err_Unimplemented_Feature;
540   }
541
542
543   FT_CALLBACK_DEF( FT_Error )
544   tt_face_free_charmap_stub( TT_Face  face,
545                              void*    cmap )
546   {
547     FT_UNUSED( face );
548     FT_UNUSED( cmap );
549
550     return 0;
551   }
552
553 #endif /* FT_CONFIG_OPTION_OLD_INTERNALS */
554
555 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
556 #define PUT_EMBEDDED_BITMAPS(a) a 
557 #else
558 #define PUT_EMBEDDED_BITMAPS(a) 0 
559 #endif
560 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
561 #define PUT_PS_NAMES(a) a 
562 #else
563 #define PUT_PS_NAMES(a) 0 
564 #endif
565
566   FT_DEFINE_SFNT_INTERFACE(sfnt_interface,
567     tt_face_goto_table,
568
569     sfnt_init_face,
570     sfnt_load_face,
571     sfnt_done_face,
572     sfnt_get_interface,
573
574     tt_face_load_any,
575
576     tt_face_load_sfnt_header_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
577     tt_face_load_directory_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
578
579     tt_face_load_head,
580     tt_face_load_hhea,
581     tt_face_load_cmap,
582     tt_face_load_maxp,
583     tt_face_load_os2,
584     tt_face_load_post,
585
586     tt_face_load_name,
587     tt_face_free_name,
588
589     tt_face_load_hdmx_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
590     tt_face_free_hdmx_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
591
592     tt_face_load_kern,
593     tt_face_load_gasp,
594     tt_face_load_pclt,
595
596     /* see `ttload.h' */
597     PUT_EMBEDDED_BITMAPS(tt_face_load_bhed),
598
599     tt_face_set_sbit_strike_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
600     tt_face_load_sbit_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
601
602     tt_find_sbit_image, /* FT_CONFIG_OPTION_OLD_INTERNALS */
603     tt_load_sbit_metrics, /* FT_CONFIG_OPTION_OLD_INTERNALS */
604
605     PUT_EMBEDDED_BITMAPS(tt_face_load_sbit_image),
606
607     tt_face_free_sbit_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
608
609     /* see `ttpost.h' */
610     PUT_PS_NAMES(tt_face_get_ps_name),
611     PUT_PS_NAMES(tt_face_free_ps_names),
612
613     tt_face_load_charmap_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
614     tt_face_free_charmap_stub, /* FT_CONFIG_OPTION_OLD_INTERNALS */
615
616     /* since version 2.1.8 */
617
618     tt_face_get_kerning,
619
620     /* since version 2.2 */
621
622     tt_face_load_font_dir,
623     tt_face_load_hmtx,
624
625     /* see `ttsbit.h' and `sfnt.h' */
626     PUT_EMBEDDED_BITMAPS(tt_face_load_eblc),
627     PUT_EMBEDDED_BITMAPS(tt_face_free_eblc),
628
629     PUT_EMBEDDED_BITMAPS(tt_face_set_sbit_strike),
630     PUT_EMBEDDED_BITMAPS(tt_face_load_strike_metrics),
631
632     tt_face_get_metrics
633   )
634
635
636   FT_DEFINE_MODULE(sfnt_module_class,
637   
638     0,  /* not a font driver or renderer */
639     sizeof( FT_ModuleRec ),
640
641     "sfnt",     /* driver name                            */
642     0x10000L,   /* driver version 1.0                     */
643     0x20000L,   /* driver requires FreeType 2.0 or higher */
644
645     (const void*)&FT_SFNT_INTERFACE_GET,  /* module specific interface */
646
647     (FT_Module_Constructor)0,
648     (FT_Module_Destructor) 0,
649     (FT_Module_Requester)  sfnt_get_interface
650   )
651
652
653 /* END */