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