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
->ligs
= newtree234(lig_cmp
);
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;
67 for (i
= 0; i
< lenof(fi
->bmp
); i
++)
70 line
= afm_read_line(in
);
71 if (!line
|| !afm_require_key(line
, "StartFontMetrics", in
))
73 if (!(val
= strtok(NULL
, " \t"))) {
74 error(err_afmval
, in
->pos
, "StartFontMetrics", 1);
77 if (atof(val
) >= 5.0) {
78 error(err_afmvers
, &in
->pos
);
83 line
= afm_read_line(in
);
86 key
= strtok(line
, " \t");
87 if (strcmp(key
, "EndFontMetrics") == 0) {
92 } else if (strcmp(key
, "FontName") == 0) {
93 if (!(val
= strtok(NULL
, " \t"))) {
94 error(err_afmval
, &in
->pos
, key
, 1);
97 fi
->name
= dupstr(val
);
98 } else if (strcmp(key
, "FontBBox") == 0) {
100 for (i
= 0; i
< 3; i
++) {
101 if (!(val
= strtok(NULL
, " \t"))) {
102 error(err_afmval
, &in
->pos
, key
, 4);
105 fi
->fontbbox
[i
] = atof(val
);
107 } else if (strcmp(key
, "CapHeight") == 0) {
108 if (!(val
= strtok(NULL
, " \t"))) {
109 error(err_afmval
, &in
->pos
, key
, 1);
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);
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);
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);
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);
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);
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);
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);
154 fi
->italicangle
= atof(val
);
155 } else if (strcmp(key
, "StartCharMetrics") == 0) {
159 if (!(val
= strtok(NULL
, " \t"))) {
160 error(err_afmval
, &in
->pos
, key
, 1);
163 fi
->nglyphs
= atoi(val
);
165 glyphs
= snewn(fi
->nglyphs
, char const *);
166 widths
= snewn(fi
->nglyphs
, int);
167 for (i
= 0; i
< fi
->nglyphs
; i
++) {
169 line
= afm_read_line(in
);
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")) ||
177 error(err_afmval
, &in
->pos
, key
, 1);
180 widths
[i
] = atoi(val
);
181 } else if (strcmp(key
, "N") == 0) {
182 if (!(val
= strtok(NULL
, " \t")) ||
184 error(err_afmval
, &in
->pos
, key
, 1);
187 glyphs
[i
] = dupstr(val
);
190 key
= strtok(NULL
, " \t");
191 } while (key
&& strcmp(key
, ";"));
192 key
= strtok(NULL
, " \t");
196 line
= afm_read_line(in
);
197 if (!line
|| !afm_require_key(line
, "EndCharMetrics", in
))
203 for (i
= 0; i
< fi
->nglyphs
; i
++) {
205 ucs
= ps_glyph_to_unicode(fi
->glyphs
[i
]);
209 font_index_glyphs(fi
);
210 } else if (strcmp(key
, "StartKernPairs") == 0 ||
211 strcmp(key
, "StartKernPairs0") == 0) {
214 if (!(val
= strtok(NULL
, " \t"))) {
215 error(err_afmval
, &in
->pos
, key
, 1);
220 kerns
= snewn(nkerns
, kern_pair
);
221 for (i
= 0; i
< nkerns
; i
++) {
222 line
= afm_read_line(in
);
225 key
= strtok(line
, " \t");
226 if (strcmp(key
, "KPX") == 0) {
230 nl
= strtok(NULL
, " \t");
231 nr
= strtok(NULL
, " \t");
232 val
= strtok(NULL
, " \t");
234 error(err_afmval
, &in
->pos
, key
, 3);
237 l
= find_glyph(fi
, nl
);
238 r
= find_glyph(fi
, nr
);
239 if (l
== -1 || r
== -1) continue;
240 kp
= snew(kern_pair
);
243 kp
->kern
= atoi(val
);
244 add234(fi
->kerns
, kp
);
247 line
= afm_read_line(in
);
248 if (!line
|| !afm_require_key(line
, "EndKernPairs", in
))