#include "ippevecommon.h"
#include "dither.h"
static unsigned pcl_bottom,
pcl_left,
pcl_right,
pcl_top,
pcl_blanks;
static unsigned char pcl_white,
*pcl_line,
*pcl_comp;
static void pcl_end_page(cups_page_header2_t *header, unsigned page);
static void pcl_start_page(cups_page_header2_t *header, unsigned page);
static int pcl_to_pcl(const char *filename);
static void pcl_write_line(cups_page_header2_t *header, unsigned y, const unsigned char *line);
static int raster_to_pcl(const char *filename);
int
main(int argc,
char *argv[])
{
const char *content_type;
if (argc > 2)
{
fputs("ERROR: Too many arguments supplied, aborting.\n", stderr);
return (1);
}
else if ((content_type = getenv("CONTENT_TYPE")) == NULL)
{
fputs("ERROR: CONTENT_TYPE environment variable not set, aborting.\n", stderr);
return (1);
}
else if (!strcasecmp(content_type, "application/vnd.hp-pcl"))
{
return (pcl_to_pcl(argv[1]));
}
else if (!strcasecmp(content_type, "image/pwg-raster") || !strcasecmp(content_type, "image/urf"))
{
return (raster_to_pcl(argv[1]));
}
else
{
fprintf(stderr, "ERROR: CONTENT_TYPE %s not supported.\n", content_type);
return (1);
}
}
static void
pcl_end_page(
cups_page_header2_t *header,
unsigned page)
{
fputs("\033*r0B", stdout);
if (!(header->Duplex && (page & 1)))
putchar('\f');
free(pcl_line);
free(pcl_comp);
}
static void
pcl_start_page(
cups_page_header2_t *header,
unsigned page)
{
pcl_top = header->HWResolution[1] / 6;
pcl_bottom = header->cupsHeight - header->HWResolution[1] / 6 - 1;
if (header->PageSize[1] == 842)
{
pcl_left = (header->cupsWidth - 8 * header->HWResolution[0]) / 2;
pcl_right = pcl_left + 8 * header->HWResolution[0] - 1;
}
else
{
pcl_left = header->HWResolution[0] / 4;
pcl_right = header->cupsWidth - header->HWResolution[0] / 4 - 1;
}
if (!header->Duplex || (page & 1))
{
printf("\033&l12D\033&k12H");
printf("\033&l0O");
switch (header->PageSize[1])
{
case 540 :
printf("\033&l80A");
break;
case 595 :
printf("\033&l25A");
break;
case 624 :
printf("\033&l90A");
break;
case 649 :
printf("\033&l91A");
break;
case 684 :
printf("\033&l81A");
break;
case 709 :
printf("\033&l100A");
break;
case 756 :
printf("\033&l1A");
break;
case 792 :
printf("\033&l2A");
break;
case 842 :
printf("\033&l26A");
break;
case 1008 :
printf("\033&l3A");
break;
case 1191 :
printf("\033&l27A");
break;
case 1224 :
printf("\033&l6A");
break;
}
printf("\033&l%uE\033&l0L", 12 * pcl_top / header->HWResolution[1]);
if (header->Duplex)
{
int mode = header->Duplex ? 1 + header->Tumble != 0 : 0;
printf("\033&l%dS", mode);
}
}
else if (header->Duplex)
printf("\033&a2G");
printf("\033*t%uR", header->HWResolution[0]);
printf("\033*r%uS", pcl_right - pcl_left + 1);
printf("\033*r%uT", pcl_bottom - pcl_top + 1);
printf("\033&a0H\033&a%uV", 720 * pcl_top / header->HWResolution[1]);
printf("\033*b2M");
printf("\033*r1A");
pcl_white = header->cupsBitsPerColor == 1 ? 0 : 255;
pcl_blanks = 0;
pcl_line = malloc(header->cupsWidth / 8 + 1);
pcl_comp = malloc(2 * header->cupsBytesPerLine + 2);
fprintf(stderr, "ATTR: job-impressions-completed=%d\n", page);
}
static int
pcl_to_pcl(const char *filename)
{
int fd;
char buffer[65536];
ssize_t bytes;
if (filename)
{
if ((fd = open(filename, O_RDONLY)) < 0)
{
fprintf(stderr, "ERROR: Unable to open \"%s\": %s\n", filename, strerror(errno));
return (1);
}
}
else
{
fd = 0;
}
fputs("ATTR: job-impressions=unknown\n", stderr);
while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
write(1, buffer, (size_t)bytes);
if (fd > 0)
close(fd);
return (0);
}
static void
pcl_write_line(
cups_page_header2_t *header,
unsigned y,
const unsigned char *line)
{
unsigned x;
unsigned char bit,
byte,
*outptr,
*outend,
*start,
*compptr;
unsigned count;
const unsigned char *ditherline;
if (line[0] == pcl_white && !memcmp(line, line + 1, header->cupsBytesPerLine - 1))
{
pcl_blanks ++;
return;
}
if (header->cupsBitsPerPixel == 1)
{
outend = (unsigned char *)line + (pcl_right + 7) / 8;
outptr = (unsigned char *)line + pcl_left / 8;
}
else
{
y &= 63;
ditherline = threshold[y];
for (x = pcl_left, bit = 128, byte = 0, outptr = pcl_line; x <= pcl_right; x ++, line ++)
{
if (*line <= ditherline[x & 63])
byte |= bit;
if (bit == 1)
{
*outptr++ = byte;
byte = 0;
bit = 128;
}
else
bit >>= 1;
}
if (bit != 128)
*outptr++ = byte;
outend = outptr;
outptr = pcl_line;
}
compptr = pcl_comp;
while (outptr < outend)
{
if ((outptr + 1) >= outend)
{
*compptr++ = 0x00;
*compptr++ = *outptr++;
}
else if (outptr[0] == outptr[1])
{
outptr ++;
count = 2;
while (outptr < (outend - 1) &&
outptr[0] == outptr[1] &&
count < 127)
{
outptr ++;
count ++;
}
*compptr++ = (unsigned char)(257 - count);
*compptr++ = *outptr++;
}
else
{
start = outptr;
outptr ++;
count = 1;
while (outptr < (outend - 1) &&
outptr[0] != outptr[1] &&
count < 127)
{
outptr ++;
count ++;
}
*compptr++ = (unsigned char)(count - 1);
memcpy(compptr, start, count);
compptr += count;
}
}
if (pcl_blanks > 0)
{
printf("\033*b%dY", pcl_blanks);
pcl_blanks = 0;
}
printf("\033*b%dW", (int)(compptr - pcl_comp));
fwrite(pcl_comp, 1, (size_t)(compptr - pcl_comp), stdout);
}
static int
raster_to_pcl(const char *filename)
{
int fd;
cups_raster_t *ras;
cups_page_header2_t header;
unsigned page = 0,
y;
unsigned char *line;
if (filename)
{
if ((fd = open(filename, O_RDONLY)) < 0)
{
fprintf(stderr, "ERROR: Unable to open \"%s\": %s\n", filename, strerror(errno));
return (1);
}
}
else
{
fd = 0;
}
if ((ras = cupsRasterOpen(fd, CUPS_RASTER_READ)) == NULL)
{
fputs("ERROR: Unable to read raster data, aborting.\n", stderr);
return (1);
}
fputs("\033E", stdout);
while (cupsRasterReadHeader2(ras, &header))
{
page ++;
if (header.cupsColorSpace != CUPS_CSPACE_W && header.cupsColorSpace != CUPS_CSPACE_SW && header.cupsColorSpace != CUPS_CSPACE_K)
{
fputs("ERROR: Unsupported color space, aborting.\n", stderr);
break;
}
else if (header.cupsBitsPerColor != 1 && header.cupsBitsPerColor != 8)
{
fputs("ERROR: Unsupported bit depth, aborting.\n", stderr);
break;
}
line = malloc(header.cupsBytesPerLine);
pcl_start_page(&header, page);
for (y = 0; y < header.cupsHeight; y ++)
{
if (cupsRasterReadPixels(ras, line, header.cupsBytesPerLine))
pcl_write_line(&header, y, line);
else
break;
}
pcl_end_page(&header, page);
free(line);
}
cupsRasterClose(ras);
fprintf(stderr, "ATTR: job-impressions=%d\n", page);
return (0);
}