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