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
;
62 fi
->kerns
= newtree234(kern_cmp
);
63 fi
->fontbbox
[0] = fi
->fontbbox
[1] = fi
->fontbbox
[2] = fi
->fontbbox
[3] = 0;
64 fi
->capheight
= fi
->xheight
= fi
->ascent
= fi
->descent
= 0;
65 fi
->stemh
= fi
->stemv
= fi
->italicangle
= 0;
66 for (i
= 0; i
< lenof(fi
->bmp
); i
++)
69 line
= afm_read_line(in
);
70 if (!line
|| !afm_require_key(line
, "StartFontMetrics", in
))
72 if (!(val
= strtok(NULL
, " \t"))) {
73 error(err_afmval
, in
->pos
, "StartFontMetrics", 1);
76 if (atof(val
) >= 5.0) {
77 error(err_afmvers
, &in
->pos
);
82 line
= afm_read_line(in
);
85 key
= strtok(line
, " \t");
86 if (strcmp(key
, "EndFontMetrics") == 0) {
91 } else if (strcmp(key
, "FontName") == 0) {
92 if (!(val
= strtok(NULL
, " \t"))) {
93 error(err_afmval
, &in
->pos
, key
, 1);
96 fi
->name
= dupstr(val
);
97 } else if (strcmp(key
, "FontBBox") == 0) {
99 for (i
= 0; i
< 3; i
++) {
100 if (!(val
= strtok(NULL
, " \t"))) {
101 error(err_afmval
, &in
->pos
, key
, 4);
104 fi
->fontbbox
[i
] = atof(val
);
106 } else if (strcmp(key
, "CapHeight") == 0) {
107 if (!(val
= strtok(NULL
, " \t"))) {
108 error(err_afmval
, &in
->pos
, key
, 1);
111 fi
->capheight
= atof(val
);
112 } else if (strcmp(key
, "XHeight") == 0) {
113 if (!(val
= strtok(NULL
, " \t"))) {
114 error(err_afmval
, &in
->pos
, key
, 1);
117 fi
->xheight
= atof(val
);
118 } else if (strcmp(key
, "Ascender") == 0) {
119 if (!(val
= strtok(NULL
, " \t"))) {
120 error(err_afmval
, &in
->pos
, key
, 1);
123 fi
->ascent
= atof(val
);
124 } else if (strcmp(key
, "Descender") == 0) {
125 if (!(val
= strtok(NULL
, " \t"))) {
126 error(err_afmval
, &in
->pos
, key
, 1);
129 fi
->descent
= atof(val
);
130 } else if (strcmp(key
, "CapHeight") == 0) {
131 if (!(val
= strtok(NULL
, " \t"))) {
132 error(err_afmval
, &in
->pos
, key
, 1);
135 fi
->capheight
= atof(val
);
136 } else if (strcmp(key
, "StdHW") == 0) {
137 if (!(val
= strtok(NULL
, " \t"))) {
138 error(err_afmval
, &in
->pos
, key
, 1);
141 fi
->stemh
= atof(val
);
142 } else if (strcmp(key
, "StdVW") == 0) {
143 if (!(val
= strtok(NULL
, " \t"))) {
144 error(err_afmval
, &in
->pos
, key
, 1);
147 fi
->stemv
= atof(val
);
148 } else if (strcmp(key
, "ItalicAngle") == 0) {
149 if (!(val
= strtok(NULL
, " \t"))) {
150 error(err_afmval
, &in
->pos
, key
, 1);
153 fi
->italicangle
= atof(val
);
154 } else if (strcmp(key
, "StartCharMetrics") == 0) {
158 if (!(val
= strtok(NULL
, " \t"))) {
159 error(err_afmval
, &in
->pos
, key
, 1);
162 fi
->nglyphs
= atoi(val
);
164 glyphs
= snewn(fi
->nglyphs
, char const *);
165 widths
= snewn(fi
->nglyphs
, int);
166 for (i
= 0; i
< fi
->nglyphs
; i
++) {
168 line
= afm_read_line(in
);
171 key
= strtok(line
, " \t");
172 while (key
!= NULL
) {
173 if (strcmp(key
, "WX") == 0 || strcmp(key
, "W0X") == 0) {
174 if (!(val
= strtok(NULL
, " \t")) ||
176 error(err_afmval
, &in
->pos
, key
, 1);
179 widths
[i
] = atoi(val
);
180 } else if (strcmp(key
, "N") == 0) {
181 if (!(val
= strtok(NULL
, " \t")) ||
183 error(err_afmval
, &in
->pos
, key
, 1);
186 glyphs
[i
] = dupstr(val
);
189 key
= strtok(NULL
, " \t");
190 } while (key
&& strcmp(key
, ";"));
191 key
= strtok(NULL
, " \t");
195 line
= afm_read_line(in
);
196 if (!line
|| !afm_require_key(line
, "EndCharMetrics", in
))
202 for (i
= 0; i
< fi
->nglyphs
; i
++) {
204 ucs
= ps_glyph_to_unicode(fi
->glyphs
[i
]);
208 font_index_glyphs(fi
);
209 } else if (strcmp(key
, "StartKernPairs") == 0 ||
210 strcmp(key
, "StartKernPairs0") == 0) {
213 if (!(val
= strtok(NULL
, " \t"))) {
214 error(err_afmval
, &in
->pos
, key
, 1);
219 kerns
= snewn(nkerns
, kern_pair
);
220 for (i
= 0; i
< nkerns
; i
++) {
221 line
= afm_read_line(in
);
224 key
= strtok(line
, " \t");
225 if (strcmp(key
, "KPX") == 0) {
229 nl
= strtok(NULL
, " \t");
230 nr
= strtok(NULL
, " \t");
231 val
= strtok(NULL
, " \t");
233 error(err_afmval
, &in
->pos
, key
, 3);
236 l
= find_glyph(fi
, nl
);
237 r
= find_glyph(fi
, nr
);
238 if (l
== -1 || r
== -1) continue;
239 kp
= snew(kern_pair
);
242 kp
->kern
= atoi(val
);
243 add234(fi
->kerns
, kp
);
246 line
= afm_read_line(in
);
247 if (!line
|| !afm_require_key(line
, "EndKernPairs", in
))