Include <otf.h>.
[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 <dirent.h>
28
29 #include <ft2build.h>
30 #include FT_FREETYPE_H
31
32 #include <otf.h>
33
34 /* Format MSG by FMT and print the result to the stderr, and exit.  */
35
36 #define FATAL_ERROR(fmt, arg)   \
37   do {                          \
38     fprintf (stderr, fmt, arg); \
39     exit (1);                   \
40   } while (0)
41
42
43 void
44 print_tag (OTF_Tag tag)
45 {
46   char name[5];
47
48   OTF_tag_name (tag, name);
49   printf ("%s", name);
50 }
51
52 void
53 print_gsub_gpos_info (OTF *otf, char *table)
54 {
55   int i, j;
56
57   if (OTF_get_table (otf, table) == 0)
58     {
59       OTF_ScriptList *scripts;
60       OTF_FeatureList *features;
61
62       if (! strcmp (table, "GSUB"))
63         scripts = &otf->gsub->ScriptList, features = &otf->gsub->FeatureList;
64       else
65         scripts = &otf->gpos->ScriptList, features = &otf->gpos->FeatureList;
66
67       printf ("  %s scripts: ", table);
68       for (i = 0; i < scripts->ScriptCount; i++)
69         {
70           OTF_Script *script = scripts->Script + i;
71
72           if (i > 0)
73             printf (", ");
74           print_tag (script->ScriptTag);
75           if (script->LangSysCount > 0)
76             {
77               printf (" (");
78               for (j = 0; j < script->LangSysCount; j++)
79                 {
80                   if (j > 0)
81                     printf (", ");
82                   print_tag (script->LangSysRecord[j].LangSysTag);
83                 }
84               printf (" )");
85             }
86         }
87       printf ("\n");
88
89       printf ("  %s features: ", table);
90       for (i = 0; i < features->FeatureCount; i++)
91         {
92           if (i > 0)
93             printf (",");
94           print_tag (features->Feature[i].FeatureTag);
95         }
96       printf ("\n");
97     }
98 }
99 void
100 help_and_exit (char *prog)
101 {
102   printf ("otflist %s\n", LIBOTF_VERSION);
103   printf ("Usage: %s [-l] [-h] [DIR]\n", prog);
104   printf ("List information about OpenType font files in the directory DIR.\n");
105   printf ("It actually lists all fonts that can be handled by Freetype.\n");
106   printf ("  -h         print this help, then exit\n");
107   printf ("  -l         use a long listing mode\n");
108   exit (0);
109 }
110
111 int
112 filter (const struct dirent *direntry)
113 {
114   int len = strlen (direntry->d_name);
115   const char *ext = direntry->d_name + (len - 4);
116
117   return (len >= 5
118           && (! strncmp (ext, ".ttf", 4)
119               || ! strncmp (ext, ".TTF", 4)
120               || ! strncmp (ext, ".otf", 4)
121               || ! strncmp (ext, ".OTF", 4)
122               || ! strncmp (ext, ".PFA", 4)
123               || ! strncmp (ext, ".pfa", 4)
124               || ! strncmp (ext, ".PFB", 4)
125               || ! strncmp (ext, ".pfb", 4)));
126 }
127
128 int
129 main (int argc, char **argv)
130
131   FT_Library ft_library;
132   FT_Face face;
133   int long_format = 0;
134   struct dirent **namelist;
135   int n;
136   int i, j;
137
138   if (FT_Init_FreeType (&ft_library))
139     FATAL_ERROR ("%s\n", "!! Freetype initialization failed.");
140
141   if (argc > 1)
142     {
143       if (! strcmp (argv[1], "-h") || ! strcmp (argv[1], "--help"))
144         help_and_exit (argv[0]);
145       if (! strcmp (argv[1], "-l"))
146         long_format = 1, argc--, argv++;
147     }
148   if (argc == 2)
149     {
150       if (chdir (argv[1]) < 0)
151         FATAL_ERROR ("Can't change directory to %s\n", argv[1]);
152     }
153   n = scandir (".", &namelist, filter, alphasort);
154
155   for (i = 0; i < n; i++)
156     if (! FT_New_Face (ft_library, namelist[i]->d_name, 0, &face))
157       {
158         OTF *otf = OTF_open (namelist[i]->d_name);
159         char *name, *family = NULL, *style = NULL;
160
161         if (otf)
162           {
163             OTF_get_table (otf, "name");
164
165             if (! (family = otf->name->name[16]))
166               family = otf->name->name[1];
167             if (! (style = otf->name->name[17]))
168               style = otf->name->name[2];
169           }
170         if (! family)
171           family = face->family_name;
172         if (! style)
173           style = face->style_name;
174
175         name = alloca (strlen (namelist[i]->d_name)
176                        + strlen (family)
177                        + 4);
178         sprintf (name, "%s (%s)", namelist[i]->d_name, family);
179         printf ("%-40s %s", name, style);
180         for (j = 0; j < face->num_charmaps; j++)
181           printf (" %d-%d", face->charmaps[j]->platform_id,
182                   face->charmaps[j]->encoding_id);
183         printf ("\n");
184         if (otf && long_format)
185           {
186             print_gsub_gpos_info (otf, "GSUB");
187             print_gsub_gpos_info (otf, "GPOS");
188           }
189         if (otf)
190           OTF_close (otf);
191       }
192     else
193       {
194         printf ("%s fail to open\n", namelist[i]->d_name);
195       }
196   exit (0);
197 }