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