1 /* vf.c -- VF font support */
2 /*
3  * Copyright (C) 2000, Matias Atria
4  *
5  * This program is free software; you can redistribute it and/or modify
6  * it under the terms of the GNU General Public License as published by
7  * the Free Software Foundation; either version 2 of the License, or
8  * (at your option) any later version.
9  *
10  * This program is distributed in the hope that it will be useful,
11  * but WITHOUT ANY WARRANTY; without even the implied warranty of
12  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  * GNU General Public License for more details.
14  *
15  * You should have received a copy of the GNU General Public License
16  * along with this program; if not, write to the Free Software
17  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
18  */
19 
20 #include <config.h>
21 #include <string.h>
22 
23 #include "mdvi.h"
24 #include "private.h"
25 
26 static int  vf_load_font __PROTO((DviParams *, DviFont *));
27 static void vf_free_macros __PROTO((DviFont *));
28 
29 /* only symbol exported by this file */
30 DviFontInfo vf_font_info = {
31 	"VF",
32 	1, /* virtual fonts scale just fine */
33 	vf_load_font,
34 	NULL,	/* get_glyph */
35 	NULL,	/* shrink0 */
36 	NULL,	/* shrink1 */
37 	vf_free_macros,
38 	NULL,	/* reset */
39 	NULL,	/* lookup */
40 	kpse_vf_format,
41 	NULL
42 };
43 
44 DviFontInfo ovf_font_info = {
45 	"OVF",
46 	1, /* virtual fonts scale just fine */
47 	vf_load_font,
48 	NULL,	/* get_glyph */
49 	NULL,	/* shrink0 */
50 	NULL,	/* shrink1 */
51 	vf_free_macros,
52 	NULL,	/* reset */
53 	NULL,	/* lookup */
54 	kpse_ovf_format,
55 	NULL
56 };
57 
vf_load_font(DviParams * params,DviFont * font)58 static int vf_load_font(DviParams *params, DviFont *font)
59 {
60 	FILE	*p;
61 	Uchar	*macros;
62 	int	msize;
63 	int	mlen;
64 	Int32	checksum;
65 	long	alpha, beta, z;
66 	int	op;
67 	int	i;
68 	int	nchars;
69 	int	loc, hic;
70 	DviFontRef *last;
71 
72 	macros = NULL;
73 	msize = mlen = 0;
74 	p = font->in;
75 
76 	if(fuget1(p) != 247 || fuget1(p) != 202)
77 		goto badvf;
78 	mlen = fuget1(p);
79 	fseek(p, (long)mlen, SEEK_CUR);
80 	checksum = fuget4(p);
81 	if(checksum && font->checksum && checksum != font->checksum) {
82 		mdvi_warning(_("%s: Checksum mismatch (expected %u, got %u)\n"),
83 			     font->fontname, font->checksum, checksum);
84 	} else if(!font->checksum)
85 		font->checksum = checksum;
86 	font->design = fuget4(p);
87 
88 	/* read all the fonts in the preamble */
89 	last = NULL;
90 
91 	/* initialize alpha, beta and z for TFM width computation */
92 	TFMPREPARE(font->scale, z, alpha, beta);
93 
94 	op = fuget1(p);
95 	while(op >= DVI_FNT_DEF1 && op <= DVI_FNT_DEF4) {
96 		DviFontRef *ref;
97 		Int32	scale, design;
98 		Uint32	checksum;
99 		int	id;
100 		int	n;
101 		int	hdpi;
102 		int	vdpi;
103 		char	*name;
104 
105 		/* process fnt_def commands */
106 
107 		id = fugetn(p, op - DVI_FNT_DEF1 + 1);
108 		checksum = fuget4(p);
109 		scale = fuget4(p);
110 		design = fuget4(p);
111 
112 		/* scale this font according to our parent's scale */
113 		scale = TFMSCALE(scale, z, alpha, beta);
114 		design = FROUND(params->tfm_conv * design);
115 
116 		/* compute the resolution */
117 		hdpi = FROUND(params->mag * params->dpi * scale / design);
118 		vdpi = FROUND(params->mag * params->vdpi * scale / design);
119 		n = fuget1(p) + fuget1(p);
120 		name = mdvi_malloc(n + 1);
121 		fread(name, 1, n, p);
122 		name[n] = 0;
123 		DEBUG((DBG_FONTS, "(vf) %s: defined font `%s' at %.1fpt (%dx%d dpi)\n",
124 			font->fontname, name,
125 			(double)scale / (params->tfm_conv * 0x100000), hdpi, vdpi));
126 
127 		/* get the font */
128 		ref = font_reference(params, id, name, checksum, hdpi, vdpi, scale);
129 		if(ref == NULL) {
130 			mdvi_error(_("(vf) %s: could not load font `%s'\n"),
131 				   font->fontname, name);
132 			goto error;
133 		}
134 		mdvi_free(name);
135 		if(last == NULL)
136 			font->subfonts = last = ref;
137 		else {
138 			last->next = ref;
139 			last = ref;
140 		}
141 		ref->next = NULL;
142 		op = fuget1(p);
143 	}
144 
145 	if(op >= DVI_FNT_DEF1 && op <= DVI_FNT_DEF4)
146 		goto error;
147 
148 	/* This function correctly reads both .vf and .ovf files */
149 
150 	font->chars = xnalloc(DviFontChar, 256);
151 	for(i = 0; i < 256; i++)
152 		font->chars[i].offset = 0;
153 	nchars = 256;
154 	loc = -1; hic = -1;
155 	/* now read the characters themselves */
156 	while(op <= 242) {
157 		int	pl;
158 		Int32	cc;
159 		Int32	tfm;
160 
161 		if(op == 242) {
162 			pl = fuget4(p);
163 			cc = fuget4(p);
164 			tfm = fuget4(p);
165 		} else {
166 			pl = op;
167 			cc = fuget1(p);
168 			tfm = fuget3(p);
169 		}
170 		if (cc < 0 || cc > 65536) {
171 			/* TeX engines do not support char codes bigger than 65535 */
172 			mdvi_error(_("(vf) %s: unexpected character %d\n"),
173 				   font->fontname, cc);
174 			goto error;
175 		}
176 		if(loc < 0 || cc < loc)
177 			loc = cc;
178 		if(hic < 0 || cc > hic)
179 			hic = cc;
180 		if(cc >= nchars) {
181 			font->chars = xresize(font->chars,
182 				DviFontChar, cc + 16);
183 			for(i = nchars; i < cc + 16; i++)
184 				font->chars[i].offset = 0;
185 			nchars = cc + 16;
186 		}
187 		if(font->chars[cc].offset) {
188 			mdvi_error(_("(vf) %s: character %d redefined\n"),
189 				   font->fontname, cc);
190 			goto error;
191 		}
192 
193 		DEBUG((DBG_GLYPHS, "(vf) %s: defined character %d (macro length %d)\n",
194 			font->fontname, cc, pl));
195 		font->chars[cc].width = pl + 1;
196 		font->chars[cc].code = cc;
197 		font->chars[cc].tfmwidth = TFMSCALE(tfm, z, alpha, beta);
198 		font->chars[cc].offset = mlen;
199 		font->chars[cc].loaded = 1;
200 		if(mlen + pl + 1 > msize) {
201 			msize = mlen + pl + 256;
202 			macros = xresize(macros, Uchar, msize);
203 		}
204 		if(pl && fread(macros + mlen, 1, pl, p) != pl)
205 			break;
206 		macros[mlen+pl] = DVI_EOP;
207 		mlen += pl + 1;
208 		op = fuget1(p);
209 	}
210 	if(op != 248) {
211 		mdvi_error(_("(vf) %s: no postamble\n"), font->fontname);
212 		goto error;
213 	}
214 
215 	/* make macro memory just big enough */
216 	if(msize > mlen) {
217 		macros = xresize(macros, Uchar, mlen);
218 		msize = mlen;
219 	}
220 
221 	DEBUG((DBG_FONTS|DBG_GLYPHS,
222 		"(vf) %s: macros use %d bytes\n", font->fontname, msize));
223 
224 	if(loc > 0 || hic < nchars-1) {
225 		memmove(font->chars, font->chars + loc,
226 			(hic - loc + 1) * sizeof(DviFontChar));
227 		font->chars = xresize(font->chars,
228 			DviFontChar, hic - loc + 1);
229 	}
230 	font->loc = loc;
231 	font->hic = hic;
232 	font->private = macros;
233 
234 	return 0;
235 
236 badvf:
237 	mdvi_error(_("%s: File corrupted, or not a VF file.\n"), font->fontname);
238 error:
239 	if(font->chars)
240 		mdvi_free(font->chars);
241 	if(macros)
242 		mdvi_free(macros);
243 	return -1;
244 }
245 
vf_free_macros(DviFont * font)246 static void vf_free_macros(DviFont *font)
247 {
248 	mdvi_free(font->private);
249 }
250