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