summaryrefslogtreecommitdiff
path: root/dviware/dvi2pcl/dopage.c
blob: ce269cc50c684e55c40a65fcbd882318c0370e6e (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
/* $Log:	dopage.c,v $
 * Revision 0.8  92/11/23  19:46:41  19:46:41  bt (Bo Thide')
 * Fixed resolution bug. Portable downloading. Added/changed options. PJXL color support
 * 
 * Revision 0.7  92/11/13  02:41:25  02:41:25  bt (Bo Thide')
 * More bug fixes and improvements. Support for PaintJet XL
 * 
 * Revision 0.6  92/11/10  21:47:41  21:47:41  bt (Bo Thide')
 * Bug fixes. Added -R option. Better font handling.
 * 
 * Revision 0.5  92/11/09  16:25:28  16:25:28  bt (Bo Thide')
 * Rewrite of dospecial.c. Extended \special support
 * 
 * Revision 0.4  92/11/08  02:45:44  02:45:44  bt (Bo Thide')
 * Changed to portable bit manipulations. Replaced strrstr for non-POSIX compliant C. Fixed numerous bugs. Added support for more \special's.
 * 
 * Revision 0.3  92/08/24  12:45:36  12:45:36  bt (Bo Thide')
 * Fixed 8 bit (dc font) support.
 * 
 * Revision 0.2  92/08/23  17:28:55  17:28:55  bt (Bo Thide')
 * Source cleaned up.  Changed certain function calls.  Removed globals.
 * 
 * Revision 0.1  92/08/22  23:58:47  23:58:47  bt (Bo Thide')
 * First Release.
 *  */

/*
 * This is the main printer dependent output routine, which is organized as
 * a function with side effects. The subroutine is organized as a typical
 * interpreter, with a multiway branch of the command code followed by 'goto'
 * statements leading to branches that finish up the activities common to
 * different commands.  dopage() aborts `dvi2pcl' if something unusual happens.
 *
 * The definition of dvi files refer to six registers, (h,v,w,x,y,z),  which
 * hold integer values in dvi units. In practice, we also need registers hh
 * and vv, the pixel analogs of h and v, since it is not always true that
 * hh = pixel_round(h) or vv = pixel_round(v).
 * The stack of (h,w,w,x,y,z) values is represented by eight arrays called
 * hstack,...,zstack, hhstack and vvstack.
 */

#include <stdio.h>
#include "dvi.h"
#include "globals.h"
#include "macros.h"
#include "pcl.h"

static char rcsid[] = "$Header: dopage.c,v 0.8 92/11/23 19:46:41 bt Exp $";

dopage(bitfile, dvifile, pcllevel, resolution, device)
FILE	*bitfile;
FILE	*dvifile;
short	pcllevel;
short	resolution;
short	device;
{
	unsigned char	o;
	int		k;
	int		hhh, vvv;
	bool		badchar;
	long		hh, vv;
	long		p, q;
	long		hstack[STACKSIZE], vstack[STACKSIZE], wstack[STACKSIZE];
	long		xstack[STACKSIZE], ystack[STACKSIZE], zstack[STACKSIZE];
	int		hhstack[STACKSIZE], vvstack[STACKSIZE];
	charfmt		*c;

	h_posed = v_posed = FALSE;
	s = hh = vv = h = v = w = x = y = z = 0;
	font = NULL;
	while (TRUE) {
		o = getubyte(dvifile);
		if(o >= DVI_SET1)
			p = firstpar(dvifile, o);
#ifdef DEBUG
		fprintf(stderr,"\ndopage: o = %d, p = %ld, hh = %ld", o, p, hh);
#endif
		if(o < DVI_SET1) { 
			c = drawchar(bitfile, o, hh, vv, resolution, device);
			q = c->tfm_width;
			hh += c->pxl_width;
			goto move_right;
		} else
			switch(o) { 
			case DVI_SET1:
			case DVI_SET2:
			case DVI_SET3:
			case DVI_SET4:
				c = drawchar(bitfile, p, hh, vv, resolution,
				  device);
				q = c->tfm_width;
				hh += c->pxl_width;
				goto move_right;
				break;
			case DVI_PUT1:
			case DVI_PUT2:
			case DVI_PUT3:
			case DVI_PUT4:
				drawchar(bitfile, p, hh, vv, resolution,
				  device);
				goto done;
				break;
			case DVI_SET_RULE:
				q = (long)getsquad(dvifile);
				drawrule(bitfile, rulepixels(p, conv),
				  rulepixels(q, conv), hh, vv);
				hh += rulepixels(q, conv);
				goto move_right;
				break;
			case DVI_PUT_RULE:
				q = (long)getsquad(dvifile);
				drawrule(bitfile, rulepixels(p, conv),
				  rulepixels(q, conv), hh, vv);
				goto done;
				break;
			case DVI_NOP:
				goto done;
				break;
			case DVI_BOP:
				fprintf(stderr,"\n'DVI_BOP' occurred before 'DVI_EOP'");
				goto endfalse;
				break;
			case DVI_EOP:
				if(maxpages)
					putc('\014',bitfile);  /* Formfeed */
				if(s)
					fprintf(stderr,"\nStack not empty at end of page");
				return (TRUE);
				break;
			case DVI_PUSH:
				if(s == maxssofar) { 
					maxssofar++;
					if(s ==	maxs)
						fprintf(stderr,"\nDeeper than claimed in postamble");
					if(s == STACKSIZE) { 
						fprintf(stderr,"\nStack capacity exceeded");
					goto endfalse;
					}
				}
				hstack[s] = h;
				vstack[s] = v;
				wstack[s] = w;
				xstack[s] = x;
				ystack[s] = y;
				zstack[s] = z;
				hhstack[s] = hh;
				vvstack[s] = vv;
				s++;
				goto done;
				break;
			case DVI_POP:
				if(s) { 
					s--;
					if(hh != hhstack[s]) h_posed = FALSE;
					if(vv != vvstack[s]) v_posed = FALSE;
					h = hstack[s];
					v = vstack[s];
					w = wstack[s];
					x = xstack[s];
					y = ystack[s];
					z = zstack[s];
					hh = hhstack[s];
					vv = vvstack[s];
				}
				else
					fprintf(stderr,"\nIllegal at level zero");
				goto done;
				break;
			case DVI_RIGHT1:
			case DVI_RIGHT2:
			case DVI_RIGHT3:
			case DVI_RIGHT4:
				goto out_space;
				break;
			case DVI_W0:
			case DVI_W1:
			case DVI_W2:
			case DVI_W3:
			case DVI_W4:
				w = p;
				goto out_space;
				break;
			case DVI_X0:
			case DVI_X1:
			case DVI_X2:
			case DVI_X3:
			case DVI_X4:
				x = p;
				goto out_space;
				break;
			case DVI_DOWN1:
			case DVI_DOWN2:
			case DVI_DOWN3:
			case DVI_DOWN4:
				goto move_down;
				break;
			case DVI_Y0:
			case DVI_Y1:
			case DVI_Y2:
			case DVI_Y3:
			case DVI_Y4:
				y = p;
				goto move_down;
				break;
			case DVI_Z0:
			case DVI_Z1:
			case DVI_Z2:
			case DVI_Z3:
			case DVI_Z4:
				z = p;
				goto move_down;
				break;
			case DVI_FNT_DEF1:
			case DVI_FNT_DEF2:
			case DVI_FNT_DEF3:
			case DVI_FNT_DEF4:
				skipfontdef(dvifile);
				goto done;
				break;
			case DVI_XXX1:
			case DVI_XXX2:
			case DVI_XXX3:
			case DVI_XXX4:
				badchar = FALSE;
				if((long)nextnamesfree - (long)names + p > NAMESIZE )
					prerror("Out of string space during special\n");
				for(k = 0 ; k < (int)p ; k++) { 
					q = (long)getubyte(dvifile);
					if((q < ' ') || (q > '~'))
						badchar = TRUE;
					*(nextnamesfree + k) = (char)q;
				}
				*(nextnamesfree + p) = 0;
				if(badchar)
					fprintf(stderr,"\nNon-ASCII character in xxx command");
				dospecial(bitfile, PRESCAN_OFF, pcllevel, hh,
				  vv, resolution);
				goto done;
				break;
			case DVI_PRE:
				fprintf(stderr,"\nPreamble command within a page");
				goto endfalse;
				break;
			case DVI_POST:
			case DVI_POSTPOST:
				fprintf(stderr,"\nPostamble command within a page");
				goto endfalse;
				break;
			case DVI_UNDEF0:
			case DVI_UNDEF1:
			case DVI_UNDEF2:
			case DVI_UNDEF3:
			case DVI_UNDEF4:
			case DVI_UNDEF5:
				fprintf(stderr,"\nUndefined DVI command %d.",o);
				goto done;
				break;
			default:
				font = fontptr[p];
				gfont = gfontptr[p];
				if(font->down > 0)
					fprintf(bitfile, PCL4_SELECT_FONT, font->down);
				goto done;
				break;
			}
	
out_space:
		if((font == NULL) || (p >= font->space) || (p <= -4*font->space))
			hh = round(conv*(h+p));
		else
			hh += round(conv*p);
		q = p;
		h_posed = FALSE;
move_right:
		hhh = round(conv*(h+q));
		if(abs(hhh - hh) > MAXDRIFT) { 
			h_posed = FALSE;
			hh = hhh > hh ? hhh - MAXDRIFT : hhh + MAXDRIFT;
		}
		h += q;
		if((long)abs(h) > maxhsofar) { 
			if(((long)abs(h) > maxh + 99) && verbose) { 
				fprintf(stderr,"\n|h| > %d\n", maxh);
				maxh = (long)abs(h);
			}
			maxhsofar = (long)abs(h);
		}
		goto done;

move_down:
		if((font == NULL) || ((long)abs(p) >= 5*font->space))
			vv = round(conv*(v+p));
		else
			vv += round(conv*p);
		v_posed = FALSE;
		if((v > 0) &&  (p > 0) && (v > INFINITY-p))
			fprintf(stderr,"Arithmetic overflow.  Parameter changed from %d to %d.", p, p=INFINITY-v);
		if((v < 0) && (p < 0) && (-v > INFINITY+p))
			fprintf(stderr,"\ndopage: Arithmetic overflow.  Parameter changed from %d to %d.", p, p = -(INFINITY+v));
		vvv = round(conv*(v+p));
		if(abs(vvv - vv) > MAXDRIFT)
			vv = vvv > vv ? vvv - MAXDRIFT : vvv + MAXDRIFT;
		v += p;
		if((long)abs(v) > maxvsofar) { 
			if(((long)abs(v) > maxv + 99) && verbose) { 
				fprintf(stderr,"\n|v| > %d.",maxv);
				maxv = (long)abs(v);
			}
			maxvsofar = (long)abs(v);
		}
		goto done;

done:
		;
	}
endfalse: 
	prerror("\n! Bad .pcl file: page ended unexpectedly !\n");
}