]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/bannertops.c
Merge changes from CUPS 1.4svn-r7999.
[thirdparty/cups.git] / filter / bannertops.c
CommitLineData
1f6f3dbc
MS
1/*
2 * "$Id$"
3 *
4 * Banner to PostScript filter for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2008 by Apple Inc.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
13 *
14 * This file is subject to the Apple OS-Developed Software exception.
15 *
16 * Contents:
17 *
18 */
19
20/*
21 * Include necessary headers...
22 */
23
cda47a96 24#include "pstext.h"
1f6f3dbc
MS
25#include "image.h"
26#include <cups/i18n.h>
27
28
29/*
cda47a96 30 * Constants...
1f6f3dbc
MS
31 */
32
cda47a96
MS
33#define SHOW_IMAGEABLE_AREA 1 /* Show imageable area */
34#define SHOW_JOB_BILLING 2 /* Show billing string */
35#define SHOW_JOB_ID 4 /* Show job ID */
36#define SHOW_JOB_NAME 8 /* Show job title */
37#define SHOW_JOB_ORIGINATING_USER_NAME 16 /* Show owner of job */
38#define SHOW_JOB_ORIGINATING_HOST_NAME 32 /* Show submitting system */
39#define SHOW_JOB_UUID 64 /* Show job UUID */
40#define SHOW_OPTIONS 128 /* Show print options */
41#define SHOW_PAPER_NAME 256 /* Show paper size name */
42#define SHOW_PAPER_SIZE 512 /* Show paper dimensions */
43#define SHOW_PRINTER_DRIVER_NAME 1024 /* Show printer driver name */
44#define SHOW_PRINTER_DRIVER_VERSION 2048 /* Show printer driver version */
45#define SHOW_PRINTER_INFO 4096 /* Show printer description */
46#define SHOW_PRINTER_LOCATION 8192 /* Show printer location */
47#define SHOW_PRINTER_MAKE_AND_MODEL 16384 /* Show printer make and model */
48#define SHOW_PRINTER_NAME 32768 /* Show printer queue ID */
49#define SHOW_TIME_AT_CREATION 65536 /* Show date/time when submitted */
50#define SHOW_TIME_AT_PROCESSING 131072 /* Show date/time when printed */
1f6f3dbc
MS
51
52
53/*
cda47a96 54 * Structures...
1f6f3dbc
MS
55 */
56
cda47a96 57typedef struct banner_file_s /**** Banner file data ****/
1f6f3dbc 58{
cda47a96
MS
59 int show; /* What to show */
60 char *header, /* Header text */
61 *footer; /* Footer text */
62 cups_array_t *notices, /* Notices to show */
63 *images; /* Images to show */
64} banner_file_t;
1f6f3dbc
MS
65
66
67/*
cda47a96 68 * Local functions...
1f6f3dbc
MS
69 */
70
cda47a96
MS
71static banner_file_t *load_banner(const char *filename);
72static int write_banner(banner_file_t *banner, ppd_file_t *ppd,
73 ps_text_t *fonts, int job_id,
74 const char *title, const char *username,
75 int num_options, cups_option_t *options);
76static void write_epilogue(int num_pages);
77static ps_text_t *write_prolog(const char *title, const char *user);
1f6f3dbc
MS
78
79
80/*
cda47a96 81 * 'main()' - Generate PostScript cover pages.
1f6f3dbc
MS
82 */
83
cda47a96
MS
84int /* O - Exit status */
85main(int argc, /* I - Number of command-line args */
86 char *argv[]) /* I - Command-line arguments */
1f6f3dbc 87{
cda47a96
MS
88 banner_file_t *banner; /* Banner file data */
89 int num_options; /* Number of print options */
90 cups_option_t *options; /* Print options */
91 ppd_file_t *ppd; /* PPD file */
92 ps_text_t *fonts; /* Fonts for output */
93 int job_id; /* Job ID from command-line */
94 const char *title, /* Title from command-line */
95 *username; /* Username from command-line */
96 int num_pages; /* Number of pages printed */
1f6f3dbc
MS
97
98
99 /*
cda47a96 100 * Make sure status messages are not buffered...
1f6f3dbc
MS
101 */
102
cda47a96 103 setbuf(stderr, NULL);
1f6f3dbc
MS
104
105 /*
cda47a96 106 * Check command-line...
1f6f3dbc
MS
107 */
108
cda47a96 109 if (argc < 6 || argc > 7)
1f6f3dbc 110 {
cda47a96
MS
111 _cupsLangPrintf(stderr,
112 _("Usage: %s job-id user title copies options [file]\n"),
113 "bannertops");
114 return (1);
1f6f3dbc
MS
115 }
116
117 /*
cda47a96 118 * Get stuff from command-line...
1f6f3dbc
MS
119 */
120
cda47a96
MS
121 job_id = atoi(argv[1]);
122 username = argv[2];
123 title = argv[3];
124 options = NULL;
125 num_options = cupsParseOptions(argv[5], 0, &options);
126 banner = load_banner(argv[6]);
1f6f3dbc 127
cda47a96
MS
128 /*
129 * Set standard options and get the PPD file for this printer...
130 */
1f6f3dbc 131
cda47a96 132 ppd = SetCommonOptions(num_options, options, 1);
1f6f3dbc
MS
133
134 /*
cda47a96 135 * Write a PostScript banner document and return...
1f6f3dbc
MS
136 */
137
cda47a96
MS
138 fonts = write_prolog(title, username);
139 num_pages = write_banner(banner, ppd, fonts, job_id, title, username,
140 num_options, options);
1f6f3dbc 141
cda47a96 142 write_epilogue(num_pages);
1f6f3dbc 143
cda47a96
MS
144 return (0);
145}
1f6f3dbc 146
1f6f3dbc 147
cda47a96
MS
148/*
149 * 'load_banner()' - Load the banner file.
150 */
1f6f3dbc 151
cda47a96
MS
152static banner_file_t * /* O - Banner file data */
153load_banner(const char *filename) /* I - Filename or NULL for stdin */
154{
155 cups_file_t *fp; /* File */
156 char line[2048], /* Line buffer */
157 *ptr; /* Pointer into line */
158 int linenum; /* Current line number */
159 banner_file_t *banner; /* Banner file data */
160 const char *cups_docroot; /* CUPS_DOCROOT environment variable */
1f6f3dbc 161
1f6f3dbc 162
cda47a96
MS
163 fprintf(stderr, "DEBUG: load_banner(filename=\"%s\")\n",
164 filename ? filename : "(stdin)");
165
166 /*
167 * Open the banner file...
168 */
169
170 if (filename)
171 fp = cupsFileOpen(filename, "r");
1f6f3dbc 172 else
cda47a96
MS
173 fp = cupsFileStdin();
174
175 if (!fp)
1f6f3dbc 176 {
cda47a96
MS
177 _cupsLangPrintf(stderr,
178 _("ERROR: Unable to open banner file \"%s\" - %s\n"),
179 filename ? filename : "(stdin)", strerror(errno));
1f6f3dbc
MS
180 exit(1);
181 }
182
183 /*
cda47a96 184 * Read the banner file...
1f6f3dbc
MS
185 */
186
cda47a96
MS
187 if ((cups_docroot = getenv("CUPS_DOCROOT")) == NULL)
188 cups_docroot = CUPS_DOCROOT;
189
190 banner = calloc(1, sizeof(banner_file_t));
191 linenum = 0;
192
193 while (cupsFileGets(fp, line, sizeof(line)))
1f6f3dbc 194 {
cda47a96
MS
195 /*
196 * Skip blank and comment lines...
197 */
1f6f3dbc 198
cda47a96 199 linenum ++;
1f6f3dbc 200
cda47a96
MS
201 if (line[0] == '#' || !line[0])
202 continue;
1f6f3dbc
MS
203
204 /*
cda47a96 205 * Break the line into keyword and value parts...
1f6f3dbc
MS
206 */
207
cda47a96 208 for (ptr = line; *ptr && !isspace(*ptr & 255); ptr ++);
1f6f3dbc 209
cda47a96
MS
210 while (isspace(*ptr & 255))
211 *ptr++ = '\0';
1f6f3dbc 212
cda47a96 213 if (!*ptr)
1f6f3dbc 214 {
cda47a96
MS
215 _cupsLangPrintf(stderr,
216 _("ERROR: Missing value on line %d of banner file!\n"),
217 linenum);
218 continue;
1f6f3dbc
MS
219 }
220
221 /*
cda47a96 222 * Save keyword values in the appropriate places...
1f6f3dbc
MS
223 */
224
cda47a96 225 if (!strcasecmp(line, "Footer"))
1f6f3dbc 226 {
cda47a96
MS
227 if (banner->footer)
228 fprintf(stderr, "DEBUG: Extra \"Footer\" on line %d of banner file!\n",
229 linenum);
230 else
231 banner->footer = strdup(ptr);
232 }
233 else if (!strcasecmp(line, "Header"))
234 {
235 if (banner->header)
236 fprintf(stderr, "DEBUG: Extra \"Header\" on line %d of banner file!\n",
237 linenum);
238 else
239 banner->header = strdup(ptr);
240 }
241 else if (!strcasecmp(line, "Image"))
242 {
243 char imagefile[1024]; /* Image filename */
1f6f3dbc 244
1f6f3dbc 245
cda47a96
MS
246 if (ptr[0] == '/')
247 strlcpy(imagefile, ptr, sizeof(imagefile));
248 else
249 snprintf(imagefile, sizeof(imagefile), "%s/%s", cups_docroot, ptr);
1f6f3dbc 250
cda47a96 251 if (access(imagefile, R_OK))
1f6f3dbc 252 {
cda47a96
MS
253 fprintf(stderr, "DEBUG: Image \"%s\" on line %d of banner file: %s\n",
254 ptr, linenum, strerror(errno));
1f6f3dbc 255 }
cda47a96 256 else
1f6f3dbc 257 {
cda47a96
MS
258 if (!banner->images)
259 banner->images = cupsArrayNew(NULL, NULL);
1f6f3dbc 260
cda47a96 261 cupsArrayAdd(banner->images, strdup(imagefile));
1f6f3dbc 262 }
1f6f3dbc 263 }
cda47a96 264 else if (!strcasecmp(line, "Notice"))
1f6f3dbc 265 {
cda47a96
MS
266 if (!banner->notices)
267 banner->notices = cupsArrayNew(NULL, NULL);
1f6f3dbc 268
cda47a96
MS
269 cupsArrayAdd(banner->notices, strdup(ptr));
270 }
271 else if (!strcasecmp(line, "Show"))
272 {
273 char *value; /* Current value */
1f6f3dbc 274
1f6f3dbc 275
cda47a96 276 for (value = ptr; *value; value = ptr)
1f6f3dbc
MS
277 {
278 /*
cda47a96 279 * Find the end of the current value
1f6f3dbc
MS
280 */
281
cda47a96
MS
282 while (*ptr && !isspace(*ptr & 255))
283 ptr ++;
1f6f3dbc 284
cda47a96
MS
285 while (*ptr && isspace(*ptr & 255))
286 *ptr++ = '\0';
1f6f3dbc
MS
287
288 /*
cda47a96 289 * Add the value to the show flags...
1f6f3dbc 290 */
cda47a96
MS
291 if (!strcasecmp(value, "imageable-area"))
292 banner->show |= SHOW_IMAGEABLE_AREA;
293 else if (!strcasecmp(value, "job-billing"))
294 banner->show |= SHOW_JOB_BILLING;
295 else if (!strcasecmp(value, "job-id"))
296 banner->show |= SHOW_JOB_ID;
297 else if (!strcasecmp(value, "job-name"))
298 banner->show |= SHOW_JOB_NAME;
299 else if (!strcasecmp(value, "job-originating-host-name"))
300 banner->show |= SHOW_JOB_ORIGINATING_HOST_NAME;
301 else if (!strcasecmp(value, "job-originating-user-name"))
302 banner->show |= SHOW_JOB_ORIGINATING_USER_NAME;
303 else if (!strcasecmp(value, "job-uuid"))
304 banner->show |= SHOW_JOB_UUID;
305 else if (!strcasecmp(value, "options"))
306 banner->show |= SHOW_OPTIONS;
307 else if (!strcasecmp(value, "paper-name"))
308 banner->show |= SHOW_PAPER_NAME;
309 else if (!strcasecmp(value, "paper-size"))
310 banner->show |= SHOW_PAPER_SIZE;
311 else if (!strcasecmp(value, "printer-driver-name"))
312 banner->show |= SHOW_PRINTER_DRIVER_NAME;
313 else if (!strcasecmp(value, "printer-driver-version"))
314 banner->show |= SHOW_PRINTER_DRIVER_VERSION;
315 else if (!strcasecmp(value, "printer-info"))
316 banner->show |= SHOW_PRINTER_INFO;
317 else if (!strcasecmp(value, "printer-location"))
318 banner->show |= SHOW_PRINTER_LOCATION;
319 else if (!strcasecmp(value, "printer-make-and-model"))
320 banner->show |= SHOW_PRINTER_MAKE_AND_MODEL;
321 else if (!strcasecmp(value, "printer-name"))
322 banner->show |= SHOW_PRINTER_NAME;
323 else if (!strcasecmp(value, "time-at-creation"))
324 banner->show |= SHOW_TIME_AT_CREATION;
325 else if (!strcasecmp(value, "time-at-processing"))
326 banner->show |= SHOW_TIME_AT_PROCESSING;
327 else
328 {
329 fprintf(stderr,
330 "DEBUG: Unknown \"Show\" value \"%s\" on line %d of banner "
331 "file!\n", value, linenum);
1f6f3dbc 332 }
1f6f3dbc 333 }
1f6f3dbc
MS
334 }
335 else
cda47a96
MS
336 fprintf(stderr, "DEBUG: Unknown key \"%s\" on line %d of banner file!\n",
337 line, linenum);
1f6f3dbc 338 }
1f6f3dbc 339
cda47a96
MS
340 if (filename)
341 cupsFileClose(fp);
1f6f3dbc 342
cda47a96
MS
343 return (banner);
344}
1f6f3dbc 345
1f6f3dbc 346
cda47a96
MS
347/*
348 * 'ps_ascii85()' - Print binary data as a series of base-85 numbers.
349 */
1f6f3dbc 350
cda47a96
MS
351static void
352ps_ascii85(cups_ib_t *data, /* I - Data to print */
353 int length, /* I - Number of bytes to print */
354 int last_line) /* I - Last line of raster data? */
355{
356 unsigned b; /* Binary data word */
357 unsigned char c[5]; /* ASCII85 encoded chars */
358 static int col = 0; /* Current column */
1f6f3dbc 359
1f6f3dbc 360
cda47a96
MS
361 while (length > 3)
362 {
363 b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
1f6f3dbc 364
cda47a96
MS
365 if (b == 0)
366 {
367 putchar('z');
368 col ++;
1f6f3dbc 369 }
1f6f3dbc 370 else
1f6f3dbc 371 {
cda47a96
MS
372 c[4] = (b % 85) + '!';
373 b /= 85;
374 c[3] = (b % 85) + '!';
375 b /= 85;
376 c[2] = (b % 85) + '!';
377 b /= 85;
378 c[1] = (b % 85) + '!';
379 b /= 85;
380 c[0] = b + '!';
381
382 fwrite(c, 5, 1, stdout);
383 col += 5;
1f6f3dbc 384 }
1f6f3dbc 385
cda47a96
MS
386 data += 4;
387 length -= 4;
1f6f3dbc 388
cda47a96
MS
389 if (col >= 75)
390 {
391 putchar('\n');
392 col = 0;
1f6f3dbc
MS
393 }
394 }
395
cda47a96 396 if (last_line)
1f6f3dbc 397 {
cda47a96 398 if (length > 0)
1f6f3dbc 399 {
cda47a96
MS
400 memset(data + length, 0, 4 - length);
401 b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
402
403 c[4] = (b % 85) + '!';
404 b /= 85;
405 c[3] = (b % 85) + '!';
406 b /= 85;
407 c[2] = (b % 85) + '!';
408 b /= 85;
409 c[1] = (b % 85) + '!';
410 b /= 85;
411 c[0] = b + '!';
412
413 fwrite(c, length + 1, 1, stdout);
1f6f3dbc 414 }
1f6f3dbc 415
cda47a96
MS
416 puts("~>");
417 col = 0;
418 }
419}
1f6f3dbc 420
1f6f3dbc 421
cda47a96
MS
422/*
423 * 'write_banner()' - Write a banner page...
424 */
1f6f3dbc 425
cda47a96
MS
426static int /* O - Number of pages */
427write_banner(banner_file_t *banner, /* I - Banner file */
428 ppd_file_t *ppd, /* I - PPD file */
429 ps_text_t *fonts, /* I - Fonts */
430 int job_id, /* I - Job ID */
431 const char *title, /* I - Title of job */
432 const char *username, /* I - Owner of job */
433 int num_options, /* I - Number of options */
434 cups_option_t *options) /* I - Options */
435{
436 char *notice; /* Current notice */
437 char *imagefile; /* Current image file */
438 cups_array_t *images; /* Images */
439 cups_image_t *image; /* Current image */
440 const char *option; /* Option value */
441 int i, j; /* Looping vars */
442 float x, /* Current X position */
443 y; /* Current Y position */
444 cups_lang_t *language; /* Default language */
445 int showlines; /* Number of lines to show */
446 float fontsize; /* Font size to use */
447 int num_pages; /* Number of pages */
448 float print_width, /* Printable width of page */
449 print_height, /* Printable height of page */
450 info_top, /* Top of info fields */
451 info_height, /* Height of info fields */
452 line_height, /* Height of info lines */
453 notices_height, /* Height of all notices */
454 images_width, /* Width of all images */
455 images_height, /* Height of all images */
456 total_height; /* Height of all content */
457 char text[1024]; /* Formatted field text */
1f6f3dbc 458
1f6f3dbc
MS
459
460 /*
cda47a96 461 * Figure out how many lines of text will be shown...
1f6f3dbc
MS
462 */
463
cda47a96
MS
464 showlines = 0;
465 if (banner->show & SHOW_IMAGEABLE_AREA)
466 showlines += 2;
467 if (banner->show & SHOW_JOB_BILLING)
468 showlines ++;
469 if (banner->show & SHOW_JOB_ID)
470 showlines ++;
471 if (banner->show & SHOW_JOB_NAME)
472 showlines ++;
473 if (banner->show & SHOW_JOB_ORIGINATING_USER_NAME)
474 showlines ++;
475 if (banner->show & SHOW_JOB_ORIGINATING_HOST_NAME)
476 showlines ++;
477 if (banner->show & SHOW_JOB_UUID)
478 showlines ++;
479 if (banner->show & SHOW_OPTIONS)
1f6f3dbc 480 {
cda47a96 481 for (j = 0; j < num_options; j ++)
1f6f3dbc 482 {
cda47a96
MS
483 if (strcasecmp("media", options[j].name) &&
484 strcasecmp("PageSize", options[j].name) &&
485 strcasecmp("PageRegion", options[j].name) &&
486 strcasecmp("InputSlot", options[j].name) &&
487 strcasecmp("MediaType", options[j].name) &&
488 strcasecmp("finishings", options[j].name) &&
489 strcasecmp("sides", options[j].name) &&
490 strcasecmp("Duplex", options[j].name) &&
491 strcasecmp("orientation-requested", options[j].name) &&
492 strcasecmp("landscape", options[j].name) &&
493 strcasecmp("number-up", options[j].name) &&
494 strcasecmp("OutputOrder", options[j].name))
495 continue;
496
497 showlines ++;
1f6f3dbc 498 }
1f6f3dbc 499 }
cda47a96
MS
500 if (banner->show & SHOW_PAPER_NAME)
501 showlines ++;
502 if (banner->show & SHOW_PAPER_SIZE)
503 showlines += 2;
504 if (banner->show & SHOW_PRINTER_DRIVER_NAME)
505 showlines ++;
506 if (banner->show & SHOW_PRINTER_DRIVER_VERSION)
507 showlines ++;
508 if (banner->show & SHOW_PRINTER_INFO)
509 showlines ++;
510 if (banner->show & SHOW_PRINTER_LOCATION)
511 showlines ++;
512 if (banner->show & SHOW_PRINTER_MAKE_AND_MODEL)
513 showlines ++;
514 if (banner->show & SHOW_PRINTER_NAME)
515 showlines ++;
516 if (banner->show & SHOW_TIME_AT_CREATION)
517 showlines ++;
518 if (banner->show & SHOW_TIME_AT_PROCESSING)
519 showlines ++;
1f6f3dbc
MS
520
521 /*
cda47a96 522 * Figure out the dimensions and positions of everything...
1f6f3dbc
MS
523 */
524
cda47a96
MS
525 print_width = PageRight - PageLeft;
526 print_height = PageTop - PageBottom;
527 fontsize = print_height / 60; /* Nominally 12pts */
528 line_height = 1.2 * fontsize;
529 info_height = showlines * line_height;
530 notices_height = cupsArrayCount(banner->notices) * line_height;
1f6f3dbc 531
cda47a96
MS
532 if (cupsArrayCount(banner->images))
533 {
534 images = cupsArrayNew(NULL, NULL);
535 images_height = print_height / 10; /* Nominally 1" */
1f6f3dbc 536
cda47a96
MS
537 for (imagefile = (char *)cupsArrayFirst(banner->images), images_width = 0.0;
538 imagefile;
539 imagefile = (char *)cupsArrayNext(banner->images))
1f6f3dbc 540 {
cda47a96
MS
541 if ((image = cupsImageOpen(imagefile, ColorDevice ? CUPS_IMAGE_RGB_CMYK :
542 CUPS_IMAGE_WHITE,
543 CUPS_IMAGE_WHITE, 100, 0, NULL)) == NULL)
544 {
545 fprintf(stderr, "DEBUG: Unable to open image file \"%s\"!\n",
546 imagefile);
547 continue;
548 }
549
550 images_width += cupsImageGetWidth(image) * images_height /
551 cupsImageGetHeight(image);
552 cupsArrayAdd(images, image);
1f6f3dbc
MS
553 }
554 }
555 else
556 {
cda47a96
MS
557 images = NULL;
558 images_height = 0;
559 }
1f6f3dbc 560
cda47a96
MS
561 total_height = info_height + notices_height + images_height;
562 if (cupsArrayCount(banner->notices) && showlines)
563 total_height += 2 * line_height;
564 if (cupsArrayCount(banner->images) &&
565 (showlines || cupsArrayCount(banner->notices)))
566 total_height += 2 * line_height;
1f6f3dbc 567
cda47a96 568 info_top = 0.5 * (print_height + total_height);
1f6f3dbc
MS
569
570 /*
cda47a96 571 * Write the page(s)...
1f6f3dbc
MS
572 */
573
cda47a96
MS
574 language = cupsLangDefault();
575 num_pages = Duplex ? 2 : 1;
1f6f3dbc 576
cda47a96 577 for (i = 1; i <= num_pages; i ++)
1f6f3dbc 578 {
cda47a96
MS
579 /*
580 * Start the page...
581 */
1f6f3dbc 582
cda47a96
MS
583 printf("%%Page: %s %d\n", i == 1 ? "coverpage" : "coverback", i);
584 puts("gsave");
585 printf("%.1f %.1f translate\n", PageLeft, PageBottom);
586 puts("0 setgray");
1f6f3dbc 587
cda47a96 588 y = info_top;
1f6f3dbc 589
cda47a96
MS
590 /*
591 * Information...
592 */
1f6f3dbc 593
cda47a96 594 if (banner->show)
1f6f3dbc 595 {
cda47a96 596 x = 0.33 * print_width;
1f6f3dbc 597
cda47a96
MS
598 if (banner->show & SHOW_PRINTER_NAME)
599 {
600 printf("%.1f %.1f moveto", x, y);
601 y -= line_height;
602 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
603 _cupsLangString(language, _("Printer Name: ")));
604 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, getenv("PRINTER_NAME"));
605 }
606 if (banner->show & SHOW_JOB_ID)
607 {
608 snprintf(text, sizeof(text), "%s-%d", getenv("PRINTER_NAME"), job_id);
609 printf("%.1f %.1f moveto", x, y);
610 y -= line_height;
611 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
612 _cupsLangString(language, _("Job ID: ")));
613 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
614 }
615 if (banner->show & SHOW_JOB_UUID)
616 {
617 printf("%.1f %.1f moveto", x, y);
618 y -= line_height;
619 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
620 _cupsLangString(language, _("Job UUID: ")));
621 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
622 cupsGetOption("job-uuid", num_options, options));
623 }
624 if (banner->show & SHOW_JOB_NAME)
625 {
626 printf("%.1f %.1f moveto", x, y);
627 y -= line_height;
628 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
629 _cupsLangString(language, _("Title: ")));
630 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, title);
631 }
632 if (banner->show & SHOW_JOB_ORIGINATING_USER_NAME)
633 {
634 printf("%.1f %.1f moveto", x, y);
635 y -= line_height;
636 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
637 _cupsLangString(language, _("Printed For: ")));
638 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, username);
639 }
640 if (banner->show & SHOW_JOB_ORIGINATING_HOST_NAME)
641 {
642 printf("%.1f %.1f moveto", x, y);
643 y -= line_height;
644 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
645 _cupsLangString(language, _("Printed From: ")));
646 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
647 cupsGetOption("job-originating-host-name", num_options,
648 options));
649 }
650 if (banner->show & SHOW_JOB_BILLING)
651 {
652 printf("%.1f %.1f moveto", x, y);
653 y -= line_height;
654 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
655 _cupsLangString(language, _("Billing Information: ")));
656 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
657 cupsGetOption("job-billing", num_options, options));
658 }
659 if (banner->show & SHOW_OPTIONS)
660 {
661 printf("%.1f %.1f moveto", x, y);
662 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
663 _cupsLangString(language, _("Options: ")));
1f6f3dbc 664
cda47a96
MS
665 for (j = 0; j < num_options; j ++)
666 {
667 if (strcasecmp("media", options[j].name) &&
668 strcasecmp("PageSize", options[j].name) &&
669 strcasecmp("PageRegion", options[j].name) &&
670 strcasecmp("InputSlot", options[j].name) &&
671 strcasecmp("MediaType", options[j].name) &&
672 strcasecmp("finishings", options[j].name) &&
673 strcasecmp("sides", options[j].name) &&
674 strcasecmp("Duplex", options[j].name) &&
675 strcasecmp("orientation-requested", options[j].name) &&
676 strcasecmp("landscape", options[j].name) &&
677 strcasecmp("number-up", options[j].name) &&
678 strcasecmp("OutputOrder", options[j].name))
679 continue;
680
681 if (!strcasecmp("landscape", options[j].name))
682 strlcpy(text, "orientation-requested=landscape", sizeof(text));
683 else if (!strcasecmp("orientation-requested", options[j].name))
684 {
685 switch (atoi(options[j].value))
686 {
687 default :
688 case IPP_PORTRAIT :
689 strlcpy(text, "orientation-requested=portrait",
690 sizeof(text));
691 break;
692
693 case IPP_LANDSCAPE :
694 strlcpy(text, "orientation-requested=landscape",
695 sizeof(text));
696 break;
697
698 case IPP_REVERSE_PORTRAIT :
699 strlcpy(text, "orientation-requested=reverse-portrait",
700 sizeof(text));
701 break;
702
703 case IPP_REVERSE_LANDSCAPE :
704 strlcpy(text, "orientation-requested=reverse-landscape",
705 sizeof(text));
706 break;
707 }
708 }
709 else
710 snprintf(text, sizeof(text), "%s=%s", options[j].name,
711 options[j].value);
712
713 printf("%.1f %.1f moveto", x, y);
714 y -= line_height;
715 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
716 }
717 }
1f6f3dbc 718
cda47a96
MS
719 if (banner->show & SHOW_PRINTER_INFO)
720 {
721 printf("%.1f %.1f moveto", x, y);
722 y -= line_height;
723 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
724 _cupsLangString(language, _("Description: ")));
725 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
726 getenv("PRINTER_INFO"));
727 }
728 if (banner->show & SHOW_PRINTER_LOCATION)
729 {
730 printf("%.1f %.1f moveto", x, y);
731 y -= line_height;
732 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
733 _cupsLangString(language, _("Location: ")));
734 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
735 getenv("PRINTER_LOCATION"));
736 }
737 if (banner->show & SHOW_PRINTER_MAKE_AND_MODEL)
738 {
739 printf("%.1f %.1f moveto", x, y);
740 y -= line_height;
741 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
742 _cupsLangString(language, _("Make and Model: ")));
743 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
744 ppd ? ppd->nickname : NULL);
745 }
1f6f3dbc 746
cda47a96
MS
747 if (banner->show & SHOW_PAPER_NAME)
748 {
749 if ((option = cupsGetOption("media", num_options, options)) == NULL)
750 if ((option = cupsGetOption("PageSize", num_options, options)) == NULL)
751 if ((option = cupsGetOption("PageRegion", num_options,
752 options)) == NULL)
753 option = "Default";
754
755 printf("%.1f %.1f moveto", x, y);
756 y -= line_height;
757 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
758 _cupsLangString(language, _("Media Name: ")));
759 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, option);
760 }
761 if (banner->show & SHOW_PAPER_SIZE)
762 {
763 snprintf(text, sizeof(text),
764 _cupsLangString(language, _("%.2f x %.2f inches")),
765 PageWidth / 72.0, PageLength / 72.0);
766 printf("%.1f %.1f moveto", x, y);
767 y -= line_height;
768 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
769 _cupsLangString(language, _("Media Dimensions: ")));
770 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
771
772 snprintf(text, sizeof(text),
773 _cupsLangString(language, _("%.0f x %.0f millimeters")),
774 PageWidth * 25.4 / 72.0, PageLength * 25.4 / 72.0);
775 printf("%.1f %.1f moveto", x, y);
776 y -= line_height;
777 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
778 }
779 if (banner->show & SHOW_IMAGEABLE_AREA)
780 {
781 snprintf(text, sizeof(text),
782 _cupsLangString(language,
783 _("%.2f x %.2f to %.2f x %.2f inches")),
784 PageLeft / 72.0, PageBottom / 72.0,
785 PageRight / 72.0, PageTop / 72.0);
786 printf("%.1f %.1f moveto", x, y);
787 y -= line_height;
788 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
789 _cupsLangString(language, _("Media Limits: ")));
790 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
791
792 snprintf(text, sizeof(text),
793 _cupsLangString(language,
794 _("%.0f x %.0f to %.0f x %.0f millimeters")),
795 PageLeft * 25.4 / 72.0, PageBottom * 25.4 / 72.0,
796 PageRight * 25.4 / 72.0, PageTop * 25.4 / 72.0);
797 printf("%.1f %.1f moveto", x, y);
798 y -= line_height;
799 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
800
801 printf("gsave 2 setlinewidth 1 1 %.1f %.1f rectstroke grestore\n",
802 print_width - 2.0, print_height - 2.0);
803 }
804 if (banner->show & SHOW_PRINTER_DRIVER_NAME)
805 {
806 printf("%.1f %.1f moveto", x, y);
807 y -= line_height;
808 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
809 _cupsLangString(language, _("Driver Name: ")));
810 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
811 ppd ? ppd->pcfilename : NULL);
812 }
813 if (banner->show & SHOW_PRINTER_DRIVER_VERSION)
814 {
815 ppd_attr_t *file_version = ppdFindAttr(ppd, "FileVersion", NULL);
816
817 printf("%.1f %.1f moveto", x, y);
818 y -= line_height;
819 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
820 _cupsLangString(language, _("Driver Version: ")));
821 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT,
822 file_version ? file_version->value : NULL);
823 }
824 if (banner->show & SHOW_TIME_AT_CREATION)
825 {
826 if ((option = cupsGetOption("time-at-creation", num_options,
827 options)) != NULL)
828 {
829 time_t curtime; /* Current time */
830 struct tm *curdate; /* Current date */
1f6f3dbc 831
cda47a96
MS
832 curtime = (time_t)atoi(option);
833 curdate = localtime(&curtime);
1f6f3dbc 834
cda47a96
MS
835 strftime(text, sizeof(text), "%c", curdate);
836 }
837 else
838 strlcpy(text, "?", sizeof(text));
1f6f3dbc 839
cda47a96
MS
840 printf("%.1f %.1f moveto", x, y);
841 y -= line_height;
842 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
843 _cupsLangString(language, _("Created On: ")));
844 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
845 }
846 if (banner->show & SHOW_TIME_AT_PROCESSING)
847 {
848 if ((option = cupsGetOption("time-at-processing", num_options,
849 options)) != NULL)
850 {
851 time_t curtime; /* Current time */
852 struct tm *curdate; /* Current date */
1f6f3dbc 853
cda47a96
MS
854 curtime = (time_t)atoi(option);
855 curdate = localtime(&curtime);
1f6f3dbc 856
cda47a96
MS
857 strftime(text, sizeof(text), "%c", curdate);
858 }
859 else
860 strlcpy(text, "?", sizeof(text));
1f6f3dbc 861
cda47a96
MS
862 printf("%.1f %.1f moveto", x, y);
863 y -= line_height;
864 psTextUTF8(fonts, fontsize, PS_BOLD, PS_RIGHT,
865 _cupsLangString(language, _("Printed On: ")));
866 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_LEFT, text);
867 }
1f6f3dbc
MS
868 }
869
cda47a96
MS
870 /*
871 * Notices...
872 */
1f6f3dbc 873
cda47a96 874 if (cupsArrayCount(banner->notices))
1f6f3dbc 875 {
cda47a96
MS
876 if (banner->show)
877 y -= 2 * line_height;
1f6f3dbc 878
cda47a96 879 x = 0.5 * print_width;
1f6f3dbc 880
cda47a96
MS
881 for (notice = (char *)cupsArrayFirst(banner->notices);
882 notice;
883 notice = (char *)cupsArrayNext(banner->notices))
1f6f3dbc 884 {
cda47a96
MS
885 printf("%.1f %.1f moveto", x, y);
886 y -= line_height;
887 psTextUTF8(fonts, fontsize, PS_NORMAL, PS_CENTER, notice);
1f6f3dbc 888 }
1f6f3dbc 889 }
1f6f3dbc 890
cda47a96
MS
891 /*
892 * Images...
893 */
1f6f3dbc 894
cda47a96
MS
895 if (cupsArrayCount(images))
896 {
897 if (banner->show || cupsArrayCount(banner->notices))
898 y -= 2 * line_height;
1f6f3dbc 899
cda47a96 900 x = 0.5 * (print_width - images_width);
1f6f3dbc 901
cda47a96
MS
902 for (image = (cups_image_t *)cupsArrayFirst(images);
903 image;
904 image = (cups_image_t *)cupsArrayNext(images))
905 {
906 float temp_width; /* Width of this image */
907 int depth, /* Bytes per pixel */
908 num_cols, /* Number of columns */
909 row, /* Current row */
910 num_rows, /* Number of rows */
911 out_length, /* Length of data to write */
912 out_offset; /* Offset in line buffer */
913 unsigned char *line; /* Data for current row */
914
915
916 depth = cupsImageGetDepth(image);
917 num_cols = cupsImageGetWidth(image);
918 num_rows = cupsImageGetHeight(image);
919 line = malloc(depth * num_cols + 3);
920 temp_width = num_cols * images_height / num_rows;
921 out_offset = 0;
922
923 printf("gsave %.1f %.1f translate %.3f %.3f scale\n", x, y,
924 temp_width / num_cols, images_height / num_rows);
925 x += temp_width;
926
927 switch (cupsImageGetColorSpace(image))
1f6f3dbc 928 {
cda47a96
MS
929 default :
930 case CUPS_IMAGE_WHITE :
931 printf("/DeviceGray setcolorspace"
932 "<<"
933 "/ImageType 1"
934 "/Width %d"
935 "/Height %d"
936 "/BitsPerComponent 8"
937 "/Decode[0 1]\n",
938 num_cols, num_rows);
939 break;
940
941 case CUPS_IMAGE_RGB :
942 printf("/DeviceRGB setcolorspace"
943 "<<"
944 "/ImageType 1"
945 "/Width %d"
946 "/Height %d"
947 "/BitsPerComponent 8"
948 "/Decode[0 1 0 1 0 1]\n",
949 num_cols, num_rows);
950 break;
951
952 case CUPS_IMAGE_CMYK :
953 printf("/DeviceCMYK setcolorspace"
954 "<<"
955 "/ImageType 1"
956 "/Width %d"
957 "/Height %d"
958 "/BitsPerComponent 8"
959 "/Decode[0 1 0 1 0 1 0 1]\n",
960 num_cols, num_rows);
961 break;
1f6f3dbc
MS
962 }
963
cda47a96
MS
964 puts("/DataSource currentfile"
965 "/ASCII85Decode filter"
966 "/ImageMatrix[1 0 0 -1 0 1]>>image");
1f6f3dbc 967
cda47a96
MS
968 for (row = 0, out_offset = 0; row < num_rows; row ++)
969 {
970 cupsImageGetRow(image, 0, row, num_cols, line + out_offset);
1f6f3dbc 971
cda47a96
MS
972 out_length = num_cols * depth + out_offset;
973 out_offset = out_length & 3;
1f6f3dbc 974
cda47a96 975 ps_ascii85(line, out_length, row == (num_rows - 1));
1f6f3dbc 976
cda47a96
MS
977 if (out_offset > 0)
978 memcpy(line, line + out_length - out_offset, out_offset);
979 }
1f6f3dbc 980
cda47a96 981 puts("grestore");
1f6f3dbc 982
cda47a96
MS
983 if (i == num_pages)
984 cupsImageClose(image);
985 }
986 }
1f6f3dbc 987
1f6f3dbc 988 /*
cda47a96 989 * Header and footer...
1f6f3dbc
MS
990 */
991
cda47a96 992 x = 0.5 * print_width;
1f6f3dbc 993
cda47a96 994 if (banner->header)
1f6f3dbc 995 {
cda47a96
MS
996 printf("%.1f %.1f moveto", x, print_height - 2 * fontsize);
997 psTextUTF8(fonts, 2 * fontsize, PS_BOLD, PS_CENTER, banner->header);
998 }
1f6f3dbc 999
cda47a96
MS
1000 if (banner->footer)
1001 {
1002 printf("%.1f %.1f moveto", x, fontsize);
1003 psTextUTF8(fonts, 2 * fontsize, PS_BOLD, PS_CENTER, banner->footer);
1f6f3dbc
MS
1004 }
1005
1f6f3dbc 1006 /*
cda47a96 1007 * Show the page...
1f6f3dbc
MS
1008 */
1009
cda47a96
MS
1010 puts("grestore");
1011 puts("showpage");
1f6f3dbc
MS
1012 }
1013
cda47a96 1014 return (num_pages);
1f6f3dbc
MS
1015}
1016
1017
1018/*
cda47a96 1019 * 'write_epilogue()' - Write the PostScript file epilogue.
1f6f3dbc
MS
1020 */
1021
1022static void
cda47a96 1023write_epilogue(int num_pages) /* I - Number of pages */
1f6f3dbc 1024{
cda47a96
MS
1025 puts("%%Trailer");
1026 printf("%%%%Pages: %d\n", num_pages);
1027 puts("%%EOF");
1028}
1f6f3dbc 1029
1f6f3dbc 1030
cda47a96
MS
1031/*
1032 * 'write_prolog()' - Write the PostScript file prolog with options.
1033 */
1f6f3dbc 1034
cda47a96
MS
1035ps_text_t * /* O - Fonts */
1036write_prolog(const char *title, /* I - Title of job */
1037 const char *username) /* I - Username */
1038{
1039 time_t curtime; /* Current time */
1040 struct tm *curtm; /* Current date */
1041 char curdate[255]; /* Current date (text format) */
1042 ps_text_t *fonts; /* Fonts */
1f6f3dbc 1043
1f6f3dbc 1044
cda47a96
MS
1045 /*
1046 * Get the fonts we'll need...
1047 */
1f6f3dbc 1048
cda47a96 1049 fonts = psTextInitialize();
1f6f3dbc 1050
cda47a96
MS
1051 /*
1052 * Output the DSC header...
1053 */
1f6f3dbc 1054
cda47a96
MS
1055 curtime = time(NULL);
1056 curtm = localtime(&curtime);
1057 strftime(curdate, sizeof(curdate), "%c", curtm);
1f6f3dbc 1058
cda47a96
MS
1059 puts("%!PS-Adobe-3.0");
1060 printf("%%%%BoundingBox: %.0f %.0f %.0f %.0f\n", PageLeft, PageBottom,
1061 PageRight, PageTop);
1062 printf("%%cupsRotation: %d\n", (Orientation & 3) * 90);
1063 puts("%%Creator: bannertops/" CUPS_SVERSION);
1064 printf("%%%%CreationDate: %s\n", curdate);
1065 puts("%%LanguageLevel: 2");
1066 puts("%%DocumentData: Clean7Bit");
1067 WriteTextComment("Title", title);
1068 WriteTextComment("For", username);
1069 printf("%%%%Pages: %d\n", Duplex ? 2 : 1);
1070 psTextListFonts(fonts);
1071 puts("%%EndComments");
1072 puts("%%BeginProlog");
1073 psTextEmbedFonts(fonts);
1074 puts("%%EndProlog");
1f6f3dbc 1075
cda47a96 1076 return (fonts);
1f6f3dbc
MS
1077}
1078
1079
1080/*
1081 * End of "$Id$".
1082 */