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