*** empty log message ***
[m17n/libotf.git] / example / otflist.c
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
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
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
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
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 *
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 *
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
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)
214             {
215               OTF_get_table (otf, "name");
216
217               if (! (family = otf->name->name[16]))
218                 family = otf->name->name[1];
219               if (! (style = otf->name->name[17]))
220                 style = otf->name->name[2];
221             }
222           if (! family)
223             family = face->family_name;
224           if (! style)
225             style = face->style_name;
226
227           name = alloca (strlen (filename)
228                          + strlen (family)
229                          + 4);
230           sprintf (name, "%s (%s)", filename, family);
231           printf ("%-40s %s", name, style);
232           for (i = 0; i < face->num_charmaps; i++)
233             printf (" %d-%d", face->charmaps[i]->platform_id,
234                     face->charmaps[i]->encoding_id);
235           printf ("\n");
236           if (otf && long_format)
237             {
238               print_gsub_gpos_info (otf, "GSUB");
239               print_gsub_gpos_info (otf, "GPOS");
240             }
241           if (otf)
242             OTF_close (otf);
243         }
244       else
245         {
246           printf ("%s fail to open\n", filename);
247         }
248     }
249   exit (0);
250 }