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