1// -*- C -*- 2/* Copyright (C) 1994, 2000, 2001, 2003, 2004, 2005 3 Free Software Foundation, Inc. 4 Written by Francisco Andr�s Verd� <pandres@dragonet.es> 5 6groff is free software; you can redistribute it and/or modify it under 7the terms of the GNU General Public License as published by the Free 8Software Foundation; either version 2, or (at your option) any later 9version. 10 11groff is distributed in the hope that it will be useful, but WITHOUT ANY 12WARRANTY; without even the implied warranty of MERCHANTABILITY or 13FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14for more details. 15 16You should have received a copy of the GNU General Public License along 17with groff; see the file COPYING. If not, write to the Free Software 18Foundation, 51 Franklin St - Fifth Floor, Boston, MA 02110-1301, USA. */ 19 20/* This file contains a set of utility functions to use canon CAPSL printers 21 * (lbp-4 and lbp-8 series printers) */ 22 23#ifndef LBP_H 24#define LBP_H 25 26#include <stdio.h> 27#include <stdarg.h> 28 29static FILE *lbpoutput = NULL; 30static FILE *vdmoutput = NULL; 31 32 33static inline void 34lbpinit(FILE *outfile) 35{ 36 lbpoutput = outfile; 37} 38 39 40static void 41lbpprintf(const char *format, ... ) 42{ /* Taken from cjet */ 43 va_list stuff; 44 45 va_start(stuff, format); 46 vfprintf(lbpoutput, format, stuff); 47 va_end(stuff); 48} 49 50 51static inline void 52lbpputs(const char *data) 53{ 54 fputs(data,lbpoutput); 55} 56 57 58static inline void 59lbpputc(unsigned char c) 60{ 61 fputc(c,lbpoutput); 62} 63 64 65static inline void 66lbpsavestatus(int idx ) 67{ 68 fprintf(lbpoutput,"\033[%d%%y",idx); 69} 70 71 72static inline void 73lbprestorestatus(int idx ) 74{ 75 fprintf(lbpoutput,"\033[%d%cz",idx ,'%'); 76} 77 78 79static inline void 80lbpsavepos(int idx) 81{ 82 fprintf(lbpoutput,"\033[1;%d;0x",idx); 83} 84 85 86static inline void 87lbprestorepos(int idx) 88{ 89 fprintf(lbpoutput,"\033[0;%d;0x",idx); 90} 91 92 93static inline void 94lbprestoreposx(int idx) 95{ 96 fprintf(lbpoutput,"\033[0;%d;1x",idx); 97} 98 99 100static inline void 101lbpmoverel(int despl, char direction) 102{ 103 fprintf(lbpoutput,"\033[%d%c",despl,direction); 104} 105 106 107static inline void 108lbplinerel(int width,int despl,char direction ) 109{ 110 fprintf(lbpoutput,"\033[%d;0;9{\033[%d%c\033[9}",width,despl,direction); 111} 112 113 114static inline void 115lbpmoveabs(int x, int y) 116{ 117 fprintf(lbpoutput,"\033[%d;%df",y,x); 118} 119 120 121static inline void 122lbplineto(int x,int y, int width ) 123{ 124 fprintf(lbpoutput,"\033[%d;0;9{",width); 125 lbpmoveabs(x,y); 126 fprintf(lbpoutput,"\033[9}\n"); 127} 128 129 130static inline void 131lbpruleabs(int x, int y, int hsize, int vsize) 132{ 133 lbpmoveabs(x,y); 134 fprintf(lbpoutput,"\033[0;9;000s"); 135 lbpmoveabs(x+hsize,y+vsize); 136 fprintf(lbpoutput,"\033[9r"); 137} 138 139 140static void vdmprintf(const char *format, ... ); 141 142 143static inline char * 144vdmnum(int num,char *result) 145{ 146 char b1,b2,b3; 147 char *p = result; 148 int nm; 149 150 nm = abs(num); 151 /* First byte 1024 - 32768 */ 152 b1 = ((nm >> 10) & 0x3F); 153 if (b1) *p++ = b1 | 0x40; 154 155 /* Second Byte 16 - 1024 */ 156 b2 = ((nm >> 4) & 0x3F); 157 if ( b1 || b2) *p++= b2 | 0x40; 158 159 /* Third byte 0 - 15 */ 160 b3 = ((nm & 0x0F) | 32); 161 if (num >= 0) b3 |= 16; 162 *p++ = b3; 163 *p = 0x00; /* End of the resulting string */ 164 return result; 165} 166 167 168static inline void 169vdmorigin(int newx, int newy) 170{ 171 char nx[4],ny[4]; 172 173 vdmprintf("}\"%s%s\x1e",vdmnum(newx,nx),vdmnum(newy,ny)); 174} 175 176 177static inline FILE * 178vdminit(FILE *vdmfile) 179{ 180 char scale[4],size[4],lineend[4]; 181 182/* vdmoutput = tmpfile();*/ 183 vdmoutput = vdmfile; 184 /* Initialize the VDM mode */ 185 vdmprintf("\033[0&}#GROLBP\x1e!0%s%s\x1e$\x1e}F%s\x1e",\ 186 vdmnum(-3,scale),vdmnum(1,size),vdmnum(1,lineend)); 187 return vdmoutput; 188 189} 190 191 192static inline void 193vdmend() 194{ 195 vdmprintf("}p\x1e"); 196} 197 198 199static void 200vdmprintf(const char *format, ... ) 201{ /* Taken from cjet */ 202 va_list stuff; 203 204 if (vdmoutput == NULL) vdminit(tmpfile()); 205 va_start(stuff, format); 206 vfprintf(vdmoutput, format, stuff); 207 va_end(stuff); 208} 209 210 211static inline void 212vdmsetfillmode(int pattern,int perimeter, int inverted) 213{ 214 char patt[4],perim[4], 215 rot[4], /* rotation */ 216 espejo[4], /* espejo */ 217 inv[4]; /* Inverted */ 218 219 vdmprintf("I%s%s%s%s%s\x1e",vdmnum(pattern,patt),\ 220 vdmnum(perimeter,perim),vdmnum(0,rot), 221 vdmnum(0,espejo),vdmnum(inverted,inv)); 222} 223 224 225static inline void 226vdmcircle(int centerx, int centery, int radius) 227{ 228 char x[4],y[4],rad[4]; 229 230 vdmprintf("5%s%s%s\x1e",vdmnum(centerx,x),vdmnum(centery,y),\ 231 vdmnum(radius,rad)); 232} 233 234 235static inline void 236vdmaarc(int centerx, int centery, int radius,int startangle,int angle,int style,int arcopen) 237{ 238 char x[4],y[4],rad[4],stx[4],sty[4],styl[4],op[4]; 239 240 vdmprintf("}6%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\ 241 vdmnum(centerx,x),vdmnum(centery,y),\ 242 vdmnum(radius,rad),vdmnum(startangle,stx),vdmnum(angle,sty),\ 243 vdmnum(style,styl)); 244} 245 246 247static inline void 248vdmvarc(int centerx, int centery,int radius, int startx, int starty, int endx, int endy,\ 249 int style,int arcopen) 250{ 251 char x[4],y[4],rad[4],stx[4],sty[4],enx[4],eny[4],styl[4],op[4]; 252 253 vdmprintf("}6%s%s%s%s%s%s%s%s%s\x1e",vdmnum(arcopen,op),\ 254 vdmnum(centerx,x),vdmnum(centery,y),\ 255 vdmnum(radius,rad),vdmnum(startx,stx),vdmnum(starty,sty),\ 256 vdmnum(endx,enx),vdmnum(endy,eny),vdmnum(style,styl)); 257} 258 259 260static inline void 261vdmellipse(int centerx, int centery, int radiusx, int radiusy,int rotation) 262{ 263 char x[4],y[4],radx[4],rady[4],rotat[4]; 264 265 vdmprintf("}7%s%s%s%s%s\x1e\n",vdmnum(centerx,x),vdmnum(centery,y),\ 266 vdmnum(radiusx,radx),vdmnum(radiusy,rady),\ 267 vdmnum(rotation,rotat)); 268} 269 270 271static inline void 272vdmsetlinetype(int lintype) 273{ 274 char ltyp[4], expfact[4]; 275 276 vdmprintf("E1%s%s\x1e",vdmnum(lintype,ltyp),vdmnum(1,expfact)); 277 278} 279 280 281static inline void 282vdmsetlinestyle(int lintype, int pattern,int unionstyle) 283{ 284 char patt[4],ltip[4], 285 rot[4], /* rotation */ 286 espejo[4], /* espejo */ 287 in[4]; /* Inverted */ 288 289 vdmprintf("}G%s%s%s%s%s\x1e",vdmnum(lintype,ltip),\ 290 vdmnum(pattern,patt),vdmnum(0,rot), 291 vdmnum(0,espejo),vdmnum(0,in)); 292 vdmprintf("}F%s",vdmnum(unionstyle,rot)); 293} 294 295 296static inline void 297vdmlinewidth(int width) 298{ 299 char wh[4]; 300 301 vdmprintf("F1%s\x1e",vdmnum(width,wh)); 302} 303 304 305static inline void 306vdmrectangle(int origx, int origy,int dstx, int dsty) 307{ 308 char xcoord[4],ycoord[4],sdstx[4],sdsty[4]; 309 310 vdmprintf("}:%s%s%s%s\x1e\n",vdmnum(origx,xcoord),vdmnum(dstx,sdstx),\ 311 vdmnum(origy,ycoord),vdmnum(dsty,sdsty)); 312} 313 314 315static inline void 316vdmpolyline(int numpoints, int *points) 317{ 318 int i,*p = points; 319 char xcoord[4],ycoord[4]; 320 321 if (numpoints < 2) return; 322 vdmprintf("1%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); 323 p += 2; 324 for (i = 1; i < numpoints ; i++) { 325 vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); 326 p += 2; 327 } /* for */ 328 vdmprintf("\x1e\n"); 329} 330 331 332static inline void 333vdmpolygon(int numpoints, int *points) 334{ 335 int i,*p = points; 336 char xcoord[4],ycoord[4]; 337 338 if (numpoints < 2) return; 339 vdmprintf("2%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); 340 p += 2; 341 for (i = 1; i < numpoints ; i++) { 342 vdmprintf("%s%s",vdmnum(*p,xcoord),vdmnum(*(p+1),ycoord)); 343 p += 2; 344 } /* for */ 345 vdmprintf("\x1e\n"); 346 347} 348 349 350/************************************************************************ 351 * Highter level auxiliary functions * 352 ************************************************************************/ 353static inline int 354vdminited() 355{ 356 return (vdmoutput != NULL); 357} 358 359 360static inline void 361vdmline(int startx, int starty, int sizex, int sizey) 362{ 363 int points[4]; 364 365 points[0] = startx; 366 points[1] = starty; 367 points[2] = sizex; 368 points[3] = sizey; 369 370 vdmpolyline(2,points); 371 372} 373 374 375/*#define THRESHOLD .05 */ /* inch */ 376#define THRESHOLD 1 /* points (1/300 inch) */ 377static inline void 378splinerel(double px,double py,int flush) 379{ 380 static int lx = 0 ,ly = 0; 381 static double pend = 0.0; 382 static int dy = 0, despx = 0, despy = 0, sigpend = 0; 383 int dxnew = 0, dynew = 0, sg; 384 char xcoord[4],ycoord[4]; 385 double npend ; 386 387 if (flush == -1) {lx = (int)px; ly = (int)py; return;} 388 389 if (flush == 0) { 390 dxnew = (int)px -lx; 391 dynew = (int)py -ly; 392 if ((dxnew == 0) && (dynew == 0)) return; 393 sg = (dxnew < 0)? -1 : 0; 394/* fprintf(stderr,"s (%d,%d) (%d,%d)\n",dxnew,dynew,despx,despy);*/ 395 if (dynew == 0) { 396 despx = dxnew; 397 if ((sg == sigpend) && (dy == 0)){ 398 return; 399 } 400 dy = 0; 401 } 402 else { 403 dy = 1; 404 npend = (1.0*dxnew)/dynew; 405 if (( npend == pend) && (sigpend == sg)) 406 { despy = dynew; despx = dxnew; return; } 407 else 408 { sigpend = sg; 409 pend = npend; 410 } /* else (( npend == pend) && ... */ 411 } /* else (if (dynew == 0)) */ 412 } /* if (!flush ) */ 413 414 /* if we've changed direction we must draw the line */ 415/* fprintf(stderr," (%d) %.2f,%.2f\n",flush,(float)px,(float)py);*/ 416 if ((despx != 0) || (despy != 0)) vdmprintf("%s%s",vdmnum(despx,xcoord),\ 417 vdmnum(despy,ycoord)); 418 /*if ((despx != 0) || (despy != 0)) fprintf(stderr,"2 419 *%d,%d\n",despx,despy);*/ 420 if (flush) { 421 dxnew = dy = despx = despy = 0; 422 return; 423 } /* if (flush) */ 424 dxnew -= despx; 425 dynew -= despy; 426 if ((dxnew != 0) || (dynew != 0)) vdmprintf("%s%s",vdmnum(dxnew,xcoord),\ 427 vdmnum(dynew,ycoord)); 428 429/* if ((dxnew != 0) || (dynew != 0)) fprintf(stderr,"3 430 * %d,%d\n",dxnew,dynew);*/ 431 lx = (int)px; ly = (int)py; 432 dxnew = dy = despx = despy = 0; 433 434} 435 436 437/********************************************************************** 438 * The following code to draw splines is adapted from the transfig package 439 */ 440static void 441quadratic_spline(double a_1, double b_1, double a_2, double b_2, \ 442 double a_3, double b_3, double a_4, double b_4) 443{ 444 double x_1, y_1, x_4, y_4; 445 double x_mid, y_mid; 446 447 x_1 = a_1; y_1 = b_1; 448 x_4 = a_4; y_4 = b_4; 449 x_mid = (a_2 + a_3)/2.0; 450 y_mid = (b_2 + b_3)/2.0; 451 if ((fabs(x_1 - x_mid) < THRESHOLD) 452 && (fabs(y_1 - y_mid) < THRESHOLD)) { 453 splinerel(x_mid, y_mid, 0); 454/* fprintf(tfp, "PA%.4f,%.4f;\n", x_mid, y_mid);*/ 455 } 456 else { 457 quadratic_spline(x_1, y_1, ((x_1+a_2)/2.0), ((y_1+b_2)/2.0), 458 ((3.0*a_2+a_3)/4.0), ((3.0*b_2+b_3)/4.0), x_mid, y_mid); 459 } 460 461 if ((fabs(x_mid - x_4) < THRESHOLD) 462 && (fabs(y_mid - y_4) < THRESHOLD)) { 463 splinerel(x_4, y_4, 0); 464/* fprintf(tfp, "PA%.4f,%.4f;\n", x_4, y_4);*/ 465 } 466 else { 467 quadratic_spline(x_mid, y_mid, 468 ((a_2+3.0*a_3)/4.0), ((b_2+3.0*b_3)/4.0), 469 ((a_3+x_4)/2.0), ((b_3+y_4)/2.0), x_4, y_4); 470 } 471} 472 473 474#define XCOORD(i) numbers[(2*i)] 475#define YCOORD(i) numbers[(2*i)+1] 476static void 477vdmspline(int numpoints, int o_x, int o_y, int *numbers) 478{ 479 double cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4; 480 double x_1, y_1, x_2, y_2; 481 char xcoord[4],ycoord[4]; 482 int i; 483 484 /*p = s->points; 485 x_1 = p->x/ppi;*/ 486 x_1 = o_x; 487 y_1 = o_y; 488/* p = p->next; 489 x_2 = p->x/ppi; 490 y_2 = p->y/ppi;*/ 491 x_2 = o_x + XCOORD(0); 492 y_2 = o_y + YCOORD(0); 493 cx_1 = (x_1 + x_2)/2.0; 494 cy_1 = (y_1 + y_2)/2.0; 495 cx_2 = (x_1 + 3.0*x_2)/4.0; 496 cy_2 = (y_1 + 3.0*y_2)/4.0; 497 498/* fprintf(stderr,"Spline %d (%d,%d)\n",numpoints,(int)x_1,(int)y_1);*/ 499 vdmprintf("1%s%s",vdmnum((int)x_1,xcoord),vdmnum((int)y_1,ycoord)); 500 splinerel(x_1,y_1,-1); 501 splinerel(cx_1,cy_1,0); 502/* fprintf(tfp, "PA%.4f,%.4f;PD%.4f,%.4f;\n", 503 x_1, y_1, cx_1, cy_1);*/ 504 505 /*for (p = p->next; p != NULL; p = p->next) {*/ 506 for (i = 1; i < (numpoints); i++) { 507 x_1 = x_2; 508 y_1 = y_2; 509/* x_2 = p->x/ppi; 510 y_2 = p->y/ppi;*/ 511 x_2 = x_1 + XCOORD(i); 512 y_2 = y_1 + YCOORD(i); 513 cx_3 = (3.0*x_1 + x_2)/4.0; 514 cy_3 = (3.0*y_1 + y_2)/4.0; 515 cx_4 = (x_1 + x_2)/2.0; 516 cy_4 = (y_1 + y_2)/2.0; 517 /* fprintf(stderr,"Point (%d,%d) - (%d,%d)\n",(int)x_1,(int)(y_1),(int)x_2,(int)y_2);*/ 518 quadratic_spline(cx_1, cy_1, cx_2, cy_2, cx_3, cy_3, cx_4, cy_4); 519 cx_1 = cx_4; 520 cy_1 = cy_4; 521 cx_2 = (x_1 + 3.0*x_2)/4.0; 522 cy_2 = (y_1 + 3.0*y_2)/4.0; 523 } 524 x_1 = x_2; 525 y_1 = y_2; 526/* p = s->points->next; 527 x_2 = p->x/ppi; 528 y_2 = p->y/ppi;*/ 529 x_2 = o_x + XCOORD(0); 530 y_2 = o_y + YCOORD(0); 531 cx_3 = (3.0*x_1 + x_2)/4.0; 532 cy_3 = (3.0*y_1 + y_2)/4.0; 533 cx_4 = (x_1 + x_2)/2.0; 534 cy_4 = (y_1 + y_2)/2.0; 535 splinerel(x_1, y_1, 0); 536 splinerel(x_1, y_1, 1); 537 /*vdmprintf("%s%s",vdmnum((int)(x_1-lx),xcoord),\ 538 vdmnum((int)(y_1-ly),ycoord));*/ 539 vdmprintf("\x1e\n"); 540/* fprintf(tfp, "PA%.4f,%.4f;PU;\n", x_1, y_1);*/ 541 542 543} 544 545 546#endif 547