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