]> git.ipfire.org Git - thirdparty/cups.git/blame - driver/rastertoescpx.c
Merge changes from CUPS 1.5svn-r8849.
[thirdparty/cups.git] / driver / rastertoescpx.c
CommitLineData
ac884b6a
MS
1/*
2 * "$Id$"
3 *
4 * Advanced EPSON ESC/P raster driver for CUPS.
5 *
4d301e69 6 * Copyright 2007-2009 by Apple Inc.
ac884b6a
MS
7 * Copyright 1993-2005 by Easy Software Products.
8 *
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
14 *
15 * Contents:
16 *
17 * Setup() - Prepare the printer for graphics output.
18 * StartPage() - Start a page of graphics.
19 * EndPage() - Finish a page of graphics.
20 * Shutdown() - Shutdown a printer.
839a51c8 21 * CancelJob() - Cancel the current job...
ac884b6a
MS
22 * CompressData() - Compress a line of graphics.
23 * OutputBand() - Output a band of graphics.
24 * ProcessLine() - Read graphics from the page stream and output
25 * as needed.
26 * main() - Main entry and processing of driver.
27 */
28
29/*
30 * Include necessary headers...
31 */
32
33#include "driver.h"
f0ab5bff 34#include <cups/i18n.h>
ac884b6a
MS
35#include <cups/string.h>
36#include "data/escp.h"
839a51c8 37#include <signal.h>
f0ab5bff 38#include <errno.h>
ac884b6a
MS
39
40
41/*
42 * Softweave data...
43 */
44
45typedef struct cups_weave_str
46{
47 struct cups_weave_str *prev, /* Previous band */
48 *next; /* Next band */
49 int x, y, /* Column/Line on the page */
50 plane, /* Color plane */
51 dirty, /* Is this buffer dirty? */
52 row, /* Row in the buffer */
53 count; /* Max rows this pass */
54 unsigned char *buffer; /* Data buffer */
55} cups_weave_t;
56
57
58/*
59 * Globals...
60 */
61
62cups_rgb_t *RGB; /* RGB color separation data */
63cups_cmyk_t *CMYK; /* CMYK color separation data */
64unsigned char *PixelBuffer, /* Pixel buffer */
65 *CMYKBuffer, /* CMYK buffer */
66 *OutputBuffers[7], /* Output buffers */
67 *DotBuffers[7], /* Dot buffers */
68 *CompBuffer; /* Compression buffer */
69short *InputBuffer; /* Color separation buffer */
70cups_weave_t *DotAvailList, /* Available buffers */
71 *DotUsedList, /* Used buffers */
72 *DotBands[128][7]; /* Buffers in use */
73int DotBufferSize, /* Size of dot buffers */
74 DotRowMax, /* Maximum row number in buffer */
75 DotColStep, /* Step for each output column */
76 DotRowStep, /* Step for each output line */
77 DotRowFeed, /* Amount to feed for interleave */
78 DotRowCount, /* Number of rows to output */
79 DotRowOffset[7], /* Offset for each color on print head */
80 DotRowCurrent, /* Current row */
81 DotSize; /* Dot size (Pro 5000 only) */
82int PrinterPlanes, /* # of color planes */
83 BitPlanes, /* # of bit planes per color */
84 PrinterTop, /* Top of page */
85 PrinterLength; /* Length of page */
86cups_lut_t *DitherLuts[7]; /* Lookup tables for dithering */
87cups_dither_t *DitherStates[7]; /* Dither state tables */
88int OutputFeed; /* Number of lines to skip */
839a51c8 89int Canceled; /* Is the job canceled? */
ac884b6a
MS
90
91
92/*
93 * Prototypes...
94 */
95
96void Setup(ppd_file_t *);
839a51c8
MS
97void StartPage(ppd_file_t *, cups_page_header2_t *);
98void EndPage(ppd_file_t *, cups_page_header2_t *);
ac884b6a
MS
99void Shutdown(ppd_file_t *);
100
101void AddBand(cups_weave_t *band);
839a51c8 102void CancelJob(int sig);
ac884b6a
MS
103void CompressData(ppd_file_t *, const unsigned char *, const int,
104 int, int, const int, const int, const int,
105 const int);
839a51c8 106void OutputBand(ppd_file_t *, cups_page_header2_t *,
ac884b6a
MS
107 cups_weave_t *band);
108void ProcessLine(ppd_file_t *, cups_raster_t *,
839a51c8 109 cups_page_header2_t *, const int y);
ac884b6a
MS
110
111
112/*
113 * 'Setup()' - Prepare a printer for graphics output.
114 */
115
116void
117Setup(ppd_file_t *ppd) /* I - PPD file */
118{
119 /*
120 * Some EPSON printers need an additional command issued at the
121 * beginning of each job to exit from USB "packet" mode...
122 */
123
124 if (ppd->model_number & ESCP_USB)
125 cupsWritePrintData("\000\000\000\033\001@EJL 1284.4\n@EJL \n\033@", 29);
126}
127
128
129/*
130 * 'StartPage()' - Start a page of graphics.
131 */
132
133void
134StartPage(ppd_file_t *ppd, /* I - PPD file */
839a51c8 135 cups_page_header2_t *header) /* I - Page header */
ac884b6a
MS
136{
137 int i, y; /* Looping vars */
138 int subrow, /* Current subrow */
139 modrow, /* Subrow modulus */
140 plane; /* Current color plane */
141 unsigned char *ptr; /* Pointer into dot buffer */
142 int bands; /* Number of bands to allocate */
143 int units; /* Units for resolution */
144 cups_weave_t *band; /* Current band */
145 const char *colormodel; /* Color model string */
146 char resolution[PPD_MAX_NAME],
147 /* Resolution string */
148 spec[PPD_MAX_NAME]; /* PPD attribute name */
149 ppd_attr_t *attr; /* Attribute from PPD file */
150 const float default_lut[2] = /* Default dithering lookup table */
151 {
152 0.0,
153 1.0
154 };
155
156
157 fprintf(stderr, "DEBUG: StartPage...\n");
158 fprintf(stderr, "DEBUG: MediaClass = \"%s\"\n", header->MediaClass);
159 fprintf(stderr, "DEBUG: MediaColor = \"%s\"\n", header->MediaColor);
160 fprintf(stderr, "DEBUG: MediaType = \"%s\"\n", header->MediaType);
161 fprintf(stderr, "DEBUG: OutputType = \"%s\"\n", header->OutputType);
162
163 fprintf(stderr, "DEBUG: AdvanceDistance = %d\n", header->AdvanceDistance);
164 fprintf(stderr, "DEBUG: AdvanceMedia = %d\n", header->AdvanceMedia);
165 fprintf(stderr, "DEBUG: Collate = %d\n", header->Collate);
166 fprintf(stderr, "DEBUG: CutMedia = %d\n", header->CutMedia);
167 fprintf(stderr, "DEBUG: Duplex = %d\n", header->Duplex);
168 fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0],
169 header->HWResolution[1]);
170 fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n",
171 header->ImagingBoundingBox[0], header->ImagingBoundingBox[1],
172 header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]);
173 fprintf(stderr, "DEBUG: InsertSheet = %d\n", header->InsertSheet);
174 fprintf(stderr, "DEBUG: Jog = %d\n", header->Jog);
175 fprintf(stderr, "DEBUG: LeadingEdge = %d\n", header->LeadingEdge);
176 fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0],
177 header->Margins[1]);
178 fprintf(stderr, "DEBUG: ManualFeed = %d\n", header->ManualFeed);
179 fprintf(stderr, "DEBUG: MediaPosition = %d\n", header->MediaPosition);
180 fprintf(stderr, "DEBUG: MediaWeight = %d\n", header->MediaWeight);
181 fprintf(stderr, "DEBUG: MirrorPrint = %d\n", header->MirrorPrint);
182 fprintf(stderr, "DEBUG: NegativePrint = %d\n", header->NegativePrint);
183 fprintf(stderr, "DEBUG: NumCopies = %d\n", header->NumCopies);
184 fprintf(stderr, "DEBUG: Orientation = %d\n", header->Orientation);
185 fprintf(stderr, "DEBUG: OutputFaceUp = %d\n", header->OutputFaceUp);
186 fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0],
187 header->PageSize[1]);
188 fprintf(stderr, "DEBUG: Separations = %d\n", header->Separations);
189 fprintf(stderr, "DEBUG: TraySwitch = %d\n", header->TraySwitch);
190 fprintf(stderr, "DEBUG: Tumble = %d\n", header->Tumble);
191 fprintf(stderr, "DEBUG: cupsWidth = %d\n", header->cupsWidth);
192 fprintf(stderr, "DEBUG: cupsHeight = %d\n", header->cupsHeight);
193 fprintf(stderr, "DEBUG: cupsMediaType = %d\n", header->cupsMediaType);
194 fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header->cupsBitsPerColor);
195 fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header->cupsBitsPerPixel);
196 fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header->cupsBytesPerLine);
197 fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header->cupsColorOrder);
198 fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace);
199 fprintf(stderr, "DEBUG: cupsCompression = %d\n", header->cupsCompression);
200 fprintf(stderr, "DEBUG: cupsRowCount = %d\n", header->cupsRowCount);
201 fprintf(stderr, "DEBUG: cupsRowFeed = %d\n", header->cupsRowFeed);
202 fprintf(stderr, "DEBUG: cupsRowStep = %d\n", header->cupsRowStep);
203
204 /*
205 * Figure out the color model and spec strings...
206 */
207
208 switch (header->cupsColorSpace)
209 {
210 case CUPS_CSPACE_K :
211 colormodel = "Black";
212 break;
213 case CUPS_CSPACE_W :
214 colormodel = "Gray";
215 break;
216 default :
217 case CUPS_CSPACE_RGB :
218 colormodel = "RGB";
219 break;
220 case CUPS_CSPACE_CMYK :
221 colormodel = "CMYK";
222 break;
223 }
224
225 if (header->HWResolution[0] != header->HWResolution[1])
226 snprintf(resolution, sizeof(resolution), "%dx%ddpi",
227 header->HWResolution[0], header->HWResolution[1]);
228 else
229 snprintf(resolution, sizeof(resolution), "%ddpi",
230 header->HWResolution[0]);
231
232 if (!header->MediaType[0])
233 strcpy(header->MediaType, "Plain");
234
235 /*
236 * Load the appropriate color profiles...
237 */
238
239 RGB = NULL;
240 CMYK = NULL;
241
242 fputs("DEBUG: Attempting to load color profiles using the following values:\n", stderr);
243 fprintf(stderr, "DEBUG: ColorModel = %s\n", colormodel);
244 fprintf(stderr, "DEBUG: MediaType = %s\n", header->MediaType);
245 fprintf(stderr, "DEBUG: Resolution = %s\n", resolution);
246
247 if (header->cupsColorSpace == CUPS_CSPACE_RGB ||
248 header->cupsColorSpace == CUPS_CSPACE_W)
249 RGB = cupsRGBLoad(ppd, colormodel, header->MediaType, resolution);
250 else
251 RGB = NULL;
252
253 CMYK = cupsCMYKLoad(ppd, colormodel, header->MediaType, resolution);
254
255 if (RGB)
256 fputs("DEBUG: Loaded RGB separation from PPD.\n", stderr);
257
258 if (CMYK)
259 fputs("DEBUG: Loaded CMYK separation from PPD.\n", stderr);
260 else
261 {
262 fputs("DEBUG: Loading default CMYK separation.\n", stderr);
263 CMYK = cupsCMYKNew(4);
264 }
265
266 PrinterPlanes = CMYK->num_channels;
267
268 fprintf(stderr, "DEBUG: PrinterPlanes = %d\n", PrinterPlanes);
269
270 /*
271 * Get the dithering parameters...
272 */
273
274 switch (PrinterPlanes)
275 {
276 case 1 : /* K */
277 DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
278 resolution, "Black");
279 break;
280
281 case 2 : /* Kk */
282 DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
283 resolution, "Black");
284 DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
285 resolution, "LightBlack");
286 break;
287
288 case 3 : /* CMY */
289 DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
290 resolution, "Cyan");
291 DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
292 resolution, "Magenta");
293 DitherLuts[2] = cupsLutLoad(ppd, colormodel, header->MediaType,
294 resolution, "Yellow");
295 break;
296
297 case 4 : /* CMYK */
298 DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
299 resolution, "Cyan");
300 DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
301 resolution, "Magenta");
302 DitherLuts[2] = cupsLutLoad(ppd, colormodel, header->MediaType,
303 resolution, "Yellow");
304 DitherLuts[3] = cupsLutLoad(ppd, colormodel, header->MediaType,
305 resolution, "Black");
306 break;
307
308 case 6 : /* CcMmYK */
309 DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
310 resolution, "Cyan");
311 DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
312 resolution, "LightCyan");
313 DitherLuts[2] = cupsLutLoad(ppd, colormodel, header->MediaType,
314 resolution, "Magenta");
315 DitherLuts[3] = cupsLutLoad(ppd, colormodel, header->MediaType,
316 resolution, "LightMagenta");
317 DitherLuts[4] = cupsLutLoad(ppd, colormodel, header->MediaType,
318 resolution, "Yellow");
319 DitherLuts[5] = cupsLutLoad(ppd, colormodel, header->MediaType,
320 resolution, "Black");
321 break;
322
323 case 7 : /* CcMmYKk */
324 DitherLuts[0] = cupsLutLoad(ppd, colormodel, header->MediaType,
325 resolution, "Cyan");
326 DitherLuts[1] = cupsLutLoad(ppd, colormodel, header->MediaType,
327 resolution, "LightCyan");
328 DitherLuts[2] = cupsLutLoad(ppd, colormodel, header->MediaType,
329 resolution, "Magenta");
330 DitherLuts[3] = cupsLutLoad(ppd, colormodel, header->MediaType,
331 resolution, "LightMagenta");
332 DitherLuts[4] = cupsLutLoad(ppd, colormodel, header->MediaType,
333 resolution, "Yellow");
334 DitherLuts[5] = cupsLutLoad(ppd, colormodel, header->MediaType,
335 resolution, "Black");
336 DitherLuts[6] = cupsLutLoad(ppd, colormodel, header->MediaType,
337 resolution, "LightBlack");
338 break;
339 }
340
341 for (plane = 0; plane < PrinterPlanes; plane ++)
342 {
343 DitherStates[plane] = cupsDitherNew(header->cupsWidth);
344
345 if (!DitherLuts[plane])
346 DitherLuts[plane] = cupsLutNew(2, default_lut);
347 }
348
349 if (DitherLuts[0][4095].pixel > 1)
350 BitPlanes = 2;
351 else
352 BitPlanes = 1;
353
354 /*
355 * Initialize the printer...
356 */
357
358 printf("\033@");
359
360 if (ppd->model_number & ESCP_REMOTE)
361 {
362 /*
363 * Go into remote mode...
364 */
365
366 cupsWritePrintData("\033(R\010\000\000REMOTE1", 13);
367
368 /*
369 * Disable status reporting...
370 */
371
372 cupsWritePrintData("ST\002\000\000\000", 6);
373
374 /*
375 * Enable borderless printing...
376 */
377
378 if ((attr = ppdFindAttr(ppd, "cupsESCPFP", NULL)) != NULL && attr->value)
379 {
380 /*
381 * Set horizontal offset...
382 */
383
384 i = atoi(attr->value);
385
386 cupsWritePrintData("FP\003\000\000", 5);
387 putchar(i & 255);
388 putchar(i >> 8);
389 }
390
391 /*
392 * Set media type...
393 */
394
395 if (header->cupsMediaType)
396 {
397 sprintf(spec, "%d", header->cupsMediaType);
398
399 if ((attr = ppdFindAttr(ppd, "cupsESCPSN0", spec)) != NULL && attr->value)
400 {
401 /*
402 * Set feed sequence...
403 */
404
405 cupsWritePrintData("SN\003\000\000\000", 6);
406 putchar(atoi(attr->value));
407 }
408
409 if ((attr = ppdFindAttr(ppd, "cupsESCPSN1", spec)) != NULL && attr->value)
410 {
411 /*
412 * Set platten gap...
413 */
414
415 cupsWritePrintData("SN\003\000\000\001", 6);
416 putchar(atoi(attr->value));
417 }
418
419 if ((attr = ppdFindAttr(ppd, "cupsESCPSN2", spec)) != NULL && attr->value)
420 {
421 /*
422 * Paper feeding/ejecting sequence...
423 */
424
425 cupsWritePrintData("SN\003\000\000\002", 6);
426 putchar(atoi(attr->value));
427 }
428
429 if ((attr = ppdFindAttr(ppd, "cupsESCPSN6", spec)) != NULL && attr->value)
430 {
431 /*
432 * Eject delay...
433 */
434
435 cupsWritePrintData("SN\003\000\000\006", 6);
436 putchar(atoi(attr->value));
437 }
438
439 if ((attr = ppdFindAttr(ppd, "cupsESCPMT", spec)) != NULL && attr->value)
440 {
441 /*
442 * Set media type.
443 */
444
445 cupsWritePrintData("MT\003\000\000\000", 6);
446 putchar(atoi(attr->value));
447 }
448
449 if ((attr = ppdFindAttr(ppd, "cupsESCPPH", spec)) != NULL && attr->value)
450 {
451 /*
452 * Set paper thickness.
453 */
454
455 cupsWritePrintData("PH\002\000\000", 5);
456 putchar(atoi(attr->value));
457 }
458 }
459
460 sprintf(spec, "%d", header->MediaPosition);
461
462 if (header->MediaPosition)
463 {
464 if ((attr = ppdFindAttr(ppd, "cupsESCPPC", spec)) != NULL && attr->value)
465 {
466 /*
467 * Paper check.
468 */
469
470 cupsWritePrintData("PC\002\000\000", 5);
471 putchar(atoi(attr->value));
472 }
473
474 if ((attr = ppdFindAttr(ppd, "cupsESCPPP", spec)) != NULL && attr->value)
475 {
476 /*
477 * Paper path.
478 */
479
480 int a, b;
481
482 a = b = 0;
483 sscanf(attr->value, "%d%d", &a, &b);
484
485 cupsWritePrintData("PP\003\000\000", 5);
486 putchar(a);
487 putchar(b);
488 }
489
490 if ((attr = ppdFindAttr(ppd, "cupsESCPEX", spec)) != NULL && attr->value)
491 {
492 /*
493 * Set media position.
494 */
495
496 cupsWritePrintData("EX\006\000\000\000\000\000\005", 9);
497 putchar(atoi(attr->value));
498 }
499 }
500
501 if ((attr = ppdFindAttr(ppd, "cupsESCPMS", spec)) != NULL && attr->value)
502 {
503 /*
504 * Set media size...
505 */
506
507 cupsWritePrintData("MS\010\000\000", 5);
508 putchar(atoi(attr->value));
509
510 switch (header->PageSize[1])
511 {
512 case 1191 : /* A3 */
513 putchar(0x01);
514 putchar(0x00);
515 putchar(0x00);
516 putchar(0x00);
517 putchar(0x00);
518 putchar(0x00);
519 break;
520 case 1032 : /* B4 */
521 putchar(0x02);
522 putchar(0x00);
523 putchar(0x00);
524 putchar(0x00);
525 putchar(0x00);
526 putchar(0x00);
527 break;
528 case 842 : /* A4 */
529 putchar(0x03);
530 putchar(0x00);
531 putchar(0x00);
532 putchar(0x00);
533 putchar(0x00);
534 putchar(0x00);
535 break;
536 case 595 : /* A4.Transverse */
537 putchar(0x03);
538 putchar(0x01);
539 putchar(0x00);
540 putchar(0x00);
541 putchar(0x00);
542 putchar(0x00);
543 break;
544 case 729 : /* B5 */
545 putchar(0x04);
546 putchar(0x00);
547 putchar(0x00);
548 putchar(0x00);
549 putchar(0x00);
550 putchar(0x00);
551 break;
552 case 516 : /* B5.Transverse */
553 putchar(0x04);
554 putchar(0x01);
555 putchar(0x00);
556 putchar(0x00);
557 putchar(0x00);
558 putchar(0x00);
559 break;
560 case 1369 : /* Super A3/B */
561 putchar(0x20);
562 putchar(0x00);
563 putchar(0x00);
564 putchar(0x00);
565 putchar(0x00);
566 putchar(0x00);
567 break;
568 case 792 : /* Letter */
569 putchar(0x08);
570 putchar(0x00);
571 putchar(0x00);
572 putchar(0x00);
573 putchar(0x00);
574 putchar(0x00);
575 break;
576 case 612 : /* Letter.Transverse */
577 putchar(0x08);
578 putchar(0x01);
579 putchar(0x00);
580 putchar(0x00);
581 putchar(0x00);
582 putchar(0x00);
583 break;
584 case 1004 : /* Legal */
585 putchar(0x0a);
586 putchar(0x00);
587 putchar(0x00);
588 putchar(0x00);
589 putchar(0x00);
590 putchar(0x00);
591 break;
592 case 1224 : /* Tabloid */
593 putchar(0x2d);
594 putchar(0x00);
595 putchar(0x00);
596 putchar(0x00);
597 putchar(0x00);
598 putchar(0x00);
599 break;
600 default : /* Custom size */
601 putchar(0xff);
602 putchar(0xff);
603 i = 360 * header->PageSize[0] / 72;
604 putchar(i);
605 putchar(i >> 8);
606 i = 360 * header->PageSize[1] / 72;
607 putchar(i);
608 putchar(i >> 8);
609 break;
610 }
611 }
612
613 sprintf(spec, "%d", header->CutMedia);
614
615 if ((attr = ppdFindAttr(ppd, "cupsESCPAC", spec)) != NULL && attr->value)
616 {
617 /*
618 * Enable/disable cutter.
619 */
620
621 cupsWritePrintData("AC\002\000\000", 5);
622 putchar(atoi(attr->value));
623
624 if ((attr = ppdFindAttr(ppd, "cupsESCPSN80", header->MediaType)) != NULL && attr->value)
625 {
626 /*
627 * Cutting method...
628 */
629
630 cupsWritePrintData("SN\003\000\000\200", 6);
631 putchar(atoi(attr->value));
632 }
633
634 if ((attr = ppdFindAttr(ppd, "cupsESCPSN81", header->MediaType)) != NULL && attr->value)
635 {
636 /*
637 * Cutting pressure...
638 */
639
640 cupsWritePrintData("SN\003\000\000\201", 6);
641 putchar(atoi(attr->value));
642 }
643 }
644
645 if ((attr = ppdFindAttr(ppd, "cupsESCPCO", spec)) != NULL && attr->value)
646 {
647 /*
648 * Enable/disable cutter.
649 */
650
651 cupsWritePrintData("CO\010\000\000\000", 6);
652 putchar(atoi(attr->value));
653 cupsWritePrintData("\000\000\000\000\000", 5);
654 }
655
656 /*
657 * Exit remote mode...
658 */
659
660 cupsWritePrintData("\033\000\000\000", 4);
661 }
662
663 /*
664 * Enter graphics mode...
665 */
666
667 cupsWritePrintData("\033(G\001\000\001", 6);
668
669 /*
670 * Set the line feed increment...
671 */
672
673 /* TODO: get this from the PPD file... */
674 for (units = 1440; units < header->HWResolution[0]; units *= 2);
675
676 if (ppd->model_number & ESCP_EXT_UNITS)
677 {
678 cupsWritePrintData("\033(U\005\000", 5);
679 putchar(units / header->HWResolution[1]);
680 putchar(units / header->HWResolution[1]);
681 putchar(units / header->HWResolution[0]);
682 putchar(units);
683 putchar(units >> 8);
684 }
685 else
686 {
687 cupsWritePrintData("\033(U\001\000", 5);
688 putchar(3600 / header->HWResolution[1]);
689 }
690
691 /*
692 * Set the page length...
693 */
694
695 PrinterLength = header->PageSize[1] * header->HWResolution[1] / 72;
696
697 if (ppd->model_number & ESCP_PAGE_SIZE)
698 {
699 /*
700 * Set page size (expands bottom margin)...
701 */
702
703 cupsWritePrintData("\033(S\010\000", 5);
704
705 i = header->PageSize[0] * header->HWResolution[1] / 72;
706 putchar(i);
707 putchar(i >> 8);
708 putchar(i >> 16);
709 putchar(i >> 24);
710
711 i = header->PageSize[1] * header->HWResolution[1] / 72;
712 putchar(i);
713 putchar(i >> 8);
714 putchar(i >> 16);
715 putchar(i >> 24);
716 }
717 else
718 {
719 cupsWritePrintData("\033(C\002\000", 5);
720 putchar(PrinterLength & 255);
721 putchar(PrinterLength >> 8);
722 }
723
724 /*
725 * Set the top and bottom margins...
726 */
727
728 PrinterTop = (int)((ppd->sizes[1].length - ppd->sizes[1].top) *
729 header->HWResolution[1] / 72.0);
730
731 if (ppd->model_number & ESCP_EXT_MARGINS)
732 {
733 cupsWritePrintData("\033(c\010\000", 5);
734
735 putchar(PrinterTop);
736 putchar(PrinterTop >> 8);
737 putchar(PrinterTop >> 16);
738 putchar(PrinterTop >> 24);
739
740 putchar(PrinterLength);
741 putchar(PrinterLength >> 8);
742 putchar(PrinterLength >> 16);
743 putchar(PrinterLength >> 24);
744 }
745 else
746 {
747 cupsWritePrintData("\033(c\004\000", 5);
748
749 putchar(PrinterTop & 255);
750 putchar(PrinterTop >> 8);
751
752 putchar(PrinterLength & 255);
753 putchar(PrinterLength >> 8);
754 }
755
756 /*
757 * Set the top position...
758 */
759
760 cupsWritePrintData("\033(V\002\000\000\000", 7);
761
762 /*
763 * Enable unidirectional printing depending on the mode...
764 */
765
766 if ((attr = cupsFindAttr(ppd, "cupsESCPDirection", colormodel,
767 header->MediaType, resolution, spec,
768 sizeof(spec))) != NULL)
769 printf("\033U%c", atoi(attr->value));
770
771 /*
772 * Enable/disable microweaving as needed...
773 */
774
775 if ((attr = cupsFindAttr(ppd, "cupsESCPMicroWeave", colormodel,
776 header->MediaType, resolution, spec,
777 sizeof(spec))) != NULL)
778 printf("\033(i\001%c%c", 0, atoi(attr->value));
779
780 /*
781 * Set the dot size and print speed as needed...
782 */
783
784 if ((attr = cupsFindAttr(ppd, "cupsESCPDotSize", colormodel,
785 header->MediaType, resolution, spec,
786 sizeof(spec))) != NULL)
787 printf("\033(e\002%c%c%c", 0, 0, atoi(attr->value));
788
789 if (ppd->model_number & ESCP_ESCK)
790 {
791 /*
792 * Set the print mode...
793 */
794
795 if (PrinterPlanes == 1)
796 {
797 /*
798 * Fast black printing.
799 */
800
801 cupsWritePrintData("\033(K\002\000\000\001", 7);
802 }
803 else
804 {
805 /*
806 * Color printing.
807 */
808
809 cupsWritePrintData("\033(K\002\000\000\002", 7);
810 }
811 }
812
813 /*
814 * Get softweave settings from header...
815 */
816
817 if (header->cupsRowCount <= 1)
818 {
819 DotRowCount = 1;
820 DotColStep = 1;
821 DotRowStep = 1;
822 DotRowFeed = 1;
823 }
824 else
825 {
826 DotRowCount = header->cupsRowCount;
827 DotRowFeed = header->cupsRowFeed;
828 DotRowStep = header->cupsRowStep % 100;
829 DotColStep = header->cupsRowStep / 100;
830
831 if (DotColStep == 0)
832 DotColStep ++;
833 }
834
835 /*
836 * Setup softweave parameters...
837 */
838
839 DotRowCurrent = 0;
840 DotRowMax = DotRowCount * DotRowStep;
841 DotBufferSize = (header->cupsWidth / DotColStep * BitPlanes + 7) / 8;
842
843 fprintf(stderr, "DEBUG: DotBufferSize = %d\n", DotBufferSize);
844 fprintf(stderr, "DEBUG: DotColStep = %d\n", DotColStep);
845 fprintf(stderr, "DEBUG: DotRowMax = %d\n", DotRowMax);
846 fprintf(stderr, "DEBUG: DotRowStep = %d\n", DotRowStep);
847 fprintf(stderr, "DEBUG: DotRowFeed = %d\n", DotRowFeed);
848 fprintf(stderr, "DEBUG: DotRowCount = %d\n", DotRowCount);
849
850 DotAvailList = NULL;
851 DotUsedList = NULL;
852 DotBuffers[0] = NULL;
853
854 fprintf(stderr, "DEBUG: model_number = %x\n", ppd->model_number);
855
856 if (DotRowMax > 1)
857 {
858 /*
859 * Compute offsets for the color jets on the print head...
860 */
861
862 bands = DotRowStep * DotColStep * PrinterPlanes * 4;
863
864 memset(DotRowOffset, 0, sizeof(DotRowOffset));
865
866 if (PrinterPlanes == 1)
867 {
868 /*
869 * Use full height of print head...
870 */
871
872 if ((attr = ppdFindAttr(ppd, "cupsESCPBlack", resolution)) != NULL &&
873 attr->value)
874 {
875 /*
876 * Use custom black head data...
877 */
878
879 sscanf(attr->value, "%d%d", &DotRowCount, &DotRowStep);
880 }
881 }
882 else if (ppd->model_number & ESCP_STAGGER)
883 {
884 /*
885 * Use staggered print head...
886 */
887
888 fputs("DEBUG: Offset head detected...\n", stderr);
889
890 if ((attr = ppdFindAttr(ppd, "cupsESCPOffsets", resolution)) != NULL &&
891 attr->value)
892 {
893 /*
894 * Use only 1/3 of the print head when printing color...
895 */
896
897 sscanf(attr->value, "%d%d%d%d", DotRowOffset + 0,
898 DotRowOffset + 1, DotRowOffset + 2, DotRowOffset + 3);
899 }
900 }
901
902 for (i = 0; i < PrinterPlanes; i ++)
903 fprintf(stderr, "DEBUG: DotRowOffset[%d] = %d\n", i, DotRowOffset[i]);
904
905 /*
906 * Allocate bands...
907 */
908
909 for (i = 0; i < bands; i ++)
910 {
911 band = (cups_weave_t *)calloc(1, sizeof(cups_weave_t));
912 band->next = DotAvailList;
913 DotAvailList = band;
914
915 band->buffer = calloc(DotRowCount, DotBufferSize);
916 }
917
1f0275e3
MS
918 if (!DotAvailList)
919 {
4d301e69 920 fputs("ERROR: Unable to allocate band list\n", stderr);
1f0275e3
MS
921 exit(1);
922 }
923
ac884b6a
MS
924 fputs("DEBUG: Pointer list at start of page...\n", stderr);
925
926 for (band = DotAvailList; band != NULL; band = band->next)
927 fprintf(stderr, "DEBUG: %p\n", band);
928
929 fputs("DEBUG: ----END----\n", stderr);
930
931 /*
932 * Fill the initial bands...
933 */
934
935 modrow = DotColStep * DotRowStep;
936
937 if (DotRowFeed == 0)
938 {
939 /*
940 * Automatically compute the optimal feed value...
941 */
942
943 DotRowFeed = DotRowCount / DotColStep - DotRowStep;
944
945 while ((((DotRowFeed % 2) == 0) == ((DotRowCount % 2) == 0) ||
946 ((DotRowFeed % 3) == 0) == ((DotRowCount % 3) == 0) ||
947 ((DotRowFeed % 5) == 0) == ((DotRowCount % 5) == 0)) &&
948 DotRowFeed > 1)
949 DotRowFeed --;
950
951 if (DotRowFeed < 1)
952 DotRowFeed = 1;
953
954 fprintf(stderr, "DEBUG: Auto DotRowFeed = %d, modrow=%d...\n",
955 DotRowFeed, modrow);
956 }
957
958 memset(DotBands, 0, sizeof(DotBands));
959
960 for (i = modrow, subrow = modrow - 1, y = DotRowFeed;
961 i > 0;
962 i --, y += DotRowFeed)
963 {
964 while (DotBands[subrow][0])
965 {
966 /*
967 * This subrow is already used, move to another one...
968 */
969
970 subrow = (subrow + 1) % modrow;
971 }
972
973 for (plane = 0; plane < PrinterPlanes; plane ++)
974 {
975 /*
976 * Pull the next available band from the list...
977 */
978
979 band = DotAvailList;
980 DotAvailList = DotAvailList->next;
981 DotBands[subrow][plane] = band;
982
983 /*
984 * Start the band in the first few passes, with the number of rows
985 * varying to allow for a nice interleaved pattern...
986 */
987
988 band->x = subrow / DotRowStep;
989 band->y = (subrow % DotRowStep) + DotRowOffset[plane];
990 band->plane = plane;
991 band->row = 0;
992 band->count = DotRowCount - y / DotRowStep;
993
994 if (band->count < 1)
995 band->count = 1;
996 else if (band->count > DotRowCount)
997 band->count = DotRowCount;
998
999 fprintf(stderr, "DEBUG: DotBands[%d][%d] = %p, x = %d, y = %d, plane = %d, count = %d\n",
1000 subrow, plane, band, band->x, band->y, band->plane, band->count);
1001 }
1002
1003 subrow = (subrow + DotRowFeed) % modrow;
1004 }
1005 }
1006 else
1007 {
1008 /*
1009 * Allocate memory for a single line of graphics...
1010 */
1011
1012 ptr = calloc(PrinterPlanes, DotBufferSize);
1013
1014 for (plane = 0; plane < PrinterPlanes; plane ++, ptr += DotBufferSize)
1015 DotBuffers[plane] = ptr;
1016 }
1017
1018 /*
1019 * Set the output resolution...
1020 */
1021
1022 cupsWritePrintData("\033(D\004\000", 5);
1023 putchar(units);
1024 putchar(units >> 8);
1025 putchar(units * DotRowStep / header->HWResolution[1]);
1026 putchar(units * DotColStep / header->HWResolution[0]);
1027
1028 /*
1029 * Set the top of form...
1030 */
1031
1032 OutputFeed = 0;
1033
1034 /*
1035 * Allocate buffers as needed...
1036 */
1037
1038 PixelBuffer = malloc(header->cupsBytesPerLine);
1039 InputBuffer = malloc(header->cupsWidth * PrinterPlanes * 2);
1040 OutputBuffers[0] = malloc(PrinterPlanes * header->cupsWidth);
1041
1042 for (i = 1; i < PrinterPlanes; i ++)
1043 OutputBuffers[i] = OutputBuffers[0] + i * header->cupsWidth;
1044
1045 if (RGB)
1046 CMYKBuffer = malloc(header->cupsWidth * PrinterPlanes);
1047
1048 CompBuffer = malloc(10 * DotBufferSize * DotRowMax);
1049}
1050
1051
1052/*
1053 * 'EndPage()' - Finish a page of graphics.
1054 */
1055
1056void
1057EndPage(ppd_file_t *ppd, /* I - PPD file */
839a51c8 1058 cups_page_header2_t *header) /* I - Page header */
ac884b6a
MS
1059{
1060 int i; /* Looping var */
1061 cups_weave_t *band, /* Current band */
1062 *next; /* Next band in list */
1063 int plane; /* Current plane */
1064 int subrow; /* Current subrow */
1065 int subrows; /* Number of subrows */
1066
1067
1068 /*
1069 * Output the last bands of print data as necessary...
1070 */
1071
1072 if (DotRowMax > 1)
1073 {
1074 /*
1075 * Move the remaining bands to the used or avail lists...
1076 */
1077
1078 subrows = DotRowStep * DotColStep;
1079
1080 for (subrow = 0; subrow < subrows; subrow ++)
1081 for (plane = 0; plane < PrinterPlanes; plane ++)
1082 {
1083 if (DotBands[subrow][plane]->dirty)
1084 {
1085 /*
1086 * Insert into the used list...
1087 */
1088
1089 DotBands[subrow][plane]->count = DotBands[subrow][plane]->row;
1090
1091 AddBand(DotBands[subrow][plane]);
1092 }
1093 else
1094 {
1095 /*
1096 * Nothing here, so move it to the available list...
1097 */
1098
1099 DotBands[subrow][plane]->next = DotAvailList;
1100 DotAvailList = DotBands[subrow][plane];
1101 }
1102
1103 DotBands[subrow][plane] = NULL;
1104 }
1105
1106 /*
1107 * Loop until all bands are written...
1108 */
1109
1110 fputs("DEBUG: Pointer list at end of page...\n", stderr);
1111
1112 for (band = DotUsedList; band != NULL; band = band->next)
1113 fprintf(stderr, "DEBUG: %p (used)\n", band);
1114 for (band = DotAvailList; band != NULL; band = band->next)
1115 fprintf(stderr, "DEBUG: %p (avail)\n", band);
1116
1117 fputs("DEBUG: ----END----\n", stderr);
1118
1119 for (band = DotUsedList; band != NULL; band = next)
1120 {
1121 next = band->next;
1122
1123 OutputBand(ppd, header, band);
1124
1125 fprintf(stderr, "DEBUG: freeing used band %p, prev = %p, next = %p\n",
1126 band, band->prev, band->next);
1127
1128 free(band->buffer);
1129 free(band);
1130 }
1131
1132 /*
1133 * Free memory for the available bands, if any...
1134 */
1135
1136 for (band = DotAvailList; band != NULL; band = next)
1137 {
1138 next = band->next;
1139
1140 fprintf(stderr, "DEBUG: freeing avail band %p, prev = %p, next = %p\n",
1141 band, band->prev, band->next);
1142
1143 free(band->buffer);
1144 free(band);
1145 }
1146 }
1147 else
1148 free(DotBuffers[0]);
1149
1150 /*
1151 * Output a page eject sequence...
1152 */
1153
1154 putchar(12);
1155
1156 /*
1157 * Free memory for the page...
1158 */
1159
1160 for (i = 0; i < PrinterPlanes; i ++)
1161 {
1162 cupsDitherDelete(DitherStates[i]);
1163 cupsLutDelete(DitherLuts[i]);
1164 }
1165
1166 free(OutputBuffers[0]);
1167
1168 free(PixelBuffer);
1169 free(InputBuffer);
1170 free(CompBuffer);
1171
1172 cupsCMYKDelete(CMYK);
1173
1174 if (RGB)
1175 {
1176 cupsRGBDelete(RGB);
1177 free(CMYKBuffer);
1178 }
1179}
1180
1181
1182/*
1183 * 'Shutdown()' - Shutdown a printer.
1184 */
1185
1186void
1187Shutdown(ppd_file_t *ppd) /* I - PPD file */
1188{
1189 /*
1190 * Reset the printer...
1191 */
1192
1193 printf("\033@");
1194
1195 if (ppd->model_number & ESCP_REMOTE)
1196 {
1197 /*
1198 * Go into remote mode...
1199 */
1200
1201 cupsWritePrintData("\033(R\010\000\000REMOTE1", 13);
1202
1203 /*
1204 * Load defaults...
1205 */
1206
1207 cupsWritePrintData("LD\000\000", 4);
1208
1209 /*
1210 * Exit remote mode...
1211 */
1212
1213 cupsWritePrintData("\033\000\000\000", 4);
1214 }
1215}
1216
1217
1218/*
1219 * 'AddBand()' - Add a band of data to the used list.
1220 */
1221
1222void
1223AddBand(cups_weave_t *band) /* I - Band to add */
1224{
1225 cups_weave_t *current, /* Current band */
1226 *prev; /* Previous band */
1227
1228
1229 if (band->count < 1)
1230 return;
1231
1232 for (current = DotUsedList, prev = NULL;
1233 current != NULL;
1234 prev = current, current = current->next)
1235 if (band->y < current->y ||
1236 (band->y == current->y && band->x < current->x) ||
1237 (band->y == current->y && band->x == current->x &&
1238 band->plane < current->plane))
1239 break;
1240
1241 if (current != NULL)
1242 {
1243 /*
1244 * Insert the band...
1245 */
1246
1247 band->next = current;
1248 band->prev = prev;
1249 current->prev = band;
1250
1251 if (prev != NULL)
1252 prev->next = band;
1253 else
1254 DotUsedList = band;
1255 }
1256 else if (prev != NULL)
1257 {
1258 /*
1259 * Append the band to the end...
1260 */
1261
1262 band->prev = prev;
1263 prev->next = band;
1264 band->next = NULL;
1265 }
1266 else
1267 {
1268 /*
1269 * First band in list...
1270 */
1271
1272 DotUsedList = band;
1273 band->prev = NULL;
1274 band->next = NULL;
1275 }
1276}
1277
1278
839a51c8
MS
1279/*
1280 * 'CancelJob()' - Cancel the current job...
1281 */
1282
1283void
1284CancelJob(int sig) /* I - Signal */
1285{
1286 (void)sig;
1287
1288 Canceled = 1;
1289}
1290
1291
ac884b6a
MS
1292/*
1293 * 'CompressData()' - Compress a line of graphics.
1294 */
1295
1296void
1297CompressData(ppd_file_t *ppd, /* I - PPD file information */
1298 const unsigned char *line, /* I - Data to compress */
1299 const int length,/* I - Number of bytes */
1300 int plane, /* I - Color plane */
1301 int type, /* I - Type of compression */
1302 const int rows, /* I - Number of lines to write */
1303 const int xstep, /* I - Spacing between columns */
1304 const int ystep, /* I - Spacing between lines */
1305 const int offset)/* I - Head offset */
1306{
1307 register const unsigned char *line_ptr,
1308 /* Current byte pointer */
1309 *line_end, /* End-of-line byte pointer */
1310 *start; /* Start of compression sequence */
1311 register unsigned char *comp_ptr; /* Pointer into compression buffer */
1312 register int count; /* Count of bytes for output */
1313 register int bytes; /* Number of bytes per row */
1314 static int ctable[7][7] = /* Colors */
1315 {
1316 { 0, 0, 0, 0, 0, 0, 0 }, /* K */
1317 { 0, 16, 0, 0, 0, 0, 0 }, /* Kk */
1318 { 2, 1, 4, 0, 0, 0, 0 }, /* CMY */
1319 { 2, 1, 4, 0, 0, 0, 0 }, /* CMYK */
1320 { 0, 0, 0, 0, 0, 0, 0 },
1321 { 2, 18, 1, 17, 4, 0, 0 }, /* CcMmYK */
1322 { 2, 18, 1, 17, 4, 0, 16 }, /* CcMmYKk */
1323 };
1324
1325
1326 switch (type)
1327 {
1328 case 0 :
1329 /*
1330 * Do no compression...
1331 */
1332
1333 line_ptr = (const unsigned char *)line;
1334 line_end = (const unsigned char *)line + length;
1335 break;
1336
1337 default :
1338 /*
1339 * Do TIFF pack-bits encoding...
1340 */
1341
1342 line_ptr = (const unsigned char *)line;
1343 line_end = (const unsigned char *)line + length;
1344 comp_ptr = CompBuffer;
1345
1346 while (line_ptr < line_end && (comp_ptr - CompBuffer) < length)
1347 {
1348 if ((line_ptr + 1) >= line_end)
1349 {
1350 /*
1351 * Single byte on the end...
1352 */
1353
1354 *comp_ptr++ = 0x00;
1355 *comp_ptr++ = *line_ptr++;
1356 }
1357 else if (line_ptr[0] == line_ptr[1])
1358 {
1359 /*
1360 * Repeated sequence...
1361 */
1362
1363 line_ptr ++;
1364 count = 2;
1365
1366 while (line_ptr < (line_end - 1) &&
1367 line_ptr[0] == line_ptr[1] &&
1368 count < 127)
1369 {
1370 line_ptr ++;
1371 count ++;
1372 }
1373
1374 *comp_ptr++ = 257 - count;
1375 *comp_ptr++ = *line_ptr++;
1376 }
1377 else
1378 {
1379 /*
1380 * Non-repeated sequence...
1381 */
1382
1383 start = line_ptr;
1384 line_ptr ++;
1385 count = 1;
1386
1387 while (line_ptr < (line_end - 1) &&
1388 line_ptr[0] != line_ptr[1] &&
1389 count < 127)
1390 {
1391 line_ptr ++;
1392 count ++;
1393 }
1394
1395 *comp_ptr++ = count - 1;
1396
1397 memcpy(comp_ptr, start, count);
1398 comp_ptr += count;
1399 }
1400 }
1401
1402 if ((comp_ptr - CompBuffer) < length)
1403 {
1404 line_ptr = (const unsigned char *)CompBuffer;
1405 line_end = (const unsigned char *)comp_ptr;
1406 }
1407 else
1408 {
1409 type = 0;
1410 line_ptr = (const unsigned char *)line;
1411 line_end = (const unsigned char *)line + length;
1412 }
1413 break;
1414 }
1415
1416 /*
1417 * Position the print head...
1418 */
1419
1420 putchar(0x0d);
1421
1422 if (offset)
1423 {
1424 if (BitPlanes == 1)
1425 cupsWritePrintData("\033(\\\004\000\240\005", 7);
1426 else
1427 printf("\033\\");
1428
1429 putchar(offset);
1430 putchar(offset >> 8);
1431 }
1432
1433 /*
1434 * Send the graphics...
1435 */
1436
1437 bytes = length / rows;
1438
1439 if (ppd->model_number & ESCP_RASTER_ESCI)
1440 {
1441 /*
1442 * Send graphics with ESC i command.
1443 */
1444
1445 printf("\033i");
1446 putchar(ctable[PrinterPlanes - 1][plane]);
1447 putchar(type != 0);
1448 putchar(BitPlanes);
1449 putchar(bytes & 255);
1450 putchar(bytes >> 8);
1451 putchar(rows & 255);
1452 putchar(rows >> 8);
1453 }
1454 else
1455 {
1456 /*
1457 * Set the color if necessary...
1458 */
1459
1460 if (PrinterPlanes > 1)
1461 {
1462 plane = ctable[PrinterPlanes - 1][plane];
1463
1464 if (plane & 0x10)
1465 printf("\033(r%c%c%c%c", 2, 0, 1, plane & 0x0f);
1466 else
1467 printf("\033r%c", plane);
1468 }
1469
1470 /*
1471 * Send graphics with ESC . command.
1472 */
1473
1474 bytes *= 8;
1475
1476 printf("\033.");
1477 putchar(type != 0);
1478 putchar(ystep);
1479 putchar(xstep);
1480 putchar(rows);
1481 putchar(bytes & 255);
1482 putchar(bytes >> 8);
1483 }
1484
1485 cupsWritePrintData(line_ptr, line_end - line_ptr);
1486}
1487
1488
1489/*
1490 * 'OutputBand()' - Output a band of graphics.
1491 */
1492
1493void
1494OutputBand(ppd_file_t *ppd, /* I - PPD file */
839a51c8 1495 cups_page_header2_t *header, /* I - Page header */
ac884b6a
MS
1496 cups_weave_t *band) /* I - Current band */
1497{
1498 int xstep, /* Spacing between columns */
1499 ystep; /* Spacing between rows */
1500
1501
1502 /*
1503 * Interleaved ESC/P2 graphics...
1504 */
1505
1506 OutputFeed = band->y - DotRowCurrent;
1507 DotRowCurrent = band->y;
1508
1509 fprintf(stderr, "DEBUG: Printing band %p, x = %d, y = %d, plane = %d, count = %d, OutputFeed = %d\n",
1510 band, band->x, band->y, band->plane, band->count, OutputFeed);
1511
1512 /*
1513 * Compute step values...
1514 */
1515
1516 xstep = 3600 * DotColStep / header->HWResolution[0];
1517 ystep = 3600 * DotRowStep / header->HWResolution[1];
1518
1519 /*
1520 * Output the band...
1521 */
1522
1523 if (OutputFeed > 0)
1524 {
1525 cupsWritePrintData("\033(v\002\000", 5);
1526 putchar(OutputFeed & 255);
1527 putchar(OutputFeed >> 8);
1528
1529 OutputFeed = 0;
1530 }
1531
1532 CompressData(ppd, band->buffer, band->count * DotBufferSize, band->plane,
1533 header->cupsCompression, band->count, xstep, ystep, band->x);
1534
1535 /*
1536 * Clear the band...
1537 */
1538
1539 memset(band->buffer, 0, band->count * DotBufferSize);
1540 band->dirty = 0;
1541
1542 /*
1543 * Flush the output buffers...
1544 */
1545
1546 fflush(stdout);
1547}
1548
1549
1550/*
1551 * 'ProcessLine()' - Read graphics from the page stream and output as needed.
1552 */
1553
1554void
1555ProcessLine(ppd_file_t *ppd, /* I - PPD file */
1556 cups_raster_t *ras, /* I - Raster stream */
839a51c8 1557 cups_page_header2_t *header, /* I - Page header */
ac884b6a
MS
1558 const int y) /* I - Current scanline */
1559{
1560 int plane, /* Current color plane */
1561 width, /* Width of line */
1562 subwidth, /* Width of interleaved row */
1563 subrow, /* Subrow for interleaved output */
1564 offset, /* Offset to current line */
1565 pass, /* Pass number */
1566 xstep, /* X step value */
1567 ystep; /* Y step value */
1568 cups_weave_t *band; /* Current band */
1569
1570
1571 /*
1572 * Read a row of graphics...
1573 */
1574
1575 if (!cupsRasterReadPixels(ras, PixelBuffer, header->cupsBytesPerLine))
1576 return;
1577
1578 /*
1579 * Perform the color separation...
1580 */
1581
ac884b6a
MS
1582 width = header->cupsWidth;
1583 subwidth = header->cupsWidth / DotColStep;
1584 xstep = 3600 / header->HWResolution[0];
1585 ystep = 3600 / header->HWResolution[1];
1586
1587 switch (header->cupsColorSpace)
1588 {
1589 case CUPS_CSPACE_W :
1590 if (RGB)
1591 {
1592 cupsRGBDoGray(RGB, PixelBuffer, CMYKBuffer, width);
1593 cupsCMYKDoCMYK(CMYK, CMYKBuffer, InputBuffer, width);
1594 }
1595 else
1596 cupsCMYKDoGray(CMYK, PixelBuffer, InputBuffer, width);
1597 break;
1598
1599 case CUPS_CSPACE_K :
1600 cupsCMYKDoBlack(CMYK, PixelBuffer, InputBuffer, width);
1601 break;
1602
1603 default :
1604 case CUPS_CSPACE_RGB :
1605 if (RGB)
1606 {
1607 cupsRGBDoRGB(RGB, PixelBuffer, CMYKBuffer, width);
1608 cupsCMYKDoCMYK(CMYK, CMYKBuffer, InputBuffer, width);
1609 }
1610 else
1611 cupsCMYKDoRGB(CMYK, PixelBuffer, InputBuffer, width);
1612 break;
1613
1614 case CUPS_CSPACE_CMYK :
1615 cupsCMYKDoCMYK(CMYK, PixelBuffer, InputBuffer, width);
1616 break;
1617 }
1618
1619 /*
1620 * Dither the pixels...
1621 */
1622
1623 for (plane = 0; plane < PrinterPlanes; plane ++)
1624 {
1625 cupsDitherLine(DitherStates[plane], DitherLuts[plane], InputBuffer + plane,
1626 PrinterPlanes, OutputBuffers[plane]);
1627
1628 if (DotRowMax == 1)
1629 {
1630 /*
1631 * Handle microweaved output...
1632 */
1633
1634 if (cupsCheckBytes(OutputBuffers[plane], width))
1635 continue;
1636
1637 if (BitPlanes == 1)
1638 cupsPackHorizontal(OutputBuffers[plane], DotBuffers[plane],
1639 width, 0, 1);
1640 else
1641 cupsPackHorizontal2(OutputBuffers[plane], DotBuffers[plane],
1642 width, 1);
1643
1644 if (OutputFeed > 0)
1645 {
1646 cupsWritePrintData("\033(v\002\000", 5);
1647 putchar(OutputFeed & 255);
1648 putchar(OutputFeed >> 8);
1649 OutputFeed = 0;
1650 }
1651
1652 CompressData(ppd, DotBuffers[plane], DotBufferSize, plane, 1, 1,
1653 xstep, ystep, 0);
1654 fflush(stdout);
1655 }
1656 else
1657 {
1658 /*
1659 * Handle softweaved output...
1660 */
1661
1662 for (pass = 0, subrow = y % DotRowStep;
1663 pass < DotColStep;
1664 pass ++, subrow += DotRowStep)
1665 {
1666 /*
1667 * See if we need to output the band...
1668 */
1669
1670 band = DotBands[subrow][plane];
1671 offset = band->row * DotBufferSize;
1672
1673 if (BitPlanes == 1)
1674 cupsPackHorizontal(OutputBuffers[plane] + pass,
1675 band->buffer + offset, subwidth, 0, DotColStep);
1676 else
1677 cupsPackHorizontal2(OutputBuffers[plane] + pass,
1678 band->buffer + offset, subwidth, DotColStep);
1679
1680 band->row ++;
1681 band->dirty |= !cupsCheckBytes(band->buffer + offset, DotBufferSize);
1682 if (band->row >= band->count)
1683 {
1684 if (band->dirty)
1685 {
1686 /*
1687 * Dirty band needs to be added to the used list...
1688 */
1689
1690 AddBand(band);
1691
1692 /*
1693 * Then find a new band...
1694 */
1695
1696 if (DotAvailList == NULL)
1697 {
1698 OutputBand(ppd, header, DotUsedList);
1699
1700 DotBands[subrow][plane] = DotUsedList;
1701 DotUsedList->x = band->x;
1702 DotUsedList->y = band->y + band->count * DotRowStep;
1703 DotUsedList->plane = band->plane;
1704 DotUsedList->row = 0;
1705 DotUsedList->count = DotRowCount;
1706 DotUsedList = DotUsedList->next;
1707 }
1708 else
1709 {
1710 DotBands[subrow][plane] = DotAvailList;
1711 DotAvailList->x = band->x;
1712 DotAvailList->y = band->y + band->count * DotRowStep;
1713 DotAvailList->plane = band->plane;
1714 DotAvailList->row = 0;
1715 DotAvailList->count = DotRowCount;
1716 DotAvailList = DotAvailList->next;
1717 }
1718 }
1719 else
1720 {
1721 /*
1722 * This band isn't dirty, so reuse it...
1723 */
1724
1725 fprintf(stderr, "DEBUG: Blank band %p, x = %d, y = %d, plane = %d, count = %d\n",
1726 band, band->x, band->y, band->plane, band->count);
1727
1728 band->y += band->count * DotRowStep;
1729 band->row = 0;
1730 band->count = DotRowCount;
1731 }
1732 }
1733 }
1734 }
1735 }
1736
1737 if (DotRowMax == 1)
1738 OutputFeed ++;
1739}
1740
1741
1742/*
1743 * 'main()' - Main entry and processing of driver.
1744 */
1745
1746int /* O - Exit status */
1747main(int argc, /* I - Number of command-line arguments */
1748 char *argv[]) /* I - Command-line arguments */
1749{
1750 int fd; /* File descriptor */
1751 cups_raster_t *ras; /* Raster stream for printing */
839a51c8 1752 cups_page_header2_t header; /* Page header from file */
ac884b6a
MS
1753 int page; /* Current page */
1754 int y; /* Current line */
1755 ppd_file_t *ppd; /* PPD file */
1756 int num_options; /* Number of options */
1757 cups_option_t *options; /* Options */
839a51c8
MS
1758#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
1759 struct sigaction action; /* Actions for POSIX signals */
1760#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
ac884b6a
MS
1761
1762
1763 /*
1764 * Make sure status messages are not buffered...
1765 */
1766
1767 setbuf(stderr, NULL);
1768
1769 /*
1770 * Check command-line...
1771 */
1772
1773 if (argc < 6 || argc > 7)
1774 {
f0ab5bff
MS
1775 _cupsLangPrintf(stderr,
1776 _("ERROR: %s job-id user title copies options [file]\n"),
1777 "rastertoescpx");
ac884b6a
MS
1778 return (1);
1779 }
1780
1781 num_options = cupsParseOptions(argv[5], 0, &options);
1782
1783 /*
1784 * Open the PPD file...
1785 */
1786
1787 ppd = ppdOpenFile(getenv("PPD"));
1788
1789 if (!ppd)
1790 {
4d301e69 1791 _cupsLangPuts(stderr, _("ERROR: Unable to open PPD file\n"));
ac884b6a
MS
1792 return (1);
1793 }
1794
1795 ppdMarkDefaults(ppd);
1796 cupsMarkOptions(ppd, num_options, options);
1797
1798 /*
1799 * Open the page stream...
1800 */
1801
1802 if (argc == 7)
1803 {
1804 if ((fd = open(argv[6], O_RDONLY)) == -1)
1805 {
f0ab5bff
MS
1806 _cupsLangPrintf(stderr, _("ERROR: Unable to open raster file - %s\n"),
1807 strerror(errno));
ac884b6a
MS
1808 return (1);
1809 }
1810 }
1811 else
1812 fd = 0;
1813
1814 ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
1815
839a51c8
MS
1816 /*
1817 * Register a signal handler to eject the current page if the
1818 * job is cancelled.
1819 */
1820
1821 Canceled = 0;
1822
1823#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
1824 sigset(SIGTERM, CancelJob);
1825#elif defined(HAVE_SIGACTION)
1826 memset(&action, 0, sizeof(action));
1827
1828 sigemptyset(&action.sa_mask);
1829 action.sa_handler = CancelJob;
1830 sigaction(SIGTERM, &action, NULL);
1831#else
1832 signal(SIGTERM, CancelJob);
1833#endif /* HAVE_SIGSET */
1834
ac884b6a
MS
1835 /*
1836 * Initialize the print device...
1837 */
1838
1839 Setup(ppd);
1840
1841 /*
1842 * Process pages as needed...
1843 */
1844
1845 page = 0;
1846
839a51c8 1847 while (cupsRasterReadHeader2(ras, &header))
ac884b6a 1848 {
839a51c8
MS
1849 /*
1850 * Write a status message with the page number and number of copies.
1851 */
1852
1853 if (Canceled)
1854 break;
1855
ac884b6a
MS
1856 page ++;
1857
1858 fprintf(stderr, "PAGE: %d 1\n", page);
f0ab5bff 1859 _cupsLangPrintf(stderr, _("INFO: Starting page %d...\n"), page);
ac884b6a
MS
1860
1861 StartPage(ppd, &header);
1862
1863 for (y = 0; y < header.cupsHeight; y ++)
1864 {
839a51c8
MS
1865 /*
1866 * Let the user know how far we have progressed...
1867 */
1868
1869 if (Canceled)
1870 break;
1871
ac884b6a 1872 if ((y & 127) == 0)
f0ab5bff
MS
1873 _cupsLangPrintf(stderr, _("INFO: Printing page %d, %d%% complete...\n"),
1874 page, 100 * y / header.cupsHeight);
ac884b6a 1875
839a51c8
MS
1876 /*
1877 * Read and write a line of graphics or whitespace...
1878 */
1879
ac884b6a
MS
1880 ProcessLine(ppd, ras, &header, y);
1881 }
1882
839a51c8
MS
1883 /*
1884 * Eject the page...
1885 */
1886
f0ab5bff 1887 _cupsLangPrintf(stderr, _("INFO: Finished page %d...\n"), page);
ac884b6a
MS
1888
1889 EndPage(ppd, &header);
839a51c8
MS
1890
1891 if (Canceled)
1892 break;
ac884b6a
MS
1893 }
1894
1895 Shutdown(ppd);
1896
1897 cupsFreeOptions(num_options, options);
1898
1899 cupsRasterClose(ras);
1900
1901 if (fd != 0)
1902 close(fd);
1903
1904 if (page == 0)
1905 {
4d301e69 1906 _cupsLangPuts(stderr, _("ERROR: No pages found\n"));
ac884b6a
MS
1907 return (1);
1908 }
1909 else
1910 {
f0ab5bff 1911 _cupsLangPuts(stderr, _("INFO: Ready to print.\n"));
ac884b6a
MS
1912 return (0);
1913 }
1914}
1915
1916
1917/*
1918 * End of "$Id$".
1919 */