Initial import from FreeBSD RELENG_4:
[dragonfly.git] / contrib / groff / src / devices / grolbp / lbp.h
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 
32 lbpinit(FILE *outfile)
33 {
34         lbpoutput = outfile;
35 };
36
37
38 static inline void 
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
49 lbpputs(const char *data)
50 {
51         fputs(data,lbpoutput);
52 };
53
54 static inline void
55 lbpputc(char c)
56 {
57         fputc(c,lbpoutput);
58 };
59
60
61 static inline void 
62 lbpsavestatus(int index )
63 {
64         fprintf(lbpoutput,"\033[%d%%y",index);
65 };
66
67 static inline void 
68 lbprestorestatus(int index )
69 {
70         fprintf(lbpoutput,"\033[%d%cz",index ,'%');
71 };
72
73 static inline void 
74 lbpsavepos(int index)
75 {
76         fprintf(lbpoutput,"\033[1;%d;0x",index);
77 };
78
79 static inline void 
80 lbprestorepos(int index)
81 {
82         fprintf(lbpoutput,"\033[0;%d;0x",index);
83 };
84
85 static inline void 
86 lbprestoreposx(int index)
87 {
88         fprintf(lbpoutput,"\033[0;%d;1x",index);
89 };
90
91 static inline void 
92 lbpmoverel(int despl, char direction)
93 {
94         fprintf(lbpoutput,"\033[%d%c",despl,direction);
95 };
96
97 static inline void 
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 
104 lbpmoveabs(int x, int y)
105 {
106         fprintf(lbpoutput,"\033[%d;%df",y,x);
107 };
108
109 static inline void
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
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 *
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
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 *
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
176 vdmend()
177 {
178         vdmprintf("}p\x1e");
179 };
180
181 static inline void 
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
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
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
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
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
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
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
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
271 vdmlinewidth(int width)
272 {
273   char wh[4];
274
275         vdmprintf("F1%s\x1e",vdmnum(width,wh));
276 };
277
278 static inline void
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
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
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
325 vdminited()
326 {
327         return (vdmoutput != NULL);
328 }; /* vdminited */
329
330
331 static inline void
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
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
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
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