Home | History | Annotate | Download | only in sfnt
      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*
     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 = 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 
    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 )
    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 )
    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 )
    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 )
    468   tt_face_free_hdmx_stub( TT_Face  face )
    469   {
    470     FT_UNUSED( face );
    471   }
    472 
    473 
    474   FT_CALLBACK_DEF( FT_Error )
    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 )
    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 )
    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 )
    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 )
    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