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 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
13 * Include necessary headers...
16 #include <cups/raster-private.h>
19 #endif /* HAVE_STDINT_H */
23 * Private structures...
26 struct _cups_raster_s
/**** Raster stream data ****/
28 unsigned sync
; /* Sync word from start of stream */
29 void *ctx
; /* File descriptor */
30 cups_raster_iocb_t iocb
; /* IO callback */
31 cups_mode_t mode
; /* Read/write mode */
32 cups_page_header2_t header
; /* Raster header for current page */
33 unsigned rowheight
, /* Row height in lines */
34 count
, /* Current row run-length count */
35 remaining
, /* Remaining rows in page image */
36 bpp
; /* Bytes per pixel/color */
37 unsigned char *pixels
, /* Pixels for current row */
38 *pend
, /* End of pixel buffer */
39 *pcurrent
; /* Current byte in pixel buffer */
40 int compressed
, /* Non-zero if data is compressed */
41 swapped
; /* Non-zero if data is byte-swapped */
42 unsigned char *buffer
, /* Read/write buffer */
43 *bufptr
, /* Current (read) position in buffer */
44 *bufend
; /* End of current (read) buffer */
45 size_t bufsize
; /* Buffer size */
47 size_t iocount
; /* Number of bytes read/written */
49 unsigned apple_page_count
;/* Apple raster page count */
57 static ssize_t
cups_raster_io(cups_raster_t
*r
, unsigned char *buf
, size_t bytes
);
58 static unsigned cups_raster_read_header(cups_raster_t
*r
);
59 static ssize_t
cups_raster_read(cups_raster_t
*r
, unsigned char *buf
,
61 static int cups_raster_update(cups_raster_t
*r
);
62 static ssize_t
cups_raster_write(cups_raster_t
*r
,
63 const unsigned char *pixels
);
64 static ssize_t
cups_read_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
65 static void cups_swap(unsigned char *buf
, size_t bytes
);
66 static ssize_t
cups_write_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
70 * 'cupsRasterClose()' - Close a raster stream.
72 * The file descriptor associated with the raster stream must be closed
73 * separately as needed.
77 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
93 * 'cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output.
95 * The "media" argument specifies the media to use.
97 * The "type" argument specifies a "pwg-raster-document-type-supported" value
98 * that controls the color space and bit depth of the raster data.
100 * The "xres" and "yres" arguments specify the raster resolution in dots per
103 * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value
104 * to apply for the back side of a page. Pass @code NULL@ for the front side.
106 * @since CUPS 2.2/macOS 10.12@
109 int /* O - 1 on success, 0 on failure */
110 cupsRasterInitPWGHeader(
111 cups_page_header2_t
*h
, /* I - Page header */
112 pwg_media_t
*media
, /* I - PWG media information */
113 const char *type
, /* I - PWG raster type string */
114 int xdpi
, /* I - Cross-feed direction (horizontal) resolution */
115 int ydpi
, /* I - Feed direction (vertical) resolution */
116 const char *sides
, /* I - IPP "sides" option value */
117 const char *sheet_back
) /* I - Transform for back side or @code NULL@ for none */
119 if (!h
|| !media
|| !type
|| xdpi
<= 0 || ydpi
<= 0)
121 _cupsRasterAddError("%s", strerror(EINVAL
));
126 * Initialize the page header...
129 memset(h
, 0, sizeof(cups_page_header2_t
));
131 strlcpy(h
->cupsPageSizeName
, media
->pwg
, sizeof(h
->cupsPageSizeName
));
133 h
->PageSize
[0] = (unsigned)(72 * media
->width
/ 2540);
134 h
->PageSize
[1] = (unsigned)(72 * media
->length
/ 2540);
136 /* This never gets written but is needed for some applications */
137 h
->cupsPageSize
[0] = 72.0f
* media
->width
/ 2540.0f
;
138 h
->cupsPageSize
[1] = 72.0f
* media
->length
/ 2540.0f
;
140 h
->ImagingBoundingBox
[2] = h
->PageSize
[0];
141 h
->ImagingBoundingBox
[3] = h
->PageSize
[1];
143 h
->HWResolution
[0] = (unsigned)xdpi
;
144 h
->HWResolution
[1] = (unsigned)ydpi
;
146 h
->cupsWidth
= (unsigned)(media
->width
* xdpi
/ 2540);
147 h
->cupsHeight
= (unsigned)(media
->length
* ydpi
/ 2540);
149 if (h
->cupsWidth
> 0x00ffffff || h
->cupsHeight
> 0x00ffffff)
151 _cupsRasterAddError("Raster dimensions too large.");
155 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxRight
] = h
->cupsWidth
;
156 h
->cupsInteger
[CUPS_RASTER_PWG_ImageBoxBottom
] = h
->cupsHeight
;
159 * Colorspace and bytes per line...
162 if (!strcmp(type
, "adobe-rgb_8"))
164 h
->cupsBitsPerColor
= 8;
165 h
->cupsBitsPerPixel
= 24;
166 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
168 else if (!strcmp(type
, "adobe-rgb_16"))
170 h
->cupsBitsPerColor
= 16;
171 h
->cupsBitsPerPixel
= 48;
172 h
->cupsColorSpace
= CUPS_CSPACE_ADOBERGB
;
174 else if (!strcmp(type
, "black_1"))
176 h
->cupsBitsPerColor
= 1;
177 h
->cupsBitsPerPixel
= 1;
178 h
->cupsColorSpace
= CUPS_CSPACE_K
;
180 else if (!strcmp(type
, "black_8"))
182 h
->cupsBitsPerColor
= 8;
183 h
->cupsBitsPerPixel
= 8;
184 h
->cupsColorSpace
= CUPS_CSPACE_K
;
186 else if (!strcmp(type
, "black_16"))
188 h
->cupsBitsPerColor
= 16;
189 h
->cupsBitsPerPixel
= 16;
190 h
->cupsColorSpace
= CUPS_CSPACE_K
;
192 else if (!strcmp(type
, "cmyk_8"))
194 h
->cupsBitsPerColor
= 8;
195 h
->cupsBitsPerPixel
= 32;
196 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
198 else if (!strcmp(type
, "cmyk_16"))
200 h
->cupsBitsPerColor
= 16;
201 h
->cupsBitsPerPixel
= 64;
202 h
->cupsColorSpace
= CUPS_CSPACE_CMYK
;
204 else if (!strncmp(type
, "device", 6) && type
[6] >= '1' && type
[6] <= '9')
206 int ncolors
, bits
; /* Number of colors and bits */
209 if (sscanf(type
, "device%d_%d", &ncolors
, &bits
) != 2 || ncolors
> 15 || (bits
!= 8 && bits
!= 16))
211 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
215 h
->cupsBitsPerColor
= (unsigned)bits
;
216 h
->cupsBitsPerPixel
= (unsigned)(ncolors
* bits
);
217 h
->cupsColorSpace
= (cups_cspace_t
)(CUPS_CSPACE_DEVICE1
+ ncolors
- 1);
219 else if (!strcmp(type
, "rgb_8"))
221 h
->cupsBitsPerColor
= 8;
222 h
->cupsBitsPerPixel
= 24;
223 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
225 else if (!strcmp(type
, "rgb_16"))
227 h
->cupsBitsPerColor
= 16;
228 h
->cupsBitsPerPixel
= 48;
229 h
->cupsColorSpace
= CUPS_CSPACE_RGB
;
231 else if (!strcmp(type
, "sgray_1"))
233 h
->cupsBitsPerColor
= 1;
234 h
->cupsBitsPerPixel
= 1;
235 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
237 else if (!strcmp(type
, "sgray_8"))
239 h
->cupsBitsPerColor
= 8;
240 h
->cupsBitsPerPixel
= 8;
241 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
243 else if (!strcmp(type
, "sgray_16"))
245 h
->cupsBitsPerColor
= 16;
246 h
->cupsBitsPerPixel
= 16;
247 h
->cupsColorSpace
= CUPS_CSPACE_SW
;
249 else if (!strcmp(type
, "srgb_8"))
251 h
->cupsBitsPerColor
= 8;
252 h
->cupsBitsPerPixel
= 24;
253 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
255 else if (!strcmp(type
, "srgb_16"))
257 h
->cupsBitsPerColor
= 16;
258 h
->cupsBitsPerPixel
= 48;
259 h
->cupsColorSpace
= CUPS_CSPACE_SRGB
;
263 _cupsRasterAddError("Unsupported raster type \'%s\'.", type
);
267 h
->cupsColorOrder
= CUPS_ORDER_CHUNKED
;
268 h
->cupsNumColors
= h
->cupsBitsPerPixel
/ h
->cupsBitsPerColor
;
269 h
->cupsBytesPerLine
= (h
->cupsWidth
* h
->cupsBitsPerPixel
+ 7) / 8;
275 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 1;
276 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 1;
280 if (!strcmp(sides
, "two-sided-long-edge"))
284 else if (!strcmp(sides
, "two-sided-short-edge"))
289 else if (strcmp(sides
, "one-sided"))
291 _cupsRasterAddError("Unsupported sides value \'%s\'.", sides
);
297 if (!strcmp(sheet_back
, "flipped"))
300 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
302 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
304 else if (!strcmp(sheet_back
, "manual-tumble"))
308 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
309 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
312 else if (!strcmp(sheet_back
, "rotated"))
316 h
->cupsInteger
[CUPS_RASTER_PWG_CrossFeedTransform
] = 0xffffffffU
;
317 h
->cupsInteger
[CUPS_RASTER_PWG_FeedTransform
] = 0xffffffffU
;
320 else if (strcmp(sheet_back
, "normal"))
322 _cupsRasterAddError("Unsupported sheet_back value \'%s\'.", sheet_back
);
333 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
335 * This function associates a raster stream with the given file descriptor.
336 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
337 * image processor (RIP) filters that generate raster data, "fd" will be 1
340 * When writing raster data, the @code CUPS_RASTER_WRITE@,
341 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
342 * be used - compressed and PWG output is generally 25-50% smaller but adds a
343 * 100-300% execution time overhead.
346 cups_raster_t
* /* O - New stream */
347 cupsRasterOpen(int fd
, /* I - File descriptor */
348 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
349 @code CUPS_RASTER_WRITE@,
350 @code CUPS_RASTER_WRITE_COMPRESSED@,
351 or @code CUPS_RASTER_WRITE_PWG@ */
353 if (mode
== CUPS_RASTER_READ
)
354 return (cupsRasterOpenIO(cups_read_fd
, (void *)((intptr_t)fd
), mode
));
356 return (cupsRasterOpenIO(cups_write_fd
, (void *)((intptr_t)fd
), mode
));
361 * 'cupsRasterOpenIO()' - Open a raster stream using a callback function.
363 * This function associates a raster stream with the given callback function and
366 * When writing raster data, the @code CUPS_RASTER_WRITE@,
367 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
368 * be used - compressed and PWG output is generally 25-50% smaller but adds a
369 * 100-300% execution time overhead.
372 cups_raster_t
* /* O - New stream */
374 cups_raster_iocb_t iocb
, /* I - Read/write callback */
375 void *ctx
, /* I - Context pointer for callback */
376 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
377 @code CUPS_RASTER_WRITE@,
378 @code CUPS_RASTER_WRITE_COMPRESSED@,
379 or @code CUPS_RASTER_WRITE_PWG@ */
381 cups_raster_t
*r
; /* New stream */
384 _cupsRasterClearError();
386 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
388 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
397 if (mode
== CUPS_RASTER_READ
)
400 * Open for read - get sync word...
403 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) !=
406 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
412 if (r
->sync
!= CUPS_RASTER_SYNC
&&
413 r
->sync
!= CUPS_RASTER_REVSYNC
&&
414 r
->sync
!= CUPS_RASTER_SYNCv1
&&
415 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
416 r
->sync
!= CUPS_RASTER_SYNCv2
&&
417 r
->sync
!= CUPS_RASTER_REVSYNCv2
&&
418 r
->sync
!= CUPS_RASTER_SYNCapple
&&
419 r
->sync
!= CUPS_RASTER_REVSYNCapple
)
421 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
426 if (r
->sync
== CUPS_RASTER_SYNCv2
||
427 r
->sync
== CUPS_RASTER_REVSYNCv2
||
428 r
->sync
== CUPS_RASTER_SYNCapple
||
429 r
->sync
== CUPS_RASTER_REVSYNCapple
)
432 if (r
->sync
== CUPS_RASTER_REVSYNC
||
433 r
->sync
== CUPS_RASTER_REVSYNCv1
||
434 r
->sync
== CUPS_RASTER_REVSYNCv2
||
435 r
->sync
== CUPS_RASTER_REVSYNCapple
)
438 if (r
->sync
== CUPS_RASTER_SYNCapple
||
439 r
->sync
== CUPS_RASTER_REVSYNCapple
)
441 unsigned char header
[8]; /* File header */
443 if (cups_raster_io(r
, (unsigned char *)header
, sizeof(header
)) !=
446 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
454 DEBUG_printf(("1cupsRasterOpenIO: r->swapped=%d, r->sync=%08x\n", r
->swapped
, r
->sync
));
459 * Open for write - put sync word...
465 case CUPS_RASTER_WRITE
:
466 r
->sync
= CUPS_RASTER_SYNC
;
469 case CUPS_RASTER_WRITE_COMPRESSED
:
471 r
->sync
= CUPS_RASTER_SYNCv2
;
474 case CUPS_RASTER_WRITE_PWG
:
476 r
->sync
= htonl(CUPS_RASTER_SYNC_PWG
);
477 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNC_PWG
;
480 case CUPS_RASTER_WRITE_APPLE
:
482 r
->sync
= htonl(CUPS_RASTER_SYNCapple
);
483 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNCapple
;
484 r
->apple_page_count
= 0xffffffffU
;
488 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) < (ssize_t
)sizeof(r
->sync
))
490 _cupsRasterAddError("Unable to write raster stream header: %s\n",
502 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
503 * version 1 page header structure.
505 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
507 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
508 * of the version 2 page header data. This function handles reading version 2
509 * page headers and copying only the version 1 data into the provided buffer.
514 unsigned /* O - 1 on success, 0 on failure/end-of-file */
515 cupsRasterReadHeader(
516 cups_raster_t
*r
, /* I - Raster stream */
517 cups_page_header_t
*h
) /* I - Pointer to header data */
520 * Get the raster header...
523 if (!cups_raster_read_header(r
))
525 memset(h
, 0, sizeof(cups_page_header_t
));
530 * Copy the header to the user-supplied buffer...
533 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
540 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
541 * version 2 page header structure.
543 * @since CUPS 1.2/macOS 10.5@
546 unsigned /* O - 1 on success, 0 on failure/end-of-file */
547 cupsRasterReadHeader2(
548 cups_raster_t
*r
, /* I - Raster stream */
549 cups_page_header2_t
*h
) /* I - Pointer to header data */
552 * Get the raster header...
555 DEBUG_printf(("cupsRasterReadHeader2(r=%p, h=%p)", (void *)r
, (void *)h
));
557 if (!cups_raster_read_header(r
))
559 memset(h
, 0, sizeof(cups_page_header2_t
));
564 * Copy the header to the user-supplied buffer...
567 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
574 * 'cupsRasterReadPixels()' - Read raster pixels.
576 * For best performance, filters should read one or more whole lines.
577 * The "cupsBytesPerLine" value from the page header can be used to allocate
578 * the line buffer and as the number of bytes to read.
581 unsigned /* O - Number of bytes read */
582 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
583 unsigned char *p
, /* I - Pointer to pixel buffer */
584 unsigned len
) /* I - Number of bytes to read */
586 ssize_t bytes
; /* Bytes read */
587 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
588 unsigned remaining
; /* Bytes remaining */
589 unsigned char *ptr
, /* Pointer to read buffer */
590 byte
, /* Byte from file */
591 *temp
; /* Pointer into buffer */
592 unsigned count
; /* Repetition count */
595 DEBUG_printf(("cupsRasterReadPixels(r=%p, p=%p, len=%u)", (void *)r
, (void *)p
, len
));
597 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0 ||
598 r
->header
.cupsBytesPerLine
== 0)
600 DEBUG_puts("1cupsRasterReadPixels: Returning 0.");
604 DEBUG_printf(("1cupsRasterReadPixels: compressed=%d, remaining=%u", r
->compressed
, r
->remaining
));
609 * Read without compression...
612 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
614 if (cups_raster_io(r
, p
, len
) < (ssize_t
)len
)
616 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
621 * Swap bytes as needed...
625 (r
->header
.cupsBitsPerColor
== 16 ||
626 r
->header
.cupsBitsPerPixel
== 12 ||
627 r
->header
.cupsBitsPerPixel
== 16))
634 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
640 * Read compressed data...
644 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
646 while (remaining
> 0 && r
->remaining
> 0)
651 * Need to read a new row...
654 if (remaining
== cupsBytesPerLine
)
660 * Read using a modified PackBits compression...
663 if (!cups_raster_read(r
, &byte
, 1))
665 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
669 r
->count
= (unsigned)byte
+ 1;
675 bytes
= (ssize_t
)cupsBytesPerLine
;
680 * Get a new repeat count...
683 if (!cups_raster_read(r
, &byte
, 1))
685 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
692 * Clear to end of line...
695 switch (r
->header
.cupsColorSpace
)
698 case CUPS_CSPACE_RGB
:
699 case CUPS_CSPACE_SW
:
700 case CUPS_CSPACE_SRGB
:
701 case CUPS_CSPACE_RGBW
:
702 case CUPS_CSPACE_ADOBERGB
:
703 memset(temp
, 0xff, (size_t)bytes
);
706 memset(temp
, 0x00, (size_t)bytes
);
716 * Copy N literal pixels...
719 count
= (unsigned)(257 - byte
) * r
->bpp
;
721 if (count
> (unsigned)bytes
)
722 count
= (unsigned)bytes
;
724 if (!cups_raster_read(r
, temp
, count
))
726 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
731 bytes
-= (ssize_t
)count
;
736 * Repeat the next N bytes...
739 count
= ((unsigned)byte
+ 1) * r
->bpp
;
740 if (count
> (unsigned)bytes
)
741 count
= (unsigned)bytes
;
746 bytes
-= (ssize_t
)count
;
748 if (!cups_raster_read(r
, temp
, r
->bpp
))
750 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0.");
759 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
767 * Swap bytes as needed...
770 if ((r
->header
.cupsBitsPerColor
== 16 ||
771 r
->header
.cupsBitsPerPixel
== 12 ||
772 r
->header
.cupsBitsPerPixel
== 16) &&
774 cups_swap(ptr
, (size_t)bytes
);
780 if (remaining
>= cupsBytesPerLine
)
782 bytes
= (ssize_t
)cupsBytesPerLine
;
783 r
->pcurrent
= r
->pixels
;
789 bytes
= (ssize_t
)remaining
;
790 r
->pcurrent
= r
->pixels
+ bytes
;
794 * Copy data as needed...
798 memcpy(p
, ptr
, (size_t)bytes
);
803 * Copy fragment from buffer...
806 if ((unsigned)(bytes
= (int)(r
->pend
- r
->pcurrent
)) > remaining
)
807 bytes
= (ssize_t
)remaining
;
809 memcpy(p
, r
->pcurrent
, (size_t)bytes
);
810 r
->pcurrent
+= bytes
;
812 if (r
->pcurrent
>= r
->pend
)
814 r
->pcurrent
= r
->pixels
;
820 remaining
-= (unsigned)bytes
;
824 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len
));
831 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
834 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
839 unsigned /* O - 1 on success, 0 on failure */
840 cupsRasterWriteHeader(
841 cups_raster_t
*r
, /* I - Raster stream */
842 cups_page_header_t
*h
) /* I - Raster page header */
844 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
848 * Make a copy of the header, and compute the number of raster
849 * lines in the page image...
852 memset(&(r
->header
), 0, sizeof(r
->header
));
853 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
855 if (!cups_raster_update(r
))
859 * Write the raster header...
862 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
865 * PWG raster data is always network byte order with much of the page header
869 cups_page_header2_t fh
; /* File page header */
871 memset(&fh
, 0, sizeof(fh
));
873 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
875 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
876 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
877 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
878 /* PrintContentType */
880 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
881 fh
.Duplex
= htonl(r
->header
.Duplex
);
882 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
883 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
884 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
885 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
886 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
887 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
888 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
889 fh
.Jog
= htonl(r
->header
.Jog
);
890 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
891 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
892 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
893 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
894 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
895 fh
.Orientation
= htonl(r
->header
.Orientation
);
896 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
897 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
898 fh
.Tumble
= htonl(r
->header
.Tumble
);
899 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
900 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
901 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
902 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
903 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
904 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
905 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
906 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
907 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
909 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
910 /* CrossFeedTransform */
911 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
913 fh
.cupsInteger
[3] = htonl(r
->header
.cupsInteger
[3]);
915 fh
.cupsInteger
[4] = htonl(r
->header
.cupsInteger
[4]);
917 fh
.cupsInteger
[5] = htonl(r
->header
.cupsInteger
[5]);
919 fh
.cupsInteger
[6] = htonl(r
->header
.cupsInteger
[6]);
921 fh
.cupsInteger
[7] = htonl(r
->header
.cupsInteger
[7]);
923 fh
.cupsInteger
[8] = htonl(r
->header
.cupsInteger
[8]);
925 fh
.cupsInteger
[14] = htonl(r
->header
.cupsInteger
[14]);
926 /* VendorIdentifier */
927 fh
.cupsInteger
[15] = htonl(r
->header
.cupsInteger
[15]);
930 void *dst
= fh
.cupsReal
; /* Bypass bogus compiler warning */
931 void *src
= r
->header
.cupsReal
;
932 memcpy(dst
, src
, sizeof(fh
.cupsReal
) + sizeof(fh
.cupsString
));
935 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
936 sizeof(fh
.cupsRenderingIntent
));
937 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
938 sizeof(fh
.cupsPageSizeName
));
940 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
942 else if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
945 * Raw raster data is always network byte order with most of the page header
949 unsigned char appleheader
[32]; /* Raw page header */
951 if (r
->apple_page_count
== 0xffffffffU
)
954 * Write raw page count from raster page header...
957 r
->apple_page_count
= r
->header
.cupsInteger
[0];
959 appleheader
[0] = 'A';
960 appleheader
[1] = 'S';
961 appleheader
[2] = 'T';
963 appleheader
[4] = (unsigned char)(r
->apple_page_count
>> 24);
964 appleheader
[5] = (unsigned char)(r
->apple_page_count
>> 16);
965 appleheader
[6] = (unsigned char)(r
->apple_page_count
>> 8);
966 appleheader
[7] = (unsigned char)(r
->apple_page_count
);
968 if (cups_raster_io(r
, appleheader
, 8) != 8)
972 memset(appleheader
, 0, sizeof(appleheader
));
974 appleheader
[0] = (unsigned char)r
->header
.cupsBitsPerPixel
;
975 appleheader
[1] = r
->header
.cupsColorSpace
== CUPS_CSPACE_SRGB
? 1 :
976 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGBW
? 2 :
977 r
->header
.cupsColorSpace
== CUPS_CSPACE_ADOBERGB
? 3 :
978 r
->header
.cupsColorSpace
== CUPS_CSPACE_W
? 4 :
979 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGB
? 5 :
980 r
->header
.cupsColorSpace
== CUPS_CSPACE_CMYK
? 6 : 0;
981 appleheader
[12] = (unsigned char)(r
->header
.cupsWidth
>> 24);
982 appleheader
[13] = (unsigned char)(r
->header
.cupsWidth
>> 16);
983 appleheader
[14] = (unsigned char)(r
->header
.cupsWidth
>> 8);
984 appleheader
[15] = (unsigned char)(r
->header
.cupsWidth
);
985 appleheader
[16] = (unsigned char)(r
->header
.cupsHeight
>> 24);
986 appleheader
[17] = (unsigned char)(r
->header
.cupsHeight
>> 16);
987 appleheader
[18] = (unsigned char)(r
->header
.cupsHeight
>> 8);
988 appleheader
[19] = (unsigned char)(r
->header
.cupsHeight
);
989 appleheader
[20] = (unsigned char)(r
->header
.HWResolution
[0] >> 24);
990 appleheader
[21] = (unsigned char)(r
->header
.HWResolution
[0] >> 16);
991 appleheader
[22] = (unsigned char)(r
->header
.HWResolution
[0] >> 8);
992 appleheader
[23] = (unsigned char)(r
->header
.HWResolution
[0]);
994 return (cups_raster_io(r
, appleheader
, sizeof(appleheader
)) == sizeof(appleheader
));
997 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
998 == sizeof(r
->header
));
1003 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
1004 * page header structure.
1006 * The page header can be initialized using @link cupsRasterInitPWGHeader@.
1008 * @since CUPS 1.2/macOS 10.5@
1011 unsigned /* O - 1 on success, 0 on failure */
1012 cupsRasterWriteHeader2(
1013 cups_raster_t
*r
, /* I - Raster stream */
1014 cups_page_header2_t
*h
) /* I - Raster page header */
1016 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
1020 * Make a copy of the header, and compute the number of raster
1021 * lines in the page image...
1024 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
1026 if (!cups_raster_update(r
))
1029 if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
1031 r
->rowheight
= h
->HWResolution
[0] / h
->HWResolution
[1];
1033 if (h
->HWResolution
[0] != (r
->rowheight
* h
->HWResolution
[1]))
1040 * Write the raster header...
1043 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
1046 * PWG raster data is always network byte order with most of the page header
1050 cups_page_header2_t fh
; /* File page header */
1052 memset(&fh
, 0, sizeof(fh
));
1053 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
1054 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
1055 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
1056 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
1057 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
1058 sizeof(fh
.cupsRenderingIntent
));
1059 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
1060 sizeof(fh
.cupsPageSizeName
));
1062 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
1063 fh
.Duplex
= htonl(r
->header
.Duplex
);
1064 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
1065 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
1066 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
1067 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
1068 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
1069 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
1070 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
1071 fh
.Jog
= htonl(r
->header
.Jog
);
1072 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
1073 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
1074 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
1075 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
1076 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
1077 fh
.Orientation
= htonl(r
->header
.Orientation
);
1078 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
1079 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
1080 fh
.Tumble
= htonl(r
->header
.Tumble
);
1081 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
1082 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
1083 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
1084 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
1085 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
1086 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
1087 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
1088 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
1089 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
1090 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
1091 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
1092 fh
.cupsInteger
[3] = htonl((unsigned)(r
->header
.cupsImagingBBox
[0] * r
->header
.HWResolution
[0] / 72.0));
1093 fh
.cupsInteger
[4] = htonl((unsigned)(r
->header
.cupsImagingBBox
[1] * r
->header
.HWResolution
[1] / 72.0));
1094 fh
.cupsInteger
[5] = htonl((unsigned)(r
->header
.cupsImagingBBox
[2] * r
->header
.HWResolution
[0] / 72.0));
1095 fh
.cupsInteger
[6] = htonl((unsigned)(r
->header
.cupsImagingBBox
[3] * r
->header
.HWResolution
[1] / 72.0));
1096 fh
.cupsInteger
[7] = htonl(0xffffff);
1098 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
1100 else if (r
->mode
== CUPS_RASTER_WRITE_APPLE
)
1103 * Raw raster data is always network byte order with most of the page header
1107 unsigned char appleheader
[32]; /* Raw page header */
1108 unsigned height
= r
->header
.cupsHeight
* r
->rowheight
;
1109 /* Computed page height */
1111 if (r
->apple_page_count
== 0xffffffffU
)
1114 * Write raw page count from raster page header...
1117 r
->apple_page_count
= r
->header
.cupsInteger
[0];
1119 appleheader
[0] = 'A';
1120 appleheader
[1] = 'S';
1121 appleheader
[2] = 'T';
1123 appleheader
[4] = (unsigned char)(r
->apple_page_count
>> 24);
1124 appleheader
[5] = (unsigned char)(r
->apple_page_count
>> 16);
1125 appleheader
[6] = (unsigned char)(r
->apple_page_count
>> 8);
1126 appleheader
[7] = (unsigned char)(r
->apple_page_count
);
1128 if (cups_raster_io(r
, appleheader
, 8) != 8)
1132 memset(appleheader
, 0, sizeof(appleheader
));
1134 appleheader
[0] = (unsigned char)r
->header
.cupsBitsPerPixel
;
1135 appleheader
[1] = r
->header
.cupsColorSpace
== CUPS_CSPACE_SRGB
? 1 :
1136 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGBW
? 2 :
1137 r
->header
.cupsColorSpace
== CUPS_CSPACE_ADOBERGB
? 3 :
1138 r
->header
.cupsColorSpace
== CUPS_CSPACE_W
? 4 :
1139 r
->header
.cupsColorSpace
== CUPS_CSPACE_RGB
? 5 :
1140 r
->header
.cupsColorSpace
== CUPS_CSPACE_CMYK
? 6 : 0;
1141 appleheader
[12] = (unsigned char)(r
->header
.cupsWidth
>> 24);
1142 appleheader
[13] = (unsigned char)(r
->header
.cupsWidth
>> 16);
1143 appleheader
[14] = (unsigned char)(r
->header
.cupsWidth
>> 8);
1144 appleheader
[15] = (unsigned char)(r
->header
.cupsWidth
);
1145 appleheader
[16] = (unsigned char)(height
>> 24);
1146 appleheader
[17] = (unsigned char)(height
>> 16);
1147 appleheader
[18] = (unsigned char)(height
>> 8);
1148 appleheader
[19] = (unsigned char)(height
);
1149 appleheader
[20] = (unsigned char)(r
->header
.HWResolution
[0] >> 24);
1150 appleheader
[21] = (unsigned char)(r
->header
.HWResolution
[0] >> 16);
1151 appleheader
[22] = (unsigned char)(r
->header
.HWResolution
[0] >> 8);
1152 appleheader
[23] = (unsigned char)(r
->header
.HWResolution
[0]);
1154 return (cups_raster_io(r
, appleheader
, sizeof(appleheader
)) == sizeof(appleheader
));
1157 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
1158 == sizeof(r
->header
));
1163 * 'cupsRasterWritePixels()' - Write raster pixels.
1165 * For best performance, filters should write one or more whole lines.
1166 * The "cupsBytesPerLine" value from the page header can be used to allocate
1167 * the line buffer and as the number of bytes to write.
1170 unsigned /* O - Number of bytes written */
1171 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
1172 unsigned char *p
, /* I - Bytes to write */
1173 unsigned len
)/* I - Number of bytes to write */
1175 ssize_t bytes
; /* Bytes read */
1176 unsigned remaining
; /* Bytes remaining */
1179 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u", (void *)r
, (void *)p
, len
, r
->remaining
));
1181 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
|| r
->remaining
== 0)
1187 * Without compression, just write the raster data raw unless the data needs
1191 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
1194 (r
->header
.cupsBitsPerColor
== 16 ||
1195 r
->header
.cupsBitsPerPixel
== 12 ||
1196 r
->header
.cupsBitsPerPixel
== 16))
1198 unsigned char *bufptr
; /* Pointer into write buffer */
1199 unsigned count
; /* Remaining count */
1202 * Allocate a write buffer as needed...
1205 if ((size_t)len
> r
->bufsize
)
1208 bufptr
= realloc(r
->buffer
, len
);
1210 bufptr
= malloc(len
);
1220 * Byte swap the pixels...
1223 for (bufptr
= r
->buffer
, count
= len
; count
> 1; count
-= 2, bufptr
+= 2)
1229 if (count
) /* This should never happen... */
1233 * Write the byte-swapped buffer...
1236 bytes
= cups_raster_io(r
, r
->buffer
, len
);
1239 bytes
= cups_raster_io(r
, p
, len
);
1248 * Otherwise, compress each line...
1251 for (remaining
= len
; remaining
> 0; remaining
-= (unsigned)bytes
, p
+= bytes
)
1254 * Figure out the number of remaining bytes on the current line...
1257 if ((bytes
= (ssize_t
)remaining
) > (ssize_t
)(r
->pend
- r
->pcurrent
))
1258 bytes
= (ssize_t
)(r
->pend
- r
->pcurrent
);
1263 * Check to see if this line is the same as the previous line...
1266 if (memcmp(p
, r
->pcurrent
, (size_t)bytes
))
1268 if (cups_raster_write(r
, r
->pixels
) <= 0)
1276 * Mark more bytes as the same...
1279 r
->pcurrent
+= bytes
;
1281 if (r
->pcurrent
>= r
->pend
)
1284 * Increase the repeat count...
1287 r
->count
+= r
->rowheight
;
1288 r
->pcurrent
= r
->pixels
;
1291 * Flush out this line if it is the last one...
1296 if (r
->remaining
== 0)
1298 if (cups_raster_write(r
, r
->pixels
) <= 0)
1303 else if (r
->count
> (256 - r
->rowheight
))
1305 if (cups_raster_write(r
, r
->pixels
) <= 0)
1319 * Copy the raster data to the buffer...
1322 memcpy(r
->pcurrent
, p
, (size_t)bytes
);
1324 r
->pcurrent
+= bytes
;
1326 if (r
->pcurrent
>= r
->pend
)
1329 * Increase the repeat count...
1332 r
->count
+= r
->rowheight
;
1333 r
->pcurrent
= r
->pixels
;
1336 * Flush out this line if it is the last one...
1341 if (r
->remaining
== 0)
1343 if (cups_raster_write(r
, r
->pixels
) <= 0)
1355 * 'cups_raster_read_header()' - Read a raster page header.
1358 static unsigned /* O - 1 on success, 0 on fail */
1359 cups_raster_read_header(
1360 cups_raster_t
*r
) /* I - Raster stream */
1362 size_t len
; /* Length for read/swap */
1365 DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%d", (void *)r
, r
? r
->mode
: 0));
1367 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
1370 DEBUG_printf(("4cups_raster_read_header: r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1372 memset(&(r
->header
), 0, sizeof(r
->header
));
1375 * Read the header...
1382 * Get the length of the raster header...
1385 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
1386 len
= sizeof(cups_page_header_t
);
1388 len
= sizeof(cups_page_header2_t
);
1390 DEBUG_printf(("4cups_raster_read_header: len=%d", (int)len
));
1396 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < (ssize_t
)len
)
1398 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1403 * Swap bytes as needed...
1408 unsigned *s
, /* Current word */
1409 temp
; /* Temporary copy */
1412 DEBUG_puts("4cups_raster_read_header: Swapping header bytes.");
1414 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
1419 *s
= ((temp
& 0xff) << 24) |
1420 ((temp
& 0xff00) << 8) |
1421 ((temp
& 0xff0000) >> 8) |
1422 ((temp
& 0xff000000) >> 24);
1424 DEBUG_printf(("4cups_raster_read_header: %08x => %08x", temp
, *s
));
1429 case CUPS_RASTER_SYNCapple
:
1430 case CUPS_RASTER_REVSYNCapple
:
1432 unsigned char appleheader
[32]; /* Raw header */
1433 static const unsigned rawcspace
[] =
1438 CUPS_CSPACE_ADOBERGB
,
1443 static const unsigned rawnumcolors
[] =
1454 if (cups_raster_read(r
, appleheader
, sizeof(appleheader
)) < (ssize_t
)sizeof(appleheader
))
1456 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT
, CUPS_LLCAST r
->iocount
));
1460 strlcpy(r
->header
.MediaClass
, "PwgRaster", sizeof(r
->header
.MediaClass
));
1462 r
->header
.cupsBitsPerPixel
= appleheader
[0];
1463 r
->header
.cupsColorSpace
= appleheader
[1] >= (sizeof(rawcspace
) / sizeof(rawcspace
[0])) ? CUPS_CSPACE_DEVICE1
: rawcspace
[appleheader
[1]];
1464 r
->header
.cupsNumColors
= appleheader
[1] >= (sizeof(rawnumcolors
) / sizeof(rawnumcolors
[0])) ? 1 : rawnumcolors
[appleheader
[1]];
1465 r
->header
.cupsBitsPerColor
= r
->header
.cupsBitsPerPixel
/ r
->header
.cupsNumColors
;
1466 r
->header
.cupsWidth
= ((((((unsigned)appleheader
[12] << 8) | (unsigned)appleheader
[13]) << 8) | (unsigned)appleheader
[14]) << 8) | (unsigned)appleheader
[15];
1467 r
->header
.cupsHeight
= ((((((unsigned)appleheader
[16] << 8) | (unsigned)appleheader
[17]) << 8) | (unsigned)appleheader
[18]) << 8) | (unsigned)appleheader
[19];
1468 r
->header
.cupsBytesPerLine
= r
->header
.cupsWidth
* r
->header
.cupsBitsPerPixel
/ 8;
1469 r
->header
.cupsColorOrder
= CUPS_ORDER_CHUNKED
;
1470 r
->header
.HWResolution
[0] = r
->header
.HWResolution
[1] = ((((((unsigned)appleheader
[20] << 8) | (unsigned)appleheader
[21]) << 8) | (unsigned)appleheader
[22]) << 8) | (unsigned)appleheader
[23];
1472 if (r
->header
.HWResolution
[0] > 0)
1474 r
->header
.PageSize
[0] = (unsigned)(r
->header
.cupsWidth
* 72 / r
->header
.HWResolution
[0]);
1475 r
->header
.PageSize
[1] = (unsigned)(r
->header
.cupsHeight
* 72 / r
->header
.HWResolution
[1]);
1476 r
->header
.cupsPageSize
[0] = (float)(r
->header
.cupsWidth
* 72.0 / r
->header
.HWResolution
[0]);
1477 r
->header
.cupsPageSize
[1] = (float)(r
->header
.cupsHeight
* 72.0 / r
->header
.HWResolution
[1]);
1480 r
->header
.cupsInteger
[0] = r
->apple_page_count
;
1481 r
->header
.cupsInteger
[7] = 0xffffff;
1487 * Update the header and row count...
1490 if (!cups_raster_update(r
))
1493 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
));
1495 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);
1500 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
1503 static ssize_t
/* O - Bytes read/write or -1 */
1504 cups_raster_io(cups_raster_t
*r
, /* I - Raster stream */
1505 unsigned char *buf
, /* I - Buffer for read/write */
1506 size_t bytes
) /* I - Number of bytes to read/write */
1508 ssize_t count
, /* Number of bytes read/written */
1509 total
; /* Total bytes read/written */
1512 DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", (void *)r
, (void *)buf
, CUPS_LLCAST bytes
));
1514 for (total
= 0; total
< (ssize_t
)bytes
; total
+= count
, buf
+= count
)
1516 count
= (*r
->iocb
)(r
->ctx
, buf
, bytes
- (size_t)total
);
1518 DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count
, (int)total
));
1521 DEBUG_puts("6cups_raster_io: Returning 0.");
1526 DEBUG_puts("6cups_raster_io: Returning -1 on error.");
1531 r
->iocount
+= (size_t)count
;
1535 DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT
".", CUPS_LLCAST total
));
1542 * 'cups_raster_read()' - Read through the raster buffer.
1545 static ssize_t
/* O - Number of bytes read */
1546 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
1547 unsigned char *buf
, /* I - Buffer */
1548 size_t bytes
) /* I - Number of bytes to read */
1550 ssize_t count
, /* Number of bytes read */
1551 remaining
, /* Remaining bytes in buffer */
1552 total
; /* Total bytes read */
1555 DEBUG_printf(("5cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", (void *)r
, (void *)buf
, CUPS_LLCAST bytes
));
1558 return (cups_raster_io(r
, buf
, bytes
));
1561 * Allocate a read buffer as needed...
1564 count
= (ssize_t
)(2 * r
->header
.cupsBytesPerLine
);
1568 if ((size_t)count
> r
->bufsize
)
1570 ssize_t offset
= r
->bufptr
- r
->buffer
;
1571 /* Offset to current start of buffer */
1572 ssize_t end
= r
->bufend
- r
->buffer
;/* Offset to current end of buffer */
1573 unsigned char *rptr
; /* Pointer in read buffer */
1576 rptr
= realloc(r
->buffer
, (size_t)count
);
1578 rptr
= malloc((size_t)count
);
1584 r
->bufptr
= rptr
+ offset
;
1585 r
->bufend
= rptr
+ end
;
1586 r
->bufsize
= (size_t)count
;
1590 * Loop until we have read everything...
1593 for (total
= 0, remaining
= (int)(r
->bufend
- r
->bufptr
);
1594 total
< (ssize_t
)bytes
;
1595 total
+= count
, buf
+= count
)
1597 count
= (ssize_t
)bytes
- total
;
1599 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
));
1606 * Read into the raster buffer and then copy...
1609 remaining
= (*r
->iocb
)(r
->ctx
, r
->buffer
, r
->bufsize
);
1613 r
->bufptr
= r
->buffer
;
1614 r
->bufend
= r
->buffer
+ remaining
;
1617 r
->iocount
+= (size_t)remaining
;
1623 * Read directly into "buf"...
1626 count
= (*r
->iocb
)(r
->ctx
, buf
, (size_t)count
);
1632 r
->iocount
+= (size_t)count
;
1640 * Copy bytes from raster buffer to "buf"...
1643 if (count
> remaining
)
1652 *buf
= *(r
->bufptr
)++;
1655 else if (count
< 128)
1658 * Copy up to 127 bytes without using memcpy(); this is
1659 * faster because it avoids an extra function call and is
1660 * often further optimized by the compiler...
1663 unsigned char *bufptr
; /* Temporary buffer pointer */
1667 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
1675 * Use memcpy() for a large read...
1678 memcpy(buf
, r
->bufptr
, (size_t)count
);
1684 DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total
));
1691 * 'cups_raster_update()' - Update the raster header and row count for the
1695 static int /* O - 1 on success, 0 on failure */
1696 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
1698 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
1699 r
->header
.cupsNumColors
== 0)
1702 * Set the "cupsNumColors" field according to the colorspace...
1705 switch (r
->header
.cupsColorSpace
)
1707 case CUPS_CSPACE_W
:
1708 case CUPS_CSPACE_K
:
1709 case CUPS_CSPACE_WHITE
:
1710 case CUPS_CSPACE_GOLD
:
1711 case CUPS_CSPACE_SILVER
:
1712 case CUPS_CSPACE_SW
:
1713 r
->header
.cupsNumColors
= 1;
1716 case CUPS_CSPACE_RGB
:
1717 case CUPS_CSPACE_CMY
:
1718 case CUPS_CSPACE_YMC
:
1719 case CUPS_CSPACE_CIEXYZ
:
1720 case CUPS_CSPACE_CIELab
:
1721 case CUPS_CSPACE_SRGB
:
1722 case CUPS_CSPACE_ADOBERGB
:
1723 case CUPS_CSPACE_ICC1
:
1724 case CUPS_CSPACE_ICC2
:
1725 case CUPS_CSPACE_ICC3
:
1726 case CUPS_CSPACE_ICC4
:
1727 case CUPS_CSPACE_ICC5
:
1728 case CUPS_CSPACE_ICC6
:
1729 case CUPS_CSPACE_ICC7
:
1730 case CUPS_CSPACE_ICC8
:
1731 case CUPS_CSPACE_ICC9
:
1732 case CUPS_CSPACE_ICCA
:
1733 case CUPS_CSPACE_ICCB
:
1734 case CUPS_CSPACE_ICCC
:
1735 case CUPS_CSPACE_ICCD
:
1736 case CUPS_CSPACE_ICCE
:
1737 case CUPS_CSPACE_ICCF
:
1738 r
->header
.cupsNumColors
= 3;
1741 case CUPS_CSPACE_RGBA
:
1742 case CUPS_CSPACE_RGBW
:
1743 case CUPS_CSPACE_CMYK
:
1744 case CUPS_CSPACE_YMCK
:
1745 case CUPS_CSPACE_KCMY
:
1746 case CUPS_CSPACE_GMCK
:
1747 case CUPS_CSPACE_GMCS
:
1748 r
->header
.cupsNumColors
= 4;
1751 case CUPS_CSPACE_KCMYcm
:
1752 if (r
->header
.cupsBitsPerPixel
< 8)
1753 r
->header
.cupsNumColors
= 6;
1755 r
->header
.cupsNumColors
= 4;
1758 case CUPS_CSPACE_DEVICE1
:
1759 case CUPS_CSPACE_DEVICE2
:
1760 case CUPS_CSPACE_DEVICE3
:
1761 case CUPS_CSPACE_DEVICE4
:
1762 case CUPS_CSPACE_DEVICE5
:
1763 case CUPS_CSPACE_DEVICE6
:
1764 case CUPS_CSPACE_DEVICE7
:
1765 case CUPS_CSPACE_DEVICE8
:
1766 case CUPS_CSPACE_DEVICE9
:
1767 case CUPS_CSPACE_DEVICEA
:
1768 case CUPS_CSPACE_DEVICEB
:
1769 case CUPS_CSPACE_DEVICEC
:
1770 case CUPS_CSPACE_DEVICED
:
1771 case CUPS_CSPACE_DEVICEE
:
1772 case CUPS_CSPACE_DEVICEF
:
1773 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
1774 CUPS_CSPACE_DEVICE1
+ 1;
1778 /* Unknown color space */
1784 * Set the number of bytes per pixel/color...
1787 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
1788 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
1790 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
1796 * Set the number of remaining rows...
1799 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
1800 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
1802 r
->remaining
= r
->header
.cupsHeight
;
1805 * Allocate the compression buffer...
1810 if (r
->pixels
!= NULL
)
1813 if ((r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1)) == NULL
)
1822 r
->pcurrent
= r
->pixels
;
1823 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
1832 * 'cups_raster_write()' - Write a row of compressed raster data...
1835 static ssize_t
/* O - Number of bytes written */
1837 cups_raster_t
*r
, /* I - Raster stream */
1838 const unsigned char *pixels
) /* I - Pixel data to write */
1840 const unsigned char *start
, /* Start of sequence */
1841 *ptr
, /* Current pointer in sequence */
1842 *pend
, /* End of raster buffer */
1843 *plast
; /* Pointer to last pixel */
1844 unsigned char *wptr
; /* Pointer into write buffer */
1845 unsigned bpp
, /* Bytes per pixel */
1849 DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r
, (void *)pixels
));
1852 * Allocate a write buffer as needed...
1855 count
= r
->header
.cupsBytesPerLine
* 2;
1859 if ((size_t)count
> r
->bufsize
)
1862 wptr
= realloc(r
->buffer
, count
);
1864 wptr
= malloc(count
);
1868 DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT
" bytes for raster buffer: %s", CUPS_LLCAST count
, strerror(errno
)));
1877 * Write the row repeat count...
1881 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1884 *wptr
++ = (unsigned char)(r
->count
- 1);
1887 * Write using a modified PackBits compression...
1890 for (ptr
= pixels
; ptr
< pend
;)
1898 * Encode a single pixel at the end...
1902 for (count
= bpp
; count
> 0; count
--)
1905 else if (!memcmp(start
, ptr
, bpp
))
1908 * Encode a sequence of repeating pixels...
1911 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1912 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1915 *wptr
++ = (unsigned char)(count
- 1);
1916 for (count
= bpp
; count
> 0; count
--)
1922 * Encode a sequence of non-repeating pixels...
1925 for (count
= 1; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1926 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1929 if (ptr
>= plast
&& count
< 128)
1935 *wptr
++ = (unsigned char)(257 - count
);
1938 memcpy(wptr
, start
, count
);
1943 DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT
" bytes.", CUPS_LLCAST (wptr
- r
->buffer
)));
1945 return (cups_raster_io(r
, r
->buffer
, (size_t)(wptr
- r
->buffer
)));
1950 * 'cups_read_fd()' - Read bytes from a file.
1953 static ssize_t
/* O - Bytes read or -1 */
1954 cups_read_fd(void *ctx
, /* I - File descriptor as pointer */
1955 unsigned char *buf
, /* I - Buffer for read */
1956 size_t bytes
) /* I - Maximum number of bytes to read */
1958 int fd
= (int)((intptr_t)ctx
);
1959 /* File descriptor */
1960 ssize_t count
; /* Number of bytes read */
1963 #ifdef WIN32 /* Sigh */
1964 while ((count
= read(fd
, buf
, (unsigned)bytes
)) < 0)
1966 while ((count
= read(fd
, buf
, bytes
)) < 0)
1968 if (errno
!= EINTR
&& errno
!= EAGAIN
)
1970 DEBUG_printf(("4cups_read_fd: %s", strerror(errno
)));
1974 DEBUG_printf(("4cups_read_fd: Returning %d bytes.", (int)count
));
1981 * 'cups_swap()' - Swap bytes in raster data...
1985 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1986 size_t bytes
) /* I - Number of bytes to swap */
1988 unsigned char even
, odd
; /* Temporary variables */
2007 * 'cups_write_fd()' - Write bytes to a file.
2010 static ssize_t
/* O - Bytes written or -1 */
2011 cups_write_fd(void *ctx
, /* I - File descriptor pointer */
2012 unsigned char *buf
, /* I - Bytes to write */
2013 size_t bytes
) /* I - Number of bytes to write */
2015 int fd
= (int)((intptr_t)ctx
);
2016 /* File descriptor */
2017 ssize_t count
; /* Number of bytes written */
2020 #ifdef WIN32 /* Sigh */
2021 while ((count
= write(fd
, buf
, (unsigned)bytes
)) < 0)
2023 while ((count
= write(fd
, buf
, bytes
)) < 0)
2025 if (errno
!= EINTR
&& errno
!= EAGAIN
)
2027 DEBUG_printf(("4cups_write_fd: %s", strerror(errno
)));