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 Authors: 1988 Jeffrey M. Hsu
5 1992 Stephen R. Whiteley
6 ****************************************************************************/
7
8 /*
9 * Postscript driver
10 */
11
12 #include "spice.h"
13 #include "plotdev.h"
14
15 static FILE *plotfile;
16
17 #define SOLID 0
18 static char *linestyle[] = {
19 "[]", /* solid */
20 "[1 2]", /* dotted */
21 "[7 7]", /* longdashed */
22 "[3 3]", /* shortdashed */
23 "[3 5 1 5]" }; /* dotdashed */
24
25 typedef struct {
26 int lastlinestyle; /* initial invalid value */
27 int strokecnt; /* count line elements, avoid overflow */
28 } PSdevdep;
29
30 #define DEVDEP(g) (*((PSdevdep *) (g)->devdep))
31
32 static int Xoff, Yoff;
33
34 /* line memory */
35 static int lastx ,lasty;
36
37
38 int
PS_Init()39 PS_Init()
40 {
41 dispdev->numlinestyles = 4;
42 dispdev->numcolors = 2;
43
44 /* 8" X 10.5" drawable area */
45 dispdev->width = 576; /* 8 * 72 */
46 dispdev->height = 756; /* 10.5 * 72 */
47
48 return (0);
49 }
50
51
52 int
PS_NewViewport(graph)53 PS_NewViewport(graph)
54
55 /* devdep initially contains name of output file */
56 GRAPH *graph;
57 {
58
59 plotfile = fopen((char*)graph->devdep, "w");
60
61 if (!plotfile) {
62 perror(graph->devdep);
63 graph->devdep = (char *) NULL;
64 return (1);
65 }
66
67 switch (graph->graphtype) {
68 default:
69 case GR_PLOT:
70 case GR_GRAF:
71 case GR_MPLT:
72 /* square plotting area */
73 graph->absolute.width = dispdev->width;
74 graph->absolute.height = dispdev->width;
75 Xoff = 18;
76 Yoff = 108;
77 break;
78 case GR_SCED:
79 /* full page plot */
80 graph->absolute.width = dispdev->width;
81 graph->absolute.height = dispdev->height;
82 Xoff = 18;
83 Yoff = 18;
84 break;
85 }
86
87 /* start file off with a % */
88 fprintf(plotfile, "%%! nutmeg plot\n");
89
90 /* reasonable values, used in gr_ for placement */
91 graph->fontwidth = 5;
92 graph->fontheight = 10;
93
94 /* set up a reasonable font */
95 fprintf(plotfile, "/Helvetica findfont 10 scalefont setfont\n");
96
97 graph->devdep = tmalloc(sizeof(PSdevdep));
98 DEVDEP(graph).lastlinestyle = -1;
99 DEVDEP(graph).strokecnt = 0;
100 graph->linestyle = -1;
101 lastx = -1;
102 lasty = -1;
103
104 return (0);
105 }
106
107
108 int
PS_Close()109 PS_Close()
110
111 {
112 return (0);
113 }
114
115
116 int
PS_Halt()117 PS_Halt()
118 {
119
120 if (plotfile) {
121 if (DEVDEP(currentgraph).lastlinestyle != -1) {
122 /* haven't stroked last path */
123 fprintf(plotfile, "stroke\n");
124 }
125 fprintf(plotfile, "showpage\n");
126 fclose(plotfile);
127 }
128 return (0);
129 }
130
131
132 /* ARGSUSED */
133 int
PS_Pixel(x,y)134 PS_Pixel(x, y)
135
136 int x, y;
137 {
138 int savedlstyle;
139
140 savedlstyle = currentgraph->linestyle;
141 PS_SetLinestyle(SOLID);
142 if (DEVDEP(currentgraph).strokecnt > 499) {
143 if (DEVDEP(currentgraph).lastlinestyle == -1)
144 fprintf(plotfile, "newpath\n");
145 else
146 fprintf(plotfile, "stroke\n");
147 DEVDEP(currentgraph).strokecnt = 0;
148 }
149 fprintf(plotfile, "%d %d moveto\n", x+Xoff, y+Yoff);
150 fprintf(plotfile, "%d %d lineto\n", x+Xoff, y+Yoff+1);
151 (DEVDEP(currentgraph).strokecnt)++;
152 PS_SetLinestyle(savedlstyle);
153 return (0);
154 }
155
156
157 int
PS_Line(x1,y1,x2,y2)158 PS_Line(x1, y1, x2, y2)
159
160 int x1, y1, x2, y2;
161 {
162 /* clip out unchanged points */
163 if (x1 == x2 && y1 == y2 && x1 == lastx && y1 == lasty)
164 return (0);
165
166 if (currentgraph->linestyle == -1)
167 PS_SetLinestyle(SOLID);
168 if (DEVDEP(currentgraph).lastlinestyle != currentgraph->linestyle ||
169 DEVDEP(currentgraph).strokecnt > 499) {
170 if (DEVDEP(currentgraph).lastlinestyle == -1)
171 fprintf(plotfile, "newpath\n");
172 else
173 fprintf(plotfile, "stroke\n");
174 DEVDEP(currentgraph).strokecnt = 0;
175 }
176 if ((x1 != lastx) || (y1 != lasty) || !DEVDEP(currentgraph).strokecnt)
177 fprintf(plotfile, "%d %d moveto\n", x1+Xoff, y1+Yoff);
178 if ((x2 != x1) || (y2 != y1))
179 fprintf(plotfile, "%d %d lineto\n", x2+Xoff, y2+Yoff);
180
181 /* validate cache */
182 lastx = x2;
183 lasty = y2;
184 DEVDEP(currentgraph).lastlinestyle = currentgraph->linestyle;
185 (DEVDEP(currentgraph).strokecnt)++;
186 return (0);
187 }
188
189
190 int
PS_Box(x1,y1,x2,y2)191 PS_Box(x1, y1, x2, y2)
192 int x1, y1, x2, y2;
193 {
194 PS_Line(x1,y1,x1,y2);
195 PS_Line(x1,y2,x2,y2);
196 PS_Line(x2,y2,x2,y1);
197 PS_Line(x2,y1,x1,y1);
198 return (0);
199 }
200
201
202 /* ARGSUSED */
203 int
PS_Arc(x0,y0,radius,theta1,theta2)204 PS_Arc(x0, y0, radius, theta1, theta2)
205
206 int x0, y0, radius;
207 double theta1, theta2;
208 {
209 int a1, a2;
210
211 if (theta1 >= theta2)
212 theta2 = 2 * M_PI + theta2;
213
214 a1 = (180.0 / M_PI) * theta1;
215 a2 = (180.0 / M_PI) * theta2;
216
217 if (currentgraph->linestyle == -1)
218 PS_SetLinestyle(SOLID);
219 if (DEVDEP(currentgraph).strokecnt) {
220 fprintf(plotfile, "stroke\n");
221 DEVDEP(currentgraph).strokecnt = 0;
222 }
223 else if (DEVDEP(currentgraph).lastlinestyle == -1) {
224 fprintf(plotfile, "newpath\n");
225 DEVDEP(currentgraph).lastlinestyle = currentgraph->linestyle;
226 }
227
228 fprintf(plotfile, "%d %d %d %d %d arc\n",
229 x0+Xoff,y0+Yoff,radius,a1,a2);
230 fprintf(plotfile, "stroke\n");
231 lastx = -1;
232 lasty = -1;
233 return (0);
234 }
235
236
237 int
PS_Polygon(p)238 PS_Polygon(p)
239 POLYGON *p;
240 {
241 /* This is currently used only to print dots for sced. The
242 * polygon code below looks bad and causes errors if the dots
243 * are too small, thus we use the specialized routine below.
244 */
245
246 int *xy, x, y, savedlstyle;
247
248 xy = (int*)p->xy;
249 if (xy[0] == xy[8]) {
250 x = xy[0];
251 y = xy[5];
252 }
253 else {
254 x = xy[4];
255 y = xy[1];
256 }
257 if (DEVDEP(currentgraph).strokecnt) {
258 fprintf(plotfile, "stroke\n");
259 DEVDEP(currentgraph).strokecnt = 0;
260 }
261 savedlstyle = currentgraph->linestyle;
262 PS_SetLinestyle(SOLID);
263 fprintf(plotfile,"%d %d moveto\n",x+1+Xoff,y+Yoff);
264 fprintf(plotfile,"%d %d 3 0 359 arc closepath fill\n",x+Xoff,y+Yoff);
265 PS_SetLinestyle(savedlstyle);
266 lastx = -1;
267 lasty = -1;
268 return (0);
269
270
271 /*
272 int *xy, nvert, savedlstyle;
273
274 xy = (int*)p->xy;
275 nvert = p->nvertices;
276 savedlstyle = currentgraph->linestyle;
277 PS_SetLinestyle(SOLID);
278
279 fprintf(plotfile, "%d %d moveto ", *xy+Xoff, *(xy+1)+Yoff);
280 xy += 2;
281 nvert--;
282 while (nvert--) {
283 fprintf(plotfile, "%d %d lineto\n", *xy+Xoff, *(xy+1)+Yoff);
284 xy += 2;
285 }
286 fprintf(plotfile,"closepath\nfill\n");
287 PS_SetLinestyle(savedlstyle);
288 return (0);
289 */
290 }
291
292
293 int
PS_Text(text,x,y)294 PS_Text(text, x, y)
295
296 char *text;
297 int x, y;
298 {
299
300 int savedlstyle;
301 char tbuf[BSIZE_SP], *s;
302
303 if (text == NULL)
304 return (0);
305
306 s = tbuf;
307 while (*text) {
308 if (*text == '(' || *text == ')' || *text == '\\')
309 *s++ = '\\';
310 *s++ = *text++;
311 }
312 *s = '\0';
313
314 if (DEVDEP(currentgraph).strokecnt) {
315 fprintf(plotfile, "stroke\n");
316 DEVDEP(currentgraph).strokecnt = 0;
317 }
318 /* set linestyle to solid
319 * or may get funny color text on some plotters
320 */
321 savedlstyle = currentgraph->linestyle;
322 PS_SetLinestyle(SOLID);
323
324 /* move to (x, y) */
325 fprintf(plotfile, "%d %d moveto\n", x+Xoff, y+Yoff);
326 fprintf(plotfile, "(%s) show\n", tbuf);
327
328 /* restore old linestyle */
329 PS_SetLinestyle(savedlstyle);
330 lastx = -1;
331 lasty = -1;
332 return (0);
333 }
334
335
336 int
PS_SetLinestyle(linestyleid)337 PS_SetLinestyle(linestyleid)
338
339 int linestyleid;
340 {
341
342 /* special case
343 get it when PS_Text restores a -1 linestyle */
344 if (linestyleid == -1) {
345 currentgraph->linestyle = -1;
346 return (0);
347 }
348
349 if (linestyleid < 0) {
350 internalerror("bad linestyleid");
351 return (0);
352 }
353
354 if (linestyleid > dispdev->numlinestyles)
355 linestyleid = (linestyleid % dispdev->numlinestyles) + 1;
356
357 if (currentgraph->linestyle != linestyleid) {
358 if (DEVDEP(currentgraph).strokecnt) {
359 fprintf(plotfile, "stroke\n");
360 DEVDEP(currentgraph).strokecnt = 0;
361 lastx = -1;
362 lasty = -1;
363 }
364 fprintf(plotfile, "%s 0 setdash\n", linestyle[linestyleid]);
365 currentgraph->linestyle = linestyleid;
366 }
367 return (0);
368 }
369
370
371 /* ARGSUSED */
372 int
PS_SetColor(colorid)373 PS_SetColor(colorid)
374 {
375 /* do nothing */
376 return (0);
377 }
378
379
380 int
PS_Update()381 PS_Update()
382
383 {
384 fflush(plotfile);
385 return (0);
386 }
387
388
389 /* transformed text for sced hardcopy */
390
391 int
PS_ScaledText(text,x,y,Xform)392 PS_ScaledText(text,x,y,Xform)
393
394 char *text;
395 int x, y, Xform;
396 {
397 /* Xform code:
398 * 0x8: mirror x
399 * 0x4: mirror y
400 * 0x3: 0-no rotation, 1-90, 2-180, 3-270
401 */
402 int savedlstyle, deg;
403 char tbuf[BSIZE_SP], *s;
404
405 if (text == NULL)
406 return (0);
407
408 if (Xform == (char)0) {
409 PS_Text(text,x,y);
410 return (0);
411 }
412
413 s = tbuf;
414 while (*text) {
415 if (*text == '(' || *text == ')' || *text == '\\')
416 *s++ = '\\';
417 *s++ = *text++;
418 }
419 *s = '\0';
420
421 if (DEVDEP(currentgraph).strokecnt) {
422 fprintf(plotfile, "stroke\n");
423 DEVDEP(currentgraph).strokecnt = 0;
424 }
425
426 /* set linestyle to solid
427 * or may get funny color text on some plotters
428 */
429 savedlstyle = currentgraph->linestyle;
430 PS_SetLinestyle(SOLID);
431
432 fprintf(plotfile,"gsave\n");
433 fprintf(plotfile,"%d %d translate\n",x+Xoff,y+Yoff);
434 if (Xform & 12)
435 fprintf(plotfile,"%d %d scale\n",
436 (Xform & 8) ? -1 : 1, (Xform & 4) ? -1 : 1);
437 deg = (Xform & 3) * 90;
438 if (deg)
439 fprintf(plotfile,"%d rotate\n",deg);
440 fprintf(plotfile,"0 0 moveto\n");
441 fprintf(plotfile,"(%s) show\n",tbuf);
442 fprintf(plotfile,"grestore\n");
443
444 /* restore old linestyle */
445 PS_SetLinestyle(savedlstyle);
446 lastx = -1;
447 lasty = -1;
448 return (0);
449 }
450