6 char *afm_read_line(input
*in
) {
16 error(err_afmeof
, &in
->pos
);
19 line
= snewn(len
, char);
20 while (c
!= EOF
&& c
!= '\r' && c
!= '\n') {
23 line
= sresize(line
, len
, char);
29 /* Cope with CRLF terminated lines */
31 if (c
!= '\n' && c
!= EOF
)
32 ungetc(c
, in
->currfp
);
35 } while (line
[(strspn(line
, " \t"))] == 0 ||
36 strncmp(line
, "Comment ", 8) == 0 ||
37 strncmp(line
, "Comment\t", 8) == 0);
42 static int afm_require_key(char *line
, char const *expected
, input
*in
) {
43 char *key
= strtok(line
, " \t");
45 if (strcmp(key
, expected
) == 0)
47 error(err_afmkey
, &in
->pos
, expected
);
51 void read_afm_file(input
*in
) {
52 char *line
, *key
, *val
;
58 fi
->widths
= newtree234(width_cmp
);
60 fi
->kerns
= newtree234(kern_cmp
);
61 fi
->ligs
= newtree234(lig_cmp
);
62 fi
->fontbbox
[0] = fi
->fontbbox
[1] = fi
->fontbbox
[2] = fi
->fontbbox
[3] = 0;
63 fi
->capheight
= fi
->xheight
= fi
->ascent
= fi
->descent
= 0;
64 fi
->stemh
= fi
->stemv
= fi
->italicangle
= 0;
65 for (i
= 0; i
< lenof(fi
->bmp
); i
++)
68 line
= afm_read_line(in
);
69 if (!line
|| !afm_require_key(line
, "StartFontMetrics", in
))
71 if (!(val
= strtok(NULL
, " \t"))) {
72 error(err_afmval
, in
->pos
, "StartFontMetrics", 1);
75 if (atof(val
) >= 5.0) {
76 error(err_afmvers
, &in
->pos
);
81 line
= afm_read_line(in
);
84 key
= strtok(line
, " \t");
85 if (strcmp(key
, "EndFontMetrics") == 0) {
90 } else if (strcmp(key
, "FontName") == 0) {
91 if (!(val
= strtok(NULL
, " \t"))) {
92 error(err_afmval
, &in
->pos
, key
, 1);
95 fi
->name
= dupstr(val
);
96 } else if (strcmp(key
, "FontBBox") == 0) {
98 for (i
= 0; i
< 3; i
++) {
99 if (!(val
= strtok(NULL
, " \t"))) {
100 error(err_afmval
, &in
->pos
, key
, 4);
103 fi
->fontbbox
[i
] = atof(val
);
105 } else if (strcmp(key
, "CapHeight") == 0) {
106 if (!(val
= strtok(NULL
, " \t"))) {
107 error(err_afmval
, &in
->pos
, key
, 1);
110 fi
->capheight
= atof(val
);
111 } else if (strcmp(key
, "XHeight") == 0) {
112 if (!(val
= strtok(NULL
, " \t"))) {
113 error(err_afmval
, &in
->pos
, key
, 1);
116 fi
->xheight
= atof(val
);
117 } else if (strcmp(key
, "Ascender") == 0) {
118 if (!(val
= strtok(NULL
, " \t"))) {
119 error(err_afmval
, &in
->pos
, key
, 1);
122 fi
->ascent
= atof(val
);
123 } else if (strcmp(key
, "Descender") == 0) {
124 if (!(val
= strtok(NULL
, " \t"))) {
125 error(err_afmval
, &in
->pos
, key
, 1);
128 fi
->descent
= atof(val
);
129 } else if (strcmp(key
, "CapHeight") == 0) {
130 if (!(val
= strtok(NULL
, " \t"))) {
131 error(err_afmval
, &in
->pos
, key
, 1);
134 fi
->capheight
= atof(val
);
135 } else if (strcmp(key
, "StdHW") == 0) {
136 if (!(val
= strtok(NULL
, " \t"))) {
137 error(err_afmval
, &in
->pos
, key
, 1);
140 fi
->stemh
= atof(val
);
141 } else if (strcmp(key
, "StdVW") == 0) {
142 if (!(val
= strtok(NULL
, " \t"))) {
143 error(err_afmval
, &in
->pos
, key
, 1);
146 fi
->stemv
= atof(val
);
147 } else if (strcmp(key
, "ItalicAngle") == 0) {
148 if (!(val
= strtok(NULL
, " \t"))) {
149 error(err_afmval
, &in
->pos
, key
, 1);
152 fi
->italicangle
= atof(val
);
153 } else if (strcmp(key
, "StartCharMetrics") == 0) {
155 if (!(val
= strtok(NULL
, " \t"))) {
156 error(err_afmval
, &in
->pos
, key
, 1);
161 for (i
= 0; i
< nglyphs
; i
++) {
165 line
= afm_read_line(in
);
168 key
= strtok(line
, " \t");
169 while (key
!= NULL
) {
170 if (strcmp(key
, "WX") == 0 || strcmp(key
, "W0X") == 0) {
171 if (!(val
= strtok(NULL
, " \t")) ||
173 error(err_afmval
, &in
->pos
, key
, 1);
177 } else if (strcmp(key
, "N") == 0) {
178 if (!(val
= strtok(NULL
, " \t")) ||
180 error(err_afmval
, &in
->pos
, key
, 1);
183 g
= glyph_intern(val
);
184 } else if (strcmp(key
, "L") == 0) {
186 if (!(val
= strtok(NULL
, " \t")) ||
188 error(err_afmval
, &in
->pos
, key
, 1);
191 succ
= glyph_intern(val
);
192 if (!(val
= strtok(NULL
, " \t")) ||
194 error(err_afmval
, &in
->pos
, key
, 1);
197 lig
= glyph_intern(val
);
198 if (g
!= NOGLYPH
&& succ
!= NOGLYPH
&&
200 ligature
*l
= snew(ligature
);
208 key
= strtok(NULL
, " \t");
209 } while (key
&& strcmp(key
, ";"));
210 key
= strtok(NULL
, " \t");
213 if (width
!= 0 && g
!= NOGLYPH
) {
215 glyph_width
*w
= snew(glyph_width
);
218 add234(fi
->widths
, w
);
219 ucs
= ps_glyph_to_unicode(g
);
224 line
= afm_read_line(in
);
225 if (!line
|| !afm_require_key(line
, "EndCharMetrics", in
))
229 } else if (strcmp(key
, "StartKernPairs") == 0 ||
230 strcmp(key
, "StartKernPairs0") == 0) {
233 if (!(val
= strtok(NULL
, " \t"))) {
234 error(err_afmval
, &in
->pos
, key
, 1);
239 kerns
= snewn(nkerns
, kern_pair
);
240 for (i
= 0; i
< nkerns
; i
++) {
241 line
= afm_read_line(in
);
244 key
= strtok(line
, " \t");
245 if (strcmp(key
, "KPX") == 0) {
249 nl
= strtok(NULL
, " \t");
250 nr
= strtok(NULL
, " \t");
251 val
= strtok(NULL
, " \t");
253 error(err_afmval
, &in
->pos
, key
, 3);
256 l
= glyph_intern(nl
);
257 r
= glyph_intern(nr
);
258 if (l
== -1 || r
== -1) continue;
259 kp
= snew(kern_pair
);
262 kp
->kern
= atoi(val
);
263 add234(fi
->kerns
, kp
);
266 line
= afm_read_line(in
);
267 if (!line
|| !afm_require_key(line
, "EndKernPairs", in
))