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