1 /* 2 * EPSON ESC/P and ESC/P2 filter for CUPS. 3 * 4 * Copyright 2007-2015 by Apple Inc. 5 * Copyright 1993-2007 by Easy Software Products. 6 * 7 * These coded instructions, statements, and computer programs are the 8 * property of Apple Inc. and are protected by Federal copyright 9 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 10 * which should have been included with this file. If this file is 11 * missing or damaged, see the license at "http://www.cups.org/". 12 * 13 * This file is subject to the Apple OS-Developed Software exception. 14 */ 15 16 /* 17 * Include necessary headers... 18 */ 19 20 #include <cups/cups.h> 21 #include <cups/ppd.h> 22 #include <cups/string-private.h> 23 #include <cups/language-private.h> 24 #include <cups/raster.h> 25 #include <unistd.h> 26 #include <fcntl.h> 27 #include <signal.h> 28 29 30 /* 31 * Model numbers... 32 */ 33 34 #define EPSON_9PIN 0 35 #define EPSON_24PIN 1 36 #define EPSON_COLOR 2 37 #define EPSON_PHOTO 3 38 #define EPSON_ICOLOR 4 39 #define EPSON_IPHOTO 5 40 41 42 /* 43 * Macros... 44 */ 45 46 #define pwrite(s,n) fwrite((s), 1, (n), stdout) 47 48 49 /* 50 * Globals... 51 */ 52 53 unsigned char *Planes[6], /* Output buffers */ 54 *CompBuffer, /* Compression buffer */ 55 *LineBuffers[2]; /* Line bitmap buffers */ 56 int Model, /* Model number */ 57 EjectPage, /* Eject the page when done? */ 58 Shingling, /* Shingle output? */ 59 Canceled; /* Has the current job been canceled? */ 60 unsigned NumPlanes, /* Number of color planes */ 61 Feed, /* Number of lines to skip */ 62 DotBit, /* Bit in buffers */ 63 DotBytes, /* # bytes in a dot column */ 64 DotColumns, /* # columns in 1/60 inch */ 65 LineCount, /* # of lines processed */ 66 EvenOffset, /* Offset into 'even' buffers */ 67 OddOffset; /* Offset into 'odd' buffers */ 68 69 70 /* 71 * Prototypes... 72 */ 73 74 void Setup(void); 75 void StartPage(const ppd_file_t *ppd, const cups_page_header2_t *header); 76 void EndPage(const cups_page_header2_t *header); 77 void Shutdown(void); 78 79 void CancelJob(int sig); 80 void CompressData(const unsigned char *line, unsigned length, unsigned plane, 81 unsigned type, unsigned xstep, unsigned ystep); 82 void OutputLine(const cups_page_header2_t *header); 83 void OutputRows(const cups_page_header2_t *header, int row); 84 85 86 /* 87 * 'Setup()' - Prepare the printer for printing. 88 */ 89 90 void 91 Setup(void) 92 { 93 const char *device_uri; /* The device for the printer... */ 94 95 96 /* 97 * EPSON USB printers need an additional command issued at the 98 * beginning of each job to exit from "packet" mode... 99 */ 100 101 if ((device_uri = getenv("DEVICE_URI")) != NULL && 102 strncmp(device_uri, "usb:", 4) == 0 && Model >= EPSON_ICOLOR) 103 pwrite("\000\000\000\033\001@EJL 1284.4\n@EJL \n\033@", 29); 104 } 105 106 107 /* 108 * 'StartPage()' - Start a page of graphics. 109 */ 110 111 void 112 StartPage( 113 const ppd_file_t *ppd, /* I - PPD file */ 114 const cups_page_header2_t *header) /* I - Page header */ 115 { 116 int n, t; /* Numbers */ 117 unsigned plane; /* Looping var */ 118 119 120 /* 121 * Show page device dictionary... 122 */ 123 124 fprintf(stderr, "DEBUG: StartPage...\n"); 125 fprintf(stderr, "DEBUG: Duplex = %d\n", header->Duplex); 126 fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0], header->HWResolution[1]); 127 fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n", header->ImagingBoundingBox[0], header->ImagingBoundingBox[1], header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]); 128 fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0], header->Margins[1]); 129 fprintf(stderr, "DEBUG: ManualFeed = %d\n", header->ManualFeed); 130 fprintf(stderr, "DEBUG: MediaPosition = %d\n", header->MediaPosition); 131 fprintf(stderr, "DEBUG: NumCopies = %d\n", header->NumCopies); 132 fprintf(stderr, "DEBUG: Orientation = %d\n", header->Orientation); 133 fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0], header->PageSize[1]); 134 fprintf(stderr, "DEBUG: cupsWidth = %d\n", header->cupsWidth); 135 fprintf(stderr, "DEBUG: cupsHeight = %d\n", header->cupsHeight); 136 fprintf(stderr, "DEBUG: cupsMediaType = %d\n", header->cupsMediaType); 137 fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header->cupsBitsPerColor); 138 fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header->cupsBitsPerPixel); 139 fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header->cupsBytesPerLine); 140 fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header->cupsColorOrder); 141 fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace); 142 fprintf(stderr, "DEBUG: cupsCompression = %d\n", header->cupsCompression); 143 144 /* 145 * Send a reset sequence. 146 */ 147 148 if (ppd && ppd->nickname && strstr(ppd->nickname, "OKIDATA") != NULL) 149 printf("\033{A"); /* Set EPSON emulation mode */ 150 151 printf("\033@"); 152 153 /* 154 * See which type of printer we are using... 155 */ 156 157 switch (Model) 158 { 159 case EPSON_9PIN : 160 case EPSON_24PIN : 161 printf("\033P\022"); /* Set 10 CPI */ 162 163 if (header->HWResolution[0] == 360 || header->HWResolution[0] == 240) 164 { 165 printf("\033x1"); /* LQ printing */ 166 printf("\033U1"); /* Unidirectional */ 167 } 168 else 169 { 170 printf("\033x0"); /* Draft printing */ 171 printf("\033U0"); /* Bidirectional */ 172 } 173 174 printf("\033l%c\033Q%c", 0, /* Side margins */ 175 (int)(10.0 * header->PageSize[0] / 72.0 + 0.5)); 176 printf("\033\062\033C%c", /* Page length in 1/6th inches */ 177 (int)(header->PageSize[1] / 12.0 + 0.5)); 178 printf("\033N%c", 0); /* Bottom margin */ 179 printf("\033O"); /* No perforation skip */ 180 181 /* 182 * Setup various buffer limits... 183 */ 184 185 DotBytes = header->cupsRowCount / 8; 186 DotColumns = header->HWResolution[0] / 60; 187 Shingling = 0; 188 189 if (Model == EPSON_9PIN) 190 printf("\033\063\030"); /* Set line feed */ 191 else 192 switch (header->HWResolution[0]) 193 { 194 case 60: 195 case 120 : 196 case 240 : 197 printf("\033\063\030"); /* Set line feed */ 198 break; 199 200 case 180 : 201 case 360 : 202 Shingling = 1; 203 204 if (header->HWResolution[1] == 180) 205 printf("\033\063\010");/* Set line feed */ 206 else 207 printf("\033+\010"); /* Set line feed */ 208 break; 209 } 210 break; 211 212 default : 213 /* 214 * Set graphics mode... 215 */ 216 217 pwrite("\033(G\001\000\001", 6); /* Graphics mode */ 218 219 /* 220 * Set the media size... 221 */ 222 223 if (Model < EPSON_ICOLOR) 224 { 225 pwrite("\033(U\001\000", 5); /* Resolution/units */ 226 putchar((int)(3600 / header->HWResolution[1])); 227 } 228 else 229 { 230 pwrite("\033(U\005\000", 5); 231 putchar((int)(1440 / header->HWResolution[1])); 232 putchar((int)(1440 / header->HWResolution[1])); 233 putchar((int)(1440 / header->HWResolution[0])); 234 putchar(0xa0); /* n/1440ths... */ 235 putchar(0x05); 236 } 237 238 n = (int)(header->PageSize[1] * header->HWResolution[1] / 72.0); 239 240 pwrite("\033(C\002\000", 5); /* Page length */ 241 putchar(n); 242 putchar(n >> 8); 243 244 if (ppd) 245 t = (int)((ppd->sizes[1].length - ppd->sizes[1].top) * header->HWResolution[1] / 72.0); 246 else 247 t = 0; 248 249 pwrite("\033(c\004\000", 5); /* Top & bottom margins */ 250 putchar(t); 251 putchar(t >> 8); 252 putchar(n); 253 putchar(n >> 8); 254 255 if (header->HWResolution[1] == 720) 256 { 257 pwrite("\033(i\001\000\001", 6); /* Microweave */ 258 pwrite("\033(e\002\000\000\001", 7); /* Small dots */ 259 } 260 261 pwrite("\033(V\002\000\000\000", 7); /* Set absolute position 0 */ 262 263 DotBytes = 0; 264 DotColumns = 0; 265 Shingling = 0; 266 break; 267 } 268 269 /* 270 * Set other stuff... 271 */ 272 273 if (header->cupsColorSpace == CUPS_CSPACE_CMY) 274 NumPlanes = 3; 275 else if (header->cupsColorSpace == CUPS_CSPACE_KCMY) 276 NumPlanes = 4; 277 else if (header->cupsColorSpace == CUPS_CSPACE_KCMYcm) 278 NumPlanes = 6; 279 else 280 NumPlanes = 1; 281 282 Feed = 0; /* No blank lines yet */ 283 284 /* 285 * Allocate memory for a line/row of graphics... 286 */ 287 288 if ((Planes[0] = malloc(header->cupsBytesPerLine + NumPlanes)) == NULL) 289 { 290 fputs("ERROR: Unable to allocate memory\n", stderr); 291 exit(1); 292 } 293 294 for (plane = 1; plane < NumPlanes; plane ++) 295 Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes; 296 297 if (header->cupsCompression || DotBytes) 298 { 299 if ((CompBuffer = calloc(2, header->cupsWidth + 1)) == NULL) 300 { 301 fputs("ERROR: Unable to allocate memory\n", stderr); 302 exit(1); 303 } 304 } 305 else 306 CompBuffer = NULL; 307 308 if (DotBytes) 309 { 310 if ((LineBuffers[0] = calloc((size_t)DotBytes, header->cupsWidth * (size_t)(Shingling + 1))) == NULL) 311 { 312 fputs("ERROR: Unable to allocate memory\n", stderr); 313 exit(1); 314 } 315 316 LineBuffers[1] = LineBuffers[0] + DotBytes * header->cupsWidth; 317 DotBit = 128; 318 LineCount = 0; 319 EvenOffset = 0; 320 OddOffset = 0; 321 } 322 } 323 324 325 /* 326 * 'EndPage()' - Finish a page of graphics. 327 */ 328 329 void 330 EndPage( 331 const cups_page_header2_t *header) /* I - Page header */ 332 { 333 if (DotBytes && header) 334 { 335 /* 336 * Flush remaining graphics as needed... 337 */ 338 339 if (!Shingling) 340 { 341 if (DotBit < 128 || EvenOffset) 342 OutputRows(header, 0); 343 } 344 else if (OddOffset > EvenOffset) 345 { 346 OutputRows(header, 1); 347 OutputRows(header, 0); 348 } 349 else 350 { 351 OutputRows(header, 0); 352 OutputRows(header, 1); 353 } 354 } 355 356 /* 357 * Eject the current page... 358 */ 359 360 putchar(12); /* Form feed */ 361 fflush(stdout); 362 363 /* 364 * Free memory... 365 */ 366 367 free(Planes[0]); 368 369 if (CompBuffer) 370 free(CompBuffer); 371 372 if (DotBytes) 373 free(LineBuffers[0]); 374 } 375 376 377 /* 378 * 'Shutdown()' - Shutdown the printer. 379 */ 380 381 void 382 Shutdown(void) 383 { 384 /* 385 * Send a reset sequence. 386 */ 387 388 printf("\033@"); 389 } 390 391 392 /* 393 * 'CancelJob()' - Cancel the current job... 394 */ 395 396 void 397 CancelJob(int sig) /* I - Signal */ 398 { 399 (void)sig; 400 401 Canceled = 1; 402 } 403 404 405 /* 406 * 'CompressData()' - Compress a line of graphics. 407 */ 408 409 void 410 CompressData(const unsigned char *line, /* I - Data to compress */ 411 unsigned length,/* I - Number of bytes */ 412 unsigned plane, /* I - Color plane */ 413 unsigned type, /* I - Type of compression */ 414 unsigned xstep, /* I - X resolution */ 415 unsigned ystep) /* I - Y resolution */ 416 { 417 const unsigned char *line_ptr, /* Current byte pointer */ 418 *line_end, /* End-of-line byte pointer */ 419 *start; /* Start of compression sequence */ 420 unsigned char *comp_ptr, /* Pointer into compression buffer */ 421 temp; /* Current byte */ 422 int count; /* Count of bytes for output */ 423 static int ctable[6] = { 0, 2, 1, 4, 18, 17 }; 424 /* KCMYcm color values */ 425 426 427 /* 428 * Setup pointers... 429 */ 430 431 line_ptr = line; 432 line_end = line + length; 433 434 /* 435 * Do depletion for 720 DPI printing... 436 */ 437 438 if (ystep == 5) 439 { 440 for (comp_ptr = (unsigned char *)line; comp_ptr < line_end;) 441 { 442 /* 443 * Grab the current byte... 444 */ 445 446 temp = *comp_ptr; 447 448 /* 449 * Check adjacent bits... 450 */ 451 452 if ((temp & 0xc0) == 0xc0) 453 temp &= 0xbf; 454 if ((temp & 0x60) == 0x60) 455 temp &= 0xdf; 456 if ((temp & 0x30) == 0x30) 457 temp &= 0xef; 458 if ((temp & 0x18) == 0x18) 459 temp &= 0xf7; 460 if ((temp & 0x0c) == 0x0c) 461 temp &= 0xfb; 462 if ((temp & 0x06) == 0x06) 463 temp &= 0xfd; 464 if ((temp & 0x03) == 0x03) 465 temp &= 0xfe; 466 467 *comp_ptr++ = temp; 468 469 /* 470 * Check the last bit in the current byte and the first bit in the 471 * next byte... 472 */ 473 474 if ((temp & 0x01) && comp_ptr < line_end && *comp_ptr & 0x80) 475 *comp_ptr &= 0x7f; 476 } 477 } 478 479 switch (type) 480 { 481 case 0 : 482 /* 483 * Do no compression... 484 */ 485 break; 486 487 case 1 : 488 /* 489 * Do TIFF pack-bits encoding... 490 */ 491 492 comp_ptr = CompBuffer; 493 494 while (line_ptr < line_end) 495 { 496 if ((line_ptr + 1) >= line_end) 497 { 498 /* 499 * Single byte on the end... 500 */ 501 502 *comp_ptr++ = 0x00; 503 *comp_ptr++ = *line_ptr++; 504 } 505 else if (line_ptr[0] == line_ptr[1]) 506 { 507 /* 508 * Repeated sequence... 509 */ 510 511 line_ptr ++; 512 count = 2; 513 514 while (line_ptr < (line_end - 1) && 515 line_ptr[0] == line_ptr[1] && 516 count < 127) 517 { 518 line_ptr ++; 519 count ++; 520 } 521 522 *comp_ptr++ = (unsigned char)(257 - count); 523 *comp_ptr++ = *line_ptr++; 524 } 525 else 526 { 527 /* 528 * Non-repeated sequence... 529 */ 530 531 start = line_ptr; 532 line_ptr ++; 533 count = 1; 534 535 while (line_ptr < (line_end - 1) && 536 line_ptr[0] != line_ptr[1] && 537 count < 127) 538 { 539 line_ptr ++; 540 count ++; 541 } 542 543 *comp_ptr++ = (unsigned char)(count - 1); 544 545 memcpy(comp_ptr, start, (size_t)count); 546 comp_ptr += count; 547 } 548 } 549 550 line_ptr = CompBuffer; 551 line_end = comp_ptr; 552 break; 553 } 554 555 putchar(0x0d); /* Move print head to left margin */ 556 557 if (Model < EPSON_ICOLOR) 558 { 559 /* 560 * Do graphics the "old" way... 561 */ 562 563 if (NumPlanes > 1) 564 { 565 /* 566 * Set the color... 567 */ 568 569 if (plane > 3) 570 printf("\033(r%c%c%c%c", 2, 0, 1, ctable[plane] & 15); 571 /* Set extended color */ 572 else if (NumPlanes == 3) 573 printf("\033r%c", ctable[plane + 1]); 574 /* Set color */ 575 else 576 printf("\033r%c", ctable[plane]); /* Set color */ 577 } 578 579 /* 580 * Send a raster plane... 581 */ 582 583 length *= 8; 584 printf("\033."); /* Raster graphics */ 585 putchar((int)type); 586 putchar((int)ystep); 587 putchar((int)xstep); 588 putchar(1); 589 putchar((int)length); 590 putchar((int)(length >> 8)); 591 } 592 else 593 { 594 /* 595 * Do graphics the "new" way... 596 */ 597 598 printf("\033i"); 599 putchar(ctable[plane]); 600 putchar((int)type); 601 putchar(1); 602 putchar((int)length); 603 putchar((int)(length >> 8)); 604 putchar(1); 605 putchar(0); 606 } 607 608 pwrite(line_ptr, (size_t)(line_end - line_ptr)); 609 fflush(stdout); 610 } 611 612 613 /* 614 * 'OutputLine()' - Output a line of graphics. 615 */ 616 617 void 618 OutputLine( 619 const cups_page_header2_t *header) /* I - Page header */ 620 { 621 if (header->cupsRowCount) 622 { 623 unsigned width; 624 unsigned char *tempptr, 625 *evenptr, 626 *oddptr; 627 unsigned int x; 628 unsigned char bit; 629 const unsigned char *pixel; 630 unsigned char *temp; 631 632 633 /* 634 * Collect bitmap data in the line buffers and write after each buffer. 635 */ 636 637 for (x = header->cupsWidth, bit = 128, pixel = Planes[0], 638 temp = CompBuffer; 639 x > 0; 640 x --, temp ++) 641 { 642 if (*pixel & bit) 643 *temp |= DotBit; 644 645 if (bit > 1) 646 bit >>= 1; 647 else 648 { 649 bit = 128; 650 pixel ++; 651 } 652 } 653 654 if (DotBit > 1) 655 DotBit >>= 1; 656 else 657 { 658 /* 659 * Copy the holding buffer to the output buffer, shingling as necessary... 660 */ 661 662 if (Shingling && LineCount != 0) 663 { 664 /* 665 * Shingle the output... 666 */ 667 668 if (LineCount & 1) 669 { 670 evenptr = LineBuffers[1] + OddOffset; 671 oddptr = LineBuffers[0] + EvenOffset + DotBytes; 672 } 673 else 674 { 675 evenptr = LineBuffers[0] + EvenOffset; 676 oddptr = LineBuffers[1] + OddOffset + DotBytes; 677 } 678 679 for (width = header->cupsWidth, tempptr = CompBuffer; 680 width > 1; 681 width -= 2, tempptr += 2, oddptr += DotBytes * 2, 682 evenptr += DotBytes * 2) 683 { 684 evenptr[0] = tempptr[0]; 685 oddptr[0] = tempptr[1]; 686 } 687 688 if (width == 1) 689 { 690 evenptr[0] = tempptr[0]; 691 oddptr[0] = tempptr[1]; 692 } 693 } 694 else 695 { 696 /* 697 * Don't shingle the output... 698 */ 699 700 for (width = header->cupsWidth, tempptr = CompBuffer, 701 evenptr = LineBuffers[0] + EvenOffset; 702 width > 0; 703 width --, tempptr ++, evenptr += DotBytes) 704 *evenptr = tempptr[0]; 705 } 706 707 if (Shingling && LineCount != 0) 708 { 709 EvenOffset ++; 710 OddOffset ++; 711 712 if (EvenOffset == DotBytes) 713 { 714 EvenOffset = 0; 715 OutputRows(header, 0); 716 } 717 718 if (OddOffset == DotBytes) 719 { 720 OddOffset = 0; 721 OutputRows(header, 1); 722 } 723 } 724 else 725 { 726 EvenOffset ++; 727 728 if (EvenOffset == DotBytes) 729 { 730 EvenOffset = 0; 731 OutputRows(header, 0); 732 } 733 } 734 735 DotBit = 128; 736 LineCount ++; 737 738 memset(CompBuffer, 0, header->cupsWidth); 739 } 740 } 741 else 742 { 743 unsigned plane; /* Current plane */ 744 unsigned bytes; /* Bytes per plane */ 745 unsigned xstep, ystep; /* X & Y resolutions */ 746 747 /* 748 * Write a single line of bitmap data as needed... 749 */ 750 751 xstep = 3600 / header->HWResolution[0]; 752 ystep = 3600 / header->HWResolution[1]; 753 bytes = header->cupsBytesPerLine / NumPlanes; 754 755 for (plane = 0; plane < NumPlanes; plane ++) 756 { 757 /* 758 * Skip blank data... 759 */ 760 761 if (!Planes[plane][0] && 762 memcmp(Planes[plane], Planes[plane] + 1, (size_t)bytes - 1) == 0) 763 continue; 764 765 /* 766 * Output whitespace as needed... 767 */ 768 769 if (Feed > 0) 770 { 771 pwrite("\033(v\002\000", 5); /* Relative vertical position */ 772 putchar((int)Feed); 773 putchar((int)(Feed >> 8)); 774 775 Feed = 0; 776 } 777 778 CompressData(Planes[plane], bytes, plane, header->cupsCompression, xstep, ystep); 779 } 780 781 Feed ++; 782 } 783 } 784 785 786 /* 787 * 'OutputRows()' - Output 8, 24, or 48 rows. 788 */ 789 790 void 791 OutputRows( 792 const cups_page_header2_t *header, /* I - Page image header */ 793 int row) /* I - Row number (0 or 1) */ 794 { 795 unsigned i, n, /* Looping vars */ 796 dot_count, /* Number of bytes to print */ 797 dot_min; /* Minimum number of bytes */ 798 unsigned char *dot_ptr, /* Pointer to print data */ 799 *ptr; /* Current data */ 800 801 802 dot_min = DotBytes * DotColumns; 803 804 if (LineBuffers[row][0] != 0 || 805 memcmp(LineBuffers[row], LineBuffers[row] + 1, header->cupsWidth * DotBytes - 1)) 806 { 807 /* 808 * Skip leading space... 809 */ 810 811 i = 0; 812 dot_count = header->cupsWidth * DotBytes; 813 dot_ptr = LineBuffers[row]; 814 815 while (dot_count >= dot_min && dot_ptr[0] == 0 && 816 memcmp(dot_ptr, dot_ptr + 1, dot_min - 1) == 0) 817 { 818 i ++; 819 dot_ptr += dot_min; 820 dot_count -= dot_min; 821 } 822 823 /* 824 * Skip trailing space... 825 */ 826 827 while (dot_count >= dot_min && dot_ptr[dot_count - dot_min] == 0 && 828 memcmp(dot_ptr + dot_count - dot_min, 829 dot_ptr + dot_count - dot_min + 1, dot_min - 1) == 0) 830 dot_count -= dot_min; 831 832 /* 833 * Position print head for printing... 834 */ 835 836 if (i == 0) 837 putchar('\r'); 838 else 839 { 840 putchar(0x1b); 841 putchar('$'); 842 putchar((int)(i & 255)); 843 putchar((int)(i >> 8)); 844 } 845 846 /* 847 * Start bitmap graphics for this line... 848 */ 849 850 printf("\033*"); /* Select bit image */ 851 switch (header->HWResolution[0]) 852 { 853 case 60 : /* 60x60/72 DPI gfx */ 854 putchar(0); 855 break; 856 case 120 : /* 120x60/72 DPI gfx */ 857 putchar(1); 858 break; 859 case 180 : /* 180 DPI gfx */ 860 putchar(39); 861 break; 862 case 240 : /* 240x72 DPI gfx */ 863 putchar(3); 864 break; 865 case 360 : /* 360x180/360 DPI gfx */ 866 if (header->HWResolution[1] == 180) 867 { 868 if (Shingling && LineCount != 0) 869 putchar(40); /* 360x180 fast */ 870 else 871 putchar(41); /* 360x180 slow */ 872 } 873 else 874 { 875 if (Shingling && LineCount != 0) 876 putchar(72); /* 360x360 fast */ 877 else 878 putchar(73); /* 360x360 slow */ 879 } 880 break; 881 } 882 883 n = dot_count / DotBytes; 884 putchar((int)(n & 255)); 885 putchar((int)(n / 256)); 886 887 /* 888 * Write the graphics data... 889 */ 890 891 if (header->HWResolution[0] == 120 || 892 header->HWResolution[0] == 240) 893 { 894 /* 895 * Need to interleave the dots to avoid hosing the print head... 896 */ 897 898 for (n = dot_count / 2, ptr = dot_ptr; n > 0; n --, ptr += 2) 899 { 900 putchar(*ptr); 901 putchar(0); 902 } 903 904 if (dot_count & 1) 905 putchar(*ptr); 906 907 /* 908 * Move the head back and print the odd bytes... 909 */ 910 911 if (i == 0) 912 putchar('\r'); 913 else 914 { 915 putchar(0x1b); 916 putchar('$'); 917 putchar((int)(i & 255)); 918 putchar((int)(i >> 8)); 919 } 920 921 if (header->HWResolution[0] == 120) 922 printf("\033*\001"); /* Select bit image */ 923 else 924 printf("\033*\003"); /* Select bit image */ 925 926 n = (unsigned)dot_count / DotBytes; 927 putchar((int)(n & 255)); 928 putchar((int)(n / 256)); 929 930 for (n = dot_count / 2, ptr = dot_ptr + 1; n > 0; n --, ptr += 2) 931 { 932 putchar(0); 933 putchar(*ptr); 934 } 935 936 if (dot_count & 1) 937 putchar(0); 938 } 939 else 940 pwrite(dot_ptr, dot_count); 941 } 942 943 /* 944 * Feed the paper... 945 */ 946 947 putchar('\n'); 948 949 if (Shingling && row == 1) 950 { 951 if (header->HWResolution[1] == 360) 952 printf("\n\n\n\n"); 953 else 954 printf("\n"); 955 } 956 957 fflush(stdout); 958 959 /* 960 * Clear the buffer... 961 */ 962 963 memset(LineBuffers[row], 0, header->cupsWidth * DotBytes); 964 } 965 966 967 /* 968 * 'main()' - Main entry and processing of driver. 969 */ 970 971 int /* O - Exit status */ 972 main(int argc, /* I - Number of command-line arguments */ 973 char *argv[]) /* I - Command-line arguments */ 974 { 975 int fd; /* File descriptor */ 976 cups_raster_t *ras; /* Raster stream for printing */ 977 cups_page_header2_t header; /* Page header from file */ 978 ppd_file_t *ppd; /* PPD file */ 979 int page; /* Current page */ 980 unsigned y; /* Current line */ 981 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) 982 struct sigaction action; /* Actions for POSIX signals */ 983 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */ 984 985 986 /* 987 * Make sure status messages are not buffered... 988 */ 989 990 setbuf(stderr, NULL); 991 992 /* 993 * Check command-line... 994 */ 995 996 if (argc < 6 || argc > 7) 997 { 998 /* 999 * We don't have the correct number of arguments; write an error message 1000 * and return. 1001 */ 1002 1003 _cupsLangPrintFilter(stderr, "ERROR", 1004 _("%s job-id user title copies options [file]"), 1005 "rastertoepson"); 1006 return (1); 1007 } 1008 1009 /* 1010 * Open the page stream... 1011 */ 1012 1013 if (argc == 7) 1014 { 1015 if ((fd = open(argv[6], O_RDONLY)) == -1) 1016 { 1017 _cupsLangPrintError("ERROR", _("Unable to open raster file")); 1018 sleep(1); 1019 return (1); 1020 } 1021 } 1022 else 1023 fd = 0; 1024 1025 ras = cupsRasterOpen(fd, CUPS_RASTER_READ); 1026 1027 /* 1028 * Register a signal handler to eject the current page if the 1029 * job is cancelled. 1030 */ 1031 1032 Canceled = 0; 1033 1034 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ 1035 sigset(SIGTERM, CancelJob); 1036 #elif defined(HAVE_SIGACTION) 1037 memset(&action, 0, sizeof(action)); 1038 1039 sigemptyset(&action.sa_mask); 1040 action.sa_handler = CancelJob; 1041 sigaction(SIGTERM, &action, NULL); 1042 #else 1043 signal(SIGTERM, CancelJob); 1044 #endif /* HAVE_SIGSET */ 1045 1046 /* 1047 * Initialize the print device... 1048 */ 1049 1050 ppd = ppdOpenFile(getenv("PPD")); 1051 if (!ppd) 1052 { 1053 ppd_status_t status; /* PPD error */ 1054 int linenum; /* Line number */ 1055 1056 _cupsLangPrintFilter(stderr, "ERROR", 1057 _("The PPD file could not be opened.")); 1058 1059 status = ppdLastError(&linenum); 1060 1061 fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum); 1062 1063 return (1); 1064 } 1065 1066 Model = ppd->model_number; 1067 1068 Setup(); 1069 1070 /* 1071 * Process pages as needed... 1072 */ 1073 1074 page = 0; 1075 1076 while (cupsRasterReadHeader2(ras, &header)) 1077 { 1078 /* 1079 * Write a status message with the page number and number of copies. 1080 */ 1081 1082 if (Canceled) 1083 break; 1084 1085 page ++; 1086 1087 fprintf(stderr, "PAGE: %d %d\n", page, header.NumCopies); 1088 _cupsLangPrintFilter(stderr, "INFO", _("Starting page %d."), page); 1089 1090 /* 1091 * Start the page... 1092 */ 1093 1094 StartPage(ppd, &header); 1095 1096 /* 1097 * Loop for each line on the page... 1098 */ 1099 1100 for (y = 0; y < header.cupsHeight; y ++) 1101 { 1102 /* 1103 * Let the user know how far we have progressed... 1104 */ 1105 1106 if (Canceled) 1107 break; 1108 1109 if ((y & 127) == 0) 1110 { 1111 _cupsLangPrintFilter(stderr, "INFO", 1112 _("Printing page %d, %u%% complete."), 1113 page, 100 * y / header.cupsHeight); 1114 fprintf(stderr, "ATTR: job-media-progress=%u\n", 1115 100 * y / header.cupsHeight); 1116 } 1117 1118 /* 1119 * Read a line of graphics... 1120 */ 1121 1122 if (cupsRasterReadPixels(ras, Planes[0], header.cupsBytesPerLine) < 1) 1123 break; 1124 1125 /* 1126 * Write it to the printer... 1127 */ 1128 1129 OutputLine(&header); 1130 } 1131 1132 /* 1133 * Eject the page... 1134 */ 1135 1136 _cupsLangPrintFilter(stderr, "INFO", _("Finished page %d."), page); 1137 1138 EndPage(&header); 1139 1140 if (Canceled) 1141 break; 1142 } 1143 1144 /* 1145 * Shutdown the printer... 1146 */ 1147 1148 Shutdown(); 1149 1150 ppdClose(ppd); 1151 1152 /* 1153 * Close the raster stream... 1154 */ 1155 1156 cupsRasterClose(ras); 1157 if (fd != 0) 1158 close(fd); 1159 1160 /* 1161 * If no pages were printed, send an error message... 1162 */ 1163 1164 if (page == 0) 1165 { 1166 _cupsLangPrintFilter(stderr, "ERROR", _("No pages were found.")); 1167 return (1); 1168 } 1169 else 1170 return (0); 1171 } 1172