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