]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/rastertodymo.c
Move 1.2 branch to trunk.
[thirdparty/cups.git] / filter / rastertodymo.c
CommitLineData
74456259 1/*
c9d3f842 2 * "$Id$"
74456259 3 *
725dbff8 4 * Label printer filter for the Common UNIX Printing System (CUPS).
74456259 5 *
c9d3f842 6 * Copyright 2001-2005 by Easy Software Products.
74456259 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
c9d3f842 18 * Hollywood, Maryland 20636 USA
74456259 19 *
9639c4de 20 * Voice: (301) 373-9600
74456259 21 * EMail: cups-info@cups.org
22 * WWW: http://www.cups.org
23 *
dab1a4d8 24 * This file is subject to the Apple OS-Developed Software exception.
25 *
74456259 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 * Shutdown() - Shutdown the printer.
32 * CancelJob() - Cancel the current job...
74456259 33 * OutputLine() - Output a line of graphics.
34 * main() - Main entry and processing of driver.
35 */
36
37/*
38 * Include necessary headers...
39 */
40
41#include <cups/cups.h>
42#include <cups/string.h>
43#include "raster.h"
44#include <stdlib.h>
45#include <unistd.h>
46#include <fcntl.h>
47#include <signal.h>
48
49
725dbff8 50/*
51 * This driver filter currently supports Dymo and Zebra label printers.
52 *
53 * The Dymo portion of the driver has been tested with the 300, 330,
54 * and 330 Turbo label printers; it may also work with older models.
55 * The Dymo printers support printing at 136, 203, and 300 DPI.
56 *
ea19a116 57 * The Zebra portion of the driver has been tested with the LP-2844Z label
725dbff8 58 * printer; it may also work with other models. The driver supports both
ea19a116 59 * EPL and ZPL as defined in Zebra's on-line developer documentation.
725dbff8 60 */
61
62/*
63 * Model number constants...
64 */
65
66#define DYMO_3x0 0 /* Dymo Labelwriter 300/330/330 Turbo */
67
ea19a116 68#define ZEBRA_EPL_LINE 0x10 /* Zebra EPL line mode printers */
69#define ZEBRA_EPL_PAGE 0x11 /* Zebra EPL page mode printers */
70#define ZEBRA_ZPL 0x12 /* Zebra ZPL-based printers */
725dbff8 71
72
74456259 73/*
74 * Globals...
75 */
76
77unsigned char *Buffer; /* Output buffer */
725dbff8 78int ModelNumber, /* cupsModelNumber attribute */
79 Page, /* Current page */
80 Feed, /* Number of lines to skip */
ea19a116 81 Canceled; /* Non-zero if job is canceled */
74456259 82
83
84/*
85 * Prototypes...
86 */
87
88void Setup(void);
89void StartPage(cups_page_header_t *header);
725dbff8 90void EndPage(cups_page_header_t *header);
74456259 91void CancelJob(int sig);
ea19a116 92void OutputLine(cups_page_header_t *header, int y);
74456259 93
94
95/*
96 * 'Setup()' - Prepare the printer for printing.
97 */
98
99void
100Setup(void)
101{
725dbff8 102 int i; /* Looping var */
103 ppd_file_t *ppd; /* PPD file */
74456259 104
105
106 /*
725dbff8 107 * Get the model number from the PPD file...
74456259 108 */
109
725dbff8 110 if ((ppd = ppdOpenFile(getenv("PPD"))) != NULL)
111 {
112 ModelNumber = ppd->model_number;
113 ppdClose(ppd);
114 }
c67094f2 115
116 /*
725dbff8 117 * Initialize based on the model number...
c67094f2 118 */
119
725dbff8 120 switch (ModelNumber)
121 {
122 case DYMO_3x0 :
123 /*
124 * Clear any remaining data...
125 */
126
127 for (i = 0; i < 100; i ++)
128 putchar(0x1b);
129
130 /*
131 * Reset the printer...
132 */
133
134 fputs("\033@", stdout);
135 break;
136
ea19a116 137 case ZEBRA_EPL_LINE :
138 break;
139
140 case ZEBRA_EPL_PAGE :
141 break;
142
725dbff8 143 case ZEBRA_ZPL :
725dbff8 144 break;
145 }
74456259 146}
147
148
149/*
150 * 'StartPage()' - Start a page of graphics.
151 */
152
153void
154StartPage(cups_page_header_t *header) /* I - Page header */
155{
9a12ff91 156 int length; /* Actual label length */
74456259 157#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
158 struct sigaction action; /* Actions for POSIX signals */
159#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
160
161
162 /*
163 * Register a signal handler to eject the current page if the
ea19a116 164 * job is canceled.
74456259 165 */
166
167#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
168 sigset(SIGTERM, CancelJob);
169#elif defined(HAVE_SIGACTION)
170 memset(&action, 0, sizeof(action));
171
172 sigemptyset(&action.sa_mask);
173 action.sa_handler = CancelJob;
174 sigaction(SIGTERM, &action, NULL);
175#else
176 signal(SIGTERM, CancelJob);
177#endif /* HAVE_SIGSET */
178
725dbff8 179 switch (ModelNumber)
180 {
181 case DYMO_3x0 :
182 /*
183 * Setup printer/job attributes...
184 */
185
186 length = header->PageSize[1] * header->HWResolution[1] / 72;
187
188 printf("\033L%c%c", length >> 8, length);
189 printf("\033D%c", header->cupsBytesPerLine);
190
191 printf("\033%c", header->cupsCompression + 'c'); /* Darkness */
192 break;
74456259 193
ea19a116 194 case ZEBRA_EPL_LINE :
195 /*
196 * Set darkness...
197 */
198
199 printf("D%d", 7 * header->cupsCompression / 100);
200
201 /*
202 * Start buffered output...
203 */
204
205 putchar('B');
206 break;
207
208 case ZEBRA_EPL_PAGE :
209 /*
210 * Set darkness...
211 */
212
213 printf("D%d", 15 * header->cupsCompression / 100);
214
215 /*
216 * Set label size...
217 */
218
219 printf("q%d\n", header->cupsWidth);
220 break;
221
725dbff8 222 case ZEBRA_ZPL :
725dbff8 223 /*
224 * Set darkness...
225 */
9a12ff91 226
ea19a116 227 printf("~SD%02d\n", 30 * header->cupsCompression / 100);
74456259 228
725dbff8 229 /*
230 * Start bitmap graphics...
231 */
232
233 printf("~DGR:CUPS.GRF,%d,%d,\n",
234 header->cupsHeight * header->cupsBytesPerLine,
235 header->cupsBytesPerLine);
236 break;
237 }
74456259 238
239 /*
240 * Allocate memory for a line of graphics...
241 */
242
243 Buffer = malloc(header->cupsBytesPerLine);
244 Feed = 0;
245}
246
247
248/*
249 * 'EndPage()' - Finish a page of graphics.
250 */
251
252void
725dbff8 253EndPage(cups_page_header_t *header) /* I - Page header */
74456259 254{
255#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
725dbff8 256 struct sigaction action; /* Actions for POSIX signals */
74456259 257#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
258
259
725dbff8 260 switch (ModelNumber)
261 {
262 case DYMO_3x0 :
263 /*
264 * Eject the current page...
265 */
266
267 fputs("\033E", stdout);
ea19a116 268 break;
74456259 269
ea19a116 270 case ZEBRA_EPL_LINE :
271 /*
272 * End buffered output, eject the label...
273 */
274
275 putchar('E');
276 break;
277
278 case ZEBRA_EPL_PAGE :
279 /*
280 * Print the label...
281 */
282
283 puts("P1");
725dbff8 284 break;
285
286 case ZEBRA_ZPL :
ea19a116 287 if (Canceled)
725dbff8 288 {
289 /*
290 * Cancel bitmap download...
291 */
292
293 puts("~DN");
294 break;
295 }
296
297 /*
ea19a116 298 * Start label, set origin to 1/8,1/16", and set length...
725dbff8 299 */
74456259 300
725dbff8 301 puts("^XA");
ea19a116 302 printf("^LH%d,%d\n", header->HWResolution[0] / 8,
303 header->HWResolution[1] / 16);
725dbff8 304 printf("^LL%d\n", header->cupsHeight);
305
306 /*
307 * Cut labels if requested...
308 */
309
310 if (header->CutMedia)
311 puts("^MMC");
ea19a116 312 else
313 puts("^MMT");
725dbff8 314
315 /*
316 * Display the label image...
317 */
318
319 puts("~FO0,0^XGR:CUPS.GRF,1,1^FS");
320
321 /*
322 * End the label and eject...
323 */
324
325 puts("^XZ");
326 break;
327 }
74456259 328
ea19a116 329 fflush(stdout);
330
74456259 331 /*
332 * Unregister the signal handler...
333 */
334
335#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
336 sigset(SIGTERM, SIG_IGN);
337#elif defined(HAVE_SIGACTION)
338 memset(&action, 0, sizeof(action));
339
340 sigemptyset(&action.sa_mask);
341 action.sa_handler = SIG_IGN;
342 sigaction(SIGTERM, &action, NULL);
343#else
344 signal(SIGTERM, SIG_IGN);
345#endif /* HAVE_SIGSET */
346
347 /*
348 * Free memory...
349 */
350
351 free(Buffer);
352}
353
354
355/*
356 * 'CancelJob()' - Cancel the current job...
357 */
358
359void
360CancelJob(int sig) /* I - Signal */
361{
725dbff8 362 /*
363 * Tell the main loop to stop...
364 */
74456259 365
366 (void)sig;
367
ea19a116 368 Canceled = 1;
725dbff8 369}
74456259 370
74456259 371
725dbff8 372/*
373 * 'OutputLine()' - Output a line of graphics...
374 */
375
376void
ea19a116 377OutputLine(cups_page_header_t *header, /* I - Page header */
378 int y) /* I - Line number */
725dbff8 379{
380 int i; /* Looping var */
381 unsigned char *ptr; /* Pointer into buffer */
382
74456259 383
725dbff8 384 switch (ModelNumber)
385 {
386 case DYMO_3x0 :
387 /*
388 * See if the line is blank; if not, write it to the printer...
389 */
390
391 if (Buffer[0] ||
392 memcmp(Buffer, Buffer + 1, header->cupsBytesPerLine - 1))
393 {
394 if (Feed)
395 {
396 while (Feed > 255)
397 {
398 printf("\033f\001%c", 255);
399 Feed -= 255;
400 }
401
402 printf("\033f\001%c", Feed);
403 Feed = 0;
404 }
74456259 405
725dbff8 406 putchar(0x16);
407 fwrite(Buffer, header->cupsBytesPerLine, 1, stdout);
408 fflush(stdout);
409
410#ifdef __sgi
411 /*
412 * This hack works around a bug in the IRIX serial port driver when
413 * run at high baud rates (e.g. 115200 baud)... This results in
414 * slightly slower label printing, but at least the labels come
415 * out properly.
416 */
417
418 sginap(1);
419#endif /* __sgi */
420 }
421 else
422 Feed ++;
423 break;
424
ea19a116 425 case ZEBRA_EPL_LINE :
426 printf("g%03d", header->cupsBytesPerLine);
427 fwrite(Buffer, 1, header->cupsBytesPerLine, stdout);
428 fflush(stdout);
429 break;
430
431 case ZEBRA_EPL_PAGE :
432 printf("GW0,%d,%d,1", y, header->cupsBytesPerLine);
433 fwrite(Buffer, 1, header->cupsBytesPerLine, stdout);
434 putchar('\n');
435 fflush(stdout);
436 break;
437
725dbff8 438 case ZEBRA_ZPL :
725dbff8 439 for (i = header->cupsBytesPerLine, ptr = Buffer; i > 0; i --, ptr ++)
725dbff8 440 if (!*ptr && (i == 1 || !memcmp(ptr, ptr + 1, i - 1)))
441 {
442 putchar(',');
443 break;
444 }
445 else
725dbff8 446 printf("%02X", *ptr);
447
448 putchar('\n');
449 break;
450 }
74456259 451}
452
453
454/*
455 * 'main()' - Main entry and processing of driver.
456 */
457
725dbff8 458int /* O - Exit status */
459main(int argc, /* I - Number of command-line arguments */
460 char *argv[]) /* I - Command-line arguments */
74456259 461{
725dbff8 462 int fd; /* File descriptor */
463 cups_raster_t *ras; /* Raster stream for printing */
464 cups_page_header_t header; /* Page header from file */
465 int y; /* Current line */
74456259 466
467
468 /*
469 * Make sure status messages are not buffered...
470 */
471
472 setbuf(stderr, NULL);
473
474 /*
475 * Check command-line...
476 */
477
478 if (argc < 6 || argc > 7)
479 {
480 /*
481 * We don't have the correct number of arguments; write an error message
482 * and return.
483 */
484
485 fputs("ERROR: rastertodymo job-id user title copies options [file]\n", stderr);
486 return (1);
487 }
488
489 /*
490 * Open the page stream...
491 */
492
493 if (argc == 7)
494 {
725dbff8 495 if ((fd = open(argv[6], O_RDONLY)) == -1)
74456259 496 {
497 perror("ERROR: Unable to open raster file - ");
498 sleep(1);
499 return (1);
500 }
501 }
502 else
2e32fcdb 503 fd = 0;
74456259 504
2e32fcdb 505 ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
74456259 506
507 /*
508 * Initialize the print device...
509 */
510
511 Setup();
512
513 /*
514 * Process pages as needed...
515 */
516
725dbff8 517 Page = 0;
ea19a116 518 Canceled = 0;
74456259 519
520 while (cupsRasterReadHeader(ras, &header))
521 {
522 /*
523 * Write a status message with the page number and number of copies.
524 */
525
526 Page ++;
527
528 fprintf(stderr, "PAGE: %d 1\n", Page);
529
530 /*
531 * Start the page...
532 */
533
534 StartPage(&header);
535
536 /*
537 * Loop for each line on the page...
538 */
539
ea19a116 540 for (y = 0; y < header.cupsHeight && !Canceled; y ++)
74456259 541 {
542 /*
543 * Let the user know how far we have progressed...
544 */
545
546 if ((y & 15) == 0)
547 fprintf(stderr, "INFO: Printing page %d, %d%% complete...\n", Page,
548 100 * y / header.cupsHeight);
549
550 /*
551 * Read a line of graphics...
552 */
553
554 if (cupsRasterReadPixels(ras, Buffer, header.cupsBytesPerLine) < 1)
555 break;
556
557 /*
725dbff8 558 * Write it to the printer...
74456259 559 */
560
ea19a116 561 OutputLine(&header, y);
74456259 562 }
563
564 /*
565 * Eject the page...
566 */
567
bbf6bc56 568 EndPage(&header);
725dbff8 569
ea19a116 570 if (Canceled)
725dbff8 571 break;
74456259 572 }
573
574 /*
575 * Close the raster stream...
576 */
577
578 cupsRasterClose(ras);
725dbff8 579 if (fd != 0)
2e32fcdb 580 close(fd);
74456259 581
582 /*
583 * If no pages were printed, send an error message...
584 */
585
586 if (Page == 0)
587 fputs("ERROR: No pages found!\n", stderr);
588 else
725dbff8 589 fputs("INFO: Ready to print.\n", stderr);
74456259 590
591 return (Page == 0);
592}
593
594
595/*
c9d3f842 596 * End of "$Id$".
74456259 597 */