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