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
;
60 fi
->kerns
= newtree234(kern_cmp
);
62 line
= afm_read_line(in
);
63 if (!line
|| !afm_require_key(line
, "StartFontMetrics", in
))
65 if (!(val
= strtok(NULL
, " \t"))) {
66 error(err_afmval
, in
->pos
, "StartFontMetrics", 1);
69 if (atof(val
) >= 5.0) {
70 error(err_afmvers
, &in
->pos
);
75 line
= afm_read_line(in
);
78 key
= strtok(line
, " \t");
79 if (strcmp(key
, "EndFontMetrics") == 0) {
84 } else if (strcmp(key
, "FontName") == 0) {
85 if (!(val
= strtok(NULL
, " \t"))) {
86 error(err_afmval
, &in
->pos
, key
, 1);
89 fi
->name
= dupstr(val
);
90 } else if (strcmp(key
, "StartCharMetrics") == 0) {
94 if (!(val
= strtok(NULL
, " \t"))) {
95 error(err_afmval
, &in
->pos
, key
, 1);
98 fi
->nglyphs
= atoi(val
);
100 glyphs
= snewn(fi
->nglyphs
, char const *);
101 widths
= snewn(fi
->nglyphs
, int);
102 for (i
= 0; i
< fi
->nglyphs
; i
++) {
104 line
= afm_read_line(in
);
107 key
= strtok(line
, " \t");
108 while (key
!= NULL
) {
109 if (strcmp(key
, "WX") == 0 || strcmp(key
, "W0X") == 0) {
110 if (!(val
= strtok(NULL
, " \t")) ||
112 error(err_afmval
, &in
->pos
, key
, 1);
115 widths
[i
] = atoi(val
);
116 } else if (strcmp(key
, "N") == 0) {
117 if (!(val
= strtok(NULL
, " \t")) ||
119 error(err_afmval
, &in
->pos
, key
, 1);
122 glyphs
[i
] = dupstr(val
);
125 key
= strtok(NULL
, " \t");
126 } while (key
&& strcmp(key
, ";"));
127 key
= strtok(NULL
, " \t");
131 line
= afm_read_line(in
);
132 if (!line
|| !afm_require_key(line
, "EndCharMetrics", in
))
138 for (i
= 0; i
< fi
->nglyphs
; i
++) {
140 ucs
= ps_glyph_to_unicode(fi
->glyphs
[i
]);
144 font_index_glyphs(fi
);
145 } else if (strcmp(key
, "StartKernPairs") == 0 ||
146 strcmp(key
, "StartKernPairs0") == 0) {
149 if (!(val
= strtok(NULL
, " \t"))) {
150 error(err_afmval
, &in
->pos
, key
, 1);
155 kerns
= snewn(nkerns
, kern_pair
);
156 for (i
= 0; i
< nkerns
; i
++) {
157 line
= afm_read_line(in
);
160 key
= strtok(line
, " \t");
161 if (strcmp(key
, "KPX") == 0) {
165 nl
= strtok(NULL
, " \t");
166 nr
= strtok(NULL
, " \t");
167 val
= strtok(NULL
, " \t");
169 error(err_afmval
, &in
->pos
, key
, 3);
172 l
= find_glyph(fi
, nl
);
173 r
= find_glyph(fi
, nr
);
174 if (l
== -1 || r
== -1) continue;
175 kp
= snew(kern_pair
);
178 kp
->kern
= atoi(val
);
179 add234(fi
->kerns
, kp
);
182 line
= afm_read_line(in
);
183 if (!line
|| !afm_require_key(line
, "EndKernPairs", in
))