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