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