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