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