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