1 /**********
2 Author: Jim Groves
3 **********/
4 
5 /*
6     HPGL driver
7 */
8 
9 /*
10    1000 plotter units / inch  - 1pu = 0.025mm  1pu = 1mil
11 
12   SP - select pen
13   PU - pen up (PU x,y)
14   PD - pen down (PD x,y)
15   LT - line type
16        0   dots only at plotted points
17        1   .   .    .   .    .
18        2   ___     ___     ___     ___
19        3   ----    ----    ----    ----
20        4   ----- . ----- . ----- . -----.
21        5   ---- -  ---- -  ---- -
22        6   --- - - --- - - --- - - --- - -
23        null - solid line
24   IN - initialize
25   DF - default values (PA, solid line, set 0)
26   PA - plot absolute
27   SI - absolute character size (SI width, height) in cm
28 
29 */
30 
31 #include "ngspice/ngspice.h"
32 #include "ngspice/cpdefs.h"
33 #include "ngspice/graph.h"
34 #include "ngspice/ftedbgra.h"
35 #include "ngspice/ftedev.h"
36 #include "ngspice/fteinput.h"
37 #include "ngspice/fteext.h"
38 #include "variable.h"
39 #include "plotting/graphdb.h"
40 #include "hpgl.h"
41 
42 #define RAD_TO_DEG      (180.0 / M_PI)
43 #define DEVDEP(g) (*((GLdevdep *) (g)->devdep))
44 #define MAX_GL_LINES    9999
45 #define SOLID 0
46 #define DOTTED 1
47 
48 #define gtype         graph->grid.gridtype
49 #define xoff          dispdev->minx
50 #define yoff          dispdev->miny
51 #define XOFF          25      /* printer left margin */
52 #define YOFF          28      /* printer bottom margin */
53 #define XTADJ         0       /* printer text adjustment x */
54 #define YTADJ         0       /* printer text adjustment y */
55 
56 #define DELXMAX       360     /* printer gridsize divisible by 10, [7-2] */
57 #define DELYMAX       360     /* printer gridsize divisible by [10-8], [6-2] */
58 
59 #define FONTWIDTH     6       /* printer default fontwidth */
60 #define FONTHEIGHT    8       /* printer default fontheight */
61 
62 typedef struct {
63     int lastlinestyle;      /* initial invalid value */
64     int lastx, lasty, linecount;
65 } GLdevdep;
66 
67 static char *linestyle[] = {
68     "",     /* solid */
69     "1",    /* was 1 - dotted */
70     "",     /* longdashed */
71     "3",    /* shortdashed */
72     "4",    /* longdotdashed */
73     "5",    /* shortdotdashed */
74     "1"
75 };
76 
77 static FILE *plotfile;
78 extern char psscale[32];
79 static int fontwidth  = FONTWIDTH;
80 static int fontheight = FONTHEIGHT;
81 static int   jgmult      = 10;
82 static int screenflag = 0;
83 static double tocm = 0.0025;
84 static double scale;    /* Used for fine tuning */
85 static int hcopygraphid;
86 
87 
GL_Init(void)88 int GL_Init(void)
89 {
90     if (!cp_getvar("hcopyscale", CP_STRING, psscale, sizeof(psscale))) {
91         scale = 1.0;
92     }
93     else {
94         sscanf(psscale, "%lf", &scale);
95         if ((scale <= 0) || (scale > 10))
96             scale = 1.0;
97     }
98 
99     dispdev->numlinestyles = NUMELEMS(linestyle);
100     dispdev->numcolors = 6;
101 
102     dispdev->width = (int)(DELXMAX * scale);
103     dispdev->height = (int)(DELYMAX * scale);
104 
105 
106     screenflag = 0;
107     dispdev->minx = (int)(XOFF * 1.0);
108     dispdev->miny = (int)(YOFF * 1.0);
109 
110     return 0;
111 }
112 
113 
114 /* devdep initially contains name of output file */
GL_NewViewport(GRAPH * graph)115 int GL_NewViewport(GRAPH *graph)
116 {
117     hcopygraphid = graph->graphid;
118 
119     if ((plotfile = fopen((char*) graph->devdep, "w")) == NULL) {
120         perror((char *) graph->devdep);
121         free(graph->devdep);
122         graph->devdep = NULL;
123         graph->n_byte_devdep = 0;
124         return 1;
125     }
126 
127     if (graph->absolute.width) {
128         /* hardcopying from the screen */
129 
130         screenflag = 1;
131 
132         /* scale to fit on 8 1/2 square */
133 
134     }
135 
136     /* reasonable values, used in gr_ for placement */
137     graph->fontwidth = (int)(fontwidth * scale); /* was 12, p.w.h. */
138     graph->fontheight = (int)(fontheight * scale); /* was 24, p.w.h. */
139 
140     graph->absolute.width = dispdev->width;
141     graph->absolute.height = dispdev->height;
142     /* Also done in gr_init, if called . . . */
143     graph->viewportxoff = 16 * fontwidth;
144     graph->viewportyoff = 8 * fontheight;
145 
146     xoff = XOFF;
147     yoff = YOFF;
148 
149     /* start file off with a % */
150     fprintf(plotfile, "IN;DF;PA;");
151     fprintf(plotfile, "SI %f,%f;",
152             tocm * jgmult * fontwidth * scale,
153             tocm * jgmult * fontheight * scale);
154 
155 #ifdef notdef
156     if (!screenflag)
157 #endif
158     {
159         graph->devdep = TMALLOC(GLdevdep, 1);
160         graph->n_byte_devdep = sizeof(GLdevdep);
161     }
162 
163     DEVDEP(graph).lastlinestyle = -1;
164     DEVDEP(graph).lastx = -1;
165     DEVDEP(graph).lasty = -1;
166     DEVDEP(graph).linecount = 0;
167     graph->linestyle = -1;
168 
169     return 0;
170 }
171 
172 
GL_Close(void)173 int GL_Close(void)
174 {
175     /* in case GL_Close is called as part of an abort,
176        w/o having reached GL_NewViewport */
177     if (plotfile) {
178         if (DEVDEP(currentgraph).lastlinestyle != -1) {
179             DEVDEP(currentgraph).linecount = 0;
180         }
181         fclose(plotfile);
182         plotfile = NULL;
183     }
184     /* In case of hardcopy command destroy the hardcopy graph
185      * and reset currentgraph to graphid 1, if possible
186      */
187     if (!screenflag) {
188         DestroyGraph(hcopygraphid);
189         currentgraph = FindGraph(1);
190     }
191 
192     return 0;
193 }
194 
195 
GL_Clear(void)196 int GL_Clear(void)
197 {
198     /* do nothing */
199 
200     return 0;
201 }
202 
203 
204 int
GL_DrawLine(int x1,int y1,int x2,int y2,bool isgrid)205 GL_DrawLine(int x1, int y1, int x2, int y2, bool isgrid)
206 {
207     NG_IGNORE(isgrid);
208     /* note: this is not extendible to more than one graph
209        => will have to give NewViewport a writeable graph XXX */
210 
211 
212     if (DEVDEP(currentgraph).linecount == 0
213             || x1 != DEVDEP(currentgraph).lastx
214             || y1 != DEVDEP(currentgraph).lasty) {
215         fprintf(plotfile, "PU;PA %d , %d ;",
216                 jgmult * (x1 + xoff), jgmult * (y1 + yoff));
217     }
218     if (x1 != x2 || y1 != y2) {
219         fprintf(plotfile, "PD;PA %d , %d ;",
220                 jgmult * (x2 + xoff), jgmult * (y2 + yoff));
221         DEVDEP(currentgraph).linecount += 1;
222     }
223 
224     DEVDEP(currentgraph).lastx = x2;
225     DEVDEP(currentgraph).lasty = y2;
226     DEVDEP(currentgraph).lastlinestyle = currentgraph->linestyle;
227 
228     return 0;
229 }
230 
231 
232 /* ARGSUSED */
GL_Arc(int x0,int y0,int r,double theta,double delta_theta)233 int GL_Arc(int x0, int y0, int r, double theta, double delta_theta)
234 {
235     int  x1, y1, angle;
236 
237     x1 = x0 + (int)(r * cos(theta));
238     y1 = y0 + (int)(r * sin(theta));
239 
240     angle = (int)(RAD_TO_DEG * delta_theta);
241 
242     fprintf(plotfile, "PU;PA %d , %d;",
243             jgmult * (x1 + xoff + XTADJ), jgmult * (y1 + yoff + YTADJ));
244     fprintf(plotfile, "PD;AA %d , %d, %d;",
245             jgmult * (x0 + xoff + XTADJ), jgmult*(y0 + yoff + YTADJ), angle);
246 
247     DEVDEP(currentgraph).linecount = 0;
248 
249     return 0;
250 }
251 
252 
GL_Text(const char * text,int x,int y,int angle)253 int GL_Text(const char *text, int x, int y, int angle)
254 {
255     NG_IGNORE(angle);
256 
257     /* move to (x, y) */
258     NG_IGNORE(angle);
259 
260     fprintf(plotfile, "PU;PA %d , %d;",
261             jgmult * (x + xoff + XTADJ), jgmult * (y + yoff + YTADJ));
262     fprintf(plotfile, "LB %s \x03", text);
263 
264     DEVDEP(currentgraph).lastx = -1;
265     DEVDEP(currentgraph).lasty = -1;
266 
267     return 0;
268 }
269 
270 
GL_SetLinestyle(int linestyleid)271 int GL_SetLinestyle(int linestyleid)
272 {
273     /* special case
274        get it when GL_Text restores a -1 linestyle */
275     if (linestyleid == -1) {
276         currentgraph->linestyle = -1;
277         return 0;
278     }
279 
280     if (linestyleid < 0 || linestyleid > dispdev->numlinestyles) {
281         internalerror("bad linestyleid");
282         return 0;
283     }
284 
285     if (currentgraph->linestyle != linestyleid) {
286         fprintf(plotfile, "LT %s ;", linestyle[linestyleid]);
287         currentgraph->linestyle = linestyleid;
288     }
289 
290     return 0;
291 }
292 
293 
GL_SetColor(int colorid)294 int GL_SetColor(int colorid)
295 {
296     fprintf(plotfile, "SP %d;", colorid);
297 
298     return 0;
299 }
300 
301 
GL_Update(void)302 int GL_Update(void)
303 {
304     fflush(plotfile);
305 
306     return 0;
307 }
308