1 /*
2 * Raster file routines for CUPS.
3 *
4 * Copyright © 2020-2024 by OpenPrinting.
5 * Copyright 2007-2019 by Apple Inc.
6 * Copyright 1997-2006 by Easy Software Products.
7 *
8 * This file is part of the CUPS Imaging library.
9 *
10 * Licensed under Apache License v2.0. See the file "LICENSE" for more
11 * information.
12 */
13
14 /*
15 * Include necessary headers...
16 */
17
18 #include "raster-private.h"
19 #include "debug-internal.h"
20 #ifdef HAVE_STDINT_H
21 # include <stdint.h>
22 #endif /* HAVE_STDINT_H */
23
24
25 /*
26 * Private structures...
27 */
28
29 typedef void (*_cups_copyfunc_t)(void *dst, const void *src, size_t bytes);
30
31
32 /*
33 * Local globals...
34 */
35
36 static const char * const apple_media_types[] =
37 { /* media-type values for Apple Raster */
38 "auto",
39 "stationery",
40 "transparency",
41 "envelope",
42 "cardstock",
43 "labels",
44 "stationery-letterhead",
45 "disc",
46 "photographic-matte",
47 "photographic-satin",
48 "photographic-semi-gloss",
49 "photographic-glossy",
50 "photographic-high-gloss",
51 "other"
52 };
53
54 #ifdef DEBUG
55 static const char * const cups_modes[] =
56 { /* Open modes */
57 "CUPS_RASTER_READ",
58 "CUPS_RASTER_WRITE",
59 "CUPS_RASTER_WRITE_COMPRESSED",
60 "CUPS_RASTER_WRITE_PWG",
61 "CUPS_RASTER_WRITE_APPLE"
62 };
63 #endif /* DEBUG */
64
65
66 /*
67 * Local functions...
68 */
69
70 static ssize_t cups_raster_io(cups_raster_t *r, unsigned char *buf, size_t bytes);
71 static ssize_t cups_raster_read(cups_raster_t *r, unsigned char *buf, size_t bytes);
72 static int cups_raster_update(cups_raster_t *r);
73 static ssize_t cups_raster_write(cups_raster_t *r, const unsigned char *pixels);
74 static void cups_swap(unsigned char *buf, size_t bytes);
75 static void cups_swap_copy(unsigned char *dst, const unsigned char *src, size_t bytes);
76
77
78 /*
79 * '_cupsRasterColorSpaceString()' - Return the colorspace name for a
80 * cupsColorSpace value.
81 */
82
83 const char *
_cupsRasterColorSpaceString(cups_cspace_t cspace)84 _cupsRasterColorSpaceString(
85 cups_cspace_t cspace) /* I - cupsColorSpace value */
86 {
87 static const char * const cups_color_spaces[] =
88 { /* Color spaces */
89 "W",
90 "RGB",
91 "RGBA",
92 "K",
93 "CMY",
94 "YMC",
95 "CMYK",
96 "YMCK",
97 "KCMY",
98 "KCMYcm",
99 "GMCK",
100 "GMCS",
101 "WHITE",
102 "GOLD",
103 "SILVER",
104 "CIEXYZ",
105 "CIELab",
106 "RGBW",
107 "SW",
108 "SRGB",
109 "ADOBERGB",
110 "21",
111 "22",
112 "23",
113 "24",
114 "25",
115 "26",
116 "27",
117 "28",
118 "29",
119 "30",
120 "31",
121 "ICC1",
122 "ICC2",
123 "ICC3",
124 "ICC4",
125 "ICC5",
126 "ICC6",
127 "ICC7",
128 "ICC8",
129 "ICC9",
130 "ICCA",
131 "ICCB",
132 "ICCC",
133 "ICCD",
134 "ICCE",
135 "ICCF",
136 "47",
137 "DEVICE1",
138 "DEVICE2",
139 "DEVICE3",
140 "DEVICE4",
141 "DEVICE5",
142 "DEVICE6",
143 "DEVICE7",
144 "DEVICE8",
145 "DEVICE9",
146 "DEVICEA",
147 "DEVICEB",
148 "DEVICEC",
149 "DEVICED",
150 "DEVICEE",
151 "DEVICEF"
152 };
153
154 if (cspace < CUPS_CSPACE_W || cspace > CUPS_CSPACE_DEVICEF)
155 return ("Unknown");
156 else
157 return (cups_color_spaces[cspace]);
158 }
159
160
161 /*
162 * '_cupsRasterDelete()' - Free a raster stream.
163 *
164 * The file descriptor associated with the raster stream must be closed
165 * separately as needed.
166 */
167
168 void
_cupsRasterDelete(cups_raster_t * r)169 _cupsRasterDelete(cups_raster_t *r) /* I - Stream to free */
170 {
171 if (r != NULL)
172 {
173 if (r->buffer)
174 free(r->buffer);
175
176 if (r->pixels)
177 free(r->pixels);
178
179 free(r);
180 }
181 }
182
183
184 /*
185 * '_cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output.
186 *
187 * The "media" argument specifies the media to use.
188 *
189 * The "type" argument specifies a "pwg-raster-document-type-supported" value
190 * that controls the color space and bit depth of the raster data.
191 *
192 * The "xres" and "yres" arguments specify the raster resolution in dots per
193 * inch.
194 *
195 * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value
196 * to apply for the back side of a page. Pass @code NULL@ for the front side.
197 *
198 * @since CUPS 2.2/macOS 10.12@
199 */
200
201 int /* O - 1 on success, 0 on failure */
_cupsRasterInitPWGHeader(cups_page_header2_t * h,pwg_media_t * media,const char * type,int xdpi,int ydpi,const char * sides,const char * sheet_back)202 _cupsRasterInitPWGHeader(
203 cups_page_header2_t *h, /* I - Page header */
204 pwg_media_t *media, /* I - PWG media information */
205 const char *type, /* I - PWG raster type string */
206 int xdpi, /* I - Cross-feed direction (horizontal) resolution */
207 int ydpi, /* I - Feed direction (vertical) resolution */
208 const char *sides, /* I - IPP "sides" option value */
209 const char *sheet_back) /* I - Transform for back side or @code NULL@ for none */
210 {
211 if (!h || !media || !type || xdpi <= 0 || ydpi <= 0)
212 {
213 _cupsRasterAddError("%s", strerror(EINVAL));
214 return (0);
215 }
216
217 /*
218 * Initialize the page header...
219 */
220
221 memset(h, 0, sizeof(cups_page_header2_t));
222
223 strlcpy(h->cupsPageSizeName, media->pwg, sizeof(h->cupsPageSizeName));
224
225 h->PageSize[0] = (unsigned)(72 * media->width / 2540);
226 h->PageSize[1] = (unsigned)(72 * media->length / 2540);
227
228 /* This never gets written but is needed for some applications */
229 h->cupsPageSize[0] = 72.0f * media->width / 2540.0f;
230 h->cupsPageSize[1] = 72.0f * media->length / 2540.0f;
231
232 h->ImagingBoundingBox[2] = h->PageSize[0];
233 h->ImagingBoundingBox[3] = h->PageSize[1];
234
235 h->HWResolution[0] = (unsigned)xdpi;
236 h->HWResolution[1] = (unsigned)ydpi;
237
238 h->cupsWidth = (unsigned)(media->width * xdpi / 2540);
239 h->cupsHeight = (unsigned)(media->length * ydpi / 2540);
240
241 if (h->cupsWidth > 0x00ffffff || h->cupsHeight > 0x00ffffff)
242 {
243 _cupsRasterAddError("Raster dimensions too large.");
244 return (0);
245 }
246
247 h->cupsInteger[CUPS_RASTER_PWG_ImageBoxRight] = h->cupsWidth;
248 h->cupsInteger[CUPS_RASTER_PWG_ImageBoxBottom] = h->cupsHeight;
249
250 /*
251 * Colorspace and bytes per line...
252 */
253
254 if (!strcmp(type, "adobe-rgb_8"))
255 {
256 h->cupsBitsPerColor = 8;
257 h->cupsBitsPerPixel = 24;
258 h->cupsColorSpace = CUPS_CSPACE_ADOBERGB;
259 }
260 else if (!strcmp(type, "adobe-rgb_16"))
261 {
262 h->cupsBitsPerColor = 16;
263 h->cupsBitsPerPixel = 48;
264 h->cupsColorSpace = CUPS_CSPACE_ADOBERGB;
265 }
266 else if (!strcmp(type, "black_1"))
267 {
268 h->cupsBitsPerColor = 1;
269 h->cupsBitsPerPixel = 1;
270 h->cupsColorSpace = CUPS_CSPACE_K;
271 }
272 else if (!strcmp(type, "black_8"))
273 {
274 h->cupsBitsPerColor = 8;
275 h->cupsBitsPerPixel = 8;
276 h->cupsColorSpace = CUPS_CSPACE_K;
277 }
278 else if (!strcmp(type, "black_16"))
279 {
280 h->cupsBitsPerColor = 16;
281 h->cupsBitsPerPixel = 16;
282 h->cupsColorSpace = CUPS_CSPACE_K;
283 }
284 else if (!strcmp(type, "cmyk_8"))
285 {
286 h->cupsBitsPerColor = 8;
287 h->cupsBitsPerPixel = 32;
288 h->cupsColorSpace = CUPS_CSPACE_CMYK;
289 }
290 else if (!strcmp(type, "cmyk_16"))
291 {
292 h->cupsBitsPerColor = 16;
293 h->cupsBitsPerPixel = 64;
294 h->cupsColorSpace = CUPS_CSPACE_CMYK;
295 }
296 else if (!strncmp(type, "device", 6) && type[6] >= '1' && type[6] <= '9')
297 {
298 int ncolors, bits; /* Number of colors and bits */
299
300
301 if (sscanf(type, "device%d_%d", &ncolors, &bits) != 2 || ncolors > 15 || (bits != 8 && bits != 16))
302 {
303 _cupsRasterAddError("Unsupported raster type \'%s\'.", type);
304 return (0);
305 }
306
307 h->cupsBitsPerColor = (unsigned)bits;
308 h->cupsBitsPerPixel = (unsigned)(ncolors * bits);
309 h->cupsColorSpace = (cups_cspace_t)(CUPS_CSPACE_DEVICE1 + ncolors - 1);
310 }
311 else if (!strcmp(type, "rgb_8"))
312 {
313 h->cupsBitsPerColor = 8;
314 h->cupsBitsPerPixel = 24;
315 h->cupsColorSpace = CUPS_CSPACE_RGB;
316 }
317 else if (!strcmp(type, "rgb_16"))
318 {
319 h->cupsBitsPerColor = 16;
320 h->cupsBitsPerPixel = 48;
321 h->cupsColorSpace = CUPS_CSPACE_RGB;
322 }
323 else if (!strcmp(type, "sgray_1"))
324 {
325 h->cupsBitsPerColor = 1;
326 h->cupsBitsPerPixel = 1;
327 h->cupsColorSpace = CUPS_CSPACE_SW;
328 }
329 else if (!strcmp(type, "sgray_8"))
330 {
331 h->cupsBitsPerColor = 8;
332 h->cupsBitsPerPixel = 8;
333 h->cupsColorSpace = CUPS_CSPACE_SW;
334 }
335 else if (!strcmp(type, "sgray_16"))
336 {
337 h->cupsBitsPerColor = 16;
338 h->cupsBitsPerPixel = 16;
339 h->cupsColorSpace = CUPS_CSPACE_SW;
340 }
341 else if (!strcmp(type, "srgb_8"))
342 {
343 h->cupsBitsPerColor = 8;
344 h->cupsBitsPerPixel = 24;
345 h->cupsColorSpace = CUPS_CSPACE_SRGB;
346 }
347 else if (!strcmp(type, "srgb_16"))
348 {
349 h->cupsBitsPerColor = 16;
350 h->cupsBitsPerPixel = 48;
351 h->cupsColorSpace = CUPS_CSPACE_SRGB;
352 }
353 else
354 {
355 _cupsRasterAddError("Unsupported raster type \'%s\'.", type);
356 return (0);
357 }
358
359 h->cupsColorOrder = CUPS_ORDER_CHUNKED;
360 h->cupsNumColors = h->cupsBitsPerPixel / h->cupsBitsPerColor;
361 h->cupsBytesPerLine = (h->cupsWidth * h->cupsBitsPerPixel + 7) / 8;
362
363 /*
364 * Duplex support...
365 */
366
367 h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 1;
368 h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 1;
369
370 if (sides)
371 {
372 if (!strcmp(sides, "two-sided-long-edge"))
373 {
374 h->Duplex = 1;
375 }
376 else if (!strcmp(sides, "two-sided-short-edge"))
377 {
378 h->Duplex = 1;
379 h->Tumble = 1;
380 }
381 else if (strcmp(sides, "one-sided"))
382 {
383 _cupsRasterAddError("Unsupported sides value \'%s\'.", sides);
384 return (0);
385 }
386
387 if (sheet_back)
388 {
389 if (!strcmp(sheet_back, "flipped"))
390 {
391 if (h->Tumble)
392 h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU;
393 else
394 h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 0xffffffffU;
395 }
396 else if (!strcmp(sheet_back, "manual-tumble"))
397 {
398 if (h->Tumble)
399 {
400 h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU;
401 h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 0xffffffffU;
402 }
403 }
404 else if (!strcmp(sheet_back, "rotated"))
405 {
406 if (!h->Tumble)
407 {
408 h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU;
409 h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 0xffffffffU;
410 }
411 }
412 else if (strcmp(sheet_back, "normal"))
413 {
414 _cupsRasterAddError("Unsupported sheet_back value \'%s\'.", sheet_back);
415 return (0);
416 }
417 }
418 }
419
420 return (1);
421 }
422
423
424 /*
425 * '_cupsRasterNew()' - Create a raster stream using a callback function.
426 *
427 * This function associates a raster stream with the given callback function and
428 * context pointer.
429 *
430 * When writing raster data, the @code CUPS_RASTER_WRITE@,
431 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
432 * be used - compressed and PWG output is generally 25-50% smaller but adds a
433 * 100-300% execution time overhead.
434 */
435
436 cups_raster_t * /* O - New stream */
_cupsRasterNew(cups_raster_iocb_t iocb,void * ctx,cups_mode_t mode)437 _cupsRasterNew(
438 cups_raster_iocb_t iocb, /* I - Read/write callback */
439 void *ctx, /* I - Context pointer for callback */
440 cups_mode_t mode) /* I - Mode - @code CUPS_RASTER_READ@,
441 @code CUPS_RASTER_WRITE@,
442 @code CUPS_RASTER_WRITE_COMPRESSED@,
443 or @code CUPS_RASTER_WRITE_PWG@ */
444 {
445 cups_raster_t *r; /* New stream */
446
447
448 DEBUG_printf(("_cupsRasterOpenIO(iocb=%p, ctx=%p, mode=%s)", (void *)iocb, ctx, cups_modes[mode]));
449
450 _cupsRasterClearError();
451
452 if ((r = calloc(1, sizeof(cups_raster_t))) == NULL)
453 {
454 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
455 strerror(errno));
456 DEBUG_puts("1_cupsRasterOpenIO: Returning NULL.");
457 return (NULL);
458 }
459
460 r->ctx = ctx;
461 r->iocb = iocb;
462 r->mode = mode;
463
464 if (mode == CUPS_RASTER_READ)
465 {
466 /*
467 * Open for read - get sync word...
468 */
469
470 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) !=
471 sizeof(r->sync))
472 {
473 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
474 strerror(errno));
475 free(r);
476 DEBUG_puts("1_cupsRasterOpenIO: Unable to read header, returning NULL.");
477 return (NULL);
478 }
479
480 if (r->sync != CUPS_RASTER_SYNC &&
481 r->sync != CUPS_RASTER_REVSYNC &&
482 r->sync != CUPS_RASTER_SYNCv1 &&
483 r->sync != CUPS_RASTER_REVSYNCv1 &&
484 r->sync != CUPS_RASTER_SYNCv2 &&
485 r->sync != CUPS_RASTER_REVSYNCv2 &&
486 r->sync != CUPS_RASTER_SYNCapple &&
487 r->sync != CUPS_RASTER_REVSYNCapple)
488 {
489 _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
490 free(r);
491 DEBUG_puts("1_cupsRasterOpenIO: Unknown format, returning NULL.");
492 return (NULL);
493 }
494
495 if (r->sync == CUPS_RASTER_SYNCv2 ||
496 r->sync == CUPS_RASTER_REVSYNCv2 ||
497 r->sync == CUPS_RASTER_SYNCapple ||
498 r->sync == CUPS_RASTER_REVSYNCapple)
499 r->compressed = 1;
500
501 DEBUG_printf(("1_cupsRasterOpenIO: sync=%08x", r->sync));
502
503 if (r->sync == CUPS_RASTER_REVSYNC ||
504 r->sync == CUPS_RASTER_REVSYNCv1 ||
505 r->sync == CUPS_RASTER_REVSYNCv2 ||
506 r->sync == CUPS_RASTER_REVSYNCapple)
507 r->swapped = 1;
508
509 if (r->sync == CUPS_RASTER_SYNCapple ||
510 r->sync == CUPS_RASTER_REVSYNCapple)
511 {
512 unsigned char header[8]; /* File header */
513
514 if (cups_raster_io(r, (unsigned char *)header, sizeof(header)) !=
515 sizeof(header))
516 {
517 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
518 strerror(errno));
519 free(r);
520 DEBUG_puts("1_cupsRasterOpenIO: Unable to read header, returning NULL.");
521 return (NULL);
522 }
523 }
524
525 #ifdef DEBUG
526 r->iostart = r->iocount;
527 #endif /* DEBUG */
528 }
529 else
530 {
531 /*
532 * Open for write - put sync word...
533 */
534
535 switch (mode)
536 {
537 default :
538 case CUPS_RASTER_WRITE :
539 r->sync = CUPS_RASTER_SYNC;
540 break;
541
542 case CUPS_RASTER_WRITE_COMPRESSED :
543 r->compressed = 1;
544 r->sync = CUPS_RASTER_SYNCv2;
545 break;
546
547 case CUPS_RASTER_WRITE_PWG :
548 r->compressed = 1;
549 r->sync = htonl(CUPS_RASTER_SYNC_PWG);
550 r->swapped = r->sync != CUPS_RASTER_SYNC_PWG;
551 break;
552
553 case CUPS_RASTER_WRITE_APPLE :
554 r->compressed = 1;
555 r->sync = htonl(CUPS_RASTER_SYNCapple);
556 r->swapped = r->sync != CUPS_RASTER_SYNCapple;
557 r->apple_page_count = 0xffffffffU;
558 break;
559 }
560
561 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) < (ssize_t)sizeof(r->sync))
562 {
563 _cupsRasterAddError("Unable to write raster stream header: %s\n",
564 strerror(errno));
565 free(r);
566 DEBUG_puts("1_cupsRasterOpenIO: Unable to write header, returning NULL.");
567 return (NULL);
568 }
569 }
570
571 DEBUG_printf(("1_cupsRasterOpenIO: compressed=%d, swapped=%d, returning %p", r->compressed, r->swapped, (void *)r));
572
573 return (r);
574 }
575
576
577 /*
578 * '_cupsRasterReadHeader()' - Read a raster page header.
579 */
580
581 unsigned /* O - 1 on success, 0 on fail */
_cupsRasterReadHeader(cups_raster_t * r)582 _cupsRasterReadHeader(
583 cups_raster_t *r) /* I - Raster stream */
584 {
585 size_t len; /* Length for read/swap */
586
587
588 DEBUG_printf(("3_cupsRasterReadHeader(r=%p), r->mode=%s", (void *)r, r ? cups_modes[r->mode] : ""));
589
590 if (r == NULL || r->mode != CUPS_RASTER_READ)
591 return (0);
592
593 DEBUG_printf(("4_cupsRasterReadHeader: r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
594
595 memset(&(r->header), 0, sizeof(r->header));
596
597 /*
598 * Read the header...
599 */
600
601 switch (r->sync)
602 {
603 default :
604 /*
605 * Get the length of the raster header...
606 */
607
608 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1)
609 len = sizeof(cups_page_header_t);
610 else
611 len = sizeof(cups_page_header2_t);
612
613 DEBUG_printf(("4_cupsRasterReadHeader: len=%d", (int)len));
614
615 /*
616 * Read it...
617 */
618
619 if (cups_raster_read(r, (unsigned char *)&(r->header), len) < (ssize_t)len)
620 {
621 DEBUG_printf(("4_cupsRasterReadHeader: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
622 return (0);
623 }
624
625 /*
626 * Swap bytes as needed...
627 */
628
629 if (r->swapped)
630 {
631 unsigned *s, /* Current word */
632 temp; /* Temporary copy */
633
634
635 DEBUG_puts("4_cupsRasterReadHeader: Swapping header bytes.");
636
637 for (len = 81, s = &(r->header.AdvanceDistance);
638 len > 0;
639 len --, s ++)
640 {
641 temp = *s;
642 *s = ((temp & 0xff) << 24) |
643 ((temp & 0xff00) << 8) |
644 ((temp & 0xff0000) >> 8) |
645 ((temp & 0xff000000) >> 24);
646
647 DEBUG_printf(("4_cupsRasterReadHeader: %08x => %08x", temp, *s));
648 }
649 }
650 break;
651
652 case CUPS_RASTER_SYNCapple :
653 case CUPS_RASTER_REVSYNCapple :
654 {
655 unsigned char appleheader[32]; /* Raw header */
656 static const unsigned rawcspace[] =
657 {
658 CUPS_CSPACE_SW,
659 CUPS_CSPACE_SRGB,
660 CUPS_CSPACE_CIELab,
661 CUPS_CSPACE_ADOBERGB,
662 CUPS_CSPACE_W,
663 CUPS_CSPACE_RGB,
664 CUPS_CSPACE_CMYK
665 };
666 static const unsigned rawnumcolors[] =
667 {
668 1,
669 3,
670 3,
671 3,
672 1,
673 3,
674 4
675 };
676
677 if (cups_raster_read(r, appleheader, sizeof(appleheader)) < (ssize_t)sizeof(appleheader))
678 {
679 DEBUG_printf(("4_cupsRasterReadHeader: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount));
680 return (0);
681 }
682
683 strlcpy(r->header.MediaClass, "PwgRaster", sizeof(r->header.MediaClass));
684 /* PwgRaster */
685 r->header.cupsBitsPerPixel = appleheader[0];
686 r->header.cupsColorSpace = appleheader[1] >= (sizeof(rawcspace) / sizeof(rawcspace[0])) ? CUPS_CSPACE_DEVICE1 : rawcspace[appleheader[1]];
687 r->header.cupsNumColors = appleheader[1] >= (sizeof(rawnumcolors) / sizeof(rawnumcolors[0])) ? 1 : rawnumcolors[appleheader[1]];
688 r->header.cupsBitsPerColor = r->header.cupsBitsPerPixel / r->header.cupsNumColors;
689 r->header.cupsWidth = ((unsigned)appleheader[12] << 24) | ((unsigned)appleheader[13] << 16) | ((unsigned)appleheader[14] << 8) | (unsigned)appleheader[15];
690 r->header.cupsHeight = ((unsigned)appleheader[16] << 24) | ((unsigned)appleheader[17] << 16) | ((unsigned)appleheader[18] << 8) | (unsigned)appleheader[19];
691 r->header.cupsBytesPerLine = r->header.cupsWidth * r->header.cupsBitsPerPixel / 8;
692 r->header.cupsColorOrder = CUPS_ORDER_CHUNKED;
693 r->header.HWResolution[0] = r->header.HWResolution[1] = ((unsigned)appleheader[20] << 24) | ((unsigned)appleheader[21] << 16) | ((unsigned)appleheader[22] << 8) | (unsigned)appleheader[23];
694 if (r->header.HWResolution[0] > 0)
695 {
696 r->header.PageSize[0] = (r->header.cupsWidth * 72 / r->header.HWResolution[0]);
697 r->header.PageSize[1] = (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 */
_cupsRasterReadPixels(cups_raster_t * r,unsigned char * p,unsigned len)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 */
_cupsRasterWriteHeader(cups_raster_t * r)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 */
_cupsRasterWritePixels(cups_raster_t * r,unsigned char * p,unsigned len)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 */
cups_raster_io(cups_raster_t * r,unsigned char * buf,size_t bytes)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 */
cups_raster_read(cups_raster_t * r,unsigned char * buf,size_t bytes)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 + (ssize_t)(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 */
cups_raster_update(cups_raster_t * r)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 */
cups_raster_write(cups_raster_t * r,const unsigned char * pixels)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
cups_swap(unsigned char * buf,size_t bytes)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
cups_swap_copy(unsigned char * dst,const unsigned char * src,size_t bytes)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 }
1874