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