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