]> git.ipfire.org Git - thirdparty/cups-filters.git/commitdiff
libcupsfilters: Joined cfFilterImageToPS() and cfFilterPSToPS() in one file
authorTill Kamppeter <till.kamppeter@gmail.com>
Fri, 8 Apr 2022 23:32:23 +0000 (01:32 +0200)
committerTill Kamppeter <till.kamppeter@gmail.com>
Fri, 8 Apr 2022 23:32:23 +0000 (01:32 +0200)
cfFilterImageToPS() and cfFilterPSToPS() have some common functions
which were implemented in both the imagetops.c and pstops.c
files. Joined the files into one imagetops-pstops.c file letting the
two filter functions share these functions. Also did some code
clean-up for more consistency.

Makefile.am
cupsfilters/imagetops-pstops.c [moved from cupsfilters/pstops.c with 71% similarity]
cupsfilters/imagetops.c [deleted file]

index 133f0ef8372b21b770736d3fe61c194ce10781d0..35f8cc7fbb5445c8546b16483fe30f2d8872e325 100644 (file)
@@ -465,7 +465,6 @@ libcupsfilters_la_SOURCES = \
        cupsfilters/image-tiff.c \
        cupsfilters/image-zoom.c \
        cupsfilters/imagetopdf.c \
-       cupsfilters/imagetops.c \
        cupsfilters/imagetoraster.c \
        cupsfilters/ipp.c \
        cupsfilters/lut.c \
@@ -499,7 +498,7 @@ libcupsfilters_la_SOURCES = \
        cupsfilters/pdftoraster.cxx \
        cupsfilters/pdfutils.c \
        cupsfilters/ppdgenerator.c \
-       cupsfilters/pstops.c \
+       cupsfilters/imagetops-pstops.c \
        cupsfilters/pwgtoraster.c \
        cupsfilters/raster.c \
        cupsfilters/rastertops.c \
similarity index 71%
rename from cupsfilters/pstops.c
rename to cupsfilters/imagetops-pstops.c
index d70258ddc9dc72ab5aa19b54d708ecf2eef614af..b587a13e846e2686ca8f035d266f13af2ac2a3f5 100644 (file)
@@ -1,5 +1,6 @@
 /*
- * PostScript filter function for cups-filters.
+ * PostScript filter function and image file to PostScript filter function
+ * for cups-filters.
  *
  * Copyright © 2020 by Till Kamppeter
  * Copyright © 2007-2018 by Apple Inc.
  * Include necessary headers...
  */
 
-#include "filter.h"
+#include <cupsfilters/filter.h>
+#include <cupsfilters/image.h>
+#include <cupsfilters/raster.h>
+#include <cupsfilters/image-private.h>
+#include <ppd/ppd.h>
+#include <cups/file.h>
+#include <cups/array.h>
 #include <limits.h>
 #include <math.h>
 #include <ctype.h>
 #include <signal.h>
+#include <string.h>
 #include <errno.h>
-#include <cups/file.h>
-#include <cups/array.h>
-#include <ppd/ppd.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 
@@ -114,7 +119,7 @@ typedef struct                              /**** Document information ****/
   int           Orientation,            /* 0 = portrait, 1 = landscape, etc. */
                 Duplex,                 /* Duplexed? */
                 LanguageLevel,          /* PS Language level of printer */
-                ColorDevice;            /* Color printer? */
+                Color;                  /* Color printer? */
   float         PageLeft,               /* Left margin */
                 PageRight,              /* Right margin */
                 PageBottom,             /* Bottom margin */
@@ -179,6 +184,7 @@ static ssize_t              copy_trailer(pstops_doc_t *doc,
 static void            do_prolog(pstops_doc_t *doc, ppd_file_t *ppd);
 static void            do_setup(pstops_doc_t *doc, ppd_file_t *ppd);
 static void            doc_printf(pstops_doc_t *doc, const char *format, ...);
+static void            doc_putc(pstops_doc_t *doc, const char c);
 static void            doc_puts(pstops_doc_t *doc, const char *s);
 static void            doc_write(pstops_doc_t *doc, const char *s, size_t len);
 static void            end_nup(pstops_doc_t *doc, int number);
@@ -187,6 +193,10 @@ static int         include_feature(pstops_doc_t *doc, ppd_file_t *ppd,
                                        cups_option_t **options);
 static char            *parse_text(const char *start, char **end, char *buffer,
                                    size_t bufsize);
+static void            ps_hex(pstops_doc_t *doc, cf_ib_t *data, int length,
+                              int last_line);
+static void            ps_ascii85(pstops_doc_t *doc, cf_ib_t *data, int length,
+                                  int last_line);
 static int             set_pstops_options(pstops_doc_t *doc, ppd_file_t *ppd,
                                           int job_id, char *job_user,
                                           char *job_title, int copies,
@@ -201,6 +211,7 @@ static ssize_t              skip_page(pstops_doc_t *doc,
                                  char *line, ssize_t linelen, size_t linesize);
 static void            start_nup(pstops_doc_t *doc, int number,
                                  int show_border, const int *bounding_box);
+static void            write_common(pstops_doc_t *doc);
 static void            write_label_prolog(pstops_doc_t *doc, const char *label,
                                           float bottom, float top,
                                           float width);
@@ -388,151 +399,1439 @@ cfFilterPSToPS(int inputfd,         /* I - File descriptor input stream */
   * Write any "exit server" options that have been selected...
   */
 
-  ppdEmit(data->ppd, outputfp, PPD_ORDER_EXIT);
+  ppdEmit(data->ppd, outputfp, PPD_ORDER_EXIT);
+
+ /*
+  * Write any JCL commands that are needed to print PostScript code...
+  */
+
+  if (doc.emit_jcl)
+    ppdEmitJCL(data->ppd, outputfp, doc.job_id, doc.user, doc.title);
+
+ /*
+  * Start with a DSC header...
+  */
+
+  doc_puts(&doc, "%!PS-Adobe-3.0\n");
+
+ /*
+  * Skip leading PJL in the document...
+  */
+
+  while (!strncmp(line, "\033%-12345X", 9) || !strncmp(line, "@PJL ", 5))
+  {
+   /*
+    * Yup, we have leading PJL fun, so skip it until we hit the line
+    * with "ENTER LANGUAGE"...
+    */
+
+    if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                "cfFilterPSToPS: Skipping PJL header...");
+
+    while (strstr(line, "ENTER LANGUAGE") == NULL && strncmp(line, "%!", 2))
+      if ((len = (ssize_t)cupsFileGetLine(inputfp, line, sizeof(line))) == 0)
+        break;
+
+    if (!strncmp(line, "%!", 2))
+      break;
+
+    if ((len = (ssize_t)cupsFileGetLine(inputfp, line, sizeof(line))) == 0)
+      break;
+  }
+
+ /*
+  * Now see if the document conforms to the Adobe Document Structuring
+  * Conventions...
+  */
+
+  if (!strncmp(line, "%!PS-Adobe-", 11))
+  {
+   /*
+    * Yes, filter the document...
+    */
+
+    copy_dsc(&doc, data->ppd, line, len, sizeof(line));
+  }
+  else
+  {
+   /*
+    * No, display an error message and treat the file as if it contains
+    * a single page...
+    */
+
+    copy_non_dsc(&doc, data->ppd, line, len, sizeof(line));
+  }
+
+ /*
+  * Send %%EOF as needed...
+  */
+
+  if (!doc.saw_eof)
+    doc_puts(&doc, "%%EOF\n");
+
+ /*
+  * End the job with the appropriate JCL command or CTRL-D...
+  */
+
+  if (doc.emit_jcl)
+  {
+    if (data->ppd && data->ppd->jcl_end)
+      ppdEmitJCLEnd(data->ppd, doc.outputfp);
+    else
+      doc_putc(&doc, 0x04);
+  }
+
+ /*
+  * Close files and remove the temporary file if needed...
+  */
+
+  if (doc.temp)
+  {
+    cupsFileClose(doc.temp);
+    unlink(doc.tempfile);
+  }
+
+  if (doc.pages)
+  {
+    for (pageinfo = (pstops_page_t *)cupsArrayFirst(doc.pages);
+         pageinfo; pageinfo = (pstops_page_t *)cupsArrayNext(doc.pages))
+    {
+      if (pageinfo->label)
+       free(pageinfo->label);
+      if (pageinfo->num_options && pageinfo->options)
+       cupsFreeOptions(pageinfo->num_options, pageinfo->options);
+      free(pageinfo);
+    }
+    cupsArrayDelete(doc.pages);
+    doc.pages = NULL;
+  }
+
+  if(doc.inputPageRange)
+    { 
+      retry_wait:
+        if (waitpid (pstops_pid, &childStatus, 0) == -1) {
+          if (errno == EINTR)
+            goto retry_wait;
+          if (log) log(ld, CF_LOGLEVEL_ERROR,
+          "cfFilterPSToPS: Error while waiting for input_page_ranges to finish - %s.",
+          strerror(errno));
+        }
+        /* How did the sub-process terminate */
+    if (childStatus) {
+      if (WIFEXITED(childStatus)) {
+       /* Via exit() anywhere or return() in the main() function */
+       if (log) log(ld, CF_LOGLEVEL_ERROR,
+                    "cfFilterPSToPS: input-page-ranges filter (PID %d) stopped with status %d",
+                    pstops_pid, WEXITSTATUS(childStatus));
+      } else {
+       /* Via signal */
+       if (log) log(ld, CF_LOGLEVEL_ERROR,
+                    "cfFilterPSToPS: imput-page-ranges filter (PID %d) crashed on signal %d",
+                    pstops_pid, WTERMSIG(childStatus));
+      }
+      status=1;
+    } else {
+      if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                  "cfFilterPSToPS: input-page-ranges-filter (PID %d) exited with no errors.",
+                  pstops_pid);
+    }
+  }
+
+  cupsFileClose(inputfp);
+  close(inputfd);
+
+  fclose(outputfp);
+  close(outputfd);
+
+  return (status);
+}
+
+
+/*
+ * 'cfFilterImageToPS()' - Filter function to convert many common image file
+ *                 formats into PostScript
+ */
+
+int                                       /* O - Error status */
+cfFilterImageToPS(int inputfd,            /* I - File descriptor input stream */
+                 int outputfd,           /* I - File descriptor output stream*/
+                 int inputseekable,      /* I - Is input stream seekable?
+                                            (unused) */
+                 cf_filter_data_t *data, /* I - Job and printer data */
+                 void *parameters)       /* I - Filter-specific parameters
+                                            (unused) */
+{
+  pstops_doc_t doc;                    /* Document information */
+  cf_image_t   *img;                   /* Image to print */
+  float                xprint,                 /* Printable area */
+               yprint,
+               xinches,                /* Total size in inches */
+               yinches;
+  float                xsize,                  /* Total size in points */
+               ysize,
+               xsize2,
+               ysize2;
+  float                aspect;                 /* Aspect ratio */
+  int          xpages,                 /* # x pages */
+               ypages,                 /* # y pages */
+               xpage,                  /* Current x page */
+               ypage,                  /* Current y page */
+               page;                   /* Current page number */
+  int          xc0, yc0,               /* Corners of the page in image coords*/
+               xc1, yc1;
+  cf_ib_t      *row;                   /* Current row */
+  int          y;                      /* Current Y coordinate in image */
+  int          colorspace;             /* Output colorspace */
+  int          out_offset,             /* Offset into output buffer */
+               out_length;             /* Length of output buffer */
+  ppd_file_t   *ppd;                   /* PPD file */
+  ppd_choice_t *choice;                /* PPD option choice */
+  int          num_options;            /* Number of print options */
+  cups_option_t        *options;               /* Print options */
+  const char   *val;                   /* Option value */
+  int          slowcollate;            /* Collate copies the slow way */
+  float                g;                      /* Gamma correction value */
+  float                b;                      /* Brightness factor */
+  float                zoom;                   /* Zoom facter */
+  int          xppi, yppi;             /* Pixels-per-inch */
+  int          hue, sat;               /* Hue and saturation adjustment */
+  int          realcopies,             /* Real copies being printed */
+               emit_jcl;               /* Emit JCL? */
+  float                left, top;              /* Left and top of image */
+  time_t       curtime;                /* Current time */
+  struct tm    *curtm;                 /* Current date */
+  char         curdate[255];           /* Current date string */
+  int          fillprint = 0;          /* print-scaling = fill */
+  int          cropfit = 0;            /* -o crop-to-fit = true */
+  cups_page_header2_t h;                /* CUPS Raster page header, to */
+                                        /* accommodate results of command */
+                                        /* line parsing for PPD-less queue */
+  int          Flip,                   /* Flip/mirror pages */
+               XPosition,              /* Horizontal position on page */
+               YPosition,              /* Vertical position on page */
+               Collate,                /* Collate copies? */
+               Copies;                 /* Number of copies */
+  char         tempfile[1024];         /* Name of file to print */
+  FILE          *inputfp;              /* Input file */
+  int           fd;                    /* File descriptor for temp file */
+  char          buf[BUFSIZ];
+  int           bytes;
+  cf_logfunc_t log = data->logfunc;
+  void          *ld = data->logdata;
+  cf_filter_iscanceledfunc_t iscanceled = data->iscanceledfunc;
+  void          *icd = data->iscanceleddata;
+
+
+ /*
+  * Make sure status messages are not buffered...
+  */
+
+  setbuf(stderr, NULL);
+
+ /*
+  * Ignore broken pipe signals...
+  */
+
+  signal(SIGPIPE, SIG_IGN);
+
+ /*
+  * Initialize data structure
+  */
+
+  Flip = 0;
+  XPosition = 0;
+  YPosition = 0;
+  Collate = 0;
+  Copies = 1;
+
+ /*
+  * Initialize document information structure...
+  */
+
+  memset(&doc, 0, sizeof(pstops_doc_t));
+
+ /*
+  * Open the input data stream specified by the inputfd ...
+  */
+
+  if ((inputfp = fdopen(inputfd, "r")) == NULL)
+  {
+    if (!iscanceled || !iscanceled(icd))
+    {
+      if (log) log(ld, CF_LOGLEVEL_ERROR,
+                  "cfFilterImageToPS: Unable to open input data stream.");
+    }
+
+    return (1);
+  }
+
+ /*
+  * Copy input into temporary file if needed ...
+  */
+
+  if (!inputseekable) {
+    if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
+    {
+      if (log) log(ld, CF_LOGLEVEL_ERROR,
+                  "cfFilterImageToPS: Unable to copy input: %s",
+                  strerror(errno));
+      return (1);
+    }
+
+    if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                "cfFilterImageToPS: Copying input to temp file \"%s\"",
+                tempfile);
+
+    while ((bytes = fread(buf, 1, sizeof(buf), inputfp)) > 0)
+      bytes = write(fd, buf, bytes);
+
+    fclose(inputfp);
+    close(fd);
+
+   /*
+    * Open the temporary file to read it instead of the original input ...
+    */
+
+    if ((inputfp = fopen(tempfile, "r")) == NULL)
+    {
+      if (!iscanceled || !iscanceled(icd))
+      {
+       if (log) log(ld, CF_LOGLEVEL_ERROR,
+                    "cfFilterImageToPS: Unable to open temporary file.");
+      }
+
+      unlink(tempfile);
+      return (1);
+    }
+  }
+
+ /*
+  * Open the output data stream specified by the outputfd...
+  */
+
+  if ((doc.outputfp = fdopen(outputfd, "w")) == NULL)
+  {
+    if (!iscanceled || !iscanceled(icd))
+    {
+      if (log) log(ld, CF_LOGLEVEL_ERROR,
+                  "cfFilterImageToPS: Unable to open output data stream.");
+    }
+
+    fclose(inputfp);
+
+    if (!inputseekable)
+      unlink(tempfile);
+    return (1);
+  }
+
+ /*
+  * Process command-line options and write the prolog...
+  */
+
+  zoom = 1.0;
+  xppi = 0;
+  yppi = 0;
+  hue  = 0;
+  sat  = 100;
+  g    = 1.0;
+  b    = 1.0;
+
+  Copies = data->copies;
+
+ /*
+  * Option list...
+  */
+
+  options     = data->options;
+  num_options = data->num_options;
+
+ /*
+  * Process job options...
+  */
+
+  ppd = data->ppd;
+  cfFilterSetCommonOptions(ppd, num_options, options, 0,
+                        &doc.Orientation, &doc.Duplex,
+                        &doc.LanguageLevel, &doc.Color,
+                        &doc.PageLeft, &doc.PageRight,
+                        &doc.PageTop, &doc.PageBottom,
+                        &doc.PageWidth, &doc.PageLength,
+                        log, ld);
+
+  /* The cfFilterSetCommonOptions() does not set doc.Color
+     according to option settings (user's demand for color/gray),
+     so we parse the options and set the mode here */
+  cfRasterParseIPPOptions(&h, data, 0, 1);
+  if (doc.Color)
+    doc.Color = h.cupsNumColors <= 1 ? 0 : 1;
+  if (!ppd) {
+    /* Without PPD use also the other findings of cfRasterParseIPPOptions() */
+    doc.Orientation = h.Orientation;
+    doc.Duplex = h.Duplex;
+    doc.LanguageLevel = 2;
+    doc.PageWidth = h.cupsPageSize[0] != 0.0 ? h.cupsPageSize[0] :
+      (float)h.PageSize[0];
+    doc.PageLength = h.cupsPageSize[1] != 0.0 ? h.cupsPageSize[1] :
+      (float)h.PageSize[1];
+    doc.PageLeft = h.cupsImagingBBox[0] != 0.0 ? h.cupsImagingBBox[0] :
+      (float)h.ImagingBoundingBox[0];
+    doc.PageBottom = h.cupsImagingBBox[1] != 0.0 ? h.cupsImagingBBox[1] :
+      (float)h.ImagingBoundingBox[1];
+    doc.PageRight = h.cupsImagingBBox[2] != 0.0 ? h.cupsImagingBBox[2] :
+      (float)h.ImagingBoundingBox[2];
+    doc.PageTop = h.cupsImagingBBox[3] != 0.0 ? h.cupsImagingBBox[3] :
+      (float)h.ImagingBoundingBox[3];
+    Flip = h.MirrorPrint ? 1 : 0;
+    Collate = h.Collate ? 1 : 0;
+    Copies = h.NumCopies;
+  }
+
+  if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
+  {
+   /*
+    * This IPP attribute is unnecessarily complicated...
+    *
+    *   single-document, separate-documents-collated-copies, and
+    *   single-document-new-sheet all require collated copies.
+    *
+    *   separate-documents-uncollated-copies allows for uncollated copies.
+    */
+
+    Collate = strcasecmp(val, "separate-documents-uncollated-copies") != 0;
+  }
+
+  if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
+      strcasecmp(val, "True") == 0)
+    Collate = 1;
+
+  if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
+  {
+   /*
+    * Get gamma value from 1 to 10000...
+    */
+
+    g = atoi(val) * 0.001f;
+
+    if (g < 0.001f)
+      g = 0.001f;
+    else if (g > 10.0f)
+      g = 10.0f;
+  }
+
+  if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
+  {
+   /*
+    * Get brightness value from 10 to 1000.
+    */
+
+    b = atoi(val) * 0.01f;
+
+    if (b < 0.1f)
+      b = 0.1f;
+    else if (b > 10.0f)
+      b = 10.0f;
+  }
+
+  if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
+  {
+    sscanf(val, "%d", &xppi);
+    yppi = xppi;
+    zoom = 0.0;
+  }
+
+  if ((val = cupsGetOption("position", num_options, options)) != NULL)
+  {
+    if (strcasecmp(val, "center") == 0)
+    {
+      XPosition = 0;
+      YPosition = 0;
+    }
+    else if (strcasecmp(val, "top") == 0)
+    {
+      XPosition = 0;
+      YPosition = 1;
+    }
+    else if (strcasecmp(val, "left") == 0)
+    {
+      XPosition = -1;
+      YPosition = 0;
+    }
+    else if (strcasecmp(val, "right") == 0)
+    {
+      XPosition = 1;
+      YPosition = 0;
+    }
+    else if (strcasecmp(val, "top-left") == 0)
+    {
+      XPosition = -1;
+      YPosition = 1;
+    }
+    else if (strcasecmp(val, "top-right") == 0)
+    {
+      XPosition = 1;
+      YPosition = 1;
+    }
+    else if (strcasecmp(val, "bottom") == 0)
+    {
+      XPosition = 0;
+      YPosition = -1;
+    }
+    else if (strcasecmp(val, "bottom-left") == 0)
+    {
+      XPosition = -1;
+      YPosition = -1;
+    }
+    else if (strcasecmp(val, "bottom-right") == 0)
+    {
+      XPosition = 1;
+      YPosition = -1;
+    }
+  }
+
+  if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
+    sat = atoi(val);
+
+  if ((val = cupsGetOption("hue", num_options, options)) != NULL)
+    hue = atoi(val);
+
+  if ((choice = ppdFindMarkedChoice(ppd, "MirrorPrint")) != NULL)
+  {
+    val = choice->choice;
+    choice->marked = 0;
+  }
+  else
+    val = cupsGetOption("mirror", num_options, options);
+
+  if (val && (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
+              !strcasecmp(val, "yes")))
+    Flip = 1;
+
+  if ((val = cupsGetOption("emit-jcl", num_options, options)) != NULL &&
+      (!strcasecmp(val, "false") || !strcasecmp(val, "off") ||
+       !strcasecmp(val, "no") || !strcmp(val, "0")))
+    emit_jcl = 0;
+  else
+    emit_jcl = 1;
+
+ /*
+  * Open the input image to print...
+  */
+
+  colorspace = doc.Color ? CF_IMAGE_RGB_CMYK : CF_IMAGE_WHITE;
+
+  img = cfImageOpenFP(inputfp, colorspace, CF_IMAGE_WHITE, sat, hue, NULL);
+  if (img != NULL) {
+
+    int margin_defined = 0;
+    int fidelity = 0;
+    int document_large = 0;
+
+    if (ppd && (ppd->custom_margins[0] || ppd->custom_margins[1] ||
+               ppd->custom_margins[2] || ppd->custom_margins[3]))
+      /* In case of custom margins */
+      margin_defined = 1;
+    if (doc.PageLength != doc.PageTop - doc.PageBottom ||
+       doc.PageWidth != doc.PageRight - doc.PageLeft)
+      margin_defined = 1;
+
+    if((val = cupsGetOption("ipp-attribute-fidelity", num_options, options))
+       != NULL)
+    {
+      if(!strcasecmp(val, "true") || !strcasecmp(val, "yes") ||
+        !strcasecmp(val, "on")) {
+       fidelity = 1;
+      }
+    }
+
+    float w = (float)cfImageGetWidth(img);
+    float h = (float)cfImageGetHeight(img);
+    float pw = doc.PageRight - doc.PageLeft;
+    float ph = doc.PageTop - doc.PageBottom;
+    int tempOrientation = doc.Orientation;
+    if ((val = cupsGetOption("orientation-requested", num_options, options)) !=
+       NULL)
+      tempOrientation = atoi(val);
+    else if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
+    {
+      if(!strcasecmp(val, "true") || !strcasecmp(val, "yes"))
+       tempOrientation = 4;
+    }
+    if (tempOrientation == 0) {
+      if (((pw > ph) && (w < h)) || ((pw < ph) && (w > h)))
+       tempOrientation = 4;
+    }
+    if (tempOrientation == 4 || tempOrientation == 5)
+    {
+      int tmp = pw;
+      pw = ph;
+      ph = tmp;
+    }
+    if (w * 72.0 / img->xppi > pw || h * 72.0 / img->yppi > ph)
+      document_large = 1;
+
+    if ((val = cupsGetOption("print-scaling", num_options, options)) != NULL)
+    {
+      if (!strcasecmp(val, "auto"))
+      {
+       if (fidelity || document_large) {
+         if (margin_defined)
+           zoom = 1.0;       // fit method
+         else
+           fillprint = 1;    // fill method
+       }
+       else
+         cropfit = 1;        // none method
+      }
+      else if (!strcasecmp(val, "auto-fit"))
+      {
+       if (fidelity || document_large)
+         zoom = 1.0;         // fit method
+       else
+         cropfit = 1;        // none method
+      }
+      else if (!strcasecmp(val, "fill"))
+       fillprint = 1;        // fill method
+      else if (!strcasecmp(val, "fit"))
+       zoom = 1.0;           // fitplot = 1 or fit method
+      else
+       cropfit = 1;            // none or crop-to-fit
+    }
+    else
+    {       // print-scaling is not defined, look for alternate options.
+      if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
+       zoom = atoi(val) * 0.01;
+      else if (((val =
+                cupsGetOption("fit-to-page", num_options, options)) != NULL) ||
+              ((val = cupsGetOption("fitplot", num_options, options)) != NULL))
+      {
+       if (!strcasecmp(val, "yes") || !strcasecmp(val, "on") ||
+           !strcasecmp(val, "true"))
+         zoom = 1.0;
+       else
+         zoom = 0.0;
+      }
+      else if ((val = cupsGetOption("natural-scaling", num_options, options)) !=
+              NULL)
+       zoom = 0.0;
+
+      if ((val = cupsGetOption("fill", num_options,options)) != NULL)
+      {
+       if (!strcasecmp(val, "true") || !strcasecmp(val, "yes"))
+         fillprint = 1;
+      }
+
+      if ((val = cupsGetOption("crop-to-fit", num_options,options)) != NULL)
+      {
+       if (!strcasecmp(val, "true") || !strcasecmp(val, "yes"))
+         cropfit=1;
+      }
+    }
+    if (fillprint || cropfit)
+    {
+      /* For cropfit do the math without the unprintable margins to get correct
+         centering */
+      if (cropfit)
+      {
+       pw = doc.PageWidth;
+       ph = doc.PageLength;
+       doc.PageBottom = 0.0;
+       doc.PageTop = doc.PageLength;
+       doc.PageLeft = 0.0;
+       doc.PageRight = doc.PageWidth;
+      }
+      tempOrientation = doc.Orientation;
+      int flag = 3;
+      if ((val = cupsGetOption("orientation-requested", num_options,
+                              options)) != NULL)
+       tempOrientation = atoi(val);
+      else if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
+      {
+       if (!strcasecmp(val,"true") || !strcasecmp(val,"yes"))
+         tempOrientation = 4;
+      }
+      if (tempOrientation > 0)
+      {
+       if (tempOrientation == 4 || tempOrientation == 5)
+       {
+         float temp = pw;
+         pw = ph;
+         ph = temp;
+         flag = 4;
+       }
+      }
+      if (tempOrientation==0)
+      { 
+       if (((pw > ph) && (w < h)) || ((pw < ph) && (w > h)))
+       {
+         int temp = pw;
+         pw = ph;
+         ph = temp;
+         flag = 4;
+       }
+      }
+      if (fillprint) {
+       float final_w, final_h;
+       if (w * ph / pw <= h) {
+         final_w = w;
+         final_h = w * ph / pw; 
+       }
+       else
+       {
+         final_w = h * pw / ph;
+         final_h = h;
+       }
+       float posw = (w - final_w) / 2, posh = (h - final_h) / 2;
+       posw = (1 + XPosition) * posw;
+       posh = (1 - YPosition) * posh;
+       cf_image_t *img2 = cfImageCrop(img, posw, posh, final_w, final_h);
+       cfImageClose(img);
+       img = img2;
+      }
+      else
+      {
+       float final_w = w, final_h = h;
+        if (w > pw * img->xppi / 72.0)
+          final_w = pw * img->xppi / 72.0;
+        if (h > ph * img->yppi / 72.0)
+          final_h = ph * img->yppi / 72.0;
+       float posw = (w - final_w) / 2, posh = (h - final_h) / 2;
+       posw = (1 + XPosition) * posw;
+       posh = (1 - YPosition) * posh;
+       cf_image_t *img2 = cfImageCrop(img, posw, posh, final_w, final_h);
+       cfImageClose(img);
+       img = img2;
+       if (flag == 4)
+       {
+         doc.PageBottom += (doc.PageLength - final_w * 72.0 / img->xppi) / 2;
+         doc.PageTop = doc.PageBottom + final_w * 72.0 / img->xppi;
+         doc.PageLeft += (doc.PageWidth - final_h * 72.0 / img->yppi) / 2;
+         doc.PageRight = doc.PageLeft + final_h * 72.0 / img->yppi;
+       }
+       else
+       {
+         doc.PageBottom += (doc.PageLength - final_h * 72.0 / img->yppi) / 2;
+         doc.PageTop = doc.PageBottom + final_h * 72.0 / img->yppi;
+         doc.PageLeft += (doc.PageWidth - final_w * 72.0 / img->xppi) / 2;
+         doc.PageRight = doc.PageLeft + final_w * 72.0 / img->xppi;
+       }
+       if (doc.PageBottom < 0) doc.PageBottom = 0;
+       if (doc.PageLeft < 0) doc.PageLeft = 0;
+      }
+    }
+  }
+
+  if (!inputseekable)
+    unlink(tempfile);
+
+  if (img == NULL)
+  {
+    if (log) log(ld, CF_LOGLEVEL_ERROR,
+                "cfFilterImageToPS: The print file could not be opened - %s",
+                strerror(errno));
+    return (1);
+  }
+
+  colorspace = cfImageGetColorSpace(img);
+
+ /*
+  * Scale as necessary...
+  */
+
+  if (zoom == 0.0 && xppi == 0)
+  {
+    xppi = cfImageGetXPPI(img);
+    yppi = cfImageGetYPPI(img);
+  }
+
+  if (yppi == 0)
+    yppi = xppi;
+
+  if (log) log(ld, CF_LOGLEVEL_DEBUG,
+              "cfFilterImageToPS: Before scaling: xppi=%d, yppi=%d, zoom=%.2f",
+              xppi, yppi, zoom);
+
+  if (xppi > 0)
+  {
+   /*
+    * Scale the image as neccesary to match the desired pixels-per-inch.
+    */
+
+    if (doc.Orientation & 1)
+    {
+      xprint = (doc.PageTop - doc.PageBottom) / 72.0;
+      yprint = (doc.PageRight - doc.PageLeft) / 72.0;
+    }
+    else
+    {
+      xprint = (doc.PageRight - doc.PageLeft) / 72.0;
+      yprint = (doc.PageTop - doc.PageBottom) / 72.0;
+    }
+
+    if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                "cfFilterImageToPS: Before scaling: xprint=%.1f, yprint=%.1f",
+                xprint, yprint);
+
+    xinches = (float)cfImageGetWidth(img) / (float)xppi;
+    yinches = (float)cfImageGetHeight(img) / (float)yppi;
+
+    if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                "cfFilterImageToPS: Image size is %.1f x %.1f inches...",
+                xinches, yinches);
+
+    if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
+    {
+      xinches = xinches * atoi(val) / 100;
+      yinches = yinches * atoi(val) / 100;
+    }
+
+    if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
+        cupsGetOption("landscape", num_options, options) == NULL)
+    {
+     /*
+      * Rotate the image if it will fit landscape but not portrait...
+      */
+
+      if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                  "cfFilterImageToPS: Auto orientation...");
+
+      if ((xinches > xprint || yinches > yprint) &&
+          xinches <= yprint && yinches <= xprint)
+      {
+       /*
+       * Rotate the image as needed...
+       */
+
+       if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                    "cfFilterImageToPS: Using landscape orientation...");
+
+       doc.Orientation = (doc.Orientation + 1) & 3;
+       xsize       = yprint;
+       yprint      = xprint;
+       xprint      = xsize;
+      }
+    }
+  }
+  else
+  {
+   /*
+    * Scale percentage of page size...
+    */
+
+    xprint = (doc.PageRight - doc.PageLeft) / 72.0;
+    yprint = (doc.PageTop - doc.PageBottom) / 72.0;
+    aspect = (float)cfImageGetYPPI(img) / (float)cfImageGetXPPI(img);
+
+    if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                "cfFilterImageToPS: Before scaling: xprint=%.1f, yprint=%.1f",
+                xprint, yprint);
+
+    if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                "cfFilterImageToPS: cfImageGetXPPI(img) = %d, "
+                "cfImageGetYPPI(img) = %d, aspect = %f",
+                cfImageGetXPPI(img), cfImageGetYPPI(img), aspect);
+
+    xsize = xprint * zoom;
+    ysize = xsize * cfImageGetHeight(img) / cfImageGetWidth(img) / aspect;
+
+    if (ysize > (yprint * zoom))
+    {
+      ysize = yprint * zoom;
+      xsize = ysize * cfImageGetWidth(img) * aspect /
+       cfImageGetHeight(img);
+    }
+
+    xsize2 = yprint * zoom;
+    ysize2 = xsize2 * cfImageGetHeight(img) / cfImageGetWidth(img) /
+      aspect;
+
+    if (ysize2 > (xprint * zoom))
+    {
+      ysize2 = xprint * zoom;
+      xsize2 = ysize2 * cfImageGetWidth(img) * aspect /
+       cfImageGetHeight(img);
+    }
+
+    if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                "cfFilterImageToPS: Portrait size is %.2f x %.2f inches",
+                xsize, ysize);
+    if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                "cfFilterImageToPS: Landscape size is %.2f x %.2f inches",
+                xsize2, ysize2);
+
+    if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
+        cupsGetOption("landscape", num_options, options) == NULL)
+    {
+     /*
+      * Choose the rotation with the largest area, but prefer
+      * portrait if they are equal...
+      */
+
+      if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                  "cfFilterImageToPS: Auto orientation...");
+
+      if ((xsize * ysize) < (xsize2 * xsize2))
+      {
+       /*
+       * Do landscape orientation...
+       */
+
+       if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                    "cfFilterImageToPS: Using landscape orientation...");
+
+       doc.Orientation = 1;
+       xinches     = xsize2;
+       yinches     = ysize2;
+       xprint      = (doc.PageTop - doc.PageBottom) / 72.0;
+       yprint      = (doc.PageRight - doc.PageLeft) / 72.0;
+      }
+      else
+      {
+       /*
+       * Do portrait orientation...
+       */
+
+       if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                    "cfFilterImageToPS: Using portrait orientation...");
+
+       doc.Orientation = 0;
+       xinches     = xsize;
+       yinches     = ysize;
+      }
+    }
+    else if (doc.Orientation & 1)
+    {
+      if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                  "cfFilterImageToPS: Using landscape orientation...");
+
+      xinches     = xsize2;
+      yinches     = ysize2;
+      xprint      = (doc.PageTop - doc.PageBottom) / 72.0;
+      yprint      = (doc.PageRight - doc.PageLeft) / 72.0;
+    }
+    else
+    {
+      if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                  "cfFilterImageToPS: Using portrait orientation...");
+
+      xinches     = xsize;
+      yinches     = ysize;
+      xprint      = (doc.PageRight - doc.PageLeft) / 72.0;
+      yprint      = (doc.PageTop - doc.PageBottom) / 72.0;
+    }
+  }
+
+ /*
+  * Compute the number of pages to print and the size of the image on each
+  * page...
+  */
+
+  xpages = ceil(xinches / xprint);
+  ypages = ceil(yinches / yprint);
+
+  xprint = xinches / xpages;
+  yprint = yinches / ypages;
+
+  if (log) log(ld, CF_LOGLEVEL_DEBUG,
+              "cfFilterImageToPS: xpages = %dx%.2fin, ypages = %dx%.2fin",
+              xpages, xprint, ypages, yprint);
+
+ /*
+  * Update the page size for custom sizes...
+  */
+
+  if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
+      strcasecmp(choice->choice, "Custom") == 0)
+  {
+    float      width,          /* New width in points */
+               length;         /* New length in points */
+    char       s[255];         /* New custom page size... */
+
+
+   /*
+    * Use the correct width and length for the current orientation...
+    */
+
+    if (doc.Orientation & 1)
+    {
+      width  = yprint * 72.0;
+      length = xprint * 72.0;
+    }
+    else
+    {
+      width  = xprint * 72.0;
+      length = yprint * 72.0;
+    }
+
+   /*
+    * Add margins to page size...
+    */
+
+    width  += ppd->custom_margins[0] + ppd->custom_margins[2];
+    length += ppd->custom_margins[1] + ppd->custom_margins[3];
+
+   /*
+    * Enforce minimums...
+    */
+
+    if (width < ppd->custom_min[0])
+      width = ppd->custom_min[0];
+
+    if (length < ppd->custom_min[1])
+      length = ppd->custom_min[1];
+
+    if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                "cfFilterImageToPS: Updated custom page size to %.2f x %.2f inches...",
+                width / 72.0, length / 72.0);
+
+   /*
+    * Set the new custom size...
+    */
+
+    sprintf(s, "Custom.%.0fx%.0f", width, length);
+    ppdMarkOption(ppd, "PageSize", s);
+
+   /*
+    * Update page variables...
+    */
+
+    doc.PageWidth  = width;
+    doc.PageLength = length;
+    doc.PageLeft   = ppd->custom_margins[0];
+    doc.PageRight  = width - ppd->custom_margins[2];
+    doc.PageBottom = ppd->custom_margins[1];
+    doc.PageTop    = length - ppd->custom_margins[3];
+  }
+
+ /*
+  * See if we need to collate, and if so how we need to do it...
+  */
+
+  if (xpages == 1 && ypages == 1)
+    Collate = 0;
+
+  slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
+
+  if (Copies > 1 && !slowcollate)
+  {
+    realcopies = Copies;
+    Copies     = 1;
+  }
+  else
+    realcopies = 1;
+
+ /*
+  * Write any "exit server" options that have been selected...
+  */
+
+  ppdEmit(ppd, doc.outputfp, PPD_ORDER_EXIT);
+
+ /*
+  * Write any JCL commands that are needed to print PostScript code...
+  */
+
+  if (emit_jcl)
+    ppdEmitJCL(ppd, doc.outputfp, data->job_id, data->job_user,
+              data->job_title);
+
+ /*
+  * Start sending the document with any commands needed...
+  */
+
+  curtime = time(NULL);
+  curtm   = localtime(&curtime);
+
+  doc_puts(&doc, "%!PS-Adobe-3.0\n");
+  doc_printf(&doc, "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
+         doc.PageLeft, doc.PageBottom, doc.PageRight, doc.PageTop);
+  doc_printf(&doc, "%%%%LanguageLevel: %d\n", doc.LanguageLevel);
+  doc_printf(&doc, "%%%%Pages: %d\n", xpages * ypages * Copies);
+  doc_puts(&doc, "%%DocumentData: Clean7Bit\n");
+  doc_puts(&doc, "%%DocumentNeededResources: font Helvetica-Bold\n");
+  doc_puts(&doc, "%%Creator: imagetops\n");
+  strftime(curdate, sizeof(curdate), "%c", curtm);
+  doc_printf(&doc, "%%%%CreationDate: %s\n", curdate);
+  write_text_comment(&doc, "Title", data->job_title);
+  write_text_comment(&doc, "For", data->job_user);
+  if (doc.Orientation & 1)
+    doc_puts(&doc, "%%Orientation: Landscape\n");
+  else
+    doc_puts(&doc, "%%Orientation: Portrait\n");
+  doc_puts(&doc, "%%EndComments\n");
+  doc_puts(&doc, "%%BeginProlog\n");
+
+  if (ppd != NULL && ppd->patches != NULL)
+  {
+    doc_puts(&doc, ppd->patches);
+    doc_putc(&doc, '\n');
+  }
+
+  ppdEmit(ppd, doc.outputfp, PPD_ORDER_DOCUMENT);
+  ppdEmit(ppd, doc.outputfp, PPD_ORDER_ANY);
+  ppdEmit(ppd, doc.outputfp, PPD_ORDER_PROLOG);
+
+  if (g != 1.0 || b != 1.0)
+    doc_printf(&doc,
+           "{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
+           "ifelse %.3f mul } bind settransfer\n", g, b);
+
+  write_common(&doc);
+  switch (doc.Orientation)
+  {
+    case 0 :
+        write_label_prolog(&doc, cupsGetOption("page-label", num_options,
+                                            options),
+                        doc.PageBottom, doc.PageTop, doc.PageWidth);
+        break;
+
+    case 1 :
+        write_label_prolog(&doc, cupsGetOption("page-label", num_options,
+                                            options),
+                        doc.PageLeft, doc.PageRight, doc.PageLength);
+        break;
+
+    case 2 :
+        write_label_prolog(&doc, cupsGetOption("page-label", num_options,
+                                            options),
+                        doc.PageLength - doc.PageTop,
+                        doc.PageLength - doc.PageBottom,
+                        doc.PageWidth);
+        break;
+
+    case 3 :
+       write_label_prolog(&doc, cupsGetOption("page-label", num_options,
+                                            options),
+                        doc.PageWidth - doc.PageRight,
+                        doc.PageWidth - doc.PageLeft,
+                        doc.PageLength);
+        break;
+  }
+
+  if (realcopies > 1)
+  {
+    if (ppd == NULL || ppd->language_level == 1)
+      doc_printf(&doc, "/#copies %d def\n", realcopies);
+    else
+      doc_printf(&doc, "<</NumCopies %d>>setpagedevice\n", realcopies);
+  }
+
+  doc_puts(&doc, "%%EndProlog\n");
+
+ /*
+  * Output the pages...
+  */
+
+  row = malloc(cfImageGetWidth(img) * abs(colorspace) + 3);
+  if (row == NULL)
+  {
+    log(ld, CF_LOGLEVEL_ERROR,
+       "cfFilterImageToPS: Could not allocate memory.");
+    cfImageClose(img);
+    return (2);
+  }
+
+  if (log)
+  {
+    log(ld, CF_LOGLEVEL_DEBUG,
+       "cfFilterImageToPS: XPosition=%d, YPosition=%d, Orientation=%d",
+       XPosition, YPosition, doc.Orientation);
+    log(ld, CF_LOGLEVEL_DEBUG,
+       "cfFilterImageToPS: xprint=%.1f, yprint=%.1f", xprint, yprint);
+    log(ld, CF_LOGLEVEL_DEBUG,
+       "cfFilterImageToPS: PageLeft=%.0f, PageRight=%.0f, PageWidth=%.0f",
+       doc.PageLeft, doc.PageRight, doc.PageWidth);
+    log(ld, CF_LOGLEVEL_DEBUG,
+       "cfFilterImageToPS: PageBottom=%.0f, PageTop=%.0f, PageLength=%.0f",
+       doc.PageBottom, doc.PageTop, doc.PageLength);
+  }
+
+  switch (doc.Orientation)
+  {
+    default :
+       switch (XPosition)
+       {
+         case -1 :
+              left = doc.PageLeft;
+             break;
+         default :
+              left = (doc.PageRight + doc.PageLeft - xprint * 72) / 2;
+             break;
+         case 1 :
+              left = doc.PageRight - xprint * 72;
+             break;
+       }
+
+       switch (YPosition)
+       {
+         case -1 :
+             top = doc.PageBottom + yprint * 72;
+             break;
+         default :
+             top = (doc.PageTop + doc.PageBottom + yprint * 72) / 2;
+             break;
+         case 1 :
+             top = doc.PageTop;
+             break;
+       }
+       break;
+
+    case 1 :
+       switch (XPosition)
+       {
+         case -1 :
+              left = doc.PageBottom;
+             break;
+         default :
+              left = (doc.PageTop + doc.PageBottom - xprint * 72) / 2;
+             break;
+         case 1 :
+              left = doc.PageTop - xprint * 72;
+             break;
+       }
+
+       switch (YPosition)
+       {
+         case -1 :
+             top = doc.PageLeft + yprint * 72;
+             break;
+         default :
+             top = (doc.PageRight + doc.PageLeft + yprint * 72) / 2;
+             break;
+         case 1 :
+             top = doc.PageRight;
+             break;
+       }
+       break;
+
+    case 2 :
+       switch (XPosition)
+       {
+         case 1 :
+              left = doc.PageLeft;
+             break;
+         default :
+              left = (doc.PageRight + doc.PageLeft - xprint * 72) / 2;
+             break;
+         case -1 :
+              left = doc.PageRight - xprint * 72;
+             break;
+       }
+
+       switch (YPosition)
+       {
+         case 1 :
+             top = doc.PageBottom + yprint * 72;
+             break;
+         default :
+             top = (doc.PageTop + doc.PageBottom + yprint * 72) / 2;
+             break;
+         case -1 :
+             top = doc.PageTop;
+             break;
+       }
+       break;
+
+    case 3 :
+       switch (XPosition)
+       {
+         case 1 :
+              left = doc.PageBottom;
+             break;
+         default :
+              left = (doc.PageTop + doc.PageBottom - xprint * 72) / 2;
+             break;
+         case -1 :
+              left = doc.PageTop - xprint * 72;
+             break;
+       }
+
+       switch (YPosition)
+       {
+         case 1 :
+             top = doc.PageLeft + yprint * 72;
+             break;
+         default :
+             top = (doc.PageRight + doc.PageLeft + yprint * 72) / 2;
+             break;
+         case -1 :
+             top = doc.PageRight;
+             break;
+       }
+       break;
+  }
+
+  if (log) log(ld, CF_LOGLEVEL_DEBUG,
+              "cfFilterImageToPS: left=%.2f, top=%.2f", left, top);
+
+  for (page = 1; Copies > 0; Copies --)
+    for (xpage = 0; xpage < xpages; xpage ++)
+      for (ypage = 0; ypage < ypages; ypage ++, page ++)
+      {
+       if (iscanceled && iscanceled(icd))
+       {
+         if (log) log(ld, CF_LOGLEVEL_DEBUG,
+                      "cfFilterImageToPS: Job canceled");
+         goto canceled;
+       }
+
+        if (log && ppd && ppd->num_filters == 0)
+         log(ld, CF_LOGLEVEL_CONTROL,
+             "PAGE: %d %d", page, realcopies);
+
+       if (log) log(ld, CF_LOGLEVEL_INFO,
+                    "cfFilterImageToPS: Printing page %d.", page);
+
+        doc_printf(&doc, "%%%%Page: %d %d\n", page, page);
+
+        ppdEmit(ppd, doc.outputfp, PPD_ORDER_PAGE);
+
+       doc_puts(&doc, "gsave\n");
 
- /*
-  * Write any JCL commands that are needed to print PostScript code...
-  */
+       if (Flip)
+         doc_printf(&doc, "%.0f 0 translate -1 1 scale\n", doc.PageWidth);
 
-  if (doc.emit_jcl)
-    ppdEmitJCL(data->ppd, outputfp, doc.job_id, doc.user, doc.title);
+       switch (doc.Orientation)
+       {
+         case 1 : /* Landscape */
+             doc_printf(&doc, "%.0f 0 translate 90 rotate\n",
+                     doc.PageWidth);
+              break;
+         case 2 : /* Reverse Portrait */
+             doc_printf(&doc, "%.0f %.0f translate 180 rotate\n",
+                     doc.PageWidth, doc.PageLength);
+             break;
+         case 3 : /* Reverse Landscape */
+             doc_printf(&doc, "0 %.0f translate -90 rotate\n",
+                     doc.PageLength);
+              break;
+       }
 
- /*
-  * Start with a DSC header...
-  */
+        doc_puts(&doc, "gsave\n");
 
-  fputs("%!PS-Adobe-3.0\n", outputfp);
+       xc0 = cfImageGetWidth(img) * xpage / xpages;
+       xc1 = cfImageGetWidth(img) * (xpage + 1) / xpages - 1;
+       yc0 = cfImageGetHeight(img) * ypage / ypages;
+       yc1 = cfImageGetHeight(img) * (ypage + 1) / ypages - 1;
 
- /*
-  * Skip leading PJL in the document...
-  */
+        doc_printf(&doc, "%.1f %.1f translate\n", left, top);
 
-  while (!strncmp(line, "\033%-12345X", 9) || !strncmp(line, "@PJL ", 5))
-  {
-   /*
-    * Yup, we have leading PJL fun, so skip it until we hit the line
-    * with "ENTER LANGUAGE"...
-    */
+       doc_printf(&doc, "%.3f %.3f scale\n\n",
+               xprint * 72.0 / (xc1 - xc0 + 1),
+               yprint * 72.0 / (yc1 - yc0 + 1));
 
-    if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                "cfFilterPSToPS: Skipping PJL header...");
+       if (doc.LanguageLevel == 1)
+       {
+         doc_printf(&doc, "/picture %d string def\n",
+                 (xc1 - xc0 + 1) * abs(colorspace));
+         doc_printf(&doc, "%d %d 8[1 0 0 -1 0 1]",
+                 (xc1 - xc0 + 1), (yc1 - yc0 + 1));
+
+          if (colorspace == CF_IMAGE_WHITE)
+            doc_puts(&doc, "{currentfile picture readhexstring pop} image\n");
+          else
+            doc_printf(&doc,
+                      "{currentfile picture readhexstring pop} false %d "
+                      "colorimage\n",
+                      abs(colorspace));
+
+          for (y = yc0; y <= yc1; y ++)
+          {
+            cfImageGetRow(img, xc0, y, xc1 - xc0 + 1, row);
+            ps_hex(&doc, row, (xc1 - xc0 + 1) * abs(colorspace),
+                  y == yc1);
+          }
+       }
+       else
+       {
+          switch (colorspace)
+         {
+           case CF_IMAGE_WHITE :
+               doc_puts(&doc, "/DeviceGray setcolorspace\n");
+               break;
+            case CF_IMAGE_RGB :
+               doc_puts(&doc, "/DeviceRGB setcolorspace\n");
+               break;
+            case CF_IMAGE_CMYK :
+               doc_puts(&doc, "/DeviceCMYK setcolorspace\n");
+               break;
+          }
 
-    while (strstr(line, "ENTER LANGUAGE") == NULL && strncmp(line, "%!", 2))
-      if ((len = (ssize_t)cupsFileGetLine(inputfp, line, sizeof(line))) == 0)
-        break;
+          doc_printf(&doc,
+                 "<<"
+                 "/ImageType 1"
+                 "/Width %d"
+                 "/Height %d"
+                 "/BitsPerComponent 8",
+                 xc1 - xc0 + 1, yc1 - yc0 + 1);
 
-    if (!strncmp(line, "%!", 2))
-      break;
+          switch (colorspace)
+         {
+           case CF_IMAGE_WHITE :
+                doc_puts(&doc, "/Decode[0 1]");
+               break;
+            case CF_IMAGE_RGB :
+                doc_puts(&doc, "/Decode[0 1 0 1 0 1]");
+               break;
+            case CF_IMAGE_CMYK :
+                doc_puts(&doc, "/Decode[0 1 0 1 0 1 0 1]");
+               break;
+          }
 
-    if ((len = (ssize_t)cupsFileGetLine(inputfp, line, sizeof(line))) == 0)
-      break;
-  }
+          doc_puts(&doc, "\n/DataSource currentfile/ASCII85Decode filter");
 
- /*
-  * Now see if the document conforms to the Adobe Document Structuring
-  * Conventions...
-  */
+          if (((xc1 - xc0 + 1) / xprint) < 100.0)
+            doc_puts(&doc, "/Interpolate true");
 
-  if (!strncmp(line, "%!PS-Adobe-", 11))
-  {
-   /*
-    * Yes, filter the document...
-    */
+          doc_puts(&doc, "/ImageMatrix[1 0 0 -1 0 1]>>image\n");
 
-    copy_dsc(&doc, data->ppd, line, len, sizeof(line));
-  }
-  else
-  {
-   /*
-    * No, display an error message and treat the file as if it contains
-    * a single page...
-    */
+          for (y = yc0, out_offset = 0; y <= yc1; y ++)
+          {
+            cfImageGetRow(img, xc0, y, xc1 - xc0 + 1, row + out_offset);
 
-    copy_non_dsc(&doc, data->ppd, line, len, sizeof(line));
-  }
+            out_length = (xc1 - xc0 + 1) * abs(colorspace) + out_offset;
+            out_offset = out_length & 3;
 
- /*
-  * Send %%EOF as needed...
-  */
+            ps_ascii85(&doc, row, out_length, y == yc1);
 
-  if (!doc.saw_eof)
-    fputs("%%EOF\n", outputfp);
+            if (out_offset > 0)
+              memcpy(row, row + out_length - out_offset, out_offset);
+          }
+       }
 
- /*
-  * End the job with the appropriate JCL command or CTRL-D...
-  */
+       doc_puts(&doc, "grestore\n");
+       write_labels(&doc, 0);
+       doc_puts(&doc, "grestore\n");
+       doc_puts(&doc, "showpage\n");
+      }
 
-  if (doc.emit_jcl)
-  {
-    if (data->ppd && data->ppd->jcl_end)
-      ppdEmitJCLEnd(data->ppd, outputfp);
-    else
-      fputc(0x04, outputfp);
-  }
+ canceled:
+  doc_puts(&doc, "%%EOF\n");
 
+  free(row);
+  
  /*
-  * Close files and remove the temporary file if needed...
+  * End the job with the appropriate JCL command or CTRL-D otherwise.
   */
 
-  if (doc.temp)
-  {
-    cupsFileClose(doc.temp);
-    unlink(doc.tempfile);
-  }
-
-  if (doc.pages)
+  if (emit_jcl)
   {
-    for (pageinfo = (pstops_page_t *)cupsArrayFirst(doc.pages);
-         pageinfo; pageinfo = (pstops_page_t *)cupsArrayNext(doc.pages))
-    {
-      if (pageinfo->label)
-       free(pageinfo->label);
-      if (pageinfo->num_options && pageinfo->options)
-       cupsFreeOptions(pageinfo->num_options, pageinfo->options);
-      free(pageinfo);
-    }
-    cupsArrayDelete(doc.pages);
-    doc.pages = NULL;
+    if (ppd && ppd->jcl_end)
+      ppdEmitJCLEnd(ppd, doc.outputfp);
+    else
+      doc_putc(&doc, 0x04);
   }
 
-  if(doc.inputPageRange)
-    { 
-      retry_wait:
-        if (waitpid (pstops_pid, &childStatus, 0) == -1) {
-          if (errno == EINTR)
-            goto retry_wait;
-          if (log) log(ld, CF_LOGLEVEL_ERROR,
-          "cfFilterPSToPS: Error while waiting for input_page_ranges to finish - %s.",
-          strerror(errno));
-        }
-        /* How did the sub-process terminate */
-    if (childStatus) {
-      if (WIFEXITED(childStatus)) {
-       /* Via exit() anywhere or return() in the main() function */
-       if (log) log(ld, CF_LOGLEVEL_ERROR,
-                    "cfFilterPSToPS: input-page-ranges filter (PID %d) stopped with status %d",
-                    pstops_pid, WEXITSTATUS(childStatus));
-      } else {
-       /* Via signal */
-       if (log) log(ld, CF_LOGLEVEL_ERROR,
-                    "cfFilterPSToPS: imput-page-ranges filter (PID %d) crashed on signal %d",
-                    pstops_pid, WTERMSIG(childStatus));
-      }
-      status=1;
-    } else {
-      if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                  "cfFilterPSToPS: input-page-ranges-filter (PID %d) exited with no errors.",
-                  pstops_pid);
-    }
-  }
+  if (log) log(ld, CF_LOGLEVEL_DEBUG,
+              "cfFilterImageToPS: Printing completed.", page);
 
-  cupsFileClose(inputfp);
-  close(inputfd);
+ /*
+  * Close files...
+  */
 
-  fclose(outputfp);
+  cfImageClose(img);
+  fclose(doc.outputfp);
   close(outputfd);
 
-  return (status);
+  return (0);
 }
 
 
@@ -681,7 +1980,7 @@ copy_bytes(pstops_doc_t *doc,              /* I - Document info */
 
     nleft -= (size_t)nbytes;
 
-    fwrite(buffer, 1, (size_t)nbytes, doc->outputfp);
+    doc_write(doc, buffer, (size_t)nbytes);
   }
 }
 
@@ -1060,7 +2359,7 @@ copy_dsc(pstops_doc_t *doc,               /* I - Document info */
            "PAGE: %d %d", doc->page,
            doc->slow_collate ? 1 : doc->copies);
 
-      fprintf(doc->outputfp, "%%%%Page: (filler) %d\n", doc->page);
+      doc_printf(doc, "%%%%Page: (filler) %d\n", doc->page);
     }
 
     start_nup(doc, doc->number_up, 0, doc->bounding_box);
@@ -1119,16 +2418,16 @@ copy_dsc(pstops_doc_t *doc,             /* I - Document info */
         * Send the trailer...
        */
 
-        fputs("%%Trailer\n", doc->outputfp);
-       fprintf(doc->outputfp, "%%%%Pages: %d\n", cupsArrayCount(doc->pages));
+        doc_puts(doc, "%%Trailer\n");
+       doc_printf(doc, "%%%%Pages: %d\n", cupsArrayCount(doc->pages));
        if (doc->number_up > 1 || doc->fit_to_page)
-         fprintf(doc->outputfp, "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
+         doc_printf(doc, "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
                 doc->PageLeft, doc->PageBottom, doc->PageRight, doc->PageTop);
        else
-         fprintf(doc->outputfp, "%%%%BoundingBox: %d %d %d %d\n",
+         doc_printf(doc, "%%%%BoundingBox: %d %d %d %d\n",
                 doc->new_bounding_box[0], doc->new_bounding_box[1],
                 doc->new_bounding_box[2], doc->new_bounding_box[3]);
-        fputs("%%EOF\n", doc->outputfp);
+        doc_puts(doc, "%%EOF\n");
 
        /*
         * Start a new document...
@@ -1137,7 +2436,7 @@ copy_dsc(pstops_doc_t *doc,               /* I - Document info */
         ppdEmitJCLEnd(ppd, doc->outputfp);
         ppdEmitJCL(ppd, doc->outputfp, doc->job_id, doc->user, doc->title);
 
-       fputs("%!PS-Adobe-3.0\n", doc->outputfp);
+       doc_puts(doc, "%!PS-Adobe-3.0\n");
 
        number = 0;
       }
@@ -1178,14 +2477,14 @@ copy_dsc(pstops_doc_t *doc,             /* I - Document info */
 
        if (doc->number_up > 1)
        {
-         fprintf(doc->outputfp, "%%%%Page: (%d) %d\n", number, number);
-         fprintf(doc->outputfp, "%%%%PageBoundingBox: %.0f %.0f %.0f %.0f\n",
+         doc_printf(doc, "%%%%Page: (%d) %d\n", number, number);
+         doc_printf(doc, "%%%%PageBoundingBox: %.0f %.0f %.0f %.0f\n",
                 doc->PageLeft, doc->PageBottom, doc->PageRight, doc->PageTop);
        }
        else
        {
-          fprintf(doc->outputfp, "%%%%Page: %s %d\n", pageinfo->label, number);
-         fprintf(doc->outputfp, "%%%%PageBoundingBox: %d %d %d %d\n",
+          doc_printf(doc, "%%%%Page: %s %d\n", pageinfo->label, number);
+         doc_printf(doc, "%%%%PageBoundingBox: %d %d %d %d\n",
                  pageinfo->bounding_box[0], pageinfo->bounding_box[1],
                  pageinfo->bounding_box[2], pageinfo->bounding_box[3]);
        }
@@ -1204,7 +2503,7 @@ copy_dsc(pstops_doc_t *doc,               /* I - Document info */
   */
 
   if (doc->use_ESPshowpage)
-    fputs("userdict/showpage/ESPshowpage load put\n", doc->outputfp);
+    doc_puts(doc, "userdict/showpage/ESPshowpage load put\n");
 
  /*
   * Write/copy the trailer...
@@ -1252,13 +2551,13 @@ copy_non_dsc(pstops_doc_t *doc,         /* I - Document info */
   * Then write a standard DSC comment section...
   */
 
-  fprintf(doc->outputfp, "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
+  doc_printf(doc, "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
          doc->PageLeft, doc->PageBottom, doc->PageRight, doc->PageTop);
 
   if (doc->slow_collate && doc->copies > 1)
-    fprintf(doc->outputfp, "%%%%Pages: %d\n", doc->copies);
+    doc_printf(doc, "%%%%Pages: %d\n", doc->copies);
   else
-    fputs("%%Pages: 1\n", doc->outputfp);
+    doc_puts(doc, "%%Pages: 1\n");
 
   write_text_comment(doc, "For", doc->user);
   write_text_comment(doc, "Title", doc->title);
@@ -1270,7 +2569,7 @@ copy_non_dsc(pstops_doc_t *doc,           /* I - Document info */
     * that are required...
     */
 
-    fprintf(doc->outputfp, "%%%%Requirements: numcopies(%d)%s%s\n", doc->copies,
+    doc_printf(doc, "%%%%Requirements: numcopies(%d)%s%s\n", doc->copies,
            doc->collate ? " collate" : "",
            doc->Duplex ? " duplex" : "");
 
@@ -1278,7 +2577,7 @@ copy_non_dsc(pstops_doc_t *doc,           /* I - Document info */
     * Apple uses RBI comments for various non-PPD options...
     */
 
-    fprintf(doc->outputfp, "%%RBINumCopies: %d\n", doc->copies);
+    doc_printf(doc, "%%RBINumCopies: %d\n", doc->copies);
   }
   else
   {
@@ -1287,36 +2586,36 @@ copy_non_dsc(pstops_doc_t *doc,         /* I - Document info */
     */
 
     if (doc->Duplex)
-      fputs("%%Requirements: duplex\n", doc->outputfp);
+      doc_puts(doc, "%%Requirements: duplex\n");
 
    /*
     * Apple uses RBI comments for various non-PPD options...
     */
 
-    fputs("%RBINumCopies: 1\n", doc->outputfp);
+    doc_puts(doc, "%RBINumCopies: 1\n");
   }
 
-  fputs("%%EndComments\n", doc->outputfp);
+  doc_puts(doc, "%%EndComments\n");
 
  /*
   * Then the prolog...
   */
 
-  fputs("%%BeginProlog\n", doc->outputfp);
+  doc_puts(doc, "%%BeginProlog\n");
 
   do_prolog(doc, ppd);
 
-  fputs("%%EndProlog\n", doc->outputfp);
+  doc_puts(doc, "%%EndProlog\n");
 
  /*
   * Then the setup section...
   */
 
-  fputs("%%BeginSetup\n", doc->outputfp);
+  doc_puts(doc, "%%BeginSetup\n");
 
   do_setup(doc, ppd);
 
-  fputs("%%EndSetup\n", doc->outputfp);
+  doc_puts(doc, "%%EndSetup\n");
 
  /*
   * Finally, embed a copy of the file inside a %%Page...
@@ -1326,31 +2625,31 @@ copy_non_dsc(pstops_doc_t *doc,         /* I - Document info */
     log(ld, CF_LOGLEVEL_CONTROL,
        "PAGE: 1 %d", doc->temp ? 1 : doc->copies);
 
-  fputs("%%Page: 1 1\n", doc->outputfp);
-  fputs("%%BeginPageSetup\n", doc->outputfp);
+  doc_puts(doc, "%%Page: 1 1\n");
+  doc_puts(doc, "%%BeginPageSetup\n");
   ppdEmit(ppd, doc->outputfp, PPD_ORDER_PAGE);
-  fputs("%%EndPageSetup\n", doc->outputfp);
-  fputs("%%BeginDocument: nondsc\n", doc->outputfp);
+  doc_puts(doc, "%%EndPageSetup\n");
+  doc_puts(doc, "%%BeginDocument: nondsc\n");
 
-  fwrite(line, (size_t)linelen, 1, doc->outputfp);
+  doc_write(doc, line, (size_t)linelen);
 
   if (doc->temp)
     cupsFileWrite(doc->temp, line, (size_t)linelen);
 
   while ((bytes = cupsFileRead(doc->inputfp, buffer, sizeof(buffer))) > 0)
   {
-    fwrite(buffer, 1, (size_t)bytes, doc->outputfp);
+    doc_write(doc, buffer, (size_t)bytes);
 
     if (doc->temp)
       cupsFileWrite(doc->temp, buffer, (size_t)bytes);
   }
 
-  fputs("%%EndDocument\n", doc->outputfp);
+  doc_puts(doc, "%%EndDocument\n");
 
   if (doc->use_ESPshowpage)
   {
     write_labels_outputfile_only(doc, doc->Orientation);
-    fputs("ESPshowpage\n", doc->outputfp);
+    doc_puts(doc, "ESPshowpage\n");
   }
 
   if (doc->temp && (!iscanceled || !iscanceled(icd)))
@@ -1380,20 +2679,20 @@ copy_non_dsc(pstops_doc_t *doc,         /* I - Document info */
        log(ld, CF_LOGLEVEL_CONTROL,
            "PAGE: 1 1");
 
-      fprintf(doc->outputfp, "%%%%Page: %d %d\n", copy + 1, copy + 1);
-      fputs("%%BeginPageSetup\n", doc->outputfp);
+      doc_printf(doc, "%%%%Page: %d %d\n", copy + 1, copy + 1);
+      doc_puts(doc, "%%BeginPageSetup\n");
       ppdEmit(ppd, doc->outputfp, PPD_ORDER_PAGE);
-      fputs("%%EndPageSetup\n", doc->outputfp);
-      fputs("%%BeginDocument: nondsc\n", doc->outputfp);
+      doc_puts(doc, "%%EndPageSetup\n");
+      doc_puts(doc, "%%BeginDocument: nondsc\n");
 
       copy_bytes(doc, 0, 0);
 
-      fputs("%%EndDocument\n", doc->outputfp);
+      doc_puts(doc, "%%EndDocument\n");
 
       if (doc->use_ESPshowpage)
       {
        write_labels_outputfile_only(doc, doc->Orientation);
-        fputs("ESPshowpage\n", doc->outputfp);
+        doc_puts(doc, "ESPshowpage\n");
       }
     }
   }
@@ -1403,7 +2702,7 @@ copy_non_dsc(pstops_doc_t *doc,           /* I - Document info */
   */
 
   if (doc->use_ESPshowpage)
-    fputs("userdict/showpage/ESPshowpage load put\n", doc->outputfp);
+    doc_puts(doc, "userdict/showpage/ESPshowpage load put\n");
 }
 
 
@@ -1707,14 +3006,14 @@ copy_page(pstops_doc_t *doc,            /* I - Document info */
 
     if (doc->number_up > 1)
     {
-      fprintf(doc->outputfp, "%%%%Page: (%d) %d\n", doc->page, doc->page);
-      fprintf(doc->outputfp, "%%%%PageBoundingBox: %.0f %.0f %.0f %.0f\n",
+      doc_printf(doc, "%%%%Page: (%d) %d\n", doc->page, doc->page);
+      doc_printf(doc, "%%%%PageBoundingBox: %.0f %.0f %.0f %.0f\n",
              doc->PageLeft, doc->PageBottom, doc->PageRight, doc->PageTop);
     }
     else
     {
-      fprintf(doc->outputfp, "%%%%Page: %s %d\n", pageinfo->label, doc->page);
-      fprintf(doc->outputfp, "%%%%PageBoundingBox: %d %d %d %d\n",
+      doc_printf(doc, "%%%%Page: %s %d\n", pageinfo->label, doc->page);
+      doc_printf(doc, "%%%%PageBoundingBox: %d %d %d %d\n",
              pageinfo->bounding_box[0], pageinfo->bounding_box[1],
              pageinfo->bounding_box[2], pageinfo->bounding_box[3]);
     }
@@ -2051,7 +3350,7 @@ copy_trailer(pstops_doc_t *doc,           /* I - Document info */
 
   (void)ppd;
 
-  fputs("%%Trailer\n", doc->outputfp);
+  doc_puts(doc, "%%Trailer\n");
 
   while (linelen > 0)
   {
@@ -2060,7 +3359,7 @@ copy_trailer(pstops_doc_t *doc,           /* I - Document info */
     else if (strncmp(line, "%%Trailer", 9) &&
              strncmp(line, "%%Pages:", 8) &&
              strncmp(line, "%%BoundingBox:", 14))
-      fwrite(line, 1, (size_t)linelen, doc->outputfp);
+      doc_write(doc, line, (size_t)linelen);
 
     linelen = (ssize_t)cupsFileGetLine(doc->inputfp, line, linesize);
   }
@@ -2068,12 +3367,12 @@ copy_trailer(pstops_doc_t *doc,         /* I - Document info */
   if (log) log(ld, CF_LOGLEVEL_DEBUG,
               "cfFilterPSToPS: Wrote %d pages...", number);
 
-  fprintf(doc->outputfp, "%%%%Pages: %d\n", number);
+  doc_printf(doc, "%%%%Pages: %d\n", number);
   if (doc->number_up > 1 || doc->fit_to_page)
-    fprintf(doc->outputfp, "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
+    doc_printf(doc, "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
            doc->PageLeft, doc->PageBottom, doc->PageRight, doc->PageTop);
   else
-    fprintf(doc->outputfp, "%%%%BoundingBox: %d %d %d %d\n",
+    doc_printf(doc, "%%%%BoundingBox: %d %d %d %d\n",
            doc->new_bounding_box[0], doc->new_bounding_box[1],
            doc->new_bounding_box[2], doc->new_bounding_box[3]);
 
@@ -2184,23 +3483,7 @@ do_setup(pstops_doc_t *doc,              /* I - Document information */
   * Make sure we have rectclip and rectstroke procedures of some sort...
   */
 
-  doc_puts(doc,
-           "% x y w h ESPrc - Clip to a rectangle.\n"
-          "userdict/ESPrc/rectclip where{pop/rectclip load}\n"
-          "{{newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
-          "neg 0 rlineto closepath clip newpath}bind}ifelse put\n");
-
-  doc_puts(doc,
-           "% x y w h ESPrf - Fill a rectangle.\n"
-          "userdict/ESPrf/rectfill where{pop/rectfill load}\n"
-          "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
-          "neg 0 rlineto closepath fill grestore}bind}ifelse put\n");
-
-  doc_puts(doc,
-           "% x y w h ESPrs - Stroke a rectangle.\n"
-          "userdict/ESPrs/rectstroke where{pop/rectstroke load}\n"
-          "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
-          "neg 0 rlineto closepath stroke grestore}bind}ifelse put\n");
+  write_common(doc);
 
  /*
   * Write the page and label prologs...
@@ -2262,6 +3545,22 @@ doc_printf(pstops_doc_t *doc,            /* I - Document information */
 }
 
 
+/*
+ * 'doc_putc()' - Send a single character to the output file and/or the
+ *                temp file.
+ *
+ * This function should be used for all page-level output that is affected
+ * by ordering, collation, etc.
+ */
+
+static void
+doc_putc(pstops_doc_t *doc,            /* I - Document information */
+         const char   c)               /* I - Character to send */
+{
+  doc_write(doc, &c, 1);
+}
+
+
 /*
  * 'doc_puts()' - Send a nul-terminated string to the output file and/or the
  *                temp file.
@@ -2517,6 +3816,126 @@ parse_text(const char *start,           /* I - Start of text value */
 }
 
 
+/*
+ * 'ps_hex()' - Print binary data as a series of hexadecimal numbers.
+ */
+
+static void
+ps_hex(pstops_doc_t *doc,
+       cf_ib_t *data,                  /* I - Data to print */
+       int       length,               /* I - Number of bytes to print */
+       int       last_line)            /* I - Last line of raster data? */
+{
+  static int   col = 0;                /* Current column */
+  static char  *hex = "0123456789ABCDEF";
+                                       /* Hex digits */
+
+
+  while (length > 0)
+  {
+   /*
+    * Put the hex chars out to the file; note that we don't use fprintf()
+    * for speed reasons...
+    */
+
+    doc_putc(doc, hex[*data >> 4]);
+    doc_putc(doc, hex[*data & 15]);
+
+    data ++;
+    length --;
+
+    col += 2;
+    if (col > 78)
+    {
+      doc_putc(doc, '\n');
+      col = 0;
+    }
+  }
+
+  if (last_line && col)
+  {
+    doc_putc(doc, '\n');
+    col = 0;
+  }
+}
+
+
+/*
+ * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
+ */
+
+static void
+ps_ascii85(pstops_doc_t *doc,
+          cf_ib_t *data,               /* I - Data to print */
+          int       length,            /* I - Number of bytes to print */
+          int       last_line)         /* I - Last line of raster data? */
+{
+  unsigned     b;                      /* Binary data word */
+  unsigned char        c[5];                   /* ASCII85 encoded chars */
+  static int   col = 0;                /* Current column */
+
+
+  while (length > 3)
+  {
+    b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
+
+    if (b == 0)
+    {
+      doc_putc(doc, 'z');
+      col ++;
+    }
+    else
+    {
+      c[4] = (b % 85) + '!';
+      b /= 85;
+      c[3] = (b % 85) + '!';
+      b /= 85;
+      c[2] = (b % 85) + '!';
+      b /= 85;
+      c[1] = (b % 85) + '!';
+      b /= 85;
+      c[0] = b + '!';
+
+      doc_write(doc, (const char *)c, 5);
+      col += 5;
+    }
+
+    data += 4;
+    length -= 4;
+
+    if (col >= 75)
+    {
+      doc_putc(doc, '\n');
+      col = 0;
+    }
+  }
+
+  if (last_line)
+  {
+    if (length > 0)
+    {
+      memset(data + length, 0, 4 - length);
+      b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
+
+      c[4] = (b % 85) + '!';
+      b /= 85;
+      c[3] = (b % 85) + '!';
+      b /= 85;
+      c[2] = (b % 85) + '!';
+      b /= 85;
+      c[1] = (b % 85) + '!';
+      b /= 85;
+      c[0] = b + '!';
+
+      doc_write(doc, (const char *)c, length + 1);
+    }
+
+    doc_puts(doc, "~>\n");
+    col = 0;
+  }
+}
+
+
 /*
  * 'set_pstops_options()' - Set pstops options.
  */
@@ -2579,7 +3998,7 @@ set_pstops_options(
   /* Set some common values */
   cfFilterSetCommonOptions(ppd, num_options, options, 1,
                         &doc->Orientation, &doc->Duplex,
-                        &doc->LanguageLevel, &doc->ColorDevice,
+                        &doc->LanguageLevel, &doc->Color,
                         &doc->PageLeft, &doc->PageRight,
                         &doc->PageTop, &doc->PageBottom,
                         &doc->PageWidth, &doc->PageLength,
@@ -3456,6 +4875,31 @@ start_nup(pstops_doc_t *doc,             /* I - Document information */
 }
 
 
+/*
+ * 'write_common()' - Write common procedures...
+ */
+
+void
+write_common(pstops_doc_t *doc)
+{
+  doc_puts(doc,
+           "% x y w h ESPrc - Clip to a rectangle.\n"
+          "userdict/ESPrc/rectclip where{pop/rectclip load}\n"
+          "{{newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
+          "neg 0 rlineto closepath clip newpath}bind}ifelse put\n");
+  doc_puts(doc,
+           "% x y w h ESPrf - Fill a rectangle.\n"
+          "userdict/ESPrf/rectfill where{pop/rectfill load}\n"
+          "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
+          "neg 0 rlineto closepath fill grestore}bind}ifelse put\n");
+  doc_puts(doc,
+           "% x y w h ESPrs - Stroke a rectangle.\n"
+          "userdict/ESPrs/rectstroke where{pop/rectstroke load}\n"
+          "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
+          "neg 0 rlineto closepath stroke grestore}bind}ifelse put\n");
+}
+
+
 /*
  * 'write_label_prolog()' - Write the prolog with the classification
  *                          and page label.
@@ -3636,7 +5080,7 @@ write_labels_outputfile_only(pstops_doc_t *doc,/* I - Document information */
        length;                         /* Length of page */
 
 
-  fputs("gsave\n", doc->outputfp);
+  doc_puts(doc, "gsave\n");
 
   if ((orient ^ doc->Orientation) & 1)
   {
@@ -3652,19 +5096,19 @@ write_labels_outputfile_only(pstops_doc_t *doc,/* I - Document information */
   switch (orient & 3)
   {
     case 1 : /* Landscape */
-        fprintf(doc->outputfp, "%.1f 0.0 translate 90 rotate\n", length);
+        doc_printf(doc, "%.1f 0.0 translate 90 rotate\n", length);
         break;
     case 2 : /* Reverse Portrait */
-        fprintf(doc->outputfp, "%.1f %.1f translate 180 rotate\n",
+        doc_printf(doc, "%.1f %.1f translate 180 rotate\n",
                width, length);
         break;
     case 3 : /* Reverse Landscape */
-        fprintf(doc->outputfp, "0.0 %.1f translate -90 rotate\n", width);
+        doc_printf(doc, "0.0 %.1f translate -90 rotate\n", width);
         break;
   }
 
-  fputs("ESPwl\n", doc->outputfp);
-  fputs("grestore\n", doc->outputfp);
+  doc_puts(doc, "ESPwl\n");
+  doc_puts(doc, "grestore\n");
 }
 
 
@@ -3767,7 +5211,7 @@ write_text_comment(pstops_doc_t *doc,     /* I - Document */
   * in the Adobe Document Structuring Conventions specification.
   */
 
-  fprintf(doc->outputfp, "%%%%%s: (", name);
+  doc_printf(doc, "%%%%%s: (", name);
   len = 5 + strlen(name);
 
   while (*value)
@@ -3781,7 +5225,7 @@ write_text_comment(pstops_doc_t *doc,     /* I - Document */
       if (len >= 251)                  /* Keep line < 254 chars */
         break;
 
-      fprintf(doc->outputfp, "\\%03o", *value & 255);
+      doc_printf(doc, "\\%03o", *value & 255);
       len += 4;
     }
     else if (*value == '\\')
@@ -3793,8 +5237,8 @@ write_text_comment(pstops_doc_t *doc,     /* I - Document */
       if (len >= 253)                  /* Keep line < 254 chars */
         break;
 
-      fputc('\\', doc->outputfp);
-      fputc('\\', doc->outputfp);
+      doc_putc(doc, '\\');
+      doc_putc(doc, '\\');
       len += 2;
     }
     else
@@ -3806,12 +5250,12 @@ write_text_comment(pstops_doc_t *doc,   /* I - Document */
       if (len >= 254)                  /* Keep line < 254 chars */
         break;
 
-      fputc(*value, doc->outputfp);
+      doc_putc(doc, *value);
       len ++;
     }
 
     value ++;
   }
 
-  fputs(")\n", doc->outputfp);
+  doc_puts(doc, ")\n");
 }
diff --git a/cupsfilters/imagetops.c b/cupsfilters/imagetops.c
deleted file mode 100644 (file)
index aec05d0..0000000
+++ /dev/null
@@ -1,1735 +0,0 @@
-/*
- *   Image file to PostScript filter function for cups-filters.
- *
- *   Copyright 2007-2011 by Apple Inc.
- *   Copyright 1993-2007 by Easy Software Products.
- *
- *   These coded instructions, statements, and computer programs are the
- *   property of Apple Inc. and are protected by Federal copyright
- *   law.  Distribution and use rights are outlined in the file "LICENSE.txt"
- *   which should have been included with this file.  If this file is
- *   file is missing or damaged, see the license at "http://www.cups.org/".
- *
- *   This file is subject to the Apple OS-Developed Software exception.
- *
- * Contents:
- *
- *   cfFilterImageToPS()        - imagetops filter function
- *   WriteCommon()      - Write common procedures...
- *   WriteLabelProlog() - Write the prolog with the classification
- *                        and page label.
- *   WriteLabels()      - Write the actual page labels.
- *   WriteTextComment() - Write a DSC comment.
- *   ps_hex()           - Print binary data as a series of hexadecimal numbers.
- *   ps_ascii85()       - Print binary data as a series of base-85 numbers.
- */
-
-/*
- * Include necessary headers...
- */
-
-#include <cupsfilters/filter.h>
-#include <cupsfilters/image.h>
-#include <cupsfilters/raster.h>
-#include <cupsfilters/image-private.h>
-#include <math.h>
-#include <signal.h>
-#include <string.h>
-#include <errno.h>
-
-
-/*
- * Types...
- */
-
-typedef struct {                       /**** Document information ****/
-  int          Orientation,            /* 0 = portrait, 1 = landscape, etc. */
-               Duplex,                 /* Duplexed? */
-               LanguageLevel,          /* Language level of printer */
-               Color;                  /* Print in color? */
-  float        PageLeft,               /* Left margin */
-               PageRight,              /* Right margin */
-               PageBottom,             /* Bottom margin */
-               PageTop,                /* Top margin */
-               PageWidth,              /* Total page width */
-               PageLength;             /* Total page length */
-  FILE         *outputfp;
-} imagetops_doc_t;
-
-
-/*
- * Local functions...
- */
-
-static void    WriteCommon(imagetops_doc_t *doc);
-static void    WriteLabelProlog(imagetops_doc_t *doc,
-                                const char *label, float bottom,
-                                float top, float width);
-static void    WriteLabels(imagetops_doc_t *doc, int orient);
-static void    WriteTextComment(imagetops_doc_t *doc,
-                                const char *name, const char *value);
-static void    ps_hex(FILE *outputfp, cf_ib_t *, int, int);
-static void    ps_ascii85(FILE *outputfp, cf_ib_t *, int, int);
-
-
-/*
- * 'cfFilterImageToPS()' - Filter function to convert many common image file
- *                 formats into PostScript
- */
-
-int                             /* O - Error status */
-cfFilterImageToPS(int inputfd,         /* I - File descriptor input stream */
-         int outputfd,        /* I - File descriptor output stream */
-         int inputseekable,   /* I - Is input stream seekable? (unused) */
-         cf_filter_data_t *data, /* I - Job and printer data */
-         void *parameters)    /* I - Filter-specific parameters (unused) */
-{
-  imagetops_doc_t      doc;            /* Document information */
-  cf_image_t   *img;                   /* Image to print */
-  float                xprint,                 /* Printable area */
-               yprint,
-               xinches,                /* Total size in inches */
-               yinches;
-  float                xsize,                  /* Total size in points */
-               ysize,
-               xsize2,
-               ysize2;
-  float                aspect;                 /* Aspect ratio */
-  int          xpages,                 /* # x pages */
-               ypages,                 /* # y pages */
-               xpage,                  /* Current x page */
-               ypage,                  /* Current y page */
-               page;                   /* Current page number */
-  int          xc0, yc0,                       /* Corners of the page in image coords */
-               xc1, yc1;
-  cf_ib_t      *row;                   /* Current row */
-  int          y;                      /* Current Y coordinate in image */
-  int          colorspace;             /* Output colorspace */
-  int          out_offset,             /* Offset into output buffer */
-               out_length;             /* Length of output buffer */
-  ppd_file_t   *ppd;                   /* PPD file */
-  ppd_choice_t *choice;                /* PPD option choice */
-  int          num_options;            /* Number of print options */
-  cups_option_t        *options;               /* Print options */
-  const char   *val;                   /* Option value */
-  int          slowcollate;            /* Collate copies the slow way */
-  float                g;                      /* Gamma correction value */
-  float                b;                      /* Brightness factor */
-  float                zoom;                   /* Zoom facter */
-  int          xppi, yppi;             /* Pixels-per-inch */
-  int          hue, sat;               /* Hue and saturation adjustment */
-  int          realcopies,             /* Real copies being printed */
-               emit_jcl;               /* Emit JCL? */
-  float                left, top;              /* Left and top of image */
-  time_t       curtime;                /* Current time */
-  struct tm    *curtm;                 /* Current date */
-  char         curdate[255];           /* Current date string */
-  int          fillprint = 0;          /* print-scaling = fill */
-  int          cropfit = 0;            /* -o crop-to-fit = true */
-  cups_page_header2_t h;                /* CUPS Raster page header, to */
-                                        /* accommodate results of command */
-                                        /* line parsing for PPD-less queue */
-  int          Flip,                   /* Flip/mirror pages */
-               XPosition,              /* Horizontal position on page */
-               YPosition,              /* Vertical position on page */
-               Collate,                /* Collate copies? */
-               Copies;                 /* Number of copies */
-  char         tempfile[1024];         /* Name of file to print */
-  FILE          *inputfp;              /* Input file */
-  int           fd;                    /* File descriptor for temp file */
-  char          buf[BUFSIZ];
-  int           bytes;
-  cf_logfunc_t log = data->logfunc;
-  void          *ld = data->logdata;
-  cf_filter_iscanceledfunc_t iscanceled = data->iscanceledfunc;
-  void          *icd = data->iscanceleddata;
-
-
- /*
-  * Make sure status messages are not buffered...
-  */
-
-  setbuf(stderr, NULL);
-
- /*
-  * Ignore broken pipe signals...
-  */
-
-  signal(SIGPIPE, SIG_IGN);
-
- /*
-  * Initialize data structure
-  */
-
-  Flip = 0;
-  XPosition = 0;
-  YPosition = 0;
-  Collate = 0;
-  Copies = 1;
-
- /*
-  * Open the input data stream specified by the inputfd ...
-  */
-
-  if ((inputfp = fdopen(inputfd, "r")) == NULL)
-  {
-    if (!iscanceled || !iscanceled(icd))
-    {
-      if (log) log(ld, CF_LOGLEVEL_ERROR,
-                  "cfFilterImageToPS: Unable to open input data stream.");
-    }
-
-    return (1);
-  }
-
- /*
-  * Copy input into temporary file if needed ...
-  */
-
-  if (!inputseekable) {
-    if ((fd = cupsTempFd(tempfile, sizeof(tempfile))) < 0)
-    {
-      if (log) log(ld, CF_LOGLEVEL_ERROR,
-                  "cfFilterImageToPS: Unable to copy input: %s",
-                  strerror(errno));
-      return (1);
-    }
-
-    if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                "cfFilterImageToPS: Copying input to temp file \"%s\"",
-                tempfile);
-
-    while ((bytes = fread(buf, 1, sizeof(buf), inputfp)) > 0)
-      bytes = write(fd, buf, bytes);
-
-    fclose(inputfp);
-    close(fd);
-
-   /*
-    * Open the temporary file to read it instead of the original input ...
-    */
-
-    if ((inputfp = fopen(tempfile, "r")) == NULL)
-    {
-      if (!iscanceled || !iscanceled(icd))
-      {
-       if (log) log(ld, CF_LOGLEVEL_ERROR,
-                    "cfFilterImageToPS: Unable to open temporary file.");
-      }
-
-      unlink(tempfile);
-      return (1);
-    }
-  }
-
- /*
-  * Open the output data stream specified by the outputfd...
-  */
-
-  if ((doc.outputfp = fdopen(outputfd, "w")) == NULL)
-  {
-    if (!iscanceled || !iscanceled(icd))
-    {
-      if (log) log(ld, CF_LOGLEVEL_ERROR,
-                  "cfFilterImageToPS: Unable to open output data stream.");
-    }
-
-    fclose(inputfp);
-
-    if (!inputseekable)
-      unlink(tempfile);
-    return (1);
-  }
-
- /*
-  * Process command-line options and write the prolog...
-  */
-
-  zoom = 1.0;
-  xppi = 0;
-  yppi = 0;
-  hue  = 0;
-  sat  = 100;
-  g    = 1.0;
-  b    = 1.0;
-
-  Copies = data->copies;
-
- /*
-  * Option list...
-  */
-
-  options     = data->options;
-  num_options = data->num_options;
-
- /*
-  * Process job options...
-  */
-
-  ppd = data->ppd;
-  cfFilterSetCommonOptions(ppd, num_options, options, 0,
-                        &doc.Orientation, &doc.Duplex,
-                        &doc.LanguageLevel, &doc.Color,
-                        &doc.PageLeft, &doc.PageRight,
-                        &doc.PageTop, &doc.PageBottom,
-                        &doc.PageWidth, &doc.PageLength,
-                        log, ld);
-
-  /* The cfFilterSetCommonOptions() does not set doc.Color
-     according to option settings (user's demand for color/gray),
-     so we parse the options and set the mode here */
-  cfRasterParseIPPOptions(&h, data, 0, 1);
-  if (doc.Color)
-    doc.Color = h.cupsNumColors <= 1 ? 0 : 1;
-  if (!ppd) {
-    /* Without PPD use also the other findings of cfRasterParseIPPOptions() */
-    doc.Orientation = h.Orientation;
-    doc.Duplex = h.Duplex;
-    doc.LanguageLevel = 2;
-    doc.PageWidth = h.cupsPageSize[0] != 0.0 ? h.cupsPageSize[0] :
-      (float)h.PageSize[0];
-    doc.PageLength = h.cupsPageSize[1] != 0.0 ? h.cupsPageSize[1] :
-      (float)h.PageSize[1];
-    doc.PageLeft = h.cupsImagingBBox[0] != 0.0 ? h.cupsImagingBBox[0] :
-      (float)h.ImagingBoundingBox[0];
-    doc.PageBottom = h.cupsImagingBBox[1] != 0.0 ? h.cupsImagingBBox[1] :
-      (float)h.ImagingBoundingBox[1];
-    doc.PageRight = h.cupsImagingBBox[2] != 0.0 ? h.cupsImagingBBox[2] :
-      (float)h.ImagingBoundingBox[2];
-    doc.PageTop = h.cupsImagingBBox[3] != 0.0 ? h.cupsImagingBBox[3] :
-      (float)h.ImagingBoundingBox[3];
-    Flip = h.MirrorPrint ? 1 : 0;
-    Collate = h.Collate ? 1 : 0;
-    Copies = h.NumCopies;
-  }
-
-  if ((val = cupsGetOption("multiple-document-handling", num_options, options)) != NULL)
-  {
-   /*
-    * This IPP attribute is unnecessarily complicated...
-    *
-    *   single-document, separate-documents-collated-copies, and
-    *   single-document-new-sheet all require collated copies.
-    *
-    *   separate-documents-uncollated-copies allows for uncollated copies.
-    */
-
-    Collate = strcasecmp(val, "separate-documents-uncollated-copies") != 0;
-  }
-
-  if ((val = cupsGetOption("Collate", num_options, options)) != NULL &&
-      strcasecmp(val, "True") == 0)
-    Collate = 1;
-
-  if ((val = cupsGetOption("gamma", num_options, options)) != NULL)
-  {
-   /*
-    * Get gamma value from 1 to 10000...
-    */
-
-    g = atoi(val) * 0.001f;
-
-    if (g < 0.001f)
-      g = 0.001f;
-    else if (g > 10.0f)
-      g = 10.0f;
-  }
-
-  if ((val = cupsGetOption("brightness", num_options, options)) != NULL)
-  {
-   /*
-    * Get brightness value from 10 to 1000.
-    */
-
-    b = atoi(val) * 0.01f;
-
-    if (b < 0.1f)
-      b = 0.1f;
-    else if (b > 10.0f)
-      b = 10.0f;
-  }
-
-  if ((val = cupsGetOption("ppi", num_options, options)) != NULL)
-  {
-    sscanf(val, "%d", &xppi);
-    yppi = xppi;
-    zoom = 0.0;
-  }
-
-  if ((val = cupsGetOption("position", num_options, options)) != NULL)
-  {
-    if (strcasecmp(val, "center") == 0)
-    {
-      XPosition = 0;
-      YPosition = 0;
-    }
-    else if (strcasecmp(val, "top") == 0)
-    {
-      XPosition = 0;
-      YPosition = 1;
-    }
-    else if (strcasecmp(val, "left") == 0)
-    {
-      XPosition = -1;
-      YPosition = 0;
-    }
-    else if (strcasecmp(val, "right") == 0)
-    {
-      XPosition = 1;
-      YPosition = 0;
-    }
-    else if (strcasecmp(val, "top-left") == 0)
-    {
-      XPosition = -1;
-      YPosition = 1;
-    }
-    else if (strcasecmp(val, "top-right") == 0)
-    {
-      XPosition = 1;
-      YPosition = 1;
-    }
-    else if (strcasecmp(val, "bottom") == 0)
-    {
-      XPosition = 0;
-      YPosition = -1;
-    }
-    else if (strcasecmp(val, "bottom-left") == 0)
-    {
-      XPosition = -1;
-      YPosition = -1;
-    }
-    else if (strcasecmp(val, "bottom-right") == 0)
-    {
-      XPosition = 1;
-      YPosition = -1;
-    }
-  }
-
-  if ((val = cupsGetOption("saturation", num_options, options)) != NULL)
-    sat = atoi(val);
-
-  if ((val = cupsGetOption("hue", num_options, options)) != NULL)
-    hue = atoi(val);
-
-  if ((choice = ppdFindMarkedChoice(ppd, "MirrorPrint")) != NULL)
-  {
-    val = choice->choice;
-    choice->marked = 0;
-  }
-  else
-    val = cupsGetOption("mirror", num_options, options);
-
-  if (val && (!strcasecmp(val, "true") || !strcasecmp(val, "on") ||
-              !strcasecmp(val, "yes")))
-    Flip = 1;
-
-  if ((val = cupsGetOption("emit-jcl", num_options, options)) != NULL &&
-      (!strcasecmp(val, "false") || !strcasecmp(val, "off") ||
-       !strcasecmp(val, "no") || !strcmp(val, "0")))
-    emit_jcl = 0;
-  else
-    emit_jcl = 1;
-
- /*
-  * Open the input image to print...
-  */
-
-  colorspace = doc.Color ? CF_IMAGE_RGB_CMYK : CF_IMAGE_WHITE;
-
-  img = cfImageOpenFP(inputfp, colorspace, CF_IMAGE_WHITE, sat, hue, NULL);
-  if (img != NULL) {
-
-    int margin_defined = 0;
-    int fidelity = 0;
-    int document_large = 0;
-
-    if (ppd && (ppd->custom_margins[0] || ppd->custom_margins[1] ||
-               ppd->custom_margins[2] || ppd->custom_margins[3]))
-      /* In case of custom margins */
-      margin_defined = 1;
-    if (doc.PageLength != doc.PageTop - doc.PageBottom ||
-       doc.PageWidth != doc.PageRight - doc.PageLeft)
-      margin_defined = 1;
-
-    if((val = cupsGetOption("ipp-attribute-fidelity", num_options, options))
-       != NULL)
-    {
-      if(!strcasecmp(val, "true") || !strcasecmp(val, "yes") ||
-        !strcasecmp(val, "on")) {
-       fidelity = 1;
-      }
-    }
-
-    float w = (float)cfImageGetWidth(img);
-    float h = (float)cfImageGetHeight(img);
-    float pw = doc.PageRight - doc.PageLeft;
-    float ph = doc.PageTop - doc.PageBottom;
-    int tempOrientation = doc.Orientation;
-    if ((val = cupsGetOption("orientation-requested", num_options, options)) !=
-       NULL)
-      tempOrientation = atoi(val);
-    else if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
-    {
-      if(!strcasecmp(val, "true") || !strcasecmp(val, "yes"))
-       tempOrientation = 4;
-    }
-    if (tempOrientation == 0) {
-      if (((pw > ph) && (w < h)) || ((pw < ph) && (w > h)))
-       tempOrientation = 4;
-    }
-    if (tempOrientation == 4 || tempOrientation == 5)
-    {
-      int tmp = pw;
-      pw = ph;
-      ph = tmp;
-    }
-    if (w * 72.0 / img->xppi > pw || h * 72.0 / img->yppi > ph)
-      document_large = 1;
-
-    if ((val = cupsGetOption("print-scaling", num_options, options)) != NULL)
-    {
-      if (!strcasecmp(val, "auto"))
-      {
-       if (fidelity || document_large) {
-         if (margin_defined)
-           zoom = 1.0;       // fit method
-         else
-           fillprint = 1;    // fill method
-       }
-       else
-         cropfit = 1;        // none method
-      }
-      else if (!strcasecmp(val, "auto-fit"))
-      {
-       if (fidelity || document_large)
-         zoom = 1.0;         // fit method
-       else
-         cropfit = 1;        // none method
-      }
-      else if (!strcasecmp(val, "fill"))
-       fillprint = 1;        // fill method
-      else if (!strcasecmp(val, "fit"))
-       zoom = 1.0;           // fitplot = 1 or fit method
-      else
-       cropfit = 1;            // none or crop-to-fit
-    }
-    else
-    {       // print-scaling is not defined, look for alternate options.
-      if ((val = cupsGetOption("scaling", num_options, options)) != NULL)
-       zoom = atoi(val) * 0.01;
-      else if (((val =
-                cupsGetOption("fit-to-page", num_options, options)) != NULL) ||
-              ((val = cupsGetOption("fitplot", num_options, options)) != NULL))
-      {
-       if (!strcasecmp(val, "yes") || !strcasecmp(val, "on") ||
-           !strcasecmp(val, "true"))
-         zoom = 1.0;
-       else
-         zoom = 0.0;
-      }
-      else if ((val = cupsGetOption("natural-scaling", num_options, options)) !=
-              NULL)
-       zoom = 0.0;
-
-      if ((val = cupsGetOption("fill", num_options,options)) != NULL)
-      {
-       if (!strcasecmp(val, "true") || !strcasecmp(val, "yes"))
-         fillprint = 1;
-      }
-
-      if ((val = cupsGetOption("crop-to-fit", num_options,options)) != NULL)
-      {
-       if (!strcasecmp(val, "true") || !strcasecmp(val, "yes"))
-         cropfit=1;
-      }
-    }
-    if (fillprint || cropfit)
-    {
-      /* For cropfit do the math without the unprintable margins to get correct
-         centering */
-      if (cropfit)
-      {
-       pw = doc.PageWidth;
-       ph = doc.PageLength;
-       doc.PageBottom = 0.0;
-       doc.PageTop = doc.PageLength;
-       doc.PageLeft = 0.0;
-       doc.PageRight = doc.PageWidth;
-      }
-      tempOrientation = doc.Orientation;
-      int flag = 3;
-      if ((val = cupsGetOption("orientation-requested", num_options,
-                              options)) != NULL)
-       tempOrientation = atoi(val);
-      else if ((val = cupsGetOption("landscape", num_options, options)) != NULL)
-      {
-       if (!strcasecmp(val,"true") || !strcasecmp(val,"yes"))
-         tempOrientation = 4;
-      }
-      if (tempOrientation > 0)
-      {
-       if (tempOrientation == 4 || tempOrientation == 5)
-       {
-         float temp = pw;
-         pw = ph;
-         ph = temp;
-         flag = 4;
-       }
-      }
-      if (tempOrientation==0)
-      { 
-       if (((pw > ph) && (w < h)) || ((pw < ph) && (w > h)))
-       {
-         int temp = pw;
-         pw = ph;
-         ph = temp;
-         flag = 4;
-       }
-      }
-      if (fillprint) {
-       float final_w, final_h;
-       if (w * ph / pw <= h) {
-         final_w = w;
-         final_h = w * ph / pw; 
-       }
-       else
-       {
-         final_w = h * pw / ph;
-         final_h = h;
-       }
-       float posw = (w - final_w) / 2, posh = (h - final_h) / 2;
-       posw = (1 + XPosition) * posw;
-       posh = (1 - YPosition) * posh;
-       cf_image_t *img2 = cfImageCrop(img, posw, posh, final_w, final_h);
-       cfImageClose(img);
-       img = img2;
-      }
-      else
-      {
-       float final_w = w, final_h = h;
-        if (w > pw * img->xppi / 72.0)
-          final_w = pw * img->xppi / 72.0;
-        if (h > ph * img->yppi / 72.0)
-          final_h = ph * img->yppi / 72.0;
-       float posw = (w - final_w) / 2, posh = (h - final_h) / 2;
-       posw = (1 + XPosition) * posw;
-       posh = (1 - YPosition) * posh;
-       cf_image_t *img2 = cfImageCrop(img, posw, posh, final_w, final_h);
-       cfImageClose(img);
-       img = img2;
-       if (flag == 4)
-       {
-         doc.PageBottom += (doc.PageLength - final_w * 72.0 / img->xppi) / 2;
-         doc.PageTop = doc.PageBottom + final_w * 72.0 / img->xppi;
-         doc.PageLeft += (doc.PageWidth - final_h * 72.0 / img->yppi) / 2;
-         doc.PageRight = doc.PageLeft + final_h * 72.0 / img->yppi;
-       }
-       else
-       {
-         doc.PageBottom += (doc.PageLength - final_h * 72.0 / img->yppi) / 2;
-         doc.PageTop = doc.PageBottom + final_h * 72.0 / img->yppi;
-         doc.PageLeft += (doc.PageWidth - final_w * 72.0 / img->xppi) / 2;
-         doc.PageRight = doc.PageLeft + final_w * 72.0 / img->xppi;
-       }
-       if (doc.PageBottom < 0) doc.PageBottom = 0;
-       if (doc.PageLeft < 0) doc.PageLeft = 0;
-      }
-    }
-  }
-
-  if (!inputseekable)
-    unlink(tempfile);
-
-  if (img == NULL)
-  {
-    if (log) log(ld, CF_LOGLEVEL_ERROR,
-                "cfFilterImageToPS: The print file could not be opened - %s",
-                strerror(errno));
-    return (1);
-  }
-
-  colorspace = cfImageGetColorSpace(img);
-
- /*
-  * Scale as necessary...
-  */
-
-  if (zoom == 0.0 && xppi == 0)
-  {
-    xppi = cfImageGetXPPI(img);
-    yppi = cfImageGetYPPI(img);
-  }
-
-  if (yppi == 0)
-    yppi = xppi;
-
-  if (log) log(ld, CF_LOGLEVEL_DEBUG,
-              "cfFilterImageToPS: Before scaling: xppi=%d, yppi=%d, zoom=%.2f",
-              xppi, yppi, zoom);
-
-  if (xppi > 0)
-  {
-   /*
-    * Scale the image as neccesary to match the desired pixels-per-inch.
-    */
-
-    if (doc.Orientation & 1)
-    {
-      xprint = (doc.PageTop - doc.PageBottom) / 72.0;
-      yprint = (doc.PageRight - doc.PageLeft) / 72.0;
-    }
-    else
-    {
-      xprint = (doc.PageRight - doc.PageLeft) / 72.0;
-      yprint = (doc.PageTop - doc.PageBottom) / 72.0;
-    }
-
-    if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                "cfFilterImageToPS: Before scaling: xprint=%.1f, yprint=%.1f",
-                xprint, yprint);
-
-    xinches = (float)cfImageGetWidth(img) / (float)xppi;
-    yinches = (float)cfImageGetHeight(img) / (float)yppi;
-
-    if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                "cfFilterImageToPS: Image size is %.1f x %.1f inches...",
-                xinches, yinches);
-
-    if ((val = cupsGetOption("natural-scaling", num_options, options)) != NULL)
-    {
-      xinches = xinches * atoi(val) / 100;
-      yinches = yinches * atoi(val) / 100;
-    }
-
-    if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
-        cupsGetOption("landscape", num_options, options) == NULL)
-    {
-     /*
-      * Rotate the image if it will fit landscape but not portrait...
-      */
-
-      if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                  "cfFilterImageToPS: Auto orientation...");
-
-      if ((xinches > xprint || yinches > yprint) &&
-          xinches <= yprint && yinches <= xprint)
-      {
-       /*
-       * Rotate the image as needed...
-       */
-
-       if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                    "cfFilterImageToPS: Using landscape orientation...");
-
-       doc.Orientation = (doc.Orientation + 1) & 3;
-       xsize       = yprint;
-       yprint      = xprint;
-       xprint      = xsize;
-      }
-    }
-  }
-  else
-  {
-   /*
-    * Scale percentage of page size...
-    */
-
-    xprint = (doc.PageRight - doc.PageLeft) / 72.0;
-    yprint = (doc.PageTop - doc.PageBottom) / 72.0;
-    aspect = (float)cfImageGetYPPI(img) / (float)cfImageGetXPPI(img);
-
-    if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                "cfFilterImageToPS: Before scaling: xprint=%.1f, yprint=%.1f",
-                xprint, yprint);
-
-    if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                "cfFilterImageToPS: cfImageGetXPPI(img) = %d, "
-                "cfImageGetYPPI(img) = %d, aspect = %f",
-                cfImageGetXPPI(img), cfImageGetYPPI(img), aspect);
-
-    xsize = xprint * zoom;
-    ysize = xsize * cfImageGetHeight(img) / cfImageGetWidth(img) / aspect;
-
-    if (ysize > (yprint * zoom))
-    {
-      ysize = yprint * zoom;
-      xsize = ysize * cfImageGetWidth(img) * aspect /
-       cfImageGetHeight(img);
-    }
-
-    xsize2 = yprint * zoom;
-    ysize2 = xsize2 * cfImageGetHeight(img) / cfImageGetWidth(img) /
-      aspect;
-
-    if (ysize2 > (xprint * zoom))
-    {
-      ysize2 = xprint * zoom;
-      xsize2 = ysize2 * cfImageGetWidth(img) * aspect /
-       cfImageGetHeight(img);
-    }
-
-    if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                "cfFilterImageToPS: Portrait size is %.2f x %.2f inches",
-                xsize, ysize);
-    if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                "cfFilterImageToPS: Landscape size is %.2f x %.2f inches",
-                xsize2, ysize2);
-
-    if (cupsGetOption("orientation-requested", num_options, options) == NULL &&
-        cupsGetOption("landscape", num_options, options) == NULL)
-    {
-     /*
-      * Choose the rotation with the largest area, but prefer
-      * portrait if they are equal...
-      */
-
-      if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                  "cfFilterImageToPS: Auto orientation...");
-
-      if ((xsize * ysize) < (xsize2 * xsize2))
-      {
-       /*
-       * Do landscape orientation...
-       */
-
-       if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                    "cfFilterImageToPS: Using landscape orientation...");
-
-       doc.Orientation = 1;
-       xinches     = xsize2;
-       yinches     = ysize2;
-       xprint      = (doc.PageTop - doc.PageBottom) / 72.0;
-       yprint      = (doc.PageRight - doc.PageLeft) / 72.0;
-      }
-      else
-      {
-       /*
-       * Do portrait orientation...
-       */
-
-       if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                    "cfFilterImageToPS: Using portrait orientation...");
-
-       doc.Orientation = 0;
-       xinches     = xsize;
-       yinches     = ysize;
-      }
-    }
-    else if (doc.Orientation & 1)
-    {
-      if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                  "cfFilterImageToPS: Using landscape orientation...");
-
-      xinches     = xsize2;
-      yinches     = ysize2;
-      xprint      = (doc.PageTop - doc.PageBottom) / 72.0;
-      yprint      = (doc.PageRight - doc.PageLeft) / 72.0;
-    }
-    else
-    {
-      if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                  "cfFilterImageToPS: Using portrait orientation...");
-
-      xinches     = xsize;
-      yinches     = ysize;
-      xprint      = (doc.PageRight - doc.PageLeft) / 72.0;
-      yprint      = (doc.PageTop - doc.PageBottom) / 72.0;
-    }
-  }
-
- /*
-  * Compute the number of pages to print and the size of the image on each
-  * page...
-  */
-
-  xpages = ceil(xinches / xprint);
-  ypages = ceil(yinches / yprint);
-
-  xprint = xinches / xpages;
-  yprint = yinches / ypages;
-
-  if (log) log(ld, CF_LOGLEVEL_DEBUG,
-              "cfFilterImageToPS: xpages = %dx%.2fin, ypages = %dx%.2fin",
-              xpages, xprint, ypages, yprint);
-
- /*
-  * Update the page size for custom sizes...
-  */
-
-  if ((choice = ppdFindMarkedChoice(ppd, "PageSize")) != NULL &&
-      strcasecmp(choice->choice, "Custom") == 0)
-  {
-    float      width,          /* New width in points */
-               length;         /* New length in points */
-    char       s[255];         /* New custom page size... */
-
-
-   /*
-    * Use the correct width and length for the current orientation...
-    */
-
-    if (doc.Orientation & 1)
-    {
-      width  = yprint * 72.0;
-      length = xprint * 72.0;
-    }
-    else
-    {
-      width  = xprint * 72.0;
-      length = yprint * 72.0;
-    }
-
-   /*
-    * Add margins to page size...
-    */
-
-    width  += ppd->custom_margins[0] + ppd->custom_margins[2];
-    length += ppd->custom_margins[1] + ppd->custom_margins[3];
-
-   /*
-    * Enforce minimums...
-    */
-
-    if (width < ppd->custom_min[0])
-      width = ppd->custom_min[0];
-
-    if (length < ppd->custom_min[1])
-      length = ppd->custom_min[1];
-
-    if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                "cfFilterImageToPS: Updated custom page size to %.2f x %.2f inches...",
-                width / 72.0, length / 72.0);
-
-   /*
-    * Set the new custom size...
-    */
-
-    sprintf(s, "Custom.%.0fx%.0f", width, length);
-    ppdMarkOption(ppd, "PageSize", s);
-
-   /*
-    * Update page variables...
-    */
-
-    doc.PageWidth  = width;
-    doc.PageLength = length;
-    doc.PageLeft   = ppd->custom_margins[0];
-    doc.PageRight  = width - ppd->custom_margins[2];
-    doc.PageBottom = ppd->custom_margins[1];
-    doc.PageTop    = length - ppd->custom_margins[3];
-  }
-
- /*
-  * See if we need to collate, and if so how we need to do it...
-  */
-
-  if (xpages == 1 && ypages == 1)
-    Collate = 0;
-
-  slowcollate = Collate && ppdFindOption(ppd, "Collate") == NULL;
-
-  if (Copies > 1 && !slowcollate)
-  {
-    realcopies = Copies;
-    Copies     = 1;
-  }
-  else
-    realcopies = 1;
-
- /*
-  * Write any "exit server" options that have been selected...
-  */
-
-  ppdEmit(ppd, doc.outputfp, PPD_ORDER_EXIT);
-
- /*
-  * Write any JCL commands that are needed to print PostScript code...
-  */
-
-  if (emit_jcl)
-    ppdEmitJCL(ppd, doc.outputfp, data->job_id, data->job_user,
-              data->job_title);
-
- /*
-  * Start sending the document with any commands needed...
-  */
-
-  curtime = time(NULL);
-  curtm   = localtime(&curtime);
-
-  fputs("%!PS-Adobe-3.0\n", doc.outputfp);
-  fprintf(doc.outputfp, "%%%%BoundingBox: %.0f %.0f %.0f %.0f\n",
-         doc.PageLeft, doc.PageBottom, doc.PageRight, doc.PageTop);
-  fprintf(doc.outputfp, "%%%%LanguageLevel: %d\n", doc.LanguageLevel);
-  fprintf(doc.outputfp, "%%%%Pages: %d\n", xpages * ypages * Copies);
-  fputs("%%DocumentData: Clean7Bit\n", doc.outputfp);
-  fputs("%%DocumentNeededResources: font Helvetica-Bold\n", doc.outputfp);
-  fputs("%%Creator: imagetops\n", doc.outputfp);
-  strftime(curdate, sizeof(curdate), "%c", curtm);
-  fprintf(doc.outputfp, "%%%%CreationDate: %s\n", curdate);
-  WriteTextComment(&doc, "Title", data->job_title);
-  WriteTextComment(&doc, "For", data->job_user);
-  if (doc.Orientation & 1)
-    fputs("%%Orientation: Landscape\n", doc.outputfp);
-  else
-    fputs("%%Orientation: Portrait\n", doc.outputfp);
-  fputs("%%EndComments\n", doc.outputfp);
-  fputs("%%BeginProlog\n", doc.outputfp);
-
-  if (ppd != NULL && ppd->patches != NULL)
-  {
-    fputs(ppd->patches, doc.outputfp);
-    fputc('\n', doc.outputfp);
-  }
-
-  ppdEmit(ppd, doc.outputfp, PPD_ORDER_DOCUMENT);
-  ppdEmit(ppd, doc.outputfp, PPD_ORDER_ANY);
-  ppdEmit(ppd, doc.outputfp, PPD_ORDER_PROLOG);
-
-  if (g != 1.0 || b != 1.0)
-    fprintf(doc.outputfp,
-           "{ neg 1 add dup 0 lt { pop 1 } { %.3f exp neg 1 add } "
-           "ifelse %.3f mul } bind settransfer\n", g, b);
-
-  WriteCommon(&doc);
-  switch (doc.Orientation)
-  {
-    case 0 :
-        WriteLabelProlog(&doc, cupsGetOption("page-label", num_options,
-                                            options),
-                        doc.PageBottom, doc.PageTop, doc.PageWidth);
-        break;
-
-    case 1 :
-        WriteLabelProlog(&doc, cupsGetOption("page-label", num_options,
-                                            options),
-                        doc.PageLeft, doc.PageRight, doc.PageLength);
-        break;
-
-    case 2 :
-        WriteLabelProlog(&doc, cupsGetOption("page-label", num_options,
-                                            options),
-                        doc.PageLength - doc.PageTop,
-                        doc.PageLength - doc.PageBottom,
-                        doc.PageWidth);
-        break;
-
-    case 3 :
-       WriteLabelProlog(&doc, cupsGetOption("page-label", num_options,
-                                            options),
-                        doc.PageWidth - doc.PageRight,
-                        doc.PageWidth - doc.PageLeft,
-                        doc.PageLength);
-        break;
-  }
-
-  if (realcopies > 1)
-  {
-    if (ppd == NULL || ppd->language_level == 1)
-      fprintf(doc.outputfp, "/#copies %d def\n", realcopies);
-    else
-      fprintf(doc.outputfp, "<</NumCopies %d>>setpagedevice\n", realcopies);
-  }
-
-  fputs("%%EndProlog\n", doc.outputfp);
-
- /*
-  * Output the pages...
-  */
-
-  row = malloc(cfImageGetWidth(img) * abs(colorspace) + 3);
-  if (row == NULL)
-  {
-    log(ld, CF_LOGLEVEL_ERROR,
-       "cfFilterImageToPS: Could not allocate memory.");
-    cfImageClose(img);
-    return (2);
-  }
-
-  if (log)
-  {
-    log(ld, CF_LOGLEVEL_DEBUG,
-       "cfFilterImageToPS: XPosition=%d, YPosition=%d, Orientation=%d",
-       XPosition, YPosition, doc.Orientation);
-    log(ld, CF_LOGLEVEL_DEBUG,
-       "cfFilterImageToPS: xprint=%.1f, yprint=%.1f", xprint, yprint);
-    log(ld, CF_LOGLEVEL_DEBUG,
-       "cfFilterImageToPS: PageLeft=%.0f, PageRight=%.0f, PageWidth=%.0f",
-       doc.PageLeft, doc.PageRight, doc.PageWidth);
-    log(ld, CF_LOGLEVEL_DEBUG,
-       "cfFilterImageToPS: PageBottom=%.0f, PageTop=%.0f, PageLength=%.0f",
-       doc.PageBottom, doc.PageTop, doc.PageLength);
-  }
-
-  switch (doc.Orientation)
-  {
-    default :
-       switch (XPosition)
-       {
-         case -1 :
-              left = doc.PageLeft;
-             break;
-         default :
-              left = (doc.PageRight + doc.PageLeft - xprint * 72) / 2;
-             break;
-         case 1 :
-              left = doc.PageRight - xprint * 72;
-             break;
-       }
-
-       switch (YPosition)
-       {
-         case -1 :
-             top = doc.PageBottom + yprint * 72;
-             break;
-         default :
-             top = (doc.PageTop + doc.PageBottom + yprint * 72) / 2;
-             break;
-         case 1 :
-             top = doc.PageTop;
-             break;
-       }
-       break;
-
-    case 1 :
-       switch (XPosition)
-       {
-         case -1 :
-              left = doc.PageBottom;
-             break;
-         default :
-              left = (doc.PageTop + doc.PageBottom - xprint * 72) / 2;
-             break;
-         case 1 :
-              left = doc.PageTop - xprint * 72;
-             break;
-       }
-
-       switch (YPosition)
-       {
-         case -1 :
-             top = doc.PageLeft + yprint * 72;
-             break;
-         default :
-             top = (doc.PageRight + doc.PageLeft + yprint * 72) / 2;
-             break;
-         case 1 :
-             top = doc.PageRight;
-             break;
-       }
-       break;
-
-    case 2 :
-       switch (XPosition)
-       {
-         case 1 :
-              left = doc.PageLeft;
-             break;
-         default :
-              left = (doc.PageRight + doc.PageLeft - xprint * 72) / 2;
-             break;
-         case -1 :
-              left = doc.PageRight - xprint * 72;
-             break;
-       }
-
-       switch (YPosition)
-       {
-         case 1 :
-             top = doc.PageBottom + yprint * 72;
-             break;
-         default :
-             top = (doc.PageTop + doc.PageBottom + yprint * 72) / 2;
-             break;
-         case -1 :
-             top = doc.PageTop;
-             break;
-       }
-       break;
-
-    case 3 :
-       switch (XPosition)
-       {
-         case 1 :
-              left = doc.PageBottom;
-             break;
-         default :
-              left = (doc.PageTop + doc.PageBottom - xprint * 72) / 2;
-             break;
-         case -1 :
-              left = doc.PageTop - xprint * 72;
-             break;
-       }
-
-       switch (YPosition)
-       {
-         case 1 :
-             top = doc.PageLeft + yprint * 72;
-             break;
-         default :
-             top = (doc.PageRight + doc.PageLeft + yprint * 72) / 2;
-             break;
-         case -1 :
-             top = doc.PageRight;
-             break;
-       }
-       break;
-  }
-
-  if (log) log(ld, CF_LOGLEVEL_DEBUG,
-              "cfFilterImageToPS: left=%.2f, top=%.2f", left, top);
-
-  for (page = 1; Copies > 0; Copies --)
-    for (xpage = 0; xpage < xpages; xpage ++)
-      for (ypage = 0; ypage < ypages; ypage ++, page ++)
-      {
-       if (iscanceled && iscanceled(icd))
-       {
-         if (log) log(ld, CF_LOGLEVEL_DEBUG,
-                      "cfFilterImageToPS: Job canceled");
-         goto canceled;
-       }
-
-        if (log && ppd && ppd->num_filters == 0)
-         log(ld, CF_LOGLEVEL_CONTROL,
-             "PAGE: %d %d", page, realcopies);
-
-       if (log) log(ld, CF_LOGLEVEL_INFO,
-                    "cfFilterImageToPS: Printing page %d.", page);
-
-        fprintf(doc.outputfp, "%%%%Page: %d %d\n", page, page);
-
-        ppdEmit(ppd, doc.outputfp, PPD_ORDER_PAGE);
-
-       fputs("gsave\n", doc.outputfp);
-
-       if (Flip)
-         fprintf(doc.outputfp, "%.0f 0 translate -1 1 scale\n", doc.PageWidth);
-
-       switch (doc.Orientation)
-       {
-         case 1 : /* Landscape */
-             fprintf(doc.outputfp, "%.0f 0 translate 90 rotate\n",
-                     doc.PageWidth);
-              break;
-         case 2 : /* Reverse Portrait */
-             fprintf(doc.outputfp, "%.0f %.0f translate 180 rotate\n",
-                     doc.PageWidth, doc.PageLength);
-             break;
-         case 3 : /* Reverse Landscape */
-             fprintf(doc.outputfp, "0 %.0f translate -90 rotate\n",
-                     doc.PageLength);
-              break;
-       }
-
-        fputs("gsave\n", doc.outputfp);
-
-       xc0 = cfImageGetWidth(img) * xpage / xpages;
-       xc1 = cfImageGetWidth(img) * (xpage + 1) / xpages - 1;
-       yc0 = cfImageGetHeight(img) * ypage / ypages;
-       yc1 = cfImageGetHeight(img) * (ypage + 1) / ypages - 1;
-
-        fprintf(doc.outputfp, "%.1f %.1f translate\n", left, top);
-
-       fprintf(doc.outputfp, "%.3f %.3f scale\n\n",
-               xprint * 72.0 / (xc1 - xc0 + 1),
-               yprint * 72.0 / (yc1 - yc0 + 1));
-
-       if (doc.LanguageLevel == 1)
-       {
-         fprintf(doc.outputfp, "/picture %d string def\n",
-                 (xc1 - xc0 + 1) * abs(colorspace));
-         fprintf(doc.outputfp, "%d %d 8[1 0 0 -1 0 1]",
-                 (xc1 - xc0 + 1), (yc1 - yc0 + 1));
-
-          if (colorspace == CF_IMAGE_WHITE)
-            fputs("{currentfile picture readhexstring pop} image\n",
-                 doc.outputfp);
-          else
-            fprintf(doc.outputfp,
-                   "{currentfile picture readhexstring pop} false %d "
-                   "colorimage\n",
-                   abs(colorspace));
-
-          for (y = yc0; y <= yc1; y ++)
-          {
-            cfImageGetRow(img, xc0, y, xc1 - xc0 + 1, row);
-            ps_hex(doc.outputfp, row, (xc1 - xc0 + 1) * abs(colorspace),
-                  y == yc1);
-          }
-       }
-       else
-       {
-          switch (colorspace)
-         {
-           case CF_IMAGE_WHITE :
-               fputs("/DeviceGray setcolorspace\n", doc.outputfp);
-               break;
-            case CF_IMAGE_RGB :
-               fputs("/DeviceRGB setcolorspace\n", doc.outputfp);
-               break;
-            case CF_IMAGE_CMYK :
-               fputs("/DeviceCMYK setcolorspace\n", doc.outputfp);
-               break;
-          }
-
-          fprintf(doc.outputfp,
-                 "<<"
-                 "/ImageType 1"
-                 "/Width %d"
-                 "/Height %d"
-                 "/BitsPerComponent 8",
-                 xc1 - xc0 + 1, yc1 - yc0 + 1);
-
-          switch (colorspace)
-         {
-           case CF_IMAGE_WHITE :
-                fputs("/Decode[0 1]", doc.outputfp);
-               break;
-            case CF_IMAGE_RGB :
-                fputs("/Decode[0 1 0 1 0 1]", doc.outputfp);
-               break;
-            case CF_IMAGE_CMYK :
-                fputs("/Decode[0 1 0 1 0 1 0 1]", doc.outputfp);
-               break;
-          }
-
-          fputs("\n/DataSource currentfile/ASCII85Decode filter", doc.outputfp);
-
-          if (((xc1 - xc0 + 1) / xprint) < 100.0)
-            fputs("/Interpolate true", doc.outputfp);
-
-          fputs("/ImageMatrix[1 0 0 -1 0 1]>>image\n", doc.outputfp);
-
-          for (y = yc0, out_offset = 0; y <= yc1; y ++)
-          {
-            cfImageGetRow(img, xc0, y, xc1 - xc0 + 1, row + out_offset);
-
-            out_length = (xc1 - xc0 + 1) * abs(colorspace) + out_offset;
-            out_offset = out_length & 3;
-
-            ps_ascii85(doc.outputfp, row, out_length, y == yc1);
-
-            if (out_offset > 0)
-              memcpy(row, row + out_length - out_offset, out_offset);
-          }
-       }
-
-       fputs("grestore\n", doc.outputfp);
-       WriteLabels(&doc, 0);
-       fputs("grestore\n", doc.outputfp);
-       fputs("showpage\n", doc.outputfp);
-      }
-
- canceled:
-  fputs("%%EOF\n", doc.outputfp);
-
-  free(row);
-  
- /*
-  * End the job with the appropriate JCL command or CTRL-D otherwise.
-  */
-
-  if (emit_jcl)
-  {
-    if (ppd && ppd->jcl_end)
-      ppdEmitJCLEnd(ppd, doc.outputfp);
-    else
-      fputc(0x04, doc.outputfp);
-  }
-
-  if (log) log(ld, CF_LOGLEVEL_DEBUG,
-              "cfFilterImageToPS: Printing completed.", page);
-
- /*
-  * Close files...
-  */
-
-  cfImageClose(img);
-  fclose(doc.outputfp);
-  close(outputfd);
-
-  return (0);
-}
-
-
-/*
- * 'WriteCommon()' - Write common procedures...
- */
-
-void
-WriteCommon(imagetops_doc_t *doc)
-{
-  fputs("% x y w h ESPrc - Clip to a rectangle.\n"
-        "userdict/ESPrc/rectclip where{pop/rectclip load}\n"
-        "{{newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
-        "neg 0 rlineto closepath clip newpath}bind}ifelse put\n",
-       doc->outputfp);
-  fputs("% x y w h ESPrf - Fill a rectangle.\n"
-        "userdict/ESPrf/rectfill where{pop/rectfill load}\n"
-        "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
-        "neg 0 rlineto closepath fill grestore}bind}ifelse put\n",
-       doc->outputfp);
-  fputs("% x y w h ESPrs - Stroke a rectangle.\n"
-        "userdict/ESPrs/rectstroke where{pop/rectstroke load}\n"
-        "{{gsave newpath 4 2 roll moveto 1 index 0 rlineto 0 exch rlineto\n"
-        "neg 0 rlineto closepath stroke grestore}bind}ifelse put\n",
-       doc->outputfp);
-}
-
-
-/*
- * 'WriteLabelProlog()' - Write the prolog with the classification
- *                        and page label.
- */
-
-void
-WriteLabelProlog(imagetops_doc_t *doc,
-                const char *label,     /* I - Page label */
-                float      bottom,     /* I - Bottom position in points */
-                float      top,        /* I - Top position in points */
-                float      width)      /* I - Width in points */
-{
-  const char   *classification;        /* CLASSIFICATION environment variable*/
-  const char   *ptr;                   /* Temporary string pointer */
-
-
- /*
-  * First get the current classification...
-  */
-
-  if ((classification = getenv("CLASSIFICATION")) == NULL)
-    classification = "";
-  if (strcmp(classification, "none") == 0)
-    classification = "";
-
- /*
-  * If there is nothing to show, bind an empty 'write labels' procedure
-  * and return...
-  */
-
-  if (!classification[0] && (label == NULL || !label[0]))
-  {
-    fputs("userdict/ESPwl{}bind put\n", doc->outputfp);
-    return;
-  }
-
- /*
-  * Set the classification + page label string...
-  */
-
-  fprintf(doc->outputfp, "userdict");
-  if (strcmp(classification, "confidential") == 0)
-    fprintf(doc->outputfp, "/ESPpl(CONFIDENTIAL");
-  else if (strcmp(classification, "classified") == 0)
-    fprintf(doc->outputfp, "/ESPpl(CLASSIFIED");
-  else if (strcmp(classification, "secret") == 0)
-    fprintf(doc->outputfp, "/ESPpl(SECRET");
-  else if (strcmp(classification, "topsecret") == 0)
-    fprintf(doc->outputfp, "/ESPpl(TOP SECRET");
-  else if (strcmp(classification, "unclassified") == 0)
-    fprintf(doc->outputfp, "/ESPpl(UNCLASSIFIED");
-  else
-  {
-    fprintf(doc->outputfp, "/ESPpl(");
-
-    for (ptr = classification; *ptr; ptr ++)
-      if (*ptr < 32 || *ptr > 126)
-        fprintf(doc->outputfp, "\\%03o", *ptr);
-      else if (*ptr == '_')
-        fputc(' ', doc->outputfp);
-      else
-      {
-       if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
-         fputc('\\', doc->outputfp);
-
-       fputc(*ptr, doc->outputfp);
-      }
-  }
-
-  if (label)
-  {
-    if (classification[0])
-      fprintf(doc->outputfp, " - ");
-
-   /*
-    * Quote the label string as needed...
-    */
-
-    for (ptr = label; *ptr; ptr ++)
-      if (*ptr < 32 || *ptr > 126)
-        fprintf(doc->outputfp, "\\%03o", *ptr);
-      else
-      {
-       if (*ptr == '(' || *ptr == ')' || *ptr == '\\')
-         fputc('\\', doc->outputfp);
-
-       fputc(*ptr, doc->outputfp);
-      }
-  }
-
-  fputs(")put\n", doc->outputfp);
-
- /*
-  * Then get a 14 point Helvetica-Bold font...
-  */
-
-  fputs("userdict/ESPpf /Helvetica-Bold findfont 14 scalefont put\n",
-       doc->outputfp);
-
- /*
-  * Finally, the procedure to write the labels on the page...
-  */
-
-  fputs("userdict/ESPwl{\n", doc->outputfp);
-  fputs("  ESPpf setfont\n", doc->outputfp);
-  fprintf(doc->outputfp,
-         "  ESPpl stringwidth pop dup 12 add exch -0.5 mul %.0f add\n",
-         width * 0.5f);
-  fputs("  1 setgray\n", doc->outputfp);
-  fprintf(doc->outputfp, "  dup 6 sub %.0f 3 index 20 ESPrf\n", bottom - 2.0);
-  fprintf(doc->outputfp, "  dup 6 sub %.0f 3 index 20 ESPrf\n", top - 18.0);
-  fputs("  0 setgray\n", doc->outputfp);
-  fprintf(doc->outputfp, "  dup 6 sub %.0f 3 index 20 ESPrs\n", bottom - 2.0);
-  fprintf(doc->outputfp, "  dup 6 sub %.0f 3 index 20 ESPrs\n", top - 18.0);
-  fprintf(doc->outputfp, "  dup %.0f moveto ESPpl show\n", bottom + 2.0);
-  fprintf(doc->outputfp, "  %.0f moveto ESPpl show\n", top - 14.0);
-  fputs("pop\n", doc->outputfp);
-  fputs("}bind put\n", doc->outputfp);
-}
-
-
-/*
- * 'WriteLabels()' - Write the actual page labels.
- */
-
-void
-WriteLabels(imagetops_doc_t *doc,
-            int orient)        /* I - Orientation of the page */
-{
-  float        width,          /* Width of page */
-       length;         /* Length of page */
-
-
-  fputs("gsave\n", doc->outputfp);
-
-  if ((orient ^ doc->Orientation) & 1)
-  {
-    width  = doc->PageLength;
-    length = doc->PageWidth;
-  }
-  else
-  {
-    width  = doc->PageWidth;
-    length = doc->PageLength;
-  }
-
-  switch (orient & 3)
-  {
-    case 1 : /* Landscape */
-        fprintf(doc->outputfp, "%.1f 0.0 translate 90 rotate\n", length);
-        break;
-    case 2 : /* Reverse Portrait */
-        fprintf(doc->outputfp, "%.1f %.1f translate 180 rotate\n", width,
-               length);
-        break;
-    case 3 : /* Reverse Landscape */
-        fprintf(doc->outputfp, "0.0 %.1f translate -90 rotate\n", width);
-        break;
-  }
-
-  fputs("ESPwl\n", doc->outputfp);
-  fputs("grestore\n", doc->outputfp);
-}
-
-
-/*
- * 'WriteTextComment()' - Write a DSC text comment.
- */
-
-void
-WriteTextComment(imagetops_doc_t *doc,
-                 const char *name,     /* I - Comment name ("Title", etc.) */
-                 const char *value)    /* I - Comment value */
-{
-  int  len;                            /* Current line length */
-
-
- /*
-  * DSC comments are of the form:
-  *
-  *   %%name: value
-  *
-  * The name and value must be limited to 7-bit ASCII for most printers,
-  * so we escape all non-ASCII and ASCII control characters as described
-  * in the Adobe Document Structuring Conventions specification.
-  */
-
-  fprintf(doc->outputfp, "%%%%%s: (", name);
-  len = 5 + strlen(name);
-
-  while (*value)
-  {
-    if (*value < ' ' || *value >= 127)
-    {
-     /*
-      * Escape this character value...
-      */
-
-      if (len >= 251)                  /* Keep line < 254 chars */
-        break;
-
-      fprintf(doc->outputfp, "\\%03o", *value & 255);
-      len += 4;
-    }
-    else if (*value == '\\')
-    {
-     /*
-      * Escape the backslash...
-      */
-
-      if (len >= 253)                  /* Keep line < 254 chars */
-        break;
-
-      fputc('\\', doc->outputfp);
-      fputc('\\', doc->outputfp);
-      len += 2;
-    }
-    else
-    {
-     /*
-      * Put this character literally...
-      */
-
-      if (len >= 254)                  /* Keep line < 254 chars */
-        break;
-
-      fputc(*value, doc->outputfp);
-      len ++;
-    }
-
-    value ++;
-  }
-
-  fputs(")\n", doc->outputfp);
-}
-
-
-/*
- * 'ps_hex()' - Print binary data as a series of hexadecimal numbers.
- */
-
-static void
-ps_hex(FILE *outputfp,
-       cf_ib_t *data,                  /* I - Data to print */
-       int       length,               /* I - Number of bytes to print */
-       int       last_line)            /* I - Last line of raster data? */
-{
-  static int   col = 0;                /* Current column */
-  static char  *hex = "0123456789ABCDEF";
-                                       /* Hex digits */
-
-
-  while (length > 0)
-  {
-   /*
-    * Put the hex chars out to the file; note that we don't use fprintf()
-    * for speed reasons...
-    */
-
-    fputc(hex[*data >> 4], outputfp);
-    fputc(hex[*data & 15], outputfp);
-
-    data ++;
-    length --;
-
-    col += 2;
-    if (col > 78)
-    {
-      fputc('\n', outputfp);
-      col = 0;
-    }
-  }
-
-  if (last_line && col)
-  {
-    fputc('\n', outputfp);
-    col = 0;
-  }
-}
-
-
-/*
- * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
- */
-
-static void
-ps_ascii85(FILE *outputfp,
-          cf_ib_t *data,               /* I - Data to print */
-          int       length,            /* I - Number of bytes to print */
-          int       last_line)         /* I - Last line of raster data? */
-{
-  unsigned     b;                      /* Binary data word */
-  unsigned char        c[5];                   /* ASCII85 encoded chars */
-  static int   col = 0;                /* Current column */
-
-
-  while (length > 3)
-  {
-    b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
-
-    if (b == 0)
-    {
-      fputc('z', outputfp);
-      col ++;
-    }
-    else
-    {
-      c[4] = (b % 85) + '!';
-      b /= 85;
-      c[3] = (b % 85) + '!';
-      b /= 85;
-      c[2] = (b % 85) + '!';
-      b /= 85;
-      c[1] = (b % 85) + '!';
-      b /= 85;
-      c[0] = b + '!';
-
-      fwrite(c, 5, 1, outputfp);
-      col += 5;
-    }
-
-    data += 4;
-    length -= 4;
-
-    if (col >= 75)
-    {
-      fputc('\n', outputfp);
-      col = 0;
-    }
-  }
-
-  if (last_line)
-  {
-    if (length > 0)
-    {
-      memset(data + length, 0, 4 - length);
-      b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
-
-      c[4] = (b % 85) + '!';
-      b /= 85;
-      c[3] = (b % 85) + '!';
-      b /= 85;
-      c[2] = (b % 85) + '!';
-      b /= 85;
-      c[1] = (b % 85) + '!';
-      b /= 85;
-      c[0] = b + '!';
-
-      fwrite(c, length + 1, 1, outputfp);
-    }
-
-    fputs("~>\n", outputfp);
-    col = 0;
-  }
-}