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