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