*
* Contents:
*
+ * main() - Generate PostScript cover pages.
+ * load_banner() - Load the banner file.
+ * ps_ascii85() - Print binary data as a series of base-85 numbers.
+ * write_banner() - Write a banner page...
+ * write_epilogue() - Write the PostScript file epilogue.
+ * write_prolog() - Write the PostScript file prolog with options.
*/
/*
* Include necessary headers...
*/
-#include "common.h"
+#include "pstext.h"
#include "image.h"
#include <cups/i18n.h>
/*
- * Globals...
+ * Constants...
*/
-char *Glyphs[65536]; /* PostScript glyphs for Unicode */
-int NumFonts; /* Number of fonts to use */
-char *Fonts[256][4]; /* Fonts to use */
-unsigned short Chars[65536]; /* 0xffcc (ff = font, cc = char) */
-unsigned short Codes[65536]; /* Unicode glyph mapping to fonts */
-int Widths[256]; /* Widths of each font */
-int Directions[256];/* Text directions for each font */
+#define SHOW_IMAGEABLE_AREA 1 /* Show imageable area */
+#define SHOW_JOB_BILLING 2 /* Show billing string */
+#define SHOW_JOB_ID 4 /* Show job ID */
+#define SHOW_JOB_NAME 8 /* Show job title */
+#define SHOW_JOB_ORIGINATING_USER_NAME 16 /* Show owner of job */
+#define SHOW_JOB_ORIGINATING_HOST_NAME 32 /* Show submitting system */
+#define SHOW_JOB_UUID 64 /* Show job UUID */
+#define SHOW_OPTIONS 128 /* Show print options */
+#define SHOW_PAPER_NAME 256 /* Show paper size name */
+#define SHOW_PAPER_SIZE 512 /* Show paper dimensions */
+#define SHOW_PRINTER_DRIVER_NAME 1024 /* Show printer driver name */
+#define SHOW_PRINTER_DRIVER_VERSION 2048 /* Show printer driver version */
+#define SHOW_PRINTER_INFO 4096 /* Show printer description */
+#define SHOW_PRINTER_LOCATION 8192 /* Show printer location */
+#define SHOW_PRINTER_MAKE_AND_MODEL 16384 /* Show printer make and model */
+#define SHOW_PRINTER_NAME 32768 /* Show printer queue ID */
+#define SHOW_TIME_AT_CREATION 65536 /* Show date/time when submitted */
+#define SHOW_TIME_AT_PROCESSING 131072 /* Show date/time when printed */
/*
- * Local functions...
- */
-
-static void write_line(int row, lchar_t *line);
-static void write_string(int col, int row, int len, lchar_t *s);
-static void write_text(const char *s);
-
-
-/*
- * 'main()' - Generate PostScript cover pages.
+ * Structures...
*/
-int /* O - Exit status */
-main(int argc, /* I - Number of command-line arguments */
- char *argv[]) /* I - Command-line arguments */
+typedef struct banner_file_s /**** Banner file data ****/
{
-}
+ int show; /* What to show */
+ char *header, /* Header text */
+ *footer; /* Footer text */
+ cups_array_t *notices, /* Notices to show */
+ *images; /* Images to show */
+} banner_file_t;
/*
- * 'WriteEpilogue()' - Write the PostScript file epilogue.
- */
-
-void
-WriteEpilogue(void)
-{
- puts("%%Trailer");
- printf("%%%%Pages: %d\n", NumPages);
- puts("%%EOF");
-
- free(Page[0]);
- free(Page);
-}
-
-
-/*
- * 'WritePage()' - Write a page of text.
+ * Local functions...
*/
-void
-WritePage(void)
-{
- int line; /* Current line */
-
-
- NumPages ++;
- printf("%%%%Page: %d %d\n", NumPages, NumPages);
-
- puts("gsave");
-
- if (PrettyPrint)
- printf("%d H\n", NumPages);
-
- for (line = 0; line < SizeLines; line ++)
- write_line(line, Page[line]);
-
- puts("grestore");
- puts("showpage");
-
- memset(Page[0], 0, sizeof(lchar_t) * SizeColumns * SizeLines);
-}
+static banner_file_t *load_banner(const char *filename);
+static int write_banner(banner_file_t *banner, ppd_file_t *ppd,
+ ps_text_t *fonts, int job_id,
+ const char *title, const char *username,
+ int num_options, cups_option_t *options);
+static void write_epilogue(int num_pages);
+static ps_text_t *write_prolog(const char *title, const char *user);
/*
- * 'WriteProlog()' - Write the PostScript file prolog with options.
+ * 'main()' - Generate PostScript cover pages.
*/
-void
-WriteProlog(const char *title, /* I - Title of job */
- const char *user, /* I - Username */
- const char *classification, /* I - Classification */
- const char *label, /* I - Page label */
- ppd_file_t *ppd) /* I - PPD file info */
+int /* O - Exit status */
+main(int argc, /* I - Number of command-line args */
+ char *argv[]) /* I - Command-line arguments */
{
- int i, j, k; /* Looping vars */
- char *charset; /* Character set string */
- char filename[1024]; /* Glyph filenames */
- FILE *fp; /* Glyph files */
- const char *datadir; /* CUPS_DATADIR environment variable */
- char line[1024], /* Line from file */
- *lineptr, /* Pointer into line */
- *valptr; /* Pointer to value in line */
- int ch, unicode; /* Character values */
- int start, end; /* Start and end values for range */
- char glyph[64]; /* Glyph name */
- time_t curtime; /* Current time */
- struct tm *curtm; /* Current date */
- char curdate[255]; /* Current date (text format) */
- int num_fonts; /* Number of unique fonts */
- char *fonts[1024]; /* Unique fonts */
- static char *names[] = /* Font names */
- {
- "cupsNormal",
- "cupsBold",
- "cupsItalic"
- };
+ banner_file_t *banner; /* Banner file data */
+ int num_options; /* Number of print options */
+ cups_option_t *options; /* Print options */
+ ppd_file_t *ppd; /* PPD file */
+ ps_text_t *fonts; /* Fonts for output */
+ int job_id; /* Job ID from command-line */
+ const char *title, /* Title from command-line */
+ *username; /* Username from command-line */
+ int num_pages; /* Number of pages printed */
/*
- * Get the data directory...
+ * Make sure status messages are not buffered...
*/
- if ((datadir = getenv("CUPS_DATADIR")) == NULL)
- datadir = CUPS_DATADIR;
+ setbuf(stderr, NULL);
/*
- * Adjust margins as necessary...
+ * Check command-line...
*/
- if (classification || label)
+ if (argc < 6 || argc > 7)
{
- /*
- * Leave room for labels...
- */
-
- PageBottom += 36;
- PageTop -= 36;
+ _cupsLangPrintf(stderr,
+ _("Usage: %s job-id user title copies options [file]\n"),
+ "bannertops");
+ return (1);
}
/*
- * Allocate memory for the page...
+ * Get stuff from command-line...
*/
- SizeColumns = (PageRight - PageLeft) / 72.0 * CharsPerInch;
- SizeLines = (PageTop - PageBottom) / 72.0 * LinesPerInch;
+ job_id = atoi(argv[1]);
+ username = argv[2];
+ title = argv[3];
+ options = NULL;
+ num_options = cupsParseOptions(argv[5], 0, &options);
+ banner = load_banner(argv[6]);
- Page = calloc(sizeof(lchar_t *), SizeLines);
- Page[0] = calloc(sizeof(lchar_t), SizeColumns * SizeLines);
- for (i = 1; i < SizeLines; i ++)
- Page[i] = Page[0] + i * SizeColumns;
+ /*
+ * Set standard options and get the PPD file for this printer...
+ */
- if (PageColumns > 1)
- {
- ColumnGutter = CharsPerInch / 2;
- ColumnWidth = (SizeColumns - ColumnGutter * (PageColumns - 1)) /
- PageColumns;
- }
- else
- ColumnWidth = SizeColumns;
+ ppd = SetCommonOptions(num_options, options, 1);
/*
- * Output the DSC header...
+ * Write a PostScript banner document and return...
*/
- curtime = time(NULL);
- curtm = localtime(&curtime);
- strftime(curdate, sizeof(curdate), "%c", curtm);
+ fonts = write_prolog(title, username);
+ num_pages = write_banner(banner, ppd, fonts, job_id, title, username,
+ num_options, options);
- puts("%!PS-Adobe-3.0");
- printf("%%%%BoundingBox: 0 0 %.0f %.0f\n", PageWidth, PageLength);
- printf("%%cupsRotation: %d\n", (Orientation & 3) * 90);
- puts("%%Creator: texttops/" CUPS_SVERSION);
- printf("%%%%CreationDate: %s\n", curdate);
- WriteTextComment("Title", title);
- WriteTextComment("For", user);
- puts("%%Pages: (atend)");
+ write_epilogue(num_pages);
- /*
- * Initialize globals...
- */
+ return (0);
+}
- NumFonts = 0;
- memset(Fonts, 0, sizeof(Fonts));
- memset(Glyphs, 0, sizeof(Glyphs));
- memset(Chars, 0, sizeof(Chars));
- memset(Codes, 0, sizeof(Codes));
- /*
- * Load the PostScript glyph names and the corresponding character
- * set definition...
- */
+/*
+ * 'load_banner()' - Load the banner file.
+ */
- snprintf(filename, sizeof(filename), "%s/data/psglyphs", datadir);
+static banner_file_t * /* O - Banner file data */
+load_banner(const char *filename) /* I - Filename or NULL for stdin */
+{
+ cups_file_t *fp; /* File */
+ char line[2048], /* Line buffer */
+ *ptr; /* Pointer into line */
+ int linenum; /* Current line number */
+ banner_file_t *banner; /* Banner file data */
+ const char *cups_docroot; /* CUPS_DOCROOT environment variable */
- if ((fp = fopen(filename, "r")) != NULL)
- {
- while (fscanf(fp, "%x%63s", &unicode, glyph) == 2)
- Glyphs[unicode] = strdup(glyph);
- fclose(fp);
- }
+ fprintf(stderr, "DEBUG: load_banner(filename=\"%s\")\n",
+ filename ? filename : "(stdin)");
+
+ /*
+ * Open the banner file...
+ */
+
+ if (filename)
+ fp = cupsFileOpen(filename, "r");
else
+ fp = cupsFileStdin();
+
+ if (!fp)
{
- fprintf(stderr, _("ERROR: Unable to open \"%s\" - %s\n"), filename,
- strerror(errno));
+ _cupsLangPrintf(stderr,
+ _("ERROR: Unable to open banner file \"%s\" - %s\n"),
+ filename ? filename : "(stdin)", strerror(errno));
exit(1);
}
/*
- * Get the output character set...
+ * Read the banner file...
*/
- charset = getenv("CHARSET");
- if (charset != NULL && strcmp(charset, "us-ascii") != 0)
+ if ((cups_docroot = getenv("CUPS_DOCROOT")) == NULL)
+ cups_docroot = CUPS_DOCROOT;
+
+ banner = calloc(1, sizeof(banner_file_t));
+ linenum = 0;
+
+ while (cupsFileGets(fp, line, sizeof(line)))
{
- snprintf(filename, sizeof(filename), "%s/charsets/%s", datadir, charset);
+ /*
+ * Skip blank and comment lines...
+ */
- if ((fp = fopen(filename, "r")) == NULL)
- {
- /*
- * Can't open charset file!
- */
+ linenum ++;
- fprintf(stderr, _("ERROR: Unable to open %s: %s\n"), filename,
- strerror(errno));
- exit(1);
- }
+ if (line[0] == '#' || !line[0])
+ continue;
/*
- * Opened charset file; now see if this is really a charset file...
+ * Break the line into keyword and value parts...
*/
- if (fgets(line, sizeof(line), fp) == NULL)
- {
- /*
- * Bad/empty charset file!
- */
+ for (ptr = line; *ptr && !isspace(*ptr & 255); ptr ++);
- fclose(fp);
- fprintf(stderr, _("ERROR: Bad charset file %s\n"), filename);
- exit(1);
- }
+ while (isspace(*ptr & 255))
+ *ptr++ = '\0';
- if (strncmp(line, "charset", 7) != 0)
+ if (!*ptr)
{
- /*
- * Bad format/not a charset file!
- */
-
- fclose(fp);
- fprintf(stderr, _("ERROR: Bad charset file %s\n"), filename);
- exit(1);
+ _cupsLangPrintf(stderr,
+ _("ERROR: Missing value on line %d of banner file!\n"),
+ linenum);
+ continue;
}
/*
- * See if this is an 8-bit or UTF-8 character set file...
+ * Save keyword values in the appropriate places...
*/
- line[strlen(line) - 1] = '\0'; /* Drop \n */
- for (lineptr = line + 7; isspace(*lineptr & 255); lineptr ++); /* Skip whitespace */
-
- if (strcmp(lineptr, "8bit") == 0)
+ if (!strcasecmp(line, "Footer"))
+ {
+ if (banner->footer)
+ fprintf(stderr, "DEBUG: Extra \"Footer\" on line %d of banner file!\n",
+ linenum);
+ else
+ banner->footer = strdup(ptr);
+ }
+ else if (!strcasecmp(line, "Header"))
{
- /*
- * 8-bit text...
- */
+ if (banner->header)
+ fprintf(stderr, "DEBUG: Extra \"Header\" on line %d of banner file!\n",
+ linenum);
+ else
+ banner->header = strdup(ptr);
+ }
+ else if (!strcasecmp(line, "Image"))
+ {
+ char imagefile[1024]; /* Image filename */
- UTF8 = 0;
- NumFonts = 0;
- /*
- * Read the font description(s)...
- */
+ if (ptr[0] == '/')
+ strlcpy(imagefile, ptr, sizeof(imagefile));
+ else
+ snprintf(imagefile, sizeof(imagefile), "%s/%s", cups_docroot, ptr);
- while (fgets(line, sizeof(line), fp) != NULL)
+ if (access(imagefile, R_OK))
{
- /*
- * Skip comment and blank lines...
- */
-
- if (line[0] == '#' || line[0] == '\n')
- continue;
-
- /*
- * Read the font descriptions that should look like:
- *
- * first last direction width normal [bold italic bold-italic]
- */
-
- lineptr = line;
-
- start = strtol(lineptr, &lineptr, 16);
- end = strtol(lineptr, &lineptr, 16);
-
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- if (!*lineptr)
- break; /* Must be a font mapping */
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (!*lineptr)
- {
- /*
- * Can't have a font without all required values...
- */
-
- fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- *lineptr++ = '\0';
-
- if (strcmp(valptr, "ltor") == 0)
- Directions[NumFonts] = 1;
- else if (strcmp(valptr, "rtol") == 0)
- Directions[NumFonts] = -1;
- else
- {
- fprintf(stderr, _("ERROR: Bad text direction %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- /*
- * Got the direction, now get the width...
- */
-
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (!*lineptr)
- {
- /*
- * Can't have a font without all required values...
- */
-
- fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- *lineptr++ = '\0';
-
- if (strcmp(valptr, "single") == 0)
- Widths[NumFonts] = 1;
- else if (strcmp(valptr, "double") == 0)
- Widths[NumFonts] = 2;
- else
- {
- fprintf(stderr, _("ERROR: Bad text width %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- /*
- * Get the fonts...
- */
-
- for (i = 0; *lineptr && i < 4; i ++)
- {
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (*lineptr)
- *lineptr++ = '\0';
-
- if (lineptr > valptr)
- Fonts[NumFonts][i] = strdup(valptr);
- }
-
- /*
- * Fill in remaining fonts as needed...
- */
-
- for (j = i; j < 4; j ++)
- Fonts[NumFonts][j] = strdup(Fonts[NumFonts][0]);
-
- /*
- * Define the character mappings...
- */
-
- for (i = start, j = NumFonts * 256; i <= end; i ++, j ++)
- Chars[i] = j;
-
- NumFonts ++;
+ fprintf(stderr, "DEBUG: Image \"%s\" on line %d of banner file: %s\n",
+ ptr, linenum, strerror(errno));
}
-
- /*
- * Read encoding lines...
- */
-
- do
+ else
{
- /*
- * Skip comment and blank lines...
- */
+ if (!banner->images)
+ banner->images = cupsArrayNew(NULL, NULL);
- if (line[0] == '#' || line[0] == '\n')
- continue;
-
- /*
- * Grab the character and unicode glyph number.
- */
-
- if (sscanf(line, "%x%x", &ch, &unicode) == 2 && ch < 256)
- Codes[Chars[ch]] = unicode;
+ cupsArrayAdd(banner->images, strdup(imagefile));
}
- while (fgets(line, sizeof(line), fp) != NULL);
-
- fclose(fp);
}
- else if (strcmp(lineptr, "utf8") == 0)
+ else if (!strcasecmp(line, "Notice"))
{
- /*
- * UTF-8 (Unicode) text...
- */
-
- UTF8 = 1;
+ if (!banner->notices)
+ banner->notices = cupsArrayNew(NULL, NULL);
- /*
- * Read the font descriptions...
- */
+ cupsArrayAdd(banner->notices, strdup(ptr));
+ }
+ else if (!strcasecmp(line, "Show"))
+ {
+ char *value; /* Current value */
- NumFonts = 0;
- while (fgets(line, sizeof(line), fp) != NULL)
+ for (value = ptr; *value; value = ptr)
{
/*
- * Skip comment and blank lines...
+ * Find the end of the current value
*/
- if (line[0] == '#' || line[0] == '\n')
- continue;
-
- /*
- * Read the font descriptions that should look like:
- *
- * start end direction width normal [bold italic bold-italic]
- */
-
- lineptr = line;
-
- start = strtol(lineptr, &lineptr, 16);
- end = strtol(lineptr, &lineptr, 16);
-
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (!*lineptr)
- {
- /*
- * Can't have a font without all required values...
- */
-
- fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- *lineptr++ = '\0';
-
- if (strcmp(valptr, "ltor") == 0)
- Directions[NumFonts] = 1;
- else if (strcmp(valptr, "rtol") == 0)
- Directions[NumFonts] = -1;
- else
- {
- fprintf(stderr, _("ERROR: Bad text direction %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- /*
- * Got the direction, now get the width...
- */
-
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (!*lineptr)
- {
- /*
- * Can't have a font without all required values...
- */
-
- fprintf(stderr, _("ERROR: Bad font description line: %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- *lineptr++ = '\0';
-
- if (strcmp(valptr, "single") == 0)
- Widths[NumFonts] = 1;
- else if (strcmp(valptr, "double") == 0)
- Widths[NumFonts] = 2;
- else
- {
- fprintf(stderr, _("ERROR: Bad text width %s\n"), valptr);
- fclose(fp);
- exit(1);
- }
-
- /*
- * Get the fonts...
- */
-
- for (i = 0; *lineptr && i < 4; i ++)
- {
- while (isspace(*lineptr & 255))
- lineptr ++;
-
- valptr = lineptr;
-
- while (!isspace(*lineptr & 255) && *lineptr)
- lineptr ++;
-
- if (*lineptr)
- *lineptr++ = '\0';
+ while (*ptr && !isspace(*ptr & 255))
+ ptr ++;
- if (lineptr > valptr)
- Fonts[NumFonts][i] = strdup(valptr);
- }
-
- /*
- * Fill in remaining fonts as needed...
- */
-
- for (j = i; j < 4; j ++)
- Fonts[NumFonts][j] = strdup(Fonts[NumFonts][0]);
+ while (*ptr && isspace(*ptr & 255))
+ *ptr++ = '\0';
/*
- * Define the character mappings...
+ * Add the value to the show flags...
*/
-
- for (i = start, j = NumFonts * 256; i <= end; i ++, j ++)
- {
- Chars[i] = j;
- Codes[j] = i;
+ if (!strcasecmp(value, "imageable-area"))
+ banner->show |= SHOW_IMAGEABLE_AREA;
+ else if (!strcasecmp(value, "job-billing"))
+ banner->show |= SHOW_JOB_BILLING;
+ else if (!strcasecmp(value, "job-id"))
+ banner->show |= SHOW_JOB_ID;
+ else if (!strcasecmp(value, "job-name"))
+ banner->show |= SHOW_JOB_NAME;
+ else if (!strcasecmp(value, "job-originating-host-name"))
+ banner->show |= SHOW_JOB_ORIGINATING_HOST_NAME;
+ else if (!strcasecmp(value, "job-originating-user-name"))
+ banner->show |= SHOW_JOB_ORIGINATING_USER_NAME;
+ else if (!strcasecmp(value, "job-uuid"))
+ banner->show |= SHOW_JOB_UUID;
+ else if (!strcasecmp(value, "options"))
+ banner->show |= SHOW_OPTIONS;
+ else if (!strcasecmp(value, "paper-name"))
+ banner->show |= SHOW_PAPER_NAME;
+ else if (!strcasecmp(value, "paper-size"))
+ banner->show |= SHOW_PAPER_SIZE;
+ else if (!strcasecmp(value, "printer-driver-name"))
+ banner->show |= SHOW_PRINTER_DRIVER_NAME;
+ else if (!strcasecmp(value, "printer-driver-version"))
+ banner->show |= SHOW_PRINTER_DRIVER_VERSION;
+ else if (!strcasecmp(value, "printer-info"))
+ banner->show |= SHOW_PRINTER_INFO;
+ else if (!strcasecmp(value, "printer-location"))
+ banner->show |= SHOW_PRINTER_LOCATION;
+ else if (!strcasecmp(value, "printer-make-and-model"))
+ banner->show |= SHOW_PRINTER_MAKE_AND_MODEL;
+ else if (!strcasecmp(value, "printer-name"))
+ banner->show |= SHOW_PRINTER_NAME;
+ else if (!strcasecmp(value, "time-at-creation"))
+ banner->show |= SHOW_TIME_AT_CREATION;
+ else if (!strcasecmp(value, "time-at-processing"))
+ banner->show |= SHOW_TIME_AT_PROCESSING;
+ else
+ {
+ fprintf(stderr,
+ "DEBUG: Unknown \"Show\" value \"%s\" on line %d of banner "
+ "file!\n", value, linenum);
}
-
- /*
- * Move to the next font, stopping if needed...
- */
-
- NumFonts ++;
- if (NumFonts >= 256)
- break;
}
-
- fclose(fp);
}
else
- {
- fprintf(stderr, _("ERROR: Bad charset type %s\n"), lineptr);
- fclose(fp);
- exit(1);
- }
+ fprintf(stderr, "DEBUG: Unknown key \"%s\" on line %d of banner file!\n",
+ line, linenum);
}
- else
- {
- /*
- * Standard ASCII output just uses Courier, Courier-Bold, and
- * possibly Courier-Oblique.
- */
-
- NumFonts = 1;
- Fonts[0][ATTR_NORMAL] = strdup("Courier");
- Fonts[0][ATTR_BOLD] = strdup("Courier-Bold");
- Fonts[0][ATTR_ITALIC] = strdup("Courier-Oblique");
- Fonts[0][ATTR_BOLDITALIC] = strdup("Courier-BoldOblique");
+ if (filename)
+ cupsFileClose(fp);
- Widths[0] = 1;
- Directions[0] = 1;
+ return (banner);
+}
- /*
- * Define US-ASCII characters...
- */
- for (i = 32; i < 127; i ++)
- {
- Chars[i] = i;
- Codes[i] = i;
- }
- }
+/*
+ * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
+ */
- /*
- * Generate a list of unique fonts to use...
- */
+static void
+ps_ascii85(cups_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 */
- for (i = 0, num_fonts = 0; i < NumFonts; i ++)
- for (j = PrettyPrint ? 2 : 1; j >= 0; j --)
- {
- for (k = 0; k < num_fonts; k ++)
- if (strcmp(Fonts[i][j], fonts[k]) == 0)
- break;
- if (k >= num_fonts)
- {
- /*
- * Add new font...
- */
+ while (length > 3)
+ {
+ b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
- fonts[num_fonts] = Fonts[i][j];
- num_fonts ++;
- }
+ if (b == 0)
+ {
+ putchar('z');
+ col ++;
}
-
- /*
- * List the fonts that will be used...
- */
-
- for (i = 0; i < num_fonts; i ++)
- if (i == 0)
- printf("%%%%DocumentNeededResources: font %s\n", fonts[i]);
else
- printf("%%%%+ font %s\n", fonts[i]);
-
- puts("%%DocumentSuppliedResources: procset texttops 1.1 0");
-
- for (i = 0; i < num_fonts; i ++)
- {
- if (ppd != NULL)
{
- fprintf(stderr, "DEBUG: ppd->num_fonts = %d\n", ppd->num_fonts);
-
- for (j = 0; j < ppd->num_fonts; j ++)
- {
- fprintf(stderr, "DEBUG: ppd->fonts[%d] = %s\n", j, ppd->fonts[j]);
-
- if (strcmp(fonts[i], ppd->fonts[j]) == 0)
- break;
- }
+ 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, stdout);
+ col += 5;
}
- else
- j = 0;
- if ((ppd != NULL && j >= ppd->num_fonts) ||
- strncmp(fonts[i], "Courier", 7) == 0 ||
- strcmp(fonts[i], "Symbol") == 0)
- {
- /*
- * Need to embed this font...
- */
+ data += 4;
+ length -= 4;
- printf("%%%%+ font %s\n", fonts[i]);
+ if (col >= 75)
+ {
+ putchar('\n');
+ col = 0;
}
}
- puts("%%EndComments");
-
- puts("%%BeginProlog");
-
- /*
- * Download any missing fonts...
- */
-
- for (i = 0; i < num_fonts; i ++)
+ if (last_line)
{
- if (ppd != NULL)
+ if (length > 0)
{
- for (j = 0; j < ppd->num_fonts; j ++)
- if (strcmp(fonts[i], ppd->fonts[j]) == 0)
- break;
+ 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, stdout);
}
- else
- j = 0;
- if ((ppd != NULL && j >= ppd->num_fonts) ||
- strncmp(fonts[i], "Courier", 7) == 0 ||
- strcmp(fonts[i], "Symbol") == 0)
- {
- /*
- * Need to embed this font...
- */
+ puts("~>");
+ col = 0;
+ }
+}
- printf("%%%%BeginResource: font %s\n", fonts[i]);
- /**** MRS: Need to use CUPS_FONTPATH env var! ****/
- /**** Also look for Fontmap file or name.pfa, name.pfb... ****/
- snprintf(filename, sizeof(filename), "%s/fonts/%s", datadir, fonts[i]);
- if ((fp = fopen(filename, "rb")) != NULL)
- {
- while ((j = fread(line, 1, sizeof(line), fp)) > 0)
- fwrite(line, 1, j, stdout);
+/*
+ * 'write_banner()' - Write a banner page...
+ */
- fclose(fp);
- }
+static int /* O - Number of pages */
+write_banner(banner_file_t *banner, /* I - Banner file */
+ ppd_file_t *ppd, /* I - PPD file */
+ ps_text_t *fonts, /* I - Fonts */
+ int job_id, /* I - Job ID */
+ const char *title, /* I - Title of job */
+ const char *username, /* I - Owner of job */
+ int num_options, /* I - Number of options */
+ cups_option_t *options) /* I - Options */
+{
+ char *notice; /* Current notice */
+ char *imagefile; /* Current image file */
+ cups_array_t *images; /* Images */
+ cups_image_t *image; /* Current image */
+ const char *option; /* Option value */
+ int i, j; /* Looping vars */
+ float x, /* Current X position */
+ y; /* Current Y position */
+ cups_lang_t *language; /* Default language */
+ int showlines; /* Number of lines to show */
+ float fontsize; /* Font size to use */
+ int num_pages; /* Number of pages */
+ float print_width, /* Printable width of page */
+ print_height, /* Printable height of page */
+ info_top, /* Top of info fields */
+ info_height, /* Height of info fields */
+ line_height, /* Height of info lines */
+ notices_height, /* Height of all notices */
+ images_width, /* Width of all images */
+ images_height, /* Height of all images */
+ total_height; /* Height of all content */
+ char text[1024]; /* Formatted field text */
- puts("\n%%EndResource");
- }
- }
/*
- * Write the encoding array(s)...
+ * Figure out how many lines of text will be shown...
*/
- puts("% character encoding(s)");
-
- for (i = 0; i < NumFonts; i ++)
+ showlines = 0;
+ if (banner->show & SHOW_IMAGEABLE_AREA)
+ showlines += 2;
+ if (banner->show & SHOW_JOB_BILLING)
+ showlines ++;
+ if (banner->show & SHOW_JOB_ID)
+ showlines ++;
+ if (banner->show & SHOW_JOB_NAME)
+ showlines ++;
+ if (banner->show & SHOW_JOB_ORIGINATING_USER_NAME)
+ showlines ++;
+ if (banner->show & SHOW_JOB_ORIGINATING_HOST_NAME)
+ showlines ++;
+ if (banner->show & SHOW_JOB_UUID)
+ showlines ++;
+ if (banner->show & SHOW_OPTIONS)
{
- printf("/cupsEncoding%02x [\n", i);
-
- for (ch = 0; ch < 256; ch ++)
+ for (j = 0; j < num_options; j ++)
{
- if (Glyphs[Codes[i * 256 + ch]])
- printf("/%s", Glyphs[Codes[i * 256 + ch]]);
- else if (Codes[i * 256 + ch] > 255)
- printf("/uni%04X", Codes[i * 256 + ch]);
- else
- printf("/.notdef");
-
- if ((ch & 7) == 7)
- putchar('\n');
+ if (strcasecmp("media", options[j].name) &&
+ strcasecmp("PageSize", options[j].name) &&
+ strcasecmp("PageRegion", options[j].name) &&
+ strcasecmp("InputSlot", options[j].name) &&
+ strcasecmp("MediaType", options[j].name) &&
+ strcasecmp("finishings", options[j].name) &&
+ strcasecmp("sides", options[j].name) &&
+ strcasecmp("Duplex", options[j].name) &&
+ strcasecmp("orientation-requested", options[j].name) &&
+ strcasecmp("landscape", options[j].name) &&
+ strcasecmp("number-up", options[j].name) &&
+ strcasecmp("OutputOrder", options[j].name))
+ continue;
+
+ showlines ++;
}
-
- puts("] def");
}
+ if (banner->show & SHOW_PAPER_NAME)
+ showlines ++;
+ if (banner->show & SHOW_PAPER_SIZE)
+ showlines += 2;
+ if (banner->show & SHOW_PRINTER_DRIVER_NAME)
+ showlines ++;
+ if (banner->show & SHOW_PRINTER_DRIVER_VERSION)
+ showlines ++;
+ if (banner->show & SHOW_PRINTER_INFO)
+ showlines ++;
+ if (banner->show & SHOW_PRINTER_LOCATION)
+ showlines ++;
+ if (banner->show & SHOW_PRINTER_MAKE_AND_MODEL)
+ showlines ++;
+ if (banner->show & SHOW_PRINTER_NAME)
+ showlines ++;
+ if (banner->show & SHOW_TIME_AT_CREATION)
+ showlines ++;
+ if (banner->show & SHOW_TIME_AT_PROCESSING)
+ showlines ++;
/*
- * Create the fonts...
+ * Figure out the dimensions and positions of everything...
*/
- if (NumFonts == 1)
- {
- /*
- * Just reencode the named fonts...
- */
+ print_width = PageRight - PageLeft;
+ print_height = PageTop - PageBottom;
+ fontsize = print_height / 60; /* Nominally 12pts */
+ line_height = 1.2 * fontsize;
+ info_height = showlines * line_height;
+ notices_height = cupsArrayCount(banner->notices) * line_height;
- puts("% Reencode fonts");
+ if (cupsArrayCount(banner->images))
+ {
+ images = cupsArrayNew(NULL, NULL);
+ images_height = print_height / 10; /* Nominally 1" */
- for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
+ for (imagefile = (char *)cupsArrayFirst(banner->images), images_width = 0.0;
+ imagefile;
+ imagefile = (char *)cupsArrayNext(banner->images))
{
- printf("/%s findfont\n", Fonts[0][i]);
- puts("dup length 1 add dict begin\n"
- " { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
- " /Encoding cupsEncoding00 def\n"
- " currentdict\n"
- "end");
- printf("/%s exch definefont pop\n", names[i]);
+ if ((image = cupsImageOpen(imagefile, ColorDevice ? CUPS_IMAGE_RGB_CMYK :
+ CUPS_IMAGE_WHITE,
+ CUPS_IMAGE_WHITE, 100, 0, NULL)) == NULL)
+ {
+ fprintf(stderr, "DEBUG: Unable to open image file \"%s\"!\n",
+ imagefile);
+ continue;
+ }
+
+ images_width += cupsImageGetWidth(image) * images_height /
+ cupsImageGetHeight(image);
+ cupsArrayAdd(images, image);
}
}
else
{
- /*
- * Construct composite fonts... Start by reencoding the base fonts...
- */
-
- puts("% Reencode base fonts");
-
- for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
- for (j = 0; j < NumFonts; j ++)
- {
- printf("/%s findfont\n", Fonts[j][i]);
- printf("dup length 1 add dict begin\n"
- " { 1 index /FID ne { def } { pop pop } ifelse } forall\n"
- " /Encoding cupsEncoding%02x def\n"
- " currentdict\n"
- "end\n", j);
- printf("/%s%02x exch definefont /%s%02x exch def\n", names[i], j,
- names[i], j);
- }
-
- /*
- * Then merge them into composite fonts...
- */
+ images = NULL;
+ images_height = 0;
+ images_width = 0;
+ }
- puts("% Create composite fonts...");
+ total_height = info_height + notices_height + images_height;
+ if (cupsArrayCount(banner->notices) && showlines)
+ total_height += 2 * line_height;
+ if (cupsArrayCount(banner->images) &&
+ (showlines || cupsArrayCount(banner->notices)))
+ total_height += 2 * line_height;
- for (i = PrettyPrint ? 2 : 1; i >= 0; i --)
- {
- puts("8 dict begin");
- puts("/FontType 0 def/FontMatrix[1.0 0 0 1.0 0 0]def/FMapType 2 def/Encoding[");
- for (j = 0; j < NumFonts; j ++)
- if (j == (NumFonts - 1))
- printf("%d", j);
- else if ((j & 15) == 15)
- printf("%d\n", j);
- else
- printf("%d ", j);
- puts("]def/FDepVector[");
- for (j = 0; j < NumFonts; j ++)
- if (j == (NumFonts - 1))
- printf("%s%02x", names[i], j);
- else if ((j & 3) == 3)
- printf("%s%02x\n", names[i], j);
- else
- printf("%s%02x ", names[i], j);
- puts("]def currentdict end");
- printf("/%s exch definefont pop\n", names[i]);
- }
- }
+ info_top = 0.5 * (print_height + total_height);
/*
- * Output the texttops procset...
+ * Write the page(s)...
*/
- puts("%%BeginResource: procset texttops 1.1 0");
-
- puts("% Define fonts");
+ language = cupsLangDefault();
+ num_pages = Duplex ? 2 : 1;
- printf("/FN /cupsNormal findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
- 120.0 / CharsPerInch, 68.0 / LinesPerInch);
- printf("/FB /cupsBold findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
- 120.0 / CharsPerInch, 68.0 / LinesPerInch);
- if (PrettyPrint)
- printf("/FI /cupsItalic findfont [%.3f 0 0 %.3f 0 0] makefont def\n",
- 120.0 / CharsPerInch, 68.0 / LinesPerInch);
-
- puts("% Common procedures");
-
- puts("/N { FN setfont moveto } bind def");
- puts("/B { FB setfont moveto } bind def");
- printf("/U { gsave 0.5 setlinewidth 0 %.3f rmoveto "
- "0 rlineto stroke grestore } bind def\n", -6.8 / LinesPerInch);
-
- if (PrettyPrint)
+ for (i = 1; i <= num_pages; i ++)
{
- if (ColorDevice)
- {
- puts("/S { 0.0 setgray show } bind def");
- puts("/r { 0.5 0.0 0.0 setrgbcolor show } bind def");
- puts("/g { 0.0 0.5 0.0 setrgbcolor show } bind def");
- puts("/b { 0.0 0.0 0.5 setrgbcolor show } bind def");
- }
- else
- {
- puts("/S { 0.0 setgray show } bind def");
- puts("/r { 0.2 setgray show } bind def");
- puts("/g { 0.2 setgray show } bind def");
- puts("/b { 0.2 setgray show } bind def");
- }
-
- puts("/I { FI setfont moveto } bind def");
-
- puts("/n {");
- puts("\t20 string cvs % convert page number to string");
- if (NumFonts > 1)
- {
- /*
- * Convert a number to double-byte chars...
- */
-
- puts("\tdup length % get length");
- puts("\tdup 2 mul string /P exch def % P = string twice as long");
- puts("\t0 1 2 index 1 sub { % loop through each character in the page number");
- puts("\t\tdup 3 index exch get % get character N from the page number");
- puts("\t\texch 2 mul dup % compute offset in P");
- puts("\t\tP exch 0 put % font 0");
- puts("\t\t1 add P exch 2 index put % character");
- puts("\t\tpop % discard character");
- puts("\t} for % do for loop");
- puts("\tpop pop % discard string and length");
- puts("\tP % put string on stack");
- }
- puts("} bind def");
-
- printf("/T");
- write_text(title);
- puts("def");
-
- printf("/D");
- write_text(curdate);
- puts("def");
-
- puts("/H {");
- puts("\tgsave");
- puts("\t0.9 setgray");
+ /*
+ * Start the page...
+ */
- if (Duplex)
- {
- puts("\tdup 2 mod 0 eq {");
- printf("\t\t%.3f %.3f translate } {\n",
- PageWidth - PageRight, PageTop + 72.0f / LinesPerInch);
- printf("\t\t%.3f %.3f translate } ifelse\n",
- PageLeft, PageTop + 72.0f / LinesPerInch);
- }
+ printf("%%%%Page: %s %d\n", i == 1 ? "coverpage" : "coverback", i);
+ puts("gsave");
+ if (i == 1)
+ printf("%.1f %.1f translate\n", PageLeft, PageBottom);
else
- printf("\t%.3f %.3f translate\n",
- PageLeft, PageTop + 72.0f / LinesPerInch);
+ printf("%.1f %.1f translate\n", PageWidth - PageRight,
+ PageLength - PageRight);
+ puts("0 setgray");
- printf("\t0 0 %.3f %.3f rectfill\n", PageRight - PageLeft,
- 144.0f / LinesPerInch);
+ y = info_top;
- puts("\tFB setfont");
- puts("\t0 setgray");
+ /*
+ * Information...
+ */
- if (Duplex)
+ if (banner->show)
{
- puts("\tdup 2 mod 0 eq {");
- printf("\t\tT stringwidth pop neg %.3f add %.3f } {\n",
- PageRight - PageLeft - 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- printf("\t\t%.3f %.3f } ifelse\n", 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- }
- else
- printf("\t%.3f %.3f\n", 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
-
- puts("\tmoveto T show");
+ x = 0.33 * print_width;
- printf("\tD dup stringwidth pop neg 2 div %.3f add %.3f\n",
- (PageRight - PageLeft) * 0.5,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- puts("\tmoveto show");
+ if (banner->show & SHOW_PRINTER_NAME)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Printer Name: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, getenv("PRINTER"));
+ }
+ if (banner->show & SHOW_JOB_ID)
+ {
+ snprintf(text, sizeof(text), "%s-%d", getenv("PRINTER"), job_id);
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Job ID: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
+ }
+ if (banner->show & SHOW_JOB_UUID)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Job UUID: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
+ cupsGetOption("job-uuid", num_options, options));
+ }
+ if (banner->show & SHOW_JOB_NAME)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Title: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, title);
+ }
+ if (banner->show & SHOW_JOB_ORIGINATING_USER_NAME)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Printed For: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, username);
+ }
+ if (banner->show & SHOW_JOB_ORIGINATING_HOST_NAME)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Printed From: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
+ cupsGetOption("job-originating-host-name", num_options,
+ options));
+ }
+ if (banner->show & SHOW_JOB_BILLING)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Billing Information: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
+ cupsGetOption("job-billing", num_options, options));
+ }
+ if (banner->show & SHOW_OPTIONS)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Options: ")));
- if (Duplex)
- {
- puts("\tdup n exch 2 mod 0 eq {");
- printf("\t\t%.3f %.3f } {\n", 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- printf("\t\tdup stringwidth pop neg %.3f add %.3f } ifelse\n",
- PageRight - PageLeft - 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
- }
- else
- printf("\tn dup stringwidth pop neg %.3f add %.3f\n",
- PageRight - PageLeft - 36.0f / LinesPerInch,
- (0.5f + 0.157f) * 72.0f / LinesPerInch);
+ for (j = 0; j < num_options; j ++)
+ {
+ if (strcasecmp("media", options[j].name) &&
+ strcasecmp("PageSize", options[j].name) &&
+ strcasecmp("PageRegion", options[j].name) &&
+ strcasecmp("InputSlot", options[j].name) &&
+ strcasecmp("MediaType", options[j].name) &&
+ strcasecmp("finishings", options[j].name) &&
+ strcasecmp("sides", options[j].name) &&
+ strcasecmp("Duplex", options[j].name) &&
+ strcasecmp("orientation-requested", options[j].name) &&
+ strcasecmp("landscape", options[j].name) &&
+ strcasecmp("number-up", options[j].name) &&
+ strcasecmp("OutputOrder", options[j].name))
+ continue;
+
+ if (!strcasecmp("landscape", options[j].name))
+ strlcpy(text, "orientation-requested=landscape", sizeof(text));
+ else if (!strcasecmp("orientation-requested", options[j].name))
+ {
+ switch (atoi(options[j].value))
+ {
+ default :
+ case IPP_PORTRAIT :
+ strlcpy(text, "orientation-requested=portrait",
+ sizeof(text));
+ break;
+
+ case IPP_LANDSCAPE :
+ strlcpy(text, "orientation-requested=landscape",
+ sizeof(text));
+ break;
+
+ case IPP_REVERSE_PORTRAIT :
+ strlcpy(text, "orientation-requested=reverse-portrait",
+ sizeof(text));
+ break;
+
+ case IPP_REVERSE_LANDSCAPE :
+ strlcpy(text, "orientation-requested=reverse-landscape",
+ sizeof(text));
+ break;
+ }
+ }
+ else
+ snprintf(text, sizeof(text), "%s=%s", options[j].name,
+ options[j].value);
+
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
+ }
+ }
- puts("\tmoveto show");
- puts("\tgrestore");
- puts("} bind def");
- }
- else
- puts("/S { show } bind def");
+ if (banner->show & SHOW_PRINTER_INFO)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Description: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
+ getenv("PRINTER_INFO"));
+ }
+ if (banner->show & SHOW_PRINTER_LOCATION)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Location: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
+ getenv("PRINTER_LOCATION"));
+ }
+ if (banner->show & SHOW_PRINTER_MAKE_AND_MODEL)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Make and Model: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
+ ppd ? ppd->nickname : NULL);
+ }
- puts("%%EndResource");
+ if (banner->show & SHOW_PAPER_NAME)
+ {
+ if ((option = cupsGetOption("media", num_options, options)) == NULL)
+ if ((option = cupsGetOption("PageSize", num_options, options)) == NULL)
+ if ((option = cupsGetOption("PageRegion", num_options,
+ options)) == NULL)
+ option = "Default";
+
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Media Name: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, option);
+ }
+ if (banner->show & SHOW_PAPER_SIZE)
+ {
+ snprintf(text, sizeof(text),
+ _cupsLangString(language, _("%.2f x %.2f inches")),
+ PageWidth / 72.0, PageLength / 72.0);
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Media Dimensions: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
+
+ snprintf(text, sizeof(text),
+ _cupsLangString(language, _("%.0f x %.0f millimeters")),
+ PageWidth * 25.4 / 72.0, PageLength * 25.4 / 72.0);
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
+ }
+ if (banner->show & SHOW_IMAGEABLE_AREA)
+ {
+ snprintf(text, sizeof(text),
+ _cupsLangString(language,
+ _("%.2f x %.2f to %.2f x %.2f inches")),
+ PageLeft / 72.0, PageBottom / 72.0,
+ PageRight / 72.0, PageTop / 72.0);
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Media Limits: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
+
+ snprintf(text, sizeof(text),
+ _cupsLangString(language,
+ _("%.0f x %.0f to %.0f x %.0f millimeters")),
+ PageLeft * 25.4 / 72.0, PageBottom * 25.4 / 72.0,
+ PageRight * 25.4 / 72.0, PageTop * 25.4 / 72.0);
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
+
+ printf("gsave 2 setlinewidth 1 1 %.1f %.1f rectstroke grestore\n",
+ print_width - 2.0, print_height - 2.0);
+ }
+ if (banner->show & SHOW_PRINTER_DRIVER_NAME)
+ {
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Driver Name: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
+ ppd ? ppd->pcfilename : NULL);
+ }
+ if (banner->show & SHOW_PRINTER_DRIVER_VERSION)
+ {
+ ppd_attr_t *file_version = ppdFindAttr(ppd, "FileVersion", NULL);
+
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Driver Version: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
+ file_version ? file_version->value : NULL);
+ }
+ if (banner->show & SHOW_TIME_AT_CREATION)
+ {
+ if ((option = cupsGetOption("time-at-creation", num_options,
+ options)) != NULL)
+ {
+ time_t curtime; /* Current time */
+ struct tm *curdate; /* Current date */
- puts("%%EndProlog");
-}
+ curtime = (time_t)atoi(option);
+ curdate = localtime(&curtime);
+ strftime(text, sizeof(text), "%c", curdate);
+ }
+ else
+ strlcpy(text, "?", sizeof(text));
-/*
- * 'write_line()' - Write a row of text.
- */
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Created On: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
+ }
+ if (banner->show & SHOW_TIME_AT_PROCESSING)
+ {
+ if ((option = cupsGetOption("time-at-processing", num_options,
+ options)) != NULL)
+ {
+ time_t curtime; /* Current time */
+ struct tm *curdate; /* Current date */
-static void
-write_line(int row, /* I - Row number (0 to N) */
- lchar_t *line) /* I - Line to print */
-{
- int i; /* Looping var */
- int col; /* Current column */
- int attr; /* Current attribute */
- int font, /* Font to use */
- lastfont, /* Last font */
- mono; /* Monospaced? */
- lchar_t *start; /* First character in sequence */
+ curtime = (time_t)atoi(option);
+ curdate = localtime(&curtime);
+ strftime(text, sizeof(text), "%c", curdate);
+ }
+ else
+ strlcpy(text, "?", sizeof(text));
- for (col = 0; col < SizeColumns;)
- {
- while (col < SizeColumns && (line->ch == ' ' || line->ch == 0))
- {
- col ++;
- line ++;
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
+ _cupsLangString(language, _("Printed On: ")));
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
+ }
}
- if (col >= SizeColumns)
- break;
+ /*
+ * Notices...
+ */
- if (NumFonts == 1)
+ if (cupsArrayCount(banner->notices))
{
- /*
- * All characters in a single font - assume monospaced...
- */
+ if (banner->show)
+ y -= 2 * line_height;
- attr = line->attr;
- start = line;
+ x = 0.5 * print_width;
- while (col < SizeColumns && line->ch != 0 && attr == line->attr)
+ for (notice = (char *)cupsArrayFirst(banner->notices);
+ notice;
+ notice = (char *)cupsArrayNext(banner->notices))
{
- col ++;
- line ++;
+ printf("%.1f %.1f moveto", x, y);
+ y -= line_height;
+ psTextUTF8(fonts, fontsize, PS_NORMAL, PS_CENTER, notice);
}
-
- write_string(col - (line - start), row, line - start, start);
}
- else
- {
- /*
- * Multiple fonts; break up based on the font...
- */
-
- attr = line->attr;
- start = line;
- lastfont = Chars[line->ch] / 256;
- mono = strncmp(Fonts[lastfont][0], "Courier", 7) == 0;
- col ++;
- line ++;
- if (mono)
- {
- while (col < SizeColumns && line->ch != 0 && attr == line->attr)
- {
- font = Chars[line->ch] / 256;
- if (strncmp(Fonts[font][0], "Courier", 7) != 0 ||
- font != lastfont)
- break;
+ /*
+ * Images...
+ */
- col ++;
- line ++;
- }
- }
+ if (cupsArrayCount(images))
+ {
+ if (banner->show || cupsArrayCount(banner->notices))
+ y -= 2 * line_height;
- if (Directions[lastfont] > 0)
- write_string(col - (line - start), row, line - start, start);
- else
- {
- /*
- * Do right-to-left text...
- */
+ x = 0.5 * (print_width - images_width);
- while (col < SizeColumns && line->ch != 0 && attr == line->attr)
+ for (image = (cups_image_t *)cupsArrayFirst(images);
+ image;
+ image = (cups_image_t *)cupsArrayNext(images))
+ {
+ float temp_width; /* Width of this image */
+ int depth, /* Bytes per pixel */
+ num_cols, /* Number of columns */
+ row, /* Current row */
+ num_rows, /* Number of rows */
+ out_length, /* Length of data to write */
+ out_offset; /* Offset in line buffer */
+ unsigned char *line; /* Data for current row */
+
+
+ depth = cupsImageGetDepth(image);
+ num_cols = cupsImageGetWidth(image);
+ num_rows = cupsImageGetHeight(image);
+ line = malloc(depth * num_cols + 3);
+ temp_width = num_cols * images_height / num_rows;
+
+ printf("gsave %.1f %.1f translate %.3f %.3f scale\n", x, y,
+ temp_width / num_cols, images_height / num_rows);
+ x += temp_width;
+
+ switch (cupsImageGetColorSpace(image))
{
- if (Directions[Chars[line->ch] / 256] > 0 &&
- !ispunct(line->ch & 255) && !isspace(line->ch & 255))
- break;
-
- col ++;
- line ++;
+ default :
+ case CUPS_IMAGE_WHITE :
+ printf("/DeviceGray setcolorspace"
+ "<<"
+ "/ImageType 1"
+ "/Width %d"
+ "/Height %d"
+ "/BitsPerComponent 8"
+ "/Decode[0 1]\n",
+ num_cols, num_rows);
+ break;
+
+ case CUPS_IMAGE_RGB :
+ printf("/DeviceRGB setcolorspace"
+ "<<"
+ "/ImageType 1"
+ "/Width %d"
+ "/Height %d"
+ "/BitsPerComponent 8"
+ "/Decode[0 1 0 1 0 1]\n",
+ num_cols, num_rows);
+ break;
+
+ case CUPS_IMAGE_CMYK :
+ printf("/DeviceCMYK setcolorspace"
+ "<<"
+ "/ImageType 1"
+ "/Width %d"
+ "/Height %d"
+ "/BitsPerComponent 8"
+ "/Decode[0 1 0 1 0 1 0 1]\n",
+ num_cols, num_rows);
+ break;
}
- for (i = 1; start < line; i ++, start ++)
- if (!isspace(start->ch & 255))
- write_string(col - i, row, 1, start);
- }
- }
- }
-}
-
+ puts("/DataSource currentfile"
+ "/ASCII85Decode filter"
+ "/ImageMatrix[1 0 0 -1 0 1]>>image");
-/*
- * 'write_string()' - Write a string of text.
- */
-
-static void
-write_string(int col, /* I - Start column */
- int row, /* I - Row */
- int len, /* I - Number of characters */
- lchar_t *s) /* I - String to print */
-{
- int ch; /* Current character */
- float x, y; /* Position of text */
- unsigned attr; /* Character attributes */
-
-
- /*
- * Position the text and set the font...
- */
-
- if (Duplex && (NumPages & 1) == 0)
- {
- x = PageWidth - PageRight;
- y = PageTop;
- }
- else
- {
- x = PageLeft;
- y = PageTop;
- }
-
- x += (float)col * 72.0f / (float)CharsPerInch;
- y -= (float)(row + 0.843) * 72.0f / (float)LinesPerInch;
-
- attr = s->attr;
+ for (row = 0, out_offset = 0; row < num_rows; row ++)
+ {
+ cupsImageGetRow(image, 0, row, num_cols, line + out_offset);
- if (attr & ATTR_RAISED)
- y += 36.0 / (float)LinesPerInch;
- else if (attr & ATTR_LOWERED)
- y -= 36.0 / (float)LinesPerInch;
+ out_length = num_cols * depth + out_offset;
+ out_offset = out_length & 3;
- if (x == (int)x)
- printf("%.0f ", x);
- else
- printf("%.3f ", x);
+ ps_ascii85(line, out_length, row == (num_rows - 1));
- if (y == (int)y)
- printf("%.0f ", y);
- else
- printf("%.3f ", y);
+ if (out_offset > 0)
+ memcpy(line, line + out_length - out_offset, out_offset);
+ }
- if (attr & ATTR_BOLD)
- putchar('B');
- else if (attr & ATTR_ITALIC)
- putchar('I');
- else
- putchar('N');
+ puts("grestore");
- if (attr & ATTR_UNDERLINE)
- printf(" %.3f U", (float)len * 72.0 / (float)CharsPerInch);
+ if (i == num_pages)
+ cupsImageClose(image);
+ }
+ }
- if (NumFonts > 1)
- {
/*
- * Write a hex string...
+ * Header and footer...
*/
- putchar('<');
+ x = 0.5 * print_width;
- while (len > 0)
+ if (banner->header)
{
- printf("%04x", Chars[s->ch]);
+ printf("%.1f %.1f moveto", x, print_height - 2 * fontsize);
+ psTextUTF8(fonts, 2 * fontsize, PS_BOLD, PS_CENTER, banner->header);
+ }
- len --;
- s ++;
+ if (banner->footer)
+ {
+ printf("%.1f %.1f moveto", x, fontsize);
+ psTextUTF8(fonts, 2 * fontsize, PS_BOLD, PS_CENTER, banner->footer);
}
- putchar('>');
- }
- else
- {
/*
- * Write a quoted string...
+ * Show the page...
*/
- putchar('(');
-
- while (len > 0)
- {
- ch = Chars[s->ch];
-
- if (ch < 32 || ch > 126)
- {
- /*
- * Quote 8-bit and control characters...
- */
-
- printf("\\%03o", ch);
- }
- else
- {
- /*
- * Quote the parenthesis and backslash as needed...
- */
-
- if (ch == '(' || ch == ')' || ch == '\\')
- putchar('\\');
-
- putchar(ch);
- }
-
- len --;
- s ++;
- }
-
- putchar(')');
+ puts("grestore");
+ puts("showpage");
}
- if (PrettyPrint)
- {
- if (attr & ATTR_RED)
- puts("r");
- else if (attr & ATTR_GREEN)
- puts("g");
- else if (attr & ATTR_BLUE)
- puts("b");
- else
- puts("S");
- }
- else
- puts("S");
+ return (num_pages);
}
/*
- * 'write_text()' - Write a text string, quoting/encoding as needed.
+ * 'write_epilogue()' - Write the PostScript file epilogue.
*/
static void
-write_text(const char *s) /* I - String to write */
+write_epilogue(int num_pages) /* I - Number of pages */
{
- int ch; /* Actual character value (UTF8) */
- const unsigned char *utf8; /* UTF8 text */
-
-
- if (NumFonts > 1)
- {
- /*
- * 8/8 encoding...
- */
-
- putchar('<');
+ puts("%%Trailer");
+ printf("%%%%Pages: %d\n", num_pages);
+ puts("%%EOF");
+}
- utf8 = (const unsigned char *)s;
- while (*utf8)
- {
- if (*utf8 < 0xc0 || !UTF8)
- ch = *utf8 ++;
- else if ((*utf8 & 0xe0) == 0xc0)
- {
- /*
- * Two byte character...
- */
-
- ch = ((utf8[0] & 0x1f) << 6) | (utf8[1] & 0x3f);
- utf8 += 2;
- }
- else
- {
- /*
- * Three byte character...
- */
+/*
+ * 'write_prolog()' - Write the PostScript file prolog with options.
+ */
- ch = ((((utf8[0] & 0x1f) << 6) | (utf8[1] & 0x3f)) << 6) |
- (utf8[2] & 0x3f);
- utf8 += 3;
- }
+ps_text_t * /* O - Fonts */
+write_prolog(const char *title, /* I - Title of job */
+ const char *username) /* I - Username */
+{
+ time_t curtime; /* Current time */
+ struct tm *curtm; /* Current date */
+ char curdate[255]; /* Current date (text format) */
+ ps_text_t *fonts; /* Fonts */
- printf("%04x", Chars[ch]);
- }
- putchar('>');
- }
- else
- {
- /*
- * Standard 8-bit encoding...
- */
+ /*
+ * Get the fonts we'll need...
+ */
- putchar('(');
+ fonts = psTextInitialize();
- while (*s)
- {
- if (*s < 32 || *s > 126)
- printf("\\%03o", *s);
- else
- {
- if (*s == '(' || *s == ')' || *s == '\\')
- putchar('\\');
+ /*
+ * Output the DSC header...
+ */
- putchar(*s);
- }
+ curtime = time(NULL);
+ curtm = localtime(&curtime);
+ strftime(curdate, sizeof(curdate), "%c", curtm);
- s ++;
- }
+ puts("%!PS-Adobe-3.0");
+ printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
+ PageRight, PageTop);
+ printf("%%cupsRotation: %d\n", (Orientation & 3) * 90);
+ puts("%%Creator: bannertops/" CUPS_SVERSION);
+ printf("%%%%CreationDate: %s\n", curdate);
+ puts("%%LanguageLevel: 2");
+ puts("%%DocumentData: Clean7Bit");
+ WriteTextComment("Title", title);
+ WriteTextComment("For", username);
+ printf("%%%%Pages: %d\n", Duplex ? 2 : 1);
+ psTextListFonts(fonts);
+ puts("%%EndComments");
+ puts("%%BeginProlog");
+ psTextEmbedFonts(fonts);
+ puts("%%EndProlog");
- putchar(')');
- }
+ return (fonts);
}