I've worked out why ligation was being (correctly) suppressed in code
[sgt/halibut] / in_afm.c
CommitLineData
ba0fe3ec 1#include <stdio.h>
2#include <stdlib.h>
3#include "halibut.h"
4#include "paper.h"
5
6char *afm_read_line(input *in) {
7 int i, len = 256;
8 int c;
9 char *line;
10
11 do {
12 i = 0;
13 in->pos.line++;
14 c = getc(in->currfp);
15 if (c == EOF) {
16 error(err_afmeof, &in->pos);
17 return NULL;
18 }
19 line = snewn(len, char);
20 while (c != EOF && c != '\r' && c != '\n') {
21 if (i >= len - 1) {
22 len += 256;
23 line = sresize(line, len, char);
24 }
25 line[i++] = c;
26 c = getc(in->currfp);
27 }
28 if (c == '\r') {
29 /* Cope with CRLF terminated lines */
30 c = getc(in->currfp);
31 if (c != '\n' && c != EOF)
32 ungetc(c, in->currfp);
33 }
34 line[i] = 0;
35 } while (line[(strspn(line, " \t"))] == 0 ||
36 strncmp(line, "Comment ", 8) == 0 ||
37 strncmp(line, "Comment\t", 8) == 0);
38
39 return line;
40}
41
42static int afm_require_key(char *line, char const *expected, input *in) {
43 char *key = strtok(line, " \t");
44
45 if (strcmp(key, expected) == 0)
46 return TRUE;
47 error(err_afmkey, &in->pos, expected);
48 return FALSE;
49}
50
51void read_afm_file(input *in) {
52 char *line, *key, *val;
53 font_info *fi;
50926836 54 size_t i;
ba0fe3ec 55
56 fi = snew(font_info);
57 fi->name = NULL;
58 fi->nglyphs = 0;
59 fi->glyphs = NULL;
60 fi->widths = NULL;
44407fea 61 fi->fp = NULL;
ba0fe3ec 62 fi->kerns = newtree234(kern_cmp);
b5232689 63 fi->ligs = newtree234(lig_cmp);
255b7ff3 64 fi->fontbbox[0] = fi->fontbbox[1] = fi->fontbbox[2] = fi->fontbbox[3] = 0;
65 fi->capheight = fi->xheight = fi->ascent = fi->descent = 0;
66 fi->stemh = fi->stemv = fi->italicangle = 0;
50926836 67 for (i = 0; i < lenof(fi->bmp); i++)
68 fi->bmp[i] = 0xFFFF;
ba0fe3ec 69 in->pos.line = 0;
70 line = afm_read_line(in);
71 if (!line || !afm_require_key(line, "StartFontMetrics", in))
72 goto giveup;
73 if (!(val = strtok(NULL, " \t"))) {
74 error(err_afmval, in->pos, "StartFontMetrics", 1);
75 goto giveup;
76 }
77 if (atof(val) >= 5.0) {
78 error(err_afmvers, &in->pos);
79 goto giveup;
80 }
81 sfree(line);
82 for (;;) {
83 line = afm_read_line(in);
84 if (line == NULL)
85 goto giveup;
86 key = strtok(line, " \t");
87 if (strcmp(key, "EndFontMetrics") == 0) {
88 fi->next = all_fonts;
89 all_fonts = fi;
90 fclose(in->currfp);
91 return;
92 } else if (strcmp(key, "FontName") == 0) {
93 if (!(val = strtok(NULL, " \t"))) {
94 error(err_afmval, &in->pos, key, 1);
95 goto giveup;
96 }
97 fi->name = dupstr(val);
255b7ff3 98 } else if (strcmp(key, "FontBBox") == 0) {
99 int i;
100 for (i = 0; i < 3; i++) {
101 if (!(val = strtok(NULL, " \t"))) {
102 error(err_afmval, &in->pos, key, 4);
103 goto giveup;
104 }
105 fi->fontbbox[i] = atof(val);
106 }
107 } else if (strcmp(key, "CapHeight") == 0) {
108 if (!(val = strtok(NULL, " \t"))) {
109 error(err_afmval, &in->pos, key, 1);
110 goto giveup;
111 }
112 fi->capheight = atof(val);
113 } else if (strcmp(key, "XHeight") == 0) {
114 if (!(val = strtok(NULL, " \t"))) {
115 error(err_afmval, &in->pos, key, 1);
116 goto giveup;
117 }
118 fi->xheight = atof(val);
119 } else if (strcmp(key, "Ascender") == 0) {
120 if (!(val = strtok(NULL, " \t"))) {
121 error(err_afmval, &in->pos, key, 1);
122 goto giveup;
123 }
124 fi->ascent = atof(val);
125 } else if (strcmp(key, "Descender") == 0) {
126 if (!(val = strtok(NULL, " \t"))) {
127 error(err_afmval, &in->pos, key, 1);
128 goto giveup;
129 }
130 fi->descent = atof(val);
131 } else if (strcmp(key, "CapHeight") == 0) {
132 if (!(val = strtok(NULL, " \t"))) {
133 error(err_afmval, &in->pos, key, 1);
134 goto giveup;
135 }
136 fi->capheight = atof(val);
137 } else if (strcmp(key, "StdHW") == 0) {
138 if (!(val = strtok(NULL, " \t"))) {
139 error(err_afmval, &in->pos, key, 1);
140 goto giveup;
141 }
142 fi->stemh = atof(val);
143 } else if (strcmp(key, "StdVW") == 0) {
144 if (!(val = strtok(NULL, " \t"))) {
145 error(err_afmval, &in->pos, key, 1);
146 goto giveup;
147 }
148 fi->stemv = atof(val);
149 } else if (strcmp(key, "ItalicAngle") == 0) {
150 if (!(val = strtok(NULL, " \t"))) {
151 error(err_afmval, &in->pos, key, 1);
152 goto giveup;
153 }
154 fi->italicangle = atof(val);
ba0fe3ec 155 } else if (strcmp(key, "StartCharMetrics") == 0) {
156 char const **glyphs;
157 int *widths;
158 int i;
159 if (!(val = strtok(NULL, " \t"))) {
160 error(err_afmval, &in->pos, key, 1);
161 goto giveup;
162 }
163 fi->nglyphs = atoi(val);
164 sfree(line);
165 glyphs = snewn(fi->nglyphs, char const *);
166 widths = snewn(fi->nglyphs, int);
167 for (i = 0; i < fi->nglyphs; i++) {
168 glyphs[i] = NULL;
169 line = afm_read_line(in);
170 if (line == NULL)
171 goto giveup;
172 key = strtok(line, " \t");
173 while (key != NULL) {
174 if (strcmp(key, "WX") == 0 || strcmp(key, "W0X") == 0) {
175 if (!(val = strtok(NULL, " \t")) ||
176 !strcmp(val, ";")) {
177 error(err_afmval, &in->pos, key, 1);
178 goto giveup;
179 }
180 widths[i] = atoi(val);
181 } else if (strcmp(key, "N") == 0) {
182 if (!(val = strtok(NULL, " \t")) ||
183 !strcmp(val, ";")) {
184 error(err_afmval, &in->pos, key, 1);
185 goto giveup;
186 }
187 glyphs[i] = dupstr(val);
188 }
189 do {
190 key = strtok(NULL, " \t");
191 } while (key && strcmp(key, ";"));
192 key = strtok(NULL, " \t");
193 }
194 sfree(line);
195 }
196 line = afm_read_line(in);
197 if (!line || !afm_require_key(line, "EndCharMetrics", in))
198 goto giveup;
199 sfree(line);
200 fi->glyphs = glyphs;
201 fi->widths = widths;
202
203 for (i = 0; i < fi->nglyphs; i++) {
204 wchar_t ucs;
205 ucs = ps_glyph_to_unicode(fi->glyphs[i]);
206 if (ucs < 0xFFFF)
207 fi->bmp[ucs] = i;
208 }
209 font_index_glyphs(fi);
210 } else if (strcmp(key, "StartKernPairs") == 0 ||
211 strcmp(key, "StartKernPairs0") == 0) {
212 int nkerns, i;
213 kern_pair *kerns;
214 if (!(val = strtok(NULL, " \t"))) {
215 error(err_afmval, &in->pos, key, 1);
216 goto giveup;
217 }
218 nkerns = atoi(val);
219 sfree(line);
220 kerns = snewn(nkerns, kern_pair);
221 for (i = 0; i < nkerns; i++) {
222 line = afm_read_line(in);
223 if (line == NULL)
224 goto giveup;
225 key = strtok(line, " \t");
226 if (strcmp(key, "KPX") == 0) {
227 char *nl, *nr;
228 int l, r;
229 kern_pair *kp;
230 nl = strtok(NULL, " \t");
231 nr = strtok(NULL, " \t");
232 val = strtok(NULL, " \t");
233 if (!val) {
234 error(err_afmval, &in->pos, key, 3);
235 goto giveup;
236 }
237 l = find_glyph(fi, nl);
238 r = find_glyph(fi, nr);
239 if (l == -1 || r == -1) continue;
240 kp = snew(kern_pair);
241 kp->left = l;
242 kp->right = r;
243 kp->kern = atoi(val);
244 add234(fi->kerns, kp);
245 }
246 }
247 line = afm_read_line(in);
248 if (!line || !afm_require_key(line, "EndKernPairs", in))
249 goto giveup;
250 sfree(line);
251 }
252 }
253 giveup:
254 sfree(fi);
255 fclose(in->currfp);
256 return;
257}