68cd8dce1b552e6d710c15c013dea64fcb156d75
[platform/upstream/groff.git] / src / devices / grolbp / lbp.h
1 // -*- C -*-
2 /* Copyright (C) 1994-2014  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 
32 lbpinit(FILE *outfile)
33 {
34         lbpoutput = outfile;
35 }
36
37
38 static 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
49 static inline void
50 lbpputs(const char *data)
51 {
52         fputs(data,lbpoutput);
53 }
54
55
56 static inline void
57 lbpputc(unsigned char c)
58 {
59         fputc(c,lbpoutput);
60 }
61
62
63 static inline void 
64 lbpsavestatus(int idx )
65 {
66         fprintf(lbpoutput,"\033[%d%%y",idx);
67 }
68
69
70 static inline void 
71 lbprestorestatus(int idx )
72 {
73         fprintf(lbpoutput,"\033[%d%cz",idx ,'%');
74 }
75
76
77 static inline void 
78 lbpsavepos(int idx)
79 {
80         fprintf(lbpoutput,"\033[1;%d;0x",idx);
81 }
82
83
84 static inline void 
85 lbprestorepos(int idx)
86 {
87         fprintf(lbpoutput,"\033[0;%d;0x",idx);
88 }
89
90
91 static inline void 
92 lbprestoreposx(int idx)
93 {
94         fprintf(lbpoutput,"\033[0;%d;1x",idx);
95 }
96
97
98 static inline void 
99 lbpmoverel(int despl, char direction)
100 {
101         fprintf(lbpoutput,"\033[%d%c",despl,direction);
102 }
103
104
105 static inline void 
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 
113 lbpmoveabs(int x, int y)
114 {
115         fprintf(lbpoutput,"\033[%d;%df",y,x);
116 }
117
118
119 static inline void
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
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 *
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
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 *
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
191 vdmend()
192 {
193         vdmprintf("}p\x1e");
194 }
195
196
197 static void 
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
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
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
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
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
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
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
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
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
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
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
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
352 vdminited()
353 {
354         return (vdmoutput != NULL);
355 }
356
357
358 static inline void
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
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
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
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