1 /* otflist.c -- List OpenType fonts.
2
3 Copyright (C) 2003, 2004, 2005, 2006, 2007, 2008, 2009, 2010
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 #ifdef HAVE_ALLOCA_H
35 #include <alloca.h>
36 #endif
37
38 #include <otf.h>
39
40 /* Format MSG by FMT and print the result to the stderr, and exit. */
41
42 #define FATAL_ERROR(fmt, arg) \
43 do { \
44 fprintf (stderr, fmt, arg); \
45 exit (1); \
46 } while (0)
47
48
49 void
print_tag(OTF_Tag tag)50 print_tag (OTF_Tag tag)
51 {
52 char name[5];
53
54 OTF_tag_name (tag, name);
55 printf ("%s", name);
56 }
57
58 void
print_gsub_gpos_info(OTF * otf,char * table)59 print_gsub_gpos_info (OTF *otf, char *table)
60 {
61 int i, j;
62
63 if (OTF_get_table (otf, table) == 0)
64 {
65 OTF_ScriptList *scripts;
66 OTF_FeatureList *features;
67
68 if (! strcmp (table, "GSUB"))
69 scripts = &otf->gsub->ScriptList, features = &otf->gsub->FeatureList;
70 else
71 scripts = &otf->gpos->ScriptList, features = &otf->gpos->FeatureList;
72
73 printf (" %s scripts: ", table);
74 for (i = 0; i < scripts->ScriptCount; i++)
75 {
76 OTF_Script *script = scripts->Script + i;
77
78 if (i > 0)
79 printf (", ");
80 print_tag (script->ScriptTag);
81 if (script->LangSysCount > 0)
82 {
83 printf (" (");
84 for (j = 0; j < script->LangSysCount; j++)
85 {
86 if (j > 0)
87 printf (", ");
88 print_tag (script->LangSysRecord[j].LangSysTag);
89 }
90 printf (")");
91 }
92 }
93 printf ("\n");
94
95 printf (" %s features: ", table);
96 for (i = 0; i < features->FeatureCount; i++)
97 {
98 if (i > 0)
99 printf (",");
100 print_tag (features->Feature[i].FeatureTag);
101 }
102 printf ("\n");
103 }
104 }
105 void
help_and_exit(char * prog)106 help_and_exit (char *prog)
107 {
108 printf ("otflist %s\n", LIBOTF_VERSION);
109 printf ("Usage: %s [-l] [-h] [DIR]\n", prog);
110 printf ("List information about OpenType font files in the directory DIR.\n");
111 printf ("It actually lists all fonts that can be handled by Freetype.\n");
112 printf (" -h print this help, then exit\n");
113 printf (" -l use a long listing mode\n");
114 exit (0);
115 }
116
117 int
filter(const struct dirent * direntry)118 filter (const struct dirent *direntry)
119 {
120 int len = strlen (direntry->d_name);
121 const char *ext = direntry->d_name + (len - 4);
122
123 return (len >= 5
124 && (! strncmp (ext, ".ttf", 4)
125 || ! strncmp (ext, ".TTF", 4)
126 || ! strncmp (ext, ".ttc", 4)
127 || ! strncmp (ext, ".TTC", 4)
128 || ! strncmp (ext, ".otf", 4)
129 || ! strncmp (ext, ".OTF", 4)
130 || ! strncmp (ext, ".PFA", 4)
131 || ! strncmp (ext, ".pfa", 4)
132 || ! strncmp (ext, ".PFB", 4)
133 || ! strncmp (ext, ".pfb", 4)));
134 }
135
136 int dir_index = 0;
137
138 #ifdef HAVE_SCANDIR
139
140 struct dirent **namelist = NULL;
141 int num_files = 0;
142
143 char *
next_file(char * dirname)144 next_file (char *dirname)
145 {
146 if (dir_index == 0)
147 {
148 #ifdef HAVE_ALPHASORT
149 num_files = scandir (".", &namelist, filter, alphasort);
150 #else
151 num_files = scandir (".", &namelist, filter, NULL);
152 #endif
153 }
154 if (dir_index == num_files)
155 return NULL;
156 return namelist[dir_index++]->d_name;
157 }
158
159 #else /* not HAVE_SCANDIR */
160
161 DIR *dirp;
162
163 char *
next_file(char * dirname)164 next_file (char *dirname)
165 {
166 struct dirent *dirent;
167
168 if (dir_index == 0)
169 dirp = opendir (dirname);
170 while ((dirent = readdir (dirp))
171 && (strcmp (dirent->d_name, ".") == 0
172 || strcmp (dirent->d_name, "..") == 0));
173 if (! dirent)
174 return NULL;
175 dir_index++;
176 return dirent->d_name;
177 }
178
179 #endif /* not HAVE_SCANDIR */
180
181 int
main(int argc,char ** argv)182 main (int argc, char **argv)
183 {
184 FT_Library ft_library;
185 FT_Face face;
186 char *filename;
187 int long_format = 0;
188 int i;
189
190 if (FT_Init_FreeType (&ft_library))
191 FATAL_ERROR ("%s\n", "!! Freetype initialization failed.");
192
193 if (argc > 1)
194 {
195 if (! strcmp (argv[1], "-h") || ! strcmp (argv[1], "--help"))
196 help_and_exit (argv[0]);
197 if (! strcmp (argv[1], "-l"))
198 long_format = 1, argc--, argv++;
199 }
200 if (argc == 2)
201 {
202 if (chdir (argv[1]) < 0)
203 FATAL_ERROR ("Can't change directory to %s\n", argv[1]);
204 }
205
206 while ((filename = next_file (".")) != NULL)
207 {
208 if (! FT_New_Face (ft_library, filename, 0, &face))
209 {
210 OTF *otf = OTF_open (filename);
211 char *name, *family = NULL, *style = NULL;
212
213 if (otf && OTF_get_table (otf, "name") == 0)
214 {
215 if (! (family = otf->name->name[16]))
216 family = otf->name->name[1];
217 if (! (style = otf->name->name[17]))
218 style = otf->name->name[2];
219 }
220 if (! family)
221 family = face->family_name;
222 if (! style)
223 style = face->style_name;
224
225 name = alloca (strlen (filename)
226 + strlen (family)
227 + 4);
228 sprintf (name, "%s (%s)", filename, family);
229 printf ("%-40s %s", name, style);
230 for (i = 0; i < face->num_charmaps; i++)
231 printf (" %d-%d", face->charmaps[i]->platform_id,
232 face->charmaps[i]->encoding_id);
233 printf ("\n");
234 if (otf && long_format)
235 {
236 print_gsub_gpos_info (otf, "GSUB");
237 print_gsub_gpos_info (otf, "GPOS");
238 }
239 if (otf)
240 OTF_close (otf);
241 }
242 else
243 {
244 printf ("%s fail to open\n", filename);
245 }
246 }
247 exit (0);
248 }
249