#include "pstext.h"
#include "image.h"
#include <cups/i18n.h>
#define SHOW_IMAGEABLE_AREA 1
#define SHOW_JOB_BILLING 2
#define SHOW_JOB_ID 4
#define SHOW_JOB_NAME 8
#define SHOW_JOB_ORIGINATING_USER_NAME 16
#define SHOW_JOB_ORIGINATING_HOST_NAME 32
#define SHOW_JOB_UUID 64
#define SHOW_OPTIONS 128
#define SHOW_PAPER_NAME 256
#define SHOW_PAPER_SIZE 512
#define SHOW_PRINTER_DRIVER_NAME 1024
#define SHOW_PRINTER_DRIVER_VERSION 2048
#define SHOW_PRINTER_INFO 4096
#define SHOW_PRINTER_LOCATION 8192
#define SHOW_PRINTER_MAKE_AND_MODEL 16384
#define SHOW_PRINTER_NAME 32768
#define SHOW_TIME_AT_CREATION 65536
#define SHOW_TIME_AT_PROCESSING 131072
typedef struct banner_file_s
{
int show;
char *header,
*footer;
cups_array_t *notices,
*images;
} banner_file_t;
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);
int
main(int argc,
char *argv[])
{
banner_file_t *banner;
int num_options;
cups_option_t *options;
ppd_file_t *ppd;
ps_text_t *fonts;
int job_id;
const char *title,
*username;
int num_pages;
setbuf(stderr, NULL);
if (argc < 6 || argc > 7)
{
_cupsLangPrintf(stderr,
_("Usage: %s job-id user title copies options [file]\n"),
"bannertops");
return (1);
}
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]);
ppd = SetCommonOptions(num_options, options, 1);
fonts = write_prolog(title, username);
num_pages = write_banner(banner, ppd, fonts, job_id, title, username,
num_options, options);
write_epilogue(num_pages);
return (0);
}
static banner_file_t *
load_banner(const char *filename)
{
cups_file_t *fp;
char line[2048],
*ptr;
int linenum;
banner_file_t *banner;
const char *cups_docroot;
fprintf(stderr, "DEBUG: load_banner(filename=\"%s\")\n",
filename ? filename : "(stdin)");
if (filename)
fp = cupsFileOpen(filename, "r");
else
fp = cupsFileStdin();
if (!fp)
{
_cupsLangPrintf(stderr,
_("ERROR: Unable to open banner file \"%s\" - %s\n"),
filename ? filename : "(stdin)", strerror(errno));
exit(1);
}
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)))
{
linenum ++;
if (line[0] == '#' || !line[0])
continue;
for (ptr = line; *ptr && !isspace(*ptr & 255); ptr ++);
while (isspace(*ptr & 255))
*ptr++ = '\0';
if (!*ptr)
{
_cupsLangPrintf(stderr,
_("ERROR: Missing value on line %d of banner file!\n"),
linenum);
continue;
}
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"))
{
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];
if (ptr[0] == '/')
strlcpy(imagefile, ptr, sizeof(imagefile));
else
snprintf(imagefile, sizeof(imagefile), "%s/%s", cups_docroot, ptr);
if (access(imagefile, R_OK))
{
fprintf(stderr, "DEBUG: Image \"%s\" on line %d of banner file: %s\n",
ptr, linenum, strerror(errno));
}
else
{
if (!banner->images)
banner->images = cupsArrayNew(NULL, NULL);
cupsArrayAdd(banner->images, strdup(imagefile));
}
}
else if (!strcasecmp(line, "Notice"))
{
if (!banner->notices)
banner->notices = cupsArrayNew(NULL, NULL);
cupsArrayAdd(banner->notices, strdup(ptr));
}
else if (!strcasecmp(line, "Show"))
{
char *value;
for (value = ptr; *value; value = ptr)
{
while (*ptr && !isspace(*ptr & 255))
ptr ++;
while (*ptr && isspace(*ptr & 255))
*ptr++ = '\0';
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);
}
}
}
else
fprintf(stderr, "DEBUG: Unknown key \"%s\" on line %d of banner file!\n",
line, linenum);
}
if (filename)
cupsFileClose(fp);
return (banner);
}
static void
ps_ascii85(cups_ib_t *data,
int length,
int last_line)
{
unsigned b;
unsigned char c[5];
static int col = 0;
while (length > 3)
{
b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
if (b == 0)
{
putchar('z');
col ++;
}
else
{
c[4] = (b % 85) + '!';
b /= 85;
c[3] = (b % 85) + '!';
b /= 85;
c[2] = (b % 85) + '!';
b /= 85;
c[1] = (b % 85) + '!';
b /= 85;
c[0] = b + '!';
fwrite(c, 5, 1, stdout);
col += 5;
}
data += 4;
length -= 4;
if (col >= 75)
{
putchar('\n');
col = 0;
}
}
if (last_line)
{
if (length > 0)
{
memset(data + length, 0, 4 - length);
b = (((((data[0] << 8) | data[1]) << 8) | data[2]) << 8) | data[3];
c[4] = (b % 85) + '!';
b /= 85;
c[3] = (b % 85) + '!';
b /= 85;
c[2] = (b % 85) + '!';
b /= 85;
c[1] = (b % 85) + '!';
b /= 85;
c[0] = b + '!';
fwrite(c, length + 1, 1, stdout);
}
puts("~>");
col = 0;
}
}
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)
{
char *notice;
char *imagefile;
cups_array_t *images;
cups_image_t *image;
const char *option;
int i, j;
float x,
y;
cups_lang_t *language;
int showlines;
float fontsize;
int num_pages;
float print_width,
print_height,
info_top,
info_height,
line_height,
notices_height,
images_width,
images_height,
total_height;
char text[1024];
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)
{
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;
showlines ++;
}
}
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 ++;
print_width = PageRight - PageLeft;
print_height = PageTop - PageBottom;
fontsize = print_height / 60;
line_height = 1.2 * fontsize;
info_height = showlines * line_height;
notices_height = cupsArrayCount(banner->notices) * line_height;
if (cupsArrayCount(banner->images))
{
images = cupsArrayNew(NULL, NULL);
images_height = print_height / 10;
for (imagefile = (char *)cupsArrayFirst(banner->images), images_width = 0.0;
imagefile;
imagefile = (char *)cupsArrayNext(banner->images))
{
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
{
images = NULL;
images_height = 0;
images_width = 0;
}
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;
info_top = 0.5 * (print_height + total_height);
language = cupsLangDefault();
num_pages = Duplex ? 2 : 1;
for (i = 1; i <= num_pages; i ++)
{
printf("%%%%Page: %s %d\n", i == 1 ? "coverpage" : "coverback", i);
puts("gsave");
if (i == 1)
printf("%.1f %.1f translate\n", PageLeft, PageBottom);
else
printf("%.1f %.1f translate\n", PageWidth - PageRight,
PageLength - PageTop);
puts("0 setgray");
y = info_top;
if (banner->show)
{
x = 0.33 * print_width;
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: ")));
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);
}
}
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);
}
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;
struct tm *curdate;
curtime = (time_t)atoi(option);
curdate = localtime(&curtime);
strftime(text, sizeof(text), "%c", curdate);
}
else
strlcpy(text, "?", sizeof(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;
struct tm *curdate;
curtime = (time_t)atoi(option);
curdate = localtime(&curtime);
strftime(text, sizeof(text), "%c", curdate);
}
else
strlcpy(text, "?", sizeof(text));
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 (cupsArrayCount(banner->notices))
{
if (banner->show)
y -= 2 * line_height;
x = 0.5 * print_width;
for (notice = (char *)cupsArrayFirst(banner->notices);
notice;
notice = (char *)cupsArrayNext(banner->notices))
{
printf("%.1f %.1f moveto", x, y);
y -= line_height;
psTextUTF8(fonts, fontsize, PS_NORMAL, PS_CENTER, notice);
}
}
if (cupsArrayCount(images))
{
if (banner->show || cupsArrayCount(banner->notices))
y -= 2 * line_height;
x = 0.5 * (print_width - images_width);
for (image = (cups_image_t *)cupsArrayFirst(images);
image;
image = (cups_image_t *)cupsArrayNext(images))
{
float temp_width;
int depth,
num_cols,
row,
num_rows,
out_length,
out_offset;
unsigned char *line;
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))
{
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;
}
puts("/DataSource currentfile"
"/ASCII85Decode filter"
"/ImageMatrix[1 0 0 -1 0 1]>>image");
for (row = 0, out_offset = 0; row < num_rows; row ++)
{
cupsImageGetRow(image, 0, row, num_cols, line + out_offset);
out_length = num_cols * depth + out_offset;
out_offset = out_length & 3;
ps_ascii85(line, out_length, row == (num_rows - 1));
if (out_offset > 0)
memcpy(line, line + out_length - out_offset, out_offset);
}
puts("grestore");
if (i == num_pages)
cupsImageClose(image);
}
}
x = 0.5 * print_width;
if (banner->header)
{
printf("%.1f %.1f moveto", x, print_height - 2 * fontsize);
psTextUTF8(fonts, 2 * fontsize, PS_BOLD, PS_CENTER, banner->header);
}
if (banner->footer)
{
printf("%.1f %.1f moveto", x, fontsize);
psTextUTF8(fonts, 2 * fontsize, PS_BOLD, PS_CENTER, banner->footer);
}
puts("grestore");
puts("showpage");
}
return (num_pages);
}
static void
write_epilogue(int num_pages)
{
puts("%%Trailer");
printf("%%%%Pages: %d\n", num_pages);
puts("%%EOF");
}
ps_text_t *
write_prolog(const char *title,
const char *username)
{
time_t curtime;
struct tm *curtm;
char curdate[255];
ps_text_t *fonts;
fonts = psTextInitialize();
curtime = time(NULL);
curtm = localtime(&curtime);
strftime(curdate, sizeof(curdate), "%c", curtm);
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");
return (fonts);
}