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