Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/filter/rastertohp.c
1090 views
1
/*
2
* Hewlett-Packard Page Control Language filter for CUPS.
3
*
4
* Copyright 2007-2015 by Apple Inc.
5
* Copyright 1993-2007 by Easy Software Products.
6
*
7
* Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8
*/
9
10
/*
11
* Include necessary headers...
12
*/
13
14
#include <cups/cups.h>
15
#include <cups/ppd.h>
16
#include <cups/string-private.h>
17
#include <cups/language-private.h>
18
#include <cups/raster.h>
19
#include <unistd.h>
20
#include <fcntl.h>
21
#include <signal.h>
22
23
24
/*
25
* Globals...
26
*/
27
28
unsigned char *Planes[4], /* Output buffers */
29
*CompBuffer, /* Compression buffer */
30
*BitBuffer; /* Buffer for output bits */
31
unsigned NumPlanes, /* Number of color planes */
32
ColorBits, /* Number of bits per color */
33
Feed; /* Number of lines to skip */
34
cups_bool_t Duplex; /* Current duplex mode */
35
int Page, /* Current page number */
36
Canceled; /* Has the current job been canceled? */
37
38
39
/*
40
* Prototypes...
41
*/
42
43
void Setup(void);
44
void StartPage(ppd_file_t *ppd, cups_page_header2_t *header);
45
void EndPage(void);
46
void Shutdown(void);
47
48
void CancelJob(int sig);
49
void CompressData(unsigned char *line, unsigned length, unsigned plane, unsigned type);
50
void OutputLine(cups_page_header2_t *header);
51
52
53
/*
54
* 'Setup()' - Prepare the printer for printing.
55
*/
56
57
void
58
Setup(void)
59
{
60
/*
61
* Send a PCL reset sequence.
62
*/
63
64
putchar(0x1b);
65
putchar('E');
66
}
67
68
69
/*
70
* 'StartPage()' - Start a page of graphics.
71
*/
72
73
void
74
StartPage(ppd_file_t *ppd, /* I - PPD file */
75
cups_page_header2_t *header) /* I - Page header */
76
{
77
unsigned plane; /* Looping var */
78
79
80
/*
81
* Show page device dictionary...
82
*/
83
84
fprintf(stderr, "DEBUG: StartPage...\n");
85
fprintf(stderr, "DEBUG: Duplex = %d\n", header->Duplex);
86
fprintf(stderr, "DEBUG: HWResolution = [ %d %d ]\n", header->HWResolution[0], header->HWResolution[1]);
87
fprintf(stderr, "DEBUG: ImagingBoundingBox = [ %d %d %d %d ]\n", header->ImagingBoundingBox[0], header->ImagingBoundingBox[1], header->ImagingBoundingBox[2], header->ImagingBoundingBox[3]);
88
fprintf(stderr, "DEBUG: Margins = [ %d %d ]\n", header->Margins[0], header->Margins[1]);
89
fprintf(stderr, "DEBUG: ManualFeed = %d\n", header->ManualFeed);
90
fprintf(stderr, "DEBUG: MediaPosition = %d\n", header->MediaPosition);
91
fprintf(stderr, "DEBUG: NumCopies = %d\n", header->NumCopies);
92
fprintf(stderr, "DEBUG: Orientation = %d\n", header->Orientation);
93
fprintf(stderr, "DEBUG: PageSize = [ %d %d ]\n", header->PageSize[0], header->PageSize[1]);
94
fprintf(stderr, "DEBUG: cupsWidth = %d\n", header->cupsWidth);
95
fprintf(stderr, "DEBUG: cupsHeight = %d\n", header->cupsHeight);
96
fprintf(stderr, "DEBUG: cupsMediaType = %d\n", header->cupsMediaType);
97
fprintf(stderr, "DEBUG: cupsBitsPerColor = %d\n", header->cupsBitsPerColor);
98
fprintf(stderr, "DEBUG: cupsBitsPerPixel = %d\n", header->cupsBitsPerPixel);
99
fprintf(stderr, "DEBUG: cupsBytesPerLine = %d\n", header->cupsBytesPerLine);
100
fprintf(stderr, "DEBUG: cupsColorOrder = %d\n", header->cupsColorOrder);
101
fprintf(stderr, "DEBUG: cupsColorSpace = %d\n", header->cupsColorSpace);
102
fprintf(stderr, "DEBUG: cupsCompression = %d\n", header->cupsCompression);
103
104
/*
105
* Setup printer/job attributes...
106
*/
107
108
Duplex = header->Duplex;
109
ColorBits = header->cupsBitsPerColor;
110
111
if ((!Duplex || (Page & 1)) && header->MediaPosition)
112
printf("\033&l%dH", /* Set media position */
113
header->MediaPosition);
114
115
if (Duplex && ppd && ppd->model_number == 2)
116
{
117
/*
118
* Handle duplexing on new DeskJet printers...
119
*/
120
121
printf("\033&l-2H"); /* Load media */
122
123
if (Page & 1)
124
printf("\033&l2S"); /* Set duplex mode */
125
}
126
127
if (!Duplex || (Page & 1) || (ppd && ppd->model_number == 2))
128
{
129
/*
130
* Set the media size...
131
*/
132
133
printf("\033&l6D\033&k12H"); /* Set 6 LPI, 10 CPI */
134
printf("\033&l0O"); /* Set portrait orientation */
135
136
switch (header->PageSize[1])
137
{
138
case 540 : /* Monarch Envelope */
139
printf("\033&l80A"); /* Set page size */
140
break;
141
142
case 595 : /* A5 */
143
printf("\033&l25A"); /* Set page size */
144
break;
145
146
case 624 : /* DL Envelope */
147
printf("\033&l90A"); /* Set page size */
148
break;
149
150
case 649 : /* C5 Envelope */
151
printf("\033&l91A"); /* Set page size */
152
break;
153
154
case 684 : /* COM-10 Envelope */
155
printf("\033&l81A"); /* Set page size */
156
break;
157
158
case 709 : /* B5 Envelope */
159
printf("\033&l100A"); /* Set page size */
160
break;
161
162
case 756 : /* Executive */
163
printf("\033&l1A"); /* Set page size */
164
break;
165
166
case 792 : /* Letter */
167
printf("\033&l2A"); /* Set page size */
168
break;
169
170
case 842 : /* A4 */
171
printf("\033&l26A"); /* Set page size */
172
break;
173
174
case 1008 : /* Legal */
175
printf("\033&l3A"); /* Set page size */
176
break;
177
178
case 1191 : /* A3 */
179
printf("\033&l27A"); /* Set page size */
180
break;
181
182
case 1224 : /* Tabloid */
183
printf("\033&l6A"); /* Set page size */
184
break;
185
}
186
187
printf("\033&l%dP", /* Set page length */
188
header->PageSize[1] / 12);
189
printf("\033&l0E"); /* Set top margin to 0 */
190
}
191
192
if (!Duplex || (Page & 1))
193
{
194
/*
195
* Set other job options...
196
*/
197
198
printf("\033&l%dX", header->NumCopies); /* Set number copies */
199
200
if (header->cupsMediaType &&
201
(!ppd || ppd->model_number != 2 || header->HWResolution[0] == 600))
202
printf("\033&l%dM", /* Set media type */
203
header->cupsMediaType);
204
205
if (!ppd || ppd->model_number != 2)
206
{
207
int mode = Duplex ? 1 + header->Tumble != 0 : 0;
208
209
printf("\033&l%dS", mode); /* Set duplex mode */
210
printf("\033&l0L"); /* Turn off perforation skip */
211
}
212
}
213
else if (!ppd || ppd->model_number != 2)
214
printf("\033&a2G"); /* Set back side */
215
216
/*
217
* Set graphics mode...
218
*/
219
220
if (ppd && ppd->model_number == 2)
221
{
222
/*
223
* Figure out the number of color planes...
224
*/
225
226
if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
227
NumPlanes = 4;
228
else
229
NumPlanes = 1;
230
231
/*
232
* Set the resolution and top-of-form...
233
*/
234
235
printf("\033&u%dD", header->HWResolution[0]);
236
/* Resolution */
237
printf("\033&l0e0L"); /* Reset top and don't skip */
238
printf("\033*p0Y\033*p0X"); /* Set top of form */
239
240
/*
241
* Send 26-byte configure image data command with horizontal and
242
* vertical resolutions as well as a color count...
243
*/
244
245
printf("\033*g26W");
246
putchar(2); /* Format 2 */
247
putchar((int)NumPlanes); /* Output planes */
248
249
putchar((int)(header->HWResolution[0] >> 8));/* Black resolution */
250
putchar((int)header->HWResolution[0]);
251
putchar((int)(header->HWResolution[1] >> 8));
252
putchar((int)header->HWResolution[1]);
253
putchar(0);
254
putchar(1 << ColorBits); /* # of black levels */
255
256
putchar((int)(header->HWResolution[0] >> 8));/* Cyan resolution */
257
putchar((int)header->HWResolution[0]);
258
putchar((int)(header->HWResolution[1] >> 8));
259
putchar((int)header->HWResolution[1]);
260
putchar(0);
261
putchar(1 << ColorBits); /* # of cyan levels */
262
263
putchar((int)(header->HWResolution[0] >> 8));/* Magenta resolution */
264
putchar((int)header->HWResolution[0]);
265
putchar((int)(header->HWResolution[1] >> 8));
266
putchar((int)header->HWResolution[1]);
267
putchar(0);
268
putchar(1 << ColorBits); /* # of magenta levels */
269
270
putchar((int)(header->HWResolution[0] >> 8));/* Yellow resolution */
271
putchar((int)header->HWResolution[0]);
272
putchar((int)(header->HWResolution[1] >> 8));
273
putchar((int)header->HWResolution[1]);
274
putchar(0);
275
putchar(1 << ColorBits); /* # of yellow levels */
276
277
printf("\033&l0H"); /* Set media position */
278
}
279
else
280
{
281
printf("\033*t%uR", header->HWResolution[0]);
282
/* Set resolution */
283
284
if (header->cupsColorSpace == CUPS_CSPACE_KCMY)
285
{
286
NumPlanes = 4;
287
printf("\033*r-4U"); /* Set KCMY graphics */
288
}
289
else if (header->cupsColorSpace == CUPS_CSPACE_CMY)
290
{
291
NumPlanes = 3;
292
printf("\033*r-3U"); /* Set CMY graphics */
293
}
294
else
295
NumPlanes = 1; /* Black&white graphics */
296
297
/*
298
* Set size and position of graphics...
299
*/
300
301
printf("\033*r%uS", header->cupsWidth); /* Set width */
302
printf("\033*r%uT", header->cupsHeight); /* Set height */
303
304
printf("\033&a0H"); /* Set horizontal position */
305
306
if (ppd)
307
printf("\033&a%.0fV", /* Set vertical position */
308
10.0 * (ppd->sizes[0].length - ppd->sizes[0].top));
309
else
310
printf("\033&a0V"); /* Set top-of-page */
311
}
312
313
printf("\033*r1A"); /* Start graphics */
314
315
if (header->cupsCompression)
316
printf("\033*b%uM", /* Set compression */
317
header->cupsCompression);
318
319
Feed = 0; /* No blank lines yet */
320
321
/*
322
* Allocate memory for a line of graphics...
323
*/
324
325
if ((Planes[0] = malloc(header->cupsBytesPerLine + NumPlanes)) == NULL)
326
{
327
fputs("ERROR: Unable to allocate memory\n", stderr);
328
exit(1);
329
}
330
331
for (plane = 1; plane < NumPlanes; plane ++)
332
Planes[plane] = Planes[0] + plane * header->cupsBytesPerLine / NumPlanes;
333
334
if (ColorBits > 1)
335
BitBuffer = malloc((size_t)ColorBits * (((size_t)header->cupsWidth + 7) / 8));
336
else
337
BitBuffer = NULL;
338
339
if (header->cupsCompression)
340
CompBuffer = malloc(header->cupsBytesPerLine * 2 + 2);
341
else
342
CompBuffer = NULL;
343
}
344
345
346
/*
347
* 'EndPage()' - Finish a page of graphics.
348
*/
349
350
void
351
EndPage(void)
352
{
353
/*
354
* Eject the current page...
355
*/
356
357
if (NumPlanes > 1)
358
{
359
printf("\033*rC"); /* End color GFX */
360
361
if (!(Duplex && (Page & 1)))
362
printf("\033&l0H"); /* Eject current page */
363
}
364
else
365
{
366
printf("\033*r0B"); /* End GFX */
367
368
if (!(Duplex && (Page & 1)))
369
printf("\014"); /* Eject current page */
370
}
371
372
fflush(stdout);
373
374
/*
375
* Free memory...
376
*/
377
378
free(Planes[0]);
379
380
if (BitBuffer)
381
free(BitBuffer);
382
383
if (CompBuffer)
384
free(CompBuffer);
385
}
386
387
388
/*
389
* 'Shutdown()' - Shutdown the printer.
390
*/
391
392
void
393
Shutdown(void)
394
{
395
/*
396
* Send a PCL reset sequence.
397
*/
398
399
putchar(0x1b);
400
putchar('E');
401
}
402
403
404
/*
405
* 'CancelJob()' - Cancel the current job...
406
*/
407
408
void
409
CancelJob(int sig) /* I - Signal */
410
{
411
(void)sig;
412
413
Canceled = 1;
414
}
415
416
417
/*
418
* 'CompressData()' - Compress a line of graphics.
419
*/
420
421
void
422
CompressData(unsigned char *line, /* I - Data to compress */
423
unsigned length, /* I - Number of bytes */
424
unsigned plane, /* I - Color plane */
425
unsigned type) /* I - Type of compression */
426
{
427
unsigned char *line_ptr, /* Current byte pointer */
428
*line_end, /* End-of-line byte pointer */
429
*comp_ptr, /* Pointer into compression buffer */
430
*start; /* Start of compression sequence */
431
unsigned count; /* Count of bytes for output */
432
433
434
switch (type)
435
{
436
default :
437
/*
438
* Do no compression...
439
*/
440
441
line_ptr = line;
442
line_end = line + length;
443
break;
444
445
case 1 :
446
/*
447
* Do run-length encoding...
448
*/
449
450
line_end = line + length;
451
for (line_ptr = line, comp_ptr = CompBuffer;
452
line_ptr < line_end;
453
comp_ptr += 2, line_ptr += count)
454
{
455
for (count = 1;
456
(line_ptr + count) < line_end &&
457
line_ptr[0] == line_ptr[count] &&
458
count < 256;
459
count ++);
460
461
comp_ptr[0] = (unsigned char)(count - 1);
462
comp_ptr[1] = line_ptr[0];
463
}
464
465
line_ptr = CompBuffer;
466
line_end = comp_ptr;
467
break;
468
469
case 2 :
470
/*
471
* Do TIFF pack-bits encoding...
472
*/
473
474
line_ptr = line;
475
line_end = line + length;
476
comp_ptr = CompBuffer;
477
478
while (line_ptr < line_end)
479
{
480
if ((line_ptr + 1) >= line_end)
481
{
482
/*
483
* Single byte on the end...
484
*/
485
486
*comp_ptr++ = 0x00;
487
*comp_ptr++ = *line_ptr++;
488
}
489
else if (line_ptr[0] == line_ptr[1])
490
{
491
/*
492
* Repeated sequence...
493
*/
494
495
line_ptr ++;
496
count = 2;
497
498
while (line_ptr < (line_end - 1) &&
499
line_ptr[0] == line_ptr[1] &&
500
count < 127)
501
{
502
line_ptr ++;
503
count ++;
504
}
505
506
*comp_ptr++ = (unsigned char)(257 - count);
507
*comp_ptr++ = *line_ptr++;
508
}
509
else
510
{
511
/*
512
* Non-repeated sequence...
513
*/
514
515
start = line_ptr;
516
line_ptr ++;
517
count = 1;
518
519
while (line_ptr < (line_end - 1) &&
520
line_ptr[0] != line_ptr[1] &&
521
count < 127)
522
{
523
line_ptr ++;
524
count ++;
525
}
526
527
*comp_ptr++ = (unsigned char)(count - 1);
528
529
memcpy(comp_ptr, start, count);
530
comp_ptr += count;
531
}
532
}
533
534
line_ptr = CompBuffer;
535
line_end = comp_ptr;
536
break;
537
}
538
539
/*
540
* Set the length of the data and write a raster plane...
541
*/
542
543
printf("\033*b%d%c", (int)(line_end - line_ptr), plane);
544
fwrite(line_ptr, (size_t)(line_end - line_ptr), 1, stdout);
545
}
546
547
548
/*
549
* 'OutputLine()' - Output a line of graphics.
550
*/
551
552
void
553
OutputLine(cups_page_header2_t *header) /* I - Page header */
554
{
555
unsigned plane, /* Current plane */
556
bytes, /* Bytes to write */
557
count; /* Bytes to convert */
558
unsigned char bit, /* Current plane data */
559
bit0, /* Current low bit data */
560
bit1, /* Current high bit data */
561
*plane_ptr, /* Pointer into Planes */
562
*bit_ptr; /* Pointer into BitBuffer */
563
564
565
/*
566
* Output whitespace as needed...
567
*/
568
569
if (Feed > 0)
570
{
571
printf("\033*b%dY", Feed);
572
Feed = 0;
573
}
574
575
/*
576
* Write bitmap data as needed...
577
*/
578
579
bytes = (header->cupsWidth + 7) / 8;
580
581
for (plane = 0; plane < NumPlanes; plane ++)
582
if (ColorBits == 1)
583
{
584
/*
585
* Send bits as-is...
586
*/
587
588
CompressData(Planes[plane], bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
589
header->cupsCompression);
590
}
591
else
592
{
593
/*
594
* Separate low and high bit data into separate buffers.
595
*/
596
597
for (count = header->cupsBytesPerLine / NumPlanes,
598
plane_ptr = Planes[plane], bit_ptr = BitBuffer;
599
count > 0;
600
count -= 2, plane_ptr += 2, bit_ptr ++)
601
{
602
bit = plane_ptr[0];
603
604
bit0 = (unsigned char)(((bit & 64) << 1) | ((bit & 16) << 2) | ((bit & 4) << 3) | ((bit & 1) << 4));
605
bit1 = (unsigned char)((bit & 128) | ((bit & 32) << 1) | ((bit & 8) << 2) | ((bit & 2) << 3));
606
607
if (count > 1)
608
{
609
bit = plane_ptr[1];
610
611
bit0 |= (unsigned char)((bit & 1) | ((bit & 4) >> 1) | ((bit & 16) >> 2) | ((bit & 64) >> 3));
612
bit1 |= (unsigned char)(((bit & 2) >> 1) | ((bit & 8) >> 2) | ((bit & 32) >> 3) | ((bit & 128) >> 4));
613
}
614
615
bit_ptr[0] = bit0;
616
bit_ptr[bytes] = bit1;
617
}
618
619
/*
620
* Send low and high bits...
621
*/
622
623
CompressData(BitBuffer, bytes, 'V', header->cupsCompression);
624
CompressData(BitBuffer + bytes, bytes, plane < (NumPlanes - 1) ? 'V' : 'W',
625
header->cupsCompression);
626
}
627
628
fflush(stdout);
629
}
630
631
632
/*
633
* 'main()' - Main entry and processing of driver.
634
*/
635
636
int /* O - Exit status */
637
main(int argc, /* I - Number of command-line arguments */
638
char *argv[]) /* I - Command-line arguments */
639
{
640
int fd; /* File descriptor */
641
cups_raster_t *ras; /* Raster stream for printing */
642
cups_page_header2_t header; /* Page header from file */
643
unsigned y; /* Current line */
644
ppd_file_t *ppd; /* PPD file */
645
#if defined(HAVE_SIGACTION) && !defined(HAVE_SIGSET)
646
struct sigaction action; /* Actions for POSIX signals */
647
#endif /* HAVE_SIGACTION && !HAVE_SIGSET */
648
649
650
/*
651
* Make sure status messages are not buffered...
652
*/
653
654
setbuf(stderr, NULL);
655
656
/*
657
* Check command-line...
658
*/
659
660
if (argc < 6 || argc > 7)
661
{
662
/*
663
* We don't have the correct number of arguments; write an error message
664
* and return.
665
*/
666
667
_cupsLangPrintFilter(stderr, "ERROR",
668
_("%s job-id user title copies options [file]"),
669
"rastertohp");
670
return (1);
671
}
672
673
/*
674
* Open the page stream...
675
*/
676
677
if (argc == 7)
678
{
679
if ((fd = open(argv[6], O_RDONLY)) == -1)
680
{
681
_cupsLangPrintError("ERROR", _("Unable to open raster file"));
682
sleep(1);
683
return (1);
684
}
685
}
686
else
687
fd = 0;
688
689
ras = cupsRasterOpen(fd, CUPS_RASTER_READ);
690
691
/*
692
* Register a signal handler to eject the current page if the
693
* job is cancelled.
694
*/
695
696
Canceled = 0;
697
698
#ifdef HAVE_SIGSET /* Use System V signals over POSIX to avoid bugs */
699
sigset(SIGTERM, CancelJob);
700
#elif defined(HAVE_SIGACTION)
701
memset(&action, 0, sizeof(action));
702
703
sigemptyset(&action.sa_mask);
704
action.sa_handler = CancelJob;
705
sigaction(SIGTERM, &action, NULL);
706
#else
707
signal(SIGTERM, CancelJob);
708
#endif /* HAVE_SIGSET */
709
710
/*
711
* Initialize the print device...
712
*/
713
714
ppd = ppdOpenFile(getenv("PPD"));
715
if (!ppd)
716
{
717
ppd_status_t status; /* PPD error */
718
int linenum; /* Line number */
719
720
_cupsLangPrintFilter(stderr, "ERROR",
721
_("The PPD file could not be opened."));
722
723
status = ppdLastError(&linenum);
724
725
fprintf(stderr, "DEBUG: %s on line %d.\n", ppdErrorString(status), linenum);
726
727
return (1);
728
}
729
730
Setup();
731
732
/*
733
* Process pages as needed...
734
*/
735
736
Page = 0;
737
738
while (cupsRasterReadHeader2(ras, &header))
739
{
740
/*
741
* Write a status message with the page number and number of copies.
742
*/
743
744
if (Canceled)
745
break;
746
747
Page ++;
748
749
fprintf(stderr, "PAGE: %d %d\n", Page, header.NumCopies);
750
_cupsLangPrintFilter(stderr, "INFO", _("Starting page %d."), Page);
751
752
/*
753
* Start the page...
754
*/
755
756
StartPage(ppd, &header);
757
758
/*
759
* Loop for each line on the page...
760
*/
761
762
for (y = 0; y < header.cupsHeight; y ++)
763
{
764
/*
765
* Let the user know how far we have progressed...
766
*/
767
768
if (Canceled)
769
break;
770
771
if ((y & 127) == 0)
772
{
773
_cupsLangPrintFilter(stderr, "INFO",
774
_("Printing page %d, %u%% complete."),
775
Page, 100 * y / header.cupsHeight);
776
fprintf(stderr, "ATTR: job-media-progress=%u\n",
777
100 * y / header.cupsHeight);
778
}
779
780
/*
781
* Read a line of graphics...
782
*/
783
784
if (cupsRasterReadPixels(ras, Planes[0], header.cupsBytesPerLine) < 1)
785
break;
786
787
/*
788
* See if the line is blank; if not, write it to the printer...
789
*/
790
791
if (Planes[0][0] ||
792
memcmp(Planes[0], Planes[0] + 1, header.cupsBytesPerLine - 1))
793
OutputLine(&header);
794
else
795
Feed ++;
796
}
797
798
/*
799
* Eject the page...
800
*/
801
802
_cupsLangPrintFilter(stderr, "INFO", _("Finished page %d."), Page);
803
804
EndPage();
805
806
if (Canceled)
807
break;
808
}
809
810
/*
811
* Shutdown the printer...
812
*/
813
814
Shutdown();
815
816
ppdClose(ppd);
817
818
/*
819
* Close the raster stream...
820
*/
821
822
cupsRasterClose(ras);
823
if (fd != 0)
824
close(fd);
825
826
/*
827
* If no pages were printed, send an error message...
828
*/
829
830
if (Page == 0)
831
{
832
_cupsLangPrintFilter(stderr, "ERROR", _("No pages were found."));
833
return (1);
834
}
835
else
836
return (0);
837
}
838
839