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