1 /*
2 * EPSON ESC/P and ESC/P2 filter for CUPS.
3 *
4 * Copyright 2007-2018 by Apple Inc.
5 * Copyright 1993-2007 by Easy Software Products.
6 *
7 * These coded instructions, statements, and computer programs are the
8 * property of Apple Inc. and are protected by Federal copyright
9 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
10 * which should have been included with this file. If this file is
11 * missing or damaged, see the license at "http://www.cups.org/".
12 *
13 * This file is subject to the Apple OS-Developed Software exception.
14 */
15
16 /*
17 * Include necessary headers...
18 */
19
20 #include <cups/cups.h>
21 #include <cups/ppd.h>
22 #include <cups/string-private.h>
23 #include <cups/language-private.h>
24 #include <cups/raster.h>
25 #include <unistd.h>
26 #include <fcntl.h>
27 #include <signal.h>
28
29
30 /*
31 * Model numbers...
32 */
33
34 #define EPSON_9PIN 0
35 #define EPSON_24PIN 1
36 #define EPSON_COLOR 2
37 #define EPSON_PHOTO 3
38 #define EPSON_ICOLOR 4
39 #define EPSON_IPHOTO 5
40
41
42 /*
43 * Macros...
44 */
45
46 #define pwrite(s,n) fwrite((s), 1, (n), stdout)
47
48
49 /*
50 * Globals...
51 */
52
53 unsigned char *Planes[6], /* Output buffers */
54 *CompBuffer, /* Compression buffer */
55 *LineBuffers[2]; /* Line bitmap buffers */
56 int Model, /* Model number */
57 EjectPage, /* Eject the page when done? */
58 Shingling, /* Shingle output? */
59 Canceled; /* Has the current job been canceled? */
60 unsigned NumPlanes, /* Number of color planes */
61 Feed, /* Number of lines to skip */
62 DotBit, /* Bit in buffers */
63 DotBytes, /* # bytes in a dot column */
64 DotColumns, /* # columns in 1/60 inch */
65 LineCount, /* # of lines processed */
66 EvenOffset, /* Offset into 'even' buffers */
67 OddOffset; /* Offset into 'odd' buffers */
68
69
70 /*
71 * Prototypes...
72 */
73
74 void Setup(void);
75 void StartPage(const ppd_file_t *ppd, const cups_page_header2_t *header);
76 void EndPage(const cups_page_header2_t *header);
77 void Shutdown(void);
78
79 void CancelJob(int sig);
80 void CompressData(const unsigned char *line, unsigned length, unsigned plane,
81 unsigned type, unsigned xstep, unsigned ystep);
82 void OutputLine(const cups_page_header2_t *header);
83 void OutputRows(const cups_page_header2_t *header, int row);
84
85
86 /*
87 * 'Setup()' - Prepare the printer for printing.
88 */
89
90 void
Setup(void)91 Setup(void)
92 {
93 const char *device_uri; /* The device for the printer... */
94
95
96 /*
97 * EPSON USB printers need an additional command issued at the
98 * beginning of each job to exit from "packet" mode...
99 */
100
101 if ((device_uri = getenv("DEVICE_URI")) != NULL &&
102 strncmp(device_uri, "usb:", 4) == 0 && Model >= EPSON_ICOLOR)
103 pwrite("\000\000\000\033\001@EJL 1284.4\n@EJL \n\033@", 29);
104 }
105
106
107 /*
108 * 'StartPage()' - Start a page of graphics.
109 */
110
111 void
StartPage(const ppd_file_t * ppd,const cups_page_header2_t * header)112 StartPage(
113 const ppd_file_t *ppd, /* I - PPD file */
114 const cups_page_header2_t *header) /* I - Page header */
115 {
116 int n, t; /* Numbers */
117 unsigned plane; /* Looping var */
118
119
120 /*
121 * Show page device dictionary...
122 */
123
124 fprintf(stderr, "DEBUG: StartPage...\n");
125 fprintf(stderr, "DEBUG: Duplex = %d\n", header->Duplex);
126 fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0], header->HWResolution[1]);
127 fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n", header->ImagingBoundingBox[0], header->ImagingBoundingBox[1], header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]);
128 fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0], header->Margins[1]);
129 fprintf(stderr, "DEBUG: ManualFeed = %d\n", header->ManualFeed);
130 fprintf(stderr, "DEBUG: MediaPosition = %d\n", header->MediaPosition);
131 fprintf(stderr, "DEBUG: NumCopies = %d\n", header->NumCopies);
132 fprintf(stderr, "DEBUG: Orientation = %d\n", header->Orientation);
133 fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0], header->PageSize[1]);
134 fprintf(stderr, "DEBUG: cupsWidth = %d\n", header->cupsWidth);
135 fprintf(stderr, "DEBUG: cupsHeight = %d\n", header->cupsHeight);
136 fprintf(stderr, "DEBUG: cupsMediaType = %d\n", header->cupsMediaType);
137 fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header->cupsBitsPerColor);
138 fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header->cupsBitsPerPixel);
139 fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header->cupsBytesPerLine);
140 fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header->cupsColorOrder);
141 fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace);
142 fprintf(stderr, "DEBUG: cupsCompression = %d\n", header->cupsCompression);
143
144 /*
145 * Send a reset sequence.
146 */
147
148 if (ppd && ppd->nickname && strstr(ppd->nickname, "OKIDATA") != NULL)
149 printf("\033{A"); /* Set EPSON emulation mode */
150
151 printf("\033@");
152
153 /*
154 * See which type of printer we are using...
155 */
156
157 switch (Model)
158 {
159 case EPSON_9PIN :
160 case EPSON_24PIN :
161 printf("\033P\022"); /* Set 10 CPI */
162
163 if (header->HWResolution[0] == 360 || header->HWResolution[0] == 240)
164 {
165 printf("\033x1"); /* LQ printing */
166 printf("\033U1"); /* Unidirectional */
167 }
168 else
169 {
170 printf("\033x0"); /* Draft printing */
171 printf("\033U0"); /* Bidirectional */
172 }
173
174 printf("\033l%c\033Q%c", 0, /* Side margins */
175 (int)(10.0 * header->PageSize[0] / 72.0 + 0.5));
176 printf("\033\062\033C%c", /* Page length in 1/6th inches */
177 (int)(header->PageSize[1] / 12.0 + 0.5));
178 printf("\033N%c", 0); /* Bottom margin */
179 printf("\033O"); /* No perforation skip */
180
181 /*
182 * Setup various buffer limits...
183 */
184
185 DotBytes = header->cupsRowCount / 8;
186 DotColumns = header->HWResolution[0] / 60;
187 Shingling = 0;
188
189 if (Model == EPSON_9PIN)
190 printf("\033\063\030"); /* Set line feed */
191 else
192 switch (header->HWResolution[0])
193 {
194 case 60:
195 case 120 :
196 case 240 :
197 printf("\033\063\030"); /* Set line feed */
198 break;
199
200 case 180 :
201 case 360 :
202 Shingling = 1;
203
204 if (header->HWResolution[1] == 180)
205 printf("\033\063\010");/* Set line feed */
206 else
207 printf("\033+\010"); /* Set line feed */
208 break;
209 }
210 break;
211
212 default :
213 /*
214 * Set graphics mode...
215 */
216
217 pwrite("\033(G\001\000\001", 6); /* Graphics mode */
218
219 /*
220 * Set the media size...
221 */
222
223 if (Model < EPSON_ICOLOR)
224 {
225 pwrite("\033(U\001\000", 5); /* Resolution/units */
226 putchar((int)(3600 / header->HWResolution[1]));
227 }
228 else
229 {
230 pwrite("\033(U\005\000", 5);
231 putchar((int)(1440 / header->HWResolution[1]));
232 putchar((int)(1440 / header->HWResolution[1]));
233 putchar((int)(1440 / header->HWResolution[0]));
234 putchar(0xa0); /* n/1440ths... */
235 putchar(0x05);
236 }
237
238 n = (int)(header->PageSize[1] * header->HWResolution[1] / 72.0);
239
240 pwrite("\033(C\002\000", 5); /* Page length */
241 putchar(n);
242 putchar(n >> 8);
243
244 if (ppd)
245 t = (int)((ppd->sizes[1].length - ppd->sizes[1].top) * header->HWResolution[1] / 72.0);
246 else
247 t = 0;
248
249 pwrite("\033(c\004\000", 5); /* Top & bottom margins */
250 putchar(t);
251 putchar(t >> 8);
252 putchar(n);
253 putchar(n >> 8);
254
255 if (header->HWResolution[1] == 720)
256 {
257 pwrite("\033(i\001\000\001", 6); /* Microweave */
258 pwrite("\033(e\002\000\000\001", 7); /* Small dots */
259 }
260
261 pwrite("\033(V\002\000\000\000", 7); /* Set absolute position 0 */
262
263 DotBytes = 0;
264 DotColumns = 0;
265 Shingling = 0;
266 break;
267 }
268
269 /*
270 * Set other stuff...
271 */
272
273 if (header->cupsColorSpace == CUPS_CSPACE_CMY)
274 NumPlanes = 3;
275 else if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
276 NumPlanes = 4;
277 else if (header->cupsColorSpace == CUPS_CSPACE_KCMYcm)
278 NumPlanes = 6;
279 else
280 NumPlanes = 1;
281
282 Feed = 0; /* No blank lines yet */
283
284 /*
285 * Allocate memory for a line/row of graphics...
286 */
287
288 if ((Planes[0] = malloc(header->cupsBytesPerLine + NumPlanes)) == NULL)
289 {
290 fputs("ERROR: Unable to allocate memory\n", stderr);
291 exit(1);
292 }
293
294 for (plane = 1; plane < NumPlanes; plane ++)
295 Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes;
296
297 if (header->cupsCompression || DotBytes)
298 {
299 if ((CompBuffer = calloc(2, header->cupsWidth + 1)) == NULL)
300 {
301 fputs("ERROR: Unable to allocate memory\n", stderr);
302 exit(1);
303 }
304 }
305 else
306 CompBuffer = NULL;
307
308 if (DotBytes)
309 {
310 if ((LineBuffers[0] = calloc((size_t)DotBytes, (header->cupsWidth + 7) * (size_t)(Shingling + 1))) == NULL)
311 {
312 fputs("ERROR: Unable to allocate memory\n", stderr);
313 exit(1);
314 }
315
316 LineBuffers[1] = LineBuffers[0] + DotBytes * header->cupsWidth;
317 DotBit = 128;
318 LineCount = 0;
319 EvenOffset = 0;
320 OddOffset = 0;
321 }
322 }
323
324
325 /*
326 * 'EndPage()' - Finish a page of graphics.
327 */
328
329 void
EndPage(const cups_page_header2_t * header)330 EndPage(
331 const cups_page_header2_t *header) /* I - Page header */
332 {
333 if (DotBytes && header)
334 {
335 /*
336 * Flush remaining graphics as needed...
337 */
338
339 if (!Shingling)
340 {
341 if (DotBit < 128 || EvenOffset)
342 OutputRows(header, 0);
343 }
344 else if (OddOffset > EvenOffset)
345 {
346 OutputRows(header, 1);
347 OutputRows(header, 0);
348 }
349 else
350 {
351 OutputRows(header, 0);
352 OutputRows(header, 1);
353 }
354 }
355
356 /*
357 * Eject the current page...
358 */
359
360 putchar(12); /* Form feed */
361 fflush(stdout);
362
363 /*
364 * Free memory...
365 */
366
367 free(Planes[0]);
368
369 if (CompBuffer)
370 free(CompBuffer);
371
372 if (DotBytes)
373 free(LineBuffers[0]);
374 }
375
376
377 /*
378 * 'Shutdown()' - Shutdown the printer.
379 */
380
381 void
Shutdown(void)382 Shutdown(void)
383 {
384 /*
385 * Send a reset sequence.
386 */
387
388 printf("\033@");
389 }
390
391
392 /*
393 * 'CancelJob()' - Cancel the current job...
394 */
395
396 void
CancelJob(int sig)397 CancelJob(int sig) /* I - Signal */
398 {
399 (void)sig;
400
401 Canceled = 1;
402 }
403
404
405 /*
406 * 'CompressData()' - Compress a line of graphics.
407 */
408
409 void
CompressData(const unsigned char * line,unsigned length,unsigned plane,unsigned type,unsigned xstep,unsigned ystep)410 CompressData(const unsigned char *line, /* I - Data to compress */
411 unsigned length,/* I - Number of bytes */
412 unsigned plane, /* I - Color plane */
413 unsigned type, /* I - Type of compression */
414 unsigned xstep, /* I - X resolution */
415 unsigned ystep) /* I - Y resolution */
416 {
417 const unsigned char *line_ptr, /* Current byte pointer */
418 *line_end, /* End-of-line byte pointer */
419 *start; /* Start of compression sequence */
420 unsigned char *comp_ptr, /* Pointer into compression buffer */
421 temp; /* Current byte */
422 int count; /* Count of bytes for output */
423 static int ctable[6] = { 0, 2, 1, 4, 18, 17 };
424 /* KCMYcm color values */
425
426
427 /*
428 * Setup pointers...
429 */
430
431 line_ptr = line;
432 line_end = line + length;
433
434 /*
435 * Do depletion for 720 DPI printing...
436 */
437
438 if (ystep == 5)
439 {
440 for (comp_ptr = (unsigned char *)line; comp_ptr < line_end;)
441 {
442 /*
443 * Grab the current byte...
444 */
445
446 temp = *comp_ptr;
447
448 /*
449 * Check adjacent bits...
450 */
451
452 if ((temp & 0xc0) == 0xc0)
453 temp &= 0xbf;
454 if ((temp & 0x60) == 0x60)
455 temp &= 0xdf;
456 if ((temp & 0x30) == 0x30)
457 temp &= 0xef;
458 if ((temp & 0x18) == 0x18)
459 temp &= 0xf7;
460 if ((temp & 0x0c) == 0x0c)
461 temp &= 0xfb;
462 if ((temp & 0x06) == 0x06)
463 temp &= 0xfd;
464 if ((temp & 0x03) == 0x03)
465 temp &= 0xfe;
466
467 *comp_ptr++ = temp;
468
469 /*
470 * Check the last bit in the current byte and the first bit in the
471 * next byte...
472 */
473
474 if ((temp & 0x01) && comp_ptr < line_end && *comp_ptr & 0x80)
475 *comp_ptr &= 0x7f;
476 }
477 }
478
479 switch (type)
480 {
481 case 0 :
482 /*
483 * Do no compression...
484 */
485 break;
486
487 case 1 :
488 /*
489 * Do TIFF pack-bits encoding...
490 */
491
492 comp_ptr = CompBuffer;
493
494 while (line_ptr < line_end)
495 {
496 if ((line_ptr + 1) >= line_end)
497 {
498 /*
499 * Single byte on the end...
500 */
501
502 *comp_ptr++ = 0x00;
503 *comp_ptr++ = *line_ptr++;
504 }
505 else if (line_ptr[0] == line_ptr[1])
506 {
507 /*
508 * Repeated sequence...
509 */
510
511 line_ptr ++;
512 count = 2;
513
514 while (line_ptr < (line_end - 1) &&
515 line_ptr[0] == line_ptr[1] &&
516 count < 127)
517 {
518 line_ptr ++;
519 count ++;
520 }
521
522 *comp_ptr++ = (unsigned char)(257 - count);
523 *comp_ptr++ = *line_ptr++;
524 }
525 else
526 {
527 /*
528 * Non-repeated sequence...
529 */
530
531 start = line_ptr;
532 line_ptr ++;
533 count = 1;
534
535 while (line_ptr < (line_end - 1) &&
536 line_ptr[0] != line_ptr[1] &&
537 count < 127)
538 {
539 line_ptr ++;
540 count ++;
541 }
542
543 *comp_ptr++ = (unsigned char)(count - 1);
544
545 memcpy(comp_ptr, start, (size_t)count);
546 comp_ptr += count;
547 }
548 }
549
550 line_ptr = CompBuffer;
551 line_end = comp_ptr;
552 break;
553 }
554
555 putchar(0x0d); /* Move print head to left margin */
556
557 if (Model < EPSON_ICOLOR)
558 {
559 /*
560 * Do graphics the "old" way...
561 */
562
563 if (NumPlanes > 1)
564 {
565 /*
566 * Set the color...
567 */
568
569 if (plane > 3)
570 printf("\033(r%c%c%c%c", 2, 0, 1, ctable[plane] & 15);
571 /* Set extended color */
572 else if (NumPlanes == 3)
573 printf("\033r%c", ctable[plane + 1]);
574 /* Set color */
575 else
576 printf("\033r%c", ctable[plane]); /* Set color */
577 }
578
579 /*
580 * Send a raster plane...
581 */
582
583 length *= 8;
584 printf("\033."); /* Raster graphics */
585 putchar((int)type);
586 putchar((int)ystep);
587 putchar((int)xstep);
588 putchar(1);
589 putchar((int)length);
590 putchar((int)(length >> 8));
591 }
592 else
593 {
594 /*
595 * Do graphics the "new" way...
596 */
597
598 printf("\033i");
599 putchar(ctable[plane]);
600 putchar((int)type);
601 putchar(1);
602 putchar((int)length);
603 putchar((int)(length >> 8));
604 putchar(1);
605 putchar(0);
606 }
607
608 pwrite(line_ptr, (size_t)(line_end - line_ptr));
609 fflush(stdout);
610 }
611
612
613 /*
614 * 'OutputLine()' - Output a line of graphics.
615 */
616
617 void
OutputLine(const cups_page_header2_t * header)618 OutputLine(
619 const cups_page_header2_t *header) /* I - Page header */
620 {
621 if (header->cupsRowCount)
622 {
623 unsigned width;
624 unsigned char *tempptr,
625 *evenptr,
626 *oddptr;
627 unsigned int x;
628 unsigned char bit;
629 const unsigned char *pixel;
630 unsigned char *temp;
631
632
633 /*
634 * Collect bitmap data in the line buffers and write after each buffer.
635 */
636
637 for (x = header->cupsWidth, bit = 128, pixel = Planes[0],
638 temp = CompBuffer;
639 x > 0;
640 x --, temp ++)
641 {
642 if (*pixel & bit)
643 *temp |= DotBit;
644
645 if (bit > 1)
646 bit >>= 1;
647 else
648 {
649 bit = 128;
650 pixel ++;
651 }
652 }
653
654 if (DotBit > 1)
655 DotBit >>= 1;
656 else
657 {
658 /*
659 * Copy the holding buffer to the output buffer, shingling as necessary...
660 */
661
662 if (Shingling && LineCount != 0)
663 {
664 /*
665 * Shingle the output...
666 */
667
668 if (LineCount & 1)
669 {
670 evenptr = LineBuffers[1] + OddOffset;
671 oddptr = LineBuffers[0] + EvenOffset + DotBytes;
672 }
673 else
674 {
675 evenptr = LineBuffers[0] + EvenOffset;
676 oddptr = LineBuffers[1] + OddOffset + DotBytes;
677 }
678
679 for (width = header->cupsWidth, tempptr = CompBuffer;
680 width > 1;
681 width -= 2, tempptr += 2, oddptr += DotBytes * 2,
682 evenptr += DotBytes * 2)
683 {
684 evenptr[0] = tempptr[0];
685 oddptr[0] = tempptr[1];
686 }
687
688 if (width == 1)
689 {
690 evenptr[0] = tempptr[0];
691 oddptr[0] = tempptr[1];
692 }
693 }
694 else
695 {
696 /*
697 * Don't shingle the output...
698 */
699
700 for (width = header->cupsWidth, tempptr = CompBuffer,
701 evenptr = LineBuffers[0] + EvenOffset;
702 width > 0;
703 width --, tempptr ++, evenptr += DotBytes)
704 *evenptr = tempptr[0];
705 }
706
707 if (Shingling && LineCount != 0)
708 {
709 EvenOffset ++;
710 OddOffset ++;
711
712 if (EvenOffset == DotBytes)
713 {
714 EvenOffset = 0;
715 OutputRows(header, 0);
716 }
717
718 if (OddOffset == DotBytes)
719 {
720 OddOffset = 0;
721 OutputRows(header, 1);
722 }
723 }
724 else
725 {
726 EvenOffset ++;
727
728 if (EvenOffset == DotBytes)
729 {
730 EvenOffset = 0;
731 OutputRows(header, 0);
732 }
733 }
734
735 DotBit = 128;
736 LineCount ++;
737
738 memset(CompBuffer, 0, header->cupsWidth);
739 }
740 }
741 else
742 {
743 unsigned plane; /* Current plane */
744 unsigned bytes; /* Bytes per plane */
745 unsigned xstep, ystep; /* X & Y resolutions */
746
747 /*
748 * Write a single line of bitmap data as needed...
749 */
750
751 xstep = 3600 / header->HWResolution[0];
752 ystep = 3600 / header->HWResolution[1];
753 bytes = header->cupsBytesPerLine / NumPlanes;
754
755 for (plane = 0; plane < NumPlanes; plane ++)
756 {
757 /*
758 * Skip blank data...
759 */
760
761 if (!Planes[plane][0] &&
762 memcmp(Planes[plane], Planes[plane] + 1, (size_t)bytes - 1) == 0)
763 continue;
764
765 /*
766 * Output whitespace as needed...
767 */
768
769 if (Feed > 0)
770 {
771 pwrite("\033(v\002\000", 5); /* Relative vertical position */
772 putchar((int)Feed);
773 putchar((int)(Feed >> 8));
774
775 Feed = 0;
776 }
777
778 CompressData(Planes[plane], bytes, plane, header->cupsCompression, xstep, ystep);
779 }
780
781 Feed ++;
782 }
783 }
784
785
786 /*
787 * 'OutputRows()' - Output 8, 24, or 48 rows.
788 */
789
790 void
OutputRows(const cups_page_header2_t * header,int row)791 OutputRows(
792 const cups_page_header2_t *header, /* I - Page image header */
793 int row) /* I - Row number (0 or 1) */
794 {
795 unsigned i, n, /* Looping vars */
796 dot_count, /* Number of bytes to print */
797 dot_min; /* Minimum number of bytes */
798 unsigned char *dot_ptr, /* Pointer to print data */
799 *ptr; /* Current data */
800
801
802 dot_min = DotBytes * DotColumns;
803
804 if (LineBuffers[row][0] != 0 ||
805 memcmp(LineBuffers[row], LineBuffers[row] + 1, header->cupsWidth * DotBytes - 1))
806 {
807 /*
808 * Skip leading space...
809 */
810
811 i = 0;
812 dot_count = header->cupsWidth * DotBytes;
813 dot_ptr = LineBuffers[row];
814
815 while (dot_count >= dot_min && dot_ptr[0] == 0 &&
816 memcmp(dot_ptr, dot_ptr + 1, dot_min - 1) == 0)
817 {
818 i ++;
819 dot_ptr += dot_min;
820 dot_count -= dot_min;
821 }
822
823 /*
824 * Skip trailing space...
825 */
826
827 while (dot_count >= dot_min && dot_ptr[dot_count - dot_min] == 0 &&
828 memcmp(dot_ptr + dot_count - dot_min,
829 dot_ptr + dot_count - dot_min + 1, dot_min - 1) == 0)
830 dot_count -= dot_min;
831
832 /*
833 * Position print head for printing...
834 */
835
836 if (i == 0)
837 putchar('\r');
838 else
839 {
840 putchar(0x1b);
841 putchar('$');
842 putchar((int)(i & 255));
843 putchar((int)(i >> 8));
844 }
845
846 /*
847 * Start bitmap graphics for this line...
848 */
849
850 printf("\033*"); /* Select bit image */
851 switch (header->HWResolution[0])
852 {
853 case 60 : /* 60x60/72 DPI gfx */
854 putchar(0);
855 break;
856 case 120 : /* 120x60/72 DPI gfx */
857 putchar(1);
858 break;
859 case 180 : /* 180 DPI gfx */
860 putchar(39);
861 break;
862 case 240 : /* 240x72 DPI gfx */
863 putchar(3);
864 break;
865 case 360 : /* 360x180/360 DPI gfx */
866 if (header->HWResolution[1] == 180)
867 {
868 if (Shingling && LineCount != 0)
869 putchar(40); /* 360x180 fast */
870 else
871 putchar(41); /* 360x180 slow */
872 }
873 else
874 {
875 if (Shingling && LineCount != 0)
876 putchar(72); /* 360x360 fast */
877 else
878 putchar(73); /* 360x360 slow */
879 }
880 break;
881 }
882
883 n = dot_count / DotBytes;
884 putchar((int)(n & 255));
885 putchar((int)(n / 256));
886
887 /*
888 * Write the graphics data...
889 */
890
891 if (header->HWResolution[0] == 120 ||
892 header->HWResolution[0] == 240)
893 {
894 /*
895 * Need to interleave the dots to avoid hosing the print head...
896 */
897
898 for (n = dot_count / 2, ptr = dot_ptr; n > 0; n --, ptr += 2)
899 {
900 putchar(*ptr);
901 putchar(0);
902 }
903
904 if (dot_count & 1)
905 putchar(*ptr);
906
907 /*
908 * Move the head back and print the odd bytes...
909 */
910
911 if (i == 0)
912 putchar('\r');
913 else
914 {
915 putchar(0x1b);
916 putchar('$');
917 putchar((int)(i & 255));
918 putchar((int)(i >> 8));
919 }
920
921 if (header->HWResolution[0] == 120)
922 printf("\033*\001"); /* Select bit image */
923 else
924 printf("\033*\003"); /* Select bit image */
925
926 n = (unsigned)dot_count / DotBytes;
927 putchar((int)(n & 255));
928 putchar((int)(n / 256));
929
930 for (n = dot_count / 2, ptr = dot_ptr + 1; n > 0; n --, ptr += 2)
931 {
932 putchar(0);
933 putchar(*ptr);
934 }
935
936 if (dot_count & 1)
937 putchar(0);
938 }
939 else
940 pwrite(dot_ptr, dot_count);
941 }
942
943 /*
944 * Feed the paper...
945 */
946
947 putchar('\n');
948
949 if (Shingling && row == 1)
950 {
951 if (header->HWResolution[1] == 360)
952 printf("\n\n\n\n");
953 else
954 printf("\n");
955 }
956
957 fflush(stdout);
958
959 /*
960 * Clear the buffer...
961 */
962
963 memset(LineBuffers[row], 0, header->cupsWidth * DotBytes);
964 }
965
966
967 /*
968 * 'main()' - Main entry and processing of driver.
969 */
970
971 int /* O - Exit status */
main(int argc,char * argv[])972 main(int argc, /* I - Number of command-line arguments */
973 char *argv[]) /* I - Command-line arguments */
974 {
975 int fd; /* File descriptor */
976 cups_raster_t *ras; /* Raster stream for printing */
977 cups_page_header2_t header; /* Page header from file */
978 ppd_file_t *ppd; /* PPD file */
979 int page; /* Current page */
980 unsigned y; /* Current line */
981 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
982 struct sigaction action; /* Actions for POSIX signals */
983 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
984
985
986 /*
987 * Make sure status messages are not buffered...
988 */
989
990 setbuf(stderr, NULL);
991
992 /*
993 * Check command-line...
994 */
995
996 if (argc < 6 || argc > 7)
997 {
998 /*
999 * We don't have the correct number of arguments; write an error message
1000 * and return.
1001 */
1002
1003 _cupsLangPrintFilter(stderr, "ERROR",
1004 _("%s job-id user title copies options [file]"),
1005 "rastertoepson");
1006 return (1);
1007 }
1008
1009 /*
1010 * Open the page stream...
1011 */
1012
1013 if (argc == 7)
1014 {
1015 if ((fd = open(argv[6], O_RDONLY)) == -1)
1016 {
1017 _cupsLangPrintError("ERROR", _("Unable to open raster file"));
1018 sleep(1);
1019 return (1);
1020 }
1021 }
1022 else
1023 fd = 0;
1024
1025 ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
1026
1027 /*
1028 * Register a signal handler to eject the current page if the
1029 * job is cancelled.
1030 */
1031
1032 Canceled = 0;
1033
1034 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
1035 sigset(SIGTERM, CancelJob);
1036 #elif defined(HAVE_SIGACTION)
1037 memset(&action, 0, sizeof(action));
1038
1039 sigemptyset(&action.sa_mask);
1040 action.sa_handler = CancelJob;
1041 sigaction(SIGTERM, &action, NULL);
1042 #else
1043 signal(SIGTERM, CancelJob);
1044 #endif /* HAVE_SIGSET */
1045
1046 /*
1047 * Initialize the print device...
1048 */
1049
1050 ppd = ppdOpenFile(getenv("PPD"));
1051 if (!ppd)
1052 {
1053 ppd_status_t status; /* PPD error */
1054 int linenum; /* Line number */
1055
1056 _cupsLangPrintFilter(stderr, "ERROR",
1057 _("The PPD file could not be opened."));
1058
1059 status = ppdLastError(&linenum);
1060
1061 fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum);
1062
1063 return (1);
1064 }
1065
1066 Model = ppd->model_number;
1067
1068 Setup();
1069
1070 /*
1071 * Process pages as needed...
1072 */
1073
1074 page = 0;
1075
1076 while (cupsRasterReadHeader2(ras, &header))
1077 {
1078 /*
1079 * Write a status message with the page number and number of copies.
1080 */
1081
1082 if (Canceled)
1083 break;
1084
1085 page ++;
1086
1087 fprintf(stderr, "PAGE: %d %d\n", page, header.NumCopies);
1088 _cupsLangPrintFilter(stderr, "INFO", _("Starting page %d."), page);
1089
1090 /*
1091 * Start the page...
1092 */
1093
1094 StartPage(ppd, &header);
1095
1096 /*
1097 * Loop for each line on the page...
1098 */
1099
1100 for (y = 0; y < header.cupsHeight; y ++)
1101 {
1102 /*
1103 * Let the user know how far we have progressed...
1104 */
1105
1106 if (Canceled)
1107 break;
1108
1109 if ((y & 127) == 0)
1110 {
1111 _cupsLangPrintFilter(stderr, "INFO",
1112 _("Printing page %d, %u%% complete."),
1113 page, 100 * y / header.cupsHeight);
1114 fprintf(stderr, "ATTR: job-media-progress=%u\n",
1115 100 * y / header.cupsHeight);
1116 }
1117
1118 /*
1119 * Read a line of graphics...
1120 */
1121
1122 if (cupsRasterReadPixels(ras, Planes[0], header.cupsBytesPerLine) < 1)
1123 break;
1124
1125 /*
1126 * Write it to the printer...
1127 */
1128
1129 OutputLine(&header);
1130 }
1131
1132 /*
1133 * Eject the page...
1134 */
1135
1136 _cupsLangPrintFilter(stderr, "INFO", _("Finished page %d."), page);
1137
1138 EndPage(&header);
1139
1140 if (Canceled)
1141 break;
1142 }
1143
1144 /*
1145 * Shutdown the printer...
1146 */
1147
1148 Shutdown();
1149
1150 ppdClose(ppd);
1151
1152 /*
1153 * Close the raster stream...
1154 */
1155
1156 cupsRasterClose(ras);
1157 if (fd != 0)
1158 close(fd);
1159
1160 /*
1161 * If no pages were printed, send an error message...
1162 */
1163
1164 if (page == 0)
1165 {
1166 _cupsLangPrintFilter(stderr, "ERROR", _("No pages were found."));
1167 return (1);
1168 }
1169 else
1170 return (0);
1171 }
1172