30#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
34#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
39#ifdef FT_CONFIG_OPTION_SVG
43#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
47#ifdef TT_CONFIG_OPTION_BDF
52#ifdef TT_CONFIG_OPTION_GPOS_KERNING
65#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
78#define FT_COMPONENT sfdriver
86 FT_CALLBACK_DEF( FT_Error )
87 sfnt_load_table( FT_Face face,
93 TT_Face ttface = (TT_Face)face;
96 return tt_face_load_any( ttface, tag, offset, buffer, length );
100 FT_CALLBACK_DEF(
void* )
101 get_sfnt_table( FT_Face face,
104 TT_Face ttface = (TT_Face)face;
112 table = &ttface->header;
116 table = &ttface->horizontal;
120 table = ttface->vertical_info ? &ttface->vertical : NULL;
124 table = ( ttface->os2.version == 0xFFFFU ) ? NULL : &ttface->os2;
128 table = &ttface->postscript;
132 table = &ttface->max_profile;
136 table = ttface->pclt.Version ? &ttface->pclt : NULL;
147 FT_CALLBACK_DEF( FT_Error )
148 sfnt_table_info( FT_Face face,
154 TT_Face ttface = (TT_Face)face;
157 if ( !offset || !length )
158 return FT_THROW( Invalid_Argument );
161 *length = ttface->num_tables;
164 if ( idx >= ttface->num_tables )
165 return FT_THROW( Table_Missing );
167 *tag = ttface->dir_tables[idx].Tag;
168 *offset = ttface->dir_tables[idx].Offset;
169 *length = ttface->dir_tables[idx].Length;
176 FT_DEFINE_SERVICE_SFNT_TABLEREC(
177 sfnt_service_sfnt_table,
185#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
192 FT_CALLBACK_DEF( FT_Error )
193 sfnt_get_glyph_name( FT_Face face,
202 error = tt_face_get_ps_name( (TT_Face)face, glyph_index, &gname );
204 FT_STRCPYN( buffer, gname, buffer_max );
210 FT_CALLBACK_DEF( FT_UInt )
211 sfnt_get_name_index( FT_Face face,
212 const FT_String* glyph_name )
214 TT_Face ttface = (TT_Face)face;
216 FT_UInt i, max_gid = FT_UINT_MAX;
219 if ( face->num_glyphs < 0 )
221 else if ( (FT_ULong)face->num_glyphs < FT_UINT_MAX )
222 max_gid = (FT_UInt)face->num_glyphs;
224 FT_TRACE0((
"Ignore glyph names for invalid GID 0x%08x - 0x%08lx\n",
225 FT_UINT_MAX, face->num_glyphs ));
227 for ( i = 0; i < max_gid; i++ )
230 FT_Error error = tt_face_get_ps_name( ttface, i, &gname );
236 if ( !ft_strcmp( glyph_name, gname ) )
244 FT_DEFINE_SERVICE_GLYPHDICTREC(
245 sfnt_service_glyph_dict,
260 static const unsigned char sfnt_ps_map[16] =
275 sfnt_is_postscript(
int c )
280 if ( c < 0 || c >= 0x80 )
283 cc = (
unsigned int)c;
285 return sfnt_ps_map[cc >> 3] & ( 1 << ( cc & 0x07 ) );
289#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
297 sfnt_is_alphanumeric(
int c )
299 return ft_isalnum( c );
306#define ROTL32( x, r ) ( x << r ) | ( x >> ( 32 - r ) )
310 fmix32( FT_UInt32 h )
323 murmur_hash_3_128(
const void* key,
324 const unsigned int len,
328 const FT_Byte* data = (
const FT_Byte*)key;
329 const int nblocks = (int)len / 16;
336 const FT_UInt32 c1 = 0x239b961b;
337 const FT_UInt32 c2 = 0xab0e9789;
338 const FT_UInt32 c3 = 0x38b34ae5;
339 const FT_UInt32 c4 = 0xa1e38b93;
341 const FT_UInt32* blocks = (
const FT_UInt32*)( data + nblocks * 16 );
346 for( i = -nblocks; i; i++ )
348 FT_UInt32 k1 = blocks[i * 4 + 0];
349 FT_UInt32 k2 = blocks[i * 4 + 1];
350 FT_UInt32 k3 = blocks[i * 4 + 2];
351 FT_UInt32 k4 = blocks[i * 4 + 3];
355 k1 = ROTL32( k1, 15 );
359 h1 = ROTL32( h1, 19 );
361 h1 = h1 * 5 + 0x561ccd1b;
364 k2 = ROTL32( k2, 16 );
368 h2 = ROTL32( h2, 17 );
370 h2 = h2 * 5 + 0x0bcaa747;
373 k3 = ROTL32( k3, 17 );
377 h3 = ROTL32( h3, 15 );
379 h3 = h3 * 5 + 0x96cd1c35;
382 k4 = ROTL32( k4, 18 );
386 h4 = ROTL32( h4, 13 );
388 h4 = h4 * 5 + 0x32ac3b17;
392 const FT_Byte* tail = (
const FT_Byte*)( data + nblocks * 16 );
403 k4 ^= (FT_UInt32)tail[14] << 16;
406 k4 ^= (FT_UInt32)tail[13] << 8;
409 k4 ^= (FT_UInt32)tail[12];
411 k4 = ROTL32( k4, 18 );
417 k3 ^= (FT_UInt32)tail[11] << 24;
420 k3 ^= (FT_UInt32)tail[10] << 16;
423 k3 ^= (FT_UInt32)tail[9] << 8;
426 k3 ^= (FT_UInt32)tail[8];
428 k3 = ROTL32( k3, 17 );
434 k2 ^= (FT_UInt32)tail[7] << 24;
437 k2 ^= (FT_UInt32)tail[6] << 16;
440 k2 ^= (FT_UInt32)tail[5] << 8;
443 k2 ^= (FT_UInt32)tail[4];
445 k2 = ROTL32( k2, 16 );
451 k1 ^= (FT_UInt32)tail[3] << 24;
454 k1 ^= (FT_UInt32)tail[2] << 16;
457 k1 ^= (FT_UInt32)tail[1] << 8;
460 k1 ^= (FT_UInt32)tail[0];
462 k1 = ROTL32( k1, 15 );
494 ((FT_UInt32*)out)[0] = h1;
495 ((FT_UInt32*)out)[1] = h2;
496 ((FT_UInt32*)out)[2] = h3;
497 ((FT_UInt32*)out)[3] = h4;
504 typedef int (*char_type_func)(
int c );
508#define IS_WIN( n ) ( (n)->platformID == 3 && \
509 ( (n)->encodingID == 1 || (n)->encodingID == 0 ) )
511#define IS_APPLE( n ) ( (n)->platformID == 1 && \
512 (n)->encodingID == 0 )
515 get_win_string( FT_Memory memory,
518 char_type_func char_type,
519 FT_Bool report_invalid_characters )
529 if ( FT_QALLOC( result, entry->stringLength / 2 + 1 ) )
532 if ( FT_STREAM_SEEK( entry->stringOffset ) ||
533 FT_FRAME_ENTER( entry->stringLength ) )
534 goto get_win_string_error;
536 r = (FT_String*)result;
537 p = (FT_Char*)stream->cursor;
539 for ( len = entry->stringLength / 2; len > 0; len--, p += 2 )
541 if ( p[0] == 0 && char_type( p[1] ) )
545 if ( report_invalid_characters )
546 FT_TRACE0((
"get_win_string:"
547 " Character 0x%X invalid in PS name string\n",
548 ((
unsigned)p[0])*256 + (
unsigned)p[1] ));
559 get_win_string_error:
562 entry->stringLength = 0;
563 entry->stringOffset = 0;
564 FT_FREE( entry->string );
571 get_apple_string( FT_Memory memory,
574 char_type_func char_type,
575 FT_Bool report_invalid_characters )
585 if ( FT_QALLOC( result, entry->stringLength + 1 ) )
588 if ( FT_STREAM_SEEK( entry->stringOffset ) ||
589 FT_FRAME_ENTER( entry->stringLength ) )
590 goto get_apple_string_error;
592 r = (FT_String*)result;
593 p = (FT_Char*)stream->cursor;
595 for ( len = entry->stringLength; len > 0; len--, p++ )
597 if ( char_type( *p ) )
601 if ( report_invalid_characters )
602 FT_TRACE0((
"get_apple_string:"
603 " Character `%c' (0x%X) invalid in PS name string\n",
615 get_apple_string_error:
618 entry->stringOffset = 0;
619 entry->stringLength = 0;
620 FT_FREE( entry->string );
626 FT_CALLBACK_DEF( FT_Bool )
627 sfnt_get_name_id( TT_Face face,
638 for ( n = 0; n < face->num_names; n++ )
640 TT_Name name = face->name_table.names + n;
643 if ( name->nameID ==
id && name->stringLength > 0 )
645 if ( IS_WIN( name ) && ( name->languageID == 0x409 || *win == -1 ) )
648 if ( IS_APPLE( name ) && ( name->languageID == 0 || *apple == -1 ) )
653 return ( *win >= 0 ) || ( *apple >= 0 );
657#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
673#define MAX_VALUE_DESCRIPTOR_LEN ( 1 + 5 + 1 + 5 + 1 + 4 )
677#define MAX_PS_NAME_LEN 127
687 fixed2float( FT_Int fixed,
711 fixed = NEG_INT( fixed );
714 int_part = ( fixed >> 16 ) & 0xFFFF;
715 frac_part = fixed & 0xFFFF;
719 while ( int_part > 0 )
721 *q++ =
'0' + int_part % 10;
737 frac_part = frac_part * 10 + 5;
740 for ( i = 0; i < 5; i++ )
742 *p++ =
'0' + (char)( frac_part / 0x10000L );
744 frac_part %= 0x10000L;
774 if ( frac_part < 34480 * 10 &&
779 else if ( frac_part == 17232 * 10 &&
783 else if ( frac_part < 17232 * 10 &&
796 static const char hexdigits[16] =
798 '0',
'1',
'2',
'3',
'4',
'5',
'6',
'7',
799 '8',
'9',
'A',
'B',
'C',
'D',
'E',
'F'
804 sfnt_get_var_ps_name( TT_Face face )
807 FT_Memory memory = face->root.memory;
809 FT_Service_MultiMasters mm = (FT_Service_MultiMasters)face->mm;
815 FT_Int found, win, apple;
822 if ( !face->var_postscript_prefix )
828 found = sfnt_get_name_id( face,
829 TT_NAME_ID_VARIATIONS_PREFIX,
835 found = sfnt_get_name_id( face,
836 TT_NAME_ID_TYPOGRAPHIC_FAMILY,
846 found = sfnt_get_name_id( face,
847 TT_NAME_ID_FONT_FAMILY,
854 FT_TRACE0((
"sfnt_get_var_ps_name:"
855 " Can't construct PS name prefix for font instances\n" ));
861 result = get_win_string( face->root.memory,
862 face->name_table.stream,
863 face->name_table.names + win,
864 sfnt_is_alphanumeric,
866 if ( !result && apple != -1 )
867 result = get_apple_string( face->root.memory,
868 face->name_table.stream,
869 face->name_table.names + apple,
870 sfnt_is_alphanumeric,
875 FT_TRACE0((
"sfnt_get_var_ps_name:"
876 " No valid PS name prefix for font instances found\n" ));
884 len = ft_strlen( result );
890 if ( len > MAX_PS_NAME_LEN - ( 1 + 32 + 3 ) )
892 len = MAX_PS_NAME_LEN - ( 1 + 32 + 3 );
895 FT_TRACE0((
"sfnt_get_var_ps_name:"
896 " Shortening variation PS name prefix\n" ));
898 " to %u characters\n", len ));
901 face->var_postscript_prefix = result;
902 face->var_postscript_prefix_len = len;
905 mm->get_var_blend( FT_FACE( face ),
911 if ( FT_IS_NAMED_INSTANCE( FT_FACE( face ) ) &&
912 !FT_IS_VARIATION( FT_FACE( face ) ) )
914 SFNT_Service sfnt = (SFNT_Service)face->sfnt;
916 FT_Long instance = ( ( face->root.face_index & 0x7FFF0000L ) >> 16 ) - 1;
917 FT_UInt psid = mm_var->namedstyle[instance].psid;
919 char* ps_name = NULL;
924 ( psid > 255 && psid < 32768 ) )
925 (void)sfnt->get_name( face, (FT_UShort)psid, &ps_name );
930 p = result + ft_strlen( result ) + 1;
937 FT_UInt strid = mm_var->namedstyle[instance].strid;
939 char* subfamily_name;
943 (void)sfnt->get_name( face, (FT_UShort)strid, &subfamily_name );
945 if ( !subfamily_name )
947 FT_TRACE1((
"sfnt_get_var_ps_name:"
948 " can't construct named instance PS name;\n" ));
950 " trying to construct normal instance PS name\n" ));
951 goto construct_instance_name;
956 if ( FT_QALLOC( result, face->var_postscript_prefix_len +
957 1 + ft_strlen( subfamily_name ) + 1 ) )
960 ft_strcpy( result, face->var_postscript_prefix );
962 p = result + face->var_postscript_prefix_len;
968 if ( ft_isalnum( *s ) )
974 FT_FREE( subfamily_name );
982 construct_instance_name:
985 if ( FT_QALLOC( result,
986 face->var_postscript_prefix_len +
987 num_coords * MAX_VALUE_DESCRIPTOR_LEN + 1 ) )
992 ft_strcpy( p, face->var_postscript_prefix );
993 p += face->var_postscript_prefix_len;
995 for ( i = 0; i < num_coords; i++, coords++, axis++ )
1002 if ( *coords == axis->def )
1006 p = fixed2float( *coords, p );
1008 t = (char)( axis->tag >> 24 );
1009 if ( t !=
' ' && ft_isalnum( t ) )
1011 t = (char)( axis->tag >> 16 );
1012 if ( t !=
' ' && ft_isalnum( t ) )
1014 t = (char)( axis->tag >> 8 );
1015 if ( t !=
' ' && ft_isalnum( t ) )
1017 t = (char)axis->tag;
1018 if ( t !=
' ' && ft_isalnum( t ) )
1025 if ( p - result > MAX_PS_NAME_LEN )
1030 FT_UInt32 seed = 123456789;
1036 murmur_hash_3_128( result, p - result, seed, hash );
1038 p = result + face->var_postscript_prefix_len;
1050 for ( i = 0; i < 4; i++, h-- )
1055 for ( j = 0; j < 8; j++ )
1057 *p-- = hexdigits[v & 0xF];
1069 FT_CALLBACK_DEF(
const char* )
1070 sfnt_get_ps_name( FT_Face face )
1072 TT_Face ttface = (TT_Face)face;
1074 FT_Int found, win, apple;
1075 const char* result = NULL;
1078 if ( ttface->postscript_name )
1079 return ttface->postscript_name;
1081#ifdef TT_CONFIG_OPTION_GX_VAR_SUPPORT
1082 if ( ttface->blend &&
1083 ( FT_IS_NAMED_INSTANCE( face ) ||
1084 FT_IS_VARIATION( face ) ) )
1086 ttface->postscript_name = sfnt_get_var_ps_name( ttface );
1087 return ttface->postscript_name;
1093 found = sfnt_get_name_id( ttface, TT_NAME_ID_PS_NAME, &win, &apple );
1099 result = get_win_string( FT_FACE_MEMORY( face ),
1100 ttface->name_table.stream,
1101 ttface->name_table.names + win,
1104 if ( !result && apple != -1 )
1105 result = get_apple_string( FT_FACE_MEMORY( face ),
1106 ttface->name_table.stream,
1107 ttface->name_table.names + apple,
1111 ttface->postscript_name = result;
1117 FT_DEFINE_SERVICE_PSFONTNAMEREC(
1118 sfnt_service_ps_name,
1127 FT_DEFINE_SERVICE_TTCMAPSREC(
1128 tt_service_get_cmap_info,
1134#ifdef TT_CONFIG_OPTION_BDF
1137 sfnt_get_charset_id( FT_Face face,
1138 const char* *acharset_encoding,
1139 const char* *acharset_registry )
1141 BDF_PropertyRec encoding, registry;
1151 error = tt_face_find_bdf_prop( face,
"CHARSET_REGISTRY", ®istry );
1154 error = tt_face_find_bdf_prop( face,
"CHARSET_ENCODING", &encoding );
1157 if ( registry.type == BDF_PROPERTY_TYPE_ATOM &&
1158 encoding.type == BDF_PROPERTY_TYPE_ATOM )
1160 *acharset_encoding = encoding.u.atom;
1161 *acharset_registry = registry.u.atom;
1164 error = FT_THROW( Invalid_Argument );
1172 FT_DEFINE_SERVICE_BDFRec(
1175 sfnt_get_charset_id,
1176 tt_face_find_bdf_prop
1187#if defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES && defined TT_CONFIG_OPTION_BDF
1188 FT_DEFINE_SERVICEDESCREC5(
1191 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table,
1192 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
1193 FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict,
1194 FT_SERVICE_ID_BDF, &sfnt_service_bdf,
1195 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info )
1196#elif defined TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1197 FT_DEFINE_SERVICEDESCREC4(
1200 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table,
1201 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
1202 FT_SERVICE_ID_GLYPH_DICT, &sfnt_service_glyph_dict,
1203 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info )
1204#elif defined TT_CONFIG_OPTION_BDF
1205 FT_DEFINE_SERVICEDESCREC4(
1208 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table,
1209 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
1210 FT_SERVICE_ID_BDF, &sfnt_service_bdf,
1211 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info )
1213 FT_DEFINE_SERVICEDESCREC3(
1216 FT_SERVICE_ID_SFNT_TABLE, &sfnt_service_sfnt_table,
1217 FT_SERVICE_ID_POSTSCRIPT_FONT_NAME, &sfnt_service_ps_name,
1218 FT_SERVICE_ID_TT_CMAP, &tt_service_get_cmap_info )
1222 FT_CALLBACK_DEF( FT_Module_Interface )
1223 sfnt_get_interface( FT_Module module,
1224 const char* module_interface )
1226 FT_UNUSED( module );
1228 return ft_service_list_lookup( sfnt_services, module_interface );
1232#ifdef TT_CONFIG_OPTION_EMBEDDED_BITMAPS
1233#define PUT_EMBEDDED_BITMAPS( a ) a
1235#define PUT_EMBEDDED_BITMAPS( a ) NULL
1238#ifdef TT_CONFIG_OPTION_COLOR_LAYERS
1239#define PUT_COLOR_LAYERS( a ) a
1241#define PUT_COLOR_LAYERS( a ) NULL
1244#ifdef FT_CONFIG_OPTION_SVG
1245#define PUT_SVG_SUPPORT( a ) a
1247#define PUT_SVG_SUPPORT( a ) NULL
1250#define PUT_COLOR_LAYERS_V1( a ) PUT_COLOR_LAYERS( a )
1252#ifdef TT_CONFIG_OPTION_POSTSCRIPT_NAMES
1253#define PUT_PS_NAMES( a ) a
1255#define PUT_PS_NAMES( a ) NULL
1258#ifdef TT_CONFIG_OPTION_GPOS_KERNING
1259#define PUT_GPOS_KERNING( a ) a
1261#define PUT_GPOS_KERNING( a ) NULL
1264 FT_DEFINE_SFNT_INTERFACE(
1287 PUT_GPOS_KERNING( tt_face_load_gpos ),
1293 PUT_EMBEDDED_BITMAPS( tt_face_load_bhed ),
1295 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit_image ),
1299 PUT_PS_NAMES( tt_face_get_ps_name ),
1301 PUT_PS_NAMES( tt_face_free_ps_names ),
1305 tt_face_get_kerning,
1307 PUT_GPOS_KERNING( tt_face_get_gpos_kerning ),
1311 tt_face_load_font_dir,
1315 PUT_EMBEDDED_BITMAPS( tt_face_load_sbit ),
1317 PUT_EMBEDDED_BITMAPS( tt_face_free_sbit ),
1320 PUT_EMBEDDED_BITMAPS( tt_face_set_sbit_strike ),
1322 PUT_EMBEDDED_BITMAPS( tt_face_load_strike_metrics ),
1325 PUT_COLOR_LAYERS( tt_face_load_cpal ),
1327 PUT_COLOR_LAYERS( tt_face_load_colr ),
1329 PUT_COLOR_LAYERS( tt_face_free_cpal ),
1331 PUT_COLOR_LAYERS( tt_face_free_colr ),
1333 PUT_COLOR_LAYERS( tt_face_palette_set ),
1335 PUT_COLOR_LAYERS( tt_face_get_colr_layer ),
1338 PUT_COLOR_LAYERS_V1( tt_face_get_colr_glyph_paint ),
1340 PUT_COLOR_LAYERS_V1( tt_face_get_color_glyph_clipbox ),
1342 PUT_COLOR_LAYERS_V1( tt_face_get_paint_layers ),
1344 PUT_COLOR_LAYERS_V1( tt_face_get_colorline_stops ),
1346 PUT_COLOR_LAYERS_V1( tt_face_get_paint ),
1349 PUT_COLOR_LAYERS( tt_face_colr_blend_layer ),
1352 tt_face_get_metrics,
1357 PUT_SVG_SUPPORT( tt_face_load_svg ),
1359 PUT_SVG_SUPPORT( tt_face_free_svg ),
1361 PUT_SVG_SUPPORT( tt_face_load_svg_doc )
1370 sizeof ( FT_ModuleRec ),
1376 (
const void*)&sfnt_interface,