"Fossies" - the Fresh Open Source Software Archive

Member "cups-2.3rc1/filter/rastertohp.c" (21 May 2019, 18977 Bytes) of package /linux/misc/cups-2.3rc1-source.tar.gz:


As a special service "Fossies" has tried to format the requested source page into HTML format using (guessed) C and C++ source code syntax highlighting (style: standard) with prefixed line numbers and code folding option. Alternatively you can here view or download the uninterpreted source code file. For more information about "rastertohp.c" see the Fossies "Dox" file reference documentation and the last Fossies "Diffs" side-by-side code changes report: 2.2.11_vs_2.3b8.

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