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