4 * EPSON ESC/P and ESC/P2 filter for CUPS.
6 * Copyright 2007-2012 by Apple Inc.
7 * Copyright 1993-2007 by Easy Software Products.
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/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * Setup() - Prepare the printer for printing.
20 * StartPage() - Start a page of graphics.
21 * EndPage() - Finish a page of graphics.
22 * Shutdown() - Shutdown the printer.
23 * CompressData() - Compress a line of graphics.
24 * OutputLine() - Output a line of graphics.
25 * main() - Main entry and processing of driver.
29 * Include necessary headers...
32 #include <cups/cups.h>
34 #include <cups/string-private.h>
35 #include <cups/language-private.h>
36 #include <cups/raster.h>
50 #define EPSON_ICOLOR 4
51 #define EPSON_IPHOTO 5
58 #define pwrite(s,n) fwrite((s), 1, (n), stdout)
65 unsigned char *Planes
[6], /* Output buffers */
66 *CompBuffer
, /* Compression buffer */
67 *LineBuffers
[2]; /* Line bitmap buffers */
68 int Model
, /* Model number */
69 NumPlanes
, /* Number of color planes */
70 Feed
, /* Number of lines to skip */
71 EjectPage
; /* Eject the page when done? */
72 int DotBit
, /* Bit in buffers */
73 DotBytes
, /* # bytes in a dot column */
74 DotColumns
, /* # columns in 1/60 inch */
75 LineCount
, /* # of lines processed */
76 EvenOffset
, /* Offset into 'even' buffers */
77 OddOffset
, /* Offset into 'odd' buffers */
78 Shingling
, /* Shingle output? */
79 Canceled
; /* Has the current job been canceled? */
87 void StartPage(const ppd_file_t
*ppd
, const cups_page_header2_t
*header
);
88 void EndPage(const cups_page_header2_t
*header
);
91 void CancelJob(int sig
);
92 void CompressData(const unsigned char *line
, int length
, int plane
,
93 int type
, int xstep
, int ystep
);
94 void OutputLine(const cups_page_header2_t
*header
);
95 void OutputRows(const cups_page_header2_t
*header
, int row
);
99 * 'Setup()' - Prepare the printer for printing.
105 const char *device_uri
; /* The device for the printer... */
109 * EPSON USB printers need an additional command issued at the
110 * beginning of each job to exit from "packet" mode...
113 if ((device_uri
= getenv("DEVICE_URI")) != NULL
&&
114 strncmp(device_uri
, "usb:", 4) == 0 && Model
>= EPSON_ICOLOR
)
115 pwrite("\000\000\000\033\001@EJL 1284.4\n@EJL \n\033@", 29);
120 * 'StartPage()' - Start a page of graphics.
125 const ppd_file_t
*ppd
, /* I - PPD file */
126 const cups_page_header2_t
*header
) /* I - Page header */
128 int n
, t
; /* Numbers */
129 int plane
; /* Looping var */
133 * Send a reset sequence.
136 if (ppd
&& ppd
->nickname
&& strstr(ppd
->nickname
, "OKIDATA") != NULL
)
137 printf("\033{A"); /* Set EPSON emulation mode */
142 * See which type of printer we are using...
149 printf("\033P\022"); /* Set 10 CPI */
151 if (header
->HWResolution
[0] == 360 || header
->HWResolution
[0] == 240)
153 printf("\033x1"); /* LQ printing */
154 printf("\033U1"); /* Unidirectional */
158 printf("\033x0"); /* Draft printing */
159 printf("\033U0"); /* Bidirectional */
162 printf("\033l%c\033Q%c", 0, /* Side margins */
163 (int)(10.0 * header
->PageSize
[0] / 72.0 + 0.5));
164 printf("\033\062\033C%c", /* Page length in 1/6th inches */
165 (int)(header
->PageSize
[1] / 12.0 + 0.5));
166 printf("\033N%c", 0); /* Bottom margin */
167 printf("\033O"); /* No perforation skip */
170 * Setup various buffer limits...
173 DotBytes
= header
->cupsRowCount
/ 8;
174 DotColumns
= header
->HWResolution
[0] / 60;
177 if (Model
== EPSON_9PIN
)
178 printf("\033\063\030"); /* Set line feed */
180 switch (header
->HWResolution
[0])
185 printf("\033\063\030"); /* Set line feed */
192 if (header
->HWResolution
[1] == 180)
193 printf("\033\063\010");/* Set line feed */
195 printf("\033+\010"); /* Set line feed */
202 * Set graphics mode...
205 pwrite("\033(G\001\000\001", 6); /* Graphics mode */
208 * Set the media size...
211 if (Model
< EPSON_ICOLOR
)
213 pwrite("\033(U\001\000", 5); /* Resolution/units */
214 putchar(3600 / header
->HWResolution
[1]);
218 pwrite("\033(U\005\000", 5);
219 putchar(1440 / header
->HWResolution
[1]);
220 putchar(1440 / header
->HWResolution
[1]);
221 putchar(1440 / header
->HWResolution
[0]);
222 putchar(0xa0); /* n/1440ths... */
226 n
= header
->PageSize
[1] * header
->HWResolution
[1] / 72.0;
228 pwrite("\033(C\002\000", 5); /* Page length */
233 t
= (ppd
->sizes
[1].length
- ppd
->sizes
[1].top
) *
234 header
->HWResolution
[1] / 72.0;
238 pwrite("\033(c\004\000", 5); /* Top & bottom margins */
244 if (header
->HWResolution
[1] == 720)
246 pwrite("\033(i\001\000\001", 6); /* Microweave */
247 pwrite("\033(e\002\000\000\001", 7); /* Small dots */
250 pwrite("\033(V\002\000\000\000", 7); /* Set absolute position 0 */
262 if (header
->cupsColorSpace
== CUPS_CSPACE_CMY
)
264 else if (header
->cupsColorSpace
== CUPS_CSPACE_KCMY
)
266 else if (header
->cupsColorSpace
== CUPS_CSPACE_KCMYcm
)
271 Feed
= 0; /* No blank lines yet */
274 * Allocate memory for a line/row of graphics...
277 if ((Planes
[0] = malloc(header
->cupsBytesPerLine
)) == NULL
)
279 fputs("ERROR: Unable to allocate memory\n", stderr
);
283 for (plane
= 1; plane
< NumPlanes
; plane
++)
284 Planes
[plane
] = Planes
[0] + plane
* header
->cupsBytesPerLine
/ NumPlanes
;
286 if (header
->cupsCompression
|| DotBytes
)
288 if ((CompBuffer
= calloc(2, header
->cupsWidth
)) == NULL
)
290 fputs("ERROR: Unable to allocate memory\n", stderr
);
299 if ((LineBuffers
[0] = calloc(DotBytes
,
300 header
->cupsWidth
* (Shingling
+ 1))) == NULL
)
302 fputs("ERROR: Unable to allocate memory\n", stderr
);
306 LineBuffers
[1] = LineBuffers
[0] + DotBytes
* header
->cupsWidth
;
316 * 'EndPage()' - Finish a page of graphics.
321 const cups_page_header2_t
*header
) /* I - Page header */
323 if (DotBytes
&& header
)
326 * Flush remaining graphics as needed...
331 if (DotBit
< 128 || EvenOffset
)
332 OutputRows(header
, 0);
334 else if (OddOffset
> EvenOffset
)
336 OutputRows(header
, 1);
337 OutputRows(header
, 0);
341 OutputRows(header
, 0);
342 OutputRows(header
, 1);
347 * Eject the current page...
350 putchar(12); /* Form feed */
363 free(LineBuffers
[0]);
368 * 'Shutdown()' - Shutdown the printer.
375 * Send a reset sequence.
383 * 'CancelJob()' - Cancel the current job...
387 CancelJob(int sig
) /* I - Signal */
396 * 'CompressData()' - Compress a line of graphics.
400 CompressData(const unsigned char *line
, /* I - Data to compress */
401 int length
,/* I - Number of bytes */
402 int plane
, /* I - Color plane */
403 int type
, /* I - Type of compression */
404 int xstep
, /* I - X resolution */
405 int ystep
) /* I - Y resolution */
407 const unsigned char *line_ptr
, /* Current byte pointer */
408 *line_end
, /* End-of-line byte pointer */
409 *start
; /* Start of compression sequence */
410 unsigned char *comp_ptr
, /* Pointer into compression buffer */
411 temp
; /* Current byte */
412 int count
; /* Count of bytes for output */
413 static int ctable
[6] = { 0, 2, 1, 4, 18, 17 };
414 /* KCMYcm color values */
422 line_end
= line
+ length
;
425 * Do depletion for 720 DPI printing...
430 for (comp_ptr
= (unsigned char *)line
; comp_ptr
< line_end
;)
433 * Grab the current byte...
439 * Check adjacent bits...
442 if ((temp
& 0xc0) == 0xc0)
444 if ((temp
& 0x60) == 0x60)
446 if ((temp
& 0x30) == 0x30)
448 if ((temp
& 0x18) == 0x18)
450 if ((temp
& 0x0c) == 0x0c)
452 if ((temp
& 0x06) == 0x06)
454 if ((temp
& 0x03) == 0x03)
460 * Check the last bit in the current byte and the first bit in the
464 if ((temp
& 0x01) && comp_ptr
< line_end
&& *comp_ptr
& 0x80)
473 * Do no compression...
479 * Do TIFF pack-bits encoding...
482 comp_ptr
= CompBuffer
;
484 while (line_ptr
< line_end
)
486 if ((line_ptr
+ 1) >= line_end
)
489 * Single byte on the end...
493 *comp_ptr
++ = *line_ptr
++;
495 else if (line_ptr
[0] == line_ptr
[1])
498 * Repeated sequence...
504 while (line_ptr
< (line_end
- 1) &&
505 line_ptr
[0] == line_ptr
[1] &&
512 *comp_ptr
++ = 257 - count
;
513 *comp_ptr
++ = *line_ptr
++;
518 * Non-repeated sequence...
525 while (line_ptr
< (line_end
- 1) &&
526 line_ptr
[0] != line_ptr
[1] &&
533 *comp_ptr
++ = count
- 1;
535 memcpy(comp_ptr
, start
, count
);
540 line_ptr
= CompBuffer
;
545 putchar(0x0d); /* Move print head to left margin */
547 if (Model
< EPSON_ICOLOR
)
550 * Do graphics the "old" way...
560 printf("\033(r%c%c%c%c", 2, 0, 1, ctable
[plane
] & 15);
561 /* Set extended color */
562 else if (NumPlanes
== 3)
563 printf("\033r%c", ctable
[plane
+ 1]);
566 printf("\033r%c", ctable
[plane
]); /* Set color */
570 * Send a raster plane...
574 printf("\033."); /* Raster graphics */
580 putchar(length
>> 8);
585 * Do graphics the "new" way...
589 putchar(ctable
[plane
]);
592 putchar(length
& 255);
593 putchar(length
>> 8);
598 pwrite(line_ptr
, line_end
- line_ptr
);
604 * 'OutputLine()' - Output a line of graphics.
609 const cups_page_header2_t
*header
) /* I - Page header */
611 if (header
->cupsRowCount
)
614 unsigned char *tempptr
,
619 const unsigned char *pixel
;
624 * Collect bitmap data in the line buffers and write after each buffer.
627 for (x
= header
->cupsWidth
, bit
= 128, pixel
= Planes
[0],
649 * Copy the holding buffer to the output buffer, shingling as necessary...
652 if (Shingling
&& LineCount
!= 0)
655 * Shingle the output...
660 evenptr
= LineBuffers
[1] + OddOffset
;
661 oddptr
= LineBuffers
[0] + EvenOffset
+ DotBytes
;
665 evenptr
= LineBuffers
[0] + EvenOffset
;
666 oddptr
= LineBuffers
[1] + OddOffset
+ DotBytes
;
669 for (width
= header
->cupsWidth
, tempptr
= CompBuffer
;
671 width
-= 2, tempptr
+= 2, oddptr
+= DotBytes
* 2,
672 evenptr
+= DotBytes
* 2)
674 evenptr
[0] = tempptr
[0];
675 oddptr
[0] = tempptr
[1];
681 * Don't shingle the output...
684 for (width
= header
->cupsWidth
, tempptr
= CompBuffer
,
685 evenptr
= LineBuffers
[0] + EvenOffset
;
687 width
--, tempptr
++, evenptr
+= DotBytes
)
688 *evenptr
= tempptr
[0];
691 if (Shingling
&& LineCount
!= 0)
696 if (EvenOffset
== DotBytes
)
699 OutputRows(header
, 0);
702 if (OddOffset
== DotBytes
)
705 OutputRows(header
, 1);
712 if (EvenOffset
== DotBytes
)
715 OutputRows(header
, 0);
722 memset(CompBuffer
, 0, header
->cupsWidth
);
727 int plane
; /* Current plane */
728 int bytes
; /* Bytes per plane */
729 int xstep
, ystep
; /* X & Y resolutions */
733 * Write a single line of bitmap data as needed...
736 xstep
= 3600 / header
->HWResolution
[0];
737 ystep
= 3600 / header
->HWResolution
[1];
738 bytes
= header
->cupsBytesPerLine
/ NumPlanes
;
740 for (plane
= 0; plane
< NumPlanes
; plane
++)
746 if (!Planes
[plane
][0] &&
747 memcmp(Planes
[plane
], Planes
[plane
] + 1, bytes
- 1) == 0)
751 * Output whitespace as needed...
756 pwrite("\033(v\002\000", 5); /* Relative vertical position */
763 CompressData(Planes
[plane
], bytes
, plane
, header
->cupsCompression
, xstep
,
773 * 'OutputRows()' - Output 8, 24, or 48 rows.
778 const cups_page_header2_t
*header
, /* I - Page image header */
779 int row
) /* I - Row number (0 or 1) */
781 unsigned i
, n
; /* Looping vars */
782 int dot_count
, /* Number of bytes to print */
783 dot_min
; /* Minimum number of bytes */
784 unsigned char *dot_ptr
, /* Pointer to print data */
785 *ptr
; /* Current data */
788 dot_min
= DotBytes
* DotColumns
;
790 if (LineBuffers
[row
][0] != 0 ||
791 memcmp(LineBuffers
[row
], LineBuffers
[row
] + 1,
792 header
->cupsWidth
* DotBytes
- 1))
795 * Skip leading space...
799 dot_count
= header
->cupsWidth
* DotBytes
;
800 dot_ptr
= LineBuffers
[row
];
802 while (dot_count
>= dot_min
&& dot_ptr
[0] == 0 &&
803 memcmp(dot_ptr
, dot_ptr
+ 1, dot_min
- 1) == 0)
807 dot_count
-= dot_min
;
811 * Skip trailing space...
814 while (dot_count
>= dot_min
&& dot_ptr
[dot_count
- dot_min
] == 0 &&
815 memcmp(dot_ptr
+ dot_count
- dot_min
,
816 dot_ptr
+ dot_count
- dot_min
+ 1, dot_min
- 1) == 0)
817 dot_count
-= dot_min
;
820 * Position print head for printing...
834 * Start bitmap graphics for this line...
837 printf("\033*"); /* Select bit image */
838 switch (header
->HWResolution
[0])
840 case 60 : /* 60x60/72 DPI gfx */
843 case 120 : /* 120x60/72 DPI gfx */
846 case 180 : /* 180 DPI gfx */
849 case 240 : /* 240x72 DPI gfx */
852 case 360 : /* 360x180/360 DPI gfx */
853 if (header
->HWResolution
[1] == 180)
855 if (Shingling
&& LineCount
!= 0)
856 putchar(40); /* 360x180 fast */
858 putchar(41); /* 360x180 slow */
862 if (Shingling
&& LineCount
!= 0)
863 putchar(72); /* 360x360 fast */
865 putchar(73); /* 360x360 slow */
870 n
= (unsigned)dot_count
/ DotBytes
;
875 * Write the graphics data...
878 if (header
->HWResolution
[0] == 120 ||
879 header
->HWResolution
[0] == 240)
882 * Need to interleave the dots to avoid hosing the print head...
885 for (n
= dot_count
/ 2, ptr
= dot_ptr
; n
> 0; n
--, ptr
+= 2)
892 * Move the head back and print the odd bytes...
905 if (header
->HWResolution
[0] == 120)
906 printf("\033*\001"); /* Select bit image */
908 printf("\033*\003"); /* Select bit image */
910 n
= (unsigned)dot_count
/ DotBytes
;
914 for (n
= dot_count
/ 2, ptr
= dot_ptr
+ 1; n
> 0; n
--, ptr
+= 2)
921 pwrite(dot_ptr
, dot_count
);
930 if (Shingling
&& row
== 1)
932 if (header
->HWResolution
[1] == 360)
941 * Clear the buffer...
944 memset(LineBuffers
[row
], 0, header
->cupsWidth
* DotBytes
);
949 * 'main()' - Main entry and processing of driver.
952 int /* O - Exit status */
953 main(int argc
, /* I - Number of command-line arguments */
954 char *argv
[]) /* I - Command-line arguments */
956 int fd
; /* File descriptor */
957 cups_raster_t
*ras
; /* Raster stream for printing */
958 cups_page_header2_t header
; /* Page header from file */
959 ppd_file_t
*ppd
; /* PPD file */
960 int page
; /* Current page */
961 int y
; /* Current line */
962 #if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
963 struct sigaction action
; /* Actions for POSIX signals */
964 #endif /* HAVE_SIGACTION && !HAVE_SIGSET */
968 * Make sure status messages are not buffered...
971 setbuf(stderr
, NULL
);
974 * Check command-line...
977 if (argc
< 6 || argc
> 7)
980 * We don't have the correct number of arguments; write an error message
984 _cupsLangPrintFilter(stderr
, "ERROR",
985 _("%s job-id user title copies options [file]"),
991 * Open the page stream...
996 if ((fd
= open(argv
[6], O_RDONLY
)) == -1)
998 _cupsLangPrintError("ERROR", _("Unable to open raster file"));
1006 ras
= cupsRasterOpen(fd
, CUPS_RASTER_READ
);
1009 * Register a signal handler to eject the current page if the
1015 #ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
1016 sigset(SIGTERM
, CancelJob
);
1017 #elif defined(HAVE_SIGACTION)
1018 memset(&action
, 0, sizeof(action
));
1020 sigemptyset(&action
.sa_mask
);
1021 action
.sa_handler
= CancelJob
;
1022 sigaction(SIGTERM
, &action
, NULL
);
1024 signal(SIGTERM
, CancelJob
);
1025 #endif /* HAVE_SIGSET */
1028 * Initialize the print device...
1031 ppd
= ppdOpenFile(getenv("PPD"));
1034 ppd_status_t status
; /* PPD error */
1035 int linenum
; /* Line number */
1037 _cupsLangPrintFilter(stderr
, "ERROR",
1038 _("The PPD file could not be opened."));
1040 status
= ppdLastError(&linenum
);
1042 fprintf(stderr
, "DEBUG: %s on line %d.\n", ppdErrorString(status
), linenum
);
1047 Model
= ppd
->model_number
;
1052 * Process pages as needed...
1057 while (cupsRasterReadHeader2(ras
, &header
))
1060 * Write a status message with the page number and number of copies.
1068 fprintf(stderr
, "PAGE: %d %d\n", page
, header
.NumCopies
);
1069 _cupsLangPrintFilter(stderr
, "INFO", _("Starting page %d."), page
);
1075 StartPage(ppd
, &header
);
1078 * Loop for each line on the page...
1081 for (y
= 0; y
< header
.cupsHeight
; y
++)
1084 * Let the user know how far we have progressed...
1092 _cupsLangPrintFilter(stderr
, "INFO",
1093 _("Printing page %d, %d%% complete."),
1094 page
, 100 * y
/ header
.cupsHeight
);
1095 fprintf(stderr
, "ATTR: job-media-progress=%d\n",
1096 100 * y
/ header
.cupsHeight
);
1100 * Read a line of graphics...
1103 if (cupsRasterReadPixels(ras
, Planes
[0], header
.cupsBytesPerLine
) < 1)
1107 * Write it to the printer...
1110 OutputLine(&header
);
1117 _cupsLangPrintFilter(stderr
, "INFO", _("Finished page %d."), page
);
1126 * Shutdown the printer...
1134 * Close the raster stream...
1137 cupsRasterClose(ras
);
1142 * If no pages were printed, send an error message...
1147 _cupsLangPrintFilter(stderr
, "ERROR", _("No pages were found."));