xref: /aosp_15_r20/external/libcups/cups/raster-stream.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Raster file routines for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright 2007-2019 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  * Copyright 1997-2006 by Easy Software Products.
6*5e7646d2SAndroid Build Coastguard Worker  *
7*5e7646d2SAndroid Build Coastguard Worker  * This file is part of the CUPS Imaging library.
8*5e7646d2SAndroid Build Coastguard Worker  *
9*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
10*5e7646d2SAndroid Build Coastguard Worker  * information.
11*5e7646d2SAndroid Build Coastguard Worker  */
12*5e7646d2SAndroid Build Coastguard Worker 
13*5e7646d2SAndroid Build Coastguard Worker /*
14*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
15*5e7646d2SAndroid Build Coastguard Worker  */
16*5e7646d2SAndroid Build Coastguard Worker 
17*5e7646d2SAndroid Build Coastguard Worker #include "raster-private.h"
18*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
19*5e7646d2SAndroid Build Coastguard Worker #ifdef HAVE_STDINT_H
20*5e7646d2SAndroid Build Coastguard Worker #  include <stdint.h>
21*5e7646d2SAndroid Build Coastguard Worker #endif /* HAVE_STDINT_H */
22*5e7646d2SAndroid Build Coastguard Worker 
23*5e7646d2SAndroid Build Coastguard Worker 
24*5e7646d2SAndroid Build Coastguard Worker /*
25*5e7646d2SAndroid Build Coastguard Worker  * Private structures...
26*5e7646d2SAndroid Build Coastguard Worker  */
27*5e7646d2SAndroid Build Coastguard Worker 
28*5e7646d2SAndroid Build Coastguard Worker typedef void (*_cups_copyfunc_t)(void *dst, const void *src, size_t bytes);
29*5e7646d2SAndroid Build Coastguard Worker 
30*5e7646d2SAndroid Build Coastguard Worker 
31*5e7646d2SAndroid Build Coastguard Worker /*
32*5e7646d2SAndroid Build Coastguard Worker  * Local globals...
33*5e7646d2SAndroid Build Coastguard Worker  */
34*5e7646d2SAndroid Build Coastguard Worker 
35*5e7646d2SAndroid Build Coastguard Worker static const char * const apple_media_types[] =
36*5e7646d2SAndroid Build Coastguard Worker {					/* media-type values for Apple Raster */
37*5e7646d2SAndroid Build Coastguard Worker   "auto",
38*5e7646d2SAndroid Build Coastguard Worker   "stationery",
39*5e7646d2SAndroid Build Coastguard Worker   "transparency",
40*5e7646d2SAndroid Build Coastguard Worker   "envelope",
41*5e7646d2SAndroid Build Coastguard Worker   "cardstock",
42*5e7646d2SAndroid Build Coastguard Worker   "labels",
43*5e7646d2SAndroid Build Coastguard Worker   "stationery-letterhead",
44*5e7646d2SAndroid Build Coastguard Worker   "disc",
45*5e7646d2SAndroid Build Coastguard Worker   "photographic-matte",
46*5e7646d2SAndroid Build Coastguard Worker   "photographic-satin",
47*5e7646d2SAndroid Build Coastguard Worker   "photographic-semi-gloss",
48*5e7646d2SAndroid Build Coastguard Worker   "photographic-glossy",
49*5e7646d2SAndroid Build Coastguard Worker   "photographic-high-gloss",
50*5e7646d2SAndroid Build Coastguard Worker   "other"
51*5e7646d2SAndroid Build Coastguard Worker };
52*5e7646d2SAndroid Build Coastguard Worker 
53*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
54*5e7646d2SAndroid Build Coastguard Worker static const char * const cups_modes[] =
55*5e7646d2SAndroid Build Coastguard Worker {					/* Open modes */
56*5e7646d2SAndroid Build Coastguard Worker   "CUPS_RASTER_READ",
57*5e7646d2SAndroid Build Coastguard Worker   "CUPS_RASTER_WRITE",
58*5e7646d2SAndroid Build Coastguard Worker   "CUPS_RASTER_WRITE_COMPRESSED",
59*5e7646d2SAndroid Build Coastguard Worker   "CUPS_RASTER_WRITE_PWG",
60*5e7646d2SAndroid Build Coastguard Worker   "CUPS_RASTER_WRITE_APPLE"
61*5e7646d2SAndroid Build Coastguard Worker };
62*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
63*5e7646d2SAndroid Build Coastguard Worker 
64*5e7646d2SAndroid Build Coastguard Worker 
65*5e7646d2SAndroid Build Coastguard Worker /*
66*5e7646d2SAndroid Build Coastguard Worker  * Local functions...
67*5e7646d2SAndroid Build Coastguard Worker  */
68*5e7646d2SAndroid Build Coastguard Worker 
69*5e7646d2SAndroid Build Coastguard Worker static ssize_t	cups_raster_io(cups_raster_t *r, unsigned char *buf, size_t bytes);
70*5e7646d2SAndroid Build Coastguard Worker static ssize_t	cups_raster_read(cups_raster_t *r, unsigned char *buf, size_t bytes);
71*5e7646d2SAndroid Build Coastguard Worker static int	cups_raster_update(cups_raster_t *r);
72*5e7646d2SAndroid Build Coastguard Worker static ssize_t	cups_raster_write(cups_raster_t *r, const unsigned char *pixels);
73*5e7646d2SAndroid Build Coastguard Worker static void	cups_swap(unsigned char *buf, size_t bytes);
74*5e7646d2SAndroid Build Coastguard Worker static void	cups_swap_copy(unsigned char *dst, const unsigned char *src, size_t bytes);
75*5e7646d2SAndroid Build Coastguard Worker 
76*5e7646d2SAndroid Build Coastguard Worker 
77*5e7646d2SAndroid Build Coastguard Worker /*
78*5e7646d2SAndroid Build Coastguard Worker  * '_cupsRasterColorSpaceString()' - Return the colorspace name for a
79*5e7646d2SAndroid Build Coastguard Worker  *                                   cupsColorSpace value.
80*5e7646d2SAndroid Build Coastguard Worker  */
81*5e7646d2SAndroid Build Coastguard Worker 
82*5e7646d2SAndroid Build Coastguard Worker const char *
_cupsRasterColorSpaceString(cups_cspace_t cspace)83*5e7646d2SAndroid Build Coastguard Worker _cupsRasterColorSpaceString(
84*5e7646d2SAndroid Build Coastguard Worker     cups_cspace_t cspace)		/* I - cupsColorSpace value */
85*5e7646d2SAndroid Build Coastguard Worker {
86*5e7646d2SAndroid Build Coastguard Worker   static const char * const cups_color_spaces[] =
87*5e7646d2SAndroid Build Coastguard Worker   {					/* Color spaces */
88*5e7646d2SAndroid Build Coastguard Worker     "W",
89*5e7646d2SAndroid Build Coastguard Worker     "RGB",
90*5e7646d2SAndroid Build Coastguard Worker     "RGBA",
91*5e7646d2SAndroid Build Coastguard Worker     "K",
92*5e7646d2SAndroid Build Coastguard Worker     "CMY",
93*5e7646d2SAndroid Build Coastguard Worker     "YMC",
94*5e7646d2SAndroid Build Coastguard Worker     "CMYK",
95*5e7646d2SAndroid Build Coastguard Worker     "YMCK",
96*5e7646d2SAndroid Build Coastguard Worker     "KCMY",
97*5e7646d2SAndroid Build Coastguard Worker     "KCMYcm",
98*5e7646d2SAndroid Build Coastguard Worker     "GMCK",
99*5e7646d2SAndroid Build Coastguard Worker     "GMCS",
100*5e7646d2SAndroid Build Coastguard Worker     "WHITE",
101*5e7646d2SAndroid Build Coastguard Worker     "GOLD",
102*5e7646d2SAndroid Build Coastguard Worker     "SILVER",
103*5e7646d2SAndroid Build Coastguard Worker     "CIEXYZ",
104*5e7646d2SAndroid Build Coastguard Worker     "CIELab",
105*5e7646d2SAndroid Build Coastguard Worker     "RGBW",
106*5e7646d2SAndroid Build Coastguard Worker     "SW",
107*5e7646d2SAndroid Build Coastguard Worker     "SRGB",
108*5e7646d2SAndroid Build Coastguard Worker     "ADOBERGB",
109*5e7646d2SAndroid Build Coastguard Worker     "21",
110*5e7646d2SAndroid Build Coastguard Worker     "22",
111*5e7646d2SAndroid Build Coastguard Worker     "23",
112*5e7646d2SAndroid Build Coastguard Worker     "24",
113*5e7646d2SAndroid Build Coastguard Worker     "25",
114*5e7646d2SAndroid Build Coastguard Worker     "26",
115*5e7646d2SAndroid Build Coastguard Worker     "27",
116*5e7646d2SAndroid Build Coastguard Worker     "28",
117*5e7646d2SAndroid Build Coastguard Worker     "29",
118*5e7646d2SAndroid Build Coastguard Worker     "30",
119*5e7646d2SAndroid Build Coastguard Worker     "31",
120*5e7646d2SAndroid Build Coastguard Worker     "ICC1",
121*5e7646d2SAndroid Build Coastguard Worker     "ICC2",
122*5e7646d2SAndroid Build Coastguard Worker     "ICC3",
123*5e7646d2SAndroid Build Coastguard Worker     "ICC4",
124*5e7646d2SAndroid Build Coastguard Worker     "ICC5",
125*5e7646d2SAndroid Build Coastguard Worker     "ICC6",
126*5e7646d2SAndroid Build Coastguard Worker     "ICC7",
127*5e7646d2SAndroid Build Coastguard Worker     "ICC8",
128*5e7646d2SAndroid Build Coastguard Worker     "ICC9",
129*5e7646d2SAndroid Build Coastguard Worker     "ICCA",
130*5e7646d2SAndroid Build Coastguard Worker     "ICCB",
131*5e7646d2SAndroid Build Coastguard Worker     "ICCC",
132*5e7646d2SAndroid Build Coastguard Worker     "ICCD",
133*5e7646d2SAndroid Build Coastguard Worker     "ICCE",
134*5e7646d2SAndroid Build Coastguard Worker     "ICCF",
135*5e7646d2SAndroid Build Coastguard Worker     "47",
136*5e7646d2SAndroid Build Coastguard Worker     "DEVICE1",
137*5e7646d2SAndroid Build Coastguard Worker     "DEVICE2",
138*5e7646d2SAndroid Build Coastguard Worker     "DEVICE3",
139*5e7646d2SAndroid Build Coastguard Worker     "DEVICE4",
140*5e7646d2SAndroid Build Coastguard Worker     "DEVICE5",
141*5e7646d2SAndroid Build Coastguard Worker     "DEVICE6",
142*5e7646d2SAndroid Build Coastguard Worker     "DEVICE7",
143*5e7646d2SAndroid Build Coastguard Worker     "DEVICE8",
144*5e7646d2SAndroid Build Coastguard Worker     "DEVICE9",
145*5e7646d2SAndroid Build Coastguard Worker     "DEVICEA",
146*5e7646d2SAndroid Build Coastguard Worker     "DEVICEB",
147*5e7646d2SAndroid Build Coastguard Worker     "DEVICEC",
148*5e7646d2SAndroid Build Coastguard Worker     "DEVICED",
149*5e7646d2SAndroid Build Coastguard Worker     "DEVICEE",
150*5e7646d2SAndroid Build Coastguard Worker     "DEVICEF"
151*5e7646d2SAndroid Build Coastguard Worker   };
152*5e7646d2SAndroid Build Coastguard Worker 
153*5e7646d2SAndroid Build Coastguard Worker   if (cspace < CUPS_CSPACE_W || cspace > CUPS_CSPACE_DEVICEF)
154*5e7646d2SAndroid Build Coastguard Worker     return ("Unknown");
155*5e7646d2SAndroid Build Coastguard Worker   else
156*5e7646d2SAndroid Build Coastguard Worker     return (cups_color_spaces[cspace]);
157*5e7646d2SAndroid Build Coastguard Worker }
158*5e7646d2SAndroid Build Coastguard Worker 
159*5e7646d2SAndroid Build Coastguard Worker 
160*5e7646d2SAndroid Build Coastguard Worker /*
161*5e7646d2SAndroid Build Coastguard Worker  * '_cupsRasterDelete()' - Free a raster stream.
162*5e7646d2SAndroid Build Coastguard Worker  *
163*5e7646d2SAndroid Build Coastguard Worker  * The file descriptor associated with the raster stream must be closed
164*5e7646d2SAndroid Build Coastguard Worker  * separately as needed.
165*5e7646d2SAndroid Build Coastguard Worker  */
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker void
_cupsRasterDelete(cups_raster_t * r)168*5e7646d2SAndroid Build Coastguard Worker _cupsRasterDelete(cups_raster_t *r)	/* I - Stream to free */
169*5e7646d2SAndroid Build Coastguard Worker {
170*5e7646d2SAndroid Build Coastguard Worker   if (r != NULL)
171*5e7646d2SAndroid Build Coastguard Worker   {
172*5e7646d2SAndroid Build Coastguard Worker     if (r->buffer)
173*5e7646d2SAndroid Build Coastguard Worker       free(r->buffer);
174*5e7646d2SAndroid Build Coastguard Worker 
175*5e7646d2SAndroid Build Coastguard Worker     if (r->pixels)
176*5e7646d2SAndroid Build Coastguard Worker       free(r->pixels);
177*5e7646d2SAndroid Build Coastguard Worker 
178*5e7646d2SAndroid Build Coastguard Worker     free(r);
179*5e7646d2SAndroid Build Coastguard Worker   }
180*5e7646d2SAndroid Build Coastguard Worker }
181*5e7646d2SAndroid Build Coastguard Worker 
182*5e7646d2SAndroid Build Coastguard Worker 
183*5e7646d2SAndroid Build Coastguard Worker /*
184*5e7646d2SAndroid Build Coastguard Worker  * '_cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output.
185*5e7646d2SAndroid Build Coastguard Worker  *
186*5e7646d2SAndroid Build Coastguard Worker  * The "media" argument specifies the media to use.
187*5e7646d2SAndroid Build Coastguard Worker  *
188*5e7646d2SAndroid Build Coastguard Worker  * The "type" argument specifies a "pwg-raster-document-type-supported" value
189*5e7646d2SAndroid Build Coastguard Worker  * that controls the color space and bit depth of the raster data.
190*5e7646d2SAndroid Build Coastguard Worker  *
191*5e7646d2SAndroid Build Coastguard Worker  * The "xres" and "yres" arguments specify the raster resolution in dots per
192*5e7646d2SAndroid Build Coastguard Worker  * inch.
193*5e7646d2SAndroid Build Coastguard Worker  *
194*5e7646d2SAndroid Build Coastguard Worker  * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value
195*5e7646d2SAndroid Build Coastguard Worker  * to apply for the back side of a page.  Pass @code NULL@ for the front side.
196*5e7646d2SAndroid Build Coastguard Worker  *
197*5e7646d2SAndroid Build Coastguard Worker  * @since CUPS 2.2/macOS 10.12@
198*5e7646d2SAndroid Build Coastguard Worker  */
199*5e7646d2SAndroid Build Coastguard Worker 
200*5e7646d2SAndroid Build Coastguard Worker int					/* O - 1 on success, 0 on failure */
_cupsRasterInitPWGHeader(cups_page_header2_t * h,pwg_media_t * media,const char * type,int xdpi,int ydpi,const char * sides,const char * sheet_back)201*5e7646d2SAndroid Build Coastguard Worker _cupsRasterInitPWGHeader(
202*5e7646d2SAndroid Build Coastguard Worker     cups_page_header2_t *h,		/* I - Page header */
203*5e7646d2SAndroid Build Coastguard Worker     pwg_media_t         *media,		/* I - PWG media information */
204*5e7646d2SAndroid Build Coastguard Worker     const char          *type,		/* I - PWG raster type string */
205*5e7646d2SAndroid Build Coastguard Worker     int                 xdpi,		/* I - Cross-feed direction (horizontal) resolution */
206*5e7646d2SAndroid Build Coastguard Worker     int                 ydpi,		/* I - Feed direction (vertical) resolution */
207*5e7646d2SAndroid Build Coastguard Worker     const char          *sides,		/* I - IPP "sides" option value */
208*5e7646d2SAndroid Build Coastguard Worker     const char          *sheet_back)	/* I - Transform for back side or @code NULL@ for none */
209*5e7646d2SAndroid Build Coastguard Worker {
210*5e7646d2SAndroid Build Coastguard Worker   if (!h || !media || !type || xdpi <= 0 || ydpi <= 0)
211*5e7646d2SAndroid Build Coastguard Worker   {
212*5e7646d2SAndroid Build Coastguard Worker     _cupsRasterAddError("%s", strerror(EINVAL));
213*5e7646d2SAndroid Build Coastguard Worker     return (0);
214*5e7646d2SAndroid Build Coastguard Worker   }
215*5e7646d2SAndroid Build Coastguard Worker 
216*5e7646d2SAndroid Build Coastguard Worker  /*
217*5e7646d2SAndroid Build Coastguard Worker   * Initialize the page header...
218*5e7646d2SAndroid Build Coastguard Worker   */
219*5e7646d2SAndroid Build Coastguard Worker 
220*5e7646d2SAndroid Build Coastguard Worker   memset(h, 0, sizeof(cups_page_header2_t));
221*5e7646d2SAndroid Build Coastguard Worker 
222*5e7646d2SAndroid Build Coastguard Worker   strlcpy(h->cupsPageSizeName, media->pwg, sizeof(h->cupsPageSizeName));
223*5e7646d2SAndroid Build Coastguard Worker 
224*5e7646d2SAndroid Build Coastguard Worker   h->PageSize[0] = (unsigned)(72 * media->width / 2540);
225*5e7646d2SAndroid Build Coastguard Worker   h->PageSize[1] = (unsigned)(72 * media->length / 2540);
226*5e7646d2SAndroid Build Coastguard Worker 
227*5e7646d2SAndroid Build Coastguard Worker   /* This never gets written but is needed for some applications */
228*5e7646d2SAndroid Build Coastguard Worker   h->cupsPageSize[0] = 72.0f * media->width / 2540.0f;
229*5e7646d2SAndroid Build Coastguard Worker   h->cupsPageSize[1] = 72.0f * media->length / 2540.0f;
230*5e7646d2SAndroid Build Coastguard Worker 
231*5e7646d2SAndroid Build Coastguard Worker   h->ImagingBoundingBox[2] = h->PageSize[0];
232*5e7646d2SAndroid Build Coastguard Worker   h->ImagingBoundingBox[3] = h->PageSize[1];
233*5e7646d2SAndroid Build Coastguard Worker 
234*5e7646d2SAndroid Build Coastguard Worker   h->HWResolution[0] = (unsigned)xdpi;
235*5e7646d2SAndroid Build Coastguard Worker   h->HWResolution[1] = (unsigned)ydpi;
236*5e7646d2SAndroid Build Coastguard Worker 
237*5e7646d2SAndroid Build Coastguard Worker   h->cupsWidth  = (unsigned)(media->width * xdpi / 2540);
238*5e7646d2SAndroid Build Coastguard Worker   h->cupsHeight = (unsigned)(media->length * ydpi / 2540);
239*5e7646d2SAndroid Build Coastguard Worker 
240*5e7646d2SAndroid Build Coastguard Worker   if (h->cupsWidth > 0x00ffffff || h->cupsHeight > 0x00ffffff)
241*5e7646d2SAndroid Build Coastguard Worker   {
242*5e7646d2SAndroid Build Coastguard Worker     _cupsRasterAddError("Raster dimensions too large.");
243*5e7646d2SAndroid Build Coastguard Worker     return (0);
244*5e7646d2SAndroid Build Coastguard Worker   }
245*5e7646d2SAndroid Build Coastguard Worker 
246*5e7646d2SAndroid Build Coastguard Worker   h->cupsInteger[CUPS_RASTER_PWG_ImageBoxRight]  = h->cupsWidth;
247*5e7646d2SAndroid Build Coastguard Worker   h->cupsInteger[CUPS_RASTER_PWG_ImageBoxBottom] = h->cupsHeight;
248*5e7646d2SAndroid Build Coastguard Worker 
249*5e7646d2SAndroid Build Coastguard Worker  /*
250*5e7646d2SAndroid Build Coastguard Worker   * Colorspace and bytes per line...
251*5e7646d2SAndroid Build Coastguard Worker   */
252*5e7646d2SAndroid Build Coastguard Worker 
253*5e7646d2SAndroid Build Coastguard Worker   if (!strcmp(type, "adobe-rgb_8"))
254*5e7646d2SAndroid Build Coastguard Worker   {
255*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 8;
256*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 24;
257*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_ADOBERGB;
258*5e7646d2SAndroid Build Coastguard Worker   }
259*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "adobe-rgb_16"))
260*5e7646d2SAndroid Build Coastguard Worker   {
261*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 16;
262*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 48;
263*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_ADOBERGB;
264*5e7646d2SAndroid Build Coastguard Worker   }
265*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "black_1"))
266*5e7646d2SAndroid Build Coastguard Worker   {
267*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 1;
268*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 1;
269*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_K;
270*5e7646d2SAndroid Build Coastguard Worker   }
271*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "black_8"))
272*5e7646d2SAndroid Build Coastguard Worker   {
273*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 8;
274*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 8;
275*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_K;
276*5e7646d2SAndroid Build Coastguard Worker   }
277*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "black_16"))
278*5e7646d2SAndroid Build Coastguard Worker   {
279*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 16;
280*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 16;
281*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_K;
282*5e7646d2SAndroid Build Coastguard Worker   }
283*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "cmyk_8"))
284*5e7646d2SAndroid Build Coastguard Worker   {
285*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 8;
286*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 32;
287*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_CMYK;
288*5e7646d2SAndroid Build Coastguard Worker   }
289*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "cmyk_16"))
290*5e7646d2SAndroid Build Coastguard Worker   {
291*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 16;
292*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 64;
293*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_CMYK;
294*5e7646d2SAndroid Build Coastguard Worker   }
295*5e7646d2SAndroid Build Coastguard Worker   else if (!strncmp(type, "device", 6) && type[6] >= '1' && type[6] <= '9')
296*5e7646d2SAndroid Build Coastguard Worker   {
297*5e7646d2SAndroid Build Coastguard Worker     int ncolors, bits;			/* Number of colors and bits */
298*5e7646d2SAndroid Build Coastguard Worker 
299*5e7646d2SAndroid Build Coastguard Worker 
300*5e7646d2SAndroid Build Coastguard Worker     if (sscanf(type, "device%d_%d", &ncolors, &bits) != 2 || ncolors > 15 || (bits != 8 && bits != 16))
301*5e7646d2SAndroid Build Coastguard Worker     {
302*5e7646d2SAndroid Build Coastguard Worker       _cupsRasterAddError("Unsupported raster type \'%s\'.", type);
303*5e7646d2SAndroid Build Coastguard Worker       return (0);
304*5e7646d2SAndroid Build Coastguard Worker     }
305*5e7646d2SAndroid Build Coastguard Worker 
306*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = (unsigned)bits;
307*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = (unsigned)(ncolors * bits);
308*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = (cups_cspace_t)(CUPS_CSPACE_DEVICE1 + ncolors - 1);
309*5e7646d2SAndroid Build Coastguard Worker   }
310*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "rgb_8"))
311*5e7646d2SAndroid Build Coastguard Worker   {
312*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 8;
313*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 24;
314*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_RGB;
315*5e7646d2SAndroid Build Coastguard Worker   }
316*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "rgb_16"))
317*5e7646d2SAndroid Build Coastguard Worker   {
318*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 16;
319*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 48;
320*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_RGB;
321*5e7646d2SAndroid Build Coastguard Worker   }
322*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "sgray_1"))
323*5e7646d2SAndroid Build Coastguard Worker   {
324*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 1;
325*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 1;
326*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_SW;
327*5e7646d2SAndroid Build Coastguard Worker   }
328*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "sgray_8"))
329*5e7646d2SAndroid Build Coastguard Worker   {
330*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 8;
331*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 8;
332*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_SW;
333*5e7646d2SAndroid Build Coastguard Worker   }
334*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "sgray_16"))
335*5e7646d2SAndroid Build Coastguard Worker   {
336*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 16;
337*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 16;
338*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_SW;
339*5e7646d2SAndroid Build Coastguard Worker   }
340*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "srgb_8"))
341*5e7646d2SAndroid Build Coastguard Worker   {
342*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 8;
343*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 24;
344*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_SRGB;
345*5e7646d2SAndroid Build Coastguard Worker   }
346*5e7646d2SAndroid Build Coastguard Worker   else if (!strcmp(type, "srgb_16"))
347*5e7646d2SAndroid Build Coastguard Worker   {
348*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerColor = 16;
349*5e7646d2SAndroid Build Coastguard Worker     h->cupsBitsPerPixel = 48;
350*5e7646d2SAndroid Build Coastguard Worker     h->cupsColorSpace   = CUPS_CSPACE_SRGB;
351*5e7646d2SAndroid Build Coastguard Worker   }
352*5e7646d2SAndroid Build Coastguard Worker   else
353*5e7646d2SAndroid Build Coastguard Worker   {
354*5e7646d2SAndroid Build Coastguard Worker     _cupsRasterAddError("Unsupported raster type \'%s\'.", type);
355*5e7646d2SAndroid Build Coastguard Worker     return (0);
356*5e7646d2SAndroid Build Coastguard Worker   }
357*5e7646d2SAndroid Build Coastguard Worker 
358*5e7646d2SAndroid Build Coastguard Worker   h->cupsColorOrder   = CUPS_ORDER_CHUNKED;
359*5e7646d2SAndroid Build Coastguard Worker   h->cupsNumColors    = h->cupsBitsPerPixel / h->cupsBitsPerColor;
360*5e7646d2SAndroid Build Coastguard Worker   h->cupsBytesPerLine = (h->cupsWidth * h->cupsBitsPerPixel + 7) / 8;
361*5e7646d2SAndroid Build Coastguard Worker 
362*5e7646d2SAndroid Build Coastguard Worker  /*
363*5e7646d2SAndroid Build Coastguard Worker   * Duplex support...
364*5e7646d2SAndroid Build Coastguard Worker   */
365*5e7646d2SAndroid Build Coastguard Worker 
366*5e7646d2SAndroid Build Coastguard Worker   h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 1;
367*5e7646d2SAndroid Build Coastguard Worker   h->cupsInteger[CUPS_RASTER_PWG_FeedTransform]      = 1;
368*5e7646d2SAndroid Build Coastguard Worker 
369*5e7646d2SAndroid Build Coastguard Worker   if (sides)
370*5e7646d2SAndroid Build Coastguard Worker   {
371*5e7646d2SAndroid Build Coastguard Worker     if (!strcmp(sides, "two-sided-long-edge"))
372*5e7646d2SAndroid Build Coastguard Worker     {
373*5e7646d2SAndroid Build Coastguard Worker       h->Duplex = 1;
374*5e7646d2SAndroid Build Coastguard Worker     }
375*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(sides, "two-sided-short-edge"))
376*5e7646d2SAndroid Build Coastguard Worker     {
377*5e7646d2SAndroid Build Coastguard Worker       h->Duplex = 1;
378*5e7646d2SAndroid Build Coastguard Worker       h->Tumble = 1;
379*5e7646d2SAndroid Build Coastguard Worker     }
380*5e7646d2SAndroid Build Coastguard Worker     else if (strcmp(sides, "one-sided"))
381*5e7646d2SAndroid Build Coastguard Worker     {
382*5e7646d2SAndroid Build Coastguard Worker       _cupsRasterAddError("Unsupported sides value \'%s\'.", sides);
383*5e7646d2SAndroid Build Coastguard Worker       return (0);
384*5e7646d2SAndroid Build Coastguard Worker     }
385*5e7646d2SAndroid Build Coastguard Worker 
386*5e7646d2SAndroid Build Coastguard Worker     if (sheet_back)
387*5e7646d2SAndroid Build Coastguard Worker     {
388*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(sheet_back, "flipped"))
389*5e7646d2SAndroid Build Coastguard Worker       {
390*5e7646d2SAndroid Build Coastguard Worker         if (h->Tumble)
391*5e7646d2SAndroid Build Coastguard Worker           h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU;
392*5e7646d2SAndroid Build Coastguard Worker         else
393*5e7646d2SAndroid Build Coastguard Worker           h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 0xffffffffU;
394*5e7646d2SAndroid Build Coastguard Worker       }
395*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(sheet_back, "manual-tumble"))
396*5e7646d2SAndroid Build Coastguard Worker       {
397*5e7646d2SAndroid Build Coastguard Worker         if (h->Tumble)
398*5e7646d2SAndroid Build Coastguard Worker         {
399*5e7646d2SAndroid Build Coastguard Worker           h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU;
400*5e7646d2SAndroid Build Coastguard Worker           h->cupsInteger[CUPS_RASTER_PWG_FeedTransform]      = 0xffffffffU;
401*5e7646d2SAndroid Build Coastguard Worker         }
402*5e7646d2SAndroid Build Coastguard Worker       }
403*5e7646d2SAndroid Build Coastguard Worker       else if (!strcmp(sheet_back, "rotated"))
404*5e7646d2SAndroid Build Coastguard Worker       {
405*5e7646d2SAndroid Build Coastguard Worker         if (!h->Tumble)
406*5e7646d2SAndroid Build Coastguard Worker         {
407*5e7646d2SAndroid Build Coastguard Worker           h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU;
408*5e7646d2SAndroid Build Coastguard Worker           h->cupsInteger[CUPS_RASTER_PWG_FeedTransform]      = 0xffffffffU;
409*5e7646d2SAndroid Build Coastguard Worker         }
410*5e7646d2SAndroid Build Coastguard Worker       }
411*5e7646d2SAndroid Build Coastguard Worker       else if (strcmp(sheet_back, "normal"))
412*5e7646d2SAndroid Build Coastguard Worker       {
413*5e7646d2SAndroid Build Coastguard Worker 	_cupsRasterAddError("Unsupported sheet_back value \'%s\'.", sheet_back);
414*5e7646d2SAndroid Build Coastguard Worker 	return (0);
415*5e7646d2SAndroid Build Coastguard Worker       }
416*5e7646d2SAndroid Build Coastguard Worker     }
417*5e7646d2SAndroid Build Coastguard Worker   }
418*5e7646d2SAndroid Build Coastguard Worker 
419*5e7646d2SAndroid Build Coastguard Worker   return (1);
420*5e7646d2SAndroid Build Coastguard Worker }
421*5e7646d2SAndroid Build Coastguard Worker 
422*5e7646d2SAndroid Build Coastguard Worker 
423*5e7646d2SAndroid Build Coastguard Worker /*
424*5e7646d2SAndroid Build Coastguard Worker  * '_cupsRasterNew()' - Create a raster stream using a callback function.
425*5e7646d2SAndroid Build Coastguard Worker  *
426*5e7646d2SAndroid Build Coastguard Worker  * This function associates a raster stream with the given callback function and
427*5e7646d2SAndroid Build Coastguard Worker  * context pointer.
428*5e7646d2SAndroid Build Coastguard Worker  *
429*5e7646d2SAndroid Build Coastguard Worker  * When writing raster data, the @code CUPS_RASTER_WRITE@,
430*5e7646d2SAndroid Build Coastguard Worker  * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
431*5e7646d2SAndroid Build Coastguard Worker  * be used - compressed and PWG output is generally 25-50% smaller but adds a
432*5e7646d2SAndroid Build Coastguard Worker  * 100-300% execution time overhead.
433*5e7646d2SAndroid Build Coastguard Worker  */
434*5e7646d2SAndroid Build Coastguard Worker 
435*5e7646d2SAndroid Build Coastguard Worker cups_raster_t *				/* O - New stream */
_cupsRasterNew(cups_raster_iocb_t iocb,void * ctx,cups_mode_t mode)436*5e7646d2SAndroid Build Coastguard Worker _cupsRasterNew(
437*5e7646d2SAndroid Build Coastguard Worker     cups_raster_iocb_t iocb,		/* I - Read/write callback */
438*5e7646d2SAndroid Build Coastguard Worker     void               *ctx,		/* I - Context pointer for callback */
439*5e7646d2SAndroid Build Coastguard Worker     cups_mode_t        mode)		/* I - Mode - @code CUPS_RASTER_READ@,
440*5e7646d2SAndroid Build Coastguard Worker 	                                       @code CUPS_RASTER_WRITE@,
441*5e7646d2SAndroid Build Coastguard Worker 					       @code CUPS_RASTER_WRITE_COMPRESSED@,
442*5e7646d2SAndroid Build Coastguard Worker 					       or @code CUPS_RASTER_WRITE_PWG@ */
443*5e7646d2SAndroid Build Coastguard Worker {
444*5e7646d2SAndroid Build Coastguard Worker   cups_raster_t	*r;			/* New stream */
445*5e7646d2SAndroid Build Coastguard Worker 
446*5e7646d2SAndroid Build Coastguard Worker 
447*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_cupsRasterOpenIO(iocb=%p, ctx=%p, mode=%s)", (void *)iocb, ctx, cups_modes[mode]));
448*5e7646d2SAndroid Build Coastguard Worker 
449*5e7646d2SAndroid Build Coastguard Worker   _cupsRasterClearError();
450*5e7646d2SAndroid Build Coastguard Worker 
451*5e7646d2SAndroid Build Coastguard Worker   if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
452*5e7646d2SAndroid Build Coastguard Worker   {
453*5e7646d2SAndroid Build Coastguard Worker     _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
454*5e7646d2SAndroid Build Coastguard Worker                         strerror(errno));
455*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1_cupsRasterOpenIO: Returning NULL.");
456*5e7646d2SAndroid Build Coastguard Worker     return (NULL);
457*5e7646d2SAndroid Build Coastguard Worker   }
458*5e7646d2SAndroid Build Coastguard Worker 
459*5e7646d2SAndroid Build Coastguard Worker   r->ctx  = ctx;
460*5e7646d2SAndroid Build Coastguard Worker   r->iocb = iocb;
461*5e7646d2SAndroid Build Coastguard Worker   r->mode = mode;
462*5e7646d2SAndroid Build Coastguard Worker 
463*5e7646d2SAndroid Build Coastguard Worker   if (mode == CUPS_RASTER_READ)
464*5e7646d2SAndroid Build Coastguard Worker   {
465*5e7646d2SAndroid Build Coastguard Worker    /*
466*5e7646d2SAndroid Build Coastguard Worker     * Open for read - get sync word...
467*5e7646d2SAndroid Build Coastguard Worker     */
468*5e7646d2SAndroid Build Coastguard Worker 
469*5e7646d2SAndroid Build Coastguard Worker     if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) !=
470*5e7646d2SAndroid Build Coastguard Worker             sizeof(r->sync))
471*5e7646d2SAndroid Build Coastguard Worker     {
472*5e7646d2SAndroid Build Coastguard Worker       _cupsRasterAddError("Unable to read header from raster stream: %s\n",
473*5e7646d2SAndroid Build Coastguard Worker                           strerror(errno));
474*5e7646d2SAndroid Build Coastguard Worker       free(r);
475*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("1_cupsRasterOpenIO: Unable to read header, returning NULL.");
476*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
477*5e7646d2SAndroid Build Coastguard Worker     }
478*5e7646d2SAndroid Build Coastguard Worker 
479*5e7646d2SAndroid Build Coastguard Worker     if (r->sync != CUPS_RASTER_SYNC &&
480*5e7646d2SAndroid Build Coastguard Worker         r->sync != CUPS_RASTER_REVSYNC &&
481*5e7646d2SAndroid Build Coastguard Worker         r->sync != CUPS_RASTER_SYNCv1 &&
482*5e7646d2SAndroid Build Coastguard Worker         r->sync != CUPS_RASTER_REVSYNCv1 &&
483*5e7646d2SAndroid Build Coastguard Worker         r->sync != CUPS_RASTER_SYNCv2 &&
484*5e7646d2SAndroid Build Coastguard Worker         r->sync != CUPS_RASTER_REVSYNCv2 &&
485*5e7646d2SAndroid Build Coastguard Worker         r->sync != CUPS_RASTER_SYNCapple &&
486*5e7646d2SAndroid Build Coastguard Worker         r->sync != CUPS_RASTER_REVSYNCapple)
487*5e7646d2SAndroid Build Coastguard Worker     {
488*5e7646d2SAndroid Build Coastguard Worker       _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
489*5e7646d2SAndroid Build Coastguard Worker       free(r);
490*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("1_cupsRasterOpenIO: Unknown format, returning NULL.");
491*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
492*5e7646d2SAndroid Build Coastguard Worker     }
493*5e7646d2SAndroid Build Coastguard Worker 
494*5e7646d2SAndroid Build Coastguard Worker     if (r->sync == CUPS_RASTER_SYNCv2 ||
495*5e7646d2SAndroid Build Coastguard Worker         r->sync == CUPS_RASTER_REVSYNCv2 ||
496*5e7646d2SAndroid Build Coastguard Worker         r->sync == CUPS_RASTER_SYNCapple ||
497*5e7646d2SAndroid Build Coastguard Worker         r->sync == CUPS_RASTER_REVSYNCapple)
498*5e7646d2SAndroid Build Coastguard Worker       r->compressed = 1;
499*5e7646d2SAndroid Build Coastguard Worker 
500*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1_cupsRasterOpenIO: sync=%08x", r->sync));
501*5e7646d2SAndroid Build Coastguard Worker 
502*5e7646d2SAndroid Build Coastguard Worker     if (r->sync == CUPS_RASTER_REVSYNC ||
503*5e7646d2SAndroid Build Coastguard Worker         r->sync == CUPS_RASTER_REVSYNCv1 ||
504*5e7646d2SAndroid Build Coastguard Worker         r->sync == CUPS_RASTER_REVSYNCv2 ||
505*5e7646d2SAndroid Build Coastguard Worker         r->sync == CUPS_RASTER_REVSYNCapple)
506*5e7646d2SAndroid Build Coastguard Worker       r->swapped = 1;
507*5e7646d2SAndroid Build Coastguard Worker 
508*5e7646d2SAndroid Build Coastguard Worker     if (r->sync == CUPS_RASTER_SYNCapple ||
509*5e7646d2SAndroid Build Coastguard Worker         r->sync == CUPS_RASTER_REVSYNCapple)
510*5e7646d2SAndroid Build Coastguard Worker     {
511*5e7646d2SAndroid Build Coastguard Worker       unsigned char	header[8];	/* File header */
512*5e7646d2SAndroid Build Coastguard Worker 
513*5e7646d2SAndroid Build Coastguard Worker       if (cups_raster_io(r, (unsigned char *)header, sizeof(header)) !=
514*5e7646d2SAndroid Build Coastguard Worker 	      sizeof(header))
515*5e7646d2SAndroid Build Coastguard Worker       {
516*5e7646d2SAndroid Build Coastguard Worker 	_cupsRasterAddError("Unable to read header from raster stream: %s\n",
517*5e7646d2SAndroid Build Coastguard Worker 			    strerror(errno));
518*5e7646d2SAndroid Build Coastguard Worker 	free(r);
519*5e7646d2SAndroid Build Coastguard Worker 	DEBUG_puts("1_cupsRasterOpenIO: Unable to read header, returning NULL.");
520*5e7646d2SAndroid Build Coastguard Worker 	return (NULL);
521*5e7646d2SAndroid Build Coastguard Worker       }
522*5e7646d2SAndroid Build Coastguard Worker     }
523*5e7646d2SAndroid Build Coastguard Worker 
524*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
525*5e7646d2SAndroid Build Coastguard Worker     r->iostart = r->iocount;
526*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
527*5e7646d2SAndroid Build Coastguard Worker   }
528*5e7646d2SAndroid Build Coastguard Worker   else
529*5e7646d2SAndroid Build Coastguard Worker   {
530*5e7646d2SAndroid Build Coastguard Worker    /*
531*5e7646d2SAndroid Build Coastguard Worker     * Open for write - put sync word...
532*5e7646d2SAndroid Build Coastguard Worker     */
533*5e7646d2SAndroid Build Coastguard Worker 
534*5e7646d2SAndroid Build Coastguard Worker     switch (mode)
535*5e7646d2SAndroid Build Coastguard Worker     {
536*5e7646d2SAndroid Build Coastguard Worker       default :
537*5e7646d2SAndroid Build Coastguard Worker       case CUPS_RASTER_WRITE :
538*5e7646d2SAndroid Build Coastguard Worker           r->sync = CUPS_RASTER_SYNC;
539*5e7646d2SAndroid Build Coastguard Worker 	  break;
540*5e7646d2SAndroid Build Coastguard Worker 
541*5e7646d2SAndroid Build Coastguard Worker       case CUPS_RASTER_WRITE_COMPRESSED :
542*5e7646d2SAndroid Build Coastguard Worker           r->compressed = 1;
543*5e7646d2SAndroid Build Coastguard Worker           r->sync       = CUPS_RASTER_SYNCv2;
544*5e7646d2SAndroid Build Coastguard Worker 	  break;
545*5e7646d2SAndroid Build Coastguard Worker 
546*5e7646d2SAndroid Build Coastguard Worker       case CUPS_RASTER_WRITE_PWG :
547*5e7646d2SAndroid Build Coastguard Worker           r->compressed = 1;
548*5e7646d2SAndroid Build Coastguard Worker           r->sync       = htonl(CUPS_RASTER_SYNC_PWG);
549*5e7646d2SAndroid Build Coastguard Worker           r->swapped    = r->sync != CUPS_RASTER_SYNC_PWG;
550*5e7646d2SAndroid Build Coastguard Worker 	  break;
551*5e7646d2SAndroid Build Coastguard Worker 
552*5e7646d2SAndroid Build Coastguard Worker       case CUPS_RASTER_WRITE_APPLE :
553*5e7646d2SAndroid Build Coastguard Worker           r->compressed     = 1;
554*5e7646d2SAndroid Build Coastguard Worker           r->sync           = htonl(CUPS_RASTER_SYNCapple);
555*5e7646d2SAndroid Build Coastguard Worker           r->swapped        = r->sync != CUPS_RASTER_SYNCapple;
556*5e7646d2SAndroid Build Coastguard Worker           r->apple_page_count = 0xffffffffU;
557*5e7646d2SAndroid Build Coastguard Worker 	  break;
558*5e7646d2SAndroid Build Coastguard Worker     }
559*5e7646d2SAndroid Build Coastguard Worker 
560*5e7646d2SAndroid Build Coastguard Worker     if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) < (ssize_t)sizeof(r->sync))
561*5e7646d2SAndroid Build Coastguard Worker     {
562*5e7646d2SAndroid Build Coastguard Worker       _cupsRasterAddError("Unable to write raster stream header: %s\n",
563*5e7646d2SAndroid Build Coastguard Worker                           strerror(errno));
564*5e7646d2SAndroid Build Coastguard Worker       free(r);
565*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("1_cupsRasterOpenIO: Unable to write header, returning NULL.");
566*5e7646d2SAndroid Build Coastguard Worker       return (NULL);
567*5e7646d2SAndroid Build Coastguard Worker     }
568*5e7646d2SAndroid Build Coastguard Worker   }
569*5e7646d2SAndroid Build Coastguard Worker 
570*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_cupsRasterOpenIO: compressed=%d, swapped=%d, returning %p", r->compressed, r->swapped, (void *)r));
571*5e7646d2SAndroid Build Coastguard Worker 
572*5e7646d2SAndroid Build Coastguard Worker   return (r);
573*5e7646d2SAndroid Build Coastguard Worker }
574*5e7646d2SAndroid Build Coastguard Worker 
575*5e7646d2SAndroid Build Coastguard Worker 
576*5e7646d2SAndroid Build Coastguard Worker /*
577*5e7646d2SAndroid Build Coastguard Worker  * '_cupsRasterReadHeader()' - Read a raster page header.
578*5e7646d2SAndroid Build Coastguard Worker  */
579*5e7646d2SAndroid Build Coastguard Worker 
580*5e7646d2SAndroid Build Coastguard Worker unsigned				/* O - 1 on success, 0 on fail */
_cupsRasterReadHeader(cups_raster_t * r)581*5e7646d2SAndroid Build Coastguard Worker _cupsRasterReadHeader(
582*5e7646d2SAndroid Build Coastguard Worker     cups_raster_t *r)			/* I - Raster stream */
583*5e7646d2SAndroid Build Coastguard Worker {
584*5e7646d2SAndroid Build Coastguard Worker   size_t	len;			/* Length for read/swap */
585*5e7646d2SAndroid Build Coastguard Worker 
586*5e7646d2SAndroid Build Coastguard Worker 
587*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("3_cupsRasterReadHeader(r=%p), r->mode=%s", (void *)r, r ? cups_modes[r->mode] : ""));
588*5e7646d2SAndroid Build Coastguard Worker 
589*5e7646d2SAndroid Build Coastguard Worker   if (r == NULL || r->mode != CUPS_RASTER_READ)
590*5e7646d2SAndroid Build Coastguard Worker     return (0);
591*5e7646d2SAndroid Build Coastguard Worker 
592*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4_cupsRasterReadHeader: r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
593*5e7646d2SAndroid Build Coastguard Worker 
594*5e7646d2SAndroid Build Coastguard Worker   memset(&(r->header), 0, sizeof(r->header));
595*5e7646d2SAndroid Build Coastguard Worker 
596*5e7646d2SAndroid Build Coastguard Worker  /*
597*5e7646d2SAndroid Build Coastguard Worker   * Read the header...
598*5e7646d2SAndroid Build Coastguard Worker   */
599*5e7646d2SAndroid Build Coastguard Worker 
600*5e7646d2SAndroid Build Coastguard Worker   switch (r->sync)
601*5e7646d2SAndroid Build Coastguard Worker   {
602*5e7646d2SAndroid Build Coastguard Worker     default :
603*5e7646d2SAndroid Build Coastguard Worker        /*
604*5e7646d2SAndroid Build Coastguard Worker 	* Get the length of the raster header...
605*5e7646d2SAndroid Build Coastguard Worker 	*/
606*5e7646d2SAndroid Build Coastguard Worker 
607*5e7646d2SAndroid Build Coastguard Worker 	if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
608*5e7646d2SAndroid Build Coastguard Worker 	  len = sizeof(cups_page_header_t);
609*5e7646d2SAndroid Build Coastguard Worker 	else
610*5e7646d2SAndroid Build Coastguard Worker 	  len = sizeof(cups_page_header2_t);
611*5e7646d2SAndroid Build Coastguard Worker 
612*5e7646d2SAndroid Build Coastguard Worker 	DEBUG_printf(("4_cupsRasterReadHeader: len=%d", (int)len));
613*5e7646d2SAndroid Build Coastguard Worker 
614*5e7646d2SAndroid Build Coastguard Worker        /*
615*5e7646d2SAndroid Build Coastguard Worker         * Read it...
616*5e7646d2SAndroid Build Coastguard Worker         */
617*5e7646d2SAndroid Build Coastguard Worker 
618*5e7646d2SAndroid Build Coastguard Worker 	if (cups_raster_read(r, (unsigned char *)&(r->header), len) < (ssize_t)len)
619*5e7646d2SAndroid Build Coastguard Worker 	{
620*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_printf(("4_cupsRasterReadHeader: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
621*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
622*5e7646d2SAndroid Build Coastguard Worker 	}
623*5e7646d2SAndroid Build Coastguard Worker 
624*5e7646d2SAndroid Build Coastguard Worker        /*
625*5e7646d2SAndroid Build Coastguard Worker 	* Swap bytes as needed...
626*5e7646d2SAndroid Build Coastguard Worker 	*/
627*5e7646d2SAndroid Build Coastguard Worker 
628*5e7646d2SAndroid Build Coastguard Worker 	if (r->swapped)
629*5e7646d2SAndroid Build Coastguard Worker 	{
630*5e7646d2SAndroid Build Coastguard Worker 	  unsigned	*s,		/* Current word */
631*5e7646d2SAndroid Build Coastguard Worker 			temp;		/* Temporary copy */
632*5e7646d2SAndroid Build Coastguard Worker 
633*5e7646d2SAndroid Build Coastguard Worker 
634*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_puts("4_cupsRasterReadHeader: Swapping header bytes.");
635*5e7646d2SAndroid Build Coastguard Worker 
636*5e7646d2SAndroid Build Coastguard Worker 	  for (len = 81, s = &(r->header.AdvanceDistance);
637*5e7646d2SAndroid Build Coastguard Worker 	       len > 0;
638*5e7646d2SAndroid Build Coastguard Worker 	       len --, s ++)
639*5e7646d2SAndroid Build Coastguard Worker 	  {
640*5e7646d2SAndroid Build Coastguard Worker 	    temp = *s;
641*5e7646d2SAndroid Build Coastguard Worker 	    *s   = ((temp & 0xff) << 24) |
642*5e7646d2SAndroid Build Coastguard Worker 		   ((temp & 0xff00) << 8) |
643*5e7646d2SAndroid Build Coastguard Worker 		   ((temp & 0xff0000) >> 8) |
644*5e7646d2SAndroid Build Coastguard Worker 		   ((temp & 0xff000000) >> 24);
645*5e7646d2SAndroid Build Coastguard Worker 
646*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("4_cupsRasterReadHeader: %08x => %08x", temp, *s));
647*5e7646d2SAndroid Build Coastguard Worker 	  }
648*5e7646d2SAndroid Build Coastguard Worker 	}
649*5e7646d2SAndroid Build Coastguard Worker         break;
650*5e7646d2SAndroid Build Coastguard Worker 
651*5e7646d2SAndroid Build Coastguard Worker     case CUPS_RASTER_SYNCapple :
652*5e7646d2SAndroid Build Coastguard Worker     case CUPS_RASTER_REVSYNCapple :
653*5e7646d2SAndroid Build Coastguard Worker         {
654*5e7646d2SAndroid Build Coastguard Worker           unsigned char	appleheader[32];	/* Raw header */
655*5e7646d2SAndroid Build Coastguard Worker           static const unsigned rawcspace[] =
656*5e7646d2SAndroid Build Coastguard Worker           {
657*5e7646d2SAndroid Build Coastguard Worker             CUPS_CSPACE_SW,
658*5e7646d2SAndroid Build Coastguard Worker             CUPS_CSPACE_SRGB,
659*5e7646d2SAndroid Build Coastguard Worker             CUPS_CSPACE_CIELab,
660*5e7646d2SAndroid Build Coastguard Worker             CUPS_CSPACE_ADOBERGB,
661*5e7646d2SAndroid Build Coastguard Worker             CUPS_CSPACE_W,
662*5e7646d2SAndroid Build Coastguard Worker             CUPS_CSPACE_RGB,
663*5e7646d2SAndroid Build Coastguard Worker             CUPS_CSPACE_CMYK
664*5e7646d2SAndroid Build Coastguard Worker           };
665*5e7646d2SAndroid Build Coastguard Worker           static const unsigned rawnumcolors[] =
666*5e7646d2SAndroid Build Coastguard Worker           {
667*5e7646d2SAndroid Build Coastguard Worker             1,
668*5e7646d2SAndroid Build Coastguard Worker             3,
669*5e7646d2SAndroid Build Coastguard Worker             3,
670*5e7646d2SAndroid Build Coastguard Worker             3,
671*5e7646d2SAndroid Build Coastguard Worker             1,
672*5e7646d2SAndroid Build Coastguard Worker             3,
673*5e7646d2SAndroid Build Coastguard Worker             4
674*5e7646d2SAndroid Build Coastguard Worker           };
675*5e7646d2SAndroid Build Coastguard Worker 
676*5e7646d2SAndroid Build Coastguard Worker 	  if (cups_raster_read(r, appleheader, sizeof(appleheader)) < (ssize_t)sizeof(appleheader))
677*5e7646d2SAndroid Build Coastguard Worker 	  {
678*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_printf(("4_cupsRasterReadHeader: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
679*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
680*5e7646d2SAndroid Build Coastguard Worker 	  }
681*5e7646d2SAndroid Build Coastguard Worker 
682*5e7646d2SAndroid Build Coastguard Worker 	  strlcpy(r->header.MediaClass, "PwgRaster", sizeof(r->header.MediaClass));
683*5e7646d2SAndroid Build Coastguard Worker 					      /* PwgRaster */
684*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsBitsPerPixel = appleheader[0];
685*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsColorSpace   = appleheader[1] >= (sizeof(rawcspace) / sizeof(rawcspace[0])) ? CUPS_CSPACE_DEVICE1 : rawcspace[appleheader[1]];
686*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsNumColors    = appleheader[1] >= (sizeof(rawnumcolors) / sizeof(rawnumcolors[0])) ? 1 : rawnumcolors[appleheader[1]];
687*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsBitsPerColor = r->header.cupsBitsPerPixel / r->header.cupsNumColors;
688*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsWidth        = ((((((unsigned)appleheader[12] << 8) | (unsigned)appleheader[13]) << 8) | (unsigned)appleheader[14]) << 8) | (unsigned)appleheader[15];
689*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsHeight       = ((((((unsigned)appleheader[16] << 8) | (unsigned)appleheader[17]) << 8) | (unsigned)appleheader[18]) << 8) | (unsigned)appleheader[19];
690*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsBytesPerLine = r->header.cupsWidth * r->header.cupsBitsPerPixel / 8;
691*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsColorOrder   = CUPS_ORDER_CHUNKED;
692*5e7646d2SAndroid Build Coastguard Worker           r->header.HWResolution[0]  = r->header.HWResolution[1] = ((((((unsigned)appleheader[20] << 8) | (unsigned)appleheader[21]) << 8) | (unsigned)appleheader[22]) << 8) | (unsigned)appleheader[23];
693*5e7646d2SAndroid Build Coastguard Worker 
694*5e7646d2SAndroid Build Coastguard Worker           if (r->header.HWResolution[0] > 0)
695*5e7646d2SAndroid Build Coastguard Worker           {
696*5e7646d2SAndroid Build Coastguard Worker 	    r->header.PageSize[0]     = (unsigned)(r->header.cupsWidth * 72 / r->header.HWResolution[0]);
697*5e7646d2SAndroid Build Coastguard Worker 	    r->header.PageSize[1]     = (unsigned)(r->header.cupsHeight * 72 / r->header.HWResolution[1]);
698*5e7646d2SAndroid Build Coastguard Worker 	    r->header.cupsPageSize[0] = (float)(r->header.cupsWidth * 72.0 / r->header.HWResolution[0]);
699*5e7646d2SAndroid Build Coastguard Worker 	    r->header.cupsPageSize[1] = (float)(r->header.cupsHeight * 72.0 / r->header.HWResolution[1]);
700*5e7646d2SAndroid Build Coastguard Worker           }
701*5e7646d2SAndroid Build Coastguard Worker 
702*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsInteger[CUPS_RASTER_PWG_TotalPageCount]   = r->apple_page_count;
703*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsInteger[CUPS_RASTER_PWG_AlternatePrimary] = 0xffffff;
704*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsInteger[CUPS_RASTER_PWG_PrintQuality]     = appleheader[3];
705*5e7646d2SAndroid Build Coastguard Worker 
706*5e7646d2SAndroid Build Coastguard Worker           if (appleheader[2] >= 2)
707*5e7646d2SAndroid Build Coastguard Worker             r->header.Duplex = 1;
708*5e7646d2SAndroid Build Coastguard Worker           if (appleheader[2] == 2)
709*5e7646d2SAndroid Build Coastguard Worker             r->header.Tumble = 1;
710*5e7646d2SAndroid Build Coastguard Worker 
711*5e7646d2SAndroid Build Coastguard Worker           r->header.MediaPosition = appleheader[5];
712*5e7646d2SAndroid Build Coastguard Worker 
713*5e7646d2SAndroid Build Coastguard Worker           if (appleheader[4] < (int)(sizeof(apple_media_types) / sizeof(apple_media_types[0])))
714*5e7646d2SAndroid Build Coastguard Worker             strlcpy(r->header.MediaType, apple_media_types[appleheader[4]], sizeof(r->header.MediaType));
715*5e7646d2SAndroid Build Coastguard Worker           else
716*5e7646d2SAndroid Build Coastguard Worker             strlcpy(r->header.MediaType, "other", sizeof(r->header.MediaType));
717*5e7646d2SAndroid Build Coastguard Worker         }
718*5e7646d2SAndroid Build Coastguard Worker         break;
719*5e7646d2SAndroid Build Coastguard Worker   }
720*5e7646d2SAndroid Build Coastguard Worker 
721*5e7646d2SAndroid Build Coastguard Worker  /*
722*5e7646d2SAndroid Build Coastguard Worker   * Update the header and row count...
723*5e7646d2SAndroid Build Coastguard Worker   */
724*5e7646d2SAndroid Build Coastguard Worker 
725*5e7646d2SAndroid Build Coastguard Worker   if (!cups_raster_update(r))
726*5e7646d2SAndroid Build Coastguard Worker     return (0);
727*5e7646d2SAndroid Build Coastguard Worker 
728*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4_cupsRasterReadHeader: cupsColorSpace=%s", _cupsRasterColorSpaceString(r->header.cupsColorSpace)));
729*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4_cupsRasterReadHeader: cupsBitsPerColor=%u", r->header.cupsBitsPerColor));
730*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4_cupsRasterReadHeader: cupsBitsPerPixel=%u", r->header.cupsBitsPerPixel));
731*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4_cupsRasterReadHeader: cupsBytesPerLine=%u", r->header.cupsBytesPerLine));
732*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4_cupsRasterReadHeader: cupsWidth=%u", r->header.cupsWidth));
733*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4_cupsRasterReadHeader: cupsHeight=%u", r->header.cupsHeight));
734*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4_cupsRasterReadHeader: r->bpp=%d", r->bpp));
735*5e7646d2SAndroid Build Coastguard Worker 
736*5e7646d2SAndroid Build Coastguard Worker   return (r->header.cupsBitsPerPixel > 0 && r->header.cupsBitsPerPixel <= 240 && r->header.cupsBitsPerColor > 0 && r->header.cupsBitsPerColor <= 16 && r->header.cupsBytesPerLine > 0 && r->header.cupsBytesPerLine <= 0x7fffffff && r->header.cupsHeight != 0 && (r->header.cupsBytesPerLine % r->bpp) == 0);
737*5e7646d2SAndroid Build Coastguard Worker }
738*5e7646d2SAndroid Build Coastguard Worker 
739*5e7646d2SAndroid Build Coastguard Worker 
740*5e7646d2SAndroid Build Coastguard Worker /*
741*5e7646d2SAndroid Build Coastguard Worker  * '_cupsRasterReadPixels()' - Read raster pixels.
742*5e7646d2SAndroid Build Coastguard Worker  *
743*5e7646d2SAndroid Build Coastguard Worker  * For best performance, filters should read one or more whole lines.
744*5e7646d2SAndroid Build Coastguard Worker  * The "cupsBytesPerLine" value from the page header can be used to allocate
745*5e7646d2SAndroid Build Coastguard Worker  * the line buffer and as the number of bytes to read.
746*5e7646d2SAndroid Build Coastguard Worker  */
747*5e7646d2SAndroid Build Coastguard Worker 
748*5e7646d2SAndroid Build Coastguard Worker unsigned				/* O - Number of bytes read */
_cupsRasterReadPixels(cups_raster_t * r,unsigned char * p,unsigned len)749*5e7646d2SAndroid Build Coastguard Worker _cupsRasterReadPixels(
750*5e7646d2SAndroid Build Coastguard Worker     cups_raster_t *r,			/* I - Raster stream */
751*5e7646d2SAndroid Build Coastguard Worker     unsigned char *p,			/* I - Pointer to pixel buffer */
752*5e7646d2SAndroid Build Coastguard Worker     unsigned      len)			/* I - Number of bytes to read */
753*5e7646d2SAndroid Build Coastguard Worker {
754*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes;			/* Bytes read */
755*5e7646d2SAndroid Build Coastguard Worker   unsigned	cupsBytesPerLine;	/* cupsBytesPerLine value */
756*5e7646d2SAndroid Build Coastguard Worker   unsigned	remaining;		/* Bytes remaining */
757*5e7646d2SAndroid Build Coastguard Worker   unsigned char	*ptr,			/* Pointer to read buffer */
758*5e7646d2SAndroid Build Coastguard Worker 		byte,			/* Byte from file */
759*5e7646d2SAndroid Build Coastguard Worker 		*temp;			/* Pointer into buffer */
760*5e7646d2SAndroid Build Coastguard Worker   unsigned	count;			/* Repetition count */
761*5e7646d2SAndroid Build Coastguard Worker 
762*5e7646d2SAndroid Build Coastguard Worker 
763*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_cupsRasterReadPixels(r=%p, p=%p, len=%u)", (void *)r, (void *)p, len));
764*5e7646d2SAndroid Build Coastguard Worker 
765*5e7646d2SAndroid Build Coastguard Worker   if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0 ||
766*5e7646d2SAndroid Build Coastguard Worker       r->header.cupsBytesPerLine == 0)
767*5e7646d2SAndroid Build Coastguard Worker   {
768*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1_cupsRasterReadPixels: Returning 0.");
769*5e7646d2SAndroid Build Coastguard Worker     return (0);
770*5e7646d2SAndroid Build Coastguard Worker   }
771*5e7646d2SAndroid Build Coastguard Worker 
772*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_cupsRasterReadPixels: compressed=%d, remaining=%u", r->compressed, r->remaining));
773*5e7646d2SAndroid Build Coastguard Worker 
774*5e7646d2SAndroid Build Coastguard Worker   if (!r->compressed)
775*5e7646d2SAndroid Build Coastguard Worker   {
776*5e7646d2SAndroid Build Coastguard Worker    /*
777*5e7646d2SAndroid Build Coastguard Worker     * Read without compression...
778*5e7646d2SAndroid Build Coastguard Worker     */
779*5e7646d2SAndroid Build Coastguard Worker 
780*5e7646d2SAndroid Build Coastguard Worker     r->remaining -= len / r->header.cupsBytesPerLine;
781*5e7646d2SAndroid Build Coastguard Worker 
782*5e7646d2SAndroid Build Coastguard Worker     if (cups_raster_io(r, p, len) < (ssize_t)len)
783*5e7646d2SAndroid Build Coastguard Worker     {
784*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
785*5e7646d2SAndroid Build Coastguard Worker       return (0);
786*5e7646d2SAndroid Build Coastguard Worker     }
787*5e7646d2SAndroid Build Coastguard Worker 
788*5e7646d2SAndroid Build Coastguard Worker    /*
789*5e7646d2SAndroid Build Coastguard Worker     * Swap bytes as needed...
790*5e7646d2SAndroid Build Coastguard Worker     */
791*5e7646d2SAndroid Build Coastguard Worker 
792*5e7646d2SAndroid Build Coastguard Worker     if (r->swapped &&
793*5e7646d2SAndroid Build Coastguard Worker         (r->header.cupsBitsPerColor == 16 ||
794*5e7646d2SAndroid Build Coastguard Worker          r->header.cupsBitsPerPixel == 12 ||
795*5e7646d2SAndroid Build Coastguard Worker          r->header.cupsBitsPerPixel == 16))
796*5e7646d2SAndroid Build Coastguard Worker       cups_swap(p, len);
797*5e7646d2SAndroid Build Coastguard Worker 
798*5e7646d2SAndroid Build Coastguard Worker    /*
799*5e7646d2SAndroid Build Coastguard Worker     * Return...
800*5e7646d2SAndroid Build Coastguard Worker     */
801*5e7646d2SAndroid Build Coastguard Worker 
802*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("1_cupsRasterReadPixels: Returning %u", len));
803*5e7646d2SAndroid Build Coastguard Worker 
804*5e7646d2SAndroid Build Coastguard Worker     return (len);
805*5e7646d2SAndroid Build Coastguard Worker   }
806*5e7646d2SAndroid Build Coastguard Worker 
807*5e7646d2SAndroid Build Coastguard Worker  /*
808*5e7646d2SAndroid Build Coastguard Worker   * Read compressed data...
809*5e7646d2SAndroid Build Coastguard Worker   */
810*5e7646d2SAndroid Build Coastguard Worker 
811*5e7646d2SAndroid Build Coastguard Worker   remaining        = len;
812*5e7646d2SAndroid Build Coastguard Worker   cupsBytesPerLine = r->header.cupsBytesPerLine;
813*5e7646d2SAndroid Build Coastguard Worker 
814*5e7646d2SAndroid Build Coastguard Worker   while (remaining > 0 && r->remaining > 0)
815*5e7646d2SAndroid Build Coastguard Worker   {
816*5e7646d2SAndroid Build Coastguard Worker     if (r->count == 0)
817*5e7646d2SAndroid Build Coastguard Worker     {
818*5e7646d2SAndroid Build Coastguard Worker      /*
819*5e7646d2SAndroid Build Coastguard Worker       * Need to read a new row...
820*5e7646d2SAndroid Build Coastguard Worker       */
821*5e7646d2SAndroid Build Coastguard Worker 
822*5e7646d2SAndroid Build Coastguard Worker       if (remaining == cupsBytesPerLine)
823*5e7646d2SAndroid Build Coastguard Worker 	ptr = p;
824*5e7646d2SAndroid Build Coastguard Worker       else
825*5e7646d2SAndroid Build Coastguard Worker 	ptr = r->pixels;
826*5e7646d2SAndroid Build Coastguard Worker 
827*5e7646d2SAndroid Build Coastguard Worker      /*
828*5e7646d2SAndroid Build Coastguard Worker       * Read using a modified PackBits compression...
829*5e7646d2SAndroid Build Coastguard Worker       */
830*5e7646d2SAndroid Build Coastguard Worker 
831*5e7646d2SAndroid Build Coastguard Worker       if (!cups_raster_read(r, &byte, 1))
832*5e7646d2SAndroid Build Coastguard Worker       {
833*5e7646d2SAndroid Build Coastguard Worker 	DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
834*5e7646d2SAndroid Build Coastguard Worker 	return (0);
835*5e7646d2SAndroid Build Coastguard Worker       }
836*5e7646d2SAndroid Build Coastguard Worker 
837*5e7646d2SAndroid Build Coastguard Worker       r->count = (unsigned)byte + 1;
838*5e7646d2SAndroid Build Coastguard Worker 
839*5e7646d2SAndroid Build Coastguard Worker       if (r->count > 1)
840*5e7646d2SAndroid Build Coastguard Worker 	ptr = r->pixels;
841*5e7646d2SAndroid Build Coastguard Worker 
842*5e7646d2SAndroid Build Coastguard Worker       temp  = ptr;
843*5e7646d2SAndroid Build Coastguard Worker       bytes = (ssize_t)cupsBytesPerLine;
844*5e7646d2SAndroid Build Coastguard Worker 
845*5e7646d2SAndroid Build Coastguard Worker       while (bytes > 0)
846*5e7646d2SAndroid Build Coastguard Worker       {
847*5e7646d2SAndroid Build Coastguard Worker        /*
848*5e7646d2SAndroid Build Coastguard Worker 	* Get a new repeat count...
849*5e7646d2SAndroid Build Coastguard Worker 	*/
850*5e7646d2SAndroid Build Coastguard Worker 
851*5e7646d2SAndroid Build Coastguard Worker         if (!cups_raster_read(r, &byte, 1))
852*5e7646d2SAndroid Build Coastguard Worker 	{
853*5e7646d2SAndroid Build Coastguard Worker 	  DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
854*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
855*5e7646d2SAndroid Build Coastguard Worker 	}
856*5e7646d2SAndroid Build Coastguard Worker 
857*5e7646d2SAndroid Build Coastguard Worker         if (byte == 128)
858*5e7646d2SAndroid Build Coastguard Worker         {
859*5e7646d2SAndroid Build Coastguard Worker          /*
860*5e7646d2SAndroid Build Coastguard Worker           * Clear to end of line...
861*5e7646d2SAndroid Build Coastguard Worker           */
862*5e7646d2SAndroid Build Coastguard Worker 
863*5e7646d2SAndroid Build Coastguard Worker           switch (r->header.cupsColorSpace)
864*5e7646d2SAndroid Build Coastguard Worker           {
865*5e7646d2SAndroid Build Coastguard Worker             case CUPS_CSPACE_W :
866*5e7646d2SAndroid Build Coastguard Worker             case CUPS_CSPACE_RGB :
867*5e7646d2SAndroid Build Coastguard Worker             case CUPS_CSPACE_SW :
868*5e7646d2SAndroid Build Coastguard Worker             case CUPS_CSPACE_SRGB :
869*5e7646d2SAndroid Build Coastguard Worker             case CUPS_CSPACE_RGBW :
870*5e7646d2SAndroid Build Coastguard Worker             case CUPS_CSPACE_ADOBERGB :
871*5e7646d2SAndroid Build Coastguard Worker                 memset(temp, 0xff, (size_t)bytes);
872*5e7646d2SAndroid Build Coastguard Worker                 break;
873*5e7646d2SAndroid Build Coastguard Worker             default :
874*5e7646d2SAndroid Build Coastguard Worker                 memset(temp, 0x00, (size_t)bytes);
875*5e7646d2SAndroid Build Coastguard Worker                 break;
876*5e7646d2SAndroid Build Coastguard Worker           }
877*5e7646d2SAndroid Build Coastguard Worker 
878*5e7646d2SAndroid Build Coastguard Worker           temp += bytes;
879*5e7646d2SAndroid Build Coastguard Worker           bytes = 0;
880*5e7646d2SAndroid Build Coastguard Worker         }
881*5e7646d2SAndroid Build Coastguard Worker 	else if (byte & 128)
882*5e7646d2SAndroid Build Coastguard Worker 	{
883*5e7646d2SAndroid Build Coastguard Worker 	 /*
884*5e7646d2SAndroid Build Coastguard Worker 	  * Copy N literal pixels...
885*5e7646d2SAndroid Build Coastguard Worker 	  */
886*5e7646d2SAndroid Build Coastguard Worker 
887*5e7646d2SAndroid Build Coastguard Worker 	  count = (unsigned)(257 - byte) * r->bpp;
888*5e7646d2SAndroid Build Coastguard Worker 
889*5e7646d2SAndroid Build Coastguard Worker           if (count > (unsigned)bytes)
890*5e7646d2SAndroid Build Coastguard Worker 	    count = (unsigned)bytes;
891*5e7646d2SAndroid Build Coastguard Worker 
892*5e7646d2SAndroid Build Coastguard Worker           if (!cups_raster_read(r, temp, count))
893*5e7646d2SAndroid Build Coastguard Worker 	  {
894*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
895*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
896*5e7646d2SAndroid Build Coastguard Worker 	  }
897*5e7646d2SAndroid Build Coastguard Worker 
898*5e7646d2SAndroid Build Coastguard Worker 	  temp  += count;
899*5e7646d2SAndroid Build Coastguard Worker 	  bytes -= (ssize_t)count;
900*5e7646d2SAndroid Build Coastguard Worker 	}
901*5e7646d2SAndroid Build Coastguard Worker 	else
902*5e7646d2SAndroid Build Coastguard Worker 	{
903*5e7646d2SAndroid Build Coastguard Worker 	 /*
904*5e7646d2SAndroid Build Coastguard Worker 	  * Repeat the next N bytes...
905*5e7646d2SAndroid Build Coastguard Worker 	  */
906*5e7646d2SAndroid Build Coastguard Worker 
907*5e7646d2SAndroid Build Coastguard Worker           count = ((unsigned)byte + 1) * r->bpp;
908*5e7646d2SAndroid Build Coastguard Worker           if (count > (unsigned)bytes)
909*5e7646d2SAndroid Build Coastguard Worker 	    count = (unsigned)bytes;
910*5e7646d2SAndroid Build Coastguard Worker 
911*5e7646d2SAndroid Build Coastguard Worker           if (count < r->bpp)
912*5e7646d2SAndroid Build Coastguard Worker 	    break;
913*5e7646d2SAndroid Build Coastguard Worker 
914*5e7646d2SAndroid Build Coastguard Worker 	  bytes -= (ssize_t)count;
915*5e7646d2SAndroid Build Coastguard Worker 
916*5e7646d2SAndroid Build Coastguard Worker           if (!cups_raster_read(r, temp, r->bpp))
917*5e7646d2SAndroid Build Coastguard Worker 	  {
918*5e7646d2SAndroid Build Coastguard Worker 	    DEBUG_puts("1_cupsRasterReadPixels: Read error, returning 0.");
919*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
920*5e7646d2SAndroid Build Coastguard Worker 	  }
921*5e7646d2SAndroid Build Coastguard Worker 
922*5e7646d2SAndroid Build Coastguard Worker 	  temp  += r->bpp;
923*5e7646d2SAndroid Build Coastguard Worker 	  count -= r->bpp;
924*5e7646d2SAndroid Build Coastguard Worker 
925*5e7646d2SAndroid Build Coastguard Worker 	  while (count > 0)
926*5e7646d2SAndroid Build Coastguard Worker 	  {
927*5e7646d2SAndroid Build Coastguard Worker 	    memcpy(temp, temp - r->bpp, r->bpp);
928*5e7646d2SAndroid Build Coastguard Worker 	    temp  += r->bpp;
929*5e7646d2SAndroid Build Coastguard Worker 	    count -= r->bpp;
930*5e7646d2SAndroid Build Coastguard Worker           }
931*5e7646d2SAndroid Build Coastguard Worker 	}
932*5e7646d2SAndroid Build Coastguard Worker       }
933*5e7646d2SAndroid Build Coastguard Worker 
934*5e7646d2SAndroid Build Coastguard Worker      /*
935*5e7646d2SAndroid Build Coastguard Worker       * Swap bytes as needed...
936*5e7646d2SAndroid Build Coastguard Worker       */
937*5e7646d2SAndroid Build Coastguard Worker 
938*5e7646d2SAndroid Build Coastguard Worker       if ((r->header.cupsBitsPerColor == 16 ||
939*5e7646d2SAndroid Build Coastguard Worker            r->header.cupsBitsPerPixel == 12 ||
940*5e7646d2SAndroid Build Coastguard Worker            r->header.cupsBitsPerPixel == 16) &&
941*5e7646d2SAndroid Build Coastguard Worker           r->swapped)
942*5e7646d2SAndroid Build Coastguard Worker       {
943*5e7646d2SAndroid Build Coastguard Worker         DEBUG_puts("1_cupsRasterReadPixels: Swapping bytes.");
944*5e7646d2SAndroid Build Coastguard Worker         cups_swap(ptr, (size_t)cupsBytesPerLine);
945*5e7646d2SAndroid Build Coastguard Worker       }
946*5e7646d2SAndroid Build Coastguard Worker 
947*5e7646d2SAndroid Build Coastguard Worker      /*
948*5e7646d2SAndroid Build Coastguard Worker       * Update pointers...
949*5e7646d2SAndroid Build Coastguard Worker       */
950*5e7646d2SAndroid Build Coastguard Worker 
951*5e7646d2SAndroid Build Coastguard Worker       if (remaining >= cupsBytesPerLine)
952*5e7646d2SAndroid Build Coastguard Worker       {
953*5e7646d2SAndroid Build Coastguard Worker 	bytes       = (ssize_t)cupsBytesPerLine;
954*5e7646d2SAndroid Build Coastguard Worker         r->pcurrent = r->pixels;
955*5e7646d2SAndroid Build Coastguard Worker 	r->count --;
956*5e7646d2SAndroid Build Coastguard Worker 	r->remaining --;
957*5e7646d2SAndroid Build Coastguard Worker       }
958*5e7646d2SAndroid Build Coastguard Worker       else
959*5e7646d2SAndroid Build Coastguard Worker       {
960*5e7646d2SAndroid Build Coastguard Worker 	bytes       = (ssize_t)remaining;
961*5e7646d2SAndroid Build Coastguard Worker         r->pcurrent = r->pixels + bytes;
962*5e7646d2SAndroid Build Coastguard Worker       }
963*5e7646d2SAndroid Build Coastguard Worker 
964*5e7646d2SAndroid Build Coastguard Worker      /*
965*5e7646d2SAndroid Build Coastguard Worker       * Copy data as needed...
966*5e7646d2SAndroid Build Coastguard Worker       */
967*5e7646d2SAndroid Build Coastguard Worker 
968*5e7646d2SAndroid Build Coastguard Worker       if (ptr != p)
969*5e7646d2SAndroid Build Coastguard Worker         memcpy(p, ptr, (size_t)bytes);
970*5e7646d2SAndroid Build Coastguard Worker     }
971*5e7646d2SAndroid Build Coastguard Worker     else
972*5e7646d2SAndroid Build Coastguard Worker     {
973*5e7646d2SAndroid Build Coastguard Worker      /*
974*5e7646d2SAndroid Build Coastguard Worker       * Copy fragment from buffer...
975*5e7646d2SAndroid Build Coastguard Worker       */
976*5e7646d2SAndroid Build Coastguard Worker 
977*5e7646d2SAndroid Build Coastguard Worker       if ((unsigned)(bytes = (int)(r->pend - r->pcurrent)) > remaining)
978*5e7646d2SAndroid Build Coastguard Worker         bytes = (ssize_t)remaining;
979*5e7646d2SAndroid Build Coastguard Worker 
980*5e7646d2SAndroid Build Coastguard Worker       memcpy(p, r->pcurrent, (size_t)bytes);
981*5e7646d2SAndroid Build Coastguard Worker       r->pcurrent += bytes;
982*5e7646d2SAndroid Build Coastguard Worker 
983*5e7646d2SAndroid Build Coastguard Worker       if (r->pcurrent >= r->pend)
984*5e7646d2SAndroid Build Coastguard Worker       {
985*5e7646d2SAndroid Build Coastguard Worker         r->pcurrent = r->pixels;
986*5e7646d2SAndroid Build Coastguard Worker 	r->count --;
987*5e7646d2SAndroid Build Coastguard Worker 	r->remaining --;
988*5e7646d2SAndroid Build Coastguard Worker       }
989*5e7646d2SAndroid Build Coastguard Worker     }
990*5e7646d2SAndroid Build Coastguard Worker 
991*5e7646d2SAndroid Build Coastguard Worker     remaining -= (unsigned)bytes;
992*5e7646d2SAndroid Build Coastguard Worker     p         += bytes;
993*5e7646d2SAndroid Build Coastguard Worker   }
994*5e7646d2SAndroid Build Coastguard Worker 
995*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_cupsRasterReadPixels: Returning %u", len));
996*5e7646d2SAndroid Build Coastguard Worker 
997*5e7646d2SAndroid Build Coastguard Worker   return (len);
998*5e7646d2SAndroid Build Coastguard Worker }
999*5e7646d2SAndroid Build Coastguard Worker 
1000*5e7646d2SAndroid Build Coastguard Worker 
1001*5e7646d2SAndroid Build Coastguard Worker /*
1002*5e7646d2SAndroid Build Coastguard Worker  * '_cupsRasterWriteHeader()' - Write a raster page header.
1003*5e7646d2SAndroid Build Coastguard Worker  */
1004*5e7646d2SAndroid Build Coastguard Worker 
1005*5e7646d2SAndroid Build Coastguard Worker unsigned				/* O - 1 on success, 0 on failure */
_cupsRasterWriteHeader(cups_raster_t * r)1006*5e7646d2SAndroid Build Coastguard Worker _cupsRasterWriteHeader(
1007*5e7646d2SAndroid Build Coastguard Worker     cups_raster_t *r)			/* I - Raster stream */
1008*5e7646d2SAndroid Build Coastguard Worker {
1009*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_cupsRasterWriteHeader(r=%p)", (void *)r));
1010*5e7646d2SAndroid Build Coastguard Worker 
1011*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_cupsRasterWriteHeader: cupsColorSpace=%s", _cupsRasterColorSpaceString(r->header.cupsColorSpace)));
1012*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_cupsRasterWriteHeader: cupsBitsPerColor=%u", r->header.cupsBitsPerColor));
1013*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_cupsRasterWriteHeader: cupsBitsPerPixel=%u", r->header.cupsBitsPerPixel));
1014*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_cupsRasterWriteHeader: cupsBytesPerLine=%u", r->header.cupsBytesPerLine));
1015*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_cupsRasterWriteHeader: cupsWidth=%u", r->header.cupsWidth));
1016*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("1_cupsRasterWriteHeader: cupsHeight=%u", r->header.cupsHeight));
1017*5e7646d2SAndroid Build Coastguard Worker 
1018*5e7646d2SAndroid Build Coastguard Worker  /*
1019*5e7646d2SAndroid Build Coastguard Worker   * Compute the number of raster lines in the page image...
1020*5e7646d2SAndroid Build Coastguard Worker   */
1021*5e7646d2SAndroid Build Coastguard Worker 
1022*5e7646d2SAndroid Build Coastguard Worker   if (!cups_raster_update(r))
1023*5e7646d2SAndroid Build Coastguard Worker   {
1024*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("1_cupsRasterWriteHeader: Unable to update parameters, returning 0.");
1025*5e7646d2SAndroid Build Coastguard Worker     return (0);
1026*5e7646d2SAndroid Build Coastguard Worker   }
1027*5e7646d2SAndroid Build Coastguard Worker 
1028*5e7646d2SAndroid Build Coastguard Worker   if (r->mode == CUPS_RASTER_WRITE_APPLE)
1029*5e7646d2SAndroid Build Coastguard Worker   {
1030*5e7646d2SAndroid Build Coastguard Worker     r->rowheight = r->header.HWResolution[0] / r->header.HWResolution[1];
1031*5e7646d2SAndroid Build Coastguard Worker 
1032*5e7646d2SAndroid Build Coastguard Worker     if (r->header.HWResolution[0] != (r->rowheight * r->header.HWResolution[1]))
1033*5e7646d2SAndroid Build Coastguard Worker       return (0);
1034*5e7646d2SAndroid Build Coastguard Worker   }
1035*5e7646d2SAndroid Build Coastguard Worker   else
1036*5e7646d2SAndroid Build Coastguard Worker     r->rowheight = 1;
1037*5e7646d2SAndroid Build Coastguard Worker 
1038*5e7646d2SAndroid Build Coastguard Worker  /*
1039*5e7646d2SAndroid Build Coastguard Worker   * Write the raster header...
1040*5e7646d2SAndroid Build Coastguard Worker   */
1041*5e7646d2SAndroid Build Coastguard Worker 
1042*5e7646d2SAndroid Build Coastguard Worker   if (r->mode == CUPS_RASTER_WRITE_PWG)
1043*5e7646d2SAndroid Build Coastguard Worker   {
1044*5e7646d2SAndroid Build Coastguard Worker    /*
1045*5e7646d2SAndroid Build Coastguard Worker     * PWG raster data is always network byte order with much of the page header
1046*5e7646d2SAndroid Build Coastguard Worker     * zeroed.
1047*5e7646d2SAndroid Build Coastguard Worker     */
1048*5e7646d2SAndroid Build Coastguard Worker 
1049*5e7646d2SAndroid Build Coastguard Worker     cups_page_header2_t	fh;		/* File page header */
1050*5e7646d2SAndroid Build Coastguard Worker 
1051*5e7646d2SAndroid Build Coastguard Worker     memset(&fh, 0, sizeof(fh));
1052*5e7646d2SAndroid Build Coastguard Worker     strlcpy(fh.MediaClass, "PwgRaster", sizeof(fh.MediaClass));
1053*5e7646d2SAndroid Build Coastguard Worker     strlcpy(fh.MediaColor, r->header.MediaColor, sizeof(fh.MediaColor));
1054*5e7646d2SAndroid Build Coastguard Worker     strlcpy(fh.MediaType, r->header.MediaType, sizeof(fh.MediaType));
1055*5e7646d2SAndroid Build Coastguard Worker     strlcpy(fh.OutputType, r->header.OutputType, sizeof(fh.OutputType));
1056*5e7646d2SAndroid Build Coastguard Worker     strlcpy(fh.cupsRenderingIntent, r->header.cupsRenderingIntent,
1057*5e7646d2SAndroid Build Coastguard Worker             sizeof(fh.cupsRenderingIntent));
1058*5e7646d2SAndroid Build Coastguard Worker     strlcpy(fh.cupsPageSizeName, r->header.cupsPageSizeName,
1059*5e7646d2SAndroid Build Coastguard Worker             sizeof(fh.cupsPageSizeName));
1060*5e7646d2SAndroid Build Coastguard Worker 
1061*5e7646d2SAndroid Build Coastguard Worker     fh.CutMedia              = htonl(r->header.CutMedia);
1062*5e7646d2SAndroid Build Coastguard Worker     fh.Duplex                = htonl(r->header.Duplex);
1063*5e7646d2SAndroid Build Coastguard Worker     fh.HWResolution[0]       = htonl(r->header.HWResolution[0]);
1064*5e7646d2SAndroid Build Coastguard Worker     fh.HWResolution[1]       = htonl(r->header.HWResolution[1]);
1065*5e7646d2SAndroid Build Coastguard Worker     fh.ImagingBoundingBox[0] = htonl(r->header.ImagingBoundingBox[0]);
1066*5e7646d2SAndroid Build Coastguard Worker     fh.ImagingBoundingBox[1] = htonl(r->header.ImagingBoundingBox[1]);
1067*5e7646d2SAndroid Build Coastguard Worker     fh.ImagingBoundingBox[2] = htonl(r->header.ImagingBoundingBox[2]);
1068*5e7646d2SAndroid Build Coastguard Worker     fh.ImagingBoundingBox[3] = htonl(r->header.ImagingBoundingBox[3]);
1069*5e7646d2SAndroid Build Coastguard Worker     fh.InsertSheet           = htonl(r->header.InsertSheet);
1070*5e7646d2SAndroid Build Coastguard Worker     fh.Jog                   = htonl(r->header.Jog);
1071*5e7646d2SAndroid Build Coastguard Worker     fh.LeadingEdge           = htonl(r->header.LeadingEdge);
1072*5e7646d2SAndroid Build Coastguard Worker     fh.ManualFeed            = htonl(r->header.ManualFeed);
1073*5e7646d2SAndroid Build Coastguard Worker     fh.MediaPosition         = htonl(r->header.MediaPosition);
1074*5e7646d2SAndroid Build Coastguard Worker     fh.MediaWeight           = htonl(r->header.MediaWeight);
1075*5e7646d2SAndroid Build Coastguard Worker     fh.NumCopies             = htonl(r->header.NumCopies);
1076*5e7646d2SAndroid Build Coastguard Worker     fh.Orientation           = htonl(r->header.Orientation);
1077*5e7646d2SAndroid Build Coastguard Worker     fh.PageSize[0]           = htonl(r->header.PageSize[0]);
1078*5e7646d2SAndroid Build Coastguard Worker     fh.PageSize[1]           = htonl(r->header.PageSize[1]);
1079*5e7646d2SAndroid Build Coastguard Worker     fh.Tumble                = htonl(r->header.Tumble);
1080*5e7646d2SAndroid Build Coastguard Worker     fh.cupsWidth             = htonl(r->header.cupsWidth);
1081*5e7646d2SAndroid Build Coastguard Worker     fh.cupsHeight            = htonl(r->header.cupsHeight);
1082*5e7646d2SAndroid Build Coastguard Worker     fh.cupsBitsPerColor      = htonl(r->header.cupsBitsPerColor);
1083*5e7646d2SAndroid Build Coastguard Worker     fh.cupsBitsPerPixel      = htonl(r->header.cupsBitsPerPixel);
1084*5e7646d2SAndroid Build Coastguard Worker     fh.cupsBytesPerLine      = htonl(r->header.cupsBytesPerLine);
1085*5e7646d2SAndroid Build Coastguard Worker     fh.cupsColorOrder        = htonl(r->header.cupsColorOrder);
1086*5e7646d2SAndroid Build Coastguard Worker     fh.cupsColorSpace        = htonl(r->header.cupsColorSpace);
1087*5e7646d2SAndroid Build Coastguard Worker     fh.cupsNumColors         = htonl(r->header.cupsNumColors);
1088*5e7646d2SAndroid Build Coastguard Worker     fh.cupsInteger[0]        = htonl(r->header.cupsInteger[0]);
1089*5e7646d2SAndroid Build Coastguard Worker     fh.cupsInteger[1]        = htonl(r->header.cupsInteger[1]);
1090*5e7646d2SAndroid Build Coastguard Worker     fh.cupsInteger[2]        = htonl(r->header.cupsInteger[2]);
1091*5e7646d2SAndroid Build Coastguard Worker     fh.cupsInteger[3]        = htonl((unsigned)(r->header.cupsImagingBBox[0] * r->header.HWResolution[0] / 72.0));
1092*5e7646d2SAndroid Build Coastguard Worker     fh.cupsInteger[4]        = htonl((unsigned)(r->header.cupsImagingBBox[1] * r->header.HWResolution[1] / 72.0));
1093*5e7646d2SAndroid Build Coastguard Worker     fh.cupsInteger[5]        = htonl((unsigned)(r->header.cupsImagingBBox[2] * r->header.HWResolution[0] / 72.0));
1094*5e7646d2SAndroid Build Coastguard Worker     fh.cupsInteger[6]        = htonl((unsigned)(r->header.cupsImagingBBox[3] * r->header.HWResolution[1] / 72.0));
1095*5e7646d2SAndroid Build Coastguard Worker     fh.cupsInteger[7]        = htonl(0xffffff);
1096*5e7646d2SAndroid Build Coastguard Worker 
1097*5e7646d2SAndroid Build Coastguard Worker     return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
1098*5e7646d2SAndroid Build Coastguard Worker   }
1099*5e7646d2SAndroid Build Coastguard Worker   else if (r->mode == CUPS_RASTER_WRITE_APPLE)
1100*5e7646d2SAndroid Build Coastguard Worker   {
1101*5e7646d2SAndroid Build Coastguard Worker    /*
1102*5e7646d2SAndroid Build Coastguard Worker     * Raw raster data is always network byte order with most of the page header
1103*5e7646d2SAndroid Build Coastguard Worker     * zeroed.
1104*5e7646d2SAndroid Build Coastguard Worker     */
1105*5e7646d2SAndroid Build Coastguard Worker 
1106*5e7646d2SAndroid Build Coastguard Worker     int			i;		/* Looping var */
1107*5e7646d2SAndroid Build Coastguard Worker     unsigned char	appleheader[32];/* Raw page header */
1108*5e7646d2SAndroid Build Coastguard Worker     unsigned		height = r->header.cupsHeight * r->rowheight;
1109*5e7646d2SAndroid Build Coastguard Worker 					/* Computed page height */
1110*5e7646d2SAndroid Build Coastguard Worker 
1111*5e7646d2SAndroid Build Coastguard Worker     if (r->apple_page_count == 0xffffffffU)
1112*5e7646d2SAndroid Build Coastguard Worker     {
1113*5e7646d2SAndroid Build Coastguard Worker      /*
1114*5e7646d2SAndroid Build Coastguard Worker       * Write raw page count from raster page header...
1115*5e7646d2SAndroid Build Coastguard Worker       */
1116*5e7646d2SAndroid Build Coastguard Worker 
1117*5e7646d2SAndroid Build Coastguard Worker       r->apple_page_count = r->header.cupsInteger[0];
1118*5e7646d2SAndroid Build Coastguard Worker 
1119*5e7646d2SAndroid Build Coastguard Worker       appleheader[0] = 'A';
1120*5e7646d2SAndroid Build Coastguard Worker       appleheader[1] = 'S';
1121*5e7646d2SAndroid Build Coastguard Worker       appleheader[2] = 'T';
1122*5e7646d2SAndroid Build Coastguard Worker       appleheader[3] = 0;
1123*5e7646d2SAndroid Build Coastguard Worker       appleheader[4] = (unsigned char)(r->apple_page_count >> 24);
1124*5e7646d2SAndroid Build Coastguard Worker       appleheader[5] = (unsigned char)(r->apple_page_count >> 16);
1125*5e7646d2SAndroid Build Coastguard Worker       appleheader[6] = (unsigned char)(r->apple_page_count >> 8);
1126*5e7646d2SAndroid Build Coastguard Worker       appleheader[7] = (unsigned char)(r->apple_page_count);
1127*5e7646d2SAndroid Build Coastguard Worker 
1128*5e7646d2SAndroid Build Coastguard Worker       if (cups_raster_io(r, appleheader, 8) != 8)
1129*5e7646d2SAndroid Build Coastguard Worker         return (0);
1130*5e7646d2SAndroid Build Coastguard Worker     }
1131*5e7646d2SAndroid Build Coastguard Worker 
1132*5e7646d2SAndroid Build Coastguard Worker     memset(appleheader, 0, sizeof(appleheader));
1133*5e7646d2SAndroid Build Coastguard Worker 
1134*5e7646d2SAndroid Build Coastguard Worker     appleheader[0]  = (unsigned char)r->header.cupsBitsPerPixel;
1135*5e7646d2SAndroid Build Coastguard Worker     appleheader[1]  = r->header.cupsColorSpace == CUPS_CSPACE_SRGB ? 1 :
1136*5e7646d2SAndroid Build Coastguard Worker                         r->header.cupsColorSpace == CUPS_CSPACE_CIELab ? 2 :
1137*5e7646d2SAndroid Build Coastguard Worker                         r->header.cupsColorSpace == CUPS_CSPACE_ADOBERGB ? 3 :
1138*5e7646d2SAndroid Build Coastguard Worker                         r->header.cupsColorSpace == CUPS_CSPACE_W ? 4 :
1139*5e7646d2SAndroid Build Coastguard Worker                         r->header.cupsColorSpace == CUPS_CSPACE_RGB ? 5 :
1140*5e7646d2SAndroid Build Coastguard Worker                         r->header.cupsColorSpace == CUPS_CSPACE_CMYK ? 6 : 0;
1141*5e7646d2SAndroid Build Coastguard Worker     appleheader[2]  = r->header.Duplex ? (r->header.Tumble ? 2 : 3) : 1;
1142*5e7646d2SAndroid Build Coastguard Worker     appleheader[3]  = (unsigned char)(r->header.cupsInteger[CUPS_RASTER_PWG_PrintQuality]);
1143*5e7646d2SAndroid Build Coastguard Worker     appleheader[5]  = (unsigned char)(r->header.MediaPosition);
1144*5e7646d2SAndroid Build Coastguard Worker     appleheader[12] = (unsigned char)(r->header.cupsWidth >> 24);
1145*5e7646d2SAndroid Build Coastguard Worker     appleheader[13] = (unsigned char)(r->header.cupsWidth >> 16);
1146*5e7646d2SAndroid Build Coastguard Worker     appleheader[14] = (unsigned char)(r->header.cupsWidth >> 8);
1147*5e7646d2SAndroid Build Coastguard Worker     appleheader[15] = (unsigned char)(r->header.cupsWidth);
1148*5e7646d2SAndroid Build Coastguard Worker     appleheader[16] = (unsigned char)(height >> 24);
1149*5e7646d2SAndroid Build Coastguard Worker     appleheader[17] = (unsigned char)(height >> 16);
1150*5e7646d2SAndroid Build Coastguard Worker     appleheader[18] = (unsigned char)(height >> 8);
1151*5e7646d2SAndroid Build Coastguard Worker     appleheader[19] = (unsigned char)(height);
1152*5e7646d2SAndroid Build Coastguard Worker     appleheader[20] = (unsigned char)(r->header.HWResolution[0] >> 24);
1153*5e7646d2SAndroid Build Coastguard Worker     appleheader[21] = (unsigned char)(r->header.HWResolution[0] >> 16);
1154*5e7646d2SAndroid Build Coastguard Worker     appleheader[22] = (unsigned char)(r->header.HWResolution[0] >> 8);
1155*5e7646d2SAndroid Build Coastguard Worker     appleheader[23] = (unsigned char)(r->header.HWResolution[0]);
1156*5e7646d2SAndroid Build Coastguard Worker 
1157*5e7646d2SAndroid Build Coastguard Worker     for (i = 0; i < (int)(sizeof(apple_media_types) / sizeof(apple_media_types[0])); i ++)
1158*5e7646d2SAndroid Build Coastguard Worker     {
1159*5e7646d2SAndroid Build Coastguard Worker       if (!strcmp(r->header.MediaType, apple_media_types[i]))
1160*5e7646d2SAndroid Build Coastguard Worker       {
1161*5e7646d2SAndroid Build Coastguard Worker         appleheader[4] = (unsigned char)i;
1162*5e7646d2SAndroid Build Coastguard Worker         break;
1163*5e7646d2SAndroid Build Coastguard Worker       }
1164*5e7646d2SAndroid Build Coastguard Worker     }
1165*5e7646d2SAndroid Build Coastguard Worker 
1166*5e7646d2SAndroid Build Coastguard Worker     return (cups_raster_io(r, appleheader, sizeof(appleheader)) == sizeof(appleheader));
1167*5e7646d2SAndroid Build Coastguard Worker   }
1168*5e7646d2SAndroid Build Coastguard Worker   else
1169*5e7646d2SAndroid Build Coastguard Worker     return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
1170*5e7646d2SAndroid Build Coastguard Worker 		== sizeof(r->header));
1171*5e7646d2SAndroid Build Coastguard Worker }
1172*5e7646d2SAndroid Build Coastguard Worker 
1173*5e7646d2SAndroid Build Coastguard Worker 
1174*5e7646d2SAndroid Build Coastguard Worker /*
1175*5e7646d2SAndroid Build Coastguard Worker  * '_cupsRasterWritePixels()' - Write raster pixels.
1176*5e7646d2SAndroid Build Coastguard Worker  *
1177*5e7646d2SAndroid Build Coastguard Worker  * For best performance, filters should write one or more whole lines.
1178*5e7646d2SAndroid Build Coastguard Worker  * The "cupsBytesPerLine" value from the page header can be used to allocate
1179*5e7646d2SAndroid Build Coastguard Worker  * the line buffer and as the number of bytes to write.
1180*5e7646d2SAndroid Build Coastguard Worker  */
1181*5e7646d2SAndroid Build Coastguard Worker 
1182*5e7646d2SAndroid Build Coastguard Worker unsigned				/* O - Number of bytes written */
_cupsRasterWritePixels(cups_raster_t * r,unsigned char * p,unsigned len)1183*5e7646d2SAndroid Build Coastguard Worker _cupsRasterWritePixels(
1184*5e7646d2SAndroid Build Coastguard Worker     cups_raster_t *r,			/* I - Raster stream */
1185*5e7646d2SAndroid Build Coastguard Worker     unsigned char *p,			/* I - Bytes to write */
1186*5e7646d2SAndroid Build Coastguard Worker     unsigned      len)			/* I - Number of bytes to write */
1187*5e7646d2SAndroid Build Coastguard Worker {
1188*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes;			/* Bytes read */
1189*5e7646d2SAndroid Build Coastguard Worker   unsigned	remaining;		/* Bytes remaining */
1190*5e7646d2SAndroid Build Coastguard Worker 
1191*5e7646d2SAndroid Build Coastguard Worker 
1192*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("_cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u", (void *)r, (void *)p, len, r->remaining));
1193*5e7646d2SAndroid Build Coastguard Worker 
1194*5e7646d2SAndroid Build Coastguard Worker   if (r == NULL || r->mode == CUPS_RASTER_READ || r->remaining == 0)
1195*5e7646d2SAndroid Build Coastguard Worker     return (0);
1196*5e7646d2SAndroid Build Coastguard Worker 
1197*5e7646d2SAndroid Build Coastguard Worker   if (!r->compressed)
1198*5e7646d2SAndroid Build Coastguard Worker   {
1199*5e7646d2SAndroid Build Coastguard Worker    /*
1200*5e7646d2SAndroid Build Coastguard Worker     * Without compression, just write the raster data raw unless the data needs
1201*5e7646d2SAndroid Build Coastguard Worker     * to be swapped...
1202*5e7646d2SAndroid Build Coastguard Worker     */
1203*5e7646d2SAndroid Build Coastguard Worker 
1204*5e7646d2SAndroid Build Coastguard Worker     r->remaining -= len / r->header.cupsBytesPerLine;
1205*5e7646d2SAndroid Build Coastguard Worker 
1206*5e7646d2SAndroid Build Coastguard Worker     if (r->swapped &&
1207*5e7646d2SAndroid Build Coastguard Worker         (r->header.cupsBitsPerColor == 16 ||
1208*5e7646d2SAndroid Build Coastguard Worker          r->header.cupsBitsPerPixel == 12 ||
1209*5e7646d2SAndroid Build Coastguard Worker          r->header.cupsBitsPerPixel == 16))
1210*5e7646d2SAndroid Build Coastguard Worker     {
1211*5e7646d2SAndroid Build Coastguard Worker       unsigned char	*bufptr;	/* Pointer into write buffer */
1212*5e7646d2SAndroid Build Coastguard Worker 
1213*5e7646d2SAndroid Build Coastguard Worker      /*
1214*5e7646d2SAndroid Build Coastguard Worker       * Allocate a write buffer as needed...
1215*5e7646d2SAndroid Build Coastguard Worker       */
1216*5e7646d2SAndroid Build Coastguard Worker 
1217*5e7646d2SAndroid Build Coastguard Worker       if ((size_t)len > r->bufsize)
1218*5e7646d2SAndroid Build Coastguard Worker       {
1219*5e7646d2SAndroid Build Coastguard Worker 	if (r->buffer)
1220*5e7646d2SAndroid Build Coastguard Worker 	  bufptr = realloc(r->buffer, len);
1221*5e7646d2SAndroid Build Coastguard Worker 	else
1222*5e7646d2SAndroid Build Coastguard Worker 	  bufptr = malloc(len);
1223*5e7646d2SAndroid Build Coastguard Worker 
1224*5e7646d2SAndroid Build Coastguard Worker 	if (!bufptr)
1225*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
1226*5e7646d2SAndroid Build Coastguard Worker 
1227*5e7646d2SAndroid Build Coastguard Worker 	r->buffer  = bufptr;
1228*5e7646d2SAndroid Build Coastguard Worker 	r->bufsize = len;
1229*5e7646d2SAndroid Build Coastguard Worker       }
1230*5e7646d2SAndroid Build Coastguard Worker 
1231*5e7646d2SAndroid Build Coastguard Worker      /*
1232*5e7646d2SAndroid Build Coastguard Worker       * Byte swap the pixels and write them...
1233*5e7646d2SAndroid Build Coastguard Worker       */
1234*5e7646d2SAndroid Build Coastguard Worker 
1235*5e7646d2SAndroid Build Coastguard Worker       cups_swap_copy(r->buffer, p, len);
1236*5e7646d2SAndroid Build Coastguard Worker 
1237*5e7646d2SAndroid Build Coastguard Worker       bytes = cups_raster_io(r, r->buffer, len);
1238*5e7646d2SAndroid Build Coastguard Worker     }
1239*5e7646d2SAndroid Build Coastguard Worker     else
1240*5e7646d2SAndroid Build Coastguard Worker       bytes = cups_raster_io(r, p, len);
1241*5e7646d2SAndroid Build Coastguard Worker 
1242*5e7646d2SAndroid Build Coastguard Worker     if (bytes < (ssize_t)len)
1243*5e7646d2SAndroid Build Coastguard Worker       return (0);
1244*5e7646d2SAndroid Build Coastguard Worker     else
1245*5e7646d2SAndroid Build Coastguard Worker       return (len);
1246*5e7646d2SAndroid Build Coastguard Worker   }
1247*5e7646d2SAndroid Build Coastguard Worker 
1248*5e7646d2SAndroid Build Coastguard Worker  /*
1249*5e7646d2SAndroid Build Coastguard Worker   * Otherwise, compress each line...
1250*5e7646d2SAndroid Build Coastguard Worker   */
1251*5e7646d2SAndroid Build Coastguard Worker 
1252*5e7646d2SAndroid Build Coastguard Worker   for (remaining = len; remaining > 0; remaining -= (unsigned)bytes, p += bytes)
1253*5e7646d2SAndroid Build Coastguard Worker   {
1254*5e7646d2SAndroid Build Coastguard Worker    /*
1255*5e7646d2SAndroid Build Coastguard Worker     * Figure out the number of remaining bytes on the current line...
1256*5e7646d2SAndroid Build Coastguard Worker     */
1257*5e7646d2SAndroid Build Coastguard Worker 
1258*5e7646d2SAndroid Build Coastguard Worker     if ((bytes = (ssize_t)remaining) > (ssize_t)(r->pend - r->pcurrent))
1259*5e7646d2SAndroid Build Coastguard Worker       bytes = (ssize_t)(r->pend - r->pcurrent);
1260*5e7646d2SAndroid Build Coastguard Worker 
1261*5e7646d2SAndroid Build Coastguard Worker     if (r->count > 0)
1262*5e7646d2SAndroid Build Coastguard Worker     {
1263*5e7646d2SAndroid Build Coastguard Worker      /*
1264*5e7646d2SAndroid Build Coastguard Worker       * Check to see if this line is the same as the previous line...
1265*5e7646d2SAndroid Build Coastguard Worker       */
1266*5e7646d2SAndroid Build Coastguard Worker 
1267*5e7646d2SAndroid Build Coastguard Worker       if (memcmp(p, r->pcurrent, (size_t)bytes))
1268*5e7646d2SAndroid Build Coastguard Worker       {
1269*5e7646d2SAndroid Build Coastguard Worker         if (cups_raster_write(r, r->pixels) <= 0)
1270*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
1271*5e7646d2SAndroid Build Coastguard Worker 
1272*5e7646d2SAndroid Build Coastguard Worker 	r->count = 0;
1273*5e7646d2SAndroid Build Coastguard Worker       }
1274*5e7646d2SAndroid Build Coastguard Worker       else
1275*5e7646d2SAndroid Build Coastguard Worker       {
1276*5e7646d2SAndroid Build Coastguard Worker        /*
1277*5e7646d2SAndroid Build Coastguard Worker         * Mark more bytes as the same...
1278*5e7646d2SAndroid Build Coastguard Worker 	*/
1279*5e7646d2SAndroid Build Coastguard Worker 
1280*5e7646d2SAndroid Build Coastguard Worker         r->pcurrent += bytes;
1281*5e7646d2SAndroid Build Coastguard Worker 
1282*5e7646d2SAndroid Build Coastguard Worker 	if (r->pcurrent >= r->pend)
1283*5e7646d2SAndroid Build Coastguard Worker 	{
1284*5e7646d2SAndroid Build Coastguard Worker 	 /*
1285*5e7646d2SAndroid Build Coastguard Worker           * Increase the repeat count...
1286*5e7646d2SAndroid Build Coastguard Worker 	  */
1287*5e7646d2SAndroid Build Coastguard Worker 
1288*5e7646d2SAndroid Build Coastguard Worker 	  r->count += r->rowheight;
1289*5e7646d2SAndroid Build Coastguard Worker 	  r->pcurrent = r->pixels;
1290*5e7646d2SAndroid Build Coastguard Worker 
1291*5e7646d2SAndroid Build Coastguard Worker 	 /*
1292*5e7646d2SAndroid Build Coastguard Worker           * Flush out this line if it is the last one...
1293*5e7646d2SAndroid Build Coastguard Worker 	  */
1294*5e7646d2SAndroid Build Coastguard Worker 
1295*5e7646d2SAndroid Build Coastguard Worker 	  r->remaining --;
1296*5e7646d2SAndroid Build Coastguard Worker 
1297*5e7646d2SAndroid Build Coastguard Worker 	  if (r->remaining == 0)
1298*5e7646d2SAndroid Build Coastguard Worker 	  {
1299*5e7646d2SAndroid Build Coastguard Worker 	    if (cups_raster_write(r, r->pixels) <= 0)
1300*5e7646d2SAndroid Build Coastguard Worker 	      return (0);
1301*5e7646d2SAndroid Build Coastguard Worker 	    else
1302*5e7646d2SAndroid Build Coastguard Worker 	      return (len);
1303*5e7646d2SAndroid Build Coastguard Worker 	  }
1304*5e7646d2SAndroid Build Coastguard Worker 	  else if (r->count > (256 - r->rowheight))
1305*5e7646d2SAndroid Build Coastguard Worker 	  {
1306*5e7646d2SAndroid Build Coastguard Worker 	    if (cups_raster_write(r, r->pixels) <= 0)
1307*5e7646d2SAndroid Build Coastguard Worker 	      return (0);
1308*5e7646d2SAndroid Build Coastguard Worker 
1309*5e7646d2SAndroid Build Coastguard Worker 	    r->count = 0;
1310*5e7646d2SAndroid Build Coastguard Worker 	  }
1311*5e7646d2SAndroid Build Coastguard Worker 	}
1312*5e7646d2SAndroid Build Coastguard Worker 
1313*5e7646d2SAndroid Build Coastguard Worker 	continue;
1314*5e7646d2SAndroid Build Coastguard Worker       }
1315*5e7646d2SAndroid Build Coastguard Worker     }
1316*5e7646d2SAndroid Build Coastguard Worker 
1317*5e7646d2SAndroid Build Coastguard Worker     if (r->count == 0)
1318*5e7646d2SAndroid Build Coastguard Worker     {
1319*5e7646d2SAndroid Build Coastguard Worker      /*
1320*5e7646d2SAndroid Build Coastguard Worker       * Copy the raster data to the buffer...
1321*5e7646d2SAndroid Build Coastguard Worker       */
1322*5e7646d2SAndroid Build Coastguard Worker 
1323*5e7646d2SAndroid Build Coastguard Worker       memcpy(r->pcurrent, p, (size_t)bytes);
1324*5e7646d2SAndroid Build Coastguard Worker 
1325*5e7646d2SAndroid Build Coastguard Worker       r->pcurrent += bytes;
1326*5e7646d2SAndroid Build Coastguard Worker 
1327*5e7646d2SAndroid Build Coastguard Worker       if (r->pcurrent >= r->pend)
1328*5e7646d2SAndroid Build Coastguard Worker       {
1329*5e7646d2SAndroid Build Coastguard Worker        /*
1330*5e7646d2SAndroid Build Coastguard Worker         * Increase the repeat count...
1331*5e7646d2SAndroid Build Coastguard Worker 	*/
1332*5e7646d2SAndroid Build Coastguard Worker 
1333*5e7646d2SAndroid Build Coastguard Worker 	r->count += r->rowheight;
1334*5e7646d2SAndroid Build Coastguard Worker 	r->pcurrent = r->pixels;
1335*5e7646d2SAndroid Build Coastguard Worker 
1336*5e7646d2SAndroid Build Coastguard Worker        /*
1337*5e7646d2SAndroid Build Coastguard Worker         * Flush out this line if it is the last one...
1338*5e7646d2SAndroid Build Coastguard Worker 	*/
1339*5e7646d2SAndroid Build Coastguard Worker 
1340*5e7646d2SAndroid Build Coastguard Worker 	r->remaining --;
1341*5e7646d2SAndroid Build Coastguard Worker 
1342*5e7646d2SAndroid Build Coastguard Worker 	if (r->remaining == 0)
1343*5e7646d2SAndroid Build Coastguard Worker 	{
1344*5e7646d2SAndroid Build Coastguard Worker 	  if (cups_raster_write(r, r->pixels) <= 0)
1345*5e7646d2SAndroid Build Coastguard Worker 	    return (0);
1346*5e7646d2SAndroid Build Coastguard Worker 	}
1347*5e7646d2SAndroid Build Coastguard Worker       }
1348*5e7646d2SAndroid Build Coastguard Worker     }
1349*5e7646d2SAndroid Build Coastguard Worker   }
1350*5e7646d2SAndroid Build Coastguard Worker 
1351*5e7646d2SAndroid Build Coastguard Worker   return (len);
1352*5e7646d2SAndroid Build Coastguard Worker }
1353*5e7646d2SAndroid Build Coastguard Worker 
1354*5e7646d2SAndroid Build Coastguard Worker 
1355*5e7646d2SAndroid Build Coastguard Worker /*
1356*5e7646d2SAndroid Build Coastguard Worker  * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
1357*5e7646d2SAndroid Build Coastguard Worker  */
1358*5e7646d2SAndroid Build Coastguard Worker 
1359*5e7646d2SAndroid Build Coastguard Worker static ssize_t				/* O - Bytes read/write or -1 */
cups_raster_io(cups_raster_t * r,unsigned char * buf,size_t bytes)1360*5e7646d2SAndroid Build Coastguard Worker cups_raster_io(cups_raster_t *r,	/* I - Raster stream */
1361*5e7646d2SAndroid Build Coastguard Worker                unsigned char *buf,	/* I - Buffer for read/write */
1362*5e7646d2SAndroid Build Coastguard Worker                size_t        bytes)	/* I - Number of bytes to read/write */
1363*5e7646d2SAndroid Build Coastguard Worker {
1364*5e7646d2SAndroid Build Coastguard Worker   ssize_t	count,			/* Number of bytes read/written */
1365*5e7646d2SAndroid Build Coastguard Worker 		total;			/* Total bytes read/written */
1366*5e7646d2SAndroid Build Coastguard Worker 
1367*5e7646d2SAndroid Build Coastguard Worker 
1368*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)r, (void *)buf, CUPS_LLCAST bytes));
1369*5e7646d2SAndroid Build Coastguard Worker 
1370*5e7646d2SAndroid Build Coastguard Worker   for (total = 0; total < (ssize_t)bytes; total += count, buf += count)
1371*5e7646d2SAndroid Build Coastguard Worker   {
1372*5e7646d2SAndroid Build Coastguard Worker     count = (*r->iocb)(r->ctx, buf, bytes - (size_t)total);
1373*5e7646d2SAndroid Build Coastguard Worker 
1374*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count, (int)total));
1375*5e7646d2SAndroid Build Coastguard Worker     if (count == 0)
1376*5e7646d2SAndroid Build Coastguard Worker       break;
1377*5e7646d2SAndroid Build Coastguard Worker //    {
1378*5e7646d2SAndroid Build Coastguard Worker //      DEBUG_puts("6cups_raster_io: Returning 0.");
1379*5e7646d2SAndroid Build Coastguard Worker //      return (0);
1380*5e7646d2SAndroid Build Coastguard Worker //    }
1381*5e7646d2SAndroid Build Coastguard Worker     else if (count < 0)
1382*5e7646d2SAndroid Build Coastguard Worker     {
1383*5e7646d2SAndroid Build Coastguard Worker       DEBUG_puts("6cups_raster_io: Returning -1 on error.");
1384*5e7646d2SAndroid Build Coastguard Worker       return (-1);
1385*5e7646d2SAndroid Build Coastguard Worker     }
1386*5e7646d2SAndroid Build Coastguard Worker 
1387*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
1388*5e7646d2SAndroid Build Coastguard Worker     r->iocount += (size_t)count;
1389*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
1390*5e7646d2SAndroid Build Coastguard Worker   }
1391*5e7646d2SAndroid Build Coastguard Worker 
1392*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("6cups_raster_io: iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
1393*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT ".", CUPS_LLCAST total));
1394*5e7646d2SAndroid Build Coastguard Worker 
1395*5e7646d2SAndroid Build Coastguard Worker   return (total);
1396*5e7646d2SAndroid Build Coastguard Worker }
1397*5e7646d2SAndroid Build Coastguard Worker 
1398*5e7646d2SAndroid Build Coastguard Worker 
1399*5e7646d2SAndroid Build Coastguard Worker /*
1400*5e7646d2SAndroid Build Coastguard Worker  * 'cups_raster_read()' - Read through the raster buffer.
1401*5e7646d2SAndroid Build Coastguard Worker  */
1402*5e7646d2SAndroid Build Coastguard Worker 
1403*5e7646d2SAndroid Build Coastguard Worker static ssize_t				/* O - Number of bytes read */
cups_raster_read(cups_raster_t * r,unsigned char * buf,size_t bytes)1404*5e7646d2SAndroid Build Coastguard Worker cups_raster_read(cups_raster_t *r,	/* I - Raster stream */
1405*5e7646d2SAndroid Build Coastguard Worker                  unsigned char *buf,	/* I - Buffer */
1406*5e7646d2SAndroid Build Coastguard Worker                  size_t        bytes)	/* I - Number of bytes to read */
1407*5e7646d2SAndroid Build Coastguard Worker {
1408*5e7646d2SAndroid Build Coastguard Worker   ssize_t	count,			/* Number of bytes read */
1409*5e7646d2SAndroid Build Coastguard Worker 		remaining,		/* Remaining bytes in buffer */
1410*5e7646d2SAndroid Build Coastguard Worker 		total;			/* Total bytes read */
1411*5e7646d2SAndroid Build Coastguard Worker 
1412*5e7646d2SAndroid Build Coastguard Worker 
1413*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT "), offset=" CUPS_LLFMT, (void *)r, (void *)buf, CUPS_LLCAST bytes, CUPS_LLCAST (r->iostart + r->bufptr - r->buffer)));
1414*5e7646d2SAndroid Build Coastguard Worker 
1415*5e7646d2SAndroid Build Coastguard Worker   if (!r->compressed)
1416*5e7646d2SAndroid Build Coastguard Worker     return (cups_raster_io(r, buf, bytes));
1417*5e7646d2SAndroid Build Coastguard Worker 
1418*5e7646d2SAndroid Build Coastguard Worker  /*
1419*5e7646d2SAndroid Build Coastguard Worker   * Allocate a read buffer as needed...
1420*5e7646d2SAndroid Build Coastguard Worker   */
1421*5e7646d2SAndroid Build Coastguard Worker 
1422*5e7646d2SAndroid Build Coastguard Worker   count = (ssize_t)(2 * r->header.cupsBytesPerLine);
1423*5e7646d2SAndroid Build Coastguard Worker   if (count < 65536)
1424*5e7646d2SAndroid Build Coastguard Worker     count = 65536;
1425*5e7646d2SAndroid Build Coastguard Worker 
1426*5e7646d2SAndroid Build Coastguard Worker   if ((size_t)count > r->bufsize)
1427*5e7646d2SAndroid Build Coastguard Worker   {
1428*5e7646d2SAndroid Build Coastguard Worker     ssize_t offset = r->bufptr - r->buffer;
1429*5e7646d2SAndroid Build Coastguard Worker 					/* Offset to current start of buffer */
1430*5e7646d2SAndroid Build Coastguard Worker     ssize_t end = r->bufend - r->buffer;/* Offset to current end of buffer */
1431*5e7646d2SAndroid Build Coastguard Worker     unsigned char *rptr;		/* Pointer in read buffer */
1432*5e7646d2SAndroid Build Coastguard Worker 
1433*5e7646d2SAndroid Build Coastguard Worker     if (r->buffer)
1434*5e7646d2SAndroid Build Coastguard Worker       rptr = realloc(r->buffer, (size_t)count);
1435*5e7646d2SAndroid Build Coastguard Worker     else
1436*5e7646d2SAndroid Build Coastguard Worker       rptr = malloc((size_t)count);
1437*5e7646d2SAndroid Build Coastguard Worker 
1438*5e7646d2SAndroid Build Coastguard Worker     if (!rptr)
1439*5e7646d2SAndroid Build Coastguard Worker       return (0);
1440*5e7646d2SAndroid Build Coastguard Worker 
1441*5e7646d2SAndroid Build Coastguard Worker     r->buffer  = rptr;
1442*5e7646d2SAndroid Build Coastguard Worker     r->bufptr  = rptr + offset;
1443*5e7646d2SAndroid Build Coastguard Worker     r->bufend  = rptr + end;
1444*5e7646d2SAndroid Build Coastguard Worker     r->bufsize = (size_t)count;
1445*5e7646d2SAndroid Build Coastguard Worker   }
1446*5e7646d2SAndroid Build Coastguard Worker 
1447*5e7646d2SAndroid Build Coastguard Worker  /*
1448*5e7646d2SAndroid Build Coastguard Worker   * Loop until we have read everything...
1449*5e7646d2SAndroid Build Coastguard Worker   */
1450*5e7646d2SAndroid Build Coastguard Worker 
1451*5e7646d2SAndroid Build Coastguard Worker   for (total = 0, remaining = (int)(r->bufend - r->bufptr);
1452*5e7646d2SAndroid Build Coastguard Worker        total < (ssize_t)bytes;
1453*5e7646d2SAndroid Build Coastguard Worker        total += count, buf += count)
1454*5e7646d2SAndroid Build Coastguard Worker   {
1455*5e7646d2SAndroid Build Coastguard Worker     count = (ssize_t)bytes - total;
1456*5e7646d2SAndroid Build Coastguard Worker 
1457*5e7646d2SAndroid Build Coastguard Worker     DEBUG_printf(("5cups_raster_read: count=" CUPS_LLFMT ", remaining=" CUPS_LLFMT ", buf=%p, bufptr=%p, bufend=%p", CUPS_LLCAST count, CUPS_LLCAST remaining, (void *)buf, (void *)r->bufptr, (void *)r->bufend));
1458*5e7646d2SAndroid Build Coastguard Worker 
1459*5e7646d2SAndroid Build Coastguard Worker     if (remaining == 0)
1460*5e7646d2SAndroid Build Coastguard Worker     {
1461*5e7646d2SAndroid Build Coastguard Worker       if (count < 16)
1462*5e7646d2SAndroid Build Coastguard Worker       {
1463*5e7646d2SAndroid Build Coastguard Worker        /*
1464*5e7646d2SAndroid Build Coastguard Worker         * Read into the raster buffer and then copy...
1465*5e7646d2SAndroid Build Coastguard Worker 	*/
1466*5e7646d2SAndroid Build Coastguard Worker 
1467*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
1468*5e7646d2SAndroid Build Coastguard Worker         r->iostart += (size_t)(r->bufend - r->buffer);
1469*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
1470*5e7646d2SAndroid Build Coastguard Worker 
1471*5e7646d2SAndroid Build Coastguard Worker         remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize);
1472*5e7646d2SAndroid Build Coastguard Worker 	if (remaining <= 0)
1473*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
1474*5e7646d2SAndroid Build Coastguard Worker 
1475*5e7646d2SAndroid Build Coastguard Worker 	r->bufptr = r->buffer;
1476*5e7646d2SAndroid Build Coastguard Worker 	r->bufend = r->buffer + remaining;
1477*5e7646d2SAndroid Build Coastguard Worker 
1478*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
1479*5e7646d2SAndroid Build Coastguard Worker         r->iocount += (size_t)remaining;
1480*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
1481*5e7646d2SAndroid Build Coastguard Worker       }
1482*5e7646d2SAndroid Build Coastguard Worker       else
1483*5e7646d2SAndroid Build Coastguard Worker       {
1484*5e7646d2SAndroid Build Coastguard Worker        /*
1485*5e7646d2SAndroid Build Coastguard Worker         * Read directly into "buf"...
1486*5e7646d2SAndroid Build Coastguard Worker 	*/
1487*5e7646d2SAndroid Build Coastguard Worker 
1488*5e7646d2SAndroid Build Coastguard Worker 	count = (*r->iocb)(r->ctx, buf, (size_t)count);
1489*5e7646d2SAndroid Build Coastguard Worker 
1490*5e7646d2SAndroid Build Coastguard Worker 	if (count <= 0)
1491*5e7646d2SAndroid Build Coastguard Worker 	  return (0);
1492*5e7646d2SAndroid Build Coastguard Worker 
1493*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
1494*5e7646d2SAndroid Build Coastguard Worker 	r->iostart += (size_t)count;
1495*5e7646d2SAndroid Build Coastguard Worker         r->iocount += (size_t)count;
1496*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
1497*5e7646d2SAndroid Build Coastguard Worker 
1498*5e7646d2SAndroid Build Coastguard Worker 	continue;
1499*5e7646d2SAndroid Build Coastguard Worker       }
1500*5e7646d2SAndroid Build Coastguard Worker     }
1501*5e7646d2SAndroid Build Coastguard Worker 
1502*5e7646d2SAndroid Build Coastguard Worker    /*
1503*5e7646d2SAndroid Build Coastguard Worker     * Copy bytes from raster buffer to "buf"...
1504*5e7646d2SAndroid Build Coastguard Worker     */
1505*5e7646d2SAndroid Build Coastguard Worker 
1506*5e7646d2SAndroid Build Coastguard Worker     if (count > remaining)
1507*5e7646d2SAndroid Build Coastguard Worker       count = remaining;
1508*5e7646d2SAndroid Build Coastguard Worker 
1509*5e7646d2SAndroid Build Coastguard Worker     if (count == 1)
1510*5e7646d2SAndroid Build Coastguard Worker     {
1511*5e7646d2SAndroid Build Coastguard Worker      /*
1512*5e7646d2SAndroid Build Coastguard Worker       * Copy 1 byte...
1513*5e7646d2SAndroid Build Coastguard Worker       */
1514*5e7646d2SAndroid Build Coastguard Worker 
1515*5e7646d2SAndroid Build Coastguard Worker       *buf = *(r->bufptr)++;
1516*5e7646d2SAndroid Build Coastguard Worker       remaining --;
1517*5e7646d2SAndroid Build Coastguard Worker     }
1518*5e7646d2SAndroid Build Coastguard Worker     else if (count < 128)
1519*5e7646d2SAndroid Build Coastguard Worker     {
1520*5e7646d2SAndroid Build Coastguard Worker      /*
1521*5e7646d2SAndroid Build Coastguard Worker       * Copy up to 127 bytes without using memcpy(); this is
1522*5e7646d2SAndroid Build Coastguard Worker       * faster because it avoids an extra function call and is
1523*5e7646d2SAndroid Build Coastguard Worker       * often further optimized by the compiler...
1524*5e7646d2SAndroid Build Coastguard Worker       */
1525*5e7646d2SAndroid Build Coastguard Worker 
1526*5e7646d2SAndroid Build Coastguard Worker       unsigned char	*bufptr;	/* Temporary buffer pointer */
1527*5e7646d2SAndroid Build Coastguard Worker 
1528*5e7646d2SAndroid Build Coastguard Worker       remaining -= count;
1529*5e7646d2SAndroid Build Coastguard Worker 
1530*5e7646d2SAndroid Build Coastguard Worker       for (bufptr = r->bufptr; count > 0; count --, total ++)
1531*5e7646d2SAndroid Build Coastguard Worker 	*buf++ = *bufptr++;
1532*5e7646d2SAndroid Build Coastguard Worker 
1533*5e7646d2SAndroid Build Coastguard Worker       r->bufptr = bufptr;
1534*5e7646d2SAndroid Build Coastguard Worker     }
1535*5e7646d2SAndroid Build Coastguard Worker     else
1536*5e7646d2SAndroid Build Coastguard Worker     {
1537*5e7646d2SAndroid Build Coastguard Worker      /*
1538*5e7646d2SAndroid Build Coastguard Worker       * Use memcpy() for a large read...
1539*5e7646d2SAndroid Build Coastguard Worker       */
1540*5e7646d2SAndroid Build Coastguard Worker 
1541*5e7646d2SAndroid Build Coastguard Worker       memcpy(buf, r->bufptr, (size_t)count);
1542*5e7646d2SAndroid Build Coastguard Worker       r->bufptr += count;
1543*5e7646d2SAndroid Build Coastguard Worker       remaining -= count;
1544*5e7646d2SAndroid Build Coastguard Worker     }
1545*5e7646d2SAndroid Build Coastguard Worker   }
1546*5e7646d2SAndroid Build Coastguard Worker 
1547*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("5cups_raster_read: Returning %ld", (long)total));
1548*5e7646d2SAndroid Build Coastguard Worker 
1549*5e7646d2SAndroid Build Coastguard Worker   return (total);
1550*5e7646d2SAndroid Build Coastguard Worker }
1551*5e7646d2SAndroid Build Coastguard Worker 
1552*5e7646d2SAndroid Build Coastguard Worker 
1553*5e7646d2SAndroid Build Coastguard Worker /*
1554*5e7646d2SAndroid Build Coastguard Worker  * 'cups_raster_update()' - Update the raster header and row count for the
1555*5e7646d2SAndroid Build Coastguard Worker  *                          current page.
1556*5e7646d2SAndroid Build Coastguard Worker  */
1557*5e7646d2SAndroid Build Coastguard Worker 
1558*5e7646d2SAndroid Build Coastguard Worker static int				/* O - 1 on success, 0 on failure */
cups_raster_update(cups_raster_t * r)1559*5e7646d2SAndroid Build Coastguard Worker cups_raster_update(cups_raster_t *r)	/* I - Raster stream */
1560*5e7646d2SAndroid Build Coastguard Worker {
1561*5e7646d2SAndroid Build Coastguard Worker   if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 ||
1562*5e7646d2SAndroid Build Coastguard Worker       r->header.cupsNumColors == 0)
1563*5e7646d2SAndroid Build Coastguard Worker   {
1564*5e7646d2SAndroid Build Coastguard Worker    /*
1565*5e7646d2SAndroid Build Coastguard Worker     * Set the "cupsNumColors" field according to the colorspace...
1566*5e7646d2SAndroid Build Coastguard Worker     */
1567*5e7646d2SAndroid Build Coastguard Worker 
1568*5e7646d2SAndroid Build Coastguard Worker     switch (r->header.cupsColorSpace)
1569*5e7646d2SAndroid Build Coastguard Worker     {
1570*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_W :
1571*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_K :
1572*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_WHITE :
1573*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_GOLD :
1574*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_SILVER :
1575*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_SW :
1576*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsNumColors = 1;
1577*5e7646d2SAndroid Build Coastguard Worker 	  break;
1578*5e7646d2SAndroid Build Coastguard Worker 
1579*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_RGB :
1580*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_CMY :
1581*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_YMC :
1582*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_CIEXYZ :
1583*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_CIELab :
1584*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_SRGB :
1585*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ADOBERGB :
1586*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICC1 :
1587*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICC2 :
1588*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICC3 :
1589*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICC4 :
1590*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICC5 :
1591*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICC6 :
1592*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICC7 :
1593*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICC8 :
1594*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICC9 :
1595*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICCA :
1596*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICCB :
1597*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICCC :
1598*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICCD :
1599*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICCE :
1600*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_ICCF :
1601*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsNumColors = 3;
1602*5e7646d2SAndroid Build Coastguard Worker 	  break;
1603*5e7646d2SAndroid Build Coastguard Worker 
1604*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_RGBA :
1605*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_RGBW :
1606*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_CMYK :
1607*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_YMCK :
1608*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_KCMY :
1609*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_GMCK :
1610*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_GMCS :
1611*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsNumColors = 4;
1612*5e7646d2SAndroid Build Coastguard Worker 	  break;
1613*5e7646d2SAndroid Build Coastguard Worker 
1614*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_KCMYcm :
1615*5e7646d2SAndroid Build Coastguard Worker           if (r->header.cupsBitsPerPixel < 8)
1616*5e7646d2SAndroid Build Coastguard Worker             r->header.cupsNumColors = 6;
1617*5e7646d2SAndroid Build Coastguard Worker 	  else
1618*5e7646d2SAndroid Build Coastguard Worker             r->header.cupsNumColors = 4;
1619*5e7646d2SAndroid Build Coastguard Worker 	  break;
1620*5e7646d2SAndroid Build Coastguard Worker 
1621*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICE1 :
1622*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICE2 :
1623*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICE3 :
1624*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICE4 :
1625*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICE5 :
1626*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICE6 :
1627*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICE7 :
1628*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICE8 :
1629*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICE9 :
1630*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICEA :
1631*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICEB :
1632*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICEC :
1633*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICED :
1634*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICEE :
1635*5e7646d2SAndroid Build Coastguard Worker       case CUPS_CSPACE_DEVICEF :
1636*5e7646d2SAndroid Build Coastguard Worker           r->header.cupsNumColors = r->header.cupsColorSpace -
1637*5e7646d2SAndroid Build Coastguard Worker 	                            CUPS_CSPACE_DEVICE1 + 1;
1638*5e7646d2SAndroid Build Coastguard Worker 	  break;
1639*5e7646d2SAndroid Build Coastguard Worker 
1640*5e7646d2SAndroid Build Coastguard Worker       default :
1641*5e7646d2SAndroid Build Coastguard Worker           /* Unknown color space */
1642*5e7646d2SAndroid Build Coastguard Worker           return (0);
1643*5e7646d2SAndroid Build Coastguard Worker     }
1644*5e7646d2SAndroid Build Coastguard Worker   }
1645*5e7646d2SAndroid Build Coastguard Worker 
1646*5e7646d2SAndroid Build Coastguard Worker  /*
1647*5e7646d2SAndroid Build Coastguard Worker   * Set the number of bytes per pixel/color...
1648*5e7646d2SAndroid Build Coastguard Worker   */
1649*5e7646d2SAndroid Build Coastguard Worker 
1650*5e7646d2SAndroid Build Coastguard Worker   if (r->header.cupsColorOrder == CUPS_ORDER_CHUNKED)
1651*5e7646d2SAndroid Build Coastguard Worker     r->bpp = (r->header.cupsBitsPerPixel + 7) / 8;
1652*5e7646d2SAndroid Build Coastguard Worker   else
1653*5e7646d2SAndroid Build Coastguard Worker     r->bpp = (r->header.cupsBitsPerColor + 7) / 8;
1654*5e7646d2SAndroid Build Coastguard Worker 
1655*5e7646d2SAndroid Build Coastguard Worker   if (r->bpp == 0)
1656*5e7646d2SAndroid Build Coastguard Worker     r->bpp = 1;
1657*5e7646d2SAndroid Build Coastguard Worker 
1658*5e7646d2SAndroid Build Coastguard Worker  /*
1659*5e7646d2SAndroid Build Coastguard Worker   * Set the number of remaining rows...
1660*5e7646d2SAndroid Build Coastguard Worker   */
1661*5e7646d2SAndroid Build Coastguard Worker 
1662*5e7646d2SAndroid Build Coastguard Worker   if (r->header.cupsColorOrder == CUPS_ORDER_PLANAR)
1663*5e7646d2SAndroid Build Coastguard Worker     r->remaining = r->header.cupsHeight * r->header.cupsNumColors;
1664*5e7646d2SAndroid Build Coastguard Worker   else
1665*5e7646d2SAndroid Build Coastguard Worker     r->remaining = r->header.cupsHeight;
1666*5e7646d2SAndroid Build Coastguard Worker 
1667*5e7646d2SAndroid Build Coastguard Worker  /*
1668*5e7646d2SAndroid Build Coastguard Worker   * Allocate the compression buffer...
1669*5e7646d2SAndroid Build Coastguard Worker   */
1670*5e7646d2SAndroid Build Coastguard Worker 
1671*5e7646d2SAndroid Build Coastguard Worker   if (r->compressed)
1672*5e7646d2SAndroid Build Coastguard Worker   {
1673*5e7646d2SAndroid Build Coastguard Worker     if (r->pixels != NULL)
1674*5e7646d2SAndroid Build Coastguard Worker       free(r->pixels);
1675*5e7646d2SAndroid Build Coastguard Worker 
1676*5e7646d2SAndroid Build Coastguard Worker     if ((r->pixels = calloc(r->header.cupsBytesPerLine, 1)) == NULL)
1677*5e7646d2SAndroid Build Coastguard Worker     {
1678*5e7646d2SAndroid Build Coastguard Worker       r->pcurrent = NULL;
1679*5e7646d2SAndroid Build Coastguard Worker       r->pend     = NULL;
1680*5e7646d2SAndroid Build Coastguard Worker       r->count    = 0;
1681*5e7646d2SAndroid Build Coastguard Worker 
1682*5e7646d2SAndroid Build Coastguard Worker       return (0);
1683*5e7646d2SAndroid Build Coastguard Worker     }
1684*5e7646d2SAndroid Build Coastguard Worker 
1685*5e7646d2SAndroid Build Coastguard Worker     r->pcurrent = r->pixels;
1686*5e7646d2SAndroid Build Coastguard Worker     r->pend     = r->pixels + r->header.cupsBytesPerLine;
1687*5e7646d2SAndroid Build Coastguard Worker     r->count    = 0;
1688*5e7646d2SAndroid Build Coastguard Worker   }
1689*5e7646d2SAndroid Build Coastguard Worker 
1690*5e7646d2SAndroid Build Coastguard Worker   return (1);
1691*5e7646d2SAndroid Build Coastguard Worker }
1692*5e7646d2SAndroid Build Coastguard Worker 
1693*5e7646d2SAndroid Build Coastguard Worker 
1694*5e7646d2SAndroid Build Coastguard Worker /*
1695*5e7646d2SAndroid Build Coastguard Worker  * 'cups_raster_write()' - Write a row of compressed raster data...
1696*5e7646d2SAndroid Build Coastguard Worker  */
1697*5e7646d2SAndroid Build Coastguard Worker 
1698*5e7646d2SAndroid Build Coastguard Worker static ssize_t				/* O - Number of bytes written */
cups_raster_write(cups_raster_t * r,const unsigned char * pixels)1699*5e7646d2SAndroid Build Coastguard Worker cups_raster_write(
1700*5e7646d2SAndroid Build Coastguard Worker     cups_raster_t       *r,		/* I - Raster stream */
1701*5e7646d2SAndroid Build Coastguard Worker     const unsigned char *pixels)	/* I - Pixel data to write */
1702*5e7646d2SAndroid Build Coastguard Worker {
1703*5e7646d2SAndroid Build Coastguard Worker   const unsigned char	*start,		/* Start of sequence */
1704*5e7646d2SAndroid Build Coastguard Worker 			*ptr,		/* Current pointer in sequence */
1705*5e7646d2SAndroid Build Coastguard Worker 			*pend,		/* End of raster buffer */
1706*5e7646d2SAndroid Build Coastguard Worker 			*plast;		/* Pointer to last pixel */
1707*5e7646d2SAndroid Build Coastguard Worker   unsigned char		*wptr;		/* Pointer into write buffer */
1708*5e7646d2SAndroid Build Coastguard Worker   unsigned		bpp,		/* Bytes per pixel */
1709*5e7646d2SAndroid Build Coastguard Worker 			count;		/* Count */
1710*5e7646d2SAndroid Build Coastguard Worker   _cups_copyfunc_t	cf;		/* Copy function */
1711*5e7646d2SAndroid Build Coastguard Worker 
1712*5e7646d2SAndroid Build Coastguard Worker 
1713*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r, (void *)pixels));
1714*5e7646d2SAndroid Build Coastguard Worker 
1715*5e7646d2SAndroid Build Coastguard Worker  /*
1716*5e7646d2SAndroid Build Coastguard Worker   * Determine whether we need to swap bytes...
1717*5e7646d2SAndroid Build Coastguard Worker   */
1718*5e7646d2SAndroid Build Coastguard Worker 
1719*5e7646d2SAndroid Build Coastguard Worker   if (r->swapped && (r->header.cupsBitsPerColor == 16 || r->header.cupsBitsPerPixel == 12 || r->header.cupsBitsPerPixel == 16))
1720*5e7646d2SAndroid Build Coastguard Worker   {
1721*5e7646d2SAndroid Build Coastguard Worker     DEBUG_puts("4cups_raster_write: Swapping bytes when writing.");
1722*5e7646d2SAndroid Build Coastguard Worker     cf = (_cups_copyfunc_t)cups_swap_copy;
1723*5e7646d2SAndroid Build Coastguard Worker   }
1724*5e7646d2SAndroid Build Coastguard Worker   else
1725*5e7646d2SAndroid Build Coastguard Worker     cf = (_cups_copyfunc_t)memcpy;
1726*5e7646d2SAndroid Build Coastguard Worker 
1727*5e7646d2SAndroid Build Coastguard Worker   /*
1728*5e7646d2SAndroid Build Coastguard Worker   * Allocate a write buffer as needed...
1729*5e7646d2SAndroid Build Coastguard Worker   */
1730*5e7646d2SAndroid Build Coastguard Worker 
1731*5e7646d2SAndroid Build Coastguard Worker   count = r->header.cupsBytesPerLine * 2;
1732*5e7646d2SAndroid Build Coastguard Worker   if (count < 65536)
1733*5e7646d2SAndroid Build Coastguard Worker     count = 65536;
1734*5e7646d2SAndroid Build Coastguard Worker 
1735*5e7646d2SAndroid Build Coastguard Worker   if ((size_t)count > r->bufsize)
1736*5e7646d2SAndroid Build Coastguard Worker   {
1737*5e7646d2SAndroid Build Coastguard Worker     if (r->buffer)
1738*5e7646d2SAndroid Build Coastguard Worker       wptr = realloc(r->buffer, count);
1739*5e7646d2SAndroid Build Coastguard Worker     else
1740*5e7646d2SAndroid Build Coastguard Worker       wptr = malloc(count);
1741*5e7646d2SAndroid Build Coastguard Worker 
1742*5e7646d2SAndroid Build Coastguard Worker     if (!wptr)
1743*5e7646d2SAndroid Build Coastguard Worker     {
1744*5e7646d2SAndroid Build Coastguard Worker       DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT " bytes for raster buffer: %s", CUPS_LLCAST count, strerror(errno)));
1745*5e7646d2SAndroid Build Coastguard Worker       return (-1);
1746*5e7646d2SAndroid Build Coastguard Worker     }
1747*5e7646d2SAndroid Build Coastguard Worker 
1748*5e7646d2SAndroid Build Coastguard Worker     r->buffer  = wptr;
1749*5e7646d2SAndroid Build Coastguard Worker     r->bufsize = count;
1750*5e7646d2SAndroid Build Coastguard Worker   }
1751*5e7646d2SAndroid Build Coastguard Worker 
1752*5e7646d2SAndroid Build Coastguard Worker  /*
1753*5e7646d2SAndroid Build Coastguard Worker   * Write the row repeat count...
1754*5e7646d2SAndroid Build Coastguard Worker   */
1755*5e7646d2SAndroid Build Coastguard Worker 
1756*5e7646d2SAndroid Build Coastguard Worker   bpp     = r->bpp;
1757*5e7646d2SAndroid Build Coastguard Worker   pend    = pixels + r->header.cupsBytesPerLine;
1758*5e7646d2SAndroid Build Coastguard Worker   plast   = pend - bpp;
1759*5e7646d2SAndroid Build Coastguard Worker   wptr    = r->buffer;
1760*5e7646d2SAndroid Build Coastguard Worker   *wptr++ = (unsigned char)(r->count - 1);
1761*5e7646d2SAndroid Build Coastguard Worker 
1762*5e7646d2SAndroid Build Coastguard Worker  /*
1763*5e7646d2SAndroid Build Coastguard Worker   * Write using a modified PackBits compression...
1764*5e7646d2SAndroid Build Coastguard Worker   */
1765*5e7646d2SAndroid Build Coastguard Worker 
1766*5e7646d2SAndroid Build Coastguard Worker   for (ptr = pixels; ptr < pend;)
1767*5e7646d2SAndroid Build Coastguard Worker   {
1768*5e7646d2SAndroid Build Coastguard Worker     start = ptr;
1769*5e7646d2SAndroid Build Coastguard Worker     ptr += bpp;
1770*5e7646d2SAndroid Build Coastguard Worker 
1771*5e7646d2SAndroid Build Coastguard Worker     if (ptr == pend)
1772*5e7646d2SAndroid Build Coastguard Worker     {
1773*5e7646d2SAndroid Build Coastguard Worker      /*
1774*5e7646d2SAndroid Build Coastguard Worker       * Encode a single pixel at the end...
1775*5e7646d2SAndroid Build Coastguard Worker       */
1776*5e7646d2SAndroid Build Coastguard Worker 
1777*5e7646d2SAndroid Build Coastguard Worker       *wptr++ = 0;
1778*5e7646d2SAndroid Build Coastguard Worker       (*cf)(wptr, start, bpp);
1779*5e7646d2SAndroid Build Coastguard Worker       wptr += bpp;
1780*5e7646d2SAndroid Build Coastguard Worker     }
1781*5e7646d2SAndroid Build Coastguard Worker     else if (!memcmp(start, ptr, bpp))
1782*5e7646d2SAndroid Build Coastguard Worker     {
1783*5e7646d2SAndroid Build Coastguard Worker      /*
1784*5e7646d2SAndroid Build Coastguard Worker       * Encode a sequence of repeating pixels...
1785*5e7646d2SAndroid Build Coastguard Worker       */
1786*5e7646d2SAndroid Build Coastguard Worker 
1787*5e7646d2SAndroid Build Coastguard Worker       for (count = 2; count < 128 && ptr < plast; count ++, ptr += bpp)
1788*5e7646d2SAndroid Build Coastguard Worker         if (memcmp(ptr, ptr + bpp, bpp))
1789*5e7646d2SAndroid Build Coastguard Worker 	  break;
1790*5e7646d2SAndroid Build Coastguard Worker 
1791*5e7646d2SAndroid Build Coastguard Worker       *wptr++ = (unsigned char)(count - 1);
1792*5e7646d2SAndroid Build Coastguard Worker       (*cf)(wptr, ptr, bpp);
1793*5e7646d2SAndroid Build Coastguard Worker       wptr += bpp;
1794*5e7646d2SAndroid Build Coastguard Worker       ptr  += bpp;
1795*5e7646d2SAndroid Build Coastguard Worker     }
1796*5e7646d2SAndroid Build Coastguard Worker     else
1797*5e7646d2SAndroid Build Coastguard Worker     {
1798*5e7646d2SAndroid Build Coastguard Worker      /*
1799*5e7646d2SAndroid Build Coastguard Worker       * Encode a sequence of non-repeating pixels...
1800*5e7646d2SAndroid Build Coastguard Worker       */
1801*5e7646d2SAndroid Build Coastguard Worker 
1802*5e7646d2SAndroid Build Coastguard Worker       for (count = 1; count < 128 && ptr < plast; count ++, ptr += bpp)
1803*5e7646d2SAndroid Build Coastguard Worker         if (!memcmp(ptr, ptr + bpp, bpp))
1804*5e7646d2SAndroid Build Coastguard Worker 	  break;
1805*5e7646d2SAndroid Build Coastguard Worker 
1806*5e7646d2SAndroid Build Coastguard Worker       if (ptr >= plast && count < 128)
1807*5e7646d2SAndroid Build Coastguard Worker       {
1808*5e7646d2SAndroid Build Coastguard Worker         count ++;
1809*5e7646d2SAndroid Build Coastguard Worker 	ptr += bpp;
1810*5e7646d2SAndroid Build Coastguard Worker       }
1811*5e7646d2SAndroid Build Coastguard Worker 
1812*5e7646d2SAndroid Build Coastguard Worker       *wptr++ = (unsigned char)(257 - count);
1813*5e7646d2SAndroid Build Coastguard Worker 
1814*5e7646d2SAndroid Build Coastguard Worker       count *= bpp;
1815*5e7646d2SAndroid Build Coastguard Worker       (*cf)(wptr, start, count);
1816*5e7646d2SAndroid Build Coastguard Worker       wptr += count;
1817*5e7646d2SAndroid Build Coastguard Worker     }
1818*5e7646d2SAndroid Build Coastguard Worker   }
1819*5e7646d2SAndroid Build Coastguard Worker 
1820*5e7646d2SAndroid Build Coastguard Worker   DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT " bytes.", CUPS_LLCAST (wptr - r->buffer)));
1821*5e7646d2SAndroid Build Coastguard Worker 
1822*5e7646d2SAndroid Build Coastguard Worker   return (cups_raster_io(r, r->buffer, (size_t)(wptr - r->buffer)));
1823*5e7646d2SAndroid Build Coastguard Worker }
1824*5e7646d2SAndroid Build Coastguard Worker 
1825*5e7646d2SAndroid Build Coastguard Worker 
1826*5e7646d2SAndroid Build Coastguard Worker /*
1827*5e7646d2SAndroid Build Coastguard Worker  * 'cups_swap()' - Swap bytes in raster data...
1828*5e7646d2SAndroid Build Coastguard Worker  */
1829*5e7646d2SAndroid Build Coastguard Worker 
1830*5e7646d2SAndroid Build Coastguard Worker static void
cups_swap(unsigned char * buf,size_t bytes)1831*5e7646d2SAndroid Build Coastguard Worker cups_swap(unsigned char *buf,		/* I - Buffer to swap */
1832*5e7646d2SAndroid Build Coastguard Worker           size_t        bytes)		/* I - Number of bytes to swap */
1833*5e7646d2SAndroid Build Coastguard Worker {
1834*5e7646d2SAndroid Build Coastguard Worker   unsigned char	even, odd;		/* Temporary variables */
1835*5e7646d2SAndroid Build Coastguard Worker 
1836*5e7646d2SAndroid Build Coastguard Worker 
1837*5e7646d2SAndroid Build Coastguard Worker   bytes /= 2;
1838*5e7646d2SAndroid Build Coastguard Worker 
1839*5e7646d2SAndroid Build Coastguard Worker   while (bytes > 0)
1840*5e7646d2SAndroid Build Coastguard Worker   {
1841*5e7646d2SAndroid Build Coastguard Worker     even   = buf[0];
1842*5e7646d2SAndroid Build Coastguard Worker     odd    = buf[1];
1843*5e7646d2SAndroid Build Coastguard Worker     buf[0] = odd;
1844*5e7646d2SAndroid Build Coastguard Worker     buf[1] = even;
1845*5e7646d2SAndroid Build Coastguard Worker 
1846*5e7646d2SAndroid Build Coastguard Worker     buf += 2;
1847*5e7646d2SAndroid Build Coastguard Worker     bytes --;
1848*5e7646d2SAndroid Build Coastguard Worker   }
1849*5e7646d2SAndroid Build Coastguard Worker }
1850*5e7646d2SAndroid Build Coastguard Worker 
1851*5e7646d2SAndroid Build Coastguard Worker 
1852*5e7646d2SAndroid Build Coastguard Worker /*
1853*5e7646d2SAndroid Build Coastguard Worker  * 'cups_swap_copy()' - Copy and swap bytes in raster data...
1854*5e7646d2SAndroid Build Coastguard Worker  */
1855*5e7646d2SAndroid Build Coastguard Worker 
1856*5e7646d2SAndroid Build Coastguard Worker static void
cups_swap_copy(unsigned char * dst,const unsigned char * src,size_t bytes)1857*5e7646d2SAndroid Build Coastguard Worker cups_swap_copy(
1858*5e7646d2SAndroid Build Coastguard Worker     unsigned char       *dst,		/* I - Destination */
1859*5e7646d2SAndroid Build Coastguard Worker     const unsigned char *src,		/* I - Source */
1860*5e7646d2SAndroid Build Coastguard Worker     size_t              bytes)		/* I - Number of bytes to swap */
1861*5e7646d2SAndroid Build Coastguard Worker {
1862*5e7646d2SAndroid Build Coastguard Worker   bytes /= 2;
1863*5e7646d2SAndroid Build Coastguard Worker 
1864*5e7646d2SAndroid Build Coastguard Worker   while (bytes > 0)
1865*5e7646d2SAndroid Build Coastguard Worker   {
1866*5e7646d2SAndroid Build Coastguard Worker     dst[0] = src[1];
1867*5e7646d2SAndroid Build Coastguard Worker     dst[1] = src[0];
1868*5e7646d2SAndroid Build Coastguard Worker 
1869*5e7646d2SAndroid Build Coastguard Worker     dst += 2;
1870*5e7646d2SAndroid Build Coastguard Worker     src += 2;
1871*5e7646d2SAndroid Build Coastguard Worker     bytes --;
1872*5e7646d2SAndroid Build Coastguard Worker   }
1873*5e7646d2SAndroid Build Coastguard Worker }
1874