]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/raster.c
Import CUPS v1.7.1
[thirdparty/cups.git] / filter / raster.c
CommitLineData
ef416fc2 1/*
61515785 2 * "$Id: raster.c 10996 2013-05-29 11:51:34Z msweet $"
ef416fc2 3 *
c7017ecc 4 * Raster file routines for CUPS.
ef416fc2 5 *
f3c17241 6 * Copyright 2007-2012 by Apple Inc.
ef416fc2 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
bc44d920 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/".
ef416fc2 16 *
ef416fc2 17 * This file is subject to the Apple OS-Developed Software exception.
18 *
19 * Contents:
20 *
ed486911 21 * cupsRasterClose() - Close a raster stream.
c8fef167
MS
22 * cupsRasterOpen() - Open a raster stream using a file descriptor.
23 * cupsRasterOpenIO() - Open a raster stream using a callback function.
ed486911 24 * cupsRasterReadHeader() - Read a raster page header and store it in a
db0bd74a 25 * version 1 page header structure.
ed486911 26 * cupsRasterReadHeader2() - Read a raster page header and store it in a
db0bd74a 27 * version 2 page header structure.
ed486911 28 * cupsRasterReadPixels() - Read raster pixels.
db0bd74a
MS
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.
ed486911 33 * cupsRasterWritePixels() - Write raster pixels.
ed486911 34 * cups_raster_read_header() - Read a raster page header.
c8fef167 35 * cups_raster_read() - Read through the raster buffer.
ed486911 36 * cups_raster_update() - Update the raster header and row count for the
37 * current page.
c8fef167
MS
38 * cups_raster_write() - Write a row of compressed raster data...
39 * cups_read_fd() - Read bytes from a file.
ed486911 40 * cups_swap() - Swap bytes in raster data...
c8fef167 41 * cups_write_fd() - Write bytes to a file.
ef416fc2 42 */
43
44/*
45 * Include necessary headers...
46 */
47
a4845881 48#include <cups/raster-private.h>
5a9febac
MS
49#ifdef HAVE_STDINT_H
50# include <stdint.h>
51#endif /* HAVE_STDINT_H */
ef416fc2 52
53
f301802f 54/*
55 * Private structures...
56 */
57
58struct _cups_raster_s /**** Raster stream data ****/
59{
60 unsigned sync; /* Sync word from start of stream */
c8fef167
MS
61 void *ctx; /* File descriptor */
62 cups_raster_iocb_t iocb; /* IO callback */
f301802f 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 */
ed486911 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 */
c8fef167 76 size_t bufsize; /* Buffer size */
f301802f 77};
78
ed486911 79
ef416fc2 80/*
81 * Local functions...
82 */
83
f14324a7 84static int cups_raster_io(cups_raster_t *r, unsigned char *buf, int bytes);
ef416fc2 85static unsigned cups_raster_read_header(cups_raster_t *r);
ed486911 86static int cups_raster_read(cups_raster_t *r, unsigned char *buf,
87 int bytes);
ef416fc2 88static void cups_raster_update(cups_raster_t *r);
c8fef167
MS
89static int cups_raster_write(cups_raster_t *r,
90 const unsigned char *pixels);
91static ssize_t cups_read_fd(void *ctx, unsigned char *buf, size_t bytes);
ed486911 92static void cups_swap(unsigned char *buf, int bytes);
c8fef167 93static ssize_t cups_write_fd(void *ctx, unsigned char *buf, size_t bytes);
ef416fc2 94
95
96/*
97 * 'cupsRasterClose()' - Close a raster stream.
db0bd74a
MS
98 *
99 * The file descriptor associated with the raster stream must be closed
100 * separately as needed.
ef416fc2 101 */
102
103void
104cupsRasterClose(cups_raster_t *r) /* I - Stream to close */
105{
106 if (r != NULL)
107 {
ed486911 108 if (r->buffer)
109 free(r->buffer);
110
ef416fc2 111 if (r->pixels)
112 free(r->pixels);
113
114 free(r);
115 }
116}
117
118
119/*
c8fef167 120 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
db0bd74a
MS
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 *
c8fef167
MS
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.
ef416fc2 131 */
132
133cups_raster_t * /* O - New stream */
134cupsRasterOpen(int fd, /* I - File descriptor */
c8fef167
MS
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
159cups_raster_t * /* O - New stream */
160cupsRasterOpenIO(
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@ */
ef416fc2 167{
168 cups_raster_t *r; /* New stream */
169
170
f7deaa1a 171 _cupsRasterClearError();
172
ef416fc2 173 if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
f7deaa1a 174 {
175 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
176 strerror(errno));
ef416fc2 177 return (NULL);
f7deaa1a 178 }
ef416fc2 179
c8fef167
MS
180 r->ctx = ctx;
181 r->iocb = iocb;
182 r->mode = mode;
ef416fc2 183
184 if (mode == CUPS_RASTER_READ)
185 {
186 /*
187 * Open for read - get sync word...
188 */
189
f14324a7 190 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) !=
c8fef167 191 sizeof(r->sync))
ef416fc2 192 {
f7deaa1a 193 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
194 strerror(errno));
ef416fc2 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 &&
ed486911 202 r->sync != CUPS_RASTER_REVSYNCv1 &&
203 r->sync != CUPS_RASTER_SYNCv2 &&
204 r->sync != CUPS_RASTER_REVSYNCv2)
ef416fc2 205 {
f7deaa1a 206 _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
ef416fc2 207 free(r);
208 return (NULL);
209 }
ed486911 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;
09a101d6 219
220 DEBUG_printf(("r->swapped=%d, r->sync=%08x\n", r->swapped, r->sync));
ef416fc2 221 }
222 else
223 {
224 /*
225 * Open for write - put sync word...
226 */
227
c8fef167 228 switch (mode)
f7deaa1a 229 {
c8fef167
MS
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;
f7deaa1a 245 }
ed486911 246
f14324a7 247 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync))
ef416fc2 248 < sizeof(r->sync))
249 {
f7deaa1a 250 _cupsRasterAddError("Unable to write raster stream header: %s\n",
251 strerror(errno));
ef416fc2 252 free(r);
253 return (NULL);
254 }
255 }
256
257 return (r);
258}
259
260
261/*
b423cd4c 262 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
db0bd74a
MS
263 * version 1 page header structure.
264 *
265 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
266 *
79e1d494
MS
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 *
db0bd74a 271 * @deprecated@
ef416fc2 272 */
273
79e1d494 274unsigned /* O - 1 on success, 0 on failure/end-of-file */
ef416fc2 275cupsRasterReadHeader(
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);
f14324a7 285
ef416fc2 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/*
b423cd4c 297 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
db0bd74a 298 * version 2 page header structure.
ef416fc2 299 *
f3c17241 300 * @since CUPS 1.2/OS X 10.5@
ef416fc2 301 */
302
79e1d494 303unsigned /* O - 1 on success, 0 on failure/end-of-file */
ef416fc2 304cupsRasterReadHeader2(
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);
f14324a7 314
ef416fc2 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.
79e1d494
MS
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.
ef416fc2 331 */
332
333unsigned /* O - Number of bytes read */
334cupsRasterReadPixels(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 */
ed486911 339 unsigned cupsBytesPerLine; /* cupsBytesPerLine value */
ef416fc2 340 unsigned remaining; /* Bytes remaining */
341 unsigned char *ptr, /* Pointer to read buffer */
ed486911 342 byte, /* Byte from file */
343 *temp; /* Pointer into buffer */
344 int count; /* Repetition count */
ef416fc2 345
346
a4845881
MS
347 if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0 ||
348 r->header.cupsBytesPerLine == 0)
ef416fc2 349 return (0);
350
ed486911 351 if (!r->compressed)
352 {
353 /*
354 * Read without compression...
355 */
356
357 r->remaining -= len / r->header.cupsBytesPerLine;
358
f14324a7 359 if (cups_raster_io(r, p, len) < (ssize_t)len)
ed486911 360 return (0);
361
362 /*
363 * Swap bytes as needed...
364 */
365
c8fef167
MS
366 if (r->swapped &&
367 (r->header.cupsBitsPerColor == 16 ||
ed486911 368 r->header.cupsBitsPerPixel == 12 ||
c8fef167 369 r->header.cupsBitsPerPixel == 16))
ed486911 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;
ef416fc2 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
ed486911 394 if (remaining == cupsBytesPerLine)
ef416fc2 395 ptr = p;
396 else
397 ptr = r->pixels;
398
ed486911 399 /*
c8fef167 400 * Read using a modified PackBits compression...
ed486911 401 */
ef416fc2 402
ed486911 403 if (!cups_raster_read(r, &byte, 1))
404 return (0);
ef416fc2 405
ed486911 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)
ef416fc2 415 {
416 /*
ed486911 417 * Get a new repeat count...
ef416fc2 418 */
419
ed486911 420 if (!cups_raster_read(r, &byte, 1))
ef416fc2 421 return (0);
422
ed486911 423 if (byte & 128)
ef416fc2 424 {
425 /*
ed486911 426 * Copy N literal pixels...
ef416fc2 427 */
428
ed486911 429 count = (257 - byte) * r->bpp;
ef416fc2 430
ed486911 431 if (count > bytes)
432 count = bytes;
ef416fc2 433
ed486911 434 if (!cups_raster_read(r, temp, count))
435 return (0);
ef416fc2 436
ed486911 437 temp += count;
438 bytes -= count;
439 }
440 else
441 {
442 /*
443 * Repeat the next N bytes...
444 */
ef416fc2 445
ed486911 446 count = (byte + 1) * r->bpp;
447 if (count > bytes)
448 count = bytes;
ef416fc2 449
ed486911 450 if (count < r->bpp)
451 break;
ef416fc2 452
ed486911 453 bytes -= count;
ef416fc2 454
ed486911 455 if (!cups_raster_read(r, temp, r->bpp))
456 return (0);
ef416fc2 457
ed486911 458 temp += r->bpp;
459 count -= r->bpp;
ef416fc2 460
ed486911 461 while (count > 0)
462 {
463 memcpy(temp, temp - r->bpp, r->bpp);
ef416fc2 464 temp += r->bpp;
465 count -= r->bpp;
ed486911 466 }
ef416fc2 467 }
468 }
469
ed486911 470 /*
471 * Swap bytes as needed...
472 */
473
f301802f 474 if ((r->header.cupsBitsPerColor == 16 ||
475 r->header.cupsBitsPerPixel == 12 ||
476 r->header.cupsBitsPerPixel == 16) &&
ed486911 477 r->swapped)
478 cups_swap(ptr, bytes);
ef416fc2 479
ed486911 480 /*
481 * Update pointers...
482 */
ef416fc2 483
ed486911 484 if (remaining >= cupsBytesPerLine)
ef416fc2 485 {
ed486911 486 bytes = cupsBytesPerLine;
ef416fc2 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
ed486911 497 /*
498 * Copy data as needed...
499 */
500
ef416fc2 501 if (ptr != p)
502 memcpy(p, ptr, bytes);
503 }
504 else
505 {
506 /*
507 * Copy fragment from buffer...
508 */
509
a2326b5b 510 if ((unsigned)(bytes = (int)(r->pend - r->pcurrent)) > remaining)
ef416fc2 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/*
db0bd74a 533 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
b423cd4c 534 * header structure.
db0bd74a
MS
535 *
536 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
537 *
538 * @deprecated@
ef416fc2 539 */
f14324a7 540
ef416fc2 541unsigned /* O - 1 on success, 0 on failure */
542cupsRasterWriteHeader(
543 cups_raster_t *r, /* I - Raster stream */
544 cups_page_header_t *h) /* I - Raster page header */
545{
c8fef167 546 if (r == NULL || r->mode == CUPS_RASTER_READ)
ef416fc2 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
c8fef167
MS
563 if (r->mode == CUPS_RASTER_WRITE_PWG)
564 {
565 /*
10ddcf65 566 * PWG raster data is always network byte order with much of the page header
c8fef167
MS
567 * zeroed.
568 */
569
570 cups_page_header2_t fh; /* File page header */
571
572 memset(&fh, 0, sizeof(fh));
10ddcf65
MS
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));
c8fef167 639
f14324a7 640 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
c8fef167
MS
641 }
642 else
f14324a7 643 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
c8fef167 644 == sizeof(r->header));
ef416fc2 645}
646
647
648/*
db0bd74a
MS
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@.
ef416fc2 653 *
f3c17241 654 * @since CUPS 1.2/OS X 10.5@
ef416fc2 655 */
f14324a7 656
ef416fc2 657unsigned /* O - 1 on success, 0 on failure */
658cupsRasterWriteHeader2(
659 cups_raster_t *r, /* I - Raster stream */
660 cups_page_header2_t *h) /* I - Raster page header */
661{
c8fef167 662 if (r == NULL || r->mode == CUPS_RASTER_READ)
ef416fc2 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
c8fef167
MS
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));
771bd8cb
MS
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]);
83e08001
MS
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]));
771bd8cb 735 fh.cupsInteger[7] = htonl(0xffffff);
c8fef167 736
f14324a7 737 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
c8fef167
MS
738 }
739 else
f14324a7 740 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
c8fef167 741 == sizeof(r->header));
ef416fc2 742}
743
744
745/*
746 * 'cupsRasterWritePixels()' - Write raster pixels.
79e1d494
MS
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.
ef416fc2 751 */
752
753unsigned /* O - Number of bytes written */
754cupsRasterWritePixels(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{
f7deaa1a 758 int bytes; /* Bytes read */
759 unsigned remaining; /* Bytes remaining */
760
761
09a101d6 762 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
763 r, p, len, r->remaining));
f301802f 764
c8fef167 765 if (r == NULL || r->mode == CUPS_RASTER_READ || r->remaining == 0)
ef416fc2 766 return (0);
767
f7deaa1a 768 if (!r->compressed)
769 {
770 /*
c8fef167
MS
771 * Without compression, just write the raster data raw unless the data needs
772 * to be swapped...
f7deaa1a 773 */
774
775 r->remaining -= len / r->header.cupsBytesPerLine;
776
c8fef167
MS
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
f14324a7 820 return (cups_raster_io(r, r->buffer, len));
c8fef167
MS
821 }
822 else
f14324a7 823 return (cups_raster_io(r, p, len));
f7deaa1a 824 }
825
ed486911 826 /*
f7deaa1a 827 * Otherwise, compress each line...
ed486911 828 */
ef416fc2 829
f7deaa1a 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
a2326b5b
MS
836 if ((bytes = remaining) > (int)(r->pend - r->pcurrent))
837 bytes = (int)(r->pend - r->pcurrent);
f7deaa1a 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);
f301802f 881
f7deaa1a 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);
ef416fc2 922}
923
924
925/*
926 * 'cups_raster_read_header()' - Read a raster page header.
927 */
928
929static unsigned /* O - 1 on success, 0 on fail */
930cups_raster_read_header(
931 cups_raster_t *r) /* I - Raster stream */
932{
09a101d6 933 int len; /* Length for read/swap */
ef416fc2 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
ed486911 954 if (cups_raster_read(r, (unsigned char *)&(r->header), len) < len)
ef416fc2 955 return (0);
956
957 /*
958 * Swap bytes as needed...
959 */
960
ed486911 961 if (r->swapped)
09a101d6 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);
ef416fc2 970 len > 0;
971 len --, s ++)
09a101d6 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 }
ef416fc2 984
985 /*
986 * Update the header and row count...
987 */
988
989 cups_raster_update(r);
990
a4845881 991 return (r->header.cupsBytesPerLine != 0 && r->header.cupsHeight != 0);
ef416fc2 992}
993
994
f14324a7
MS
995/*
996 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
997 */
998
999static int /* O - Bytes read or -1 */
83e08001 1000cups_raster_io(cups_raster_t *r, /* I - Raster stream */
f14324a7
MS
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
83e08001 1010 for (total = 0; total < (size_t)bytes; total += count, buf += count)
f14324a7
MS
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
ed486911 1026/*
1027 * 'cups_raster_read()' - Read through the raster buffer.
1028 */
1029
1030static int /* O - Number of bytes read */
1031cups_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)
f14324a7 1043 return (cups_raster_io(r, buf, bytes));
ed486911 1044
1045 /*
1046 * Allocate a read buffer as needed...
1047 */
1048
1049 count = 2 * r->header.cupsBytesPerLine;
1050
c8fef167 1051 if ((size_t)count > r->bufsize)
ed486911 1052 {
a2326b5b
MS
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 */
ed486911 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
a2326b5b 1077 for (total = 0, remaining = (int)(r->bufend - r->bufptr);
ed486911 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
c8fef167 1094 remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize);
ed486911 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
c8fef167 1107 count = (*r->iocb)(r->ctx, buf, count);
ed486911 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
ed486911 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
ef416fc2 1165/*
1166 * 'cups_raster_update()' - Update the raster header and row count for the
1167 * current page.
1168 */
1169
1170static void
1171cups_raster_update(cups_raster_t *r) /* I - Raster stream */
1172{
f301802f 1173 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 ||
1174 r->header.cupsNumColors == 0)
ef416fc2 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 :
c7017ecc 1187 case CUPS_CSPACE_SW :
ef416fc2 1188 r->header.cupsNumColors = 1;
1189 break;
1190
ef416fc2 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 :
c7017ecc
MS
1196 case CUPS_CSPACE_SRGB :
1197 case CUPS_CSPACE_ADOBERGB :
f301802f 1198 case CUPS_CSPACE_ICC1 :
1199 case CUPS_CSPACE_ICC2 :
ef416fc2 1200 case CUPS_CSPACE_ICC3 :
f301802f 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 :
ef416fc2 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 :
ef416fc2 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;
c7017ecc
MS
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;
ef416fc2 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 /*
ed486911 1273 * Allocate the compression buffer...
ef416fc2 1274 */
1275
ed486911 1276 if (r->compressed)
1277 {
1278 if (r->pixels != NULL)
1279 free(r->pixels);
ef416fc2 1280
ed486911 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 }
ef416fc2 1286}
1287
1288
f7deaa1a 1289/*
1290 * 'cups_raster_write()' - Write a row of compressed raster data...
1291 */
1292
1293static int /* O - Number of bytes written */
1294cups_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 */
1f0275e3 1304 count; /* Count */
f7deaa1a 1305
1306
09a101d6 1307 DEBUG_printf(("cups_raster_write(r=%p, pixels=%p)\n", r, pixels));
f7deaa1a 1308
1309 /*
1310 * Allocate a write buffer as needed...
1311 */
1312
1313 count = r->header.cupsBytesPerLine * 2;
c8fef167 1314 if ((size_t)count > r->bufsize)
f7deaa1a 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;
f7deaa1a 1337
1338 /*
07ed0e9a 1339 * Write using a modified PackBits compression...
f7deaa1a 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
07ed0e9a 1377 for (count = 1; count < 128 && ptr < plast; count ++, ptr += bpp)
f7deaa1a 1378 if (!memcmp(ptr, ptr + bpp, bpp))
1379 break;
1380
1381 if (ptr >= plast && count < 128)
1382 {
1383 count ++;
1384 ptr += bpp;
1385 }
f14324a7 1386
f7deaa1a 1387 *wptr++ = 257 - count;
1388
1389 count *= bpp;
1390 memcpy(wptr, start, count);
1391 wptr += count;
1392 }
1393 }
1394
a2326b5b 1395 return (cups_raster_io(r, r->buffer, (int)(wptr - r->buffer)));
f7deaa1a 1396}
1397
1398
ef416fc2 1399/*
c8fef167 1400 * 'cups_read_fd()' - Read bytes from a file.
ef416fc2 1401 */
1402
c8fef167
MS
1403static ssize_t /* O - Bytes read or -1 */
1404cups_read_fd(void *ctx, /* I - File descriptor as pointer */
1405 unsigned char *buf, /* I - Buffer for read */
f14324a7 1406 size_t bytes) /* I - Maximum number of bytes to read */
ef416fc2 1407{
c8fef167
MS
1408 int fd = (int)((intptr_t)ctx);
1409 /* File descriptor */
1410 ssize_t count; /* Number of bytes read */
ef416fc2 1411
ef416fc2 1412
a2326b5b
MS
1413#ifdef WIN32 /* Sigh */
1414 while ((count = read(fd, buf, (unsigned)bytes)) < 0)
1415#else
f14324a7 1416 while ((count = read(fd, buf, bytes)) < 0)
a2326b5b 1417#endif /* WIN32 */
f14324a7
MS
1418 if (errno != EINTR && errno != EAGAIN)
1419 return (-1);
ef416fc2 1420
f14324a7 1421 return (count);
ef416fc2 1422}
1423
1424
ed486911 1425/*
1426 * 'cups_swap()' - Swap bytes in raster data...
1427 */
1428
1429static void
1430cups_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
ef416fc2 1451/*
c8fef167 1452 * 'cups_write_fd()' - Write bytes to a file.
ef416fc2 1453 */
1454
c8fef167
MS
1455static ssize_t /* O - Bytes written or -1 */
1456cups_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 */
ef416fc2 1459{
c8fef167
MS
1460 int fd = (int)((intptr_t)ctx);
1461 /* File descriptor */
1462 ssize_t count; /* Number of bytes written */
ef416fc2 1463
ef416fc2 1464
a2326b5b
MS
1465#ifdef WIN32 /* Sigh */
1466 while ((count = write(fd, buf, (unsigned)bytes)) < 0)
1467#else
f14324a7 1468 while ((count = write(fd, buf, bytes)) < 0)
a2326b5b 1469#endif /* WIN32 */
f14324a7
MS
1470 if (errno != EINTR && errno != EAGAIN)
1471 return (-1);
ef416fc2 1472
f14324a7 1473 return (count);
ef416fc2 1474}
1475
1476
1477/*
61515785 1478 * End of "$Id: raster.c 10996 2013-05-29 11:51:34Z msweet $".
ef416fc2 1479 */