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