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