(root)/
freetype-2.13.2/
src/
sfnt/
sfdriver.c
       1  /****************************************************************************
       2   *
       3   * sfdriver.c
       4   *
       5   *   High-level SFNT driver interface (body).
       6   *
       7   * Copyright (C) 1996-2023 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/sfnt.h>
      21  #include <freetype/internal/ftobjs.h>
      22  #include <freetype/ttnameid.h>
      23  
      24  #include "sfdriver.h"
      25  #include "ttload.h"
      26  #include "sfobjs.h"
      27  
      28  #include "sferrors.h"
      29  
      30  #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
      31  #include "ttsbit.h"
      32  #endif
      33  
      34  #ifdef TT_CONFIG_OPTION_COLOR_LAYERS
      35  #include "ttcolr.h"
      36  #include "ttcpal.h"
      37  #endif
      38  
      39  #ifdef FT_CONFIG_OPTION_SVG
      40  #include "ttsvg.h"
      41  #endif
      42  
      43  #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
      44  #include "ttpost.h"
      45  #endif
      46  
      47  #ifdef TT_CONFIG_OPTION_BDF
      48  #include "ttbdf.h"
      49  #include <freetype/internal/services/svbdf.h>
      50  #endif
      51  
      52  #include "ttcmap.h"
      53  #include "ttkern.h"
      54  #include "ttmtx.h"
      55  
      56  #include <freetype/internal/services/svgldict.h>
      57  #include <freetype/internal/services/svpostnm.h>
      58  #include <freetype/internal/services/svsfnt.h>
      59  #include <freetype/internal/services/svttcmap.h>
      60  
      61  #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
      62  #include <freetype/ftmm.h>
      63  #include <freetype/internal/services/svmm.h>
      64  #endif
      65  
      66  
      67    /**************************************************************************
      68     *
      69     * The macro FT_COMPONENT is used in trace mode.  It is an implicit
      70     * parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log
      71     * messages during execution.
      72     */
      73  #undef  FT_COMPONENT
      74  #define FT_COMPONENT  sfdriver
      75  
      76  
      77    /*
      78     * SFNT TABLE SERVICE
      79     *
      80     */
      81  
      82    FT_CALLBACK_DEF( FT_Error )
      83    sfnt_load_table( FT_Face    face,    /* TT_Face */
      84                     FT_ULong   tag,
      85                     FT_Long    offset,
      86                     FT_Byte*   buffer,
      87                     FT_ULong*  length )
      88    {
      89      TT_Face  ttface = (TT_Face)face;
      90  
      91  
      92      return tt_face_load_any( ttface, tag, offset, buffer, length );
      93    }
      94  
      95  
      96    FT_CALLBACK_DEF( void* )
      97    get_sfnt_table( FT_Face      face,  /* TT_Face */
      98                    FT_Sfnt_Tag  tag )
      99    {
     100      TT_Face  ttface = (TT_Face)face;
     101  
     102      void*  table;
     103  
     104  
     105      switch ( tag )
     106      {
     107      case FT_SFNT_HEAD:
     108        table = &ttface->header;
     109        break;
     110  
     111      case FT_SFNT_HHEA:
     112        table = &ttface->horizontal;
     113        break;
     114  
     115      case FT_SFNT_VHEA:
     116        table = ttface->vertical_info ? &ttface->vertical : NULL;
     117        break;
     118  
     119      case FT_SFNT_OS2:
     120        table = ( ttface->os2.version == 0xFFFFU ) ? NULL : &ttface->os2;
     121        break;
     122  
     123      case FT_SFNT_POST:
     124        table = &ttface->postscript;
     125        break;
     126  
     127      case FT_SFNT_MAXP:
     128        table = &ttface->max_profile;
     129        break;
     130  
     131      case FT_SFNT_PCLT:
     132        table = ttface->pclt.Version ? &ttface->pclt : NULL;
     133        break;
     134  
     135      default:
     136        table = NULL;
     137      }
     138  
     139      return table;
     140    }
     141  
     142  
     143    FT_CALLBACK_DEF( FT_Error )
     144    sfnt_table_info( FT_Face    face,    /* TT_Face */
     145                     FT_UInt    idx,
     146                     FT_ULong  *tag,
     147                     FT_ULong  *offset,
     148                     FT_ULong  *length )
     149    {
     150      TT_Face  ttface = (TT_Face)face;
     151  
     152  
     153      if ( !offset || !length )
     154        return FT_THROW( Invalid_Argument );
     155  
     156      if ( !tag )
     157        *length = ttface->num_tables;
     158      else
     159      {
     160        if ( idx >= ttface->num_tables )
     161          return FT_THROW( Table_Missing );
     162  
     163        *tag    = ttface->dir_tables[idx].Tag;
     164        *offset = ttface->dir_tables[idx].Offset;
     165        *length = ttface->dir_tables[idx].Length;
     166      }
     167  
     168      return FT_Err_Ok;
     169    }
     170  
     171  
     172    FT_DEFINE_SERVICE_SFNT_TABLEREC(
     173      sfnt_service_sfnt_table,
     174  
     175      sfnt_load_table,  /* FT_SFNT_TableLoadFunc load_table */
     176      get_sfnt_table,   /* FT_SFNT_TableGetFunc  get_table  */
     177      sfnt_table_info   /* FT_SFNT_TableInfoFunc table_info */
     178    )
     179  
     180  
     181  #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
     182  
     183    /*
     184     * GLYPH DICT SERVICE
     185     *
     186     */
     187  
     188    FT_CALLBACK_DEF( FT_Error )
     189    sfnt_get_glyph_name( FT_Face     face,
     190                         FT_UInt     glyph_index,
     191                         FT_Pointer  buffer,
     192                         FT_UInt     buffer_max )
     193    {
     194      FT_String*  gname;
     195      FT_Error    error;
     196  
     197  
     198      error = tt_face_get_ps_name( (TT_Face)face, glyph_index, &gname );
     199      if ( !error )
     200        FT_STRCPYN( buffer, gname, buffer_max );
     201  
     202      return error;
     203    }
     204  
     205  
     206    FT_CALLBACK_DEF( FT_UInt )
     207    sfnt_get_name_index( FT_Face           face,
     208                         const FT_String*  glyph_name )
     209    {
     210      TT_Face  ttface = (TT_Face)face;
     211  
     212      FT_UInt  i, max_gid = FT_UINT_MAX;
     213  
     214  
     215      if ( face->num_glyphs < 0 )
     216        return 0;
     217      else if ( (FT_ULong)face->num_glyphs < FT_UINT_MAX )
     218        max_gid = (FT_UInt)face->num_glyphs;
     219      else
     220        FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08lx\n",
     221                    FT_UINT_MAX, face->num_glyphs ));
     222  
     223      for ( i = 0; i < max_gid; i++ )
     224      {
     225        FT_String*  gname;
     226        FT_Error    error = tt_face_get_ps_name( ttface, i, &gname );
     227  
     228  
     229        if ( error )
     230          continue;
     231  
     232        if ( !ft_strcmp( glyph_name, gname ) )
     233          return i;
     234      }
     235  
     236      return 0;
     237    }
     238  
     239  
     240    FT_DEFINE_SERVICE_GLYPHDICTREC(
     241      sfnt_service_glyph_dict,
     242  
     243      sfnt_get_glyph_name,  /* FT_GlyphDict_GetNameFunc   get_name   */
     244      sfnt_get_name_index   /* FT_GlyphDict_NameIndexFunc name_index */
     245    )
     246  
     247  #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
     248  
     249  
     250    /*
     251     * POSTSCRIPT NAME SERVICE
     252     *
     253     */
     254  
     255    /* an array representing allowed ASCII characters in a PS string */
     256    static const unsigned char sfnt_ps_map[16] =
     257    {
     258                  /*             4        0        C        8 */
     259      0x00, 0x00, /* 0x00: 0 0 0 0  0 0 0 0  0 0 0 0  0 0 0 0 */
     260      0x00, 0x00, /* 0x10: 0 0 0 0  0 0 0 0  0 0 0 0  0 0 0 0 */
     261      0xDE, 0x7C, /* 0x20: 1 1 0 1  1 1 1 0  0 1 1 1  1 1 0 0 */
     262      0xFF, 0xAF, /* 0x30: 1 1 1 1  1 1 1 1  1 0 1 0  1 1 1 1 */
     263      0xFF, 0xFF, /* 0x40: 1 1 1 1  1 1 1 1  1 1 1 1  1 1 1 1 */
     264      0xFF, 0xD7, /* 0x50: 1 1 1 1  1 1 1 1  1 1 0 1  0 1 1 1 */
     265      0xFF, 0xFF, /* 0x60: 1 1 1 1  1 1 1 1  1 1 1 1  1 1 1 1 */
     266      0xFF, 0x57  /* 0x70: 1 1 1 1  1 1 1 1  0 1 0 1  0 1 1 1 */
     267    };
     268  
     269  
     270    static int
     271    sfnt_is_postscript( int  c )
     272    {
     273      unsigned int  cc;
     274  
     275  
     276      if ( c < 0 || c >= 0x80 )
     277        return 0;
     278  
     279      cc = (unsigned int)c;
     280  
     281      return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) );
     282    }
     283  
     284  
     285  #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     286  
     287    /* Only ASCII letters and digits are taken for a variation font */
     288    /* instance's PostScript name.                                  */
     289    /*                                                              */
     290    /* `ft_isalnum' is a macro, but we need a function here, thus   */
     291    /* this definition.                                             */
     292    static int
     293    sfnt_is_alphanumeric( int  c )
     294    {
     295      return ft_isalnum( c );
     296    }
     297  
     298  
     299    /* the implementation of MurmurHash3 is taken and adapted from          */
     300    /* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */
     301  
     302  #define ROTL32( x, r )  ( x << r ) | ( x >> ( 32 - r ) )
     303  
     304  
     305    static FT_UInt32
     306    fmix32( FT_UInt32  h )
     307    {
     308      h ^= h >> 16;
     309      h *= 0x85ebca6b;
     310      h ^= h >> 13;
     311      h *= 0xc2b2ae35;
     312      h ^= h >> 16;
     313  
     314      return h;
     315    }
     316  
     317  
     318    static void
     319    murmur_hash_3_128( const void*         key,
     320                       const unsigned int  len,
     321                       FT_UInt32           seed,
     322                       void*               out )
     323    {
     324      const FT_Byte*  data    = (const FT_Byte*)key;
     325      const int       nblocks = (int)len / 16;
     326  
     327      FT_UInt32  h1 = seed;
     328      FT_UInt32  h2 = seed;
     329      FT_UInt32  h3 = seed;
     330      FT_UInt32  h4 = seed;
     331  
     332      const FT_UInt32  c1 = 0x239b961b;
     333      const FT_UInt32  c2 = 0xab0e9789;
     334      const FT_UInt32  c3 = 0x38b34ae5;
     335      const FT_UInt32  c4 = 0xa1e38b93;
     336  
     337      const FT_UInt32*  blocks = (const FT_UInt32*)( data + nblocks * 16 );
     338  
     339      int  i;
     340  
     341  
     342      for( i = -nblocks; i; i++ )
     343      {
     344        FT_UInt32  k1 = blocks[i * 4 + 0];
     345        FT_UInt32  k2 = blocks[i * 4 + 1];
     346        FT_UInt32  k3 = blocks[i * 4 + 2];
     347        FT_UInt32  k4 = blocks[i * 4 + 3];
     348  
     349  
     350        k1 *= c1;
     351        k1  = ROTL32( k1, 15 );
     352        k1 *= c2;
     353        h1 ^= k1;
     354  
     355        h1  = ROTL32( h1, 19 );
     356        h1 += h2;
     357        h1  = h1 * 5 + 0x561ccd1b;
     358  
     359        k2 *= c2;
     360        k2  = ROTL32( k2, 16 );
     361        k2 *= c3;
     362        h2 ^= k2;
     363  
     364        h2  = ROTL32( h2, 17 );
     365        h2 += h3;
     366        h2  = h2 * 5 + 0x0bcaa747;
     367  
     368        k3 *= c3;
     369        k3  = ROTL32( k3, 17 );
     370        k3 *= c4;
     371        h3 ^= k3;
     372  
     373        h3  = ROTL32( h3, 15 );
     374        h3 += h4;
     375        h3  = h3 * 5 + 0x96cd1c35;
     376  
     377        k4 *= c4;
     378        k4  = ROTL32( k4, 18 );
     379        k4 *= c1;
     380        h4 ^= k4;
     381  
     382        h4  = ROTL32( h4, 13 );
     383        h4 += h1;
     384        h4  = h4 * 5 + 0x32ac3b17;
     385      }
     386  
     387      {
     388        const FT_Byte*  tail = (const FT_Byte*)( data + nblocks * 16 );
     389  
     390        FT_UInt32  k1 = 0;
     391        FT_UInt32  k2 = 0;
     392        FT_UInt32  k3 = 0;
     393        FT_UInt32  k4 = 0;
     394  
     395  
     396        switch ( len & 15 )
     397        {
     398        case 15:
     399          k4 ^= (FT_UInt32)tail[14] << 16;
     400          FALL_THROUGH;
     401        case 14:
     402          k4 ^= (FT_UInt32)tail[13] << 8;
     403          FALL_THROUGH;
     404        case 13:
     405          k4 ^= (FT_UInt32)tail[12];
     406          k4 *= c4;
     407          k4  = ROTL32( k4, 18 );
     408          k4 *= c1;
     409          h4 ^= k4;
     410          FALL_THROUGH;
     411  
     412        case 12:
     413          k3 ^= (FT_UInt32)tail[11] << 24;
     414          FALL_THROUGH;
     415        case 11:
     416          k3 ^= (FT_UInt32)tail[10] << 16;
     417          FALL_THROUGH;
     418        case 10:
     419          k3 ^= (FT_UInt32)tail[9] << 8;
     420          FALL_THROUGH;
     421        case 9:
     422          k3 ^= (FT_UInt32)tail[8];
     423          k3 *= c3;
     424          k3  = ROTL32( k3, 17 );
     425          k3 *= c4;
     426          h3 ^= k3;
     427          FALL_THROUGH;
     428  
     429        case 8:
     430          k2 ^= (FT_UInt32)tail[7] << 24;
     431          FALL_THROUGH;
     432        case 7:
     433          k2 ^= (FT_UInt32)tail[6] << 16;
     434          FALL_THROUGH;
     435        case 6:
     436          k2 ^= (FT_UInt32)tail[5] << 8;
     437          FALL_THROUGH;
     438        case 5:
     439          k2 ^= (FT_UInt32)tail[4];
     440          k2 *= c2;
     441          k2  = ROTL32( k2, 16 );
     442          k2 *= c3;
     443          h2 ^= k2;
     444          FALL_THROUGH;
     445  
     446        case 4:
     447          k1 ^= (FT_UInt32)tail[3] << 24;
     448          FALL_THROUGH;
     449        case 3:
     450          k1 ^= (FT_UInt32)tail[2] << 16;
     451          FALL_THROUGH;
     452        case 2:
     453          k1 ^= (FT_UInt32)tail[1] << 8;
     454          FALL_THROUGH;
     455        case 1:
     456          k1 ^= (FT_UInt32)tail[0];
     457          k1 *= c1;
     458          k1  = ROTL32( k1, 15 );
     459          k1 *= c2;
     460          h1 ^= k1;
     461        }
     462      }
     463  
     464      h1 ^= len;
     465      h2 ^= len;
     466      h3 ^= len;
     467      h4 ^= len;
     468  
     469      h1 += h2;
     470      h1 += h3;
     471      h1 += h4;
     472  
     473      h2 += h1;
     474      h3 += h1;
     475      h4 += h1;
     476  
     477      h1 = fmix32( h1 );
     478      h2 = fmix32( h2 );
     479      h3 = fmix32( h3 );
     480      h4 = fmix32( h4 );
     481  
     482      h1 += h2;
     483      h1 += h3;
     484      h1 += h4;
     485  
     486      h2 += h1;
     487      h3 += h1;
     488      h4 += h1;
     489  
     490      ((FT_UInt32*)out)[0] = h1;
     491      ((FT_UInt32*)out)[1] = h2;
     492      ((FT_UInt32*)out)[2] = h3;
     493      ((FT_UInt32*)out)[3] = h4;
     494    }
     495  
     496  
     497  #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
     498  
     499  
     500    typedef int (*char_type_func)( int  c );
     501  
     502  
     503    /* Handling of PID/EID 3/0 and 3/1 is the same. */
     504  #define IS_WIN( n )  ( (n)->platformID == 3                             && \
     505                         ( (n)->encodingID == 1 || (n)->encodingID == 0 ) )
     506  
     507  #define IS_APPLE( n )  ( (n)->platformID == 1 && \
     508                           (n)->encodingID == 0 )
     509  
     510    static char*
     511    get_win_string( FT_Memory       memory,
     512                    FT_Stream       stream,
     513                    TT_Name         entry,
     514                    char_type_func  char_type,
     515                    FT_Bool         report_invalid_characters )
     516    {
     517      FT_Error  error;
     518  
     519      char*       result = NULL;
     520      FT_String*  r;
     521      FT_Char*    p;
     522      FT_UInt     len;
     523  
     524  
     525      if ( FT_QALLOC( result, entry->stringLength / 2 + 1 ) )
     526        return NULL;
     527  
     528      if ( FT_STREAM_SEEK( entry->stringOffset ) ||
     529           FT_FRAME_ENTER( entry->stringLength ) )
     530        goto get_win_string_error;
     531  
     532      r = (FT_String*)result;
     533      p = (FT_Char*)stream->cursor;
     534  
     535      for ( len = entry->stringLength / 2; len > 0; len--, p += 2 )
     536      {
     537        if ( p[0] == 0 && char_type( p[1] ) )
     538          *r++ = p[1];
     539        else
     540        {
     541          if ( report_invalid_characters )
     542            FT_TRACE0(( "get_win_string:"
     543                        " Character 0x%X invalid in PS name string\n",
     544                        ((unsigned)p[0])*256 + (unsigned)p[1] ));
     545          continue;
     546        }
     547      }
     548      *r = '\0';
     549  
     550      FT_FRAME_EXIT();
     551  
     552      if ( r != result )
     553        return result;
     554  
     555    get_win_string_error:
     556      FT_FREE( result );
     557  
     558      entry->stringLength = 0;
     559      entry->stringOffset = 0;
     560      FT_FREE( entry->string );
     561  
     562      return NULL;
     563    }
     564  
     565  
     566    static char*
     567    get_apple_string( FT_Memory       memory,
     568                      FT_Stream       stream,
     569                      TT_Name         entry,
     570                      char_type_func  char_type,
     571                      FT_Bool         report_invalid_characters )
     572    {
     573      FT_Error  error;
     574  
     575      char*       result = NULL;
     576      FT_String*  r;
     577      FT_Char*    p;
     578      FT_UInt     len;
     579  
     580  
     581      if ( FT_QALLOC( result, entry->stringLength + 1 ) )
     582        return NULL;
     583  
     584      if ( FT_STREAM_SEEK( entry->stringOffset ) ||
     585           FT_FRAME_ENTER( entry->stringLength ) )
     586        goto get_apple_string_error;
     587  
     588      r = (FT_String*)result;
     589      p = (FT_Char*)stream->cursor;
     590  
     591      for ( len = entry->stringLength; len > 0; len--, p++ )
     592      {
     593        if ( char_type( *p ) )
     594          *r++ = *p;
     595        else
     596        {
     597          if ( report_invalid_characters )
     598            FT_TRACE0(( "get_apple_string:"
     599                        " Character `%c' (0x%X) invalid in PS name string\n",
     600                        *p, *p ));
     601          continue;
     602        }
     603      }
     604      *r = '\0';
     605  
     606      FT_FRAME_EXIT();
     607  
     608      if ( r != result )
     609        return result;
     610  
     611    get_apple_string_error:
     612      FT_FREE( result );
     613  
     614      entry->stringOffset = 0;
     615      entry->stringLength = 0;
     616      FT_FREE( entry->string );
     617  
     618      return NULL;
     619    }
     620  
     621  
     622    FT_CALLBACK_DEF( FT_Bool )
     623    sfnt_get_name_id( TT_Face    face,
     624                      FT_UShort  id,
     625                      FT_Int    *win,
     626                      FT_Int    *apple )
     627    {
     628      FT_Int  n;
     629  
     630  
     631      *win   = -1;
     632      *apple = -1;
     633  
     634      for ( n = 0; n < face->num_names; n++ )
     635      {
     636        TT_Name  name = face->name_table.names + n;
     637  
     638  
     639        if ( name->nameID == id && name->stringLength > 0 )
     640        {
     641          if ( IS_WIN( name ) && ( name->languageID == 0x409 || *win == -1 ) )
     642            *win = n;
     643  
     644          if ( IS_APPLE( name ) && ( name->languageID == 0 || *apple == -1 ) )
     645            *apple = n;
     646        }
     647      }
     648  
     649      return ( *win >= 0 ) || ( *apple >= 0 );
     650    }
     651  
     652  
     653  #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
     654  
     655    /*
     656        The maximum length of an axis value descriptor.
     657  
     658        We need 65536 different values for the decimal fraction; this fits
     659        nicely into five decimal places.  Consequently, it consists of
     660  
     661          . the minus sign if the number is negative,
     662          . up to five characters for the digits before the decimal point,
     663          . the decimal point if there is a fractional part, and
     664          . up to five characters for the digits after the decimal point.
     665  
     666        We also need one byte for the leading `_' character and up to four
     667        bytes for the axis tag.
     668     */
     669  #define MAX_VALUE_DESCRIPTOR_LEN  ( 1 + 5 + 1 + 5 + 1 + 4 )
     670  
     671  
     672    /* the maximum length of PostScript font names */
     673  #define MAX_PS_NAME_LEN  127
     674  
     675  
     676    /*
     677     * Find the shortest decimal representation of a 16.16 fixed-point
     678     * number.  The function fills `buf' with the result, returning a pointer
     679     * to the position after the representation's last byte.
     680     */
     681  
     682    static char*
     683    fixed2float( FT_Int  fixed,
     684                 char*   buf )
     685    {
     686      char*  p;
     687      char*  q;
     688      char   tmp[5];
     689  
     690      FT_Int  int_part;
     691      FT_Int  frac_part;
     692  
     693      FT_Int  i;
     694  
     695  
     696      p = buf;
     697  
     698      if ( fixed == 0 )
     699      {
     700        *p++ = '0';
     701        return p;
     702      }
     703  
     704      if ( fixed < 0 )
     705      {
     706        *p++ = '-';
     707        fixed = NEG_INT( fixed );
     708      }
     709  
     710      int_part  = ( fixed >> 16 ) & 0xFFFF;
     711      frac_part = fixed & 0xFFFF;
     712  
     713      /* get digits of integer part (in reverse order) */
     714      q = tmp;
     715      while ( int_part > 0 )
     716      {
     717        *q++      = '0' + int_part % 10;
     718        int_part /= 10;
     719      }
     720  
     721      /* copy digits in correct order to buffer */
     722      while ( q > tmp )
     723        *p++ = *--q;
     724  
     725      if ( !frac_part )
     726        return p;
     727  
     728      /* save position of point */
     729      q    = p;
     730      *p++ = '.';
     731  
     732      /* apply rounding */
     733      frac_part = frac_part * 10 + 5;
     734  
     735      /* get digits of fractional part */
     736      for ( i = 0; i < 5; i++ )
     737      {
     738        *p++ = '0' + (char)( frac_part / 0x10000L );
     739  
     740        frac_part %= 0x10000L;
     741        if ( !frac_part )
     742          break;
     743  
     744        frac_part *= 10;
     745      }
     746  
     747      /*
     748          If the remainder stored in `frac_part' (after the last FOR loop) is
     749          smaller than 34480*10, the resulting decimal value minus 0.00001 is
     750          an equivalent representation of `fixed'.
     751  
     752          The above FOR loop always finds the larger of the two values; I
     753          verified this by iterating over all possible fixed-point numbers.
     754  
     755          If the remainder is 17232*10, both values are equally good, and we
     756          take the next even number (following IEEE 754's `round to nearest,
     757          ties to even' rounding rule).
     758  
     759          If the remainder is smaller than 17232*10, the lower of the two
     760          numbers is nearer to the exact result (values 17232 and 34480 were
     761          also found by testing all possible fixed-point values).
     762  
     763          We use this to find a shorter decimal representation.  If not ending
     764          with digit zero, we take the representation with less error.
     765       */
     766      p--;
     767      if ( p - q == 5 )  /* five digits? */
     768      {
     769        /* take the representation that has zero as the last digit */
     770        if ( frac_part < 34480 * 10 &&
     771             *p == '1'              )
     772          *p = '0';
     773  
     774        /* otherwise use the one with less error */
     775        else if ( frac_part == 17232 * 10 &&
     776                  *p & 1                  )
     777          *p -= 1;
     778  
     779        else if ( frac_part < 17232 * 10 &&
     780                  *p != '0'              )
     781          *p -= 1;
     782      }
     783  
     784      /* remove trailing zeros */
     785      while ( *p == '0' )
     786        *p-- = '\0';
     787  
     788      return p + 1;
     789    }
     790  
     791  
     792    static const char  hexdigits[16] =
     793    {
     794      '0', '1', '2', '3', '4', '5', '6', '7',
     795      '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
     796    };
     797  
     798  
     799    static const char*
     800    sfnt_get_var_ps_name( TT_Face  face )
     801    {
     802      FT_Error   error;
     803      FT_Memory  memory = face->root.memory;
     804  
     805      FT_Service_MultiMasters  mm = (FT_Service_MultiMasters)face->mm;
     806  
     807      FT_UInt     num_coords;
     808      FT_Fixed*   coords;
     809      FT_MM_Var*  mm_var;
     810  
     811      FT_Int   found, win, apple;
     812      FT_UInt  i, j;
     813  
     814      char*  result = NULL;
     815      char*  p;
     816  
     817  
     818      if ( !face->var_postscript_prefix )
     819      {
     820        FT_UInt  len;
     821  
     822  
     823        /* check whether we have a Variations PostScript Name Prefix */
     824        found = sfnt_get_name_id( face,
     825                                  TT_NAME_ID_VARIATIONS_PREFIX,
     826                                  &win,
     827                                  &apple );
     828        if ( !found )
     829        {
     830          /* otherwise use the typographic family name */
     831          found = sfnt_get_name_id( face,
     832                                    TT_NAME_ID_TYPOGRAPHIC_FAMILY,
     833                                    &win,
     834                                    &apple );
     835        }
     836  
     837        if ( !found )
     838        {
     839          /* according to the 'name' documentation in the OpenType   */
     840          /* specification the font family name is to be used if the */
     841          /* typographic family name is missing, so let's do that    */
     842          found = sfnt_get_name_id( face,
     843                                    TT_NAME_ID_FONT_FAMILY,
     844                                    &win,
     845                                    &apple );
     846        }
     847  
     848        if ( !found )
     849        {
     850          FT_TRACE0(( "sfnt_get_var_ps_name:"
     851                      " Can't construct PS name prefix for font instances\n" ));
     852          return NULL;
     853        }
     854  
     855        /* prefer Windows entries over Apple */
     856        if ( win != -1 )
     857          result = get_win_string( face->root.memory,
     858                                   face->name_table.stream,
     859                                   face->name_table.names + win,
     860                                   sfnt_is_alphanumeric,
     861                                   0 );
     862        if ( !result && apple != -1 )
     863          result = get_apple_string( face->root.memory,
     864                                     face->name_table.stream,
     865                                     face->name_table.names + apple,
     866                                     sfnt_is_alphanumeric,
     867                                     0 );
     868  
     869        if ( !result )
     870        {
     871          FT_TRACE0(( "sfnt_get_var_ps_name:"
     872                      " No valid PS name prefix for font instances found\n" ));
     873          /* XXX It probably makes sense to never let this fail */
     874          /*     since an arbitrary prefix should work, too.    */
     875          /*     On the other hand, it is very unlikely that    */
     876          /*     we ever reach this code at all.                */
     877          return NULL;
     878        }
     879  
     880        len = ft_strlen( result );
     881  
     882        /* sanitize if necessary; we reserve space for 36 bytes (a 128bit  */
     883        /* checksum as a hex number, preceded by `-' and followed by three */
     884        /* ASCII dots, to be used if the constructed PS name would be too  */
     885        /* long); this is also sufficient for a single instance            */
     886        if ( len > MAX_PS_NAME_LEN - ( 1 + 32 + 3 ) )
     887        {
     888          len         = MAX_PS_NAME_LEN - ( 1 + 32 + 3 );
     889          result[len] = '\0';
     890  
     891          FT_TRACE0(( "sfnt_get_var_ps_name:"
     892                      " Shortening variation PS name prefix\n" ));
     893          FT_TRACE0(( "                     "
     894                      " to %d characters\n", len ));
     895        }
     896  
     897        face->var_postscript_prefix     = result;
     898        face->var_postscript_prefix_len = len;
     899      }
     900  
     901      mm->get_var_blend( FT_FACE( face ),
     902                         &num_coords,
     903                         &coords,
     904                         NULL,
     905                         &mm_var );
     906  
     907      if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) &&
     908           !FT_IS_VARIATION( FT_FACE( face ) )     )
     909      {
     910        SFNT_Service  sfnt = (SFNT_Service)face->sfnt;
     911  
     912        FT_Long  instance = ( ( face->root.face_index & 0x7FFF0000L ) >> 16 ) - 1;
     913        FT_UInt  psid     = mm_var->namedstyle[instance].psid;
     914  
     915        char*  ps_name = NULL;
     916  
     917  
     918        /* try first to load the name string with index `postScriptNameID' */
     919        if ( psid == 6                      ||
     920             ( psid > 255 && psid < 32768 ) )
     921          (void)sfnt->get_name( face, (FT_UShort)psid, &ps_name );
     922  
     923        if ( ps_name )
     924        {
     925          result = ps_name;
     926          p      = result + ft_strlen( result ) + 1;
     927  
     928          goto check_length;
     929        }
     930        else
     931        {
     932          /* otherwise construct a name using `subfamilyNameID' */
     933          FT_UInt  strid = mm_var->namedstyle[instance].strid;
     934  
     935          char*  subfamily_name;
     936          char*  s;
     937  
     938  
     939          (void)sfnt->get_name( face, (FT_UShort)strid, &subfamily_name );
     940  
     941          if ( !subfamily_name )
     942          {
     943            FT_TRACE1(( "sfnt_get_var_ps_name:"
     944                        " can't construct named instance PS name;\n" ));
     945            FT_TRACE1(( "                     "
     946                        " trying to construct normal instance PS name\n" ));
     947            goto construct_instance_name;
     948          }
     949  
     950          /* after the prefix we have character `-' followed by the   */
     951          /* subfamily name (using only characters a-z, A-Z, and 0-9) */
     952          if ( FT_QALLOC( result, face->var_postscript_prefix_len +
     953                                  1 + ft_strlen( subfamily_name ) + 1 ) )
     954            return NULL;
     955  
     956          ft_strcpy( result, face->var_postscript_prefix );
     957  
     958          p = result + face->var_postscript_prefix_len;
     959          *p++ = '-';
     960  
     961          s = subfamily_name;
     962          while ( *s )
     963          {
     964            if ( ft_isalnum( *s ) )
     965              *p++ = *s;
     966            s++;
     967          }
     968          *p++ = '\0';
     969  
     970          FT_FREE( subfamily_name );
     971        }
     972      }
     973      else
     974      {
     975        FT_Var_Axis*  axis;
     976  
     977  
     978      construct_instance_name:
     979        axis = mm_var->axis;
     980  
     981        if ( FT_QALLOC( result,
     982                        face->var_postscript_prefix_len +
     983                          num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) )
     984          return NULL;
     985  
     986        p = result;
     987  
     988        ft_strcpy( p, face->var_postscript_prefix );
     989        p += face->var_postscript_prefix_len;
     990  
     991        for ( i = 0; i < num_coords; i++, coords++, axis++ )
     992        {
     993          char  t;
     994  
     995  
     996          /* omit axis value descriptor if it is identical */
     997          /* to the default axis value                     */
     998          if ( *coords == axis->def )
     999            continue;
    1000  
    1001          *p++ = '_';
    1002          p    = fixed2float( *coords, p );
    1003  
    1004          t = (char)( axis->tag >> 24 );
    1005          if ( t != ' ' && ft_isalnum( t ) )
    1006            *p++ = t;
    1007          t = (char)( axis->tag >> 16 );
    1008          if ( t != ' ' && ft_isalnum( t ) )
    1009            *p++ = t;
    1010          t = (char)( axis->tag >> 8 );
    1011          if ( t != ' ' && ft_isalnum( t ) )
    1012            *p++ = t;
    1013          t = (char)axis->tag;
    1014          if ( t != ' ' && ft_isalnum( t ) )
    1015            *p++ = t;
    1016        }
    1017        *p++ = '\0';
    1018      }
    1019  
    1020    check_length:
    1021      if ( p - result > MAX_PS_NAME_LEN )
    1022      {
    1023        /* the PS name is too long; replace the part after the prefix with */
    1024        /* a checksum; we use MurmurHash 3 with a hash length of 128 bit   */
    1025  
    1026        FT_UInt32  seed = 123456789;
    1027  
    1028        FT_UInt32   hash[4];
    1029        FT_UInt32*  h;
    1030  
    1031  
    1032        murmur_hash_3_128( result, p - result, seed, hash );
    1033  
    1034        p = result + face->var_postscript_prefix_len;
    1035        *p++ = '-';
    1036  
    1037        /* we convert the hash value to hex digits from back to front */
    1038        p += 32 + 3;
    1039        h  = hash + 3;
    1040  
    1041        *p-- = '\0';
    1042        *p-- = '.';
    1043        *p-- = '.';
    1044        *p-- = '.';
    1045  
    1046        for ( i = 0; i < 4; i++, h-- )
    1047        {
    1048          FT_UInt32  v = *h;
    1049  
    1050  
    1051          for ( j = 0; j < 8; j++ )
    1052          {
    1053            *p--   = hexdigits[v & 0xF];
    1054            v    >>= 4;
    1055          }
    1056        }
    1057      }
    1058  
    1059      return result;
    1060    }
    1061  
    1062  #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
    1063  
    1064  
    1065    FT_CALLBACK_DEF( const char* )
    1066    sfnt_get_ps_name( FT_Face  face )    /* TT_Face */
    1067    {
    1068      TT_Face  ttface = (TT_Face)face;
    1069  
    1070      FT_Int       found, win, apple;
    1071      const char*  result = NULL;
    1072  
    1073  
    1074      if ( ttface->postscript_name )
    1075        return ttface->postscript_name;
    1076  
    1077  #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
    1078      if ( ttface->blend                    &&
    1079           ( FT_IS_NAMED_INSTANCE( face ) ||
    1080             FT_IS_VARIATION( face )      ) )
    1081      {
    1082        ttface->postscript_name = sfnt_get_var_ps_name( ttface );
    1083        return ttface->postscript_name;
    1084      }
    1085  #endif
    1086  
    1087      /* scan the name table to see whether we have a Postscript name here, */
    1088      /* either in Macintosh or Windows platform encodings                  */
    1089      found = sfnt_get_name_id( ttface, TT_NAME_ID_PS_NAME, &win, &apple );
    1090      if ( !found )
    1091        return NULL;
    1092  
    1093      /* prefer Windows entries over Apple */
    1094      if ( win != -1 )
    1095        result = get_win_string( FT_FACE_MEMORY( face ),
    1096                                 ttface->name_table.stream,
    1097                                 ttface->name_table.names + win,
    1098                                 sfnt_is_postscript,
    1099                                 1 );
    1100      if ( !result && apple != -1 )
    1101        result = get_apple_string( FT_FACE_MEMORY( face ),
    1102                                   ttface->name_table.stream,
    1103                                   ttface->name_table.names + apple,
    1104                                   sfnt_is_postscript,
    1105                                   1 );
    1106  
    1107      ttface->postscript_name = result;
    1108  
    1109      return result;
    1110    }
    1111  
    1112  
    1113    FT_DEFINE_SERVICE_PSFONTNAMEREC(
    1114      sfnt_service_ps_name,
    1115  
    1116      sfnt_get_ps_name  /* FT_PsName_GetFunc get_ps_font_name */
    1117    )
    1118  
    1119  
    1120    /*
    1121     * TT CMAP INFO
    1122     */
    1123    FT_DEFINE_SERVICE_TTCMAPSREC(
    1124      tt_service_get_cmap_info,
    1125  
    1126      tt_get_cmap_info  /* TT_CMap_Info_GetFunc get_cmap_info */
    1127    )
    1128  
    1129  
    1130  #ifdef TT_CONFIG_OPTION_BDF
    1131  
    1132    static FT_Error
    1133    sfnt_get_charset_id( FT_Face       face,
    1134                         const char*  *acharset_encoding,
    1135                         const char*  *acharset_registry )
    1136    {
    1137      BDF_PropertyRec  encoding, registry;
    1138      FT_Error         error;
    1139  
    1140  
    1141      /* XXX: I don't know whether this is correct, since
    1142       *      tt_face_find_bdf_prop only returns something correct if we have
    1143       *      previously selected a size that is listed in the BDF table.
    1144       *      Should we change the BDF table format to include single offsets
    1145       *      for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
    1146       */
    1147      error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", &registry );
    1148      if ( !error )
    1149      {
    1150        error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
    1151        if ( !error )
    1152        {
    1153          if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
    1154               encoding.type == BDF_PROPERTY_TYPE_ATOM )
    1155          {
    1156            *acharset_encoding = encoding.u.atom;
    1157            *acharset_registry = registry.u.atom;
    1158          }
    1159          else
    1160            error = FT_THROW( Invalid_Argument );
    1161        }
    1162      }
    1163  
    1164      return error;
    1165    }
    1166  
    1167  
    1168    FT_DEFINE_SERVICE_BDFRec(
    1169      sfnt_service_bdf,
    1170  
    1171      sfnt_get_charset_id,   /* FT_BDF_GetCharsetIdFunc get_charset_id */
    1172      tt_face_find_bdf_prop  /* FT_BDF_GetPropertyFunc  get_property   */
    1173    )
    1174  
    1175  
    1176  #endif /* TT_CONFIG_OPTION_BDF */
    1177  
    1178  
    1179    /*
    1180     * SERVICE LIST
    1181     */
    1182  
    1183  #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
    1184    FT_DEFINE_SERVICEDESCREC5(
    1185      sfnt_services,
    1186  
    1187      FT_SERVICE_ID_SFNT_TABLE,           &sfnt_service_sfnt_table,
    1188      FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
    1189      FT_SERVICE_ID_GLYPH_DICT,           &sfnt_service_glyph_dict,
    1190      FT_SERVICE_ID_BDF,                  &sfnt_service_bdf,
    1191      FT_SERVICE_ID_TT_CMAP,              &tt_service_get_cmap_info )
    1192  #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    1193    FT_DEFINE_SERVICEDESCREC4(
    1194      sfnt_services,
    1195  
    1196      FT_SERVICE_ID_SFNT_TABLE,           &sfnt_service_sfnt_table,
    1197      FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
    1198      FT_SERVICE_ID_GLYPH_DICT,           &sfnt_service_glyph_dict,
    1199      FT_SERVICE_ID_TT_CMAP,              &tt_service_get_cmap_info )
    1200  #elif defined TT_CONFIG_OPTION_BDF
    1201    FT_DEFINE_SERVICEDESCREC4(
    1202      sfnt_services,
    1203  
    1204      FT_SERVICE_ID_SFNT_TABLE,           &sfnt_service_sfnt_table,
    1205      FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
    1206      FT_SERVICE_ID_BDF,                  &sfnt_service_bdf,
    1207      FT_SERVICE_ID_TT_CMAP,              &tt_service_get_cmap_info )
    1208  #else
    1209    FT_DEFINE_SERVICEDESCREC3(
    1210      sfnt_services,
    1211  
    1212      FT_SERVICE_ID_SFNT_TABLE,           &sfnt_service_sfnt_table,
    1213      FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
    1214      FT_SERVICE_ID_TT_CMAP,              &tt_service_get_cmap_info )
    1215  #endif
    1216  
    1217  
    1218    FT_CALLBACK_DEF( FT_Module_Interface )
    1219    sfnt_get_interface( FT_Module    module,
    1220                        const char*  module_interface )
    1221    {
    1222      FT_UNUSED( module );
    1223  
    1224      return ft_service_list_lookup( sfnt_services, module_interface );
    1225    }
    1226  
    1227  
    1228  #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
    1229  #define PUT_EMBEDDED_BITMAPS( a )  a
    1230  #else
    1231  #define PUT_EMBEDDED_BITMAPS( a )  NULL
    1232  #endif
    1233  
    1234  #ifdef TT_CONFIG_OPTION_COLOR_LAYERS
    1235  #define PUT_COLOR_LAYERS( a )  a
    1236  #else
    1237  #define PUT_COLOR_LAYERS( a )  NULL
    1238  #endif
    1239  
    1240  #ifdef FT_CONFIG_OPTION_SVG
    1241  #define PUT_SVG_SUPPORT( a )  a
    1242  #else
    1243  #define PUT_SVG_SUPPORT( a )  NULL
    1244  #endif
    1245  
    1246  #define PUT_COLOR_LAYERS_V1( a )  PUT_COLOR_LAYERS( a )
    1247  
    1248  #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
    1249  #define PUT_PS_NAMES( a )  a
    1250  #else
    1251  #define PUT_PS_NAMES( a )  NULL
    1252  #endif
    1253  
    1254    FT_DEFINE_SFNT_INTERFACE(
    1255      sfnt_interface,
    1256  
    1257      tt_face_goto_table,     /* TT_Loader_GotoTableFunc goto_table      */
    1258  
    1259      sfnt_init_face,         /* TT_Init_Face_Func       init_face       */
    1260      sfnt_load_face,         /* TT_Load_Face_Func       load_face       */
    1261      sfnt_done_face,         /* TT_Done_Face_Func       done_face       */
    1262      sfnt_get_interface,     /* FT_Module_Requester     get_interface   */
    1263  
    1264      tt_face_load_any,       /* TT_Load_Any_Func        load_any        */
    1265  
    1266      tt_face_load_head,      /* TT_Load_Table_Func      load_head       */
    1267      tt_face_load_hhea,      /* TT_Load_Metrics_Func    load_hhea       */
    1268      tt_face_load_cmap,      /* TT_Load_Table_Func      load_cmap       */
    1269      tt_face_load_maxp,      /* TT_Load_Table_Func      load_maxp       */
    1270      tt_face_load_os2,       /* TT_Load_Table_Func      load_os2        */
    1271      tt_face_load_post,      /* TT_Load_Table_Func      load_post       */
    1272  
    1273      tt_face_load_name,      /* TT_Load_Table_Func      load_name       */
    1274      tt_face_free_name,      /* TT_Free_Table_Func      free_name       */
    1275  
    1276      tt_face_load_kern,      /* TT_Load_Table_Func      load_kern       */
    1277      tt_face_load_gasp,      /* TT_Load_Table_Func      load_gasp       */
    1278      tt_face_load_pclt,      /* TT_Load_Table_Func      load_init       */
    1279  
    1280      /* see `ttload.h' */
    1281      PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ),
    1282                              /* TT_Load_Table_Func      load_bhed       */
    1283      PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ),
    1284                              /* TT_Load_SBit_Image_Func load_sbit_image */
    1285  
    1286      /* see `ttpost.h' */
    1287      PUT_PS_NAMES( tt_face_get_ps_name   ),
    1288                              /* TT_Get_PS_Name_Func     get_psname      */
    1289      PUT_PS_NAMES( tt_face_free_ps_names ),
    1290                              /* TT_Free_Table_Func      free_psnames    */
    1291  
    1292      /* since version 2.1.8 */
    1293      tt_face_get_kerning,    /* TT_Face_GetKerningFunc  get_kerning     */
    1294  
    1295      /* since version 2.2 */
    1296      tt_face_load_font_dir,  /* TT_Load_Table_Func      load_font_dir   */
    1297      tt_face_load_hmtx,      /* TT_Load_Metrics_Func    load_hmtx       */
    1298  
    1299      /* see `ttsbit.h' and `sfnt.h' */
    1300      PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
    1301                              /* TT_Load_Table_Func      load_eblc       */
    1302      PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
    1303                              /* TT_Free_Table_Func      free_eblc       */
    1304  
    1305      PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike     ),
    1306                    /* TT_Set_SBit_Strike_Func      set_sbit_strike      */
    1307      PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
    1308                    /* TT_Load_Strike_Metrics_Func  load_strike_metrics  */
    1309  
    1310      PUT_COLOR_LAYERS( tt_face_load_cpal ),
    1311                              /* TT_Load_Table_Func      load_cpal       */
    1312      PUT_COLOR_LAYERS( tt_face_load_colr ),
    1313                              /* TT_Load_Table_Func      load_colr       */
    1314      PUT_COLOR_LAYERS( tt_face_free_cpal ),
    1315                              /* TT_Free_Table_Func      free_cpal       */
    1316      PUT_COLOR_LAYERS( tt_face_free_colr ),
    1317                              /* TT_Free_Table_Func      free_colr       */
    1318      PUT_COLOR_LAYERS( tt_face_palette_set ),
    1319                              /* TT_Set_Palette_Func     set_palette     */
    1320      PUT_COLOR_LAYERS( tt_face_get_colr_layer ),
    1321                              /* TT_Get_Colr_Layer_Func  get_colr_layer  */
    1322  
    1323      PUT_COLOR_LAYERS_V1( tt_face_get_colr_glyph_paint ),
    1324                /* TT_Get_Color_Glyph_Paint_Func    get_colr_glyph_paint */
    1325      PUT_COLOR_LAYERS_V1( tt_face_get_color_glyph_clipbox ),
    1326                /* TT_Get_Color_Glyph_ClipBox_Func  get_clipbox          */
    1327      PUT_COLOR_LAYERS_V1( tt_face_get_paint_layers ),
    1328                /* TT_Get_Paint_Layers_Func         get_paint_layers     */
    1329      PUT_COLOR_LAYERS_V1( tt_face_get_colorline_stops ),
    1330                /* TT_Get_Paint                     get_paint            */
    1331      PUT_COLOR_LAYERS_V1( tt_face_get_paint ),
    1332                /* TT_Get_Colorline_Stops_Func      get_colorline_stops  */
    1333  
    1334      PUT_COLOR_LAYERS( tt_face_colr_blend_layer ),
    1335                              /* TT_Blend_Colr_Func      colr_blend      */
    1336  
    1337      tt_face_get_metrics,    /* TT_Get_Metrics_Func     get_metrics     */
    1338  
    1339      tt_face_get_name,       /* TT_Get_Name_Func        get_name        */
    1340      sfnt_get_name_id,       /* TT_Get_Name_ID_Func     get_name_id     */
    1341  
    1342      PUT_SVG_SUPPORT( tt_face_load_svg ),
    1343                              /* TT_Load_Table_Func      load_svg        */
    1344      PUT_SVG_SUPPORT( tt_face_free_svg ),
    1345                              /* TT_Free_Table_Func      free_svg        */
    1346      PUT_SVG_SUPPORT( tt_face_load_svg_doc )
    1347                              /* TT_Load_Svg_Doc_Func    load_svg_doc    */
    1348    )
    1349  
    1350  
    1351    FT_DEFINE_MODULE(
    1352      sfnt_module_class,
    1353  
    1354      0,  /* not a font driver or renderer */
    1355      sizeof ( FT_ModuleRec ),
    1356  
    1357      "sfnt",     /* driver name                            */
    1358      0x10000L,   /* driver version 1.0                     */
    1359      0x20000L,   /* driver requires FreeType 2.0 or higher */
    1360  
    1361      (const void*)&sfnt_interface,  /* module specific interface */
    1362  
    1363      NULL,               /* FT_Module_Constructor module_init   */
    1364      NULL,               /* FT_Module_Destructor  module_done   */
    1365      sfnt_get_interface  /* FT_Module_Requester   get_interface */
    1366    )
    1367  
    1368  
    1369  /* END */