Home | History | Annotate | Download | only in sfnt
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  sfdriver.c                                                             */
      4 /*                                                                         */
      5 /*    High-level SFNT driver interface (body).                             */
      6 /*                                                                         */
      7 /*  Copyright 1996-2015 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   /*                                                                       */
     56   /* The macro FT_COMPONENT is used in trace mode.  It is an implicit      */
     57   /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log  */
     58   /* messages during execution.                                            */
     59   /*                                                                       */
     60 #undef  FT_COMPONENT
     61 #define FT_COMPONENT  trace_sfdriver
     62 
     63 
     64   /*
     65    *  SFNT TABLE SERVICE
     66    *
     67    */
     68 
     69   static void*
     70   get_sfnt_table( TT_Face      face,
     71                   FT_Sfnt_Tag  tag )
     72   {
     73     void*  table;
     74 
     75 
     76     switch ( tag )
     77     {
     78     case FT_SFNT_HEAD:
     79       table = &face->header;
     80       break;
     81 
     82     case FT_SFNT_HHEA:
     83       table = &face->horizontal;
     84       break;
     85 
     86     case FT_SFNT_VHEA:
     87       table = face->vertical_info ? &face->vertical : NULL;
     88       break;
     89 
     90     case FT_SFNT_OS2:
     91       table = face->os2.version == 0xFFFFU ? NULL : &face->os2;
     92       break;
     93 
     94     case FT_SFNT_POST:
     95       table = &face->postscript;
     96       break;
     97 
     98     case FT_SFNT_MAXP:
     99       table = &face->max_profile;
    100       break;
    101 
    102     case FT_SFNT_PCLT:
    103       table = face->pclt.Version ? &face->pclt : NULL;
    104       break;
    105 
    106     default:
    107       table = NULL;
    108     }
    109 
    110     return table;
    111   }
    112 
    113 
    114   static FT_Error
    115   sfnt_table_info( TT_Face    face,
    116                    FT_UInt    idx,
    117                    FT_ULong  *tag,
    118                    FT_ULong  *offset,
    119                    FT_ULong  *length )
    120   {
    121     if ( !offset || !length )
    122       return FT_THROW( Invalid_Argument );
    123 
    124     if ( !tag )
    125       *length = face->num_tables;
    126     else
    127     {
    128       if ( idx >= face->num_tables )
    129         return FT_THROW( Table_Missing );
    130 
    131       *tag    = face->dir_tables[idx].Tag;
    132       *offset = face->dir_tables[idx].Offset;
    133       *length = face->dir_tables[idx].Length;
    134     }
    135 
    136     return FT_Err_Ok;
    137   }
    138 
    139 
    140   FT_DEFINE_SERVICE_SFNT_TABLEREC(
    141     sfnt_service_sfnt_table,
    142     (FT_SFNT_TableLoadFunc)tt_face_load_any,
    143     (FT_SFNT_TableGetFunc) get_sfnt_table,
    144     (FT_SFNT_TableInfoFunc)sfnt_table_info )
    145 
    146 
    147 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    148 
    149   /*
    150    *  GLYPH DICT SERVICE
    151    *
    152    */
    153 
    154   static FT_Error
    155   sfnt_get_glyph_name( TT_Face     face,
    156                        FT_UInt     glyph_index,
    157                        FT_Pointer  buffer,
    158                        FT_UInt     buffer_max )
    159   {
    160     FT_String*  gname;
    161     FT_Error    error;
    162 
    163 
    164     error = tt_face_get_ps_name( face, glyph_index, &gname );
    165     if ( !error )
    166       FT_STRCPYN( buffer, gname, buffer_max );
    167 
    168     return error;
    169   }
    170 
    171 
    172   static FT_UInt
    173   sfnt_get_name_index( TT_Face     face,
    174                        FT_String*  glyph_name )
    175   {
    176     FT_Face  root = &face->root;
    177 
    178     FT_UInt  i, max_gid = FT_UINT_MAX;
    179 
    180 
    181     if ( root->num_glyphs < 0 )
    182       return 0;
    183     else if ( (FT_ULong)root->num_glyphs < FT_UINT_MAX )
    184       max_gid = (FT_UInt)root->num_glyphs;
    185     else
    186       FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n",
    187                   FT_UINT_MAX, root->num_glyphs ));
    188 
    189     for ( i = 0; i < max_gid; i++ )
    190     {
    191       FT_String*  gname;
    192       FT_Error    error = tt_face_get_ps_name( face, i, &gname );
    193 
    194 
    195       if ( error )
    196         continue;
    197 
    198       if ( !ft_strcmp( glyph_name, gname ) )
    199         return i;
    200     }
    201 
    202     return 0;
    203   }
    204 
    205 
    206   FT_DEFINE_SERVICE_GLYPHDICTREC(
    207     sfnt_service_glyph_dict,
    208     (FT_GlyphDict_GetNameFunc)  sfnt_get_glyph_name,
    209     (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index )
    210 
    211 
    212 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
    213 
    214 
    215   /*
    216    *  POSTSCRIPT NAME SERVICE
    217    *
    218    */
    219 
    220   static const char*
    221   sfnt_get_ps_name( TT_Face  face )
    222   {
    223     FT_Int       n, found_win, found_apple;
    224     const char*  result = NULL;
    225 
    226 
    227     /* shouldn't happen, but just in case to avoid memory leaks */
    228     if ( face->postscript_name )
    229       return face->postscript_name;
    230 
    231     /* scan the name table to see whether we have a Postscript name here, */
    232     /* either in Macintosh or Windows platform encodings                  */
    233     found_win   = -1;
    234     found_apple = -1;
    235 
    236     for ( n = 0; n < face->num_names; n++ )
    237     {
    238       TT_NameEntryRec*  name = face->name_table.names + n;
    239 
    240 
    241       if ( name->nameID == 6 && name->stringLength > 0 )
    242       {
    243         if ( name->platformID == 3     &&
    244              name->encodingID == 1     &&
    245              name->languageID == 0x409 )
    246           found_win = n;
    247 
    248         if ( name->platformID == 1 &&
    249              name->encodingID == 0 &&
    250              name->languageID == 0 )
    251           found_apple = n;
    252       }
    253     }
    254 
    255     if ( found_win != -1 )
    256     {
    257       FT_Memory         memory = face->root.memory;
    258       TT_NameEntryRec*  name   = face->name_table.names + found_win;
    259       FT_UInt           len    = name->stringLength / 2;
    260       FT_Error          error  = FT_Err_Ok;
    261 
    262       FT_UNUSED( error );
    263 
    264 
    265       if ( !FT_ALLOC( result, name->stringLength + 1 ) )
    266       {
    267         FT_Stream   stream = face->name_table.stream;
    268         FT_String*  r      = (FT_String*)result;
    269         FT_Char*    p;
    270 
    271 
    272         if ( FT_STREAM_SEEK( name->stringOffset ) ||
    273              FT_FRAME_ENTER( name->stringLength ) )
    274         {
    275           FT_FREE( result );
    276           name->stringLength = 0;
    277           name->stringOffset = 0;
    278           FT_FREE( name->string );
    279 
    280           goto Exit;
    281         }
    282 
    283         p = (FT_Char*)stream->cursor;
    284 
    285         for ( ; len > 0; len--, p += 2 )
    286         {
    287           if ( p[0] == 0 && p[1] >= 32 )
    288             *r++ = p[1];
    289         }
    290         *r = '\0';
    291 
    292         FT_FRAME_EXIT();
    293       }
    294       goto Exit;
    295     }
    296 
    297     if ( found_apple != -1 )
    298     {
    299       FT_Memory         memory = face->root.memory;
    300       TT_NameEntryRec*  name   = face->name_table.names + found_apple;
    301       FT_UInt           len    = name->stringLength;
    302       FT_Error          error  = FT_Err_Ok;
    303 
    304       FT_UNUSED( error );
    305 
    306 
    307       if ( !FT_ALLOC( result, len + 1 ) )
    308       {
    309         FT_Stream  stream = face->name_table.stream;
    310 
    311 
    312         if ( FT_STREAM_SEEK( name->stringOffset ) ||
    313              FT_STREAM_READ( result, len )        )
    314         {
    315           name->stringOffset = 0;
    316           name->stringLength = 0;
    317           FT_FREE( name->string );
    318           FT_FREE( result );
    319           goto Exit;
    320         }
    321         ((char*)result)[len] = '\0';
    322       }
    323     }
    324 
    325   Exit:
    326     face->postscript_name = result;
    327     return result;
    328   }
    329 
    330 
    331   FT_DEFINE_SERVICE_PSFONTNAMEREC(
    332     sfnt_service_ps_name,
    333     (FT_PsName_GetFunc)sfnt_get_ps_name )
    334 
    335 
    336   /*
    337    *  TT CMAP INFO
    338    */
    339   FT_DEFINE_SERVICE_TTCMAPSREC(
    340     tt_service_get_cmap_info,
    341     (TT_CMap_Info_GetFunc)tt_get_cmap_info )
    342 
    343 
    344 #ifdef TT_CONFIG_OPTION_BDF
    345 
    346   static FT_Error
    347   sfnt_get_charset_id( TT_Face       face,
    348                        const char*  *acharset_encoding,
    349                        const char*  *acharset_registry )
    350   {
    351     BDF_PropertyRec  encoding, registry;
    352     FT_Error         error;
    353 
    354 
    355     /* XXX: I don't know whether this is correct, since
    356      *      tt_face_find_bdf_prop only returns something correct if we have
    357      *      previously selected a size that is listed in the BDF table.
    358      *      Should we change the BDF table format to include single offsets
    359      *      for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
    360      */
    361     error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", &registry );
    362     if ( !error )
    363     {
    364       error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
    365       if ( !error )
    366       {
    367         if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
    368              encoding.type == BDF_PROPERTY_TYPE_ATOM )
    369         {
    370           *acharset_encoding = encoding.u.atom;
    371           *acharset_registry = registry.u.atom;
    372         }
    373         else
    374           error = FT_THROW( Invalid_Argument );
    375       }
    376     }
    377 
    378     return error;
    379   }
    380 
    381 
    382   FT_DEFINE_SERVICE_BDFRec(
    383     sfnt_service_bdf,
    384     (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,
    385     (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop )
    386 
    387 
    388 #endif /* TT_CONFIG_OPTION_BDF */
    389 
    390 
    391   /*
    392    *  SERVICE LIST
    393    */
    394 
    395 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
    396   FT_DEFINE_SERVICEDESCREC5(
    397     sfnt_services,
    398     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
    399     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
    400     FT_SERVICE_ID_GLYPH_DICT,           &SFNT_SERVICE_GLYPH_DICT_GET,
    401     FT_SERVICE_ID_BDF,                  &SFNT_SERVICE_BDF_GET,
    402     FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
    403 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    404   FT_DEFINE_SERVICEDESCREC4(
    405     sfnt_services,
    406     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
    407     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
    408     FT_SERVICE_ID_GLYPH_DICT,           &SFNT_SERVICE_GLYPH_DICT_GET,
    409     FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
    410 #elif defined TT_CONFIG_OPTION_BDF
    411   FT_DEFINE_SERVICEDESCREC4(
    412     sfnt_services,
    413     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
    414     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
    415     FT_SERVICE_ID_BDF,                  &SFNT_SERVICE_BDF_GET,
    416     FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
    417 #else
    418   FT_DEFINE_SERVICEDESCREC3(
    419     sfnt_services,
    420     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
    421     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
    422     FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
    423 #endif
    424 
    425 
    426   FT_CALLBACK_DEF( FT_Module_Interface )
    427   sfnt_get_interface( FT_Module    module,
    428                       const char*  module_interface )
    429   {
    430     /* SFNT_SERVICES_GET dereferences `library' in PIC mode */
    431 #ifdef FT_CONFIG_OPTION_PIC
    432     FT_Library  library;
    433 
    434 
    435     if ( !module )
    436       return NULL;
    437     library = module->library;
    438     if ( !library )
    439       return NULL;
    440 #else
    441     FT_UNUSED( module );
    442 #endif
    443 
    444     return ft_service_list_lookup( SFNT_SERVICES_GET, module_interface );
    445   }
    446 
    447 
    448 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    449 #define PUT_EMBEDDED_BITMAPS( a )  a
    450 #else
    451 #define PUT_EMBEDDED_BITMAPS( a )  NULL
    452 #endif
    453 
    454 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    455 #define PUT_PS_NAMES( a )  a
    456 #else
    457 #define PUT_PS_NAMES( a )  NULL
    458 #endif
    459 
    460   FT_DEFINE_SFNT_INTERFACE(
    461     sfnt_interface,
    462     tt_face_goto_table,
    463 
    464     sfnt_init_face,
    465     sfnt_load_face,
    466     sfnt_done_face,
    467     sfnt_get_interface,
    468 
    469     tt_face_load_any,
    470 
    471     tt_face_load_head,
    472     tt_face_load_hhea,
    473     tt_face_load_cmap,
    474     tt_face_load_maxp,
    475     tt_face_load_os2,
    476     tt_face_load_post,
    477 
    478     tt_face_load_name,
    479     tt_face_free_name,
    480 
    481     tt_face_load_kern,
    482     tt_face_load_gasp,
    483     tt_face_load_pclt,
    484 
    485     /* see `ttload.h' */
    486     PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ),
    487 
    488     PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ),
    489 
    490     /* see `ttpost.h' */
    491     PUT_PS_NAMES( tt_face_get_ps_name   ),
    492     PUT_PS_NAMES( tt_face_free_ps_names ),
    493 
    494     /* since version 2.1.8 */
    495     tt_face_get_kerning,
    496 
    497     /* since version 2.2 */
    498     tt_face_load_font_dir,
    499     tt_face_load_hmtx,
    500 
    501     /* see `ttsbit.h' and `sfnt.h' */
    502     PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
    503     PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
    504 
    505     PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike     ),
    506     PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
    507 
    508     tt_face_get_metrics
    509   )
    510 
    511 
    512   FT_DEFINE_MODULE(
    513     sfnt_module_class,
    514 
    515     0,  /* not a font driver or renderer */
    516     sizeof ( FT_ModuleRec ),
    517 
    518     "sfnt",     /* driver name                            */
    519     0x10000L,   /* driver version 1.0                     */
    520     0x20000L,   /* driver requires FreeType 2.0 or higher */
    521 
    522     (const void*)&SFNT_INTERFACE_GET,  /* module specific interface */
    523 
    524     (FT_Module_Constructor)0,
    525     (FT_Module_Destructor) 0,
    526     (FT_Module_Requester)  sfnt_get_interface )
    527 
    528 
    529 /* END */
    530