#include "driver.h"
#include <cups/i18n.h>
#include <cups/string.h>
#include "data/escp.h"
#include <signal.h>
#include <errno.h>
typedef struct cups_weave_str
{
struct cups_weave_str *prev,
*next;
int x, y,
plane,
dirty,
row,
count;
unsigned char *buffer;
} cups_weave_t;
cups_rgb_t *RGB;
cups_cmyk_t *CMYK;
unsigned char *PixelBuffer,
*CMYKBuffer,
*OutputBuffers[7],
*DotBuffers[7],
*CompBuffer;
short *InputBuffer;
cups_weave_t *DotAvailList,
*DotUsedList,
*DotBands[128][7];
int DotBufferSize,
DotRowMax,
DotColStep,
DotRowStep,
DotRowFeed,
DotRowCount,
DotRowOffset[7],
DotRowCurrent,
DotSize;
int PrinterPlanes,
BitPlanes,
PrinterTop,
PrinterLength;
cups_lut_t *DitherLuts[7];
cups_dither_t *DitherStates[7];
int OutputFeed;
int Canceled;
void Setup(ppd_file_t *);
void StartPage(ppd_file_t *, cups_page_header2_t *);
void EndPage(ppd_file_t *, cups_page_header2_t *);
void Shutdown(ppd_file_t *);
void AddBand(cups_weave_t *band);
void CancelJob(int sig);
void CompressData(ppd_file_t *, const unsigned char *, const int,
int, int, const int, const int, const int,
const int);
void OutputBand(ppd_file_t *, cups_page_header2_t *,
cups_weave_t *band);
void ProcessLine(ppd_file_t *, cups_raster_t *,
cups_page_header2_t *, const int y);
void
Setup(ppd_file_t *ppd)
{
if (ppd->model_number & ESCP_USB)
cupsWritePrintData("\000\000\000\033\001@EJL 1284.4\n@EJL \n\033@", 29);
}
void
StartPage(ppd_file_t *ppd,
cups_page_header2_t *header)
{
int i, y;
int subrow,
modrow,
plane;
unsigned char *ptr;
int bands;
int units;
cups_weave_t *band;
const char *colormodel;
char resolution[PPD_MAX_NAME],
spec[PPD_MAX_NAME];
ppd_attr_t *attr;
const float default_lut[2] =
{
0.0,
1.0
};
fprintf(stderr, "DEBUG: StartPage...\n");
fprintf(stderr, "DEBUG: MediaClass = \"%s\"\n", header->MediaClass);
fprintf(stderr, "DEBUG: MediaColor = \"%s\"\n", header->MediaColor);
fprintf(stderr, "DEBUG: MediaType = \"%s\"\n", header->MediaType);
fprintf(stderr, "DEBUG: OutputType = \"%s\"\n", header->OutputType);
fprintf(stderr, "DEBUG: AdvanceDistance = %d\n", header->AdvanceDistance);
fprintf(stderr, "DEBUG: AdvanceMedia = %d\n", header->AdvanceMedia);
fprintf(stderr, "DEBUG: Collate = %d\n", header->Collate);
fprintf(stderr, "DEBUG: CutMedia = %d\n", header->CutMedia);
fprintf(stderr, "DEBUG: Duplex = %d\n", header->Duplex);
fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0],
header->HWResolution[1]);
fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n",
header->ImagingBoundingBox[0], header->ImagingBoundingBox[1],
header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]);
fprintf(stderr, "DEBUG: InsertSheet = %d\n", header->InsertSheet);
fprintf(stderr, "DEBUG: Jog = %d\n", header->Jog);
fprintf(stderr, "DEBUG: LeadingEdge = %d\n", header->LeadingEdge);
fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0],
header->Margins[1]);
fprintf(stderr, "DEBUG: ManualFeed = %d\n", header->ManualFeed);
fprintf(stderr, "DEBUG: MediaPosition = %d\n", header->MediaPosition);
fprintf(stderr, "DEBUG: MediaWeight = %d\n", header->MediaWeight);
fprintf(stderr, "DEBUG: MirrorPrint = %d\n", header->MirrorPrint);
fprintf(stderr, "DEBUG: NegativePrint = %d\n", header->NegativePrint);
fprintf(stderr, "DEBUG: NumCopies = %d\n", header->NumCopies);
fprintf(stderr, "DEBUG: Orientation = %d\n", header->Orientation);
fprintf(stderr, "DEBUG: OutputFaceUp = %d\n", header->OutputFaceUp);
fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0],
header->PageSize[1]);
fprintf(stderr, "DEBUG: Separations = %d\n", header->Separations);
fprintf(stderr, "DEBUG: TraySwitch = %d\n", header->TraySwitch);
fprintf(stderr, "DEBUG: Tumble = %d\n", header->Tumble);
fprintf(stderr, "DEBUG: cupsWidth = %d\n", header->cupsWidth);
fprintf(stderr, "DEBUG: cupsHeight = %d\n", header->cupsHeight);
fprintf(stderr, "DEBUG: cupsMediaType = %d\n", header->cupsMediaType);
fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header->cupsBitsPerColor);
fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header->cupsBitsPerPixel);
fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header->cupsBytesPerLine);
fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header->cupsColorOrder);
fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace);
fprintf(stderr, "DEBUG: cupsCompression = %d\n", header->cupsCompression);
fprintf(stderr, "DEBUG: cupsRowCount = %d\n", header->cupsRowCount);
fprintf(stderr, "DEBUG: cupsRowFeed = %d\n", header->cupsRowFeed);
fprintf(stderr, "DEBUG: cupsRowStep = %d\n", header->cupsRowStep);
switch (header->cupsColorSpace)
{
case CUPS_CSPACE_K :
colormodel = "Black";
break;
case CUPS_CSPACE_W :
colormodel = "Gray";
break;
default :
case CUPS_CSPACE_RGB :
colormodel = "RGB";
break;
case CUPS_CSPACE_CMYK :
colormodel = "CMYK";
break;
}
if (header->HWResolution[0] != header->HWResolution[1])
snprintf(resolution, sizeof(resolution), "%dx%ddpi",
header->HWResolution[0], header->HWResolution[1]);
else
snprintf(resolution, sizeof(resolution), "%ddpi",
header->HWResolution[0]);
if (!header->MediaType[0])
strcpy(header->MediaType, "Plain");
RGB = NULL;
CMYK = NULL;
fputs("DEBUG: Attempting to load color profiles using the following values:\n", stderr);
fprintf(stderr, "DEBUG: ColorModel = %s\n", colormodel);
fprintf(stderr, "DEBUG: MediaType = %s\n", header->MediaType);
fprintf(stderr, "DEBUG: Resolution = %s\n", resolution);
if (header->cupsColorSpace == CUPS_CSPACE_RGB ||
header->cupsColorSpace == CUPS_CSPACE_W)
RGB = cupsRGBLoad(ppd, colormodel, header->MediaType, resolution);
else
RGB = NULL;
CMYK = cupsCMYKLoad(ppd, colormodel, header->MediaType, resolution);
if (RGB)
fputs("DEBUG: Loaded RGB separation from PPD.\n", stderr);
if (CMYK)
fputs("DEBUG: Loaded CMYK separation from PPD.\n", stderr);
else
{
fputs("DEBUG: Loading default CMYK separation.\n", stderr);
CMYK = cupsCMYKNew(4);
}
PrinterPlanes = CMYK->num_channels;
fprintf(stderr, "DEBUG: PrinterPlanes = %d\n", PrinterPlanes);
switch (PrinterPlanes)
{
case 1 :
DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Black");
break;
case 2 :
DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Black");
DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "LightBlack");
break;
case 3 :
DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Cyan");
DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Magenta");
DitherLuts[2] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Yellow");
break;
case 4 :
DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Cyan");
DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Magenta");
DitherLuts[2] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Yellow");
DitherLuts[3] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Black");
break;
case 6 :
DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Cyan");
DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "LightCyan");
DitherLuts[2] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Magenta");
DitherLuts[3] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "LightMagenta");
DitherLuts[4] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Yellow");
DitherLuts[5] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Black");
break;
case 7 :
DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Cyan");
DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "LightCyan");
DitherLuts[2] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Magenta");
DitherLuts[3] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "LightMagenta");
DitherLuts[4] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Yellow");
DitherLuts[5] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "Black");
DitherLuts[6] = cupsLutLoad(ppd, colormodel, header->MediaType,
resolution, "LightBlack");
break;
}
for (plane = 0; plane < PrinterPlanes; plane ++)
{
DitherStates[plane] = cupsDitherNew(header->cupsWidth);
if (!DitherLuts[plane])
DitherLuts[plane] = cupsLutNew(2, default_lut);
}
if (DitherLuts[0][4095].pixel > 1)
BitPlanes = 2;
else
BitPlanes = 1;
printf("\033@");
if (ppd->model_number & ESCP_REMOTE)
{
cupsWritePrintData("\033(R\010\000\000REMOTE1", 13);
cupsWritePrintData("ST\002\000\000\000", 6);
if ((attr = ppdFindAttr(ppd, "cupsESCPFP", NULL)) != NULL && attr->value)
{
i = atoi(attr->value);
cupsWritePrintData("FP\003\000\000", 5);
putchar(i & 255);
putchar(i >> 8);
}
if (header->cupsMediaType)
{
sprintf(spec, "%d", header->cupsMediaType);
if ((attr = ppdFindAttr(ppd, "cupsESCPSN0", spec)) != NULL && attr->value)
{
cupsWritePrintData("SN\003\000\000\000", 6);
putchar(atoi(attr->value));
}
if ((attr = ppdFindAttr(ppd, "cupsESCPSN1", spec)) != NULL && attr->value)
{
cupsWritePrintData("SN\003\000\000\001", 6);
putchar(atoi(attr->value));
}
if ((attr = ppdFindAttr(ppd, "cupsESCPSN2", spec)) != NULL && attr->value)
{
cupsWritePrintData("SN\003\000\000\002", 6);
putchar(atoi(attr->value));
}
if ((attr = ppdFindAttr(ppd, "cupsESCPSN6", spec)) != NULL && attr->value)
{
cupsWritePrintData("SN\003\000\000\006", 6);
putchar(atoi(attr->value));
}
if ((attr = ppdFindAttr(ppd, "cupsESCPMT", spec)) != NULL && attr->value)
{
cupsWritePrintData("MT\003\000\000\000", 6);
putchar(atoi(attr->value));
}
if ((attr = ppdFindAttr(ppd, "cupsESCPPH", spec)) != NULL && attr->value)
{
cupsWritePrintData("PH\002\000\000", 5);
putchar(atoi(attr->value));
}
}
sprintf(spec, "%d", header->MediaPosition);
if (header->MediaPosition)
{
if ((attr = ppdFindAttr(ppd, "cupsESCPPC", spec)) != NULL && attr->value)
{
cupsWritePrintData("PC\002\000\000", 5);
putchar(atoi(attr->value));
}
if ((attr = ppdFindAttr(ppd, "cupsESCPPP", spec)) != NULL && attr->value)
{
int a, b;
a = b = 0;
sscanf(attr->value, "%d%d", &a, &b);
cupsWritePrintData("PP\003\000\000", 5);
putchar(a);
putchar(b);
}
if ((attr = ppdFindAttr(ppd, "cupsESCPEX", spec)) != NULL && attr->value)
{
cupsWritePrintData("EX\006\000\000\000\000\000\005", 9);
putchar(atoi(attr->value));
}
}
if ((attr = ppdFindAttr(ppd, "cupsESCPMS", spec)) != NULL && attr->value)
{
cupsWritePrintData("MS\010\000\000", 5);
putchar(atoi(attr->value));
switch (header->PageSize[1])
{
case 1191 :
putchar(0x01);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 1032 :
putchar(0x02);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 842 :
putchar(0x03);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 595 :
putchar(0x03);
putchar(0x01);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 729 :
putchar(0x04);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 516 :
putchar(0x04);
putchar(0x01);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 1369 :
putchar(0x20);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 792 :
putchar(0x08);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 612 :
putchar(0x08);
putchar(0x01);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 1004 :
putchar(0x0a);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
case 1224 :
putchar(0x2d);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
putchar(0x00);
break;
default :
putchar(0xff);
putchar(0xff);
i = 360 * header->PageSize[0] / 72;
putchar(i);
putchar(i >> 8);
i = 360 * header->PageSize[1] / 72;
putchar(i);
putchar(i >> 8);
break;
}
}
sprintf(spec, "%d", header->CutMedia);
if ((attr = ppdFindAttr(ppd, "cupsESCPAC", spec)) != NULL && attr->value)
{
cupsWritePrintData("AC\002\000\000", 5);
putchar(atoi(attr->value));
if ((attr = ppdFindAttr(ppd, "cupsESCPSN80", header->MediaType)) != NULL && attr->value)
{
cupsWritePrintData("SN\003\000\000\200", 6);
putchar(atoi(attr->value));
}
if ((attr = ppdFindAttr(ppd, "cupsESCPSN81", header->MediaType)) != NULL && attr->value)
{
cupsWritePrintData("SN\003\000\000\201", 6);
putchar(atoi(attr->value));
}
}
if ((attr = ppdFindAttr(ppd, "cupsESCPCO", spec)) != NULL && attr->value)
{
cupsWritePrintData("CO\010\000\000\000", 6);
putchar(atoi(attr->value));
cupsWritePrintData("\000\000\000\000\000", 5);
}
cupsWritePrintData("\033\000\000\000", 4);
}
cupsWritePrintData("\033(G\001\000\001", 6);
for (units = 1440; units < header->HWResolution[0]; units *= 2);
if (ppd->model_number & ESCP_EXT_UNITS)
{
cupsWritePrintData("\033(U\005\000", 5);
putchar(units / header->HWResolution[1]);
putchar(units / header->HWResolution[1]);
putchar(units / header->HWResolution[0]);
putchar(units);
putchar(units >> 8);
}
else
{
cupsWritePrintData("\033(U\001\000", 5);
putchar(3600 / header->HWResolution[1]);
}
PrinterLength = header->PageSize[1] * header->HWResolution[1] / 72;
if (ppd->model_number & ESCP_PAGE_SIZE)
{
cupsWritePrintData("\033(S\010\000", 5);
i = header->PageSize[0] * header->HWResolution[1] / 72;
putchar(i);
putchar(i >> 8);
putchar(i >> 16);
putchar(i >> 24);
i = header->PageSize[1] * header->HWResolution[1] / 72;
putchar(i);
putchar(i >> 8);
putchar(i >> 16);
putchar(i >> 24);
}
else
{
cupsWritePrintData("\033(C\002\000", 5);
putchar(PrinterLength & 255);
putchar(PrinterLength >> 8);
}
PrinterTop = (int)((ppd->sizes[1].length - ppd->sizes[1].top) *
header->HWResolution[1] / 72.0);
if (ppd->model_number & ESCP_EXT_MARGINS)
{
cupsWritePrintData("\033(c\010\000", 5);
putchar(PrinterTop);
putchar(PrinterTop >> 8);
putchar(PrinterTop >> 16);
putchar(PrinterTop >> 24);
putchar(PrinterLength);
putchar(PrinterLength >> 8);
putchar(PrinterLength >> 16);
putchar(PrinterLength >> 24);
}
else
{
cupsWritePrintData("\033(c\004\000", 5);
putchar(PrinterTop & 255);
putchar(PrinterTop >> 8);
putchar(PrinterLength & 255);
putchar(PrinterLength >> 8);
}
cupsWritePrintData("\033(V\002\000\000\000", 7);
if ((attr = cupsFindAttr(ppd, "cupsESCPDirection", colormodel,
header->MediaType, resolution, spec,
sizeof(spec))) != NULL)
printf("\033U%c", atoi(attr->value));
if ((attr = cupsFindAttr(ppd, "cupsESCPMicroWeave", colormodel,
header->MediaType, resolution, spec,
sizeof(spec))) != NULL)
printf("\033(i\001%c%c", 0, atoi(attr->value));
if ((attr = cupsFindAttr(ppd, "cupsESCPDotSize", colormodel,
header->MediaType, resolution, spec,
sizeof(spec))) != NULL)
printf("\033(e\002%c%c%c", 0, 0, atoi(attr->value));
if (ppd->model_number & ESCP_ESCK)
{
if (PrinterPlanes == 1)
{
cupsWritePrintData("\033(K\002\000\000\001", 7);
}
else
{
cupsWritePrintData("\033(K\002\000\000\002", 7);
}
}
if (header->cupsRowCount <= 1)
{
DotRowCount = 1;
DotColStep = 1;
DotRowStep = 1;
DotRowFeed = 1;
}
else
{
DotRowCount = header->cupsRowCount;
DotRowFeed = header->cupsRowFeed;
DotRowStep = header->cupsRowStep % 100;
DotColStep = header->cupsRowStep / 100;
if (DotColStep == 0)
DotColStep ++;
}
DotRowCurrent = 0;
DotRowMax = DotRowCount * DotRowStep;
DotBufferSize = (header->cupsWidth / DotColStep * BitPlanes + 7) / 8;
fprintf(stderr, "DEBUG: DotBufferSize = %d\n", DotBufferSize);
fprintf(stderr, "DEBUG: DotColStep = %d\n", DotColStep);
fprintf(stderr, "DEBUG: DotRowMax = %d\n", DotRowMax);
fprintf(stderr, "DEBUG: DotRowStep = %d\n", DotRowStep);
fprintf(stderr, "DEBUG: DotRowFeed = %d\n", DotRowFeed);
fprintf(stderr, "DEBUG: DotRowCount = %d\n", DotRowCount);
DotAvailList = NULL;
DotUsedList = NULL;
DotBuffers[0] = NULL;
fprintf(stderr, "DEBUG: model_number = %x\n", ppd->model_number);
if (DotRowMax > 1)
{
bands = DotRowStep * DotColStep * PrinterPlanes * 4;
memset(DotRowOffset, 0, sizeof(DotRowOffset));
if (PrinterPlanes == 1)
{
if ((attr = ppdFindAttr(ppd, "cupsESCPBlack", resolution)) != NULL &&
attr->value)
{
sscanf(attr->value, "%d%d", &DotRowCount, &DotRowStep);
}
}
else if (ppd->model_number & ESCP_STAGGER)
{
fputs("DEBUG: Offset head detected...\n", stderr);
if ((attr = ppdFindAttr(ppd, "cupsESCPOffsets", resolution)) != NULL &&
attr->value)
{
sscanf(attr->value, "%d%d%d%d", DotRowOffset + 0,
DotRowOffset + 1, DotRowOffset + 2, DotRowOffset + 3);
}
}
for (i = 0; i < PrinterPlanes; i ++)
fprintf(stderr, "DEBUG: DotRowOffset[%d] = %d\n", i, DotRowOffset[i]);
for (i = 0; i < bands; i ++)
{
band = (cups_weave_t *)calloc(1, sizeof(cups_weave_t));
band->next = DotAvailList;
DotAvailList = band;
band->buffer = calloc(DotRowCount, DotBufferSize);
}
if (!DotAvailList)
{
fputs("ERROR: Unable to allocate band list!\n", stderr);
exit(1);
}
fputs("DEBUG: Pointer list at start of page...\n", stderr);
for (band = DotAvailList; band != NULL; band = band->next)
fprintf(stderr, "DEBUG: %p\n", band);
fputs("DEBUG: ----END----\n", stderr);
modrow = DotColStep * DotRowStep;
if (DotRowFeed == 0)
{
DotRowFeed = DotRowCount / DotColStep - DotRowStep;
while ((((DotRowFeed % 2) == 0) == ((DotRowCount % 2) == 0) ||
((DotRowFeed % 3) == 0) == ((DotRowCount % 3) == 0) ||
((DotRowFeed % 5) == 0) == ((DotRowCount % 5) == 0)) &&
DotRowFeed > 1)
DotRowFeed --;
if (DotRowFeed < 1)
DotRowFeed = 1;
fprintf(stderr, "DEBUG: Auto DotRowFeed = %d, modrow=%d...\n",
DotRowFeed, modrow);
}
memset(DotBands, 0, sizeof(DotBands));
for (i = modrow, subrow = modrow - 1, y = DotRowFeed;
i > 0;
i --, y += DotRowFeed)
{
while (DotBands[subrow][0])
{
subrow = (subrow + 1) % modrow;
}
for (plane = 0; plane < PrinterPlanes; plane ++)
{
band = DotAvailList;
DotAvailList = DotAvailList->next;
DotBands[subrow][plane] = band;
band->x = subrow / DotRowStep;
band->y = (subrow % DotRowStep) + DotRowOffset[plane];
band->plane = plane;
band->row = 0;
band->count = DotRowCount - y / DotRowStep;
if (band->count < 1)
band->count = 1;
else if (band->count > DotRowCount)
band->count = DotRowCount;
fprintf(stderr, "DEBUG: DotBands[%d][%d] = %p, x = %d, y = %d, plane = %d, count = %d\n",
subrow, plane, band, band->x, band->y, band->plane, band->count);
}
subrow = (subrow + DotRowFeed) % modrow;
}
}
else
{
ptr = calloc(PrinterPlanes, DotBufferSize);
for (plane = 0; plane < PrinterPlanes; plane ++, ptr += DotBufferSize)
DotBuffers[plane] = ptr;
}
cupsWritePrintData("\033(D\004\000", 5);
putchar(units);
putchar(units >> 8);
putchar(units * DotRowStep / header->HWResolution[1]);
putchar(units * DotColStep / header->HWResolution[0]);
OutputFeed = 0;
PixelBuffer = malloc(header->cupsBytesPerLine);
InputBuffer = malloc(header->cupsWidth * PrinterPlanes * 2);
OutputBuffers[0] = malloc(PrinterPlanes * header->cupsWidth);
for (i = 1; i < PrinterPlanes; i ++)
OutputBuffers[i] = OutputBuffers[0] + i * header->cupsWidth;
if (RGB)
CMYKBuffer = malloc(header->cupsWidth * PrinterPlanes);
CompBuffer = malloc(10 * DotBufferSize * DotRowMax);
}
void
EndPage(ppd_file_t *ppd,
cups_page_header2_t *header)
{
int i;
cups_weave_t *band,
*next;
int plane;
int subrow;
int subrows;
if (DotRowMax > 1)
{
subrows = DotRowStep * DotColStep;
for (subrow = 0; subrow < subrows; subrow ++)
for (plane = 0; plane < PrinterPlanes; plane ++)
{
if (DotBands[subrow][plane]->dirty)
{
DotBands[subrow][plane]->count = DotBands[subrow][plane]->row;
AddBand(DotBands[subrow][plane]);
}
else
{
DotBands[subrow][plane]->next = DotAvailList;
DotAvailList = DotBands[subrow][plane];
}
DotBands[subrow][plane] = NULL;
}
fputs("DEBUG: Pointer list at end of page...\n", stderr);
for (band = DotUsedList; band != NULL; band = band->next)
fprintf(stderr, "DEBUG: %p (used)\n", band);
for (band = DotAvailList; band != NULL; band = band->next)
fprintf(stderr, "DEBUG: %p (avail)\n", band);
fputs("DEBUG: ----END----\n", stderr);
for (band = DotUsedList; band != NULL; band = next)
{
next = band->next;
OutputBand(ppd, header, band);
fprintf(stderr, "DEBUG: freeing used band %p, prev = %p, next = %p\n",
band, band->prev, band->next);
free(band->buffer);
free(band);
}
for (band = DotAvailList; band != NULL; band = next)
{
next = band->next;
fprintf(stderr, "DEBUG: freeing avail band %p, prev = %p, next = %p\n",
band, band->prev, band->next);
free(band->buffer);
free(band);
}
}
else
free(DotBuffers[0]);
putchar(12);
for (i = 0; i < PrinterPlanes; i ++)
{
cupsDitherDelete(DitherStates[i]);
cupsLutDelete(DitherLuts[i]);
}
free(OutputBuffers[0]);
free(PixelBuffer);
free(InputBuffer);
free(CompBuffer);
cupsCMYKDelete(CMYK);
if (RGB)
{
cupsRGBDelete(RGB);
free(CMYKBuffer);
}
}
void
Shutdown(ppd_file_t *ppd)
{
printf("\033@");
if (ppd->model_number & ESCP_REMOTE)
{
cupsWritePrintData("\033(R\010\000\000REMOTE1", 13);
cupsWritePrintData("LD\000\000", 4);
cupsWritePrintData("\033\000\000\000", 4);
}
}
void
AddBand(cups_weave_t *band)
{
cups_weave_t *current,
*prev;
if (band->count < 1)
return;
for (current = DotUsedList, prev = NULL;
current != NULL;
prev = current, current = current->next)
if (band->y < current->y ||
(band->y == current->y && band->x < current->x) ||
(band->y == current->y && band->x == current->x &&
band->plane < current->plane))
break;
if (current != NULL)
{
band->next = current;
band->prev = prev;
current->prev = band;
if (prev != NULL)
prev->next = band;
else
DotUsedList = band;
}
else if (prev != NULL)
{
band->prev = prev;
prev->next = band;
band->next = NULL;
}
else
{
DotUsedList = band;
band->prev = NULL;
band->next = NULL;
}
}
void
CancelJob(int sig)
{
(void)sig;
Canceled = 1;
}
void
CompressData(ppd_file_t *ppd,
const unsigned char *line,
const int length,
int plane,
int type,
const int rows,
const int xstep,
const int ystep,
const int offset)
{
register const unsigned char *line_ptr,
*line_end,
*start;
register unsigned char *comp_ptr;
register int count;
register int bytes;
static int ctable[7][7] =
{
{ 0, 0, 0, 0, 0, 0, 0 },
{ 0, 16, 0, 0, 0, 0, 0 },
{ 2, 1, 4, 0, 0, 0, 0 },
{ 2, 1, 4, 0, 0, 0, 0 },
{ 0, 0, 0, 0, 0, 0, 0 },
{ 2, 18, 1, 17, 4, 0, 0 },
{ 2, 18, 1, 17, 4, 0, 16 },
};
switch (type)
{
case 0 :
line_ptr = (const unsigned char *)line;
line_end = (const unsigned char *)line + length;
break;
default :
line_ptr = (const unsigned char *)line;
line_end = (const unsigned char *)line + length;
comp_ptr = CompBuffer;
while (line_ptr < line_end && (comp_ptr - CompBuffer) < length)
{
if ((line_ptr + 1) >= line_end)
{
*comp_ptr++ = 0x00;
*comp_ptr++ = *line_ptr++;
}
else if (line_ptr[0] == line_ptr[1])
{
line_ptr ++;
count = 2;
while (line_ptr < (line_end - 1) &&
line_ptr[0] == line_ptr[1] &&
count < 127)
{
line_ptr ++;
count ++;
}
*comp_ptr++ = 257 - count;
*comp_ptr++ = *line_ptr++;
}
else
{
start = line_ptr;
line_ptr ++;
count = 1;
while (line_ptr < (line_end - 1) &&
line_ptr[0] != line_ptr[1] &&
count < 127)
{
line_ptr ++;
count ++;
}
*comp_ptr++ = count - 1;
memcpy(comp_ptr, start, count);
comp_ptr += count;
}
}
if ((comp_ptr - CompBuffer) < length)
{
line_ptr = (const unsigned char *)CompBuffer;
line_end = (const unsigned char *)comp_ptr;
}
else
{
type = 0;
line_ptr = (const unsigned char *)line;
line_end = (const unsigned char *)line + length;
}
break;
}
putchar(0x0d);
if (offset)
{
if (BitPlanes == 1)
cupsWritePrintData("\033(\\\004\000\240\005", 7);
else
printf("\033\\");
putchar(offset);
putchar(offset >> 8);
}
bytes = length / rows;
if (ppd->model_number & ESCP_RASTER_ESCI)
{
printf("\033i");
putchar(ctable[PrinterPlanes - 1][plane]);
putchar(type != 0);
putchar(BitPlanes);
putchar(bytes & 255);
putchar(bytes >> 8);
putchar(rows & 255);
putchar(rows >> 8);
}
else
{
if (PrinterPlanes > 1)
{
plane = ctable[PrinterPlanes - 1][plane];
if (plane & 0x10)
printf("\033(r%c%c%c%c", 2, 0, 1, plane & 0x0f);
else
printf("\033r%c", plane);
}
bytes *= 8;
printf("\033.");
putchar(type != 0);
putchar(ystep);
putchar(xstep);
putchar(rows);
putchar(bytes & 255);
putchar(bytes >> 8);
}
cupsWritePrintData(line_ptr, line_end - line_ptr);
}
void
OutputBand(ppd_file_t *ppd,
cups_page_header2_t *header,
cups_weave_t *band)
{
int xstep,
ystep;
OutputFeed = band->y - DotRowCurrent;
DotRowCurrent = band->y;
fprintf(stderr, "DEBUG: Printing band %p, x = %d, y = %d, plane = %d, count = %d, OutputFeed = %d\n",
band, band->x, band->y, band->plane, band->count, OutputFeed);
xstep = 3600 * DotColStep / header->HWResolution[0];
ystep = 3600 * DotRowStep / header->HWResolution[1];
if (OutputFeed > 0)
{
cupsWritePrintData("\033(v\002\000", 5);
putchar(OutputFeed & 255);
putchar(OutputFeed >> 8);
OutputFeed = 0;
}
CompressData(ppd, band->buffer, band->count * DotBufferSize, band->plane,
header->cupsCompression, band->count, xstep, ystep, band->x);
memset(band->buffer, 0, band->count * DotBufferSize);
band->dirty = 0;
fflush(stdout);
}
void
ProcessLine(ppd_file_t *ppd,
cups_raster_t *ras,
cups_page_header2_t *header,
const int y)
{
int plane,
width,
subwidth,
subrow,
offset,
pass,
xstep,
ystep;
cups_weave_t *band;
if (!cupsRasterReadPixels(ras, PixelBuffer, header->cupsBytesPerLine))
return;
width = header->cupsWidth;
subwidth = header->cupsWidth / DotColStep;
xstep = 3600 / header->HWResolution[0];
ystep = 3600 / header->HWResolution[1];
switch (header->cupsColorSpace)
{
case CUPS_CSPACE_W :
if (RGB)
{
cupsRGBDoGray(RGB, PixelBuffer, CMYKBuffer, width);
cupsCMYKDoCMYK(CMYK, CMYKBuffer, InputBuffer, width);
}
else
cupsCMYKDoGray(CMYK, PixelBuffer, InputBuffer, width);
break;
case CUPS_CSPACE_K :
cupsCMYKDoBlack(CMYK, PixelBuffer, InputBuffer, width);
break;
default :
case CUPS_CSPACE_RGB :
if (RGB)
{
cupsRGBDoRGB(RGB, PixelBuffer, CMYKBuffer, width);
cupsCMYKDoCMYK(CMYK, CMYKBuffer, InputBuffer, width);
}
else
cupsCMYKDoRGB(CMYK, PixelBuffer, InputBuffer, width);
break;
case CUPS_CSPACE_CMYK :
cupsCMYKDoCMYK(CMYK, PixelBuffer, InputBuffer, width);
break;
}
for (plane = 0; plane < PrinterPlanes; plane ++)
{
cupsDitherLine(DitherStates[plane], DitherLuts[plane], InputBuffer + plane,
PrinterPlanes, OutputBuffers[plane]);
if (DotRowMax == 1)
{
if (cupsCheckBytes(OutputBuffers[plane], width))
continue;
if (BitPlanes == 1)
cupsPackHorizontal(OutputBuffers[plane], DotBuffers[plane],
width, 0, 1);
else
cupsPackHorizontal2(OutputBuffers[plane], DotBuffers[plane],
width, 1);
if (OutputFeed > 0)
{
cupsWritePrintData("\033(v\002\000", 5);
putchar(OutputFeed & 255);
putchar(OutputFeed >> 8);
OutputFeed = 0;
}
CompressData(ppd, DotBuffers[plane], DotBufferSize, plane, 1, 1,
xstep, ystep, 0);
fflush(stdout);
}
else
{
for (pass = 0, subrow = y % DotRowStep;
pass < DotColStep;
pass ++, subrow += DotRowStep)
{
band = DotBands[subrow][plane];
offset = band->row * DotBufferSize;
if (BitPlanes == 1)
cupsPackHorizontal(OutputBuffers[plane] + pass,
band->buffer + offset, subwidth, 0, DotColStep);
else
cupsPackHorizontal2(OutputBuffers[plane] + pass,
band->buffer + offset, subwidth, DotColStep);
band->row ++;
band->dirty |= !cupsCheckBytes(band->buffer + offset, DotBufferSize);
if (band->row >= band->count)
{
if (band->dirty)
{
AddBand(band);
if (DotAvailList == NULL)
{
OutputBand(ppd, header, DotUsedList);
DotBands[subrow][plane] = DotUsedList;
DotUsedList->x = band->x;
DotUsedList->y = band->y + band->count * DotRowStep;
DotUsedList->plane = band->plane;
DotUsedList->row = 0;
DotUsedList->count = DotRowCount;
DotUsedList = DotUsedList->next;
}
else
{
DotBands[subrow][plane] = DotAvailList;
DotAvailList->x = band->x;
DotAvailList->y = band->y + band->count * DotRowStep;
DotAvailList->plane = band->plane;
DotAvailList->row = 0;
DotAvailList->count = DotRowCount;
DotAvailList = DotAvailList->next;
}
}
else
{
fprintf(stderr, "DEBUG: Blank band %p, x = %d, y = %d, plane = %d, count = %d\n",
band, band->x, band->y, band->plane, band->count);
band->y += band->count * DotRowStep;
band->row = 0;
band->count = DotRowCount;
}
}
}
}
}
if (DotRowMax == 1)
OutputFeed ++;
}
int
main(int argc,
char *argv[])
{
int fd;
cups_raster_t *ras;
cups_page_header2_t header;
int page;
int y;
ppd_file_t *ppd;
int num_options;
cups_option_t *options;
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
struct sigaction action;
#endif
setbuf(stderr, NULL);
if (argc < 6 || argc > 7)
{
_cupsLangPrintf(stderr,
_("ERROR: %s job-id user title copies options [file]\n"),
"rastertoescpx");
return (1);
}
num_options = cupsParseOptions(argv[5], 0, &options);
ppd = ppdOpenFile(getenv("PPD"));
if (!ppd)
{
_cupsLangPuts(stderr, _("ERROR: Unable to open PPD file!\n"));
return (1);
}
ppdMarkDefaults(ppd);
cupsMarkOptions(ppd, num_options, options);
if (argc == 7)
{
if ((fd = open(argv[6], O_RDONLY)) == -1)
{
_cupsLangPrintf(stderr, _("ERROR: Unable to open raster file - %s\n"),
strerror(errno));
return (1);
}
}
else
fd = 0;
ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
Canceled = 0;
#ifdef HAVE_SIGSET
sigset(SIGTERM, CancelJob);
#elif defined(HAVE_SIGACTION)
memset(&action, 0, sizeof(action));
sigemptyset(&action.sa_mask);
action.sa_handler = CancelJob;
sigaction(SIGTERM, &action, NULL);
#else
signal(SIGTERM, CancelJob);
#endif
Setup(ppd);
page = 0;
while (cupsRasterReadHeader2(ras, &header))
{
if (Canceled)
break;
page ++;
fprintf(stderr, "PAGE: %d 1\n", page);
_cupsLangPrintf(stderr, _("INFO: Starting page %d...\n"), page);
StartPage(ppd, &header);
for (y = 0; y < header.cupsHeight; y ++)
{
if (Canceled)
break;
if ((y & 127) == 0)
_cupsLangPrintf(stderr, _("INFO: Printing page %d, %d%% complete...\n"),
page, 100 * y / header.cupsHeight);
ProcessLine(ppd, ras, &header, y);
}
_cupsLangPrintf(stderr, _("INFO: Finished page %d...\n"), page);
EndPage(ppd, &header);
if (Canceled)
break;
}
Shutdown(ppd);
cupsFreeOptions(num_options, options);
cupsRasterClose(ras);
if (fd != 0)
close(fd);
if (page == 0)
{
_cupsLangPuts(stderr, _("ERROR: No pages found!\n"));
return (1);
}
else
{
_cupsLangPuts(stderr, _("INFO: Ready to print.\n"));
return (0);
}
}