1/* 2 * "$Id: rastertohp.c 11093 2013-07-03 20:48:42Z msweet $" 3 * 4 * Hewlett-Packard Page Control Language filter for CUPS. 5 * 6 * Copyright 2007-2012 by Apple Inc. 7 * Copyright 1993-2007 by Easy Software Products. 8 * 9 * These coded instructions, statements, and computer programs are the 10 * property of Apple Inc. and are protected by Federal copyright 11 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 12 * which should have been included with this file. If this file is 13 * file is missing or damaged, see the license at "http://www.cups.org/". 14 * 15 * This file is subject to the Apple OS-Developed Software exception. 16 * 17 * Contents: 18 * 19 * Setup() - Prepare the printer for printing. 20 * StartPage() - Start a page of graphics. 21 * EndPage() - Finish a page of graphics. 22 * Shutdown() - Shutdown the printer. 23 * CancelJob() - Cancel the current job... 24 * CompressData() - Compress a line of graphics. 25 * OutputLine() - Output a line of graphics. 26 * main() - Main entry and processing of driver. 27 */ 28 29/* 30 * Include necessary headers... 31 */ 32 33#include <cups/cups.h> 34#include <cups/ppd.h> 35#include <cups/string-private.h> 36#include <cups/language-private.h> 37#include <cups/raster.h> 38#include <unistd.h> 39#include <fcntl.h> 40#include <signal.h> 41 42 43/* 44 * Globals... 45 */ 46 47unsigned char *Planes[4], /* Output buffers */ 48 *CompBuffer, /* Compression buffer */ 49 *BitBuffer; /* Buffer for output bits */ 50int NumPlanes, /* Number of color planes */ 51 ColorBits, /* Number of bits per color */ 52 Feed, /* Number of lines to skip */ 53 Duplex, /* Current duplex mode */ 54 Page, /* Current page number */ 55 Canceled; /* Has the current job been canceled? */ 56 57 58/* 59 * Prototypes... 60 */ 61 62void Setup(void); 63void StartPage(ppd_file_t *ppd, cups_page_header2_t *header); 64void EndPage(void); 65void Shutdown(void); 66 67void CancelJob(int sig); 68void CompressData(unsigned char *line, int length, int plane, int type); 69void OutputLine(cups_page_header2_t *header); 70 71 72/* 73 * 'Setup()' - Prepare the printer for printing. 74 */ 75 76void 77Setup(void) 78{ 79 /* 80 * Send a PCL reset sequence. 81 */ 82 83 putchar(0x1b); 84 putchar('E'); 85} 86 87 88/* 89 * 'StartPage()' - Start a page of graphics. 90 */ 91 92void 93StartPage(ppd_file_t *ppd, /* I - PPD file */ 94 cups_page_header2_t *header) /* I - Page header */ 95{ 96 int plane; /* Looping var */ 97 98 99 /* 100 * Show page device dictionary... 101 */ 102 103 fprintf(stderr, "DEBUG: StartPage...\n"); 104 fprintf(stderr, "DEBUG: MediaClass = \"%s\"\n", header->MediaClass); 105 fprintf(stderr, "DEBUG: MediaColor = \"%s\"\n", header->MediaColor); 106 fprintf(stderr, "DEBUG: MediaType = \"%s\"\n", header->MediaType); 107 fprintf(stderr, "DEBUG: OutputType = \"%s\"\n", header->OutputType); 108 109 fprintf(stderr, "DEBUG: AdvanceDistance = %d\n", header->AdvanceDistance); 110 fprintf(stderr, "DEBUG: AdvanceMedia = %d\n", header->AdvanceMedia); 111 fprintf(stderr, "DEBUG: Collate = %d\n", header->Collate); 112 fprintf(stderr, "DEBUG: CutMedia = %d\n", header->CutMedia); 113 fprintf(stderr, "DEBUG: Duplex = %d\n", header->Duplex); 114 fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0], 115 header->HWResolution[1]); 116 fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n", 117 header->ImagingBoundingBox[0], header->ImagingBoundingBox[1], 118 header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]); 119 fprintf(stderr, "DEBUG: InsertSheet = %d\n", header->InsertSheet); 120 fprintf(stderr, "DEBUG: Jog = %d\n", header->Jog); 121 fprintf(stderr, "DEBUG: LeadingEdge = %d\n", header->LeadingEdge); 122 fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0], 123 header->Margins[1]); 124 fprintf(stderr, "DEBUG: ManualFeed = %d\n", header->ManualFeed); 125 fprintf(stderr, "DEBUG: MediaPosition = %d\n", header->MediaPosition); 126 fprintf(stderr, "DEBUG: MediaWeight = %d\n", header->MediaWeight); 127 fprintf(stderr, "DEBUG: MirrorPrint = %d\n", header->MirrorPrint); 128 fprintf(stderr, "DEBUG: NegativePrint = %d\n", header->NegativePrint); 129 fprintf(stderr, "DEBUG: NumCopies = %d\n", header->NumCopies); 130 fprintf(stderr, "DEBUG: Orientation = %d\n", header->Orientation); 131 fprintf(stderr, "DEBUG: OutputFaceUp = %d\n", header->OutputFaceUp); 132 fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0], 133 header->PageSize[1]); 134 fprintf(stderr, "DEBUG: Separations = %d\n", header->Separations); 135 fprintf(stderr, "DEBUG: TraySwitch = %d\n", header->TraySwitch); 136 fprintf(stderr, "DEBUG: Tumble = %d\n", header->Tumble); 137 fprintf(stderr, "DEBUG: cupsWidth = %d\n", header->cupsWidth); 138 fprintf(stderr, "DEBUG: cupsHeight = %d\n", header->cupsHeight); 139 fprintf(stderr, "DEBUG: cupsMediaType = %d\n", header->cupsMediaType); 140 fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header->cupsBitsPerColor); 141 fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header->cupsBitsPerPixel); 142 fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header->cupsBytesPerLine); 143 fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header->cupsColorOrder); 144 fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace); 145 fprintf(stderr, "DEBUG: cupsCompression = %d\n", header->cupsCompression); 146 147 /* 148 * Setup printer/job attributes... 149 */ 150 151 Duplex = header->Duplex; 152 ColorBits = header->cupsBitsPerColor; 153 154 if ((!Duplex || (Page & 1)) && header->MediaPosition) 155 printf("\033&l%dH", /* Set media position */ 156 header->MediaPosition); 157 158 if (Duplex && ppd && ppd->model_number == 2) 159 { 160 /* 161 * Handle duplexing on new DeskJet printers... 162 */ 163 164 printf("\033&l-2H"); /* Load media */ 165 166 if (Page & 1) 167 printf("\033&l2S"); /* Set duplex mode */ 168 } 169 170 if (!Duplex || (Page & 1) || (ppd && ppd->model_number == 2)) 171 { 172 /* 173 * Set the media size... 174 */ 175 176 printf("\033&l6D\033&k12H"); /* Set 6 LPI, 10 CPI */ 177 printf("\033&l0O"); /* Set portrait orientation */ 178 179 switch (header->PageSize[1]) 180 { 181 case 540 : /* Monarch Envelope */ 182 printf("\033&l80A"); /* Set page size */ 183 break; 184 185 case 595 : /* A5 */ 186 printf("\033&l25A"); /* Set page size */ 187 break; 188 189 case 624 : /* DL Envelope */ 190 printf("\033&l90A"); /* Set page size */ 191 break; 192 193 case 649 : /* C5 Envelope */ 194 printf("\033&l91A"); /* Set page size */ 195 break; 196 197 case 684 : /* COM-10 Envelope */ 198 printf("\033&l81A"); /* Set page size */ 199 break; 200 201 case 709 : /* B5 Envelope */ 202 printf("\033&l100A"); /* Set page size */ 203 break; 204 205 case 756 : /* Executive */ 206 printf("\033&l1A"); /* Set page size */ 207 break; 208 209 case 792 : /* Letter */ 210 printf("\033&l2A"); /* Set page size */ 211 break; 212 213 case 842 : /* A4 */ 214 printf("\033&l26A"); /* Set page size */ 215 break; 216 217 case 1008 : /* Legal */ 218 printf("\033&l3A"); /* Set page size */ 219 break; 220 221 case 1191 : /* A3 */ 222 printf("\033&l27A"); /* Set page size */ 223 break; 224 225 case 1224 : /* Tabloid */ 226 printf("\033&l6A"); /* Set page size */ 227 break; 228 } 229 230 printf("\033&l%dP", /* Set page length */ 231 header->PageSize[1] / 12); 232 printf("\033&l0E"); /* Set top margin to 0 */ 233 } 234 235 if (!Duplex || (Page & 1)) 236 { 237 /* 238 * Set other job options... 239 */ 240 241 printf("\033&l%dX", header->NumCopies); /* Set number copies */ 242 243 if (header->cupsMediaType && 244 (!ppd || ppd->model_number != 2 || header->HWResolution[0] == 600)) 245 printf("\033&l%dM", /* Set media type */ 246 header->cupsMediaType); 247 248 if (!ppd || ppd->model_number != 2) 249 { 250 int mode = Duplex ? 1 + header->Tumble != 0 : 0; 251 252 printf("\033&l%dS", mode); /* Set duplex mode */ 253 printf("\033&l0L"); /* Turn off perforation skip */ 254 } 255 } 256 else if (!ppd || ppd->model_number != 2) 257 printf("\033&a2G"); /* Set back side */ 258 259 /* 260 * Set graphics mode... 261 */ 262 263 if (ppd && ppd->model_number == 2) 264 { 265 /* 266 * Figure out the number of color planes... 267 */ 268 269 if (header->cupsColorSpace == CUPS_CSPACE_KCMY) 270 NumPlanes = 4; 271 else 272 NumPlanes = 1; 273 274 /* 275 * Set the resolution and top-of-form... 276 */ 277 278 printf("\033&u%dD", header->HWResolution[0]); 279 /* Resolution */ 280 printf("\033&l0e0L"); /* Reset top and don't skip */ 281 printf("\033*p0Y\033*p0X"); /* Set top of form */ 282 283 /* 284 * Send 26-byte configure image data command with horizontal and 285 * vertical resolutions as well as a color count... 286 */ 287 288 printf("\033*g26W"); 289 putchar(2); /* Format 2 */ 290 putchar(NumPlanes); /* Output planes */ 291 292 putchar(header->HWResolution[0] >> 8); /* Black resolution */ 293 putchar(header->HWResolution[0]); 294 putchar(header->HWResolution[1] >> 8); 295 putchar(header->HWResolution[1]); 296 putchar(0); 297 putchar(1 << ColorBits); /* # of black levels */ 298 299 putchar(header->HWResolution[0] >> 8); /* Cyan resolution */ 300 putchar(header->HWResolution[0]); 301 putchar(header->HWResolution[1] >> 8); 302 putchar(header->HWResolution[1]); 303 putchar(0); 304 putchar(1 << ColorBits); /* # of cyan levels */ 305 306 putchar(header->HWResolution[0] >> 8); /* Magenta resolution */ 307 putchar(header->HWResolution[0]); 308 putchar(header->HWResolution[1] >> 8); 309 putchar(header->HWResolution[1]); 310 putchar(0); 311 putchar(1 << ColorBits); /* # of magenta levels */ 312 313 putchar(header->HWResolution[0] >> 8); /* Yellow resolution */ 314 putchar(header->HWResolution[0]); 315 putchar(header->HWResolution[1] >> 8); 316 putchar(header->HWResolution[1]); 317 putchar(0); 318 putchar(1 << ColorBits); /* # of yellow levels */ 319 320 printf("\033&l0H"); /* Set media position */ 321 } 322 else 323 { 324 printf("\033*t%dR", header->HWResolution[0]); 325 /* Set resolution */ 326 327 if (header->cupsColorSpace == CUPS_CSPACE_KCMY) 328 { 329 NumPlanes = 4; 330 printf("\033*r-4U"); /* Set KCMY graphics */ 331 } 332 else if (header->cupsColorSpace == CUPS_CSPACE_CMY) 333 { 334 NumPlanes = 3; 335 printf("\033*r-3U"); /* Set CMY graphics */ 336 } 337 else 338 NumPlanes = 1; /* Black&white graphics */ 339 340 /* 341 * Set size and position of graphics... 342 */ 343 344 printf("\033*r%dS", header->cupsWidth); /* Set width */ 345 printf("\033*r%dT", header->cupsHeight); /* Set height */ 346 347 printf("\033&a0H"); /* Set horizontal position */ 348 349 if (ppd) 350 printf("\033&a%.0fV", /* Set vertical position */ 351 10.0 * (ppd->sizes[0].length - ppd->sizes[0].top)); 352 else 353 printf("\033&a0V"); /* Set top-of-page */ 354 } 355 356 printf("\033*r1A"); /* Start graphics */ 357 358 if (header->cupsCompression) 359 printf("\033*b%dM", /* Set compression */ 360 header->cupsCompression); 361 362 Feed = 0; /* No blank lines yet */ 363 364 /* 365 * Allocate memory for a line of graphics... 366 */ 367 368 if ((Planes[0] = malloc(header->cupsBytesPerLine)) == NULL) 369 { 370 fputs("ERROR: Unable to allocate memory\n", stderr); 371 exit(1); 372 } 373 374 for (plane = 1; plane < NumPlanes; plane ++) 375 Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes; 376 377 if (ColorBits > 1) 378 BitBuffer = malloc(ColorBits * ((header->cupsWidth + 7) / 8)); 379 else 380 BitBuffer = NULL; 381 382 if (header->cupsCompression) 383 CompBuffer = malloc(header->cupsBytesPerLine * 2); 384 else 385 CompBuffer = NULL; 386} 387 388 389/* 390 * 'EndPage()' - Finish a page of graphics. 391 */ 392 393void 394EndPage(void) 395{ 396 /* 397 * Eject the current page... 398 */ 399 400 if (NumPlanes > 1) 401 { 402 printf("\033*rC"); /* End color GFX */ 403 404 if (!(Duplex && (Page & 1))) 405 printf("\033&l0H"); /* Eject current page */ 406 } 407 else 408 { 409 printf("\033*r0B"); /* End GFX */ 410 411 if (!(Duplex && (Page & 1))) 412 printf("\014"); /* Eject current page */ 413 } 414 415 fflush(stdout); 416 417 /* 418 * Free memory... 419 */ 420 421 free(Planes[0]); 422 423 if (BitBuffer) 424 free(BitBuffer); 425 426 if (CompBuffer) 427 free(CompBuffer); 428} 429 430 431/* 432 * 'Shutdown()' - Shutdown the printer. 433 */ 434 435void 436Shutdown(void) 437{ 438 /* 439 * Send a PCL reset sequence. 440 */ 441 442 putchar(0x1b); 443 putchar('E'); 444} 445 446 447/* 448 * 'CancelJob()' - Cancel the current job... 449 */ 450 451void 452CancelJob(int sig) /* I - Signal */ 453{ 454 (void)sig; 455 456 Canceled = 1; 457} 458 459 460/* 461 * 'CompressData()' - Compress a line of graphics. 462 */ 463 464void 465CompressData(unsigned char *line, /* I - Data to compress */ 466 int length, /* I - Number of bytes */ 467 int plane, /* I - Color plane */ 468 int type) /* I - Type of compression */ 469{ 470 unsigned char *line_ptr, /* Current byte pointer */ 471 *line_end, /* End-of-line byte pointer */ 472 *comp_ptr, /* Pointer into compression buffer */ 473 *start; /* Start of compression sequence */ 474 int count; /* Count of bytes for output */ 475 476 477 switch (type) 478 { 479 default : 480 /* 481 * Do no compression... 482 */ 483 484 line_ptr = line; 485 line_end = line + length; 486 break; 487 488 case 1 : 489 /* 490 * Do run-length encoding... 491 */ 492 493 line_end = line + length; 494 for (line_ptr = line, comp_ptr = CompBuffer; 495 line_ptr < line_end; 496 comp_ptr += 2, line_ptr += count) 497 { 498 for (count = 1; 499 (line_ptr + count) < line_end && 500 line_ptr[0] == line_ptr[count] && 501 count < 256; 502 count ++); 503 504 comp_ptr[0] = count - 1; 505 comp_ptr[1] = line_ptr[0]; 506 } 507 508 line_ptr = CompBuffer; 509 line_end = comp_ptr; 510 break; 511 512 case 2 : 513 /* 514 * Do TIFF pack-bits encoding... 515 */ 516 517 line_ptr = line; 518 line_end = line + length; 519 comp_ptr = CompBuffer; 520 521 while (line_ptr < line_end) 522 { 523 if ((line_ptr + 1) >= line_end) 524 { 525 /* 526 * Single byte on the end... 527 */ 528 529 *comp_ptr++ = 0x00; 530 *comp_ptr++ = *line_ptr++; 531 } 532 else if (line_ptr[0] == line_ptr[1]) 533 { 534 /* 535 * Repeated sequence... 536 */ 537 538 line_ptr ++; 539 count = 2; 540 541 while (line_ptr < (line_end - 1) && 542 line_ptr[0] == line_ptr[1] && 543 count < 127) 544 { 545 line_ptr ++; 546 count ++; 547 } 548 549 *comp_ptr++ = 257 - count; 550 *comp_ptr++ = *line_ptr++; 551 } 552 else 553 { 554 /* 555 * Non-repeated sequence... 556 */ 557 558 start = line_ptr; 559 line_ptr ++; 560 count = 1; 561 562 while (line_ptr < (line_end - 1) && 563 line_ptr[0] != line_ptr[1] && 564 count < 127) 565 { 566 line_ptr ++; 567 count ++; 568 } 569 570 *comp_ptr++ = count - 1; 571 572 memcpy(comp_ptr, start, count); 573 comp_ptr += count; 574 } 575 } 576 577 line_ptr = CompBuffer; 578 line_end = comp_ptr; 579 break; 580 } 581 582 /* 583 * Set the length of the data and write a raster plane... 584 */ 585 586 printf("\033*b%d%c", (int)(line_end - line_ptr), plane); 587 fwrite(line_ptr, line_end - line_ptr, 1, stdout); 588} 589 590 591/* 592 * 'OutputLine()' - Output a line of graphics. 593 */ 594 595void 596OutputLine(cups_page_header2_t *header) /* I - Page header */ 597{ 598 int plane, /* Current plane */ 599 bytes, /* Bytes to write */ 600 count; /* Bytes to convert */ 601 unsigned char bit, /* Current plane data */ 602 bit0, /* Current low bit data */ 603 bit1, /* Current high bit data */ 604 *plane_ptr, /* Pointer into Planes */ 605 *bit_ptr; /* Pointer into BitBuffer */ 606 607 608 /* 609 * Output whitespace as needed... 610 */ 611 612 if (Feed > 0) 613 { 614 printf("\033*b%dY", Feed); 615 Feed = 0; 616 } 617 618 /* 619 * Write bitmap data as needed... 620 */ 621 622 bytes = (header->cupsWidth + 7) / 8; 623 624 for (plane = 0; plane < NumPlanes; plane ++) 625 if (ColorBits == 1) 626 { 627 /* 628 * Send bits as-is... 629 */ 630 631 CompressData(Planes[plane], bytes, plane < (NumPlanes - 1) ? 'V' : 'W', 632 header->cupsCompression); 633 } 634 else 635 { 636 /* 637 * Separate low and high bit data into separate buffers. 638 */ 639 640 for (count = header->cupsBytesPerLine / NumPlanes, 641 plane_ptr = Planes[plane], bit_ptr = BitBuffer; 642 count > 0; 643 count -= 2, plane_ptr += 2, bit_ptr ++) 644 { 645 bit = plane_ptr[0]; 646 647 bit0 = ((bit & 64) << 1) | ((bit & 16) << 2) | ((bit & 4) << 3) | ((bit & 1) << 4); 648 bit1 = (bit & 128) | ((bit & 32) << 1) | ((bit & 8) << 2) | ((bit & 2) << 3); 649 650 if (count > 1) 651 { 652 bit = plane_ptr[1]; 653 654 bit0 |= (bit & 1) | ((bit & 4) >> 1) | ((bit & 16) >> 2) | ((bit & 64) >> 3); 655 bit1 |= ((bit & 2) >> 1) | ((bit & 8) >> 2) | ((bit & 32) >> 3) | ((bit & 128) >> 4); 656 } 657 658 bit_ptr[0] = bit0; 659 bit_ptr[bytes] = bit1; 660 } 661 662 /* 663 * Send low and high bits... 664 */ 665 666 CompressData(BitBuffer, bytes, 'V', header->cupsCompression); 667 CompressData(BitBuffer + bytes, bytes, plane < (NumPlanes - 1) ? 'V' : 'W', 668 header->cupsCompression); 669 } 670 671 fflush(stdout); 672} 673 674 675/* 676 * 'main()' - Main entry and processing of driver. 677 */ 678 679int /* O - Exit status */ 680main(int argc, /* I - Number of command-line arguments */ 681 char *argv[]) /* I - Command-line arguments */ 682{ 683 int fd; /* File descriptor */ 684 cups_raster_t *ras; /* Raster stream for printing */ 685 cups_page_header2_t header; /* Page header from file */ 686 int y; /* Current line */ 687 ppd_file_t *ppd; /* PPD file */ 688#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET) 689 struct sigaction action; /* Actions for POSIX signals */ 690#endif /* HAVE_SIGACTION && !HAVE_SIGSET */ 691 692 693 /* 694 * Make sure status messages are not buffered... 695 */ 696 697 setbuf(stderr, NULL); 698 699 /* 700 * Check command-line... 701 */ 702 703 if (argc < 6 || argc > 7) 704 { 705 /* 706 * We don't have the correct number of arguments; write an error message 707 * and return. 708 */ 709 710 _cupsLangPrintFilter(stderr, "ERROR", 711 _("%s job-id user title copies options [file]"), 712 "rastertohp"); 713 return (1); 714 } 715 716 /* 717 * Open the page stream... 718 */ 719 720 if (argc == 7) 721 { 722 if ((fd = open(argv[6], O_RDONLY)) == -1) 723 { 724 _cupsLangPrintError("ERROR", _("Unable to open raster file")); 725 sleep(1); 726 return (1); 727 } 728 } 729 else 730 fd = 0; 731 732 ras = cupsRasterOpen(fd, CUPS_RASTER_READ); 733 734 /* 735 * Register a signal handler to eject the current page if the 736 * job is cancelled. 737 */ 738 739 Canceled = 0; 740 741#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */ 742 sigset(SIGTERM, CancelJob); 743#elif defined(HAVE_SIGACTION) 744 memset(&action, 0, sizeof(action)); 745 746 sigemptyset(&action.sa_mask); 747 action.sa_handler = CancelJob; 748 sigaction(SIGTERM, &action, NULL); 749#else 750 signal(SIGTERM, CancelJob); 751#endif /* HAVE_SIGSET */ 752 753 /* 754 * Initialize the print device... 755 */ 756 757 ppd = ppdOpenFile(getenv("PPD")); 758 if (!ppd) 759 { 760 ppd_status_t status; /* PPD error */ 761 int linenum; /* Line number */ 762 763 _cupsLangPrintFilter(stderr, "ERROR", 764 _("The PPD file could not be opened.")); 765 766 status = ppdLastError(&linenum); 767 768 fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum); 769 770 return (1); 771 } 772 773 Setup(); 774 775 /* 776 * Process pages as needed... 777 */ 778 779 Page = 0; 780 781 while (cupsRasterReadHeader2(ras, &header)) 782 { 783 /* 784 * Write a status message with the page number and number of copies. 785 */ 786 787 if (Canceled) 788 break; 789 790 Page ++; 791 792 fprintf(stderr, "PAGE: %d %d\n", Page, header.NumCopies); 793 _cupsLangPrintFilter(stderr, "INFO", _("Starting page %d."), Page); 794 795 /* 796 * Start the page... 797 */ 798 799 StartPage(ppd, &header); 800 801 /* 802 * Loop for each line on the page... 803 */ 804 805 for (y = 0; y < header.cupsHeight; y ++) 806 { 807 /* 808 * Let the user know how far we have progressed... 809 */ 810 811 if (Canceled) 812 break; 813 814 if ((y & 127) == 0) 815 { 816 _cupsLangPrintFilter(stderr, "INFO", 817 _("Printing page %d, %d%% complete."), 818 Page, 100 * y / header.cupsHeight); 819 fprintf(stderr, "ATTR: job-media-progress=%d\n", 820 100 * y / header.cupsHeight); 821 } 822 823 /* 824 * Read a line of graphics... 825 */ 826 827 if (cupsRasterReadPixels(ras, Planes[0], header.cupsBytesPerLine) < 1) 828 break; 829 830 /* 831 * See if the line is blank; if not, write it to the printer... 832 */ 833 834 if (Planes[0][0] || 835 memcmp(Planes[0], Planes[0] + 1, header.cupsBytesPerLine - 1)) 836 OutputLine(&header); 837 else 838 Feed ++; 839 } 840 841 /* 842 * Eject the page... 843 */ 844 845 _cupsLangPrintFilter(stderr, "INFO", _("Finished page %d."), Page); 846 847 EndPage(); 848 849 if (Canceled) 850 break; 851 } 852 853 /* 854 * Shutdown the printer... 855 */ 856 857 Shutdown(); 858 859 if (ppd) 860 ppdClose(ppd); 861 862 /* 863 * Close the raster stream... 864 */ 865 866 cupsRasterClose(ras); 867 if (fd != 0) 868 close(fd); 869 870 /* 871 * If no pages were printed, send an error message... 872 */ 873 874 if (Page == 0) 875 { 876 _cupsLangPrintFilter(stderr, "ERROR", _("No pages were found.")); 877 return (1); 878 } 879 else 880 return (0); 881} 882 883 884/* 885 * End of "$Id: rastertohp.c 11093 2013-07-03 20:48:42Z msweet $". 886 */ 887