4 * Raster file routines for CUPS.
6 * Copyright 2007-2015 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
9 * This file is part of the CUPS Imaging library.
11 * These coded instructions, statements, and computer programs are the
12 * property of Apple Inc. and are protected by Federal copyright
13 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
14 * which should have been included with this file. If this file is
15 * file is missing or damaged, see the license at "http://www.cups.org/".
17 * This file is subject to the Apple OS-Developed Software exception.
21 * Include necessary headers...
24 #include <cups/raster-private.h>
27 #endif /* HAVE_STDINT_H */
31 * Private structures...
34 struct _cups_raster_s
/**** Raster stream data ****/
36 unsigned sync
; /* Sync word from start of stream */
37 void *ctx
; /* File descriptor */
38 cups_raster_iocb_t iocb
; /* IO callback */
39 cups_mode_t mode
; /* Read/write mode */
40 cups_page_header2_t header
; /* Raster header for current page */
41 unsigned count
, /* Current row run-length count */
42 remaining
, /* Remaining rows in page image */
43 bpp
; /* Bytes per pixel/color */
44 unsigned char *pixels
, /* Pixels for current row */
45 *pend
, /* End of pixel buffer */
46 *pcurrent
; /* Current byte in pixel buffer */
47 int compressed
, /* Non-zero if data is compressed */
48 swapped
; /* Non-zero if data is byte-swapped */
49 unsigned char *buffer
, /* Read/write buffer */
50 *bufptr
, /* Current (read) position in buffer */
51 *bufend
; /* End of current (read) buffer */
52 size_t bufsize
; /* Buffer size */
60 static ssize_t
cups_raster_io(cups_raster_t
*r
, unsigned char *buf
, size_t bytes
);
61 static unsigned cups_raster_read_header(cups_raster_t
*r
);
62 static ssize_t
cups_raster_read(cups_raster_t
*r
, unsigned char *buf
,
64 static void cups_raster_update(cups_raster_t
*r
);
65 static ssize_t
cups_raster_write(cups_raster_t
*r
,
66 const unsigned char *pixels
);
67 static ssize_t
cups_read_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
68 static void cups_swap(unsigned char *buf
, size_t bytes
);
69 static ssize_t
cups_write_fd(void *ctx
, unsigned char *buf
, size_t bytes
);
73 * 'cupsRasterClose()' - Close a raster stream.
75 * The file descriptor associated with the raster stream must be closed
76 * separately as needed.
80 cupsRasterClose(cups_raster_t
*r
) /* I - Stream to close */
96 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
98 * This function associates a raster stream with the given file descriptor.
99 * For most printer driver filters, "fd" will be 0 (stdin). For most raster
100 * image processor (RIP) filters that generate raster data, "fd" will be 1
103 * When writing raster data, the @code CUPS_RASTER_WRITE@,
104 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
105 * be used - compressed and PWG output is generally 25-50% smaller but adds a
106 * 100-300% execution time overhead.
109 cups_raster_t
* /* O - New stream */
110 cupsRasterOpen(int fd
, /* I - File descriptor */
111 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
112 @code CUPS_RASTER_WRITE@,
113 @code CUPS_RASTER_WRITE_COMPRESSED@,
114 or @code CUPS_RASTER_WRITE_PWG@ */
116 if (mode
== CUPS_RASTER_READ
)
117 return (cupsRasterOpenIO(cups_read_fd
, (void *)((intptr_t)fd
), mode
));
119 return (cupsRasterOpenIO(cups_write_fd
, (void *)((intptr_t)fd
), mode
));
124 * 'cupsRasterOpenIO()' - Open a raster stream using a callback function.
126 * This function associates a raster stream with the given callback function and
129 * When writing raster data, the @code CUPS_RASTER_WRITE@,
130 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can
131 * be used - compressed and PWG output is generally 25-50% smaller but adds a
132 * 100-300% execution time overhead.
135 cups_raster_t
* /* O - New stream */
137 cups_raster_iocb_t iocb
, /* I - Read/write callback */
138 void *ctx
, /* I - Context pointer for callback */
139 cups_mode_t mode
) /* I - Mode - @code CUPS_RASTER_READ@,
140 @code CUPS_RASTER_WRITE@,
141 @code CUPS_RASTER_WRITE_COMPRESSED@,
142 or @code CUPS_RASTER_WRITE_PWG@ */
144 cups_raster_t
*r
; /* New stream */
147 _cupsRasterClearError();
149 if ((r
= calloc(sizeof(cups_raster_t
), 1)) == NULL
)
151 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
160 if (mode
== CUPS_RASTER_READ
)
163 * Open for read - get sync word...
166 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) !=
169 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
175 if (r
->sync
!= CUPS_RASTER_SYNC
&&
176 r
->sync
!= CUPS_RASTER_REVSYNC
&&
177 r
->sync
!= CUPS_RASTER_SYNCv1
&&
178 r
->sync
!= CUPS_RASTER_REVSYNCv1
&&
179 r
->sync
!= CUPS_RASTER_SYNCv2
&&
180 r
->sync
!= CUPS_RASTER_REVSYNCv2
)
182 _cupsRasterAddError("Unknown raster format %08x!\n", r
->sync
);
187 if (r
->sync
== CUPS_RASTER_SYNCv2
||
188 r
->sync
== CUPS_RASTER_REVSYNCv2
)
191 if (r
->sync
== CUPS_RASTER_REVSYNC
||
192 r
->sync
== CUPS_RASTER_REVSYNCv1
||
193 r
->sync
== CUPS_RASTER_REVSYNCv2
)
196 DEBUG_printf(("r->swapped=%d, r->sync=%08x\n", r
->swapped
, r
->sync
));
201 * Open for write - put sync word...
207 case CUPS_RASTER_WRITE
:
208 r
->sync
= CUPS_RASTER_SYNC
;
211 case CUPS_RASTER_WRITE_COMPRESSED
:
213 r
->sync
= CUPS_RASTER_SYNCv2
;
216 case CUPS_RASTER_WRITE_PWG
:
218 r
->sync
= htonl(CUPS_RASTER_SYNC_PWG
);
219 r
->swapped
= r
->sync
!= CUPS_RASTER_SYNC_PWG
;
223 if (cups_raster_io(r
, (unsigned char *)&(r
->sync
), sizeof(r
->sync
)) < (ssize_t
)sizeof(r
->sync
))
225 _cupsRasterAddError("Unable to write raster stream header: %s\n",
237 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
238 * version 1 page header structure.
240 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
242 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset
243 * of the version 2 page header data. This function handles reading version 2
244 * page headers and copying only the version 1 data into the provided buffer.
249 unsigned /* O - 1 on success, 0 on failure/end-of-file */
250 cupsRasterReadHeader(
251 cups_raster_t
*r
, /* I - Raster stream */
252 cups_page_header_t
*h
) /* I - Pointer to header data */
255 * Get the raster header...
258 if (!cups_raster_read_header(r
))
260 memset(h
, 0, sizeof(cups_page_header_t
));
265 * Copy the header to the user-supplied buffer...
268 memcpy(h
, &(r
->header
), sizeof(cups_page_header_t
));
275 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
276 * version 2 page header structure.
278 * @since CUPS 1.2/OS X 10.5@
281 unsigned /* O - 1 on success, 0 on failure/end-of-file */
282 cupsRasterReadHeader2(
283 cups_raster_t
*r
, /* I - Raster stream */
284 cups_page_header2_t
*h
) /* I - Pointer to header data */
287 * Get the raster header...
290 if (!cups_raster_read_header(r
))
292 memset(h
, 0, sizeof(cups_page_header2_t
));
297 * Copy the header to the user-supplied buffer...
300 memcpy(h
, &(r
->header
), sizeof(cups_page_header2_t
));
307 * 'cupsRasterReadPixels()' - Read raster pixels.
309 * For best performance, filters should read one or more whole lines.
310 * The "cupsBytesPerLine" value from the page header can be used to allocate
311 * the line buffer and as the number of bytes to read.
314 unsigned /* O - Number of bytes read */
315 cupsRasterReadPixels(cups_raster_t
*r
, /* I - Raster stream */
316 unsigned char *p
, /* I - Pointer to pixel buffer */
317 unsigned len
) /* I - Number of bytes to read */
319 ssize_t bytes
; /* Bytes read */
320 unsigned cupsBytesPerLine
; /* cupsBytesPerLine value */
321 unsigned remaining
; /* Bytes remaining */
322 unsigned char *ptr
, /* Pointer to read buffer */
323 byte
, /* Byte from file */
324 *temp
; /* Pointer into buffer */
325 unsigned count
; /* Repetition count */
328 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
|| r
->remaining
== 0 ||
329 r
->header
.cupsBytesPerLine
== 0)
335 * Read without compression...
338 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
340 if (cups_raster_io(r
, p
, len
) < (ssize_t
)len
)
344 * Swap bytes as needed...
348 (r
->header
.cupsBitsPerColor
== 16 ||
349 r
->header
.cupsBitsPerPixel
== 12 ||
350 r
->header
.cupsBitsPerPixel
== 16))
361 * Read compressed data...
365 cupsBytesPerLine
= r
->header
.cupsBytesPerLine
;
367 while (remaining
> 0 && r
->remaining
> 0)
372 * Need to read a new row...
375 if (remaining
== cupsBytesPerLine
)
381 * Read using a modified PackBits compression...
384 if (!cups_raster_read(r
, &byte
, 1))
387 r
->count
= (unsigned)byte
+ 1;
393 bytes
= (ssize_t
)cupsBytesPerLine
;
398 * Get a new repeat count...
401 if (!cups_raster_read(r
, &byte
, 1))
407 * Copy N literal pixels...
410 count
= (unsigned)(257 - byte
) * r
->bpp
;
412 if (count
> (unsigned)bytes
)
413 count
= (unsigned)bytes
;
415 if (!cups_raster_read(r
, temp
, count
))
424 * Repeat the next N bytes...
427 count
= ((unsigned)byte
+ 1) * r
->bpp
;
428 if (count
> (unsigned)bytes
)
429 count
= (unsigned)bytes
;
436 if (!cups_raster_read(r
, temp
, r
->bpp
))
444 memcpy(temp
, temp
- r
->bpp
, r
->bpp
);
452 * Swap bytes as needed...
455 if ((r
->header
.cupsBitsPerColor
== 16 ||
456 r
->header
.cupsBitsPerPixel
== 12 ||
457 r
->header
.cupsBitsPerPixel
== 16) &&
459 cups_swap(ptr
, (size_t)bytes
);
465 if (remaining
>= cupsBytesPerLine
)
467 bytes
= (ssize_t
)cupsBytesPerLine
;
468 r
->pcurrent
= r
->pixels
;
474 bytes
= (ssize_t
)remaining
;
475 r
->pcurrent
= r
->pixels
+ bytes
;
479 * Copy data as needed...
483 memcpy(p
, ptr
, (size_t)bytes
);
488 * Copy fragment from buffer...
491 if ((unsigned)(bytes
= (int)(r
->pend
- r
->pcurrent
)) > remaining
)
492 bytes
= (ssize_t
)remaining
;
494 memcpy(p
, r
->pcurrent
, (size_t)bytes
);
495 r
->pcurrent
+= bytes
;
497 if (r
->pcurrent
>= r
->pend
)
499 r
->pcurrent
= r
->pixels
;
505 remaining
-= (unsigned)bytes
;
514 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
517 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
522 unsigned /* O - 1 on success, 0 on failure */
523 cupsRasterWriteHeader(
524 cups_raster_t
*r
, /* I - Raster stream */
525 cups_page_header_t
*h
) /* I - Raster page header */
527 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
531 * Make a copy of the header, and compute the number of raster
532 * lines in the page image...
535 memset(&(r
->header
), 0, sizeof(r
->header
));
536 memcpy(&(r
->header
), h
, sizeof(cups_page_header_t
));
538 cups_raster_update(r
);
541 * Write the raster header...
544 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
547 * PWG raster data is always network byte order with much of the page header
551 cups_page_header2_t fh
; /* File page header */
553 memset(&fh
, 0, sizeof(fh
));
555 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
557 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
558 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
559 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
560 /* PrintContentType */
562 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
563 fh
.Duplex
= htonl(r
->header
.Duplex
);
564 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
565 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
566 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
567 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
568 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
569 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
570 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
571 fh
.Jog
= htonl(r
->header
.Jog
);
572 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
573 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
574 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
575 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
576 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
577 fh
.Orientation
= htonl(r
->header
.Orientation
);
578 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
579 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
580 fh
.Tumble
= htonl(r
->header
.Tumble
);
581 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
582 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
583 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
584 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
585 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
586 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
587 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
588 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
589 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
591 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
592 /* CrossFeedTransform */
593 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
595 fh
.cupsInteger
[3] = htonl(r
->header
.cupsInteger
[3]);
597 fh
.cupsInteger
[4] = htonl(r
->header
.cupsInteger
[4]);
599 fh
.cupsInteger
[5] = htonl(r
->header
.cupsInteger
[5]);
601 fh
.cupsInteger
[6] = htonl(r
->header
.cupsInteger
[6]);
603 fh
.cupsInteger
[7] = htonl(r
->header
.cupsInteger
[7]);
605 fh
.cupsInteger
[8] = htonl(r
->header
.cupsInteger
[8]);
607 fh
.cupsInteger
[14] = htonl(r
->header
.cupsInteger
[14]);
608 /* VendorIdentifier */
609 fh
.cupsInteger
[15] = htonl(r
->header
.cupsInteger
[15]);
612 void *dst
= fh
.cupsReal
; /* Bypass bogus compiler warning */
613 void *src
= r
->header
.cupsReal
;
614 memcpy(dst
, src
, sizeof(fh
.cupsReal
) + sizeof(fh
.cupsString
));
617 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
618 sizeof(fh
.cupsRenderingIntent
));
619 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
620 sizeof(fh
.cupsPageSizeName
));
622 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
625 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
626 == sizeof(r
->header
));
631 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2
632 * page header structure.
634 * The page header can be initialized using @link cupsRasterInterpretPPD@.
636 * @since CUPS 1.2/OS X 10.5@
639 unsigned /* O - 1 on success, 0 on failure */
640 cupsRasterWriteHeader2(
641 cups_raster_t
*r
, /* I - Raster stream */
642 cups_page_header2_t
*h
) /* I - Raster page header */
644 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
)
648 * Make a copy of the header, and compute the number of raster
649 * lines in the page image...
652 memcpy(&(r
->header
), h
, sizeof(cups_page_header2_t
));
654 cups_raster_update(r
);
657 * Write the raster header...
660 if (r
->mode
== CUPS_RASTER_WRITE_PWG
)
663 * PWG raster data is always network byte order with most of the page header
667 cups_page_header2_t fh
; /* File page header */
669 memset(&fh
, 0, sizeof(fh
));
670 strlcpy(fh
.MediaClass
, "PwgRaster", sizeof(fh
.MediaClass
));
671 strlcpy(fh
.MediaColor
, r
->header
.MediaColor
, sizeof(fh
.MediaColor
));
672 strlcpy(fh
.MediaType
, r
->header
.MediaType
, sizeof(fh
.MediaType
));
673 strlcpy(fh
.OutputType
, r
->header
.OutputType
, sizeof(fh
.OutputType
));
674 strlcpy(fh
.cupsRenderingIntent
, r
->header
.cupsRenderingIntent
,
675 sizeof(fh
.cupsRenderingIntent
));
676 strlcpy(fh
.cupsPageSizeName
, r
->header
.cupsPageSizeName
,
677 sizeof(fh
.cupsPageSizeName
));
679 fh
.CutMedia
= htonl(r
->header
.CutMedia
);
680 fh
.Duplex
= htonl(r
->header
.Duplex
);
681 fh
.HWResolution
[0] = htonl(r
->header
.HWResolution
[0]);
682 fh
.HWResolution
[1] = htonl(r
->header
.HWResolution
[1]);
683 fh
.ImagingBoundingBox
[0] = htonl(r
->header
.ImagingBoundingBox
[0]);
684 fh
.ImagingBoundingBox
[1] = htonl(r
->header
.ImagingBoundingBox
[1]);
685 fh
.ImagingBoundingBox
[2] = htonl(r
->header
.ImagingBoundingBox
[2]);
686 fh
.ImagingBoundingBox
[3] = htonl(r
->header
.ImagingBoundingBox
[3]);
687 fh
.InsertSheet
= htonl(r
->header
.InsertSheet
);
688 fh
.Jog
= htonl(r
->header
.Jog
);
689 fh
.LeadingEdge
= htonl(r
->header
.LeadingEdge
);
690 fh
.ManualFeed
= htonl(r
->header
.ManualFeed
);
691 fh
.MediaPosition
= htonl(r
->header
.MediaPosition
);
692 fh
.MediaWeight
= htonl(r
->header
.MediaWeight
);
693 fh
.NumCopies
= htonl(r
->header
.NumCopies
);
694 fh
.Orientation
= htonl(r
->header
.Orientation
);
695 fh
.PageSize
[0] = htonl(r
->header
.PageSize
[0]);
696 fh
.PageSize
[1] = htonl(r
->header
.PageSize
[1]);
697 fh
.Tumble
= htonl(r
->header
.Tumble
);
698 fh
.cupsWidth
= htonl(r
->header
.cupsWidth
);
699 fh
.cupsHeight
= htonl(r
->header
.cupsHeight
);
700 fh
.cupsBitsPerColor
= htonl(r
->header
.cupsBitsPerColor
);
701 fh
.cupsBitsPerPixel
= htonl(r
->header
.cupsBitsPerPixel
);
702 fh
.cupsBytesPerLine
= htonl(r
->header
.cupsBytesPerLine
);
703 fh
.cupsColorOrder
= htonl(r
->header
.cupsColorOrder
);
704 fh
.cupsColorSpace
= htonl(r
->header
.cupsColorSpace
);
705 fh
.cupsNumColors
= htonl(r
->header
.cupsNumColors
);
706 fh
.cupsInteger
[0] = htonl(r
->header
.cupsInteger
[0]);
707 fh
.cupsInteger
[1] = htonl(r
->header
.cupsInteger
[1]);
708 fh
.cupsInteger
[2] = htonl(r
->header
.cupsInteger
[2]);
709 fh
.cupsInteger
[3] = htonl((unsigned)(r
->header
.cupsImagingBBox
[0] *
710 r
->header
.HWResolution
[0]));
711 fh
.cupsInteger
[4] = htonl((unsigned)(r
->header
.cupsImagingBBox
[1] *
712 r
->header
.HWResolution
[1]));
713 fh
.cupsInteger
[5] = htonl((unsigned)(r
->header
.cupsImagingBBox
[2] *
714 r
->header
.HWResolution
[0]));
715 fh
.cupsInteger
[6] = htonl((unsigned)(r
->header
.cupsImagingBBox
[3] *
716 r
->header
.HWResolution
[1]));
717 fh
.cupsInteger
[7] = htonl(0xffffff);
719 return (cups_raster_io(r
, (unsigned char *)&fh
, sizeof(fh
)) == sizeof(fh
));
722 return (cups_raster_io(r
, (unsigned char *)&(r
->header
), sizeof(r
->header
))
723 == sizeof(r
->header
));
728 * 'cupsRasterWritePixels()' - Write raster pixels.
730 * For best performance, filters should write one or more whole lines.
731 * The "cupsBytesPerLine" value from the page header can be used to allocate
732 * the line buffer and as the number of bytes to write.
735 unsigned /* O - Number of bytes written */
736 cupsRasterWritePixels(cups_raster_t
*r
, /* I - Raster stream */
737 unsigned char *p
, /* I - Bytes to write */
738 unsigned len
)/* I - Number of bytes to write */
740 ssize_t bytes
; /* Bytes read */
741 unsigned remaining
; /* Bytes remaining */
744 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
745 r
, p
, len
, r
->remaining
));
747 if (r
== NULL
|| r
->mode
== CUPS_RASTER_READ
|| r
->remaining
== 0)
753 * Without compression, just write the raster data raw unless the data needs
757 r
->remaining
-= len
/ r
->header
.cupsBytesPerLine
;
760 (r
->header
.cupsBitsPerColor
== 16 ||
761 r
->header
.cupsBitsPerPixel
== 12 ||
762 r
->header
.cupsBitsPerPixel
== 16))
764 unsigned char *bufptr
; /* Pointer into write buffer */
765 unsigned count
; /* Remaining count */
768 * Allocate a write buffer as needed...
771 if ((size_t)len
> r
->bufsize
)
774 bufptr
= realloc(r
->buffer
, len
);
776 bufptr
= malloc(len
);
786 * Byte swap the pixels...
789 for (bufptr
= r
->buffer
, count
= len
; count
> 1; count
-= 2, bufptr
+= 2)
795 if (count
) /* This should never happen... */
799 * Write the byte-swapped buffer...
802 return ((unsigned)cups_raster_io(r
, r
->buffer
, len
));
805 return ((unsigned)cups_raster_io(r
, p
, len
));
809 * Otherwise, compress each line...
812 for (remaining
= len
; remaining
> 0; remaining
-= (unsigned)bytes
, p
+= bytes
)
815 * Figure out the number of remaining bytes on the current line...
818 if ((bytes
= (ssize_t
)remaining
) > (ssize_t
)(r
->pend
- r
->pcurrent
))
819 bytes
= (ssize_t
)(r
->pend
- r
->pcurrent
);
824 * Check to see if this line is the same as the previous line...
827 if (memcmp(p
, r
->pcurrent
, (size_t)bytes
))
829 if (!cups_raster_write(r
, r
->pixels
))
837 * Mark more bytes as the same...
840 r
->pcurrent
+= bytes
;
842 if (r
->pcurrent
>= r
->pend
)
845 * Increase the repeat count...
849 r
->pcurrent
= r
->pixels
;
852 * Flush out this line if it is the last one...
857 if (r
->remaining
== 0)
858 return ((unsigned)cups_raster_write(r
, r
->pixels
));
859 else if (r
->count
== 256)
861 if (cups_raster_write(r
, r
->pixels
) == 0)
875 * Copy the raster data to the buffer...
878 memcpy(r
->pcurrent
, p
, (size_t)bytes
);
880 r
->pcurrent
+= bytes
;
882 if (r
->pcurrent
>= r
->pend
)
885 * Increase the repeat count...
889 r
->pcurrent
= r
->pixels
;
892 * Flush out this line if it is the last one...
897 if (r
->remaining
== 0)
898 return ((unsigned)cups_raster_write(r
, r
->pixels
));
908 * 'cups_raster_read_header()' - Read a raster page header.
911 static unsigned /* O - 1 on success, 0 on fail */
912 cups_raster_read_header(
913 cups_raster_t
*r
) /* I - Raster stream */
915 size_t len
; /* Length for read/swap */
918 if (r
== NULL
|| r
->mode
!= CUPS_RASTER_READ
)
922 * Get the length of the raster header...
925 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
)
926 len
= sizeof(cups_page_header_t
);
928 len
= sizeof(cups_page_header2_t
);
934 memset(&(r
->header
), 0, sizeof(r
->header
));
936 if (cups_raster_read(r
, (unsigned char *)&(r
->header
), len
) < (ssize_t
)len
)
940 * Swap bytes as needed...
945 unsigned *s
, /* Current word */
946 temp
; /* Temporary copy */
949 DEBUG_puts("Swapping header bytes...");
951 for (len
= 81, s
= &(r
->header
.AdvanceDistance
);
955 DEBUG_printf(("%08x =>", *s
));
958 *s
= ((temp
& 0xff) << 24) |
959 ((temp
& 0xff00) << 8) |
960 ((temp
& 0xff0000) >> 8) |
961 ((temp
& 0xff000000) >> 24);
963 DEBUG_printf((" %08x\n", *s
));
968 * Update the header and row count...
971 cups_raster_update(r
);
973 return (r
->header
.cupsBytesPerLine
!= 0 && r
->header
.cupsHeight
!= 0 && (r
->header
.cupsBytesPerLine
% r
->bpp
) == 0);
978 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
981 static ssize_t
/* O - Bytes read/write or -1 */
982 cups_raster_io(cups_raster_t
*r
, /* I - Raster stream */
983 unsigned char *buf
, /* I - Buffer for read/write */
984 size_t bytes
) /* I - Number of bytes to read/write */
986 ssize_t count
, /* Number of bytes read/written */
987 total
; /* Total bytes read/written */
990 DEBUG_printf(("4cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT
")", r
, buf
, CUPS_LLCAST bytes
));
992 for (total
= 0; total
< (ssize_t
)bytes
; total
+= count
, buf
+= count
)
994 count
= (*r
->iocb
)(r
->ctx
, buf
, bytes
- (size_t)total
);
996 DEBUG_printf(("5cups_raster_io: count=%d, total=%d", (int)count
,
1009 * 'cups_raster_read()' - Read through the raster buffer.
1012 static ssize_t
/* O - Number of bytes read */
1013 cups_raster_read(cups_raster_t
*r
, /* I - Raster stream */
1014 unsigned char *buf
, /* I - Buffer */
1015 size_t bytes
) /* I - Number of bytes to read */
1017 ssize_t count
, /* Number of bytes read */
1018 remaining
, /* Remaining bytes in buffer */
1019 total
; /* Total bytes read */
1022 DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT
")\n", r
, buf
, CUPS_LLCAST bytes
));
1025 return (cups_raster_io(r
, buf
, bytes
));
1028 * Allocate a read buffer as needed...
1031 count
= (ssize_t
)(2 * r
->header
.cupsBytesPerLine
);
1033 if ((size_t)count
> r
->bufsize
)
1035 ssize_t offset
= r
->bufptr
- r
->buffer
;
1036 /* Offset to current start of buffer */
1037 ssize_t end
= r
->bufend
- r
->buffer
;/* Offset to current end of buffer */
1038 unsigned char *rptr
; /* Pointer in read buffer */
1041 rptr
= realloc(r
->buffer
, (size_t)count
);
1043 rptr
= malloc((size_t)count
);
1049 r
->bufptr
= rptr
+ offset
;
1050 r
->bufend
= rptr
+ end
;
1051 r
->bufsize
= (size_t)count
;
1055 * Loop until we have read everything...
1058 for (total
= 0, remaining
= (int)(r
->bufend
- r
->bufptr
);
1059 total
< (ssize_t
)bytes
;
1060 total
+= count
, buf
+= count
)
1062 count
= (ssize_t
)bytes
- total
;
1064 DEBUG_printf(("count=" CUPS_LLFMT
", remaining=" CUPS_LLFMT
", buf=%p, bufptr=%p, bufend=%p...\n", CUPS_LLCAST count
, CUPS_LLCAST remaining
, buf
, r
->bufptr
, r
->bufend
));
1071 * Read into the raster buffer and then copy...
1074 remaining
= (*r
->iocb
)(r
->ctx
, r
->buffer
, r
->bufsize
);
1078 r
->bufptr
= r
->buffer
;
1079 r
->bufend
= r
->buffer
+ remaining
;
1084 * Read directly into "buf"...
1087 count
= (*r
->iocb
)(r
->ctx
, buf
, (size_t)count
);
1097 * Copy bytes from raster buffer to "buf"...
1100 if (count
> remaining
)
1109 *buf
= *(r
->bufptr
)++;
1112 else if (count
< 128)
1115 * Copy up to 127 bytes without using memcpy(); this is
1116 * faster because it avoids an extra function call and is
1117 * often further optimized by the compiler...
1120 unsigned char *bufptr
; /* Temporary buffer pointer */
1124 for (bufptr
= r
->bufptr
; count
> 0; count
--, total
++)
1132 * Use memcpy() for a large read...
1135 memcpy(buf
, r
->bufptr
, (size_t)count
);
1146 * 'cups_raster_update()' - Update the raster header and row count for the
1151 cups_raster_update(cups_raster_t
*r
) /* I - Raster stream */
1153 if (r
->sync
== CUPS_RASTER_SYNCv1
|| r
->sync
== CUPS_RASTER_REVSYNCv1
||
1154 r
->header
.cupsNumColors
== 0)
1157 * Set the "cupsNumColors" field according to the colorspace...
1160 switch (r
->header
.cupsColorSpace
)
1162 case CUPS_CSPACE_W
:
1163 case CUPS_CSPACE_K
:
1164 case CUPS_CSPACE_WHITE
:
1165 case CUPS_CSPACE_GOLD
:
1166 case CUPS_CSPACE_SILVER
:
1167 case CUPS_CSPACE_SW
:
1168 r
->header
.cupsNumColors
= 1;
1171 case CUPS_CSPACE_RGB
:
1172 case CUPS_CSPACE_CMY
:
1173 case CUPS_CSPACE_YMC
:
1174 case CUPS_CSPACE_CIEXYZ
:
1175 case CUPS_CSPACE_CIELab
:
1176 case CUPS_CSPACE_SRGB
:
1177 case CUPS_CSPACE_ADOBERGB
:
1178 case CUPS_CSPACE_ICC1
:
1179 case CUPS_CSPACE_ICC2
:
1180 case CUPS_CSPACE_ICC3
:
1181 case CUPS_CSPACE_ICC4
:
1182 case CUPS_CSPACE_ICC5
:
1183 case CUPS_CSPACE_ICC6
:
1184 case CUPS_CSPACE_ICC7
:
1185 case CUPS_CSPACE_ICC8
:
1186 case CUPS_CSPACE_ICC9
:
1187 case CUPS_CSPACE_ICCA
:
1188 case CUPS_CSPACE_ICCB
:
1189 case CUPS_CSPACE_ICCC
:
1190 case CUPS_CSPACE_ICCD
:
1191 case CUPS_CSPACE_ICCE
:
1192 case CUPS_CSPACE_ICCF
:
1193 r
->header
.cupsNumColors
= 3;
1196 case CUPS_CSPACE_RGBA
:
1197 case CUPS_CSPACE_RGBW
:
1198 case CUPS_CSPACE_CMYK
:
1199 case CUPS_CSPACE_YMCK
:
1200 case CUPS_CSPACE_KCMY
:
1201 case CUPS_CSPACE_GMCK
:
1202 case CUPS_CSPACE_GMCS
:
1203 r
->header
.cupsNumColors
= 4;
1206 case CUPS_CSPACE_KCMYcm
:
1207 if (r
->header
.cupsBitsPerPixel
< 8)
1208 r
->header
.cupsNumColors
= 6;
1210 r
->header
.cupsNumColors
= 4;
1213 case CUPS_CSPACE_DEVICE1
:
1214 case CUPS_CSPACE_DEVICE2
:
1215 case CUPS_CSPACE_DEVICE3
:
1216 case CUPS_CSPACE_DEVICE4
:
1217 case CUPS_CSPACE_DEVICE5
:
1218 case CUPS_CSPACE_DEVICE6
:
1219 case CUPS_CSPACE_DEVICE7
:
1220 case CUPS_CSPACE_DEVICE8
:
1221 case CUPS_CSPACE_DEVICE9
:
1222 case CUPS_CSPACE_DEVICEA
:
1223 case CUPS_CSPACE_DEVICEB
:
1224 case CUPS_CSPACE_DEVICEC
:
1225 case CUPS_CSPACE_DEVICED
:
1226 case CUPS_CSPACE_DEVICEE
:
1227 case CUPS_CSPACE_DEVICEF
:
1228 r
->header
.cupsNumColors
= r
->header
.cupsColorSpace
-
1229 CUPS_CSPACE_DEVICE1
+ 1;
1235 * Set the number of bytes per pixel/color...
1238 if (r
->header
.cupsColorOrder
== CUPS_ORDER_CHUNKED
)
1239 r
->bpp
= (r
->header
.cupsBitsPerPixel
+ 7) / 8;
1241 r
->bpp
= (r
->header
.cupsBitsPerColor
+ 7) / 8;
1244 * Set the number of remaining rows...
1247 if (r
->header
.cupsColorOrder
== CUPS_ORDER_PLANAR
)
1248 r
->remaining
= r
->header
.cupsHeight
* r
->header
.cupsNumColors
;
1250 r
->remaining
= r
->header
.cupsHeight
;
1253 * Allocate the compression buffer...
1258 if (r
->pixels
!= NULL
)
1261 r
->pixels
= calloc(r
->header
.cupsBytesPerLine
, 1);
1262 r
->pcurrent
= r
->pixels
;
1263 r
->pend
= r
->pixels
+ r
->header
.cupsBytesPerLine
;
1270 * 'cups_raster_write()' - Write a row of compressed raster data...
1273 static ssize_t
/* O - Number of bytes written */
1275 cups_raster_t
*r
, /* I - Raster stream */
1276 const unsigned char *pixels
) /* I - Pixel data to write */
1278 const unsigned char *start
, /* Start of sequence */
1279 *ptr
, /* Current pointer in sequence */
1280 *pend
, /* End of raster buffer */
1281 *plast
; /* Pointer to last pixel */
1282 unsigned char *wptr
; /* Pointer into write buffer */
1283 unsigned bpp
, /* Bytes per pixel */
1287 DEBUG_printf(("cups_raster_write(r=%p, pixels=%p)\n", r
, pixels
));
1290 * Allocate a write buffer as needed...
1293 count
= r
->header
.cupsBytesPerLine
* 2;
1294 if ((size_t)count
> r
->bufsize
)
1297 wptr
= realloc(r
->buffer
, count
);
1299 wptr
= malloc(count
);
1309 * Write the row repeat count...
1313 pend
= pixels
+ r
->header
.cupsBytesPerLine
;
1316 *wptr
++ = (unsigned char)(r
->count
- 1);
1319 * Write using a modified PackBits compression...
1322 for (ptr
= pixels
; ptr
< pend
;)
1330 * Encode a single pixel at the end...
1334 for (count
= bpp
; count
> 0; count
--)
1337 else if (!memcmp(start
, ptr
, bpp
))
1340 * Encode a sequence of repeating pixels...
1343 for (count
= 2; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1344 if (memcmp(ptr
, ptr
+ bpp
, bpp
))
1347 *wptr
++ = (unsigned char)(count
- 1);
1348 for (count
= bpp
; count
> 0; count
--)
1354 * Encode a sequence of non-repeating pixels...
1357 for (count
= 1; count
< 128 && ptr
< plast
; count
++, ptr
+= bpp
)
1358 if (!memcmp(ptr
, ptr
+ bpp
, bpp
))
1361 if (ptr
>= plast
&& count
< 128)
1367 *wptr
++ = (unsigned char)(257 - count
);
1370 memcpy(wptr
, start
, count
);
1375 return (cups_raster_io(r
, r
->buffer
, (size_t)(wptr
- r
->buffer
)));
1380 * 'cups_read_fd()' - Read bytes from a file.
1383 static ssize_t
/* O - Bytes read or -1 */
1384 cups_read_fd(void *ctx
, /* I - File descriptor as pointer */
1385 unsigned char *buf
, /* I - Buffer for read */
1386 size_t bytes
) /* I - Maximum number of bytes to read */
1388 int fd
= (int)((intptr_t)ctx
);
1389 /* File descriptor */
1390 ssize_t count
; /* Number of bytes read */
1393 #ifdef WIN32 /* Sigh */
1394 while ((count
= read(fd
, buf
, (unsigned)bytes
)) < 0)
1396 while ((count
= read(fd
, buf
, bytes
)) < 0)
1398 if (errno
!= EINTR
&& errno
!= EAGAIN
)
1406 * 'cups_swap()' - Swap bytes in raster data...
1410 cups_swap(unsigned char *buf
, /* I - Buffer to swap */
1411 size_t bytes
) /* I - Number of bytes to swap */
1413 unsigned char even
, odd
; /* Temporary variables */
1432 * 'cups_write_fd()' - Write bytes to a file.
1435 static ssize_t
/* O - Bytes written or -1 */
1436 cups_write_fd(void *ctx
, /* I - File descriptor pointer */
1437 unsigned char *buf
, /* I - Bytes to write */
1438 size_t bytes
) /* I - Number of bytes to write */
1440 int fd
= (int)((intptr_t)ctx
);
1441 /* File descriptor */
1442 ssize_t count
; /* Number of bytes written */
1445 #ifdef WIN32 /* Sigh */
1446 while ((count
= write(fd
, buf
, (unsigned)bytes
)) < 0)
1448 while ((count
= write(fd
, buf
, bytes
)) < 0)
1450 if (errno
!= EINTR
&& errno
!= EAGAIN
)