Home | History | Annotate | Download | only in sfnt
      1 /***************************************************************************/
      2 /*                                                                         */
      3 /*  sfdriver.c                                                             */
      4 /*                                                                         */
      5 /*    High-level SFNT driver interface (body).                             */
      6 /*                                                                         */
      7 /*  Copyright 1996-2017 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 
    143     (FT_SFNT_TableLoadFunc)tt_face_load_any,     /* load_table */
    144     (FT_SFNT_TableGetFunc) get_sfnt_table,       /* get_table  */
    145     (FT_SFNT_TableInfoFunc)sfnt_table_info       /* table_info */
    146   )
    147 
    148 
    149 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    150 
    151   /*
    152    *  GLYPH DICT SERVICE
    153    *
    154    */
    155 
    156   static FT_Error
    157   sfnt_get_glyph_name( FT_Face     face,
    158                        FT_UInt     glyph_index,
    159                        FT_Pointer  buffer,
    160                        FT_UInt     buffer_max )
    161   {
    162     FT_String*  gname;
    163     FT_Error    error;
    164 
    165 
    166     error = tt_face_get_ps_name( (TT_Face)face, glyph_index, &gname );
    167     if ( !error )
    168       FT_STRCPYN( buffer, gname, buffer_max );
    169 
    170     return error;
    171   }
    172 
    173 
    174   static FT_UInt
    175   sfnt_get_name_index( FT_Face     face,
    176                        FT_String*  glyph_name )
    177   {
    178     TT_Face  ttface = (TT_Face)face;
    179 
    180     FT_UInt  i, max_gid = FT_UINT_MAX;
    181 
    182 
    183     if ( face->num_glyphs < 0 )
    184       return 0;
    185     else if ( (FT_ULong)face->num_glyphs < FT_UINT_MAX )
    186       max_gid = (FT_UInt)face->num_glyphs;
    187     else
    188       FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n",
    189                   FT_UINT_MAX, face->num_glyphs ));
    190 
    191     for ( i = 0; i < max_gid; i++ )
    192     {
    193       FT_String*  gname;
    194       FT_Error    error = tt_face_get_ps_name( ttface, i, &gname );
    195 
    196 
    197       if ( error )
    198         continue;
    199 
    200       if ( !ft_strcmp( glyph_name, gname ) )
    201         return i;
    202     }
    203 
    204     return 0;
    205   }
    206 
    207 
    208   FT_DEFINE_SERVICE_GLYPHDICTREC(
    209     sfnt_service_glyph_dict,
    210 
    211     (FT_GlyphDict_GetNameFunc)  sfnt_get_glyph_name,    /* get_name   */
    212     (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index     /* name_index */
    213   )
    214 
    215 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
    216 
    217 
    218   /*
    219    *  POSTSCRIPT NAME SERVICE
    220    *
    221    */
    222 
    223   static const char*
    224   sfnt_get_ps_name( TT_Face  face )
    225   {
    226     FT_Int       n, found_win, found_apple;
    227     const char*  result = NULL;
    228 
    229 
    230     /* shouldn't happen, but just in case to avoid memory leaks */
    231     if ( face->postscript_name )
    232       return face->postscript_name;
    233 
    234     /* scan the name table to see whether we have a Postscript name here, */
    235     /* either in Macintosh or Windows platform encodings                  */
    236     found_win   = -1;
    237     found_apple = -1;
    238 
    239     for ( n = 0; n < face->num_names; n++ )
    240     {
    241       TT_Name  name = face->name_table.names + n;
    242 
    243 
    244       if ( name->nameID == 6 && name->stringLength > 0 )
    245       {
    246         /* handling of PID/EID 3/0 and 3/1 is the same */
    247         if ( name->platformID == 3                              &&
    248              ( name->encodingID == 1 || name->encodingID == 0 ) &&
    249              name->languageID == 0x409                          )
    250           found_win = n;
    251 
    252         if ( name->platformID == 1 &&
    253              name->encodingID == 0 &&
    254              name->languageID == 0 )
    255           found_apple = n;
    256       }
    257     }
    258 
    259     if ( found_win != -1 )
    260     {
    261       FT_Memory  memory = face->root.memory;
    262       TT_Name    name   = face->name_table.names + found_win;
    263       FT_UInt    len    = name->stringLength / 2;
    264       FT_Error   error  = FT_Err_Ok;
    265 
    266       FT_UNUSED( error );
    267 
    268 
    269       if ( !FT_ALLOC( result, name->stringLength + 1 ) )
    270       {
    271         FT_Stream   stream = face->name_table.stream;
    272         FT_String*  r      = (FT_String*)result;
    273         FT_Char*    p;
    274 
    275 
    276         if ( FT_STREAM_SEEK( name->stringOffset ) ||
    277              FT_FRAME_ENTER( name->stringLength ) )
    278         {
    279           FT_FREE( result );
    280           name->stringLength = 0;
    281           name->stringOffset = 0;
    282           FT_FREE( name->string );
    283 
    284           goto Exit;
    285         }
    286 
    287         p = (FT_Char*)stream->cursor;
    288 
    289         for ( ; len > 0; len--, p += 2 )
    290         {
    291           if ( p[0] == 0 && p[1] >= 32 )
    292             *r++ = p[1];
    293         }
    294         *r = '\0';
    295 
    296         FT_FRAME_EXIT();
    297       }
    298       goto Exit;
    299     }
    300 
    301     if ( found_apple != -1 )
    302     {
    303       FT_Memory  memory = face->root.memory;
    304       TT_Name    name   = face->name_table.names + found_apple;
    305       FT_UInt    len    = name->stringLength;
    306       FT_Error   error  = FT_Err_Ok;
    307 
    308       FT_UNUSED( error );
    309 
    310 
    311       if ( !FT_ALLOC( result, len + 1 ) )
    312       {
    313         FT_Stream  stream = face->name_table.stream;
    314 
    315 
    316         if ( FT_STREAM_SEEK( name->stringOffset ) ||
    317              FT_STREAM_READ( result, len )        )
    318         {
    319           name->stringOffset = 0;
    320           name->stringLength = 0;
    321           FT_FREE( name->string );
    322           FT_FREE( result );
    323           goto Exit;
    324         }
    325         ((char*)result)[len] = '\0';
    326       }
    327     }
    328 
    329   Exit:
    330     face->postscript_name = result;
    331     return result;
    332   }
    333 
    334 
    335   FT_DEFINE_SERVICE_PSFONTNAMEREC(
    336     sfnt_service_ps_name,
    337 
    338     (FT_PsName_GetFunc)sfnt_get_ps_name       /* get_ps_font_name */
    339   )
    340 
    341 
    342   /*
    343    *  TT CMAP INFO
    344    */
    345   FT_DEFINE_SERVICE_TTCMAPSREC(
    346     tt_service_get_cmap_info,
    347 
    348     (TT_CMap_Info_GetFunc)tt_get_cmap_info    /* get_cmap_info */
    349   )
    350 
    351 
    352 #ifdef TT_CONFIG_OPTION_BDF
    353 
    354   static FT_Error
    355   sfnt_get_charset_id( TT_Face       face,
    356                        const char*  *acharset_encoding,
    357                        const char*  *acharset_registry )
    358   {
    359     BDF_PropertyRec  encoding, registry;
    360     FT_Error         error;
    361 
    362 
    363     /* XXX: I don't know whether this is correct, since
    364      *      tt_face_find_bdf_prop only returns something correct if we have
    365      *      previously selected a size that is listed in the BDF table.
    366      *      Should we change the BDF table format to include single offsets
    367      *      for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
    368      */
    369     error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", &registry );
    370     if ( !error )
    371     {
    372       error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
    373       if ( !error )
    374       {
    375         if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
    376              encoding.type == BDF_PROPERTY_TYPE_ATOM )
    377         {
    378           *acharset_encoding = encoding.u.atom;
    379           *acharset_registry = registry.u.atom;
    380         }
    381         else
    382           error = FT_THROW( Invalid_Argument );
    383       }
    384     }
    385 
    386     return error;
    387   }
    388 
    389 
    390   FT_DEFINE_SERVICE_BDFRec(
    391     sfnt_service_bdf,
    392 
    393     (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id,     /* get_charset_id */
    394     (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop    /* get_property   */
    395   )
    396 
    397 
    398 #endif /* TT_CONFIG_OPTION_BDF */
    399 
    400 
    401   /*
    402    *  SERVICE LIST
    403    */
    404 
    405 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
    406   FT_DEFINE_SERVICEDESCREC5(
    407     sfnt_services,
    408 
    409     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
    410     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
    411     FT_SERVICE_ID_GLYPH_DICT,           &SFNT_SERVICE_GLYPH_DICT_GET,
    412     FT_SERVICE_ID_BDF,                  &SFNT_SERVICE_BDF_GET,
    413     FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
    414 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    415   FT_DEFINE_SERVICEDESCREC4(
    416     sfnt_services,
    417 
    418     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
    419     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
    420     FT_SERVICE_ID_GLYPH_DICT,           &SFNT_SERVICE_GLYPH_DICT_GET,
    421     FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
    422 #elif defined TT_CONFIG_OPTION_BDF
    423   FT_DEFINE_SERVICEDESCREC4(
    424     sfnt_services,
    425 
    426     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
    427     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
    428     FT_SERVICE_ID_BDF,                  &SFNT_SERVICE_BDF_GET,
    429     FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
    430 #else
    431   FT_DEFINE_SERVICEDESCREC3(
    432     sfnt_services,
    433 
    434     FT_SERVICE_ID_SFNT_TABLE,           &SFNT_SERVICE_SFNT_TABLE_GET,
    435     FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
    436     FT_SERVICE_ID_TT_CMAP,              &TT_SERVICE_CMAP_INFO_GET )
    437 #endif
    438 
    439 
    440   FT_CALLBACK_DEF( FT_Module_Interface )
    441   sfnt_get_interface( FT_Module    module,
    442                       const char*  module_interface )
    443   {
    444     /* SFNT_SERVICES_GET dereferences `library' in PIC mode */
    445 #ifdef FT_CONFIG_OPTION_PIC
    446     FT_Library  library;
    447 
    448 
    449     if ( !module )
    450       return NULL;
    451     library = module->library;
    452     if ( !library )
    453       return NULL;
    454 #else
    455     FT_UNUSED( module );
    456 #endif
    457 
    458     return ft_service_list_lookup( SFNT_SERVICES_GET, module_interface );
    459   }
    460 
    461 
    462 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    463 #define PUT_EMBEDDED_BITMAPS( a )  a
    464 #else
    465 #define PUT_EMBEDDED_BITMAPS( a )  NULL
    466 #endif
    467 
    468 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    469 #define PUT_PS_NAMES( a )  a
    470 #else
    471 #define PUT_PS_NAMES( a )  NULL
    472 #endif
    473 
    474   FT_DEFINE_SFNT_INTERFACE(
    475     sfnt_interface,
    476 
    477     tt_face_goto_table,     /* TT_Loader_GotoTableFunc goto_table      */
    478 
    479     sfnt_init_face,         /* TT_Init_Face_Func       init_face       */
    480     sfnt_load_face,         /* TT_Load_Face_Func       load_face       */
    481     sfnt_done_face,         /* TT_Done_Face_Func       done_face       */
    482     sfnt_get_interface,     /* FT_Module_Requester     get_interface   */
    483 
    484     tt_face_load_any,       /* TT_Load_Any_Func        load_any        */
    485 
    486     tt_face_load_head,      /* TT_Load_Table_Func      load_head       */
    487     tt_face_load_hhea,      /* TT_Load_Metrics_Func    load_hhea       */
    488     tt_face_load_cmap,      /* TT_Load_Table_Func      load_cmap       */
    489     tt_face_load_maxp,      /* TT_Load_Table_Func      load_maxp       */
    490     tt_face_load_os2,       /* TT_Load_Table_Func      load_os2        */
    491     tt_face_load_post,      /* TT_Load_Table_Func      load_post       */
    492 
    493     tt_face_load_name,      /* TT_Load_Table_Func      load_name       */
    494     tt_face_free_name,      /* TT_Free_Table_Func      free_name       */
    495 
    496     tt_face_load_kern,      /* TT_Load_Table_Func      load_kern       */
    497     tt_face_load_gasp,      /* TT_Load_Table_Func      load_gasp       */
    498     tt_face_load_pclt,      /* TT_Load_Table_Func      load_init       */
    499 
    500     /* see `ttload.h' */
    501     PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ),
    502                             /* TT_Load_Table_Func      load_bhed       */
    503     PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ),
    504                             /* TT_Load_SBit_Image_Func load_sbit_image */
    505 
    506     /* see `ttpost.h' */
    507     PUT_PS_NAMES( tt_face_get_ps_name   ),
    508                             /* TT_Get_PS_Name_Func     get_psname      */
    509     PUT_PS_NAMES( tt_face_free_ps_names ),
    510                             /* TT_Free_Table_Func      free_psnames    */
    511 
    512     /* since version 2.1.8 */
    513     tt_face_get_kerning,    /* TT_Face_GetKerningFunc  get_kerning     */
    514 
    515     /* since version 2.2 */
    516     tt_face_load_font_dir,  /* TT_Load_Table_Func      load_font_dir   */
    517     tt_face_load_hmtx,      /* TT_Load_Metrics_Func    load_hmtx       */
    518 
    519     /* see `ttsbit.h' and `sfnt.h' */
    520     PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
    521                             /* TT_Load_Table_Func      load_eblc       */
    522     PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
    523                             /* TT_Free_Table_Func      free_eblc       */
    524 
    525     PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike     ),
    526                             /* TT_Set_SBit_Strike_Func set_sbit_strike */
    527     PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
    528                     /* TT_Load_Strike_Metrics_Func load_strike_metrics */
    529 
    530     tt_face_get_metrics,    /* TT_Get_Metrics_Func     get_metrics     */
    531 
    532     tt_face_get_name        /* TT_Get_Name_Func        get_name        */
    533   )
    534 
    535 
    536   FT_DEFINE_MODULE(
    537     sfnt_module_class,
    538 
    539     0,  /* not a font driver or renderer */
    540     sizeof ( FT_ModuleRec ),
    541 
    542     "sfnt",     /* driver name                            */
    543     0x10000L,   /* driver version 1.0                     */
    544     0x20000L,   /* driver requires FreeType 2.0 or higher */
    545 
    546     (const void*)&SFNT_INTERFACE_GET,  /* module specific interface */
    547 
    548     (FT_Module_Constructor)NULL,               /* module_init   */
    549     (FT_Module_Destructor) NULL,               /* module_done   */
    550     (FT_Module_Requester)  sfnt_get_interface  /* get_interface */
    551   )
    552 
    553 
    554 /* END */
    555