1 /***************************************************************************/
5 /* High-level SFNT driver interface (body). */
7 /* Copyright 1996-2017 by */
8 /* David Turner, Robert Wilhelm, and Werner Lemberg. */
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. */
16 /***************************************************************************/
20 #include FT_INTERNAL_DEBUG_H
21 #include FT_INTERNAL_SFNT_H
22 #include FT_INTERNAL_OBJECTS_H
23 #include FT_TRUETYPE_IDS_H
32 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
36 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
40 #ifdef TT_CONFIG_OPTION_BDF
42 #include FT_SERVICE_BDF_H
49 #include FT_SERVICE_GLYPH_DICT_H
50 #include FT_SERVICE_POSTSCRIPT_NAME_H
51 #include FT_SERVICE_SFNT_H
52 #include FT_SERVICE_TT_CMAP_H
54 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
55 #include FT_MULTIPLE_MASTERS_H
56 #include FT_SERVICE_MULTIPLE_MASTERS_H
60 /*************************************************************************/
62 /* The macro FT_COMPONENT is used in trace mode. It is an implicit */
63 /* parameter of the FT_TRACE() and FT_ERROR() macros, used to print/log */
64 /* messages during execution. */
67 #define FT_COMPONENT trace_sfdriver
76 get_sfnt_table( TT_Face face,
85 table = &face->header;
89 table = &face->horizontal;
93 table = face->vertical_info ? &face->vertical : NULL;
97 table = ( face->os2.version == 0xFFFFU ) ? NULL : &face->os2;
101 table = &face->postscript;
105 table = &face->max_profile;
109 table = face->pclt.Version ? &face->pclt : NULL;
121 sfnt_table_info( TT_Face face,
127 if ( !offset || !length )
128 return FT_THROW( Invalid_Argument );
131 *length = face->num_tables;
134 if ( idx >= face->num_tables )
135 return FT_THROW( Table_Missing );
137 *tag = face->dir_tables[idx].Tag;
138 *offset = face->dir_tables[idx].Offset;
139 *length = face->dir_tables[idx].Length;
146 FT_DEFINE_SERVICE_SFNT_TABLEREC(
147 sfnt_service_sfnt_table,
149 (FT_SFNT_TableLoadFunc)tt_face_load_any, /* load_table */
150 (FT_SFNT_TableGetFunc) get_sfnt_table, /* get_table */
151 (FT_SFNT_TableInfoFunc)sfnt_table_info /* table_info */
155 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
163 sfnt_get_glyph_name( FT_Face face,
172 error = tt_face_get_ps_name( (TT_Face)face, glyph_index, &gname );
174 FT_STRCPYN( buffer, gname, buffer_max );
181 sfnt_get_name_index( FT_Face face,
182 FT_String* glyph_name )
184 TT_Face ttface = (TT_Face)face;
186 FT_UInt i, max_gid = FT_UINT_MAX;
189 if ( face->num_glyphs < 0 )
191 else if ( (FT_ULong)face->num_glyphs < FT_UINT_MAX )
192 max_gid = (FT_UInt)face->num_glyphs;
194 FT_TRACE0(( "Ignore glyph names for invalid GID 0x%08x - 0x%08x\n",
195 FT_UINT_MAX, face->num_glyphs ));
197 for ( i = 0; i < max_gid; i++ )
200 FT_Error error = tt_face_get_ps_name( ttface, i, &gname );
206 if ( !ft_strcmp( glyph_name, gname ) )
214 FT_DEFINE_SERVICE_GLYPHDICTREC(
215 sfnt_service_glyph_dict,
217 (FT_GlyphDict_GetNameFunc) sfnt_get_glyph_name, /* get_name */
218 (FT_GlyphDict_NameIndexFunc)sfnt_get_name_index /* name_index */
221 #endif /* TT_CONFIG_OPTION_POSTSCRIPT_NAMES */
225 * POSTSCRIPT NAME SERVICE
229 /* an array representing allowed ASCII characters in a PS string */
230 static const unsigned char sfnt_ps_map[16] =
233 0x00, 0x00, /* 0x00: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */
234 0x00, 0x00, /* 0x10: 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 */
235 0xDE, 0x7C, /* 0x20: 1 1 0 1 1 1 1 0 0 1 1 1 1 1 0 0 */
236 0xFF, 0xAF, /* 0x30: 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 1 */
237 0xFF, 0xFF, /* 0x40: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */
238 0xFF, 0xD7, /* 0x50: 1 1 1 1 1 1 1 1 1 1 0 1 0 1 1 1 */
239 0xFF, 0xFF, /* 0x60: 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 1 */
240 0xFF, 0x57 /* 0x70: 1 1 1 1 1 1 1 1 0 1 0 1 0 1 1 1 */
245 sfnt_is_postscript( int c )
250 if ( c < 0 || c >= 0x80 )
253 cc = (unsigned int)c;
255 return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) );
259 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
261 /* Only ASCII letters and digits are taken for a variation font */
262 /* instance's PostScript name. */
264 /* `ft_isalnum' is a macro, but we need a function here, thus */
265 /* this definition. */
267 sfnt_is_alphanumeric( int c )
269 return ft_isalnum( c );
273 /* the implementation of MurmurHash3 is taken and adapted from */
274 /* https://github.com/aappleby/smhasher/blob/master/src/MurmurHash3.cpp */
276 #define ROTL32( x, r ) ( x << r ) | ( x >> ( 32 - r ) )
280 fmix32( FT_UInt32 h )
293 murmur_hash_3_128( const void* key,
294 const unsigned int len,
298 const FT_Byte* data = (const FT_Byte*)key;
299 const int nblocks = (int)len / 16;
306 const FT_UInt32 c1 = 0x239b961b;
307 const FT_UInt32 c2 = 0xab0e9789;
308 const FT_UInt32 c3 = 0x38b34ae5;
309 const FT_UInt32 c4 = 0xa1e38b93;
311 const FT_UInt32* blocks = (const FT_UInt32*)( data + nblocks * 16 );
316 for( i = -nblocks; i; i++ )
318 FT_UInt32 k1 = blocks[i * 4 + 0];
319 FT_UInt32 k2 = blocks[i * 4 + 1];
320 FT_UInt32 k3 = blocks[i * 4 + 2];
321 FT_UInt32 k4 = blocks[i * 4 + 3];
325 k1 = ROTL32( k1, 15 );
329 h1 = ROTL32( h1, 19 );
331 h1 = h1 * 5 + 0x561ccd1b;
334 k2 = ROTL32( k2, 16 );
338 h2 = ROTL32( h2, 17 );
340 h2 = h2 * 5 + 0x0bcaa747;
343 k3 = ROTL32( k3, 17 );
347 h3 = ROTL32( h3, 15 );
349 h3 = h3 * 5 + 0x96cd1c35;
352 k4 = ROTL32( k4, 18 );
356 h4 = ROTL32( h4, 13 );
358 h4 = h4 * 5 + 0x32ac3b17;
362 const FT_Byte* tail = (const FT_Byte*)( data + nblocks * 16 );
373 k4 ^= (FT_UInt32)tail[14] << 16;
375 k4 ^= (FT_UInt32)tail[13] << 8;
377 k4 ^= (FT_UInt32)tail[12];
379 k4 = ROTL32( k4, 18 );
384 k3 ^= (FT_UInt32)tail[11] << 24;
386 k3 ^= (FT_UInt32)tail[10] << 16;
388 k3 ^= (FT_UInt32)tail[9] << 8;
390 k3 ^= (FT_UInt32)tail[8];
392 k3 = ROTL32( k3, 17 );
397 k2 ^= (FT_UInt32)tail[7] << 24;
399 k2 ^= (FT_UInt32)tail[6] << 16;
401 k2 ^= (FT_UInt32)tail[5] << 8;
403 k2 ^= (FT_UInt32)tail[4];
405 k2 = ROTL32( k2, 16 );
410 k1 ^= (FT_UInt32)tail[3] << 24;
412 k1 ^= (FT_UInt32)tail[2] << 16;
414 k1 ^= (FT_UInt32)tail[1] << 8;
416 k1 ^= (FT_UInt32)tail[0];
418 k1 = ROTL32( k1, 15 );
450 ((FT_UInt32*)out)[0] = h1;
451 ((FT_UInt32*)out)[1] = h2;
452 ((FT_UInt32*)out)[2] = h3;
453 ((FT_UInt32*)out)[3] = h4;
457 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
460 typedef int (*char_type_func)( int c );
463 /* handling of PID/EID 3/0 and 3/1 is the same */
464 #define IS_WIN( n ) ( (n)->platformID == 3 && \
465 ( (n)->encodingID == 1 || (n)->encodingID == 0 ) && \
466 (n)->languageID == 0x409 )
468 #define IS_APPLE( n ) ( (n)->platformID == 1 && \
469 (n)->encodingID == 0 && \
470 (n)->languageID == 0 )
473 get_win_string( FT_Memory memory,
476 char_type_func char_type,
477 FT_Bool report_invalid_characters )
479 FT_Error error = FT_Err_Ok;
489 if ( FT_ALLOC( result, entry->stringLength / 2 + 1 ) )
492 if ( FT_STREAM_SEEK( entry->stringOffset ) ||
493 FT_FRAME_ENTER( entry->stringLength ) )
496 entry->stringLength = 0;
497 entry->stringOffset = 0;
498 FT_FREE( entry->string );
503 r = (FT_String*)result;
504 p = (FT_Char*)stream->cursor;
506 for ( len = entry->stringLength / 2; len > 0; len--, p += 2 )
510 if ( char_type( p[1] ) )
514 if ( report_invalid_characters )
516 FT_TRACE0(( "get_win_string:"
517 " Character `%c' (0x%X) invalid in PS name string\n",
519 /* it's not the job of FreeType to correct PS names... */
534 get_apple_string( FT_Memory memory,
537 char_type_func char_type,
538 FT_Bool report_invalid_characters )
540 FT_Error error = FT_Err_Ok;
550 if ( FT_ALLOC( result, entry->stringLength + 1 ) )
553 if ( FT_STREAM_SEEK( entry->stringOffset ) ||
554 FT_FRAME_ENTER( entry->stringLength ) )
557 entry->stringOffset = 0;
558 entry->stringLength = 0;
559 FT_FREE( entry->string );
564 r = (FT_String*)result;
565 p = (FT_Char*)stream->cursor;
567 for ( len = entry->stringLength; len > 0; len--, p++ )
569 if ( char_type( *p ) )
573 if ( report_invalid_characters )
575 FT_TRACE0(( "get_apple_string:"
576 " Character `%c' (0x%X) invalid in PS name string\n",
578 /* it's not the job of FreeType to correct PS names... */
592 sfnt_get_name_id( TT_Face face,
603 for ( n = 0; n < face->num_names; n++ )
605 TT_Name name = face->name_table.names + n;
608 if ( name->nameID == id && name->stringLength > 0 )
610 if ( IS_WIN( name ) )
613 if ( IS_APPLE( name ) )
618 return ( *win >= 0 ) || ( *apple >= 0 );
622 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
625 The maximum length of an axis value descriptor.
627 We need 65536 different values for the decimal fraction; this fits
628 nicely into five decimal places. Consequently, it consists of
630 . the minus sign if the number is negative,
631 . up to five characters for the digits before the decimal point,
632 . the decimal point if there is a fractional part, and
633 . up to five characters for the digits after the decimal point.
635 We also need one byte for the leading `_' character and up to four
636 bytes for the axis tag.
638 #define MAX_VALUE_DESCRIPTOR_LEN ( 1 + 5 + 1 + 5 + 1 + 4 )
641 /* the maximum length of PostScript font names */
642 #define MAX_PS_NAME_LEN 127
646 * Find the shortest decimal representation of a 16.16 fixed point
647 * number. The function fills `buf' with the result, returning a pointer
648 * to the position after the representation's last byte.
652 fixed2float( FT_Int fixed,
679 int_part = ( fixed >> 16 ) & 0xFFFF;
680 frac_part = fixed & 0xFFFF;
682 /* get digits of integer part (in reverse order) */
684 while ( int_part > 0 )
686 *q++ = '0' + int_part % 10;
690 /* copy digits in correct order to buffer */
697 /* save position of point */
702 frac_part = frac_part * 10 + 5;
704 /* get digits of fractional part */
705 for ( i = 0; i < 5; i++ )
707 *p++ = '0' + (char)( frac_part / 0x10000L );
709 frac_part %= 0x10000L;
717 If the remainder stored in `frac_part' (after the last FOR loop) is
718 smaller than 34480*10, the resulting decimal value minus 0.00001 is
719 an equivalent representation of `fixed'.
721 The above FOR loop always finds the larger of the two values; I
722 verified this by iterating over all possible fixed point numbers.
724 If the remainder is 17232*10, both values are equally good, and we
725 take the next even number (following IEEE 754's `round to nearest,
726 ties to even' rounding rule).
728 If the remainder is smaller than 17232*10, the lower of the two
729 numbers is nearer to the exact result (values 17232 and 34480 were
730 also found by testing all possible fixed point values).
732 We use this to find a shorter decimal representation. If not ending
733 with digit zero, we take the representation with less error.
736 if ( p - q == 5 ) /* five digits? */
738 /* take the representation that has zero as the last digit */
739 if ( frac_part < 34480 * 10 &&
743 /* otherwise use the one with less error */
744 else if ( frac_part == 17232 * 10 &&
748 else if ( frac_part < 17232 * 10 &&
753 /* remove trailing zeros */
761 static const char hexdigits[16] =
763 '0', '1', '2', '3', '4', '5', '6', '7',
764 '8', '9', 'A', 'B', 'C', 'D', 'E', 'F'
769 sfnt_get_var_ps_name( TT_Face face )
772 FT_Memory memory = face->root.memory;
774 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
780 FT_Int found, win, apple;
787 if ( !face->var_postscript_prefix )
792 /* check whether we have a Variations PostScript Name Prefix */
793 found = sfnt_get_name_id( face,
794 TT_NAME_ID_VARIATIONS_PREFIX,
799 /* otherwise use the typographic family name */
800 found = sfnt_get_name_id( face,
801 TT_NAME_ID_TYPOGRAPHIC_FAMILY,
808 /* as a last resort we try the family name; note that this is */
809 /* not in the Adobe TechNote, but GX fonts (which predate the */
810 /* TechNote) benefit from this behaviour */
811 found = sfnt_get_name_id( face,
812 TT_NAME_ID_FONT_FAMILY,
819 FT_TRACE0(( "sfnt_get_var_ps_name:"
820 " Can't construct PS name prefix for font instances\n" ));
824 /* prefer Windows entries over Apple */
826 result = get_win_string( face->root.memory,
827 face->name_table.stream,
828 face->name_table.names + win,
829 sfnt_is_alphanumeric,
832 result = get_apple_string( face->root.memory,
833 face->name_table.stream,
834 face->name_table.names + apple,
835 sfnt_is_alphanumeric,
838 len = ft_strlen( result );
840 /* sanitize if necessary; we reserve space for 36 bytes (a 128bit */
841 /* checksum as a hex number, preceded by `-' and followed by three */
842 /* ASCII dots, to be used if the constructed PS name would be too */
843 /* long); this is also sufficient for a single instance */
844 if ( len > MAX_PS_NAME_LEN - ( 1 + 32 + 3 ) )
846 len = MAX_PS_NAME_LEN - ( 1 + 32 + 3 );
849 FT_TRACE0(( "sfnt_get_var_ps_name:"
850 " Shortening variation PS name prefix\n"
852 " to %d characters\n", len ));
855 face->var_postscript_prefix = result;
856 face->var_postscript_prefix_len = len;
859 mm->get_var_blend( FT_FACE( face ),
865 if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) )
867 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
869 FT_Long instance = ( ( face->root.face_index & 0x7FFF0000L ) >> 16 ) - 1;
870 FT_UInt psid = mm_var->namedstyle[instance].psid;
872 char* ps_name = NULL;
875 /* try first to load the name string with index `postScriptNameID' */
877 ( psid > 255 && psid < 32768 ) )
878 (void)sfnt->get_name( face, (FT_UShort)psid, &ps_name );
883 p = result + ft_strlen( result ) + 1;
889 /* otherwise construct a name using `subfamilyNameID' */
890 FT_UInt strid = mm_var->namedstyle[instance].strid;
892 char* subfamily_name;
896 (void)sfnt->get_name( face, (FT_UShort)strid, &subfamily_name );
898 if ( !subfamily_name )
900 FT_TRACE1(( "sfnt_get_var_ps_name:"
901 " can't construct named instance PS name;\n"
903 " trying to construct normal instance PS name\n" ));
904 goto construct_instance_name;
907 /* after the prefix we have character `-' followed by the */
908 /* subfamily name (using only characters a-z, A-Z, and 0-9) */
909 if ( FT_ALLOC( result, face->var_postscript_prefix_len +
910 1 + ft_strlen( subfamily_name ) + 1 ) )
913 ft_strcpy( result, face->var_postscript_prefix );
915 p = result + face->var_postscript_prefix_len;
921 if ( ft_isalnum( *s ) )
927 FT_FREE( subfamily_name );
935 construct_instance_name:
938 if ( FT_ALLOC( result,
939 face->var_postscript_prefix_len +
940 num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) )
945 ft_strcpy( p, face->var_postscript_prefix );
946 p += face->var_postscript_prefix_len;
948 for ( i = 0; i < num_coords; i++, coords++, axis++ )
953 /* omit axis value descriptor if it is identical */
954 /* to the default axis value */
955 if ( *coords == axis->def )
959 p = fixed2float( *coords, p );
961 t = (char)( axis->tag >> 24 );
962 if ( t != ' ' && ft_isalnum( t ) )
964 t = (char)( axis->tag >> 16 );
965 if ( t != ' ' && ft_isalnum( t ) )
967 t = (char)( axis->tag >> 8 );
968 if ( t != ' ' && ft_isalnum( t ) )
971 if ( t != ' ' && ft_isalnum( t ) )
977 if ( p - result > MAX_PS_NAME_LEN )
979 /* the PS name is too long; replace the part after the prefix with */
980 /* a checksum; we use MurmurHash 3 with a hash length of 128 bit */
982 FT_UInt32 seed = 123456789;
988 murmur_hash_3_128( result, p - result, seed, hash );
990 p = result + face->var_postscript_prefix_len;
993 /* we convert the hash value to hex digits from back to front */
1002 for ( i = 0; i < 4; i++, h-- )
1007 for ( j = 0; j < 8; j++ )
1009 *p-- = hexdigits[v & 0xF];
1018 #endif /* TT_CONFIG_OPTION_GX_VAR_SUPPORT */
1022 sfnt_get_ps_name( TT_Face face )
1024 FT_Int found, win, apple;
1025 const char* result = NULL;
1028 if ( face->postscript_name )
1029 return face->postscript_name;
1031 #ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1034 face->postscript_name = sfnt_get_var_ps_name( face );
1035 return face->postscript_name;
1039 /* scan the name table to see whether we have a Postscript name here, */
1040 /* either in Macintosh or Windows platform encodings */
1041 found = sfnt_get_name_id( face, TT_NAME_ID_PS_NAME, &win, &apple );
1045 /* prefer Windows entries over Apple */
1047 result = get_win_string( face->root.memory,
1048 face->name_table.stream,
1049 face->name_table.names + win,
1053 result = get_apple_string( face->root.memory,
1054 face->name_table.stream,
1055 face->name_table.names + apple,
1059 face->postscript_name = result;
1065 FT_DEFINE_SERVICE_PSFONTNAMEREC(
1066 sfnt_service_ps_name,
1068 (FT_PsName_GetFunc)sfnt_get_ps_name /* get_ps_font_name */
1075 FT_DEFINE_SERVICE_TTCMAPSREC(
1076 tt_service_get_cmap_info,
1078 (TT_CMap_Info_GetFunc)tt_get_cmap_info /* get_cmap_info */
1082 #ifdef TT_CONFIG_OPTION_BDF
1085 sfnt_get_charset_id( TT_Face face,
1086 const char* *acharset_encoding,
1087 const char* *acharset_registry )
1089 BDF_PropertyRec encoding, registry;
1093 /* XXX: I don't know whether this is correct, since
1094 * tt_face_find_bdf_prop only returns something correct if we have
1095 * previously selected a size that is listed in the BDF table.
1096 * Should we change the BDF table format to include single offsets
1097 * for `CHARSET_REGISTRY' and `CHARSET_ENCODING'?
1099 error = tt_face_find_bdf_prop( face, "CHARSET_REGISTRY", ®istry );
1102 error = tt_face_find_bdf_prop( face, "CHARSET_ENCODING", &encoding );
1105 if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
1106 encoding.type == BDF_PROPERTY_TYPE_ATOM )
1108 *acharset_encoding = encoding.u.atom;
1109 *acharset_registry = registry.u.atom;
1112 error = FT_THROW( Invalid_Argument );
1120 FT_DEFINE_SERVICE_BDFRec(
1123 (FT_BDF_GetCharsetIdFunc)sfnt_get_charset_id, /* get_charset_id */
1124 (FT_BDF_GetPropertyFunc) tt_face_find_bdf_prop /* get_property */
1128 #endif /* TT_CONFIG_OPTION_BDF */
1135 #if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
1136 FT_DEFINE_SERVICEDESCREC5(
1139 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
1140 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
1141 FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET,
1142 FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET,
1143 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
1144 #elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1145 FT_DEFINE_SERVICEDESCREC4(
1148 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
1149 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
1150 FT_SERVICE_ID_GLYPH_DICT, &SFNT_SERVICE_GLYPH_DICT_GET,
1151 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
1152 #elif defined TT_CONFIG_OPTION_BDF
1153 FT_DEFINE_SERVICEDESCREC4(
1156 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
1157 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
1158 FT_SERVICE_ID_BDF, &SFNT_SERVICE_BDF_GET,
1159 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
1161 FT_DEFINE_SERVICEDESCREC3(
1164 FT_SERVICE_ID_SFNT_TABLE, &SFNT_SERVICE_SFNT_TABLE_GET,
1165 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &SFNT_SERVICE_PS_NAME_GET,
1166 FT_SERVICE_ID_TT_CMAP, &TT_SERVICE_CMAP_INFO_GET )
1170 FT_CALLBACK_DEF( FT_Module_Interface )
1171 sfnt_get_interface( FT_Module module,
1172 const char* module_interface )
1174 /* SFNT_SERVICES_GET dereferences `library' in PIC mode */
1175 #ifdef FT_CONFIG_OPTION_PIC
1181 library = module->library;
1185 FT_UNUSED( module );
1188 return ft_service_list_lookup( SFNT_SERVICES_GET, module_interface );
1192 #ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1193 #define PUT_EMBEDDED_BITMAPS( a ) a
1195 #define PUT_EMBEDDED_BITMAPS( a ) NULL
1198 #ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1199 #define PUT_PS_NAMES( a ) a
1201 #define PUT_PS_NAMES( a ) NULL
1204 FT_DEFINE_SFNT_INTERFACE(
1207 tt_face_goto_table, /* TT_Loader_GotoTableFunc goto_table */
1209 sfnt_init_face, /* TT_Init_Face_Func init_face */
1210 sfnt_load_face, /* TT_Load_Face_Func load_face */
1211 sfnt_done_face, /* TT_Done_Face_Func done_face */
1212 sfnt_get_interface, /* FT_Module_Requester get_interface */
1214 tt_face_load_any, /* TT_Load_Any_Func load_any */
1216 tt_face_load_head, /* TT_Load_Table_Func load_head */
1217 tt_face_load_hhea, /* TT_Load_Metrics_Func load_hhea */
1218 tt_face_load_cmap, /* TT_Load_Table_Func load_cmap */
1219 tt_face_load_maxp, /* TT_Load_Table_Func load_maxp */
1220 tt_face_load_os2, /* TT_Load_Table_Func load_os2 */
1221 tt_face_load_post, /* TT_Load_Table_Func load_post */
1223 tt_face_load_name, /* TT_Load_Table_Func load_name */
1224 tt_face_free_name, /* TT_Free_Table_Func free_name */
1226 tt_face_load_kern, /* TT_Load_Table_Func load_kern */
1227 tt_face_load_gasp, /* TT_Load_Table_Func load_gasp */
1228 tt_face_load_pclt, /* TT_Load_Table_Func load_init */
1230 /* see `ttload.h' */
1231 PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ),
1232 /* TT_Load_Table_Func load_bhed */
1233 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ),
1234 /* TT_Load_SBit_Image_Func load_sbit_image */
1236 /* see `ttpost.h' */
1237 PUT_PS_NAMES( tt_face_get_ps_name ),
1238 /* TT_Get_PS_Name_Func get_psname */
1239 PUT_PS_NAMES( tt_face_free_ps_names ),
1240 /* TT_Free_Table_Func free_psnames */
1242 /* since version 2.1.8 */
1243 tt_face_get_kerning, /* TT_Face_GetKerningFunc get_kerning */
1245 /* since version 2.2 */
1246 tt_face_load_font_dir, /* TT_Load_Table_Func load_font_dir */
1247 tt_face_load_hmtx, /* TT_Load_Metrics_Func load_hmtx */
1249 /* see `ttsbit.h' and `sfnt.h' */
1250 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
1251 /* TT_Load_Table_Func load_eblc */
1252 PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
1253 /* TT_Free_Table_Func free_eblc */
1255 PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ),
1256 /* TT_Set_SBit_Strike_Func set_sbit_strike */
1257 PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
1258 /* TT_Load_Strike_Metrics_Func load_strike_metrics */
1260 tt_face_get_metrics, /* TT_Get_Metrics_Func get_metrics */
1262 tt_face_get_name, /* TT_Get_Name_Func get_name */
1263 sfnt_get_name_id /* TT_Get_Name_ID_Func get_name_id */
1270 0, /* not a font driver or renderer */
1271 sizeof ( FT_ModuleRec ),
1273 "sfnt", /* driver name */
1274 0x10000L, /* driver version 1.0 */
1275 0x20000L, /* driver requires FreeType 2.0 or higher */
1277 (const void*)&SFNT_INTERFACE_GET, /* module specific interface */
1279 (FT_Module_Constructor)NULL, /* module_init */
1280 (FT_Module_Destructor) NULL, /* module_done */
1281 (FT_Module_Requester) sfnt_get_interface /* get_interface */