Copyright years udpated.
[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 #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 i;
185
186   if (FT_Init_FreeType (&ft_library))
187     FATAL_ERROR ("%s\n", "!! Freetype initialization failed.");
188
189   if (argc > 1)
190     {
191       if (! strcmp (argv[1], "-h") || ! strcmp (argv[1], "--help"))
192         help_and_exit (argv[0]);
193       if (! strcmp (argv[1], "-l"))
194         long_format = 1, argc--, argv++;
195     }
196   if (argc == 2)
197     {
198       if (chdir (argv[1]) < 0)
199         FATAL_ERROR ("Can't change directory to %s\n", argv[1]);
200     }
201
202   while ((filename = next_file (".")) != NULL)
203     {
204       if (! FT_New_Face (ft_library, filename, 0, &face))
205         {
206           OTF *otf = OTF_open (filename);
207           char *name, *family = NULL, *style = NULL;
208
209           if (otf)
210             {
211               OTF_get_table (otf, "name");
212
213               if (! (family = otf->name->name[16]))
214                 family = otf->name->name[1];
215               if (! (style = otf->name->name[17]))
216                 style = otf->name->name[2];
217             }
218           if (! family)
219             family = face->family_name;
220           if (! style)
221             style = face->style_name;
222
223           name = alloca (strlen (filename)
224                          + strlen (family)
225                          + 4);
226           sprintf (name, "%s (%s)", filename, family);
227           printf ("%-40s %s", name, style);
228           for (i = 0; i < face->num_charmaps; i++)
229             printf (" %d-%d", face->charmaps[i]->platform_id,
230                     face->charmaps[i]->encoding_id);
231           printf ("\n");
232           if (otf && long_format)
233             {
234               print_gsub_gpos_info (otf, "GSUB");
235               print_gsub_gpos_info (otf, "GPOS");
236             }
237           if (otf)
238             OTF_close (otf);
239         }
240       else
241         {
242           printf ("%s fail to open\n", filename);
243         }
244     }
245   exit (0);
246 }