(filter): Accept extentions ".ttc" and ".TTC".
[m17n/libotf.git] / example / otflist.c
1 /* otflist.c -- List OpenType fonts.
2
3 Copyright (C) 2003, 2004
4   National Institute of Advanced Industrial Science and Technology (AIST)
5   Registration Number H15PRO167
6
7 This file is part of libotf.
8
9 Libotf is free software; you can redistribute it and/or modify it
10 under the terms of the GNU Lesser General Public License as published
11 by the Free Software Foundation; either version 2.1 of the License, or
12 (at your option) any later version.
13
14 Libotf is distributed in the hope that it will be useful, but WITHOUT
15 ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
16 FITNESS FOR A PARTICULAR PURPOSE.  See the GNU Lesser General Public
17 License for more details.
18
19 You should have received a copy of the GNU Lesser General Public
20 License along with this library, in a file named COPYING; if not,
21 write to the Free Software Foundation, Inc., 59 Temple Place, Suite
22 330, Boston, MA 02111-1307, USA.  */
23
24 #include <stdio.h>
25 #include <unistd.h>
26 #include <string.h>
27 #include <sys/types.h>
28 #include <dirent.h>
29
30 #include <ft2build.h>
31 #include FT_FREETYPE_H
32
33 #include "config.h"
34 #include <otf.h>
35
36 /* Format MSG by FMT and print the result to the stderr, and exit.  */
37
38 #define FATAL_ERROR(fmt, arg)   \
39   do {                          \
40     fprintf (stderr, fmt, arg); \
41     exit (1);                   \
42   } while (0)
43
44
45 void
46 print_tag (OTF_Tag tag)
47 {
48   char name[5];
49
50   OTF_tag_name (tag, name);
51   printf ("%s", name);
52 }
53
54 void
55 print_gsub_gpos_info (OTF *otf, char *table)
56 {
57   int i, j;
58
59   if (OTF_get_table (otf, table) == 0)
60     {
61       OTF_ScriptList *scripts;
62       OTF_FeatureList *features;
63
64       if (! strcmp (table, "GSUB"))
65         scripts = &otf->gsub->ScriptList, features = &otf->gsub->FeatureList;
66       else
67         scripts = &otf->gpos->ScriptList, features = &otf->gpos->FeatureList;
68
69       printf ("  %s scripts: ", table);
70       for (i = 0; i < scripts->ScriptCount; i++)
71         {
72           OTF_Script *script = scripts->Script + i;
73
74           if (i > 0)
75             printf (", ");
76           print_tag (script->ScriptTag);
77           if (script->LangSysCount > 0)
78             {
79               printf (" (");
80               for (j = 0; j < script->LangSysCount; j++)
81                 {
82                   if (j > 0)
83                     printf (", ");
84                   print_tag (script->LangSysRecord[j].LangSysTag);
85                 }
86               printf (" )");
87             }
88         }
89       printf ("\n");
90
91       printf ("  %s features: ", table);
92       for (i = 0; i < features->FeatureCount; i++)
93         {
94           if (i > 0)
95             printf (",");
96           print_tag (features->Feature[i].FeatureTag);
97         }
98       printf ("\n");
99     }
100 }
101 void
102 help_and_exit (char *prog)
103 {
104   printf ("otflist %s\n", LIBOTF_VERSION);
105   printf ("Usage: %s [-l] [-h] [DIR]\n", prog);
106   printf ("List information about OpenType font files in the directory DIR.\n");
107   printf ("It actually lists all fonts that can be handled by Freetype.\n");
108   printf ("  -h         print this help, then exit\n");
109   printf ("  -l         use a long listing mode\n");
110   exit (0);
111 }
112
113 int
114 filter (const struct dirent *direntry)
115 {
116   int len = strlen (direntry->d_name);
117   const char *ext = direntry->d_name + (len - 4);
118
119   return (len >= 5
120           && (! strncmp (ext, ".ttf", 4)
121               || ! strncmp (ext, ".TTF", 4)
122               || ! strncmp (ext, ".ttc", 4)
123               || ! strncmp (ext, ".TTC", 4)
124               || ! strncmp (ext, ".otf", 4)
125               || ! strncmp (ext, ".OTF", 4)
126               || ! strncmp (ext, ".PFA", 4)
127               || ! strncmp (ext, ".pfa", 4)
128               || ! strncmp (ext, ".PFB", 4)
129               || ! strncmp (ext, ".pfb", 4)));
130 }
131
132 int dir_index = 0;
133
134 #ifdef HAVE_SCANDIR
135
136 struct dirent **namelist = NULL;
137 int num_files = 0;
138
139 char *
140 next_file (char *dirname)
141 {
142   if (dir_index == 0)
143     {
144 #ifdef HAVE_ALPHASORT
145       num_files = scandir (".", &namelist, filter, alphasort);
146 #else
147       num_files = scandir (".", &namelist, filter, NULL);
148 #endif
149     }
150   if (dir_index == num_files)
151     return NULL;
152   return namelist[dir_index++]->d_name;
153 }
154
155 #else  /* not HAVE_SCANDIR */
156
157 DIR *dirp;
158
159 char *
160 next_file (char *dirname)
161 {
162   struct dirent *dirent;
163
164   if (dir_index == 0)
165     dirp = opendir (dirname);
166   while ((dirent = readdir (dirp))
167          && (strcmp (dirent->d_name, ".") == 0
168              || strcmp (dirent->d_name, "..") == 0));
169   if (! dirent)
170     return NULL;
171   dir_index++;
172   return dirent->d_name;
173 }
174
175 #endif /* not HAVE_SCANDIR */
176
177 int
178 main (int argc, char **argv)
179
180   FT_Library ft_library;
181   FT_Face face;
182   char *filename;
183   int long_format = 0;
184   int n;
185   int i, j;
186
187   if (FT_Init_FreeType (&ft_library))
188     FATAL_ERROR ("%s\n", "!! Freetype initialization failed.");
189
190   if (argc > 1)
191     {
192       if (! strcmp (argv[1], "-h") || ! strcmp (argv[1], "--help"))
193         help_and_exit (argv[0]);
194       if (! strcmp (argv[1], "-l"))
195         long_format = 1, argc--, argv++;
196     }
197   if (argc == 2)
198     {
199       if (chdir (argv[1]) < 0)
200         FATAL_ERROR ("Can't change directory to %s\n", argv[1]);
201     }
202
203   while ((filename = next_file (".")) != NULL)
204     {
205       if (! FT_New_Face (ft_library, filename, 0, &face))
206         {
207           OTF *otf = OTF_open (filename);
208           char *name, *family = NULL, *style = NULL;
209
210           if (otf)
211             {
212               OTF_get_table (otf, "name");
213
214               if (! (family = otf->name->name[16]))
215                 family = otf->name->name[1];
216               if (! (style = otf->name->name[17]))
217                 style = otf->name->name[2];
218             }
219           if (! family)
220             family = face->family_name;
221           if (! style)
222             style = face->style_name;
223
224           name = alloca (strlen (filename)
225                          + strlen (family)
226                          + 4);
227           sprintf (name, "%s (%s)", filename, family);
228           printf ("%-40s %s", name, style);
229           for (j = 0; j < face->num_charmaps; j++)
230             printf (" %d-%d", face->charmaps[j]->platform_id,
231                     face->charmaps[j]->encoding_id);
232           printf ("\n");
233           if (otf && long_format)
234             {
235               print_gsub_gpos_info (otf, "GSUB");
236               print_gsub_gpos_info (otf, "GPOS");
237             }
238           if (otf)
239             OTF_close (otf);
240         }
241       else
242         {
243           printf ("%s fail to open\n", filename);
244         }
245     }
246   exit (0);
247 }