tor-browser

The Tor Browser
git clone https://git.dasho.dev/tor-browser.git
Log | Files | Refs | README | LICENSE

ttdriver.c (22120B)


      1 /****************************************************************************
      2 *
      3 * ttdriver.c
      4 *
      5 *   TrueType font driver implementation (body).
      6 *
      7 * Copyright (C) 1996-2025 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 <freetype/internal/ftdebug.h>
     20 #include <freetype/internal/ftstream.h>
     21 #include <freetype/internal/sfnt.h>
     22 #include <freetype/internal/services/svfntfmt.h>
     23 
     24 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     25 #include <freetype/ftmm.h>
     26 #include <freetype/internal/services/svmm.h>
     27 #include <freetype/internal/services/svmetric.h>
     28 #endif
     29 
     30 #include <freetype/internal/services/svtteng.h>
     31 #include <freetype/internal/services/svttglyf.h>
     32 #include <freetype/internal/services/svprop.h>
     33 #include <freetype/ftdriver.h>
     34 
     35 #include "ttdriver.h"
     36 #include "ttgload.h"
     37 #include "ttpload.h"
     38 
     39 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     40 #include "ttgxvar.h"
     41 #endif
     42 
     43 #include "tterrors.h"
     44 
     45 
     46  /**************************************************************************
     47   *
     48   * The macro FT_COMPONENT is used in trace mode.  It is an implicit
     49   * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
     50   * messages during execution.
     51   */
     52 #undef  FT_COMPONENT
     53 #define FT_COMPONENT  ttdriver
     54 
     55 
     56  /*
     57   * PROPERTY SERVICE
     58   *
     59   */
     60  FT_CALLBACK_DEF( FT_Error )
     61  tt_property_set( FT_Module    module,         /* TT_Driver */
     62                   const char*  property_name,
     63                   const void*  value,
     64                   FT_Bool      value_is_string )
     65  {
     66    FT_Error   error  = FT_Err_Ok;
     67    TT_Driver  driver = (TT_Driver)module;
     68 
     69 #ifndef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
     70    FT_UNUSED( value_is_string );
     71 #endif
     72 
     73 
     74    if ( !ft_strcmp( property_name, "interpreter-version" ) )
     75    {
     76      FT_UInt  interpreter_version;
     77 
     78 
     79 #ifdef FT_CONFIG_OPTION_ENVIRONMENT_PROPERTIES
     80      if ( value_is_string )
     81      {
     82        const char*  s = (const char*)value;
     83 
     84 
     85        interpreter_version = (FT_UInt)ft_strtol( s, NULL, 10 );
     86      }
     87      else
     88 #endif
     89      {
     90        FT_UInt*  iv = (FT_UInt*)value;
     91 
     92 
     93        interpreter_version = *iv;
     94      }
     95 
     96      switch ( interpreter_version )
     97      {
     98      case TT_INTERPRETER_VERSION_35:
     99        driver->interpreter_version = TT_INTERPRETER_VERSION_35;
    100        break;
    101 
    102      case TT_INTERPRETER_VERSION_38:
    103      case TT_INTERPRETER_VERSION_40:
    104 #ifdef TT_SUPPORT_SUBPIXEL_HINTING_MINIMAL
    105        driver->interpreter_version = TT_INTERPRETER_VERSION_40;
    106      break;
    107 #endif
    108 
    109      default:
    110        error = FT_ERR( Unimplemented_Feature );
    111      }
    112 
    113      return error;
    114    }
    115 
    116    FT_TRACE2(( "tt_property_set: missing property `%s'\n",
    117                property_name ));
    118    return FT_THROW( Missing_Property );
    119  }
    120 
    121 
    122  FT_CALLBACK_DEF( FT_Error )
    123  tt_property_get( FT_Module    module,         /* TT_Driver */
    124                   const char*  property_name,
    125                   void*        value )
    126  {
    127    FT_Error   error  = FT_Err_Ok;
    128    TT_Driver  driver = (TT_Driver)module;
    129 
    130    FT_UInt  interpreter_version = driver->interpreter_version;
    131 
    132 
    133    if ( !ft_strcmp( property_name, "interpreter-version" ) )
    134    {
    135      FT_UInt*  val = (FT_UInt*)value;
    136 
    137 
    138      *val = interpreter_version;
    139 
    140      return error;
    141    }
    142 
    143    FT_TRACE2(( "tt_property_get: missing property `%s'\n",
    144                property_name ));
    145    return FT_THROW( Missing_Property );
    146  }
    147 
    148 
    149  FT_DEFINE_SERVICE_PROPERTIESREC(
    150    tt_service_properties,
    151 
    152    tt_property_set,  /* FT_Properties_SetFunc set_property */
    153    tt_property_get   /* FT_Properties_GetFunc get_property */
    154  )
    155 
    156 
    157  /*************************************************************************/
    158  /*************************************************************************/
    159  /*************************************************************************/
    160  /****                                                                 ****/
    161  /****                                                                 ****/
    162  /****                          F A C E S                              ****/
    163  /****                                                                 ****/
    164  /****                                                                 ****/
    165  /*************************************************************************/
    166  /*************************************************************************/
    167  /*************************************************************************/
    168 
    169 
    170  /**************************************************************************
    171   *
    172   * @Function:
    173   *   tt_get_kerning
    174   *
    175   * @Description:
    176   *   A driver method used to return the kerning vector between two
    177   *   glyphs of the same face.
    178   *
    179   * @Input:
    180   *   face ::
    181   *     A handle to the source face object.
    182   *
    183   *   left_glyph ::
    184   *     The index of the left glyph in the kern pair.
    185   *
    186   *   right_glyph ::
    187   *     The index of the right glyph in the kern pair.
    188   *
    189   * @Output:
    190   *   kerning ::
    191   *     The kerning vector.  This is in font units for
    192   *     scalable formats, and in pixels for fixed-sizes
    193   *     formats.
    194   *
    195   * @Return:
    196   *   FreeType error code.  0 means success.
    197   *
    198   * @Note:
    199   *   Only horizontal layouts (left-to-right & right-to-left) are
    200   *   supported by this function.  Other layouts, or more sophisticated
    201   *   kernings, are out of scope of this method (the basic driver
    202   *   interface is meant to be simple).
    203   *
    204   *   They can be implemented by format-specific interfaces.
    205   */
    206  FT_CALLBACK_DEF( FT_Error )
    207  tt_get_kerning( FT_Face     face,        /* TT_Face */
    208                  FT_UInt     left_glyph,
    209                  FT_UInt     right_glyph,
    210                  FT_Vector*  kerning )
    211  {
    212    TT_Face       ttface = (TT_Face)face;
    213    SFNT_Service  sfnt   = (SFNT_Service)ttface->sfnt;
    214 
    215 
    216    kerning->x = 0;
    217    kerning->y = 0;
    218 
    219    if ( sfnt )
    220    {
    221      /* Use 'kern' table if available since that can be faster; otherwise */
    222      /* use GPOS kerning pairs if available.                              */
    223      if ( ttface->kern_avail_bits )
    224        kerning->x = sfnt->get_kerning( ttface,
    225                                        left_glyph,
    226                                        right_glyph );
    227 #ifdef TT_CONFIG_OPTION_GPOS_KERNING
    228      else if ( ttface->num_gpos_lookups_kerning )
    229        kerning->x = sfnt->get_gpos_kerning( ttface,
    230                                             left_glyph,
    231                                             right_glyph );
    232 #endif
    233    }
    234 
    235    return 0;
    236  }
    237 
    238 
    239  FT_CALLBACK_DEF( FT_Error )
    240  tt_get_advances( FT_Face    face,      /* TT_Face */
    241                   FT_UInt    start,
    242                   FT_UInt    count,
    243                   FT_Int32   flags,
    244                   FT_Fixed  *advances )
    245  {
    246    FT_UInt  nn;
    247    TT_Face  ttface = (TT_Face)face;
    248 
    249 
    250    /* XXX: TODO: check for sbits */
    251 
    252    if ( flags & FT_LOAD_VERTICAL_LAYOUT )
    253    {
    254 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    255      /* no fast retrieval for blended MM fonts without VVAR table */
    256      if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) &&
    257           !( ttface->variation_support & TT_FACE_FLAG_VAR_VADVANCE )  )
    258        return FT_THROW( Unimplemented_Feature );
    259 #endif
    260 
    261      for ( nn = 0; nn < count; nn++ )
    262      {
    263        FT_Short   tsb;
    264        FT_UShort  ah;
    265 
    266 
    267        /* since we don't need `tsb', we use zero for `yMax' parameter */
    268        TT_Get_VMetrics( ttface, start + nn, 0, &tsb, &ah );
    269        advances[nn] = ah;
    270      }
    271    }
    272    else
    273    {
    274 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    275      /* no fast retrieval for blended MM fonts without HVAR table */
    276      if ( ( FT_IS_NAMED_INSTANCE( face ) || FT_IS_VARIATION( face ) ) &&
    277           !( ttface->variation_support & TT_FACE_FLAG_VAR_HADVANCE )  )
    278        return FT_THROW( Unimplemented_Feature );
    279 #endif
    280 
    281      for ( nn = 0; nn < count; nn++ )
    282      {
    283        FT_Short   lsb;
    284        FT_UShort  aw;
    285 
    286 
    287        TT_Get_HMetrics( ttface, start + nn, &lsb, &aw );
    288        advances[nn] = aw;
    289      }
    290    }
    291 
    292    return FT_Err_Ok;
    293  }
    294 
    295 
    296  /*************************************************************************/
    297  /*************************************************************************/
    298  /*************************************************************************/
    299  /****                                                                 ****/
    300  /****                                                                 ****/
    301  /****                           S I Z E S                             ****/
    302  /****                                                                 ****/
    303  /****                                                                 ****/
    304  /*************************************************************************/
    305  /*************************************************************************/
    306  /*************************************************************************/
    307 
    308 
    309 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    310 
    311  FT_CALLBACK_DEF( FT_Error )
    312  tt_size_select( FT_Size   size,
    313                  FT_ULong  strike_index )
    314  {
    315    TT_Face   ttface = (TT_Face)size->face;
    316    TT_Size   ttsize = (TT_Size)size;
    317    FT_Error  error  = FT_Err_Ok;
    318 
    319 
    320    ttsize->strike_index = strike_index;
    321 
    322    if ( FT_IS_SCALABLE( size->face ) )
    323    {
    324      /* use the scaled metrics, even when tt_size_reset fails */
    325      FT_Select_Metrics( size->face, strike_index );
    326 
    327      tt_size_reset( ttsize ); /* ignore return value */
    328    }
    329    else
    330    {
    331      SFNT_Service      sfnt         = (SFNT_Service)ttface->sfnt;
    332      FT_Size_Metrics*  size_metrics = &size->metrics;
    333 
    334 
    335      error = sfnt->load_strike_metrics( ttface,
    336                                         strike_index,
    337                                         size_metrics );
    338      if ( error )
    339        ttsize->strike_index = 0xFFFFFFFFUL;
    340    }
    341 
    342    return error;
    343  }
    344 
    345 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
    346 
    347 
    348  FT_CALLBACK_DEF( FT_Error )
    349  tt_size_request( FT_Size          size,
    350                   FT_Size_Request  req )
    351  {
    352    TT_Size   ttsize = (TT_Size)size;
    353    FT_Error  error  = FT_Err_Ok;
    354 
    355 
    356 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    357 
    358    if ( FT_HAS_FIXED_SIZES( size->face ) )
    359    {
    360      TT_Face       ttface = (TT_Face)size->face;
    361      SFNT_Service  sfnt   = (SFNT_Service)ttface->sfnt;
    362      FT_ULong      strike_index;
    363 
    364 
    365      error = sfnt->set_sbit_strike( ttface, req, &strike_index );
    366 
    367      if ( error )
    368        ttsize->strike_index = 0xFFFFFFFFUL;
    369      else
    370        return tt_size_select( size, strike_index );
    371    }
    372 
    373 #endif /* TT_CONFIG_OPTION_EMBEDDED_BITMAPS */
    374 
    375    {
    376      FT_Error  err = FT_Request_Metrics( size->face, req );
    377 
    378 
    379      if ( err )
    380      {
    381        error = err;
    382        goto Exit;
    383      }
    384    }
    385 
    386    if ( FT_IS_SCALABLE( size->face ) )
    387    {
    388      error = tt_size_reset( ttsize );
    389 
    390 #ifdef TT_USE_BYTECODE_INTERPRETER
    391      /* for the `MPS' bytecode instruction we need the point size */
    392      if ( !error )
    393      {
    394        FT_UInt  resolution =
    395                   ttsize->metrics->x_ppem > ttsize->metrics->y_ppem
    396                     ? req->horiResolution
    397                     : req->vertResolution;
    398 
    399 
    400        /* if we don't have a resolution value, assume 72dpi */
    401        if ( req->type == FT_SIZE_REQUEST_TYPE_SCALES ||
    402             !resolution                              )
    403          resolution = 72;
    404 
    405        ttsize->point_size = FT_MulDiv( ttsize->ttmetrics.ppem,
    406                                        64 * 72,
    407                                        resolution );
    408      }
    409 #endif
    410    }
    411 
    412  Exit:
    413    return error;
    414  }
    415 
    416 
    417  /**************************************************************************
    418   *
    419   * @Function:
    420   *   tt_glyph_load
    421   *
    422   * @Description:
    423   *   A driver method used to load a glyph within a given glyph slot.
    424   *
    425   * @Input:
    426   *   slot ::
    427   *     A handle to the target slot object where the glyph
    428   *     will be loaded.
    429   *
    430   *   size ::
    431   *     A handle to the source face size at which the glyph
    432   *     must be scaled, loaded, etc.
    433   *
    434   *   glyph_index ::
    435   *     The index of the glyph in the font file.
    436   *
    437   *   load_flags ::
    438   *     A flag indicating what to load for this glyph.  The
    439   *     FT_LOAD_XXX constants can be used to control the
    440   *     glyph loading process (e.g., whether the outline
    441   *     should be scaled, whether to load bitmaps or not,
    442   *     whether to hint the outline, etc).
    443   *
    444   * @Return:
    445   *   FreeType error code.  0 means success.
    446   */
    447  FT_CALLBACK_DEF( FT_Error )
    448  tt_glyph_load( FT_GlyphSlot  slot,        /* TT_GlyphSlot */
    449                 FT_Size       size,        /* TT_Size      */
    450                 FT_UInt       glyph_index,
    451                 FT_Int32      load_flags )
    452  {
    453    TT_GlyphSlot  ttslot = (TT_GlyphSlot)slot;
    454    TT_Size       ttsize = (TT_Size)size;
    455    FT_Face       face   = ttslot->face;
    456    FT_Error      error;
    457 
    458 
    459    if ( !slot )
    460      return FT_THROW( Invalid_Slot_Handle );
    461 
    462    if ( !size )
    463      return FT_THROW( Invalid_Size_Handle );
    464 
    465    if ( !face )
    466      return FT_THROW( Invalid_Face_Handle );
    467 
    468 #ifdef FT_CONFIG_OPTION_INCREMENTAL
    469    if ( glyph_index >= (FT_UInt)face->num_glyphs &&
    470         !face->internal->incremental_interface   )
    471 #else
    472    if ( glyph_index >= (FT_UInt)face->num_glyphs )
    473 #endif
    474      return FT_THROW( Invalid_Argument );
    475 
    476    if ( load_flags & FT_LOAD_NO_HINTING )
    477    {
    478      /* both FT_LOAD_NO_HINTING and FT_LOAD_NO_AUTOHINT   */
    479      /* are necessary to disable hinting for tricky fonts */
    480 
    481      if ( FT_IS_TRICKY( face ) )
    482        load_flags &= ~FT_LOAD_NO_HINTING;
    483 
    484      if ( load_flags & FT_LOAD_NO_AUTOHINT )
    485        load_flags |= FT_LOAD_NO_HINTING;
    486    }
    487 
    488    if ( load_flags & ( FT_LOAD_NO_RECURSE | FT_LOAD_NO_SCALE ) )
    489    {
    490      load_flags |= FT_LOAD_NO_BITMAP | FT_LOAD_NO_SCALE;
    491 
    492      if ( !FT_IS_TRICKY( face ) )
    493        load_flags |= FT_LOAD_NO_HINTING;
    494    }
    495 
    496    /* use hinted metrics only if we load a glyph with hinting */
    497    ttsize->metrics = ( load_flags & FT_LOAD_NO_HINTING )
    498                        ? &size->metrics
    499                        : &ttsize->hinted_metrics;
    500 
    501    /* now fill in the glyph slot with outline/bitmap/layered */
    502    error = TT_Load_Glyph( ttsize, ttslot, glyph_index, load_flags );
    503 
    504    /* force drop-out mode to 2 - irrelevant now */
    505    /* slot->outline.dropout_mode = 2; */
    506 
    507    return error;
    508  }
    509 
    510 
    511  /*************************************************************************/
    512  /*************************************************************************/
    513  /*************************************************************************/
    514  /****                                                                 ****/
    515  /****                                                                 ****/
    516  /****                D R I V E R  I N T E R F A C E                   ****/
    517  /****                                                                 ****/
    518  /****                                                                 ****/
    519  /*************************************************************************/
    520  /*************************************************************************/
    521  /*************************************************************************/
    522 
    523 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    524 
    525  FT_DEFINE_SERVICE_MULTIMASTERSREC(
    526    tt_service_gx_multi_masters,
    527 
    528    NULL,                  /* FT_Get_MM_Func              get_mm                     */
    529    NULL,                  /* FT_Set_MM_Design_Func       set_mm_design              */
    530    TT_Set_MM_Blend,       /* FT_Set_MM_Blend_Func        set_mm_blend               */
    531    TT_Get_MM_Blend,       /* FT_Get_MM_Blend_Func        get_mm_blend               */
    532    TT_Get_MM_Var,         /* FT_Get_MM_Var_Func          get_mm_var                 */
    533    TT_Set_Var_Design,     /* FT_Set_Var_Design_Func      set_var_design             */
    534    TT_Get_Var_Design,     /* FT_Get_Var_Design_Func      get_var_design             */
    535    TT_Set_Named_Instance, /* FT_Set_Named_Instance_Func  set_named_instance         */
    536    TT_Get_Default_Named_Instance,
    537                    /* FT_Get_Default_Named_Instance_Func get_default_named_instance */
    538    NULL,                  /* FT_Set_MM_WeightVector_Func set_mm_weightvector        */
    539    NULL,                  /* FT_Get_MM_WeightVector_Func get_mm_weightvector        */
    540 
    541    tt_construct_ps_name,  /* FT_Construct_PS_Name_Func   construct_ps_name          */
    542    tt_var_load_delta_set_index_mapping,
    543                    /* FT_Var_Load_Delta_Set_Idx_Map_Func load_delta_set_idx_map     */
    544    tt_var_load_item_variation_store,
    545                    /* FT_Var_Load_Item_Var_Store_Func    load_item_variation_store  */
    546    tt_var_get_item_delta, /* FT_Var_Get_Item_Delta_Func  get_item_delta             */
    547    tt_var_done_item_variation_store,
    548                    /* FT_Var_Done_Item_Var_Store_Func    done_item_variation_store  */
    549    tt_var_done_delta_set_index_map,
    550                    /* FT_Var_Done_Delta_Set_Idx_Map_Func done_delta_set_index_map   */
    551    tt_get_var_blend,      /* FT_Get_Var_Blend_Func       get_var_blend              */
    552    tt_done_blend          /* FT_Done_Blend_Func          done_blend                 */
    553  )
    554 
    555  FT_DEFINE_SERVICE_METRICSVARIATIONSREC(
    556    tt_service_metrics_variations,
    557 
    558    tt_hadvance_adjust,   /* FT_HAdvance_Adjust_Func hadvance_adjust */
    559    NULL,                 /* FT_LSB_Adjust_Func      lsb_adjust      */
    560    NULL,                 /* FT_RSB_Adjust_Func      rsb_adjust      */
    561 
    562    tt_vadvance_adjust,   /* FT_VAdvance_Adjust_Func vadvance_adjust */
    563    NULL,                 /* FT_TSB_Adjust_Func      tsb_adjust      */
    564    NULL,                 /* FT_BSB_Adjust_Func      bsb_adjust      */
    565    NULL,                 /* FT_VOrg_Adjust_Func     vorg_adjust     */
    566 
    567    tt_apply_mvar,        /* FT_Metrics_Adjust_Func  metrics_adjust  */
    568    tt_size_reset_height  /* FT_Size_Reset_Func      size_reset      */
    569  )
    570 
    571 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
    572 
    573 
    574  static const FT_Service_TrueTypeEngineRec  tt_service_truetype_engine =
    575  {
    576 #ifdef TT_USE_BYTECODE_INTERPRETER
    577 
    578    FT_TRUETYPE_ENGINE_TYPE_PATENTED
    579 
    580 #else /* !TT_USE_BYTECODE_INTERPRETER */
    581 
    582    FT_TRUETYPE_ENGINE_TYPE_NONE
    583 
    584 #endif /* TT_USE_BYTECODE_INTERPRETER */
    585  };
    586 
    587 
    588  FT_DEFINE_SERVICE_TTGLYFREC(
    589    tt_service_truetype_glyf,
    590 
    591    (TT_Glyf_GetLocationFunc)tt_face_get_location      /* get_location */
    592  )
    593 
    594 
    595 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    596  FT_DEFINE_SERVICEDESCREC6(
    597    tt_services,
    598 
    599    FT_SERVICE_ID_FONT_FORMAT,        FT_FONT_FORMAT_TRUETYPE,
    600    FT_SERVICE_ID_MULTI_MASTERS,      &tt_service_gx_multi_masters,
    601    FT_SERVICE_ID_METRICS_VARIATIONS, &tt_service_metrics_variations,
    602    FT_SERVICE_ID_TRUETYPE_ENGINE,    &tt_service_truetype_engine,
    603    FT_SERVICE_ID_TT_GLYF,            &tt_service_truetype_glyf,
    604    FT_SERVICE_ID_PROPERTIES,         &tt_service_properties )
    605 #else
    606  FT_DEFINE_SERVICEDESCREC4(
    607    tt_services,
    608 
    609    FT_SERVICE_ID_FONT_FORMAT,     FT_FONT_FORMAT_TRUETYPE,
    610    FT_SERVICE_ID_TRUETYPE_ENGINE, &tt_service_truetype_engine,
    611    FT_SERVICE_ID_TT_GLYF,         &tt_service_truetype_glyf,
    612    FT_SERVICE_ID_PROPERTIES,      &tt_service_properties )
    613 #endif
    614 
    615 
    616  FT_CALLBACK_DEF( FT_Module_Interface )
    617  tt_get_interface( FT_Module    driver,    /* TT_Driver */
    618                    const char*  tt_interface )
    619  {
    620    FT_Library           library;
    621    FT_Module_Interface  result;
    622    FT_Module            sfntd;
    623    SFNT_Service         sfnt;
    624 
    625 
    626    result = ft_service_list_lookup( tt_services, tt_interface );
    627    if ( result )
    628      return result;
    629 
    630    if ( !driver )
    631      return NULL;
    632    library = driver->library;
    633    if ( !library )
    634      return NULL;
    635 
    636    /* only return the default interface from the SFNT module */
    637    sfntd = FT_Get_Module( library, "sfnt" );
    638    if ( sfntd )
    639    {
    640      sfnt = (SFNT_Service)( sfntd->clazz->module_interface );
    641      if ( sfnt )
    642        return sfnt->get_interface( driver, tt_interface );
    643    }
    644 
    645    return 0;
    646  }
    647 
    648 
    649  /* The FT_DriverInterface structure is defined in ftdriver.h. */
    650 
    651 #ifdef TT_USE_BYTECODE_INTERPRETER
    652 #define TT_HINTER_FLAG  FT_MODULE_DRIVER_HAS_HINTER
    653 #else
    654 #define TT_HINTER_FLAG  0
    655 #endif
    656 
    657 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    658 #define TT_SIZE_SELECT  tt_size_select
    659 #else
    660 #define TT_SIZE_SELECT  0
    661 #endif
    662 
    663  FT_DEFINE_DRIVER(
    664    tt_driver_class,
    665 
    666      FT_MODULE_FONT_DRIVER     |
    667      FT_MODULE_DRIVER_SCALABLE |
    668      TT_HINTER_FLAG,
    669 
    670      sizeof ( TT_DriverRec ),
    671 
    672      "truetype",      /* driver name                           */
    673      0x10000L,        /* driver version == 1.0                 */
    674      0x20000L,        /* driver requires FreeType 2.0 or above */
    675 
    676      NULL,    /* module-specific interface */
    677 
    678      tt_driver_init,           /* FT_Module_Constructor  module_init   */
    679      tt_driver_done,           /* FT_Module_Destructor   module_done   */
    680      tt_get_interface,         /* FT_Module_Requester    get_interface */
    681 
    682    sizeof ( TT_FaceRec ),
    683    sizeof ( TT_SizeRec ),
    684    sizeof ( FT_GlyphSlotRec ),
    685 
    686    tt_face_init,               /* FT_Face_InitFunc  init_face */
    687    tt_face_done,               /* FT_Face_DoneFunc  done_face */
    688    tt_size_init,               /* FT_Size_InitFunc  init_size */
    689    tt_size_done,               /* FT_Size_DoneFunc  done_size */
    690    tt_slot_init,               /* FT_Slot_InitFunc  init_slot */
    691    NULL,                       /* FT_Slot_DoneFunc  done_slot */
    692 
    693    tt_glyph_load,              /* FT_Slot_LoadFunc  load_glyph */
    694 
    695    tt_get_kerning,             /* FT_Face_GetKerningFunc   get_kerning  */
    696    NULL,                       /* FT_Face_AttachFunc       attach_file  */
    697    tt_get_advances,            /* FT_Face_GetAdvancesFunc  get_advances */
    698 
    699    tt_size_request,            /* FT_Size_RequestFunc  request_size */
    700    TT_SIZE_SELECT              /* FT_Size_SelectFunc   select_size  */
    701  )
    702 
    703 
    704 /* END */