otf: pairwise kerning based on glyph classes
[neatmkfn.git] / mkfn.c
blob1def8f51e8a071adfd673645f8f7008fff696383
1 /*
2 * mktrfn - produce troff font descriptions
4 * Copyright (C) 2012-2014 Ali Gholami Rudi <ali at rudi dot ir>
6 * This program is released under the Modified BSD license.
7 */
8 #include <ctype.h>
9 #include <fcntl.h>
10 #include <stdio.h>
11 #include <string.h>
12 #include <stdlib.h>
13 #include <unistd.h>
14 #include "trfn.h"
16 #define TOKLEN 256
18 static char *trfn_scripts; /* filtered scripts */
19 static char *trfn_langs; /* filtered languages */
21 static char *afm_charfield(char *s, char *d)
23 while (*s && !isspace(*s) && *s != ';')
24 *d++ = *s++;
25 while (isspace(*s) || *s == ';')
26 s++;
27 *d = '\0';
28 return s;
31 static int afm_read(void)
33 char ln[1024];
34 char ch[TOKLEN] = "", pos[TOKLEN] = "";
35 char c1[TOKLEN] = "", c2[TOKLEN] = "";
36 char wid[TOKLEN] = "", field[TOKLEN] = "";
37 char llx[TOKLEN] = "0", lly[TOKLEN] = "0";
38 char urx[TOKLEN] = "0", ury[TOKLEN] = "0";
39 char *s;
40 while (fgets(ln, sizeof(ln), stdin)) {
41 if (ln[0] == '#')
42 continue;
43 if (!strncmp("FontName ", ln, 8)) {
44 sscanf(ln, "FontName %s", ch);
45 trfn_psfont(ch);
46 continue;
48 if (!strncmp("StartCharMetrics", ln, 16))
49 break;
51 while (fgets(ln, sizeof(ln), stdin)) {
52 if (ln[0] == '#')
53 continue;
54 if (!strncmp("EndCharMetrics", ln, 14))
55 break;
56 s = ln;
57 while (*s) {
58 s = afm_charfield(s, field);
59 if (!strcmp("C", field)) {
60 s = afm_charfield(s, pos);
61 continue;
63 if (!strcmp("WX", field)) {
64 s = afm_charfield(s, wid);
65 continue;
67 if (!strcmp("N", field)) {
68 s = afm_charfield(s, ch);
69 continue;
71 if (!strcmp("B", field)) {
72 s = afm_charfield(s, llx);
73 s = afm_charfield(s, lly);
74 s = afm_charfield(s, urx);
75 s = afm_charfield(s, ury);
76 continue;
78 if (!strcmp("L", field)) {
79 s = afm_charfield(s, c1);
80 s = afm_charfield(s, c2);
81 continue;
83 break;
85 if (ch[0] && pos[0] && wid[0])
86 trfn_char(ch, atoi(pos), 0, atoi(wid),
87 atoi(llx), atoi(lly), atoi(urx), atoi(ury));
89 while (fgets(ln, sizeof(ln), stdin)) {
90 if (ln[0] == '#')
91 continue;
92 if (!strncmp("StartKernPairs", ln, 14))
93 break;
95 while (fgets(ln, sizeof(ln), stdin)) {
96 if (ln[0] == '#')
97 continue;
98 if (!strncmp("EndKernPairs", ln, 12))
99 break;
100 if (sscanf(ln, "KPX %s %s %s", c1, c2, wid) == 3)
101 trfn_kern(c1, c2, atoi(wid));
103 return 0;
106 /* return 1 if script script is to be included */
107 int trfn_script(char *script, int nscripts)
109 if (!trfn_scripts)
110 return nscripts == 1 || !script ||
111 !strcmp("DFLT", script) || !strcmp("latn", script);
112 if (!strcmp("help", trfn_scripts))
113 fprintf(stderr, "script: %s\n", script ? script : "");
114 if (strchr(script, ' '))
115 *strchr(script, ' ') = '\0';
116 return !!strstr(trfn_scripts, script);
119 /* return 1 if language lang is to be included */
120 int trfn_lang(char *lang, int nlangs)
122 if (!trfn_langs)
123 return nlangs == 1 || !lang;
124 if (!lang)
125 lang = "";
126 if (!strcmp("help", trfn_langs))
127 fprintf(stderr, "lang: %s\n", lang);
128 if (strchr(lang, ' '))
129 *strchr(lang, ' ') = '\0';
130 return !!strstr(trfn_langs, lang);
133 int otf_read(void);
134 void otf_feat(int res, int kmin);
136 static char *usage =
137 "Usage: mktrfn [options] <input >output\n"
138 "Options:\n"
139 " -a \tread an AFM file (default)\n"
140 " -o \tread an OTF file\n"
141 " -s \tspecial font\n"
142 " -p name \toverride font postscript name\n"
143 " -t name \tset font troff name\n"
144 " -r res \tset device resolution (720)\n"
145 " -k kmin \tspecify the minimum amount of kerning (0)\n"
146 " -b \tinclude glyph bounding boxes\n"
147 " -S scrs \tcomma-separated list of scripts to include (help to list)\n"
148 " -L langs\tcomma-separated list of languages to include (help to list)\n";
150 int main(int argc, char *argv[])
152 int afm = 1;
153 int i = 1;
154 int res = 720;
155 int spc = 0;
156 int kmin = 0;
157 int bbox = 0;
158 for (i = 1; i < argc && argv[i][0] == '-'; i++) {
159 switch (argv[i][1]) {
160 case 'a':
161 afm = 1;
162 break;
163 case 'k':
164 kmin = atoi(argv[i][2] ? argv[i] + 2 : argv[++i]);
165 break;
166 case 'L':
167 trfn_langs = argv[i][2] ? argv[i] + 2 : argv[++i];
168 break;
169 case 'o':
170 afm = 0;
171 break;
172 case 'p':
173 trfn_psfont(argv[i][2] ? argv[i] + 2 : argv[++i]);
174 break;
175 case 'r':
176 res = atoi(argv[i][2] ? argv[i] + 2 : argv[++i]);
177 break;
178 case 's':
179 spc = 1;
180 break;
181 case 'S':
182 trfn_scripts = argv[i][2] ? argv[i] + 2 : argv[++i];
183 break;
184 case 't':
185 trfn_trfont(argv[i][2] ? argv[i] + 2 : argv[++i]);
186 break;
187 case 'b':
188 bbox = 1;
189 break;
190 default:
191 printf("%s", usage);
192 return 0;
195 trfn_init(res, spc, kmin, bbox);
196 if (afm)
197 afm_read();
198 else
199 otf_read();
200 trfn_print();
201 if (!afm)
202 otf_feat(res, kmin);
203 trfn_done();
204 return 0;