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