1 /****************************************************************************/
3 /* The FreeType project -- a free and portable quality TrueType renderer. */
5 /* Copyright 1996-1999 by */
6 /* D. Turner, R.Wilhelm, and W. Lemberg */
8 /* ftdump: Simple TrueType font file resource profiler. */
10 /* This program dumps various properties of a given font file. */
14 /* NOTE: This is just a test program that is used to show off and */
15 /* debug the current engine. */
17 /****************************************************************************/
23 #include "common.h" /* for Panic() etc. */
26 #include "ftxopen.h" /* TrueType Open support */
27 #include "ftxsbit.h" /* embedded bitmap support */
30 * The following comment should be ignored. The "ttobjs.h" file does
31 * already include ft_conf.h.
33 * ------------------------------------------------------------------
35 * IGNORE> Basically, an external program using FreeType shouldn't depend on an
36 * IGNORE> internal file of the FreeType library, especially not on ft_conf.h -- but
37 * IGNORE> to avoid another configure script which tests for the existence of the
38 * IGNORE> i18n stuff we include ft_conf.h here since we can be sure that our test
39 * IGNORE> programs use the same configuration options as the library itself.
42 #include "ttobjs.h" /* We're going to access internal tables directly */
53 #define gettext( x ) ( x )
64 TT_Instance_Metrics imetrics
;
66 TT_Glyph_Metrics metrics
;
68 TT_Face_Properties properties
;
78 int flag_encodings
= 1;
85 /* If the library is linked as a DLL, TTMemory_Allocated() */
86 /* (which is not exported) cannot be accessed. */
87 /* In this case, some compilers report an error because */
88 /* they try to link against a non-existing symbol. */
90 /* We thus avoid the external reference on these compilers. */
92 #define TTMemory_Allocated 0L
95 extern long TTMemory_Allocated
;
98 long org_memory
, old_memory
, cur_memory
;
100 const char* Apple_Encodings
[33] =
102 "Roman", "Japanese", "Chinese", "Korean", "Arabic", "Hebrew",
103 "Greek", "Russian", "RSymbol", "Devanagari", "Gurmukhi",
104 "Gujarati", "Oriya", "Bengali", "Tamil", "Telugu", "Kannada",
105 "Malayalam", "Sinhalese", "Burmese", "Khmer", "Tai", "Laotian",
106 "Georgian", "Armenian", "Maldivian/Simplif. Chinese", "Tibetan",
107 "Mongolian", "Geez", "Slavic", "Vietnamese", "Sindhi", "Uninterpreted"
112 long initial_overhead
;
116 long second_instance
;
121 /* We ignore error message strings with this function */
123 #ifndef HAVE_LIBINTL_H
125 TT_ErrToString18( TT_Error error
)
127 static char temp
[32];
130 sprintf( temp
, "0x%04lx", error
);
137 Save_Memory( long* var
)
139 *var
= TTMemory_Allocated
- old_memory
;
143 #define FOOTPRINT( field ) Save_Memory( &memory_footprint.##field )
147 Print_Mem( long val
, char* string
)
149 printf( "%6ld Bytes (%4ld kByte): %s\n",
151 ( val
+ 1023L ) / 1024,
155 #define PRINT_MEM( field, string ) \
156 Print_Mem( memory_footprint.##field, string )
159 /* Print the memory footprint */
165 error
= TT_New_Glyph( face
, &glyph
);
168 fprintf( stderr
, gettext( "Could not create glyph container.\n" ) );
172 FOOTPRINT( glyph_object
);
174 /* create instance */
175 error
= TT_New_Instance( face
, &instance
);
178 fprintf( stderr
, gettext( "Could not create instance.\n" ) );
182 FOOTPRINT( first_instance
);
184 error
= TT_New_Instance( face
, &instance
);
187 fprintf( stderr
, gettext( "Could not create second instance.\n" ) );
191 FOOTPRINT( second_instance
);
193 printf( gettext( "Memory footprint statistics:\n" ) );
194 separator_line( stdout
, 78 );
196 /* NOTE: In our current implementation, the face's execution */
197 /* context object is created lazily with the first */
198 /* instance. However, all later instances share the */
199 /* the same context. */
201 PRINT_MEM( face_object
, gettext( "face object" ) );
202 PRINT_MEM( glyph_object
, gettext( "glyph object" ) );
203 PRINT_MEM( second_instance
, gettext( "instance object" ) );
205 Print_Mem( memory_footprint
.first_instance
-
206 memory_footprint
.second_instance
,
207 gettext( "exec. context object" ) );
209 separator_line( stdout
, 78 );
211 Print_Mem( memory_footprint
.face_object
+
212 memory_footprint
.glyph_object
+
213 memory_footprint
.first_instance
,
214 gettext( "total memory usage" ) );
221 fprintf( stderr
, " " );
222 Panic( gettext( "FreeType error message: %s\n" ),
223 TT_ErrToString18( error
) );
227 static char name_buffer
[257];
228 static int name_len
= 0;
232 LookUp_Name( int index
)
236 unsigned short platform
, encoding
, language
, id
;
238 unsigned short string_len
;
243 n
= properties
.num_Names
;
245 for ( i
= 0; i
< n
; i
++ )
247 TT_Get_Name_ID( face
, i
, &platform
, &encoding
, &language
, &id
);
248 TT_Get_Name_String( face
, i
, &string
, &string_len
);
253 /* The following code was inspired from Mark Leisher's */
254 /* ttf2bdf package */
258 /* Try to find a Microsoft English name */
261 for ( j
= 1; j
>= 0; j
-- )
262 if ( encoding
== j
) /* Microsoft ? */
263 if ( (language
& 0x3FF) == 0x009 ) /* English language */
269 if ( !found
&& platform
== 0 && language
== 0 )
272 /* Found a Unicode Name. */
276 if ( string_len
> 512 )
281 for ( i
= 1; i
< string_len
; i
+= 2 )
282 name_buffer
[name_len
++] = string
[i
];
284 name_buffer
[name_len
] = '\0';
299 printf( gettext( "font name table entries\n" ) );
300 separator_line( stdout
, 78 );
302 if ( LookUp_Name( 4 ) )
303 printf( "%s - ", name_buffer
);
305 if ( LookUp_Name( 5 ) )
306 printf( "%s\n\n", name_buffer
);
308 if ( LookUp_Name( 6 ) )
309 printf( gettext( "PostScript name: %s\n\n" ), name_buffer
);
311 if ( LookUp_Name( 0 ) )
312 printf( "%s\n\n", name_buffer
);
314 if ( LookUp_Name( 7 ) )
315 printf( name_buffer
);
318 separator_line( stdout
, 78 );
323 Print_Encodings( void )
326 unsigned short platform
, encoding
;
327 char* platStr
, *encoStr
;
332 printf( gettext( "character map encodings\n" ) );
333 separator_line( stdout
, 78 );
335 n
= properties
.num_CharMaps
;
339 "The file doesn't seem to have any encoding table.\n" ) );
343 printf( gettext( "There are %hu encodings:\n\n" ), n
);
345 for ( i
= 0; i
< n
; i
++ )
347 TT_Get_CharMap_ID( face
, i
, &platform
, &encoding
);
348 printf( gettext( "encoding %2u: " ), i
);
350 platStr
= encoStr
= NULL
;
354 case TT_PLATFORM_APPLE_UNICODE
:
355 platStr
= "Apple Unicode";
358 case TT_APPLE_ID_DEFAULT
:
362 case TT_APPLE_ID_UNICODE_1_1
:
366 case TT_APPLE_ID_ISO_10646
:
367 encoStr
= "(ISO 10646-1:1993)";
370 case TT_APPLE_ID_UNICODE_2_0
:
375 sprintf( tempStr
, gettext( "Unknown value %hu" ), encoding
);
380 case TT_PLATFORM_MACINTOSH
:
384 sprintf( tempStr
, gettext( "Unknown value %hu" ), encoding
);
388 encoStr
= (char*)Apple_Encodings
[encoding
];
391 case TT_PLATFORM_ISO
:
395 case TT_ISO_ID_7BIT_ASCII
:
400 case TT_ISO_ID_10646
:
404 case TT_ISO_ID_8859_1
:
409 sprintf( tempStr
, "%hu", encoding
);
414 case TT_PLATFORM_MICROSOFT
:
418 case TT_MS_ID_SYMBOL_CS
:
422 case TT_MS_ID_UNICODE_CS
:
427 encoStr
= "Shift-JIS";
430 case TT_MS_ID_GB2312
:
438 case TT_MS_ID_WANSUNG
:
447 sprintf( tempStr
, gettext( "Unknown value %hu" ), encoding
);
453 sprintf( tempStr
, "%hu - %hu", platform
, encoding
);
454 platStr
= gettext( "Unknown" );
458 printf( "%s %s\n", platStr
, encoStr
);
462 separator_line( stdout
, 78 );
470 TT_UShort glyph_index
;
473 unsigned short platform
, encoding
;
476 printf( gettext( "ftxcmap test\n" ) );
477 separator_line( stdout
, 78 );
479 n
= properties
.num_CharMaps
;
483 "The file doesn't seem to have any encoding table.\n" ) );
487 printf( gettext( "There are %hu encodings:\n\n" ), n
);
489 for ( i
= 0; i
< n
; i
++ )
492 TT_Get_CharMap_ID( face
, i
, &platform
, &encoding
);
493 printf( gettext( "encoding %2u:\n" ), i
);
495 TT_Get_CharMap( face
, i
, &charmap
);
497 char_index
= TT_CharMap_First( charmap
, &glyph_index
);
498 printf( gettext( "first: glyph index %hu, character code 0x%lx\n" ),
499 glyph_index
, char_index
);
501 char_index
= TT_CharMap_Next( charmap
, char_index
, &glyph_index
);
502 printf( gettext( "next: glyph index %hu, character code 0x%lx\n" ),
503 glyph_index
, char_index
);
505 char_index
= TT_CharMap_Last( charmap
, &glyph_index
);
506 printf( gettext( "last: glyph index %hu, character code 0x%lx\n" ),
507 glyph_index
, char_index
);
511 separator_line( stdout
, 78 );
522 error
= TT_Get_Face_Bitmaps( face
, &eblc
);
523 if ( error
== TT_Err_Table_Missing
)
527 fprintf( stderr
, gettext(
528 "Error while retrieving embedded bitmaps table.\n" ) );
532 printf( gettext( "embedded bitmap table\n" ) );
533 separator_line( stdout
, 78 );
535 printf( gettext( " version of embedded bitmap table: 0x%lx\n" ),
537 printf( gettext( " number of embedded bitmap strikes: %lu\n" ),
541 TT_SBit_Strike
* strike
= eblc
.strikes
;
545 for ( ; count
< eblc
.num_strikes
; count
++, strike
++ )
547 printf( gettext( " bitmap strike %hu/%lu: " ),
548 count
+ 1, eblc
.num_strikes
);
550 printf( gettext( "%hux%hu pixels, %hu-bit depth, glyphs [%hu..%hu]\n" ),
551 strike
->x_ppem
, strike
->y_ppem
, strike
->bit_depth
,
552 strike
->start_glyph
, strike
->end_glyph
);
554 TT_SBit_Range
* range
= strike
->sbit_ranges
;
555 TT_SBit_Range
* limit
= range
+ strike
->num_ranges
;
558 for ( ; range
< limit
; range
++ )
559 printf( gettext( " range format (%hu:%hu) glyphs %hu..%hu\n" ),
568 separator_line( stdout
, 78 );
573 fprintf( stderr
, " " );
574 Panic( gettext( "FreeType error message: %s\n" ),
575 TT_ErrToString18( error
) );
579 #define TAG2STRING( t, s ) s[0] = (char)(t >> 24), \
580 s[1] = (char)(t >> 16), \
581 s[2] = (char)(t >> 8), \
595 TT_ULong
*script_tag_list
, *stl
;
596 TT_ULong
*language_tag_list
, *ltl
;
597 TT_ULong
*feature_tag_list
, *ftl
;
599 TT_UShort script_index
, language_index
,
600 feature_index
, req_feature_index
;
602 char script_tag
[4], language_tag
[4], feature_tag
[4];
605 error
= TT_Load_GSUB_Table( face
, &gsub
, NULL
);
606 if ( error
== TT_Err_Table_Missing
)
610 fprintf( stderr
, gettext( "Error while loading GSUB table.\n" ) );
614 printf( gettext( "GSUB table\n" ) );
615 separator_line( stdout
, 78 );
617 error
= TT_GSUB_Query_Scripts( &gsub
, &script_tag_list
);
620 fprintf( stderr
, gettext(
621 "Error while querying GSUB script list.\n" ) );
625 stl
= script_tag_list
;
626 for ( ; *stl
; stl
++ )
628 TAG2STRING( *stl
, script_tag
);
630 error
= TT_GSUB_Select_Script( &gsub
, *stl
, &script_index
);
633 fprintf( stderr
, gettext(
634 "Error while selecting GSUB script `%4.4s'.\n" ),
639 printf( gettext( " script `%4.4s' (index %hu):\n" ),
640 script_tag
, script_index
);
642 error
= TT_GSUB_Query_Features( &gsub
, script_index
, 0xFFFF,
646 fprintf( stderr
, gettext(
647 "Error while querying GSUB default language system for script `%4.4s'.\n" ),
652 printf( gettext( " default language system:\n" ) );
654 ftl
= feature_tag_list
;
655 for ( ; *ftl
; ftl
++ )
657 TAG2STRING( *ftl
, feature_tag
);
659 error
= TT_GSUB_Select_Feature( &gsub
, *ftl
,
660 script_index
, 0xFFFF,
664 fprintf( stderr
, gettext(
665 "Error while selecting GSUB feature `%4.4s'\n"
666 "for default language system of script `%4.4s'.\n" ),
667 feature_tag
, script_tag
);
671 printf( gettext( " feature `%4.4s' (index %hu; lookup " ),
672 feature_tag
, feature_index
);
674 f
= gsub
.FeatureList
.FeatureRecord
[feature_index
].Feature
;
676 for ( i
= 0; i
< f
.LookupListCount
- 1; i
++ )
677 printf( "%hu, ", f
.LookupListIndex
[i
] );
678 printf( "%hu)\n", f
.LookupListIndex
[i
] );
680 free( feature_tag_list
);
682 error
= TT_GSUB_Query_Languages( &gsub
, script_index
,
683 &language_tag_list
);
686 fprintf( stderr
, gettext(
687 "Error while querying GSUB language list for script `%4.4s'.\n" ),
692 ltl
= language_tag_list
;
693 for ( ; *ltl
; ltl
++ )
695 TAG2STRING( *ltl
, language_tag
);
697 error
= TT_GSUB_Select_Language( &gsub
, *ltl
,
700 &req_feature_index
);
703 fprintf( stderr
, gettext(
704 "Error while selecting GSUB language `%4.4s' for script `%4.4s'.\n" ),
705 language_tag
, script_tag
);
709 printf( gettext( " language `%4.4s' (index %hu):\n" ),
710 language_tag
, language_index
);
712 if ( req_feature_index
!= 0xFFFF )
714 printf( gettext( " required feature index %hu (lookup " ),
717 f
= gsub
.FeatureList
.FeatureRecord
[req_feature_index
].Feature
;
719 for ( i
= 0; i
< f
.LookupListCount
- 1; i
++ )
720 printf( "%hu, ", f
.LookupListIndex
[i
] );
721 printf( "%hu)\n", f
.LookupListIndex
[i
] );
724 error
= TT_GSUB_Query_Features( &gsub
, script_index
, language_index
,
728 fprintf( stderr
, gettext(
729 "Error while querying GSUB feature list\n"
730 "for script `%4.4s', language `%4.4s'.\n" ),
731 script_tag
, language_tag
);
735 ftl
= feature_tag_list
;
736 for ( ; *ftl
; ftl
++ )
738 TAG2STRING( *ftl
, feature_tag
);
740 error
= TT_GSUB_Select_Feature( &gsub
, *ftl
,
741 script_index
, language_index
,
745 fprintf( stderr
, gettext(
746 "Error while selecting GSUB feature `%4.4s'\n"
747 "for script `%4.4s', language `%4.4s'.\n" ),
748 feature_tag
, script_tag
, language_tag
);
752 printf( gettext( " feature `%4.4s' (index %hu; lookup " ),
753 feature_tag
, feature_index
);
755 f
= gsub
.FeatureList
.FeatureRecord
[feature_index
].Feature
;
757 for ( i
= 0; i
< f
.LookupListCount
- 1; i
++ )
758 printf( "%hu, ", f
.LookupListIndex
[i
] );
759 printf( "%hu)\n", f
.LookupListIndex
[i
] );
761 free( feature_tag_list
);
763 free( language_tag_list
);
765 free( script_tag_list
);
769 lo
= gsub
.LookupList
.Lookup
;
771 printf( gettext( "Lookups:\n\n" ) );
773 for ( i
= 0; i
< gsub
.LookupList
.LookupCount
; i
++ )
774 printf( gettext( " %hu: type %hu, flag 0x%x\n" ),
775 i
, lo
[i
].LookupType
, lo
[i
].LookupFlag
);
778 separator_line( stdout
, 78 );
783 fprintf( stderr
, " " );
784 Panic( gettext( "FreeType error message: %s\n" ),
785 TT_ErrToString18( error
) );
790 main( int argc
, char** argv
)
793 char filename
[128 + 4];
794 char alt_filename
[128 + 4];
799 #ifdef HAVE_LIBINTL_H
800 setlocale( LC_ALL
, "" );
801 bindtextdomain( "freetype", LOCALEDIR
);
802 textdomain( "freetype" );
809 gt
= gettext( "ftdump: Simple TrueType Dumper -- part of the FreeType project" );
810 fprintf( stderr
, "%s\n", gt
);
811 separator_line( stderr
, strlen( gt
) );
813 fprintf( stderr
, gettext( "Usage: %s fontname[.ttf|.ttc]\n\n" ),
816 exit( EXIT_FAILURE
);
819 i
= strlen( argv
[1] );
820 while ( i
> 0 && argv
[1][i
] != '\\' )
822 if ( argv
[1][i
] == '.' )
827 filename
[128] = '\0';
828 alt_filename
[128] = '\0';
830 strncpy( filename
, argv
[1], 128 );
831 strncpy( alt_filename
, argv
[1], 128 );
835 strncpy( filename
+ strlen( filename
), ".ttf", 4 );
836 strncpy( alt_filename
+ strlen( alt_filename
), ".ttc", 4 );
839 /* Initialize engine */
843 if ( (error
= TT_Init_FreeType( &engine
)) )
845 fprintf( stderr
, gettext( "Error while initializing engine.\n" ) );
849 if ( (error
= TT_Init_SBit_Extension( engine
)) )
851 fprintf( stderr
, gettext(
852 "Error while initializing embedded bitmap extension.\n" ) );
856 if ( (error
= TT_Init_GSUB_Extension( engine
)) )
858 fprintf( stderr
, gettext(
859 "Error while initializing GSUB extension.\n" ) );
863 FOOTPRINT( initial_overhead
);
865 /* Open and Load face */
867 error
= TT_Open_Face( engine
, filename
, &face
);
868 if ( error
== TT_Err_Could_Not_Open_File
)
870 strcpy( filename
, alt_filename
);
871 error
= TT_Open_Face( engine
, alt_filename
, &face
);
874 if ( error
== TT_Err_Could_Not_Open_File
)
875 Panic( gettext( "Could not find or open %s.\n" ), filename
);
878 fprintf( stderr
, gettext( "Error while opening %s.\n" ), filename
);
882 FOOTPRINT( face_object
);
884 /* get face properties and allocate preload arrays */
886 TT_Get_Face_Properties( face
, &properties
);
887 num_glyphs
= properties
.num_Glyphs
;
889 /* Now do various dumps */
894 if ( flag_encodings
)
906 #ifndef FREETYPE_DLL /* the statistics are meaningless if we use a DLL. */
911 TT_Close_Face( face
);
913 TT_Done_FreeType( engine
);
915 exit( EXIT_SUCCESS
); /* for safety reasons */
917 return 0; /* never reached */
920 fprintf( stderr
, " " );
921 Panic( gettext( "FreeType error message: %s\n" ),
922 TT_ErrToString18( error
) );
924 return 0; /* never reached */