1 /***************************************************************************
2 JSPICE3 adaptation of Spice3e2 - Copyright (c) Stephen R. Whiteley 1992
3 Copyright 1990 Regents of the University of California.  All rights reserved.
4 Author:  1992 Stephen R. Whiteley
5 ****************************************************************************/
6 
7 /*
8  * Hewlett-Packard Laserjet (and compatible) driver.
9  */
10 
11 #include "spice.h"
12 #include "plotdev.h"
13 
14 static FILE *plotfile;
15 
16 struct hptext {
17     int x;
18     int y;
19     char *text;
20     struct hptext *next;
21 };
22 
23 struct hplaser {
24     int bytpline;
25     int maxx;
26     int maxy;
27     char *base;
28     struct hptext *textlist;
29     unsigned char linestyle;
30     unsigned char linestyle_stored;
31 };
32 
33 #define ror(x,n) ((x >> n)  | (x << (8-n)))
34 #define swap(a,b) {int t=a; a=b; b=t;}
35 
36 /* upper left of image in pcl coordinates */
37 #define OFFSETX 0
38 #define OFFSETY 90
39 
40 /* dots per inch (75, 100, 150, 300) */
41 #define RESOL  150
42 
43 int
HP_Init()44 HP_Init()
45 
46 {
47     dispdev->numlinestyles = 1;
48     dispdev->numcolors = 2;
49 
50     /* 8" X 10.5" drawable area */
51     dispdev->width = 8*RESOL;
52     dispdev->height = 10*RESOL + RESOL/2;
53     return (0);
54 }
55 
56 
57 int
HP_NewViewport(graph)58 HP_NewViewport(graph)
59 
60 /* devdep initially contains name of output file */
61 GRAPH *graph;
62 {
63     struct hplaser *hp;
64     int bpline;
65 
66     plotfile = fopen((char*)graph->devdep, "wb");
67     if (!plotfile) {
68         perror(graph->devdep);
69         graph->devdep = (char *) NULL;
70         return (1);
71     }
72     graph->devdep = tmalloc(sizeof(struct hplaser));
73     hp = (struct hplaser*)graph->devdep;
74 
75     switch (graph->graphtype) {
76         default:
77         case GR_PLOT:
78         case GR_GRAF:
79         case GR_MPLT:
80             /* square plotting area */
81             graph->absolute.width = dispdev->width;
82             graph->absolute.height = dispdev->width;
83             break;
84         case GR_SCED:
85             /* full page plot */
86             graph->absolute.width = dispdev->width;
87             graph->absolute.height = dispdev->height;
88             break;
89     }
90     /* bytes per line */
91     bpline = (graph->absolute.width + 7)/8;
92 
93     hp->base = malloc(graph->absolute.height*bpline);
94     if (hp->base == NULL) {
95         internalerror("Not enough memory for raster conversion");
96         return (1);
97     }
98     memset(hp->base,0,graph->absolute.height*bpline);
99 
100     graph->fontwidth = 15;
101     graph->fontheight = 30;
102 
103     hp->bytpline = bpline;
104     hp->maxx = graph->absolute.width - 1;
105     hp->maxy = graph->absolute.height - 1;
106     hp->linestyle = 0xff;
107     hp->linestyle_stored = 0xcc;
108     return (0);
109 }
110 
111 
112 int
HP_Close()113 HP_Close()
114 
115 {
116     return (0);
117 }
118 
119 
120 int
HP_Halt()121 HP_Halt()
122 
123 {
124     struct hplaser *hp = (struct hplaser *)currentgraph->devdep;
125     struct hptext *old;
126     char *buf, *rgen, *c;
127     int len, i;
128 
129     /* dump the stuff */
130 
131     /* reset printer
132      * top margin 10
133      * X cursor position OFFSETX
134      * Y cursor position OFFSETY
135      * resolution RESOL dpi
136      * start raster graphics at current position
137      */
138     fprintf(plotfile,
139         "\033E\033&l0E\033*p%dX\033*p%dY\033*t%dR\033*r1A",
140         OFFSETX,OFFSETY,RESOL);
141 
142     buf = tmalloc(hp->bytpline+8);
143     sprintf(buf,"\033*b%dW",hp->bytpline);
144     len = strlen(buf);
145     c = buf + len;
146 
147     rgen = hp->base;
148     for (i = 0; i <= hp->maxy; i++) {
149         memcpy(c,rgen,hp->bytpline);
150         rgen += hp->bytpline;
151 
152         if (fwrite(buf,1,hp->bytpline+len,plotfile) != hp->bytpline+len) {
153             break;
154         }
155 
156     }
157     /* end raster graphics */
158     fprintf(plotfile,"\033*rB");
159 
160     /* now for the text */
161 
162     while (hp->textlist) {
163         /* x position, y position, text */
164         fprintf(plotfile,"\033*p%dX\033*p%dY%s",
165             hp->textlist->x,hp->textlist->y,hp->textlist->text);
166         txfree(hp->textlist->text);
167         old = hp->textlist;
168         hp->textlist = hp->textlist->next;
169         txfree((char*)old);
170     }
171 
172     /* form feed
173      * reset printer
174      */
175     fprintf(plotfile,"\033*rB\014\033E");
176 
177     txfree(buf);
178     txfree(hp->base);
179     fclose(plotfile);
180     return (0);
181 }
182 
183 
184 int
HP_Pixel(x,y)185 HP_Pixel(x, y)
186 
187 int x, y;
188 {
189     unsigned char c;
190     struct hplaser *hp = (struct hplaser *)currentgraph->devdep;
191 
192     c = 0x80 >> (x & 7);
193         *(hp->base + ((x >> 3) + (hp->maxy-y)*hp->bytpline)) |= c;
194     return (0);
195 }
196 
197 
198 int
HP_Line(x1,y1,x2,y2)199 HP_Line(x1, y1, x2, y2)
200 
201 int x1, y1, x2, y2;
202 {
203 
204     struct hplaser *hp = (struct hplaser *)currentgraph->devdep;
205     int dx, dy, dy2, errterm = 0, next, lcnt;
206     char *rgen;
207     unsigned char cbuf, left, right;
208 
209     if (x2 < x1) {
210         swap(x1,x2);
211         swap(y1,y2);
212     }
213     dx = x2 - x1;
214 
215     next = hp->bytpline;
216     dy = y1 - y2;
217 
218     lcnt = hp->maxy - y1;
219     rgen = hp->base + (x1 >> 3) + lcnt*next;
220     left = 0x80 >> ((lcnt+x1) & 7);
221     right = hp->linestyle;
222 
223     if (y1 < y2) {
224         next = -next;
225         dy = -dy;
226     }
227     dy2 = dy;
228 
229     cbuf = 0x80 >> (x1 & 7);
230 
231     for (dy++; dy; dy--) {
232         errterm += dx;
233         if (errterm <= 0) {
234             if (left & right) *rgen |= cbuf;
235             rgen += next;
236             left = ror(left,1);
237             continue;
238         }
239         while (errterm > 0 && x1 != x2) {
240             if (left & right) *rgen |= cbuf;
241             left = ror(left,1);
242             cbuf = ror(cbuf,1);
243             if (cbuf & 0x80) rgen++;
244             x1++;
245             errterm -= dy2;
246         }
247         rgen += next;
248         left = ror(left,1);
249     }
250     return (0);
251 }
252 
253 
254 int
HP_Box(x1,y1,x2,y2)255 HP_Box(x1, y1, x2, y2)
256 
257 int x1, y1, x2, y2;
258 {
259     HP_Line(x1,y1,x1,y2);
260     HP_Line(x1,y2,x2,y2);
261     HP_Line(x2,y2,x2,y1);
262     HP_Line(x2,y1,x1,y1);
263     return (0);
264 }
265 
266 
267 /* ARGSUSED */
268 int
HP_Arc(x0,y0,radius,theta1,theta2)269 HP_Arc(x0, y0, radius, theta1, theta2)
270 
271 int x0, y0, radius;
272 double theta1, theta2;
273 {
274     return (0);
275 }
276 
277 
278 int
HP_Polygon(p)279 HP_Polygon(p)
280 
281 POLYGON *p;
282 {
283     int i, n = 2*p->nvertices - 2;
284 
285     for (i = 0; i < n; i += 2)
286         HP_Line(p->xy[i],p->xy[i+1],p->xy[i+2],p->xy[i+3]);
287 
288     return (0);
289 }
290 
291 
292 int
HP_Text(text,x,y)293 HP_Text(text, x, y)
294 
295 char *text;
296 int x, y;
297 {
298     struct hplaser *hp = (struct hplaser *)currentgraph->devdep;
299     struct hptext *hpt;
300 
301     hpt = (struct hptext *)tmalloc(sizeof(struct hptext));
302     hpt->x = x*(300/RESOL) + OFFSETX;
303     hpt->y = (hp->maxy - y)*(300/RESOL) + OFFSETY;
304     hpt->text = copy(text);
305     hpt->next = hp->textlist;
306     hp->textlist = hpt;
307     return (0);
308 }
309 
310 
311 int
HP_DefineLinestyle(linestyleid,mask)312 HP_DefineLinestyle(linestyleid,mask)
313 
314 int linestyleid, mask;
315 {
316     struct hplaser *hp = (struct hplaser *)currentgraph->devdep;
317 
318     if (linestyleid) {
319         hp->linestyle_stored = mask;
320         hp->linestyle = mask;
321     }
322 }
323 
324 
325 int
HP_SetLinestyle(linestyleid)326 HP_SetLinestyle(linestyleid)
327 
328 int linestyleid;
329 {
330     struct hplaser *hp = (struct hplaser *)currentgraph->devdep;
331 
332     if (linestyleid)
333         hp->linestyle = hp->linestyle_stored;
334     else
335         hp->linestyle = 0xff;
336     return (0);
337 }
338