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