Line data Source code
1 : // -*- C -*-
2 : /* Copyright (C) 1994-2020 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 1 : lbpinit(FILE *outfile)
33 : {
34 1 : lbpoutput = outfile;
35 1 : }
36 :
37 :
38 : static void
39 3 : lbpprintf(const char *format, ... )
40 : { /* Taken from cjet */
41 : va_list stuff;
42 :
43 3 : va_start(stuff, format);
44 3 : vfprintf(lbpoutput, format, stuff);
45 3 : va_end(stuff);
46 3 : }
47 :
48 :
49 : static inline void
50 11 : lbpputs(const char *data)
51 : {
52 11 : fputs(data,lbpoutput);
53 11 : }
54 :
55 :
56 : static inline void
57 727 : lbpputc(unsigned char c)
58 : {
59 727 : fputc(c,lbpoutput);
60 727 : }
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 3 : lbpmoveabs(int x, int y)
114 : {
115 3 : fprintf(lbpoutput,"\033[%d;%df",y,x);
116 3 : }
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 0 : lbpruleabs(int x, int y, int hsize, int vsize)
130 : {
131 0 : lbpmoveabs(x,y);
132 0 : fprintf(lbpoutput,"\033[0;9;000s");
133 0 : lbpmoveabs(x+hsize,y+vsize);
134 0 : fprintf(lbpoutput,"\033[9r");
135 0 : }
136 :
137 :
138 : static void vdmprintf(const char *format, ... );
139 :
140 :
141 : static inline char *
142 0 : vdmnum(int num,char *result)
143 : {
144 : char b1,b2,b3;
145 0 : char *p = result;
146 : int nm;
147 :
148 0 : nm = abs(num);
149 : /* First byte 1024 - 32768 */
150 0 : b1 = ((nm >> 10) & 0x3F);
151 0 : if (b1) *p++ = b1 | 0x40;
152 :
153 : /* Second Byte 16 - 1024 */
154 0 : b2 = ((nm >> 4) & 0x3F);
155 0 : if ( b1 || b2) *p++= b2 | 0x40;
156 :
157 : /* Third byte 0 - 15 */
158 0 : b3 = ((nm & 0x0F) | 32);
159 0 : if (num >= 0) b3 |= 16;
160 0 : *p++ = b3;
161 0 : *p = 0x00; /* End of the resulting string */
162 0 : return result;
163 : }
164 :
165 :
166 : static inline void
167 0 : vdmorigin(int newx, int newy)
168 : {
169 : char nx[4],ny[4];
170 :
171 0 : vdmprintf("}\"%s%s\x1e",vdmnum(newx,nx),vdmnum(newy,ny));
172 0 : }
173 :
174 :
175 : static inline FILE *
176 0 : vdminit(FILE *vdmfile)
177 : {
178 : char scale[4],size[4],lineend[4];
179 :
180 : /* vdmoutput = tmpfile();*/
181 0 : vdmoutput = vdmfile;
182 : /* Initialize the VDM mode */
183 0 : vdmprintf("\033[0&}#GROLBP\x1e!0%s%s\x1e$\x1e}F%s\x1e",\
184 : vdmnum(-3,scale),vdmnum(1,size),vdmnum(1,lineend));
185 0 : return vdmoutput;
186 :
187 : }
188 :
189 :
190 : static inline void
191 0 : vdmend()
192 : {
193 0 : vdmprintf("}p\x1e");
194 0 : }
195 :
196 :
197 : static void
198 0 : vdmprintf(const char *format, ... )
199 : { /* Taken from cjet */
200 : va_list stuff;
201 :
202 0 : if (vdmoutput == NULL) vdminit(tmpfile());
203 0 : va_start(stuff, format);
204 0 : vfprintf(vdmoutput, format, stuff);
205 0 : va_end(stuff);
206 0 : }
207 :
208 :
209 : static inline void
210 0 : 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 0 : 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 0 : }
221 :
222 :
223 : static inline void
224 0 : vdmcircle(int centerx, int centery, int radius)
225 : {
226 : char x[4],y[4],rad[4];
227 :
228 0 : vdmprintf("5%s%s%s\x1e",vdmnum(centerx,x),vdmnum(centery,y),\
229 : vdmnum(radius,rad));
230 0 : }
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 0 : 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 0 : 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 0 : }
256 :
257 :
258 : static inline void
259 0 : 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 0 : 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 0 : }
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 0 : vdmlinewidth(int width)
296 : {
297 : char wh[4];
298 :
299 0 : vdmprintf("F1%s\x1e",vdmnum(width,wh));
300 0 : }
301 :
302 :
303 : static inline void
304 0 : vdmrectangle(int origx, int origy,int dstx, int dsty)
305 : {
306 : char xcoord[4],ycoord[4],sdstx[4],sdsty[4];
307 :
308 0 : vdmprintf("}:%s%s%s%s\x1e\n",vdmnum(origx,xcoord),vdmnum(dstx,sdstx),\
309 : vdmnum(origy,ycoord),vdmnum(dsty,sdsty));
310 0 : }
311 :
312 :
313 : static inline void
314 0 : vdmpolyline(int numpoints, int *points)
315 : {
316 0 : int i,*p = points;
317 : char xcoord[4],ycoord[4];
318 :
319 0 : if (numpoints < 2) return;
320 0 : vdmprintf("1%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
321 0 : p += 2;
322 0 : for (i = 1; i < numpoints ; i++) {
323 0 : vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
324 0 : p += 2;
325 : } /* for */
326 0 : vdmprintf("\x1e\n");
327 : }
328 :
329 :
330 : static inline void
331 0 : vdmpolygon(int numpoints, int *points)
332 : {
333 0 : int i,*p = points;
334 : char xcoord[4],ycoord[4];
335 :
336 0 : if (numpoints < 2) return;
337 0 : vdmprintf("2%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
338 0 : p += 2;
339 0 : for (i = 1; i < numpoints ; i++) {
340 0 : vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord));
341 0 : p += 2;
342 : } /* for */
343 0 : vdmprintf("\x1e\n");
344 :
345 : }
346 :
347 :
348 : /************************************************************************
349 : * Higher level auxiliary functions *
350 : ************************************************************************/
351 : static inline int
352 2 : vdminited()
353 : {
354 2 : return (vdmoutput != NULL);
355 : }
356 :
357 :
358 : static inline void
359 0 : vdmline(int startx, int starty, int sizex, int sizey)
360 : {
361 : int points[4];
362 :
363 0 : points[0] = startx;
364 0 : points[1] = starty;
365 0 : points[2] = sizex;
366 0 : points[3] = sizey;
367 :
368 0 : vdmpolyline(2,points);
369 :
370 0 : }
371 :
372 :
373 : /*#define THRESHOLD .05 */ /* inch */
374 : #define THRESHOLD 1 /* points (1/300 inch) */
375 : static inline void
376 0 : 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 0 : int dxnew = 0, dynew = 0, sg;
382 : char xcoord[4],ycoord[4];
383 : double npend ;
384 :
385 0 : if (flush == -1) {lx = (int)px; ly = (int)py; return;}
386 :
387 0 : if (flush == 0) {
388 0 : dxnew = (int)px -lx;
389 0 : dynew = (int)py -ly;
390 0 : if ((dxnew == 0) && (dynew == 0)) return;
391 0 : sg = (dxnew < 0)? -1 : 0;
392 : /* fprintf(stderr,"s (%d,%d) (%d,%d)\n",dxnew,dynew,despx,despy);*/
393 0 : if (dynew == 0) {
394 0 : despx = dxnew;
395 0 : if ((sg == sigpend) && (dy == 0)){
396 0 : return;
397 : }
398 0 : dy = 0;
399 : }
400 : else {
401 0 : dy = 1;
402 0 : npend = (1.0*dxnew)/dynew;
403 0 : if (( npend == pend) && (sigpend == sg))
404 0 : { despy = dynew; despx = dxnew; return; }
405 : else
406 0 : { sigpend = sg;
407 0 : 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 0 : 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 0 : if (flush) {
419 0 : dxnew = dy = despx = despy = 0;
420 0 : return;
421 : } /* if (flush) */
422 0 : dxnew -= despx;
423 0 : dynew -= despy;
424 0 : 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 0 : lx = (int)px; ly = (int)py;
430 0 : 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 0 : 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 0 : x_1 = a_1; y_1 = b_1;
446 0 : x_4 = a_4; y_4 = b_4;
447 0 : x_mid = (a_2 + a_3)/2.0;
448 0 : y_mid = (b_2 + b_3)/2.0;
449 0 : if ((fabs(x_1 - x_mid) < THRESHOLD)
450 0 : && (fabs(y_1 - y_mid) < THRESHOLD)) {
451 0 : splinerel(x_mid, y_mid, 0);
452 : /* fprintf(tfp, "PA%.4f,%.4f;\n", x_mid, y_mid);*/
453 : }
454 : else {
455 0 : quadratic_spline(x_1, y_1, ((x_1+a_2)/2.0), ((y_1+b_2)/2.0),
456 0 : ((3.0*a_2+a_3)/4.0), ((3.0*b_2+b_3)/4.0), x_mid, y_mid);
457 : }
458 :
459 0 : if ((fabs(x_mid - x_4) < THRESHOLD)
460 0 : && (fabs(y_mid - y_4) < THRESHOLD)) {
461 0 : splinerel(x_4, y_4, 0);
462 : /* fprintf(tfp, "PA%.4f,%.4f;\n", x_4, y_4);*/
463 : }
464 : else {
465 0 : quadratic_spline(x_mid, y_mid,
466 0 : ((a_2+3.0*a_3)/4.0), ((b_2+3.0*b_3)/4.0),
467 0 : ((a_3+x_4)/2.0), ((b_3+y_4)/2.0), x_4, y_4);
468 : }
469 0 : }
470 :
471 :
472 : #define XCOORD(i) numbers[(2*i)]
473 : #define YCOORD(i) numbers[(2*i)+1]
474 : static void
475 0 : 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 0 : x_1 = o_x;
485 0 : y_1 = o_y;
486 : /* p = p->next;
487 : x_2 = p->x/ppi;
488 : y_2 = p->y/ppi;*/
489 0 : x_2 = o_x + XCOORD(0);
490 0 : y_2 = o_y + YCOORD(0);
491 0 : cx_1 = (x_1 + x_2)/2.0;
492 0 : cy_1 = (y_1 + y_2)/2.0;
493 0 : cx_2 = (x_1 + 3.0*x_2)/4.0;
494 0 : 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 0 : vdmprintf("1%s%s",vdmnum((int)x_1,xcoord),vdmnum((int)y_1,ycoord));
498 0 : splinerel(x_1,y_1,-1);
499 0 : 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 0 : for (i = 1; i < (numpoints); i++) {
505 0 : x_1 = x_2;
506 0 : y_1 = y_2;
507 : /* x_2 = p->x/ppi;
508 : y_2 = p->y/ppi;*/
509 0 : x_2 = x_1 + XCOORD(i);
510 0 : y_2 = y_1 + YCOORD(i);
511 0 : cx_3 = (3.0*x_1 + x_2)/4.0;
512 0 : cy_3 = (3.0*y_1 + y_2)/4.0;
513 0 : cx_4 = (x_1 + x_2)/2.0;
514 0 : 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 0 : quadratic_spline(cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4);
517 0 : cx_1 = cx_4;
518 0 : cy_1 = cy_4;
519 0 : cx_2 = (x_1 + 3.0*x_2)/4.0;
520 0 : cy_2 = (y_1 + 3.0*y_2)/4.0;
521 : }
522 0 : x_1 = x_2;
523 0 : y_1 = y_2;
524 : /* p = s->points->next;
525 : x_2 = p->x/ppi;
526 : y_2 = p->y/ppi;*/
527 0 : x_2 = o_x + XCOORD(0);
528 0 : y_2 = o_y + YCOORD(0);
529 0 : cx_3 = (3.0*x_1 + x_2)/4.0;
530 0 : cy_3 = (3.0*y_1 + y_2)/4.0;
531 0 : cx_4 = (x_1 + x_2)/2.0;
532 0 : cy_4 = (y_1 + y_2)/2.0;
533 0 : splinerel(x_1, y_1, 0);
534 0 : splinerel(x_1, y_1, 1);
535 : /*vdmprintf("%s%s",vdmnum((int)(x_1-lx),xcoord),\
536 : vdmnum((int)(y_1-ly),ycoord));*/
537 0 : vdmprintf("\x1e\n");
538 : /* fprintf(tfp, "PA%.4f,%.4f;PU;\n", x_1, y_1);*/
539 :
540 :
541 0 : }
542 :
543 :
544 : #endif
|