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