1 // -*- C -*-
2 /* Copyright (C) 1994, 2000, 2001 Free Software Foundation, Inc.
3 Written by Francisco Andr�s Verd� <pandres@dragonet.es>
4
5 groff is free software; you can redistribute it and/or modify it under
6 the terms of the GNU General Public License as published by the Free
7 Software Foundation; either version 2, or (at your option) any later
8 version.
9
10 groff is distributed in the hope that it will be useful, but WITHOUT ANY
11 WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
13 for more details.
14
15 You should have received a copy of the GNU General Public License along
16 with groff; see the file COPYING. If not, write to the Free Software
17 Foundation, 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */
18
19 /* This file contains a set of utility functions to use canon CAPSL printers
20 * (lbp-4 and lbp-8 series printers) */
21
22 #ifndef LBP_H
23 #define LBP_H
24
25 #include <stdio.h>
26 #include <stdarg.h>
27
28 static FILE *lbpoutput = NULL;
29 static FILE *vdmoutput = NULL;
30
31 static inline void
lbpinit(FILE * outfile)32 lbpinit(FILE *outfile)
33 {
34 lbpoutput = outfile;
35 };
36
37
38 static inline void
lbpprintf(const char * format,...)39 lbpprintf(const char *format, ... )
40 { /* Taken from cjet */
41 va_list stuff;
42
43 va_start(stuff, format);
44 vfprintf(lbpoutput, format, stuff);
45 va_end(stuff);
46 };
47
48 static inline void
lbpputs(const char * data)49 lbpputs(const char *data)
50 {
51 fputs(data,lbpoutput);
52 };
53
54 static inline void
lbpputc(char c)55 lbpputc(char c)
56 {
57 fputc(c,lbpoutput);
58 };
59
60
61 static inline void
lbpsavestatus(int index)62 lbpsavestatus(int index )
63 {
64 fprintf(lbpoutput,"\033[%d%%y",index);
65 };
66
67 static inline void
lbprestorestatus(int index)68 lbprestorestatus(int index )
69 {
70 fprintf(lbpoutput,"\033[%d%cz",index ,'%');
71 };
72
73 static inline void
lbpsavepos(int index)74 lbpsavepos(int index)
75 {
76 fprintf(lbpoutput,"\033[1;%d;0x",index);
77 };
78
79 static inline void
lbprestorepos(int index)80 lbprestorepos(int index)
81 {
82 fprintf(lbpoutput,"\033[0;%d;0x",index);
83 };
84
85 static inline void
lbprestoreposx(int index)86 lbprestoreposx(int index)
87 {
88 fprintf(lbpoutput,"\033[0;%d;1x",index);
89 };
90
91 static inline void
lbpmoverel(int despl,char direction)92 lbpmoverel(int despl, char direction)
93 {
94 fprintf(lbpoutput,"\033[%d%c",despl,direction);
95 };
96
97 static inline void
lbplinerel(int width,int despl,char direction)98 lbplinerel(int width,int despl,char direction )
99 {
100 fprintf(lbpoutput,"\033[%d;0;9{\033[%d%c\033[9}",width,despl,direction);
101 };
102
103 static inline void
lbpmoveabs(int x,int y)104 lbpmoveabs(int x, int y)
105 {
106 fprintf(lbpoutput,"\033[%d;%df",y,x);
107 };
108
109 static inline void
lbplineto(int x,int y,int width)110 lbplineto(int x,int y, int width )
111 {
112 fprintf(lbpoutput,"\033[%d;0;9{",width);
113 lbpmoveabs(x,y);
114 fprintf(lbpoutput,"\033[9}\n");
115 };
116
117 static inline void
lbpruleabs(int x,int y,int hsize,int vsize)118 lbpruleabs(int x, int y, int hsize, int vsize)
119 {
120 lbpmoveabs(x,y);
121 fprintf(lbpoutput,"\033[0;9;000s");
122 lbpmoveabs(x+hsize,y+vsize);
123 fprintf(lbpoutput,"\033[9r");
124 };
125
126 static inline void vdmprintf(const char *format, ... );
127
128 static inline char *
vdmnum(int num,char * result)129 vdmnum(int num,char *result)
130 {
131 char b1,b2,b3;
132 char *p = result;
133 int nm;
134
135 nm = abs(num);
136 /* First byte 1024 - 32768 */
137 b1 = ((nm >> 10) & 0x3F);
138 if (b1) *p++ = b1 | 0x40;
139
140 /* Second Byte 16 - 1024 */
141 b2 = ((nm >> 4) & 0x3F);
142 if ( b1 || b2) *p++= b2 | 0x40;
143
144 /* Third byte 0 - 15 */
145 b3 = ((nm & 0x0F) | 32);
146 if (num >= 0) b3 |= 16;
147 *p++ = b3;
148 *p = 0x00; /* End of the resulting string */
149 return result;
150 };
151
152 static inline void
vdmorigin(int newx,int newy)153 vdmorigin(int newx, int newy)
154 {
155 char nx[4],ny[4];
156
157 vdmprintf("}\"%s%s\x1e",vdmnum(newx,nx),vdmnum(newy,ny));
158 }; /* vdmorigin */
159
160
161 static inline FILE *
vdminit(FILE * vdmfile)162 vdminit(FILE *vdmfile)
163 {
164 char scale[4],size[4],lineend[4];
165
166 /* vdmoutput = tmpfile();*/
167 vdmoutput = vdmfile;
168 /* Initialize the VDM mode */
169 vdmprintf("\033[0&}#GROLBP\x1e!0%s%s\x1e$\x1e}F%s\x1e",\
170 vdmnum(-3,scale),vdmnum(1,size),vdmnum(1,lineend));
171 return vdmoutput;
172
173 };
174
175 static inline void
vdmend()176 vdmend()
177 {
178 vdmprintf("}p\x1e");
179 };
180
181 static inline void
vdmprintf(const char * format,...)182 vdmprintf(const char *format, ... )
183 { /* Taken from cjet */
184 va_list stuff;
185
186 if (vdmoutput == NULL) vdminit(tmpfile());
187 va_start(stuff, format);
188 vfprintf(vdmoutput, format, stuff);
189 va_end(stuff);
190 };
191
192 static inline void
vdmsetfillmode(int pattern,int perimeter,int inverted)193 vdmsetfillmode(int pattern,int perimeter, int inverted)
194 {
195 char patt[4],perim[4],
196 rot[4], /* rotation */
197 espejo[4], /* espejo */
198 inv[4]; /* Inverted */
199
200 vdmprintf("I%s%s%s%s%s\x1e",vdmnum(pattern,patt),\
201 vdmnum(perimeter,perim),vdmnum(0,rot),
202 vdmnum(0,espejo),vdmnum(inverted,inv));
203 };
204
205 static inline void
vdmcircle(int centerx,int centery,int radius)206 vdmcircle(int centerx, int centery, int radius)
207 {
208 char x[4],y[4],rad[4];
209
210 vdmprintf("5%s%s%s\x1e",vdmnum(centerx,x),vdmnum(centery,y),\
211 vdmnum(radius,rad));
212 };
213
214 static inline void
vdmaarc(int centerx,int centery,int radius,int startangle,int angle,int style,int arcopen)215 vdmaarc(int centerx, int centery, int radius,int startangle,int angle,int style,int arcopen)
216 {
217 char x[4],y[4],rad[4],stx[4],sty[4],styl[4],op[4];
218
219 vdmprintf("}6%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\
220 vdmnum(centerx,x),vdmnum(centery,y),\
221 vdmnum(radius,rad),vdmnum(startangle,stx),vdmnum(angle,sty),\
222 vdmnum(style,styl));
223 };
224
225 static inline void
vdmvarc(int centerx,int centery,int radius,int startx,int starty,int endx,int endy,int style,int arcopen)226 vdmvarc(int centerx, int centery,int radius, int startx, int starty, int endx, int endy,\
227 int style,int arcopen)
228 {
229 char x[4],y[4],rad[4],stx[4],sty[4],enx[4],eny[4],styl[4],op[4];
230
231 vdmprintf("}6%s%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\
232 vdmnum(centerx,x),vdmnum(centery,y),\
233 vdmnum(radius,rad),vdmnum(startx,stx),vdmnum(starty,sty),\
234 vdmnum(endx,enx),vdmnum(endy,eny),vdmnum(style,styl));
235 };
236
237 static inline void
vdmellipse(int centerx,int centery,int radiusx,int radiusy,int rotation)238 vdmellipse(int centerx, int centery, int radiusx, int radiusy,int rotation)
239 {
240 char x[4],y[4],radx[4],rady[4],rotat[4];
241
242 vdmprintf("}7%s%s%s%s%s\x1e\n",vdmnum(centerx,x),vdmnum(centery,y),\
243 vdmnum(radiusx,radx),vdmnum(radiusy,rady),\
244 vdmnum(rotation,rotat));
245 };
246
247 static inline void
vdmsetlinetype(int lintype)248 vdmsetlinetype(int lintype)
249 {
250 char ltyp[4], expfact[4];
251
252 vdmprintf("E1%s%s\x1e",vdmnum(lintype,ltyp),vdmnum(1,expfact));
253
254 };
255
256 static inline void
vdmsetlinestyle(int lintype,int pattern,int unionstyle)257 vdmsetlinestyle(int lintype, int pattern,int unionstyle)
258 {
259 char patt[4],ltip[4],
260 rot[4], /* rotation */
261 espejo[4], /* espejo */
262 in[4]; /* Inverted */
263
264 vdmprintf("}G%s%s%s%s%s\x1e",vdmnum(lintype,ltip),\
265 vdmnum(pattern,patt),vdmnum(0,rot),
266 vdmnum(0,espejo),vdmnum(0,in));
267 vdmprintf("}F%s",vdmnum(unionstyle,rot));
268 };
269
270 static inline void
vdmlinewidth(int width)271 vdmlinewidth(int width)
272 {
273 char wh[4];
274
275 vdmprintf("F1%s\x1e",vdmnum(width,wh));
276 };
277
278 static inline void
vdmrectangle(int origx,int origy,int dstx,int dsty)279 vdmrectangle(int origx, int origy,int dstx, int dsty)
280 {
281 char xcoord[4],ycoord[4],sdstx[4],sdsty[4];
282
283 vdmprintf("}:%s%s%s%s\x1e\n",vdmnum(origx,xcoord),vdmnum(dstx,sdstx),\
284 vdmnum(origy,ycoord),vdmnum(dsty,sdsty));
285 }; /* polyline */
286
287 static inline void
vdmpolyline(int numpoints,int * points)288 vdmpolyline(int numpoints, int *points)
289 {
290 int i,*p = points;
291 char xcoord[4],ycoord[4];
292
293 if (numpoints < 2) return;
294 vdmprintf("1%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
295 p += 2;
296 for (i = 1; i < numpoints ; i++) {
297 vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
298 p += 2;
299 }; /* for */
300 vdmprintf("\x1e\n");
301 }; /* polyline */
302
303 static inline void
vdmpolygon(int numpoints,int * points)304 vdmpolygon(int numpoints, int *points)
305 {
306 int i,*p = points;
307 char xcoord[4],ycoord[4];
308
309 if (numpoints < 2) return;
310 vdmprintf("2%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
311 p += 2;
312 for (i = 1; i < numpoints ; i++) {
313 vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
314 p += 2;
315 }; /* for */
316 vdmprintf("\x1e\n");
317
318 }; /* vdmpolygon */
319
320
321 /************************************************************************
322 * Highter level auxiliary functions *
323 ************************************************************************/
324 static inline int
vdminited()325 vdminited()
326 {
327 return (vdmoutput != NULL);
328 }; /* vdminited */
329
330
331 static inline void
vdmline(int startx,int starty,int sizex,int sizey)332 vdmline(int startx, int starty, int sizex, int sizey)
333 {
334 int points[4];
335
336 points[0] = startx;
337 points[1] = starty;
338 points[2] = sizex;
339 points[3] = sizey;
340
341 vdmpolyline(2,points);
342
343 };
344
345 /*#define THRESHOLD .05 */ /* inch */
346 #define THRESHOLD 1 /* points (1/300 inch) */
347 static inline void
splinerel(double px,double py,int flush)348 splinerel(double px,double py,int flush)
349 {
350 static int lx = 0 ,ly = 0;
351 static float pend = 0.0;
352 static int dy = 0, despx = 0, despy = 0, sigpend = 0;
353 int dxnew ,dynew, sg;
354 char xcoord[4],ycoord[4];
355 float npend ;
356
357 if (flush == -1) {lx = (int)px; ly = (int)py; return;};
358
359 if (flush == 0) {
360 dxnew = (int)px -lx;
361 dynew = (int)py -ly;
362 if ((dxnew == 0) && (dynew == 0)) return;
363 sg = (dxnew < 0)? -1 : 0;
364 /* fprintf(stderr,"s (%d,%d) (%d,%d)\n",dxnew,dynew,despx,despy);*/
365 if (dynew == 0) {
366 despx = dxnew;
367 if ((sg == sigpend) && (dy == 0)){
368 return;
369 };
370 dy = 0;
371 }
372 else {
373 dy = 1;
374 npend = (1.0*dxnew)/dynew;
375 if (( npend == pend) && (sigpend == sg))
376 { despy = dynew; despx = dxnew; return; }
377 else
378 { sigpend = sg;
379 pend = npend;
380 }; /* else (( npend == pend) && ... */
381 }; /* else (if (dynew == 0)) */
382 }; /* if (!flush ) */
383
384 /* if we've changed direction we must draw the line */
385 /* fprintf(stderr," (%d) %.2f,%.2f\n",flush,(float)px,(float)py);*/
386 if ((despx != 0) || (despy != 0)) vdmprintf("%s%s",vdmnum(despx,xcoord),\
387 vdmnum(despy,ycoord));
388 /*if ((despx != 0) || (despy != 0)) fprintf(stderr,"2
389 *%d,%d\n",despx,despy);*/
390 if (flush) {
391 dxnew = dy = despx = despy = 0;
392 return;
393 }; /* if (flush) */
394 dxnew -= despx;
395 dynew -= despy;
396 if ((dxnew != 0) || (dynew != 0)) vdmprintf("%s%s",vdmnum(dxnew,xcoord),\
397 vdmnum(dynew,ycoord));
398
399 /* if ((dxnew != 0) || (dynew != 0)) fprintf(stderr,"3
400 * %d,%d\n",dxnew,dynew);*/
401 lx = (int)px; ly = (int)py;
402 dxnew = dy = despx = despy = 0;
403
404 }; /* splinerel */
405
406 /**********************************************************************
407 * The following code to draw splines is adapted from the transfig package
408 */
409 static void
quadratic_spline(double a1,double b1,double a2,double b2,double a3,double b3,double a4,double b4)410 quadratic_spline(double a1,double b1, double a2, double b2, \
411 double a3, double b3, double a4, double b4)
412 {
413 double x1, y1, x4, y4;
414 double xmid, ymid;
415
416 x1 = a1; y1 = b1;
417 x4 = a4; y4 = b4;
418 xmid = (a2 + a3)/2.0;
419 ymid = (b2 + b3)/2.0;
420 if ((fabs(x1 - xmid) < THRESHOLD) && (fabs(y1 - ymid) < THRESHOLD)) {
421 splinerel(xmid,ymid,0);
422 /* fprintf(tfp, "PA%.4f,%.4f;\n", xmid, ymid);*/
423 }
424 else {
425 quadratic_spline(x1, y1, ((x1+a2)/2.0), ((y1+b2)/2.0),
426 ((3.0*a2+a3)/4.0), ((3.0*b2+b3)/4.0), xmid, ymid);
427 }
428
429 if ((fabs(xmid - x4) < THRESHOLD) && (fabs(ymid - y4) < THRESHOLD)) {
430 splinerel(x4,y4,0);
431 /* fprintf(tfp, "PA%.4f,%.4f;\n", x4, y4);*/
432 }
433 else {
434 quadratic_spline(xmid, ymid, ((a2+3.0*a3)/4.0), ((b2+3.0*b3)/4.0),
435 ((a3+x4)/2.0), ((b3+y4)/2.0), x4, y4);
436 };
437 }; /* quadratic_spline */
438
439 #define XCOORD(i) numbers[(2*i)]
440 #define YCOORD(i) numbers[(2*i)+1]
441 static void
vdmspline(int numpoints,int ox,int oy,int * numbers)442 vdmspline(int numpoints, int ox,int oy, int *numbers)
443 {
444 double cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4;
445 double x1, y1, x2, y2;
446 char xcoord[4],ycoord[4];
447 int i;
448
449 /*p = s->points;
450 x1 = p->x/ppi;*/
451 x1 = ox;
452 y1 = oy;
453 /* p = p->next;
454 x2 = p->x/ppi;
455 y2 = p->y/ppi;*/
456 x2 = ox + XCOORD(0);
457 y2 = oy + YCOORD(0);
458 cx1 = (x1 + x2)/2.0;
459 cy1 = (y1 + y2)/2.0;
460 cx2 = (x1 + 3.0*x2)/4.0;
461 cy2 = (y1 + 3.0*y2)/4.0;
462
463 /* fprintf(stderr,"Spline %d (%d,%d)\n",numpoints,(int)x1,(int)y1);*/
464 vdmprintf("1%s%s",vdmnum((int)x1,xcoord),vdmnum((int)y1,ycoord));
465 splinerel(x1,y1,-1);
466 splinerel(cx1,cy1,0);
467 /* fprintf(tfp, "PA%.4f,%.4f;PD%.4f,%.4f;\n",
468 x1, y1, cx1, cy1);*/
469
470 /*for (p = p->next; p != NULL; p = p->next) {*/
471 for (i = 1; i < (numpoints); i++) {
472 x1 = x2;
473 y1 = y2;
474 /* x2 = p->x/ppi;
475 y2 = p->y/ppi;*/
476 x2 = x1 + XCOORD(i);
477 y2 = y1 + YCOORD(i);
478 cx3 = (3.0*x1 + x2)/4.0;
479 cy3 = (3.0*y1 + y2)/4.0;
480 cx4 = (x1 + x2)/2.0;
481 cy4 = (y1 + y2)/2.0;
482 /* fprintf(stderr,"Point (%d,%d) - (%d,%d)\n",(int)x1,(int)(y1),(int)x2,(int)y2);*/
483 quadratic_spline(cx1, cy1, cx2, cy2, cx3, cy3, cx4, cy4);
484 cx1 = cx4;
485 cy1 = cy4;
486 cx2 = (x1 + 3.0*x2)/4.0;
487 cy2 = (y1 + 3.0*y2)/4.0;
488 }
489 x1 = x2;
490 y1 = y2;
491 /* p = s->points->next;
492 x2 = p->x/ppi;
493 y2 = p->y/ppi;*/
494 x2 = ox + XCOORD(0);
495 y2 = oy + YCOORD(0);
496 cx3 = (3.0*x1 + x2)/4.0;
497 cy3 = (3.0*y1 + y2)/4.0;
498 cx4 = (x1 + x2)/2.0;
499 cy4 = (y1 + y2)/2.0;
500 splinerel(x1,y1,0);
501 splinerel(x1,y1,1);
502 /*vdmprintf("%s%s",vdmnum((int)(x1-lx),xcoord),\
503 vdmnum((int)(y1-ly),ycoord));*/
504 vdmprintf("\x1e\n");
505 /* fprintf(tfp, "PA%.4f,%.4f;PU;\n", x1, y1);*/
506
507
508 }; /* vdmspline */
509
510
511 #endif
512