Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
srohatgi01
GitHub Repository: srohatgi01/cups
Path: blob/master/tools/ippevepcl.c
1090 views
1
/*
2
* Generic HP PCL printer command for ippeveprinter/CUPS.
3
*
4
* Copyright © 2019 by Apple Inc.
5
*
6
* Licensed under Apache License v2.0. See the file "LICENSE" for more
7
* information.
8
*/
9
10
/*
11
* Include necessary headers...
12
*/
13
14
#include "ippevecommon.h"
15
#include "dither.h"
16
17
18
/*
19
* Local globals...
20
*/
21
22
static unsigned pcl_bottom, /* Bottom line */
23
pcl_left, /* Left offset in line */
24
pcl_right, /* Right offset in line */
25
pcl_top, /* Top line */
26
pcl_blanks; /* Number of blank lines to skip */
27
static unsigned char pcl_white, /* White color */
28
*pcl_line, /* Line buffer */
29
*pcl_comp; /* Compression buffer */
30
31
/*
32
* Local functions...
33
*/
34
35
static void pcl_end_page(cups_page_header2_t *header, unsigned page);
36
static void pcl_start_page(cups_page_header2_t *header, unsigned page);
37
static int pcl_to_pcl(const char *filename);
38
static void pcl_write_line(cups_page_header2_t *header, unsigned y, const unsigned char *line);
39
static int raster_to_pcl(const char *filename);
40
41
42
/*
43
* 'main()' - Main entry for PCL printer command.
44
*/
45
46
int /* O - Exit status */
47
main(int argc, /* I - Number of command-line arguments */
48
char *argv[]) /* I - Command-line arguments */
49
{
50
const char *content_type; /* Content type to print */
51
52
53
/*
54
* Print it...
55
*/
56
57
if (argc > 2)
58
{
59
fputs("ERROR: Too many arguments supplied, aborting.\n", stderr);
60
return (1);
61
}
62
else if ((content_type = getenv("CONTENT_TYPE")) == NULL)
63
{
64
fputs("ERROR: CONTENT_TYPE environment variable not set, aborting.\n", stderr);
65
return (1);
66
}
67
else if (!strcasecmp(content_type, "application/vnd.hp-pcl"))
68
{
69
return (pcl_to_pcl(argv[1]));
70
}
71
else if (!strcasecmp(content_type, "image/pwg-raster") || !strcasecmp(content_type, "image/urf"))
72
{
73
return (raster_to_pcl(argv[1]));
74
}
75
else
76
{
77
fprintf(stderr, "ERROR: CONTENT_TYPE %s not supported.\n", content_type);
78
return (1);
79
}
80
}
81
82
83
/*
84
* 'pcl_end_page()' - End of PCL page.
85
*/
86
87
static void
88
pcl_end_page(
89
cups_page_header2_t *header, /* I - Page header */
90
unsigned page) /* I - Current page */
91
{
92
/*
93
* End graphics...
94
*/
95
96
fputs("\033*r0B", stdout);
97
98
/*
99
* Formfeed as needed...
100
*/
101
102
if (!(header->Duplex && (page & 1)))
103
putchar('\f');
104
105
/*
106
* Free the output buffers...
107
*/
108
109
free(pcl_line);
110
free(pcl_comp);
111
}
112
113
114
/*
115
* 'pcl_start_page()' - Start a PCL page.
116
*/
117
118
static void
119
pcl_start_page(
120
cups_page_header2_t *header, /* I - Page header */
121
unsigned page) /* I - Current page */
122
{
123
/*
124
* Setup margins to be 1/6" top and bottom and 1/4" or .135" on the
125
* left and right.
126
*/
127
128
pcl_top = header->HWResolution[1] / 6;
129
pcl_bottom = header->cupsHeight - header->HWResolution[1] / 6 - 1;
130
131
if (header->PageSize[1] == 842)
132
{
133
/* A4 gets special side margins to expose an 8" print area */
134
pcl_left = (header->cupsWidth - 8 * header->HWResolution[0]) / 2;
135
pcl_right = pcl_left + 8 * header->HWResolution[0] - 1;
136
}
137
else
138
{
139
/* All other sizes get 1/4" margins */
140
pcl_left = header->HWResolution[0] / 4;
141
pcl_right = header->cupsWidth - header->HWResolution[0] / 4 - 1;
142
}
143
144
if (!header->Duplex || (page & 1))
145
{
146
/*
147
* Set the media size...
148
*/
149
150
printf("\033&l12D\033&k12H"); /* Set 12 LPI, 10 CPI */
151
printf("\033&l0O"); /* Set portrait orientation */
152
153
switch (header->PageSize[1])
154
{
155
case 540 : /* Monarch Envelope */
156
printf("\033&l80A");
157
break;
158
159
case 595 : /* A5 */
160
printf("\033&l25A");
161
break;
162
163
case 624 : /* DL Envelope */
164
printf("\033&l90A");
165
break;
166
167
case 649 : /* C5 Envelope */
168
printf("\033&l91A");
169
break;
170
171
case 684 : /* COM-10 Envelope */
172
printf("\033&l81A");
173
break;
174
175
case 709 : /* B5 Envelope */
176
printf("\033&l100A");
177
break;
178
179
case 756 : /* Executive */
180
printf("\033&l1A");
181
break;
182
183
case 792 : /* Letter */
184
printf("\033&l2A");
185
break;
186
187
case 842 : /* A4 */
188
printf("\033&l26A");
189
break;
190
191
case 1008 : /* Legal */
192
printf("\033&l3A");
193
break;
194
195
case 1191 : /* A3 */
196
printf("\033&l27A");
197
break;
198
199
case 1224 : /* Tabloid */
200
printf("\033&l6A");
201
break;
202
}
203
204
/*
205
* Set top margin and turn off perforation skip...
206
*/
207
208
printf("\033&l%uE\033&l0L", 12 * pcl_top / header->HWResolution[1]);
209
210
if (header->Duplex)
211
{
212
int mode = header->Duplex ? 1 + header->Tumble != 0 : 0;
213
214
printf("\033&l%dS", mode); /* Set duplex mode */
215
}
216
}
217
else if (header->Duplex)
218
printf("\033&a2G"); /* Print on back side */
219
220
/*
221
* Set graphics mode...
222
*/
223
224
printf("\033*t%uR", header->HWResolution[0]);
225
/* Set resolution */
226
printf("\033*r%uS", pcl_right - pcl_left + 1);
227
/* Set width */
228
printf("\033*r%uT", pcl_bottom - pcl_top + 1);
229
/* Set height */
230
printf("\033&a0H\033&a%uV", 720 * pcl_top / header->HWResolution[1]);
231
/* Set position */
232
233
printf("\033*b2M"); /* Use PackBits compression */
234
printf("\033*r1A"); /* Start graphics */
235
236
/*
237
* Allocate the output buffers...
238
*/
239
240
pcl_white = header->cupsBitsPerColor == 1 ? 0 : 255;
241
pcl_blanks = 0;
242
pcl_line = malloc(header->cupsWidth / 8 + 1);
243
pcl_comp = malloc(2 * header->cupsBytesPerLine + 2);
244
245
fprintf(stderr, "ATTR: job-impressions-completed=%d\n", page);
246
}
247
248
249
/*
250
* 'pcl_to_pcl()' - Pass through PCL data.
251
*/
252
253
static int /* O - Exit status */
254
pcl_to_pcl(const char *filename) /* I - File to print or NULL for stdin */
255
{
256
int fd; /* File to read from */
257
char buffer[65536]; /* Copy buffer */
258
ssize_t bytes; /* Bytes to write */
259
260
261
/*
262
* Open the input file...
263
*/
264
265
if (filename)
266
{
267
if ((fd = open(filename, O_RDONLY)) < 0)
268
{
269
fprintf(stderr, "ERROR: Unable to open \"%s\": %s\n", filename, strerror(errno));
270
return (1);
271
}
272
}
273
else
274
{
275
fd = 0;
276
}
277
278
fputs("ATTR: job-impressions=unknown\n", stderr);
279
280
/*
281
* Copy to stdout...
282
*/
283
284
while ((bytes = read(fd, buffer, sizeof(buffer))) > 0)
285
write(1, buffer, (size_t)bytes);
286
287
/*
288
* Close the input file...
289
*/
290
291
if (fd > 0)
292
close(fd);
293
294
return (0);
295
}
296
297
298
/*
299
* 'pcl_write_line()' - Write a line of raster data.
300
*/
301
302
static void
303
pcl_write_line(
304
cups_page_header2_t *header, /* I - Raster information */
305
unsigned y, /* I - Line number */
306
const unsigned char *line) /* I - Pixels on line */
307
{
308
unsigned x; /* Column number */
309
unsigned char bit, /* Current bit */
310
byte, /* Current byte */
311
*outptr, /* Pointer into output buffer */
312
*outend, /* End of output buffer */
313
*start, /* Start of sequence */
314
*compptr; /* Pointer into compression buffer */
315
unsigned count; /* Count of bytes for output */
316
const unsigned char *ditherline; /* Pointer into dither table */
317
318
319
if (line[0] == pcl_white && !memcmp(line, line + 1, header->cupsBytesPerLine - 1))
320
{
321
/*
322
* Skip blank line...
323
*/
324
325
pcl_blanks ++;
326
return;
327
}
328
329
if (header->cupsBitsPerPixel == 1)
330
{
331
/*
332
* B&W bitmap data can be used directly...
333
*/
334
335
outend = (unsigned char *)line + (pcl_right + 7) / 8;
336
outptr = (unsigned char *)line + pcl_left / 8;
337
}
338
else
339
{
340
/*
341
* Dither 8-bit grayscale to B&W...
342
*/
343
344
y &= 63;
345
ditherline = threshold[y];
346
347
for (x = pcl_left, bit = 128, byte = 0, outptr = pcl_line; x <= pcl_right; x ++, line ++)
348
{
349
if (*line <= ditherline[x & 63])
350
byte |= bit;
351
352
if (bit == 1)
353
{
354
*outptr++ = byte;
355
byte = 0;
356
bit = 128;
357
}
358
else
359
bit >>= 1;
360
}
361
362
if (bit != 128)
363
*outptr++ = byte;
364
365
outend = outptr;
366
outptr = pcl_line;
367
}
368
369
/*
370
* Apply compression...
371
*/
372
373
compptr = pcl_comp;
374
375
while (outptr < outend)
376
{
377
if ((outptr + 1) >= outend)
378
{
379
/*
380
* Single byte on the end...
381
*/
382
383
*compptr++ = 0x00;
384
*compptr++ = *outptr++;
385
}
386
else if (outptr[0] == outptr[1])
387
{
388
/*
389
* Repeated sequence...
390
*/
391
392
outptr ++;
393
count = 2;
394
395
while (outptr < (outend - 1) &&
396
outptr[0] == outptr[1] &&
397
count < 127)
398
{
399
outptr ++;
400
count ++;
401
}
402
403
*compptr++ = (unsigned char)(257 - count);
404
*compptr++ = *outptr++;
405
}
406
else
407
{
408
/*
409
* Non-repeated sequence...
410
*/
411
412
start = outptr;
413
outptr ++;
414
count = 1;
415
416
while (outptr < (outend - 1) &&
417
outptr[0] != outptr[1] &&
418
count < 127)
419
{
420
outptr ++;
421
count ++;
422
}
423
424
*compptr++ = (unsigned char)(count - 1);
425
426
memcpy(compptr, start, count);
427
compptr += count;
428
}
429
}
430
431
/*
432
* Output the line...
433
*/
434
435
if (pcl_blanks > 0)
436
{
437
/*
438
* Skip blank lines first...
439
*/
440
441
printf("\033*b%dY", pcl_blanks);
442
pcl_blanks = 0;
443
}
444
445
printf("\033*b%dW", (int)(compptr - pcl_comp));
446
fwrite(pcl_comp, 1, (size_t)(compptr - pcl_comp), stdout);
447
}
448
449
450
/*
451
* 'raster_to_pcl()' - Convert raster data to PCL.
452
*/
453
454
static int /* O - Exit status */
455
raster_to_pcl(const char *filename) /* I - File to print (NULL for stdin) */
456
{
457
int fd; /* Input file */
458
cups_raster_t *ras; /* Raster stream */
459
cups_page_header2_t header; /* Page header */
460
unsigned page = 0, /* Current page */
461
y; /* Current line */
462
unsigned char *line; /* Line buffer */
463
464
465
466
/*
467
* Open the input file...
468
*/
469
470
if (filename)
471
{
472
if ((fd = open(filename, O_RDONLY)) < 0)
473
{
474
fprintf(stderr, "ERROR: Unable to open \"%s\": %s\n", filename, strerror(errno));
475
return (1);
476
}
477
}
478
else
479
{
480
fd = 0;
481
}
482
483
/*
484
* Open the raster stream and send pages...
485
*/
486
487
if ((ras = cupsRasterOpen(fd, CUPS_RASTER_READ)) == NULL)
488
{
489
fputs("ERROR: Unable to read raster data, aborting.\n", stderr);
490
return (1);
491
}
492
493
fputs("\033E", stdout);
494
495
while (cupsRasterReadHeader2(ras, &header))
496
{
497
page ++;
498
499
if (header.cupsColorSpace != CUPS_CSPACE_W && header.cupsColorSpace != CUPS_CSPACE_SW && header.cupsColorSpace != CUPS_CSPACE_K)
500
{
501
fputs("ERROR: Unsupported color space, aborting.\n", stderr);
502
break;
503
}
504
else if (header.cupsBitsPerColor != 1 && header.cupsBitsPerColor != 8)
505
{
506
fputs("ERROR: Unsupported bit depth, aborting.\n", stderr);
507
break;
508
}
509
510
line = malloc(header.cupsBytesPerLine);
511
512
pcl_start_page(&header, page);
513
for (y = 0; y < header.cupsHeight; y ++)
514
{
515
if (cupsRasterReadPixels(ras, line, header.cupsBytesPerLine))
516
pcl_write_line(&header, y, line);
517
else
518
break;
519
}
520
pcl_end_page(&header, page);
521
522
free(line);
523
}
524
525
cupsRasterClose(ras);
526
527
fprintf(stderr, "ATTR: job-impressions=%d\n", page);
528
529
return (0);
530
}
531
532