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