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