2 * Raster file routines for CUPS.
4 * Copyright 2007-2016 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products.
7 * This file is part of the CUPS Imaging library.
9 * These coded instructions, statements, and computer programs are the
10 * property of Apple Inc. and are protected by Federal copyright
11 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
12 * which should have been included with this file. If this file is
13 * file is missing or damaged, see the license at "http://www.cups.org/".
15 * This file is subject to the Apple OS-Developed Software exception.
19 * Include necessary headers...
22 #include <cups/raster-private.h>
25 #endif /* HAVE_STDINT_H */
29 * Private structures...
32 struct _cups_raster_s
/**** Raster stream data ****/
34 unsigned sync
; /* Sync word from start of stream */
35 void *ctx
; /* File descriptor */
36 cups_raster_iocb_t iocb
; /* IO callback */
37 cups_mode_t mode
; /* Read/write mode */
38 cups_page_header2_t header
; /* Raster header for current page */
39 unsigned count
, /* Current row run-length count */
40 remaining
, /* Remaining rows in page image */
41 bpp
; /* Bytes per pixel/color */
42 unsigned char *pixels
, /* Pixels for current row */
43 *pend
, /* End of pixel buffer */
44 *pcurrent
; /* Current byte in pixel buffer */
45 int compressed
, /* Non-zero if data is compressed */
46 swapped
; /* Non-zero if data is byte-swapped */
47 unsigned char *buffer
, /* Read/write buffer */
48 *bufptr
, /* Current (read) position in buffer */
49 *bufend
; /* End of current (read) buffer */
50 size_t bufsize
; /* Buffer size */
52 size_t iocount
; /* Number of bytes read/written */
54 unsigned apple_page_count
;/* Apple raster page count */
62 static ssize_t
cups_raster_io(cups_raster_t
*r
, unsigned char *buf
, size_t bytes
);
63 static unsigned cups_raster_read_header(cups_raster_t
*r
);
64 static ssize_t
cups_raster_read(cups_raster_t
*r
, unsigned char *buf
,
66 static int cups_raster_update(cups_raster_t
*r
);
67 static ssize_t
cups_raster_write(cups_raster_t
*r
,
68 const unsigned char *pixels
);
69 static ssize_t
cups_read_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
70 static void cups_swap(unsigned char *buf
, size_t bytes
);
71 static ssize_t
cups_write_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
75 * 'cupsRasterClose()' - Close a raster stream.
77 * The file descriptor associated with the raster stream must be closed
78 * separately as needed.
82 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
98 * 'cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output.
100 * The "media" argument specifies the media to use.
102 * The "type" argument specifies a "pwg-raster-document-type-supported" value
103 * that controls the color space and bit depth of the raster data.
105 * The "xres" and "yres" arguments specify the raster resolution in dots per
108 * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value
109 * to apply for the back side of a page. Pass @code NULL@ for the front side.
111 * @since CUPS 2.2/macOS 10.12@
114 int /* O - 1 on success, 0 on failure */
115 cupsRasterInitPWGHeader(
116 cups_page_header2_t
*h
, /* I - Page header */
117 pwg_media_t
*media
, /* I - PWG media information */
118 const char *type
, /* I - PWG raster type string */
119 int xdpi
, /* I - Cross-feed direction (horizontal) resolution */
120 int ydpi
, /* I - Feed direction (vertical) resolution */
121 const char *sides
, /* I - IPP "sides" option value */
122 const char *sheet_back
) /* I - Transform for back side or @code NULL@ for none */
124 if (!h
|| !media
|| !type
|| xdpi
<= 0 || ydpi
<= 0)
126 _cupsRasterAddError("%s", strerror(EINVAL
));
131 * Initialize the page header...
134 memset(h
, 0, sizeof(cups_page_header2_t
));
136 strlcpy(h
->cupsPageSizeName
, media
->pwg
, sizeof(h
->cupsPageSizeName
));
138 h
->PageSize
[0] = (unsigned)(72 * media
->width
/ 2540);
139 h
->PageSize
[1] = (unsigned)(72 * media
->length
/ 2540);
141 /* This never gets written but is needed for some applications */
142 h
->cupsPageSize
[0] = 72.0f
* media
->width
/ 2540.0f
;
143 h
->cupsPageSize
[1] = 72.0f
* media
->length
/ 2540.0f
;
145 h
->ImagingBoundingBox
[2] = h
->PageSize
[0];
146 h
->ImagingBoundingBox
[3] = h
->PageSize
[1];
148 h
->HWResolution
[0] = (unsigned)xdpi
;
149 h
->HWResolution
[1] = (unsigned)ydpi
;
151 h
->cupsWidth
= (unsigned)(media
->width
* xdpi
/ 2540);
152 h
->cupsHeight
= (unsigned)(media
->length
* ydpi
/ 2540);
154 if (h
->cupsWidth
> 0x00ffffff || h
->cupsHeight
> 0x00ffffff)
156 _cupsRasterAddError("Raster dimensions too large.");
160 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxRight
] = h
->cupsWidth
;
161 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxBottom
] = h
->cupsHeight
;
164 * Colorspace and bytes per line...
167 if (!strcmp(type
, "adobe-rgb_8"))
169 h
->cupsBitsPerColor
= 8;
170 h
->cupsBitsPerPixel
= 24;
171 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
173 else if (!strcmp(type
, "adobe-rgb_16"))
175 h
->cupsBitsPerColor
= 16;
176 h
->cupsBitsPerPixel
= 48;
177 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
179 else if (!strcmp(type
, "black_1"))
181 h
->cupsBitsPerColor
= 1;
182 h
->cupsBitsPerPixel
= 1;
183 h
->cupsColorSpace
= CUPS_CSPACE_K
;
185 else if (!strcmp(type
, "black_8"))
187 h
->cupsBitsPerColor
= 8;
188 h
->cupsBitsPerPixel
= 8;
189 h
->cupsColorSpace
= CUPS_CSPACE_K
;
191 else if (!strcmp(type
, "black_16"))
193 h
->cupsBitsPerColor
= 16;
194 h
->cupsBitsPerPixel
= 16;
195 h
->cupsColorSpace
= CUPS_CSPACE_K
;
197 else if (!strcmp(type
, "cmyk_8"))
199 h
->cupsBitsPerColor
= 8;
200 h
->cupsBitsPerPixel
= 32;
201 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
203 else if (!strcmp(type
, "cmyk_16"))
205 h
->cupsBitsPerColor
= 16;
206 h
->cupsBitsPerPixel
= 64;
207 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
209 else if (!strncmp(type
, "device", 6) && type
[6] >= '1' && type
[6] <= '9')
211 int ncolors
, bits
; /* Number of colors and bits */
214 if (sscanf(type
, "device%d_%d", &ncolors
, &bits
) != 2 || ncolors
> 15 || (bits
!= 8 && bits
!= 16))
216 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
220 h
->cupsBitsPerColor
= (unsigned)bits
;
221 h
->cupsBitsPerPixel
= (unsigned)(ncolors
* bits
);
222 h
->cupsColorSpace
= (cups_cspace_t
)(CUPS_CSPACE_DEVICE1
+ ncolors
- 1);
224 else if (!strcmp(type
, "rgb_8"))
226 h
->cupsBitsPerColor
= 8;
227 h
->cupsBitsPerPixel
= 24;
228 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
230 else if (!strcmp(type
, "rgb_16"))
232 h
->cupsBitsPerColor
= 16;
233 h
->cupsBitsPerPixel
= 48;
234 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
236 else if (!strcmp(type
, "sgray_1"))
238 h
->cupsBitsPerColor
= 1;
239 h
->cupsBitsPerPixel
= 1;
240 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
242 else if (!strcmp(type
, "sgray_8"))
244 h
->cupsBitsPerColor
= 8;
245 h
->cupsBitsPerPixel
= 8;
246 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
248 else if (!strcmp(type
, "sgray_16"))
250 h
->cupsBitsPerColor
= 16;
251 h
->cupsBitsPerPixel
= 16;
252 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
254 else if (!strcmp(type
, "srgb_8"))
256 h
->cupsBitsPerColor
= 8;
257 h
->cupsBitsPerPixel
= 24;
258 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
260 else if (!strcmp(type
, "srgb_16"))
262 h
->cupsBitsPerColor
= 16;
263 h
->cupsBitsPerPixel
= 48;
264 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
268 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
272 h
->cupsColorOrder
= CUPS_ORDER_CHUNKED
;
273 h
->cupsNumColors
= h
->cupsBitsPerPixel
/ h
->cupsBitsPerColor
;
274 h
->cupsBytesPerLine
= (h
->cupsWidth
* h
->cupsBitsPerPixel
+ 7) / 8;
280 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 1;
281 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 1;
285 if (!strcmp(sides
, "two-sided-long-edge"))
289 else if (!strcmp(sides
, "two-sided-short-edge"))
294 else if (strcmp(sides
, "one-sided"))
296 _cupsRasterAddError("Unsupported sides value \'%s\'.", sides
);
302 if (!strcmp(sheet_back
, "flipped"))
305 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
307 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
309 else if (!strcmp(sheet_back
, "manual-tumble"))
313 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
314 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
317 else if (!strcmp(sheet_back
, "rotated"))
321 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
322 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
325 else if (strcmp(sheet_back
, "normal"))
327 _cupsRasterAddError("Unsupported sheet_back value \'%s\'.", sheet_back
);
338 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
340 * This function associates a raster stream with the given file descriptor.
341 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
342 * image processor (RIP) filters that generate raster data, "fd" will be 1
345 * When writing raster data, the @code CUPS_RASTER_WRITE@,
346 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
347 * be used - compressed and PWG output is generally 25-50% smaller but adds a
348 * 100-300% execution time overhead.
351 cups_raster_t
* /* O - New stream */
352 cupsRasterOpen(int fd
, /* I - File descriptor */
353 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
354 @code CUPS_RASTER_WRITE@,
355 @code CUPS_RASTER_WRITE_COMPRESSED@,
356 or @code CUPS_RASTER_WRITE_PWG@ */
358 if (mode
== CUPS_RASTER_READ
)
359 return (cupsRasterOpenIO(cups_read_fd
, (void *)((intptr_t)fd
), mode
));
361 return (cupsRasterOpenIO(cups_write_fd
, (void *)((intptr_t)fd
), mode
));
366 * 'cupsRasterOpenIO()' - Open a raster stream using a callback function.
368 * This function associates a raster stream with the given callback function and
371 * When writing raster data, the @code CUPS_RASTER_WRITE@,
372 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
373 * be used - compressed and PWG output is generally 25-50% smaller but adds a
374 * 100-300% execution time overhead.
377 cups_raster_t
* /* O - New stream */
379 cups_raster_iocb_t iocb
, /* I - Read/write callback */
380 void *ctx
, /* I - Context pointer for callback */
381 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
382 @code CUPS_RASTER_WRITE@,
383 @code CUPS_RASTER_WRITE_COMPRESSED@,
384 or @code CUPS_RASTER_WRITE_PWG@ */
386 cups_raster_t
*r
; /* New stream */
389 _cupsRasterClearError();
391 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
393 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
402 if (mode
== CUPS_RASTER_READ
)
405 * Open for read - get sync word...
408 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) !=
411 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
417 if (r
->sync
!= CUPS_RASTER_SYNC
&&
418 r
->sync
!= CUPS_RASTER_REVSYNC
&&
419 r
->sync
!= CUPS_RASTER_SYNCv1
&&
420 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
421 r
->sync
!= CUPS_RASTER_SYNCv2
&&
422 r
->sync
!= CUPS_RASTER_REVSYNCv2
&&
423 r
->sync
!= CUPS_RASTER_SYNCapple
&&
424 r
->sync
!= CUPS_RASTER_REVSYNCapple
)
426 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
431 if (r
->sync
== CUPS_RASTER_SYNCv2
||
432 r
->sync
== CUPS_RASTER_REVSYNCv2
||
433 r
->sync
== CUPS_RASTER_SYNCapple
||
434 r
->sync
== CUPS_RASTER_REVSYNCapple
)
437 if (r
->sync
== CUPS_RASTER_REVSYNC
||
438 r
->sync
== CUPS_RASTER_REVSYNCv1
||
439 r
->sync
== CUPS_RASTER_REVSYNCv2
||
440 r
->sync
== CUPS_RASTER_REVSYNCapple
)
443 if (r
->sync
== CUPS_RASTER_SYNCapple
||
444 r
->sync
== CUPS_RASTER_REVSYNCapple
)
446 unsigned char header
[8]; /* File header */
448 if (cups_raster_io(r
, (unsigned char *)header
, sizeof(header
)) !=
451 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
459 DEBUG_printf(("1cupsRasterOpenIO: r->swapped=%d, r->sync=%08x\n", r
->swapped
, r
->sync
));
464 * Open for write - put sync word...
470 case CUPS_RASTER_WRITE
:
471 r
->sync
= CUPS_RASTER_SYNC
;
474 case CUPS_RASTER_WRITE_COMPRESSED
:
476 r
->sync
= CUPS_RASTER_SYNCv2
;
479 case CUPS_RASTER_WRITE_PWG
:
481 r
->sync
= htonl(CUPS_RASTER_SYNC_PWG
);
482 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNC_PWG
;
485 case CUPS_RASTER_WRITE_APPLE
:
487 r
->sync
= htonl(CUPS_RASTER_SYNCapple
);
488 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNCapple
;
489 r
->apple_page_count
= 0xffffffffU
;
493 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) < (ssize_t
)sizeof(r
->sync
))
495 _cupsRasterAddError("Unable to write raster stream header: %s\n",
507 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
508 * version 1 page header structure.
510 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
512 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
513 * of the version 2 page header data. This function handles reading version 2
514 * page headers and copying only the version 1 data into the provided buffer.
519 unsigned /* O - 1 on success, 0 on failure/end-of-file */
520 cupsRasterReadHeader(
521 cups_raster_t
*r
, /* I - Raster stream */
522 cups_page_header_t
*h
) /* I - Pointer to header data */
525 * Get the raster header...
528 if (!cups_raster_read_header(r
))
530 memset(h
, 0, sizeof(cups_page_header_t
));
535 * Copy the header to the user-supplied buffer...
538 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
545 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
546 * version 2 page header structure.
548 * @since CUPS 1.2/macOS 10.5@
551 unsigned /* O - 1 on success, 0 on failure/end-of-file */
552 cupsRasterReadHeader2(
553 cups_raster_t
*r
, /* I - Raster stream */
554 cups_page_header2_t
*h
) /* I - Pointer to header data */
557 * Get the raster header...
560 DEBUG_printf(("cupsRasterReadHeader2(r=%p, h=%p)", (void *)r
, (void *)h
));
562 if (!cups_raster_read_header(r
))
564 memset(h
, 0, sizeof(cups_page_header2_t
));
569 * Copy the header to the user-supplied buffer...
572 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
579 * 'cupsRasterReadPixels()' - Read raster pixels.
581 * For best performance, filters should read one or more whole lines.
582 * The "cupsBytesPerLine" value from the page header can be used to allocate
583 * the line buffer and as the number of bytes to read.
586 unsigned /* O - Number of bytes read */
587 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
588 unsigned char *p
, /* I - Pointer to pixel buffer */
589 unsigned len
) /* I - Number of bytes to read */
591 ssize_t bytes
; /* Bytes read */
592 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
593 unsigned remaining
; /* Bytes remaining */
594 unsigned char *ptr
, /* Pointer to read buffer */
595 byte
, /* Byte from file */
596 *temp
; /* Pointer into buffer */
597 unsigned count
; /* Repetition count */
600 DEBUG_printf(("cupsRasterReadPixels(r=%p, p=%p, len=%u)", (void *)r
, (void *)p
, len
));
602 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0 ||
603 r
->header
.cupsBytesPerLine
== 0)
605 DEBUG_puts("1cupsRasterReadPixels: Returning 0.");
609 DEBUG_printf(("1cupsRasterReadPixels: compressed=%d, remaining=%u", r
->compressed
, r
->remaining
));
614 * Read without compression...
617 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
619 if (cups_raster_io(r
, p
, len
) < (ssize_t
)len
)
621 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
626 * Swap bytes as needed...
630 (r
->header
.cupsBitsPerColor
== 16 ||
631 r
->header
.cupsBitsPerPixel
== 12 ||
632 r
->header
.cupsBitsPerPixel
== 16))
639 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
645 * Read compressed data...
649 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
651 while (remaining
> 0 && r
->remaining
> 0)
656 * Need to read a new row...
659 if (remaining
== cupsBytesPerLine
)
665 * Read using a modified PackBits compression...
668 if (!cups_raster_read(r
, &byte
, 1))
670 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
674 r
->count
= (unsigned)byte
+ 1;
680 bytes
= (ssize_t
)cupsBytesPerLine
;
685 * Get a new repeat count...
688 if (!cups_raster_read(r
, &byte
, 1))
690 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
697 * Clear to end of line...
700 switch (r
->header
.cupsColorSpace
)
703 case CUPS_CSPACE_RGB
:
704 case CUPS_CSPACE_SW
:
705 case CUPS_CSPACE_SRGB
:
706 case CUPS_CSPACE_RGBW
:
707 case CUPS_CSPACE_ADOBERGB
:
708 memset(temp
, 0xff, bytes
);
711 memset(temp
, 0x00, bytes
);
721 * Copy N literal pixels...
724 count
= (unsigned)(257 - byte
) * r
->bpp
;
726 if (count
> (unsigned)bytes
)
727 count
= (unsigned)bytes
;
729 if (!cups_raster_read(r
, temp
, count
))
731 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
736 bytes
-= (ssize_t
)count
;
741 * Repeat the next N bytes...
744 count
= ((unsigned)byte
+ 1) * r
->bpp
;
745 if (count
> (unsigned)bytes
)
746 count
= (unsigned)bytes
;
751 bytes
-= (ssize_t
)count
;
753 if (!cups_raster_read(r
, temp
, r
->bpp
))
755 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
764 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
772 * Swap bytes as needed...
775 if ((r
->header
.cupsBitsPerColor
== 16 ||
776 r
->header
.cupsBitsPerPixel
== 12 ||
777 r
->header
.cupsBitsPerPixel
== 16) &&
779 cups_swap(ptr
, (size_t)bytes
);
785 if (remaining
>= cupsBytesPerLine
)
787 bytes
= (ssize_t
)cupsBytesPerLine
;
788 r
->pcurrent
= r
->pixels
;
794 bytes
= (ssize_t
)remaining
;
795 r
->pcurrent
= r
->pixels
+ bytes
;
799 * Copy data as needed...
803 memcpy(p
, ptr
, (size_t)bytes
);
808 * Copy fragment from buffer...
811 if ((unsigned)(bytes
= (int)(r
->pend
- r
->pcurrent
)) > remaining
)
812 bytes
= (ssize_t
)remaining
;
814 memcpy(p
, r
->pcurrent
, (size_t)bytes
);
815 r
->pcurrent
+= bytes
;
817 if (r
->pcurrent
>= r
->pend
)
819 r
->pcurrent
= r
->pixels
;
825 remaining
-= (unsigned)bytes
;
829 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
836 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
839 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
844 unsigned /* O - 1 on success, 0 on failure */
845 cupsRasterWriteHeader(
846 cups_raster_t
*r
, /* I - Raster stream */
847 cups_page_header_t
*h
) /* I - Raster page header */
849 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
853 * Make a copy of the header, and compute the number of raster
854 * lines in the page image...
857 memset(&(r
->header
), 0, sizeof(r
->header
));
858 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
860 if (!cups_raster_update(r
))
864 * Write the raster header...
867 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
870 * PWG raster data is always network byte order with much of the page header
874 cups_page_header2_t fh
; /* File page header */
876 memset(&fh
, 0, sizeof(fh
));
878 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
880 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
881 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
882 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
883 /* PrintContentType */
885 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
886 fh
.Duplex
= htonl(r
->header
.Duplex
);
887 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
888 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
889 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
890 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
891 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
892 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
893 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
894 fh
.Jog
= htonl(r
->header
.Jog
);
895 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
896 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
897 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
898 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
899 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
900 fh
.Orientation
= htonl(r
->header
.Orientation
);
901 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
902 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
903 fh
.Tumble
= htonl(r
->header
.Tumble
);
904 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
905 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
906 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
907 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
908 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
909 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
910 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
911 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
912 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
914 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
915 /* CrossFeedTransform */
916 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
918 fh
.cupsInteger
[3] = htonl(r
->header
.cupsInteger
[3]);
920 fh
.cupsInteger
[4] = htonl(r
->header
.cupsInteger
[4]);
922 fh
.cupsInteger
[5] = htonl(r
->header
.cupsInteger
[5]);
924 fh
.cupsInteger
[6] = htonl(r
->header
.cupsInteger
[6]);
926 fh
.cupsInteger
[7] = htonl(r
->header
.cupsInteger
[7]);
928 fh
.cupsInteger
[8] = htonl(r
->header
.cupsInteger
[8]);
930 fh
.cupsInteger
[14] = htonl(r
->header
.cupsInteger
[14]);
931 /* VendorIdentifier */
932 fh
.cupsInteger
[15] = htonl(r
->header
.cupsInteger
[15]);
935 void *dst
= fh
.cupsReal
; /* Bypass bogus compiler warning */
936 void *src
= r
->header
.cupsReal
;
937 memcpy(dst
, src
, sizeof(fh
.cupsReal
) + sizeof(fh
.cupsString
));
940 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
941 sizeof(fh
.cupsRenderingIntent
));
942 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
943 sizeof(fh
.cupsPageSizeName
));
945 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
947 else if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
950 * Raw raster data is always network byte order with most of the page header
954 unsigned char appleheader
[64]; /* Raw page header */
956 if (r
->apple_page_count
== 0xffffffffU
)
959 * Write raw page count from raster page header...
962 r
->apple_page_count
= r
->header
.cupsInteger
[0];
964 appleheader
[0] = 'A';
965 appleheader
[1] = 'S';
966 appleheader
[2] = 'T';
968 appleheader
[4] = (unsigned char)(r
->apple_page_count
>> 24);
969 appleheader
[5] = (unsigned char)(r
->apple_page_count
>> 16);
970 appleheader
[6] = (unsigned char)(r
->apple_page_count
>> 8);
971 appleheader
[7] = (unsigned char)(r
->apple_page_count
);
973 if (cups_raster_io(r
, appleheader
, 8) != 8)
977 memset(appleheader
, 0, sizeof(appleheader
));
979 appleheader
[0] = (unsigned char)r
->header
.cupsBitsPerPixel
;
980 appleheader
[1] = r
->header
.cupsColorSpace
== CUPS_CSPACE_SRGB
? 1 :
981 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGBW
? 2 :
982 r
->header
.cupsColorSpace
== CUPS_CSPACE_ADOBERGB
? 3 :
983 r
->header
.cupsColorSpace
== CUPS_CSPACE_W
? 4 :
984 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGB
? 5 :
985 r
->header
.cupsColorSpace
== CUPS_CSPACE_CMYK
? 6 : 0;
986 appleheader
[12] = (unsigned char)(r
->header
.cupsWidth
>> 24);
987 appleheader
[13] = (unsigned char)(r
->header
.cupsWidth
>> 16);
988 appleheader
[14] = (unsigned char)(r
->header
.cupsWidth
>> 8);
989 appleheader
[15] = (unsigned char)(r
->header
.cupsWidth
);
990 appleheader
[16] = (unsigned char)(r
->header
.cupsHeight
>> 24);
991 appleheader
[17] = (unsigned char)(r
->header
.cupsHeight
>> 16);
992 appleheader
[18] = (unsigned char)(r
->header
.cupsHeight
>> 8);
993 appleheader
[19] = (unsigned char)(r
->header
.cupsHeight
);
994 appleheader
[20] = (unsigned char)(r
->header
.HWResolution
[0] >> 24);
995 appleheader
[21] = (unsigned char)(r
->header
.HWResolution
[0] >> 16);
996 appleheader
[22] = (unsigned char)(r
->header
.HWResolution
[0] >> 8);
997 appleheader
[23] = (unsigned char)(r
->header
.HWResolution
[0]);
999 return (cups_raster_io(r
, appleheader
, sizeof(appleheader
)) == sizeof(appleheader
));
1002 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
1003 == sizeof(r
->header
));
1008 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
1009 * page header structure.
1011 * The page header can be initialized using @link cupsRasterInterpretPPD@.
1013 * @since CUPS 1.2/macOS 10.5@
1016 unsigned /* O - 1 on success, 0 on failure */
1017 cupsRasterWriteHeader2(
1018 cups_raster_t
*r
, /* I - Raster stream */
1019 cups_page_header2_t
*h
) /* I - Raster page header */
1021 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
1025 * Make a copy of the header, and compute the number of raster
1026 * lines in the page image...
1029 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
1031 if (!cups_raster_update(r
))
1035 * Write the raster header...
1038 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
1041 * PWG raster data is always network byte order with most of the page header
1045 cups_page_header2_t fh
; /* File page header */
1047 memset(&fh
, 0, sizeof(fh
));
1048 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
1049 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
1050 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
1051 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
1052 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
1053 sizeof(fh
.cupsRenderingIntent
));
1054 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
1055 sizeof(fh
.cupsPageSizeName
));
1057 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
1058 fh
.Duplex
= htonl(r
->header
.Duplex
);
1059 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
1060 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
1061 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
1062 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
1063 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
1064 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
1065 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
1066 fh
.Jog
= htonl(r
->header
.Jog
);
1067 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
1068 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
1069 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
1070 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
1071 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
1072 fh
.Orientation
= htonl(r
->header
.Orientation
);
1073 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
1074 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
1075 fh
.Tumble
= htonl(r
->header
.Tumble
);
1076 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
1077 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
1078 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
1079 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
1080 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
1081 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
1082 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
1083 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
1084 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
1085 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
1086 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
1087 fh
.cupsInteger
[3] = htonl((unsigned)(r
->header
.cupsImagingBBox
[0] * r
->header
.HWResolution
[0] / 72.0));
1088 fh
.cupsInteger
[4] = htonl((unsigned)(r
->header
.cupsImagingBBox
[1] * r
->header
.HWResolution
[1] / 72.0));
1089 fh
.cupsInteger
[5] = htonl((unsigned)(r
->header
.cupsImagingBBox
[2] * r
->header
.HWResolution
[0] / 72.0));
1090 fh
.cupsInteger
[6] = htonl((unsigned)(r
->header
.cupsImagingBBox
[3] * r
->header
.HWResolution
[1] / 72.0));
1091 fh
.cupsInteger
[7] = htonl(0xffffff);
1093 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
1095 else if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
1098 * Raw raster data is always network byte order with most of the page header
1102 unsigned char appleheader
[64]; /* Raw page header */
1104 if (r
->apple_page_count
== 0xffffffffU
)
1107 * Write raw page count from raster page header...
1110 r
->apple_page_count
= r
->header
.cupsInteger
[0];
1112 appleheader
[0] = 'A';
1113 appleheader
[1] = 'S';
1114 appleheader
[2] = 'T';
1116 appleheader
[4] = (unsigned char)(r
->apple_page_count
>> 24);
1117 appleheader
[5] = (unsigned char)(r
->apple_page_count
>> 16);
1118 appleheader
[6] = (unsigned char)(r
->apple_page_count
>> 8);
1119 appleheader
[7] = (unsigned char)(r
->apple_page_count
);
1121 if (cups_raster_io(r
, appleheader
, 8) != 8)
1125 memset(appleheader
, 0, sizeof(appleheader
));
1127 appleheader
[0] = (unsigned char)r
->header
.cupsBitsPerPixel
;
1128 appleheader
[1] = r
->header
.cupsColorSpace
== CUPS_CSPACE_SRGB
? 1 :
1129 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGBW
? 2 :
1130 r
->header
.cupsColorSpace
== CUPS_CSPACE_ADOBERGB
? 3 :
1131 r
->header
.cupsColorSpace
== CUPS_CSPACE_W
? 4 :
1132 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGB
? 5 :
1133 r
->header
.cupsColorSpace
== CUPS_CSPACE_CMYK
? 6 : 0;
1134 appleheader
[12] = (unsigned char)(r
->header
.cupsWidth
>> 24);
1135 appleheader
[13] = (unsigned char)(r
->header
.cupsWidth
>> 16);
1136 appleheader
[14] = (unsigned char)(r
->header
.cupsWidth
>> 8);
1137 appleheader
[15] = (unsigned char)(r
->header
.cupsWidth
);
1138 appleheader
[16] = (unsigned char)(r
->header
.cupsHeight
>> 24);
1139 appleheader
[17] = (unsigned char)(r
->header
.cupsHeight
>> 16);
1140 appleheader
[18] = (unsigned char)(r
->header
.cupsHeight
>> 8);
1141 appleheader
[19] = (unsigned char)(r
->header
.cupsHeight
);
1142 appleheader
[20] = (unsigned char)(r
->header
.HWResolution
[0] >> 24);
1143 appleheader
[21] = (unsigned char)(r
->header
.HWResolution
[0] >> 16);
1144 appleheader
[22] = (unsigned char)(r
->header
.HWResolution
[0] >> 8);
1145 appleheader
[23] = (unsigned char)(r
->header
.HWResolution
[0]);
1147 return (cups_raster_io(r
, appleheader
, sizeof(appleheader
)) == sizeof(appleheader
));
1150 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
1151 == sizeof(r
->header
));
1156 * 'cupsRasterWritePixels()' - Write raster pixels.
1158 * For best performance, filters should write one or more whole lines.
1159 * The "cupsBytesPerLine" value from the page header can be used to allocate
1160 * the line buffer and as the number of bytes to write.
1163 unsigned /* O - Number of bytes written */
1164 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
1165 unsigned char *p
, /* I - Bytes to write */
1166 unsigned len
)/* I - Number of bytes to write */
1168 ssize_t bytes
; /* Bytes read */
1169 unsigned remaining
; /* Bytes remaining */
1172 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u", (void *)r
, (void *)p
, len
, r
->remaining
));
1174 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
|| r
->remaining
== 0)
1180 * Without compression, just write the raster data raw unless the data needs
1184 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
1187 (r
->header
.cupsBitsPerColor
== 16 ||
1188 r
->header
.cupsBitsPerPixel
== 12 ||
1189 r
->header
.cupsBitsPerPixel
== 16))
1191 unsigned char *bufptr
; /* Pointer into write buffer */
1192 unsigned count
; /* Remaining count */
1195 * Allocate a write buffer as needed...
1198 if ((size_t)len
> r
->bufsize
)
1201 bufptr
= realloc(r
->buffer
, len
);
1203 bufptr
= malloc(len
);
1213 * Byte swap the pixels...
1216 for (bufptr
= r
->buffer
, count
= len
; count
> 1; count
-= 2, bufptr
+= 2)
1222 if (count
) /* This should never happen... */
1226 * Write the byte-swapped buffer...
1229 bytes
= cups_raster_io(r
, r
->buffer
, len
);
1232 bytes
= cups_raster_io(r
, p
, len
);
1241 * Otherwise, compress each line...
1244 for (remaining
= len
; remaining
> 0; remaining
-= (unsigned)bytes
, p
+= bytes
)
1247 * Figure out the number of remaining bytes on the current line...
1250 if ((bytes
= (ssize_t
)remaining
) > (ssize_t
)(r
->pend
- r
->pcurrent
))
1251 bytes
= (ssize_t
)(r
->pend
- r
->pcurrent
);
1256 * Check to see if this line is the same as the previous line...
1259 if (memcmp(p
, r
->pcurrent
, (size_t)bytes
))
1261 if (cups_raster_write(r
, r
->pixels
) <= 0)
1269 * Mark more bytes as the same...
1272 r
->pcurrent
+= bytes
;
1274 if (r
->pcurrent
>= r
->pend
)
1277 * Increase the repeat count...
1281 r
->pcurrent
= r
->pixels
;
1284 * Flush out this line if it is the last one...
1289 if (r
->remaining
== 0)
1291 if (cups_raster_write(r
, r
->pixels
) <= 0)
1296 else if (r
->count
== 256)
1298 if (cups_raster_write(r
, r
->pixels
) <= 0)
1312 * Copy the raster data to the buffer...
1315 memcpy(r
->pcurrent
, p
, (size_t)bytes
);
1317 r
->pcurrent
+= bytes
;
1319 if (r
->pcurrent
>= r
->pend
)
1322 * Increase the repeat count...
1326 r
->pcurrent
= r
->pixels
;
1329 * Flush out this line if it is the last one...
1334 if (r
->remaining
== 0)
1336 if (cups_raster_write(r
, r
->pixels
) <= 0)
1348 * 'cups_raster_read_header()' - Read a raster page header.
1351 static unsigned /* O - 1 on success, 0 on fail */
1352 cups_raster_read_header(
1353 cups_raster_t
*r
) /* I - Raster stream */
1355 size_t len
; /* Length for read/swap */
1358 DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%d", (void *)r
, r
? r
->mode
: 0));
1360 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
1363 DEBUG_printf(("4cups_raster_read_header: r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1365 memset(&(r
->header
), 0, sizeof(r
->header
));
1368 * Read the header...
1375 * Get the length of the raster header...
1378 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
1379 len
= sizeof(cups_page_header_t
);
1381 len
= sizeof(cups_page_header2_t
);
1383 DEBUG_printf(("4cups_raster_read_header: len=%d", (int)len
));
1389 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < (ssize_t
)len
)
1391 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1396 * Swap bytes as needed...
1401 unsigned *s
, /* Current word */
1402 temp
; /* Temporary copy */
1405 DEBUG_puts("4cups_raster_read_header: Swapping header bytes.");
1407 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
1412 *s
= ((temp
& 0xff) << 24) |
1413 ((temp
& 0xff00) << 8) |
1414 ((temp
& 0xff0000) >> 8) |
1415 ((temp
& 0xff000000) >> 24);
1417 DEBUG_printf(("4cups_raster_read_header: %08x => %08x", temp
, *s
));
1422 case CUPS_RASTER_SYNCapple
:
1423 case CUPS_RASTER_REVSYNCapple
:
1425 unsigned char appleheader
[64]; /* Raw header */
1426 static const unsigned rawcspace
[] =
1431 CUPS_CSPACE_ADOBERGB
,
1436 static const unsigned rawnumcolors
[] =
1447 if (cups_raster_read(r
, appleheader
, sizeof(appleheader
)) < (ssize_t
)sizeof(appleheader
))
1449 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1453 strlcpy(r
->header
.MediaClass
, "PwgRaster", sizeof(r
->header
.MediaClass
));
1455 r
->header
.cupsBitsPerPixel
= appleheader
[0];
1456 r
->header
.cupsColorSpace
= appleheader
[1] >= (sizeof(rawcspace
) / sizeof(rawcspace
[0])) ? CUPS_CSPACE_DEVICE1
: rawcspace
[appleheader
[1]];
1457 r
->header
.cupsNumColors
= appleheader
[1] >= (sizeof(rawnumcolors
) / sizeof(rawnumcolors
[0])) ? 1 : rawnumcolors
[appleheader
[1]];
1458 r
->header
.cupsBitsPerColor
= r
->header
.cupsBitsPerPixel
/ r
->header
.cupsNumColors
;
1459 r
->header
.cupsWidth
= ((((((unsigned)appleheader
[12] << 8) | (unsigned)appleheader
[13]) << 8) | (unsigned)appleheader
[14]) << 8) | (unsigned)appleheader
[15];
1460 r
->header
.cupsHeight
= ((((((unsigned)appleheader
[16] << 8) | (unsigned)appleheader
[17]) << 8) | (unsigned)appleheader
[18]) << 8) | (unsigned)appleheader
[19];
1461 r
->header
.cupsBytesPerLine
= r
->header
.cupsWidth
* r
->header
.cupsBitsPerPixel
/ 8;
1462 r
->header
.cupsColorOrder
= CUPS_ORDER_CHUNKED
;
1463 r
->header
.HWResolution
[0] = r
->header
.HWResolution
[1] = ((((((unsigned)appleheader
[20] << 8) | (unsigned)appleheader
[21]) << 8) | (unsigned)appleheader
[22]) << 8) | (unsigned)appleheader
[23];
1465 if (r
->header
.HWResolution
[0] > 0)
1467 r
->header
.PageSize
[0] = (unsigned)(r
->header
.cupsWidth
* 72 / r
->header
.HWResolution
[0]);
1468 r
->header
.PageSize
[1] = (unsigned)(r
->header
.cupsHeight
* 72 / r
->header
.HWResolution
[1]);
1469 r
->header
.cupsPageSize
[0] = (float)(r
->header
.cupsWidth
* 72.0 / r
->header
.HWResolution
[0]);
1470 r
->header
.cupsPageSize
[1] = (float)(r
->header
.cupsHeight
* 72.0 / r
->header
.HWResolution
[1]);
1473 r
->header
.cupsInteger
[0] = r
->apple_page_count
;
1474 r
->header
.cupsInteger
[7] = 0xffffff;
1480 * Update the header and row count...
1483 if (!cups_raster_update(r
))
1486 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
));
1488 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);
1493 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
1496 static ssize_t
/* O - Bytes read/write or -1 */
1497 cups_raster_io(cups_raster_t
*r
, /* I - Raster stream */
1498 unsigned char *buf
, /* I - Buffer for read/write */
1499 size_t bytes
) /* I - Number of bytes to read/write */
1501 ssize_t count
, /* Number of bytes read/written */
1502 total
; /* Total bytes read/written */
1505 DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", (void *)r
, (void *)buf
, CUPS_LLCAST bytes
));
1507 for (total
= 0; total
< (ssize_t
)bytes
; total
+= count
, buf
+= count
)
1509 count
= (*r
->iocb
)(r
->ctx
, buf
, bytes
- (size_t)total
);
1511 DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count
, (int)total
));
1514 DEBUG_puts("6cups_raster_io: Returning 0.");
1519 DEBUG_puts("6cups_raster_io: Returning -1 on error.");
1524 r
->iocount
+= (size_t)count
;
1528 DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT
".", CUPS_LLCAST total
));
1535 * 'cups_raster_read()' - Read through the raster buffer.
1538 static ssize_t
/* O - Number of bytes read */
1539 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
1540 unsigned char *buf
, /* I - Buffer */
1541 size_t bytes
) /* I - Number of bytes to read */
1543 ssize_t count
, /* Number of bytes read */
1544 remaining
, /* Remaining bytes in buffer */
1545 total
; /* Total bytes read */
1548 DEBUG_printf(("5cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", (void *)r
, (void *)buf
, CUPS_LLCAST bytes
));
1551 return (cups_raster_io(r
, buf
, bytes
));
1554 * Allocate a read buffer as needed...
1557 count
= (ssize_t
)(2 * r
->header
.cupsBytesPerLine
);
1561 if ((size_t)count
> r
->bufsize
)
1563 ssize_t offset
= r
->bufptr
- r
->buffer
;
1564 /* Offset to current start of buffer */
1565 ssize_t end
= r
->bufend
- r
->buffer
;/* Offset to current end of buffer */
1566 unsigned char *rptr
; /* Pointer in read buffer */
1569 rptr
= realloc(r
->buffer
, (size_t)count
);
1571 rptr
= malloc((size_t)count
);
1577 r
->bufptr
= rptr
+ offset
;
1578 r
->bufend
= rptr
+ end
;
1579 r
->bufsize
= (size_t)count
;
1583 * Loop until we have read everything...
1586 for (total
= 0, remaining
= (int)(r
->bufend
- r
->bufptr
);
1587 total
< (ssize_t
)bytes
;
1588 total
+= count
, buf
+= count
)
1590 count
= (ssize_t
)bytes
- total
;
1592 DEBUG_printf(("6cups_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
));
1599 * Read into the raster buffer and then copy...
1602 remaining
= (*r
->iocb
)(r
->ctx
, r
->buffer
, r
->bufsize
);
1606 r
->bufptr
= r
->buffer
;
1607 r
->bufend
= r
->buffer
+ remaining
;
1610 r
->iocount
+= (size_t)remaining
;
1616 * Read directly into "buf"...
1619 count
= (*r
->iocb
)(r
->ctx
, buf
, (size_t)count
);
1625 r
->iocount
+= (size_t)count
;
1633 * Copy bytes from raster buffer to "buf"...
1636 if (count
> remaining
)
1645 *buf
= *(r
->bufptr
)++;
1648 else if (count
< 128)
1651 * Copy up to 127 bytes without using memcpy(); this is
1652 * faster because it avoids an extra function call and is
1653 * often further optimized by the compiler...
1656 unsigned char *bufptr
; /* Temporary buffer pointer */
1660 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
1668 * Use memcpy() for a large read...
1671 memcpy(buf
, r
->bufptr
, (size_t)count
);
1677 DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total
));
1684 * 'cups_raster_update()' - Update the raster header and row count for the
1688 static int /* O - 1 on success, 0 on failure */
1689 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
1691 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
1692 r
->header
.cupsNumColors
== 0)
1695 * Set the "cupsNumColors" field according to the colorspace...
1698 switch (r
->header
.cupsColorSpace
)
1700 case CUPS_CSPACE_W
:
1701 case CUPS_CSPACE_K
:
1702 case CUPS_CSPACE_WHITE
:
1703 case CUPS_CSPACE_GOLD
:
1704 case CUPS_CSPACE_SILVER
:
1705 case CUPS_CSPACE_SW
:
1706 r
->header
.cupsNumColors
= 1;
1709 case CUPS_CSPACE_RGB
:
1710 case CUPS_CSPACE_CMY
:
1711 case CUPS_CSPACE_YMC
:
1712 case CUPS_CSPACE_CIEXYZ
:
1713 case CUPS_CSPACE_CIELab
:
1714 case CUPS_CSPACE_SRGB
:
1715 case CUPS_CSPACE_ADOBERGB
:
1716 case CUPS_CSPACE_ICC1
:
1717 case CUPS_CSPACE_ICC2
:
1718 case CUPS_CSPACE_ICC3
:
1719 case CUPS_CSPACE_ICC4
:
1720 case CUPS_CSPACE_ICC5
:
1721 case CUPS_CSPACE_ICC6
:
1722 case CUPS_CSPACE_ICC7
:
1723 case CUPS_CSPACE_ICC8
:
1724 case CUPS_CSPACE_ICC9
:
1725 case CUPS_CSPACE_ICCA
:
1726 case CUPS_CSPACE_ICCB
:
1727 case CUPS_CSPACE_ICCC
:
1728 case CUPS_CSPACE_ICCD
:
1729 case CUPS_CSPACE_ICCE
:
1730 case CUPS_CSPACE_ICCF
:
1731 r
->header
.cupsNumColors
= 3;
1734 case CUPS_CSPACE_RGBA
:
1735 case CUPS_CSPACE_RGBW
:
1736 case CUPS_CSPACE_CMYK
:
1737 case CUPS_CSPACE_YMCK
:
1738 case CUPS_CSPACE_KCMY
:
1739 case CUPS_CSPACE_GMCK
:
1740 case CUPS_CSPACE_GMCS
:
1741 r
->header
.cupsNumColors
= 4;
1744 case CUPS_CSPACE_KCMYcm
:
1745 if (r
->header
.cupsBitsPerPixel
< 8)
1746 r
->header
.cupsNumColors
= 6;
1748 r
->header
.cupsNumColors
= 4;
1751 case CUPS_CSPACE_DEVICE1
:
1752 case CUPS_CSPACE_DEVICE2
:
1753 case CUPS_CSPACE_DEVICE3
:
1754 case CUPS_CSPACE_DEVICE4
:
1755 case CUPS_CSPACE_DEVICE5
:
1756 case CUPS_CSPACE_DEVICE6
:
1757 case CUPS_CSPACE_DEVICE7
:
1758 case CUPS_CSPACE_DEVICE8
:
1759 case CUPS_CSPACE_DEVICE9
:
1760 case CUPS_CSPACE_DEVICEA
:
1761 case CUPS_CSPACE_DEVICEB
:
1762 case CUPS_CSPACE_DEVICEC
:
1763 case CUPS_CSPACE_DEVICED
:
1764 case CUPS_CSPACE_DEVICEE
:
1765 case CUPS_CSPACE_DEVICEF
:
1766 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
1767 CUPS_CSPACE_DEVICE1
+ 1;
1771 /* Unknown color space */
1777 * Set the number of bytes per pixel/color...
1780 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
1781 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
1783 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
1789 * Set the number of remaining rows...
1792 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
1793 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
1795 r
->remaining
= r
->header
.cupsHeight
;
1798 * Allocate the compression buffer...
1803 if (r
->pixels
!= NULL
)
1806 if ((r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1)) == NULL
)
1815 r
->pcurrent
= r
->pixels
;
1816 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
1825 * 'cups_raster_write()' - Write a row of compressed raster data...
1828 static ssize_t
/* O - Number of bytes written */
1830 cups_raster_t
*r
, /* I - Raster stream */
1831 const unsigned char *pixels
) /* I - Pixel data to write */
1833 const unsigned char *start
, /* Start of sequence */
1834 *ptr
, /* Current pointer in sequence */
1835 *pend
, /* End of raster buffer */
1836 *plast
; /* Pointer to last pixel */
1837 unsigned char *wptr
; /* Pointer into write buffer */
1838 unsigned bpp
, /* Bytes per pixel */
1842 DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r
, (void *)pixels
));
1845 * Allocate a write buffer as needed...
1848 count
= r
->header
.cupsBytesPerLine
* 2;
1852 if ((size_t)count
> r
->bufsize
)
1855 wptr
= realloc(r
->buffer
, count
);
1857 wptr
= malloc(count
);
1861 DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT
" bytes for raster buffer: %s", CUPS_LLCAST count
, strerror(errno
)));
1870 * Write the row repeat count...
1874 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1877 *wptr
++ = (unsigned char)(r
->count
- 1);
1880 * Write using a modified PackBits compression...
1883 for (ptr
= pixels
; ptr
< pend
;)
1891 * Encode a single pixel at the end...
1895 for (count
= bpp
; count
> 0; count
--)
1898 else if (!memcmp(start
, ptr
, bpp
))
1901 * Encode a sequence of repeating pixels...
1904 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1905 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1908 *wptr
++ = (unsigned char)(count
- 1);
1909 for (count
= bpp
; count
> 0; count
--)
1915 * Encode a sequence of non-repeating pixels...
1918 for (count
= 1; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1919 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1922 if (ptr
>= plast
&& count
< 128)
1928 *wptr
++ = (unsigned char)(257 - count
);
1931 memcpy(wptr
, start
, count
);
1936 DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT
" bytes.", CUPS_LLCAST (wptr
- r
->buffer
)));
1938 return (cups_raster_io(r
, r
->buffer
, (size_t)(wptr
- r
->buffer
)));
1943 * 'cups_read_fd()' - Read bytes from a file.
1946 static ssize_t
/* O - Bytes read or -1 */
1947 cups_read_fd(void *ctx
, /* I - File descriptor as pointer */
1948 unsigned char *buf
, /* I - Buffer for read */
1949 size_t bytes
) /* I - Maximum number of bytes to read */
1951 int fd
= (int)((intptr_t)ctx
);
1952 /* File descriptor */
1953 ssize_t count
; /* Number of bytes read */
1956 #ifdef WIN32 /* Sigh */
1957 while ((count
= read(fd
, buf
, (unsigned)bytes
)) < 0)
1959 while ((count
= read(fd
, buf
, bytes
)) < 0)
1961 if (errno
!= EINTR
&& errno
!= EAGAIN
)
1963 DEBUG_printf(("4cups_read_fd: %s", strerror(errno
)));
1967 DEBUG_printf(("4cups_read_fd: Returning %d bytes.", (int)count
));
1974 * 'cups_swap()' - Swap bytes in raster data...
1978 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1979 size_t bytes
) /* I - Number of bytes to swap */
1981 unsigned char even
, odd
; /* Temporary variables */
2000 * 'cups_write_fd()' - Write bytes to a file.
2003 static ssize_t
/* O - Bytes written or -1 */
2004 cups_write_fd(void *ctx
, /* I - File descriptor pointer */
2005 unsigned char *buf
, /* I - Bytes to write */
2006 size_t bytes
) /* I - Number of bytes to write */
2008 int fd
= (int)((intptr_t)ctx
);
2009 /* File descriptor */
2010 ssize_t count
; /* Number of bytes written */
2013 #ifdef WIN32 /* Sigh */
2014 while ((count
= write(fd
, buf
, (unsigned)bytes
)) < 0)
2016 while ((count
= write(fd
, buf
, bytes
)) < 0)
2018 if (errno
!= EINTR
&& errno
!= EAGAIN
)
2020 DEBUG_printf(("4cups_write_fd: %s", strerror(errno
)));