]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/rastertolabel.c
Load cups into easysw/current.
[thirdparty/cups.git] / filter / rastertolabel.c
CommitLineData
ef416fc2 1/*
c0e1af83 2 * "$Id: rastertolabel.c 6420 2007-03-30 20:00:59Z mike $"
ef416fc2 3 *
4 * Label printer filter for the Common UNIX Printing System (CUPS).
5 *
b86bc4cf 6 * Copyright 2001-2007 by Easy Software Products.
ef416fc2 7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Easy Software Products and are protected by Federal
10 * copyright law. Distribution and use rights are outlined in the file
11 * "LICENSE.txt" which should have been included with this file. If this
12 * file is missing or damaged please contact Easy Software Products
13 * at:
14 *
15 * Attn: CUPS Licensing Information
16 * Easy Software Products
17 * 44141 Airport View Drive, Suite 204
18 * Hollywood, Maryland 20636 USA
19 *
20 * Voice: (301) 373-9600
21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
24 * This file is subject to the Apple OS-Developed Software exception.
25 *
26 * Contents:
27 *
28 * Setup() - Prepare the printer for printing.
29 * StartPage() - Start a page of graphics.
30 * EndPage() - Finish a page of graphics.
31 * CancelJob() - Cancel the current job...
32 * OutputLine() - Output a line of graphics.
f7deaa1a 33 * PCLCompress() - Output a PCL (mode 3) compressed line.
ef416fc2 34 * ZPLCompress() - Output a run-length compression sequence.
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/string.h>
c0e1af83 44#include <cups/i18n.h>
ef416fc2 45#include "raster.h"
46#include <stdlib.h>
47#include <unistd.h>
48#include <fcntl.h>
49#include <signal.h>
50
51
52/*
f7deaa1a 53 * This driver filter currently supports Dymo, Intellitech, and Zebra
54 * label printers.
ef416fc2 55 *
56 * The Dymo portion of the driver has been tested with the 300, 330,
f7deaa1a 57 * and 330 Turbo label printers; it may also work with other models.
ef416fc2 58 * The Dymo printers support printing at 136, 203, and 300 DPI.
59 *
f7deaa1a 60 * The Intellitech portion of the driver has been tested with the
61 * Intellibar 408, 412, and 808 and supports their PCL variant.
62 *
63 * The Zebra portion of the driver has been tested with the LP-2844,
64 * LP-2844Z, QL-320, and QL-420 label printers; it may also work with
65 * other models. The driver supports EPL line mode, EPL page mode,
66 * ZPL, and CPCL as defined in Zebra's on-line developer documentation.
ef416fc2 67 */
68
69/*
70 * Model number constants...
71 */
72
73#define DYMO_3x0 0 /* Dymo Labelwriter 300/330/330 Turbo */
74
75#define ZEBRA_EPL_LINE 0x10 /* Zebra EPL line mode printers */
76#define ZEBRA_EPL_PAGE 0x11 /* Zebra EPL page mode printers */
77#define ZEBRA_ZPL 0x12 /* Zebra ZPL-based printers */
78#define ZEBRA_CPCL 0x13 /* Zebra CPCL-based printers */
79
f7deaa1a 80#define INTELLITECH_PCL 0x20 /* Intellitech PCL-based printers */
81
ef416fc2 82
83/*
84 * Globals...
85 */
86
87unsigned char *Buffer; /* Output buffer */
b86bc4cf 88unsigned char *CompBuffer; /* Compression buffer */
ef416fc2 89unsigned char *LastBuffer; /* Last buffer */
90int LastSet; /* Number of repeat characters */
91int ModelNumber, /* cupsModelNumber attribute */
92 Page, /* Current page */
93 Feed, /* Number of lines to skip */
94 Canceled; /* Non-zero if job is canceled */
95
96
97/*
98 * Prototypes...
99 */
100
101void Setup(ppd_file_t *ppd);
102void StartPage(ppd_file_t *ppd, cups_page_header_t *header);
103void EndPage(ppd_file_t *ppd, cups_page_header_t *header);
104void CancelJob(int sig);
105void OutputLine(ppd_file_t *ppd, cups_page_header_t *header, int y);
f7deaa1a 106void PCLCompress(unsigned char *line, int length);
ef416fc2 107void ZPLCompress(char repeat_char, int repeat_count);
108
109
110/*
111 * 'Setup()' - Prepare the printer for printing.
112 */
113
114void
115Setup(ppd_file_t *ppd) /* I - PPD file */
116{
117 int i; /* Looping var */
118
119
120 /*
121 * Get the model number from the PPD file...
122 */
123
124 if (ppd)
125 ModelNumber = ppd->model_number;
126
127 /*
128 * Initialize based on the model number...
129 */
130
131 switch (ModelNumber)
132 {
133 case DYMO_3x0 :
134 /*
135 * Clear any remaining data...
136 */
137
138 for (i = 0; i < 100; i ++)
139 putchar(0x1b);
140
141 /*
142 * Reset the printer...
143 */
144
145 fputs("\033@", stdout);
146 break;
147
148 case ZEBRA_EPL_LINE :
149 break;
150
151 case ZEBRA_EPL_PAGE :
152 break;
153
154 case ZEBRA_ZPL :
155 break;
156
157 case ZEBRA_CPCL :
158 break;
f7deaa1a 159
160 case INTELLITECH_PCL :
161 /*
162 * Send a PCL reset sequence.
163 */
164
165 putchar(0x1b);
166 putchar('E');
167 break;
ef416fc2 168 }
169}
170
171
172/*
173 * 'StartPage()' - Start a page of graphics.
174 */
175
176void
e1d6a774 177StartPage(ppd_file_t *ppd, /* I - PPD file */
ef416fc2 178 cups_page_header_t *header) /* I - Page header */
179{
180 ppd_choice_t *choice; /* Marked choice */
181 int length; /* Actual label length */
182#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
183 struct sigaction action; /* Actions for POSIX signals */
184#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
185
186
e1d6a774 187 /*
188 * Show page device dictionary...
189 */
190
191 fprintf(stderr, "DEBUG: StartPage...\n");
192 fprintf(stderr, "DEBUG: MediaClass = \"%s\"\n", header->MediaClass);
193 fprintf(stderr, "DEBUG: MediaColor = \"%s\"\n", header->MediaColor);
194 fprintf(stderr, "DEBUG: MediaType = \"%s\"\n", header->MediaType);
195 fprintf(stderr, "DEBUG: OutputType = \"%s\"\n", header->OutputType);
196
197 fprintf(stderr, "DEBUG: AdvanceDistance = %d\n", header->AdvanceDistance);
198 fprintf(stderr, "DEBUG: AdvanceMedia = %d\n", header->AdvanceMedia);
199 fprintf(stderr, "DEBUG: Collate = %d\n", header->Collate);
200 fprintf(stderr, "DEBUG: CutMedia = %d\n", header->CutMedia);
201 fprintf(stderr, "DEBUG: Duplex = %d\n", header->Duplex);
202 fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0],
203 header->HWResolution[1]);
204 fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n",
205 header->ImagingBoundingBox[0], header->ImagingBoundingBox[1],
206 header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]);
207 fprintf(stderr, "DEBUG: InsertSheet = %d\n", header->InsertSheet);
208 fprintf(stderr, "DEBUG: Jog = %d\n", header->Jog);
209 fprintf(stderr, "DEBUG: LeadingEdge = %d\n", header->LeadingEdge);
210 fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0],
211 header->Margins[1]);
212 fprintf(stderr, "DEBUG: ManualFeed = %d\n", header->ManualFeed);
213 fprintf(stderr, "DEBUG: MediaPosition = %d\n", header->MediaPosition);
214 fprintf(stderr, "DEBUG: MediaWeight = %d\n", header->MediaWeight);
215 fprintf(stderr, "DEBUG: MirrorPrint = %d\n", header->MirrorPrint);
216 fprintf(stderr, "DEBUG: NegativePrint = %d\n", header->NegativePrint);
217 fprintf(stderr, "DEBUG: NumCopies = %d\n", header->NumCopies);
218 fprintf(stderr, "DEBUG: Orientation = %d\n", header->Orientation);
219 fprintf(stderr, "DEBUG: OutputFaceUp = %d\n", header->OutputFaceUp);
220 fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0],
221 header->PageSize[1]);
222 fprintf(stderr, "DEBUG: Separations = %d\n", header->Separations);
223 fprintf(stderr, "DEBUG: TraySwitch = %d\n", header->TraySwitch);
224 fprintf(stderr, "DEBUG: Tumble = %d\n", header->Tumble);
225 fprintf(stderr, "DEBUG: cupsWidth = %d\n", header->cupsWidth);
226 fprintf(stderr, "DEBUG: cupsHeight = %d\n", header->cupsHeight);
227 fprintf(stderr, "DEBUG: cupsMediaType = %d\n", header->cupsMediaType);
228 fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header->cupsBitsPerColor);
229 fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header->cupsBitsPerPixel);
230 fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header->cupsBytesPerLine);
231 fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header->cupsColorOrder);
232 fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace);
233 fprintf(stderr, "DEBUG: cupsCompression = %d\n", header->cupsCompression);
f7deaa1a 234 fprintf(stderr, "DEBUG: cupsRowCount = %d\n", header->cupsRowCount);
235 fprintf(stderr, "DEBUG: cupsRowFeed = %d\n", header->cupsRowFeed);
236 fprintf(stderr, "DEBUG: cupsRowStep = %d\n", header->cupsRowStep);
e1d6a774 237
ef416fc2 238 /*
239 * Register a signal handler to eject the current page if the
240 * job is canceled.
241 */
242
243#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
244 sigset(SIGTERM, CancelJob);
245#elif defined(HAVE_SIGACTION)
246 memset(&action, 0, sizeof(action));
247
248 sigemptyset(&action.sa_mask);
249 action.sa_handler = CancelJob;
250 sigaction(SIGTERM, &action, NULL);
251#else
252 signal(SIGTERM, CancelJob);
253#endif /* HAVE_SIGSET */
254
255 switch (ModelNumber)
256 {
257 case DYMO_3x0 :
258 /*
259 * Setup printer/job attributes...
260 */
261
262 length = header->PageSize[1] * header->HWResolution[1] / 72;
263
264 printf("\033L%c%c", length >> 8, length);
265 printf("\033D%c", header->cupsBytesPerLine);
266
267 printf("\033%c", header->cupsCompression + 'c'); /* Darkness */
268 break;
269
270 case ZEBRA_EPL_LINE :
271 /*
272 * Set print rate...
273 */
274
275 if ((choice = ppdFindMarkedChoice(ppd, "zePrintRate")) != NULL &&
276 strcmp(choice->choice, "Default"))
277 printf("\033S%.0f", atof(choice->choice) * 2.0 - 2.0);
278
279 /*
280 * Set darkness...
281 */
282
283 if (header->cupsCompression > 0 && header->cupsCompression <= 100)
284 printf("\033D%d", 7 * header->cupsCompression / 100);
285
286 /*
287 * Set left margin to 0...
288 */
289
290 fputs("\033M01", stdout);
291
292 /*
293 * Start buffered output...
294 */
295
296 fputs("\033B", stdout);
297 break;
298
299 case ZEBRA_EPL_PAGE :
300 /*
301 * Start a new label...
302 */
303
304 puts("");
305 puts("N");
306
307 /*
308 * Set hardware options...
309 */
310
311 if (!strcmp(header->MediaType, "Direct"))
312 puts("OD");
313
314 /*
315 * Set print rate...
316 */
317
318 if ((choice = ppdFindMarkedChoice(ppd, "zePrintRate")) != NULL &&
319 strcmp(choice->choice, "Default"))
320 {
321 float val = atof(choice->choice);
322
323 if (val >= 3.0)
324 printf("S%.0f\n", val);
325 else
326 printf("S%.0f\n", val * 2.0 - 2.0);
327 }
328
329 /*
330 * Set darkness...
331 */
332
333 if (header->cupsCompression > 0 && header->cupsCompression <= 100)
334 printf("D%d\n", 15 * header->cupsCompression / 100);
335
336 /*
337 * Set label size...
338 */
339
f42414bf 340 printf("q%d\n", (header->cupsWidth + 7) & ~7);
ef416fc2 341 break;
342
343 case ZEBRA_ZPL :
344 /*
345 * Set darkness...
346 */
347
348 if (header->cupsCompression > 0 && header->cupsCompression <= 100)
349 printf("~SD%02d\n", 30 * header->cupsCompression / 100);
350
351 /*
352 * Start bitmap graphics...
353 */
354
355 printf("~DGR:CUPS.GRF,%d,%d,\n",
356 header->cupsHeight * header->cupsBytesPerLine,
357 header->cupsBytesPerLine);
358
359 /*
360 * Allocate compression buffers...
361 */
362
363 CompBuffer = malloc(2 * header->cupsBytesPerLine + 1);
364 LastBuffer = malloc(header->cupsBytesPerLine);
365 LastSet = 0;
366 break;
367
368 case ZEBRA_CPCL :
369 /*
370 * Start label...
371 */
372
373 printf("! 0 %u %u %u %u\r\n", header->HWResolution[0],
374 header->HWResolution[1], header->cupsHeight,
375 header->NumCopies);
8ca02f3c 376 printf("PAGE-WIDTH %d\r\n", header->cupsWidth);
377 printf("PAGE-HEIGHT %d\r\n", header->cupsWidth);
ef416fc2 378 break;
f7deaa1a 379
380 case INTELLITECH_PCL :
381 /*
382 * Set the media size...
383 */
384
385 printf("\033&l6D\033&k12H"); /* Set 6 LPI, 10 CPI */
386 printf("\033&l0O"); /* Set portrait orientation */
387
388 switch (header->PageSize[1])
389 {
390 case 540 : /* Monarch Envelope */
391 printf("\033&l80A"); /* Set page size */
392 break;
393
394 case 624 : /* DL Envelope */
395 printf("\033&l90A"); /* Set page size */
396 break;
397
398 case 649 : /* C5 Envelope */
399 printf("\033&l91A"); /* Set page size */
400 break;
401
402 case 684 : /* COM-10 Envelope */
403 printf("\033&l81A"); /* Set page size */
404 break;
405
406 case 756 : /* Executive */
407 printf("\033&l1A"); /* Set page size */
408 break;
409
410 case 792 : /* Letter */
411 printf("\033&l2A"); /* Set page size */
412 break;
413
414 case 842 : /* A4 */
415 printf("\033&l26A"); /* Set page size */
416 break;
417
418 case 1008 : /* Legal */
419 printf("\033&l3A"); /* Set page size */
420 break;
421
422 default : /* Custom size */
423 printf("\033!f%dZ", header->PageSize[1] * 300 / 72);
424 break;
425 }
426
427 printf("\033&l%dP", /* Set page length */
428 header->PageSize[1] / 12);
429 printf("\033&l0E"); /* Set top margin to 0 */
430 printf("\033&l%dX", header->NumCopies);
431 /* Set number copies */
432 printf("\033&l0L"); /* Turn off perforation skip */
433
434 /*
435 * Print settings...
436 */
437
438 if (Page == 1)
439 {
440 if (header->cupsRowFeed) /* inPrintRate */
441 printf("\033!p%dS", header->cupsRowFeed);
442
443 if (header->cupsCompression != ~0)
444 /* inPrintDensity */
445 printf("\033&d%dA", 30 * header->cupsCompression / 100 - 15);
446
447 if ((choice = ppdFindMarkedChoice(ppd, "inPrintMode")) != NULL)
448 {
449 if (!strcmp(choice->choice, "Standard"))
450 fputs("\033!p0M", stdout);
451 else if (!strcmp(choice->choice, "Tear"))
452 {
453 fputs("\033!p1M", stdout);
454
455 if (header->cupsRowCount) /* inTearInterval */
456 printf("\033!n%dT", header->cupsRowCount);
457 }
458 else
459 {
460 fputs("\033!p2M", stdout);
461
462 if (header->cupsRowStep) /* inCutInterval */
463 printf("\033!n%dC", header->cupsRowStep);
464 }
465 }
466 }
467
468 /*
469 * Setup graphics...
470 */
471
472 printf("\033*t%dR", header->HWResolution[0]);
473 /* Set resolution */
474
475 printf("\033*r%dS", header->cupsWidth);
476 /* Set width */
477 printf("\033*r%dT", header->cupsHeight);
478 /* Set height */
479
480 printf("\033&a0H"); /* Set horizontal position */
481 printf("\033&a0V"); /* Set vertical position */
482 printf("\033*r1A"); /* Start graphics */
483 printf("\033*b3M"); /* Set compression */
484
485 /*
486 * Allocate compression buffers...
487 */
488
489 CompBuffer = malloc(2 * header->cupsBytesPerLine + 1);
490 LastBuffer = malloc(header->cupsBytesPerLine);
491 LastSet = 0;
492 break;
ef416fc2 493 }
494
495 /*
496 * Allocate memory for a line of graphics...
497 */
498
499 Buffer = malloc(header->cupsBytesPerLine);
500 Feed = 0;
501}
502
503
504/*
505 * 'EndPage()' - Finish a page of graphics.
506 */
507
508void
509EndPage(ppd_file_t *ppd, /* I - PPD file */
510 cups_page_header_t *header) /* I - Page header */
511{
512 int val; /* Option value */
513 ppd_choice_t *choice; /* Marked choice */
514#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
515 struct sigaction action; /* Actions for POSIX signals */
516#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
517
518
519 switch (ModelNumber)
520 {
521 case DYMO_3x0 :
522 /*
523 * Eject the current page...
524 */
525
526 fputs("\033E", stdout);
527 break;
528
529 case ZEBRA_EPL_LINE :
530 /*
531 * End buffered output, eject the label...
532 */
533
534 fputs("\033E\014", stdout);
535 break;
536
537 case ZEBRA_EPL_PAGE :
538 /*
539 * Print the label...
540 */
541
542 puts("P1");
543 break;
544
545 case ZEBRA_ZPL :
546 if (Canceled)
547 {
548 /*
549 * Cancel bitmap download...
550 */
551
552 puts("~DN");
553 break;
554 }
555
556 /*
557 * Start label...
558 */
559
560 puts("^XA");
561
562 /*
563 * Set print rate...
564 */
565
566 if ((choice = ppdFindMarkedChoice(ppd, "zePrintRate")) != NULL &&
567 strcmp(choice->choice, "Default"))
568 {
569 val = atoi(choice->choice);
570 printf("^PR%d,%d,%d\n", val, val, val);
571 }
572
573 /*
574 * Put label home in default position (0,0)...
575 */
576
577 printf("^LH0,0\n");
578
579 /*
580 * Set media tracking...
581 */
582
583 if (ppdIsMarked(ppd, "zeMediaTracking", "Continuous"))
584 {
585 /*
586 * Add label length command for continuous...
587 */
588
589 printf("^LL%d\n", header->cupsHeight);
590 printf("^MNN\n");
591 }
592 else if (ppdIsMarked(ppd, "zeMediaTracking", "Web"))
593 printf("^MNY\n");
594 else if (ppdIsMarked(ppd, "zeMediaTracking", "Mark"))
595 printf("^MNM\n");
596
597 /*
598 * Set label top
599 */
600
601 if (header->cupsRowStep != 200)
602 printf("^LT%u\n", header->cupsRowStep);
603
604 /*
605 * Set media type...
606 */
607
608 if (!strcmp(header->MediaType, "Thermal"))
609 printf("^MTT\n");
610 else if (!strcmp(header->MediaType, "Direct"))
611 printf("^MTD\n");
612
613 /*
614 * Set print mode...
615 */
616
617 if ((choice = ppdFindMarkedChoice(ppd, "zePrintMode")) != NULL &&
618 strcmp(choice->choice, "Saved"))
619 {
620 printf("^MM");
621
622 if (!strcmp(choice->choice, "Tear"))
623 printf("T,Y\n");
624 else if (!strcmp(choice->choice, "Peel"))
625 printf("P,Y\n");
626 else if (!strcmp(choice->choice, "Rewind"))
627 printf("R,Y\n");
628 else if (!strcmp(choice->choice, "Applicator"))
629 printf("A,Y\n");
630 else
631 printf("C,Y\n");
632 }
633
634 /*
635 * Set tear-off adjust position...
636 */
637
638 if (header->AdvanceDistance != 1000)
639 {
640 if ((int)header->AdvanceDistance < 0)
641 printf("~TA%04d\n", (int)header->AdvanceDistance);
642 else
643 printf("~TA%03d\n", (int)header->AdvanceDistance);
644 }
645
646 /*
647 * Allow for reprinting after an error...
648 */
649
650 if (ppdIsMarked(ppd, "zeErrorReprint", "Always"))
651 printf("^JZY\n");
652 else if (ppdIsMarked(ppd, "zeErrorReprint", "Never"))
653 printf("^JZN\n");
654
655 /*
656 * Print multiple copies
657 */
658
659 if (header->NumCopies > 1)
660 printf("^PQ%d, 0, 0, N\n", header->NumCopies);
661
662 /*
663 * Display the label image...
664 */
665
666 puts("^FO0,0^XGR:CUPS.GRF,1,1^FS");
667
668 /*
669 * End the label and eject...
670 */
671
672 puts("^XZ");
673
674 /*
675 * Free compression buffers...
676 */
677
678 free(CompBuffer);
679 free(LastBuffer);
680 break;
681
682 case ZEBRA_CPCL :
683 /*
684 * Set tear-off adjust position...
685 */
686
687 if (header->AdvanceDistance != 1000)
688 printf("PRESENT-AT %d 1\r\n", (int)header->AdvanceDistance);
689
690 /*
691 * Allow for reprinting after an error...
692 */
693
694 if (ppdIsMarked(ppd, "zeErrorReprint", "Always"))
695 puts("ON-OUT-OF-PAPER WAIT\r");
696 else if (ppdIsMarked(ppd, "zeErrorReprint", "Never"))
697 puts("ON-OUT-OF-PAPER PURGE\r");
698
699 /*
700 * Cut label?
701 */
702
703 if (header->CutMedia)
704 puts("CUT\r");
705
706 /*
707 * Set darkness...
708 */
709
710 if (header->cupsCompression > 0)
711 printf("TONE %u\r\n", 2 * header->cupsCompression);
712
713 /*
714 * Set print rate...
715 */
716
717 if ((choice = ppdFindMarkedChoice(ppd, "zePrintRate")) != NULL &&
718 strcmp(choice->choice, "Default"))
719 {
720 val = atoi(choice->choice);
721 printf("SPEED %d\r\n", val);
722 }
723
724 /*
725 * Print the label...
726 */
727
8ca02f3c 728 if ((choice = ppdFindMarkedChoice(ppd, "zeMediaTracking")) == NULL ||
729 strcmp(choice->choice, "Continuous"))
730 puts("FORM\r");
731
ef416fc2 732 puts("PRINT\r");
733 break;
f7deaa1a 734
735 case INTELLITECH_PCL :
736 printf("\033*rB"); /* End GFX */
737 printf("\014"); /* Eject current page */
738 break;
ef416fc2 739 }
740
741 fflush(stdout);
742
743 /*
744 * Unregister the signal handler...
745 */
746
747#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
748 sigset(SIGTERM, SIG_IGN);
749#elif defined(HAVE_SIGACTION)
750 memset(&action, 0, sizeof(action));
751
752 sigemptyset(&action.sa_mask);
753 action.sa_handler = SIG_IGN;
754 sigaction(SIGTERM, &action, NULL);
755#else
756 signal(SIGTERM, SIG_IGN);
757#endif /* HAVE_SIGSET */
758
759 /*
760 * Free memory...
761 */
762
763 free(Buffer);
764}
765
766
767/*
768 * 'CancelJob()' - Cancel the current job...
769 */
770
771void
772CancelJob(int sig) /* I - Signal */
773{
774 /*
775 * Tell the main loop to stop...
776 */
777
778 (void)sig;
779
780 Canceled = 1;
781}
782
783
784/*
785 * 'OutputLine()' - Output a line of graphics...
786 */
787
788void
789OutputLine(ppd_file_t *ppd, /* I - PPD file */
790 cups_page_header_t *header, /* I - Page header */
791 int y) /* I - Line number */
792{
793 int i; /* Looping var */
794 unsigned char *ptr; /* Pointer into buffer */
ed486911 795 unsigned char *compptr; /* Pointer into compression buffer */
ef416fc2 796 char repeat_char; /* Repeated character */
797 int repeat_count; /* Number of repeated characters */
798 static const char *hex = "0123456789ABCDEF";
799 /* Hex digits */
800
801
802 switch (ModelNumber)
803 {
804 case DYMO_3x0 :
805 /*
806 * See if the line is blank; if not, write it to the printer...
807 */
808
809 if (Buffer[0] ||
810 memcmp(Buffer, Buffer + 1, header->cupsBytesPerLine - 1))
811 {
812 if (Feed)
813 {
814 while (Feed > 255)
815 {
816 printf("\033f\001%c", 255);
817 Feed -= 255;
818 }
819
820 printf("\033f\001%c", Feed);
821 Feed = 0;
822 }
823
824 putchar(0x16);
825 fwrite(Buffer, header->cupsBytesPerLine, 1, stdout);
826 fflush(stdout);
827
828#ifdef __sgi
829 /*
830 * This hack works around a bug in the IRIX serial port driver when
831 * run at high baud rates (e.g. 115200 baud)... This results in
832 * slightly slower label printing, but at least the labels come
833 * out properly.
834 */
835
836 sginap(1);
837#endif /* __sgi */
838 }
839 else
840 Feed ++;
841 break;
842
843 case ZEBRA_EPL_LINE :
844 printf("\033g%03d", header->cupsBytesPerLine);
845 fwrite(Buffer, 1, header->cupsBytesPerLine, stdout);
846 fflush(stdout);
847 break;
848
849 case ZEBRA_EPL_PAGE :
850 if (Buffer[0] || memcmp(Buffer, Buffer + 1, header->cupsBytesPerLine))
851 {
852 printf("GW0,%d,%d,1\n", y, header->cupsBytesPerLine);
853 for (i = header->cupsBytesPerLine, ptr = Buffer; i > 0; i --, ptr ++)
854 putchar(~*ptr);
855 putchar('\n');
856 fflush(stdout);
857 }
858 break;
859
860 case ZEBRA_ZPL :
861 /*
862 * Determine if this row is the same as the previous line.
863 * If so, output a ':' and return...
864 */
865
866 if (LastSet)
867 {
868 if (!memcmp(Buffer, LastBuffer, header->cupsBytesPerLine))
869 {
870 putchar(':');
871 return;
872 }
873 }
874
875 /*
876 * Convert the line to hex digits...
877 */
878
879 for (ptr = Buffer, compptr = CompBuffer, i = header->cupsBytesPerLine;
880 i > 0;
881 i --, ptr ++)
882 {
883 *compptr++ = hex[*ptr >> 4];
884 *compptr++ = hex[*ptr & 15];
885 }
886
887 *compptr = '\0';
888
889 /*
890 * Run-length compress the graphics...
891 */
892
b86bc4cf 893 for (compptr = CompBuffer + 1, repeat_char = CompBuffer[0], repeat_count = 1;
ef416fc2 894 *compptr;
895 compptr ++)
896 if (*compptr == repeat_char)
897 repeat_count ++;
898 else
899 {
900 ZPLCompress(repeat_char, repeat_count);
901 repeat_char = *compptr;
902 repeat_count = 1;
903 }
904
905 if (repeat_char == '0')
906 {
907 /*
908 * Handle 0's on the end of the line...
909 */
910
911 if (repeat_count & 1)
b86bc4cf 912 {
913 repeat_count --;
ef416fc2 914 putchar('0');
b86bc4cf 915 }
ef416fc2 916
b86bc4cf 917 if (repeat_count > 0)
918 putchar(',');
ef416fc2 919 }
920 else
921 ZPLCompress(repeat_char, repeat_count);
922
b86bc4cf 923 fflush(stdout);
924
ef416fc2 925 /*
926 * Save this line for the next round...
927 */
928
929 memcpy(LastBuffer, Buffer, header->cupsBytesPerLine);
930 LastSet = 1;
931 break;
932
933 case ZEBRA_CPCL :
934 if (Buffer[0] || memcmp(Buffer, Buffer + 1, header->cupsBytesPerLine))
935 {
936 printf("CG %u 1 0 %d ", header->cupsBytesPerLine, y);
937 fwrite(Buffer, 1, header->cupsBytesPerLine, stdout);
938 puts("\r");
939 fflush(stdout);
940 }
941 break;
f7deaa1a 942
943 case INTELLITECH_PCL :
944 if (Buffer[0] ||
945 memcmp(Buffer, Buffer + 1, header->cupsBytesPerLine - 1))
946 {
947 if (Feed)
948 {
949 printf("\033*b%dY", Feed);
950 Feed = 0;
951 LastSet = 0;
952 }
953
954 PCLCompress(Buffer, header->cupsBytesPerLine);
955 }
956 else
957 Feed ++;
958 break;
959 }
960}
961
962
963/*
964 * 'PCLCompress()' - Output a PCL (mode 3) compressed line.
965 */
966
967void
968PCLCompress(unsigned char *line, /* I - Line to compress */
969 int length) /* I - Length of line */
970{
971 unsigned char *line_ptr, /* Current byte pointer */
972 *line_end, /* End-of-line byte pointer */
973 *comp_ptr, /* Pointer into compression buffer */
974 *start, /* Start of compression sequence */
975 *seed; /* Seed buffer pointer */
976 int count, /* Count of bytes for output */
977 offset; /* Offset of bytes for output */
978
979
980 /*
981 * Do delta-row compression...
982 */
983
984 line_ptr = line;
985 line_end = line + length;
986
987 comp_ptr = CompBuffer;
988 seed = LastBuffer;
989
990 while (line_ptr < line_end)
991 {
992 /*
993 * Find the next non-matching sequence...
994 */
995
996 start = line_ptr;
997
998 if (!LastSet)
999 {
1000 /*
1001 * The seed buffer is invalid, so do the next 8 bytes, max...
1002 */
1003
1004 offset = 0;
1005
1006 if ((count = line_end - line_ptr) > 8)
1007 count = 8;
1008
1009 line_ptr += count;
1010 }
1011 else
1012 {
1013 /*
1014 * The seed buffer is valid, so compare against it...
1015 */
1016
1017 while (*line_ptr == *seed &&
1018 line_ptr < line_end)
1019 {
1020 line_ptr ++;
1021 seed ++;
1022 }
1023
1024 if (line_ptr == line_end)
1025 break;
1026
1027 offset = line_ptr - start;
1028
1029 /*
1030 * Find up to 8 non-matching bytes...
1031 */
1032
1033 start = line_ptr;
1034 count = 0;
1035 while (*line_ptr != *seed &&
1036 line_ptr < line_end &&
1037 count < 8)
1038 {
1039 line_ptr ++;
1040 seed ++;
1041 count ++;
1042 }
1043 }
1044
1045 /*
1046 * Place mode 3 compression data in the buffer; see HP manuals
1047 * for details...
1048 */
1049
1050 if (offset >= 31)
1051 {
1052 /*
1053 * Output multi-byte offset...
1054 */
1055
1056 *comp_ptr++ = ((count - 1) << 5) | 31;
1057
1058 offset -= 31;
1059 while (offset >= 255)
1060 {
1061 *comp_ptr++ = 255;
1062 offset -= 255;
1063 }
1064
1065 *comp_ptr++ = offset;
1066 }
1067 else
1068 {
1069 /*
1070 * Output single-byte offset...
1071 */
1072
1073 *comp_ptr++ = ((count - 1) << 5) | offset;
1074 }
1075
1076 memcpy(comp_ptr, start, count);
1077 comp_ptr += count;
ef416fc2 1078 }
f7deaa1a 1079
1080 line_ptr = CompBuffer;
1081 line_end = comp_ptr;
1082
1083 /*
1084 * Set the length of the data and write it...
1085 */
1086
1087 printf("\033*b%dW", comp_ptr - CompBuffer);
1088 fwrite(CompBuffer, comp_ptr - CompBuffer, 1, stdout);
1089
1090 /*
1091 * Save this line as a "seed" buffer for the next...
1092 */
1093
1094 memcpy(LastBuffer, line, length);
1095 LastSet = 1;
ef416fc2 1096}
1097
1098
1099/*
1100 * 'ZPLCompress()' - Output a run-length compression sequence.
1101 */
1102
1103void
1104ZPLCompress(char repeat_char, /* I - Character to repeat */
1105 int repeat_count) /* I - Number of repeated characters */
1106{
1107 if (repeat_count > 1)
1108 {
1109 /*
1110 * Print as many z's as possible - they are the largest denomination
1111 * representing 400 characters (zC stands for 400 adjacent C's)
1112 */
1113
1114 while (repeat_count >= 400)
1115 {
1116 putchar('z');
1117 repeat_count -= 400;
1118 }
1119
1120 /*
1121 * Then print 'g' through 'y' as multiples of 20 characters...
1122 */
1123
1124 if (repeat_count >= 20)
1125 {
1126 putchar('f' + repeat_count / 20);
1127 repeat_count %= 20;
1128 }
1129
1130 /*
1131 * Finally, print 'G' through 'Y' as 1 through 19 characters...
1132 */
1133
1134 if (repeat_count > 0)
1135 putchar('F' + repeat_count);
1136 }
1137
1138 /*
1139 * Then the character to be repeated...
1140 */
1141
1142 putchar(repeat_char);
1143}
1144
1145
1146/*
1147 * 'main()' - Main entry and processing of driver.
1148 */
1149
1150int /* O - Exit status */
1151main(int argc, /* I - Number of command-line arguments */
1152 char *argv[]) /* I - Command-line arguments */
1153{
1154 int fd; /* File descriptor */
1155 cups_raster_t *ras; /* Raster stream for printing */
1156 cups_page_header_t header; /* Page header from file */
1157 int y; /* Current line */
1158 ppd_file_t *ppd; /* PPD file */
1159 int num_options; /* Number of options */
1160 cups_option_t *options; /* Options */
1161
1162
1163 /*
1164 * Make sure status messages are not buffered...
1165 */
1166
1167 setbuf(stderr, NULL);
1168
1169 /*
1170 * Check command-line...
1171 */
1172
1173 if (argc < 6 || argc > 7)
1174 {
1175 /*
1176 * We don't have the correct number of arguments; write an error message
1177 * and return.
1178 */
1179
c0e1af83 1180 fprintf(stderr, _("Usage: %s job-id user title copies options [file]\n"),
1181 argv[0]);
ef416fc2 1182 return (1);
1183 }
1184
1185 /*
1186 * Open the page stream...
1187 */
1188
1189 if (argc == 7)
1190 {
1191 if ((fd = open(argv[6], O_RDONLY)) == -1)
1192 {
1193 perror("ERROR: Unable to open raster file - ");
1194 sleep(1);
1195 return (1);
1196 }
1197 }
1198 else
1199 fd = 0;
1200
1201 ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
1202
1203 /*
1204 * Open the PPD file and apply options...
1205 */
1206
1207 num_options = cupsParseOptions(argv[5], 0, &options);
1208
1209 if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
1210 {
1211 ppdMarkDefaults(ppd);
1212 cupsMarkOptions(ppd, num_options, options);
1213 }
1214
1215 /*
1216 * Initialize the print device...
1217 */
1218
1219 Setup(ppd);
1220
1221 /*
1222 * Process pages as needed...
1223 */
1224
1225 Page = 0;
1226 Canceled = 0;
1227
1228 while (cupsRasterReadHeader(ras, &header))
1229 {
1230 /*
1231 * Write a status message with the page number and number of copies.
1232 */
1233
1234 Page ++;
1235
1236 fprintf(stderr, "PAGE: %d 1\n", Page);
1237
1238 /*
1239 * Start the page...
1240 */
1241
1242 StartPage(ppd, &header);
1243
1244 /*
1245 * Loop for each line on the page...
1246 */
1247
1248 for (y = 0; y < header.cupsHeight && !Canceled; y ++)
1249 {
1250 /*
1251 * Let the user know how far we have progressed...
1252 */
1253
1254 if ((y & 15) == 0)
c0e1af83 1255 fprintf(stderr, _("INFO: Printing page %d, %d%% complete...\n"), Page,
ef416fc2 1256 100 * y / header.cupsHeight);
1257
1258 /*
1259 * Read a line of graphics...
1260 */
1261
1262 if (cupsRasterReadPixels(ras, Buffer, header.cupsBytesPerLine) < 1)
1263 break;
1264
1265 /*
1266 * Write it to the printer...
1267 */
1268
1269 OutputLine(ppd, &header, y);
1270 }
1271
1272 /*
1273 * Eject the page...
1274 */
1275
1276 EndPage(ppd, &header);
1277
1278 if (Canceled)
1279 break;
1280 }
1281
1282 /*
1283 * Close the raster stream...
1284 */
1285
1286 cupsRasterClose(ras);
1287 if (fd != 0)
1288 close(fd);
1289
1290 /*
1291 * Close the PPD file and free the options...
1292 */
1293
1294 ppdClose(ppd);
1295 cupsFreeOptions(num_options, options);
1296
1297 /*
1298 * If no pages were printed, send an error message...
1299 */
1300
1301 if (Page == 0)
c0e1af83 1302 fputs(_("ERROR: No pages found!\n"), stderr);
ef416fc2 1303 else
c0e1af83 1304 fputs(_("INFO: Ready to print.\n"), stderr);
ef416fc2 1305
1306 return (Page == 0);
1307}
1308
1309
1310/*
c0e1af83 1311 * End of "$Id: rastertolabel.c 6420 2007-03-30 20:00:59Z mike $".
ef416fc2 1312 */