lbp.h revision 75584
1// -*- C -*-
2/* Copyright (C) 1994, 2000 Free Software Foundation, Inc.
3     Written by Francisco Andr�s Verd� <pandres@dragonet.es>
4
5groff is free software; you can redistribute it and/or modify it under
6the terms of the GNU General Public License as published by the Free
7Software Foundation; either version 2, or (at your option) any later
8version.
9
10groff is distributed in the hope that it will be useful, but WITHOUT ANY
11WARRANTY; without even the implied warranty of MERCHANTABILITY or
12FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
13for more details.
14
15You should have received a copy of the GNU General Public License along
16with groff; see the file COPYING.  If not, write to the Free Software
17Foundation, 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
28static FILE *lbpoutput = NULL;
29static FILE *vdmoutput = NULL;
30
31static inline void
32lbpinit(FILE *outfile)
33{
34	lbpoutput = outfile;
35};
36
37
38static inline void
39lbpprintf(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
48static inline void
49lbpputs(char *data)
50{
51	fputs(data,lbpoutput);
52};
53
54static inline void
55lbpputc(char c)
56{
57	fputc(c,lbpoutput);
58};
59
60
61static inline void
62lbpsavestatus(int index )
63{
64	fprintf(lbpoutput,"\033[%d%%y",index);
65};
66
67static inline void
68lbprestorestatus(int index )
69{
70	fprintf(lbpoutput,"\033[%d%cz",index ,'%');
71};
72
73static inline void
74lbpsavepos(int index)
75{
76	fprintf(lbpoutput,"\033[1;%d;0x",index);
77};
78
79static inline void
80lbprestorepos(int index)
81{
82	fprintf(lbpoutput,"\033[0;%d;0x",index);
83};
84
85static inline void
86lbprestoreposx(int index)
87{
88	fprintf(lbpoutput,"\033[0;%d;1x",index);
89};
90
91static inline void
92lbpmoverel(int despl, char direction)
93{
94	fprintf(lbpoutput,"\033[%d%c",despl,direction);
95};
96
97static inline void
98lbplinerel(int width,int despl,char direction )
99{
100	fprintf(lbpoutput,"\033[%d;0;9{\033[%d%c\033[9}",width,despl,direction);
101};
102
103static inline void
104lbpmoveabs(int x, int y)
105{
106	fprintf(lbpoutput,"\033[%d;%df",y,x);
107};
108
109static inline void
110lbplineto(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
117static inline void
118lbpruleabs(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
126static inline void vdmprintf(char *format, ... );
127
128static inline char *
129vdmnum(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
152static inline void
153vdmorigin(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
161static inline FILE *
162vdminit(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
175static inline void
176vdmend()
177{
178	vdmprintf("}p\x1e");
179};
180
181static inline void
182vdmprintf(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
192static inline void
193vdmsetfillmode(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
205static inline void
206vdmcircle(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
214static inline void
215vdmaarc(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
225static inline void
226vdmvarc(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
237static inline void
238vdmellipse(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
247static inline void
248vdmsetlinetype(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
256static inline void
257vdmsetlinestyle(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
270static inline void
271vdmlinewidth(int width)
272{
273  char wh[4];
274
275  	vdmprintf("F1%s\x1e",vdmnum(width,wh));
276};
277
278static inline void
279vdmrectangle(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
287static inline void
288vdmpolyline(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
303static inline void
304vdmpolygon(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 ************************************************************************/
324static inline int
325vdminited()
326{
327	return (vdmoutput != NULL);
328}; /* vdminited */
329
330
331static inline void
332vdmline(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) */
347static inline void
348splinerel(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 */
409static void
410quadratic_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]
441static void
442vdmspline(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