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