]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/rastertohp.c
Merge changes from CUPS 1.4svn-r8443.
[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 *
91c84a35 7 * Copyright 2007-2008 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 {
252 if (header->Duplex)
253 printf("\033&l%dS", /* Set duplex mode */
254 header->Duplex + header->Tumble);
255
256 printf("\033&l0L"); /* Turn off perforation skip */
257 }
258 }
259 else if (!ppd || ppd->model_number != 2)
260 printf("\033&a2G"); /* Set back side */
261
262 /*
263 * Set graphics mode...
264 */
265
91c84a35 266 if (ppd && ppd->model_number == 2)
ef416fc2 267 {
268 /*
269 * Figure out the number of color planes...
270 */
271
272 if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
273 NumPlanes = 4;
274 else
275 NumPlanes = 1;
276
277 /*
278 * Set the resolution and top-of-form...
279 */
280
281 printf("\033&u%dD", header->HWResolution[0]);
282 /* Resolution */
283 printf("\033&l0e0L"); /* Reset top and don't skip */
284 printf("\033*p0Y\033*p0X"); /* Set top of form */
285
286 /*
287 * Send 26-byte configure image data command with horizontal and
288 * vertical resolutions as well as a color count...
289 */
290
291 printf("\033*g26W");
292 putchar(2); /* Format 2 */
293 putchar(NumPlanes); /* Output planes */
294
295 putchar(header->HWResolution[0] >> 8); /* Black resolution */
296 putchar(header->HWResolution[0]);
297 putchar(header->HWResolution[1] >> 8);
298 putchar(header->HWResolution[1]);
299 putchar(0);
300 putchar(1 << ColorBits); /* # of black levels */
301
302 putchar(header->HWResolution[0] >> 8); /* Cyan resolution */
303 putchar(header->HWResolution[0]);
304 putchar(header->HWResolution[1] >> 8);
305 putchar(header->HWResolution[1]);
306 putchar(0);
307 putchar(1 << ColorBits); /* # of cyan levels */
308
309 putchar(header->HWResolution[0] >> 8); /* Magenta resolution */
310 putchar(header->HWResolution[0]);
311 putchar(header->HWResolution[1] >> 8);
312 putchar(header->HWResolution[1]);
313 putchar(0);
314 putchar(1 << ColorBits); /* # of magenta levels */
315
316 putchar(header->HWResolution[0] >> 8); /* Yellow resolution */
317 putchar(header->HWResolution[0]);
318 putchar(header->HWResolution[1] >> 8);
319 putchar(header->HWResolution[1]);
320 putchar(0);
321 putchar(1 << ColorBits); /* # of yellow levels */
322
323 printf("\033&l0H"); /* Set media position */
324 }
325 else
326 {
327 printf("\033*t%dR", header->HWResolution[0]);
328 /* Set resolution */
329
330 if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
331 {
332 NumPlanes = 4;
333 printf("\033*r-4U"); /* Set KCMY graphics */
334 }
335 else if (header->cupsColorSpace == CUPS_CSPACE_CMY)
336 {
337 NumPlanes = 3;
338 printf("\033*r-3U"); /* Set CMY graphics */
339 }
340 else
341 NumPlanes = 1; /* Black&white graphics */
342
343 /*
344 * Set size and position of graphics...
345 */
346
347 printf("\033*r%dS", header->cupsWidth); /* Set width */
348 printf("\033*r%dT", header->cupsHeight); /* Set height */
349
350 printf("\033&a0H"); /* Set horizontal position */
351
352 if (ppd)
353 printf("\033&a%.0fV", /* Set vertical position */
354 10.0 * (ppd->sizes[0].length - ppd->sizes[0].top));
355 else
356 printf("\033&a0V"); /* Set top-of-page */
357 }
358
359 printf("\033*r1A"); /* Start graphics */
360
361 if (header->cupsCompression)
362 printf("\033*b%dM", /* Set compression */
363 header->cupsCompression);
364
365 Feed = 0; /* No blank lines yet */
366
367 /*
368 * Allocate memory for a line of graphics...
369 */
370
91c84a35
MS
371 if ((Planes[0] = malloc(header->cupsBytesPerLine)) == NULL)
372 {
373 fputs("ERROR: Unable to allocate memory!\n", stderr);
374 exit(1);
375 }
376
ef416fc2 377 for (plane = 1; plane < NumPlanes; plane ++)
378 Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes;
379
380 if (ColorBits > 1)
381 BitBuffer = malloc(ColorBits * ((header->cupsWidth + 7) / 8));
382 else
383 BitBuffer = NULL;
384
385 if (header->cupsCompression)
386 CompBuffer = malloc(header->cupsBytesPerLine * 2);
387 else
388 CompBuffer = NULL;
389}
390
391
392/*
393 * 'EndPage()' - Finish a page of graphics.
394 */
395
396void
397EndPage(void)
398{
ef416fc2 399 /*
400 * Eject the current page...
401 */
402
403 if (NumPlanes > 1)
404 {
405 printf("\033*rC"); /* End color GFX */
406
407 if (!(Duplex && (Page & 1)))
408 printf("\033&l0H"); /* Eject current page */
409 }
410 else
411 {
412 printf("\033*r0B"); /* End GFX */
413
414 if (!(Duplex && (Page & 1)))
415 printf("\014"); /* Eject current page */
416 }
417
418 fflush(stdout);
419
ef416fc2 420 /*
421 * Free memory...
422 */
423
424 free(Planes[0]);
425
426 if (BitBuffer)
427 free(BitBuffer);
428
429 if (CompBuffer)
430 free(CompBuffer);
431}
432
433
434/*
435 * 'Shutdown()' - Shutdown the printer.
436 */
437
438void
439Shutdown(void)
440{
441 /*
442 * Send a PCL reset sequence.
443 */
444
445 putchar(0x1b);
446 putchar('E');
447}
448
449
450/*
451 * 'CancelJob()' - Cancel the current job...
452 */
453
454void
455CancelJob(int sig) /* I - Signal */
456{
ef416fc2 457 (void)sig;
458
839a51c8 459 Canceled = 1;
ef416fc2 460}
461
462
463/*
464 * 'CompressData()' - Compress a line of graphics.
465 */
466
467void
468CompressData(unsigned char *line, /* I - Data to compress */
469 int length, /* I - Number of bytes */
470 int plane, /* I - Color plane */
471 int type) /* I - Type of compression */
472{
473 unsigned char *line_ptr, /* Current byte pointer */
474 *line_end, /* End-of-line byte pointer */
475 *comp_ptr, /* Pointer into compression buffer */
476 *start; /* Start of compression sequence */
477 int count; /* Count of bytes for output */
478
479
480 switch (type)
481 {
482 default :
483 /*
484 * Do no compression...
485 */
486
487 line_ptr = line;
488 line_end = line + length;
489 break;
490
491 case 1 :
492 /*
493 * Do run-length encoding...
494 */
495
496 line_end = line + length;
497 for (line_ptr = line, comp_ptr = CompBuffer;
498 line_ptr < line_end;
499 comp_ptr += 2, line_ptr += count)
500 {
501 for (count = 1;
502 (line_ptr + count) < line_end &&
503 line_ptr[0] == line_ptr[count] &&
504 count < 256;
505 count ++);
506
507 comp_ptr[0] = count - 1;
508 comp_ptr[1] = line_ptr[0];
509 }
510
511 line_ptr = CompBuffer;
512 line_end = comp_ptr;
513 break;
514
515 case 2 :
516 /*
517 * Do TIFF pack-bits encoding...
518 */
519
520 line_ptr = line;
521 line_end = line + length;
522 comp_ptr = CompBuffer;
523
524 while (line_ptr < line_end)
525 {
526 if ((line_ptr + 1) >= line_end)
527 {
528 /*
529 * Single byte on the end...
530 */
531
532 *comp_ptr++ = 0x00;
533 *comp_ptr++ = *line_ptr++;
534 }
535 else if (line_ptr[0] == line_ptr[1])
536 {
537 /*
538 * Repeated sequence...
539 */
540
541 line_ptr ++;
542 count = 2;
543
544 while (line_ptr < (line_end - 1) &&
545 line_ptr[0] == line_ptr[1] &&
546 count < 127)
547 {
548 line_ptr ++;
549 count ++;
550 }
551
552 *comp_ptr++ = 257 - count;
553 *comp_ptr++ = *line_ptr++;
554 }
555 else
556 {
557 /*
558 * Non-repeated sequence...
559 */
560
561 start = line_ptr;
562 line_ptr ++;
563 count = 1;
564
565 while (line_ptr < (line_end - 1) &&
566 line_ptr[0] != line_ptr[1] &&
567 count < 127)
568 {
569 line_ptr ++;
570 count ++;
571 }
572
573 *comp_ptr++ = count - 1;
574
575 memcpy(comp_ptr, start, count);
576 comp_ptr += count;
577 }
578 }
579
580 line_ptr = CompBuffer;
581 line_end = comp_ptr;
582 break;
583 }
584
585 /*
586 * Set the length of the data and write a raster plane...
587 */
588
589 printf("\033*b%d%c", (int)(line_end - line_ptr), plane);
590 fwrite(line_ptr, line_end - line_ptr, 1, stdout);
591}
592
593
594/*
595 * 'OutputLine()' - Output a line of graphics.
596 */
597
598void
839a51c8 599OutputLine(cups_page_header2_t *header) /* I - Page header */
ef416fc2 600{
601 int plane, /* Current plane */
602 bytes, /* Bytes to write */
603 count; /* Bytes to convert */
604 unsigned char bit, /* Current plane data */
605 bit0, /* Current low bit data */
606 bit1, /* Current high bit data */
607 *plane_ptr, /* Pointer into Planes */
608 *bit_ptr; /* Pointer into BitBuffer */
609
610
611 /*
612 * Output whitespace as needed...
613 */
614
615 if (Feed > 0)
616 {
617 printf("\033*b%dY", Feed);
618 Feed = 0;
619 }
620
621 /*
622 * Write bitmap data as needed...
623 */
624
625 bytes = (header->cupsWidth + 7) / 8;
626
627 for (plane = 0; plane < NumPlanes; plane ++)
628 if (ColorBits == 1)
629 {
630 /*
631 * Send bits as-is...
632 */
633
634 CompressData(Planes[plane], bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
635 header->cupsCompression);
636 }
637 else
638 {
639 /*
640 * Separate low and high bit data into separate buffers.
641 */
642
643 for (count = header->cupsBytesPerLine / NumPlanes,
644 plane_ptr = Planes[plane], bit_ptr = BitBuffer;
645 count > 0;
646 count -= 2, plane_ptr += 2, bit_ptr ++)
647 {
648 bit = plane_ptr[0];
649
650 bit0 = ((bit & 64) << 1) | ((bit & 16) << 2) | ((bit & 4) << 3) | ((bit & 1) << 4);
651 bit1 = (bit & 128) | ((bit & 32) << 1) | ((bit & 8) << 2) | ((bit & 2) << 3);
652
653 if (count > 1)
654 {
655 bit = plane_ptr[1];
656
657 bit0 |= (bit & 1) | ((bit & 4) >> 1) | ((bit & 16) >> 2) | ((bit & 64) >> 3);
658 bit1 |= ((bit & 2) >> 1) | ((bit & 8) >> 2) | ((bit & 32) >> 3) | ((bit & 128) >> 4);
659 }
660
661 bit_ptr[0] = bit0;
662 bit_ptr[bytes] = bit1;
663 }
664
665 /*
666 * Send low and high bits...
667 */
668
669 CompressData(BitBuffer, bytes, 'V', header->cupsCompression);
670 CompressData(BitBuffer + bytes, bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
671 header->cupsCompression);
672 }
673
674 fflush(stdout);
675}
676
677
678/*
679 * 'main()' - Main entry and processing of driver.
680 */
681
839a51c8
MS
682int /* O - Exit status */
683main(int argc, /* I - Number of command-line arguments */
684 char *argv[]) /* I - Command-line arguments */
ef416fc2 685{
839a51c8
MS
686 int fd; /* File descriptor */
687 cups_raster_t *ras; /* Raster stream for printing */
688 cups_page_header2_t header; /* Page header from file */
689 int y; /* Current line */
690 ppd_file_t *ppd; /* PPD file */
691#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
692 struct sigaction action; /* Actions for POSIX signals */
693#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
ef416fc2 694
695
696 /*
697 * Make sure status messages are not buffered...
698 */
699
700 setbuf(stderr, NULL);
701
702 /*
703 * Check command-line...
704 */
705
706 if (argc < 6 || argc > 7)
707 {
708 /*
709 * We don't have the correct number of arguments; write an error message
710 * and return.
711 */
712
f0ab5bff
MS
713 _cupsLangPrintf(stderr,
714 _("Usage: %s job-id user title copies options [file]\n"),
715 "rastertohp");
ef416fc2 716 return (1);
717 }
718
719 /*
720 * Open the page stream...
721 */
722
723 if (argc == 7)
724 {
725 if ((fd = open(argv[6], O_RDONLY)) == -1)
726 {
f0ab5bff
MS
727 _cupsLangPrintf(stderr, _("ERROR: Unable to open raster file - %s\n"),
728 strerror(errno));
ef416fc2 729 sleep(1);
730 return (1);
731 }
732 }
733 else
734 fd = 0;
735
736 ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
737
839a51c8
MS
738 /*
739 * Register a signal handler to eject the current page if the
740 * job is cancelled.
741 */
742
743 Canceled = 0;
744
745#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
746 sigset(SIGTERM, CancelJob);
747#elif defined(HAVE_SIGACTION)
748 memset(&action, 0, sizeof(action));
749
750 sigemptyset(&action.sa_mask);
751 action.sa_handler = CancelJob;
752 sigaction(SIGTERM, &action, NULL);
753#else
754 signal(SIGTERM, CancelJob);
755#endif /* HAVE_SIGSET */
756
ef416fc2 757 /*
758 * Initialize the print device...
759 */
760
761 ppd = ppdOpenFile(getenv("PPD"));
762
763 Setup();
764
765 /*
766 * Process pages as needed...
767 */
768
769 Page = 0;
770
839a51c8 771 while (cupsRasterReadHeader2(ras, &header))
ef416fc2 772 {
773 /*
774 * Write a status message with the page number and number of copies.
775 */
776
839a51c8
MS
777 if (Canceled)
778 break;
779
ef416fc2 780 Page ++;
781
782 fprintf(stderr, "PAGE: %d %d\n", Page, header.NumCopies);
783
784 /*
785 * Start the page...
786 */
787
788 StartPage(ppd, &header);
789
790 /*
791 * Loop for each line on the page...
792 */
793
794 for (y = 0; y < header.cupsHeight; y ++)
795 {
796 /*
797 * Let the user know how far we have progressed...
798 */
799
839a51c8
MS
800 if (Canceled)
801 break;
802
ef416fc2 803 if ((y & 127) == 0)
f0ab5bff
MS
804 _cupsLangPrintf(stderr, _("INFO: Printing page %d, %d%% complete...\n"),
805 Page, 100 * y / header.cupsHeight);
ef416fc2 806
807 /*
808 * Read a line of graphics...
809 */
810
811 if (cupsRasterReadPixels(ras, Planes[0], header.cupsBytesPerLine) < 1)
812 break;
813
814 /*
815 * See if the line is blank; if not, write it to the printer...
816 */
817
818 if (Planes[0][0] ||
819 memcmp(Planes[0], Planes[0] + 1, header.cupsBytesPerLine - 1))
820 OutputLine(&header);
821 else
822 Feed ++;
823 }
824
825 /*
826 * Eject the page...
827 */
828
829 EndPage();
839a51c8
MS
830
831 if (Canceled)
832 break;
ef416fc2 833 }
834
835 /*
836 * Shutdown the printer...
837 */
838
839 Shutdown();
840
841 if (ppd)
842 ppdClose(ppd);
843
844 /*
845 * Close the raster stream...
846 */
847
848 cupsRasterClose(ras);
849 if (fd != 0)
850 close(fd);
851
852 /*
853 * If no pages were printed, send an error message...
854 */
855
856 if (Page == 0)
f0ab5bff
MS
857 {
858 _cupsLangPuts(stderr, _("ERROR: No pages found!\n"));
859 return (1);
860 }
ef416fc2 861 else
f0ab5bff
MS
862 {
863 _cupsLangPuts(stderr, _("INFO: Ready to print.\n"));
864 return (0);
865 }
ef416fc2 866}
867
868
869/*
b19ccc9e 870 * End of "$Id: rastertohp.c 7834 2008-08-04 21:02:09Z mike $".
ef416fc2 871 */