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