]> git.ipfire.org Git - thirdparty/cups.git/blame - filter/raster.c
Adjust GNU TLS cipher suite priority strings per feedback from Tim
[thirdparty/cups.git] / filter / raster.c
CommitLineData
ef416fc2 1/*
f2d18633 2 * "$Id$"
ef416fc2 3 *
7e86f2f6 4 * Raster file routines for CUPS.
ef416fc2 5 *
7e86f2f6
MS
6 * Copyright 2007-2014 by Apple Inc.
7 * Copyright 1997-2006 by Easy Software Products.
ef416fc2 8 *
7e86f2f6 9 * This file is part of the CUPS Imaging library.
ef416fc2 10 *
7e86f2f6
MS
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/".
ef416fc2 16 *
7e86f2f6 17 * This file is subject to the Apple OS-Developed Software exception.
ef416fc2 18 */
19
20/*
21 * Include necessary headers...
22 */
23
a4845881 24#include <cups/raster-private.h>
5a9febac
MS
25#ifdef HAVE_STDINT_H
26# include <stdint.h>
27#endif /* HAVE_STDINT_H */
ef416fc2 28
29
f301802f 30/*
31 * Private structures...
32 */
33
34struct _cups_raster_s /**** Raster stream data ****/
35{
36 unsigned sync; /* Sync word from start of stream */
c8fef167
MS
37 void *ctx; /* File descriptor */
38 cups_raster_iocb_t iocb; /* IO callback */
f301802f 39 cups_mode_t mode; /* Read/write mode */
40 cups_page_header2_t header; /* Raster header for current page */
7e86f2f6 41 unsigned count, /* Current row run-length count */
f301802f 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 */
ed486911 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 */
c8fef167 52 size_t bufsize; /* Buffer size */
f301802f 53};
54
ed486911 55
ef416fc2 56/*
57 * Local functions...
58 */
59
7e86f2f6 60static ssize_t cups_raster_io(cups_raster_t *r, unsigned char *buf, size_t bytes);
ef416fc2 61static unsigned cups_raster_read_header(cups_raster_t *r);
7e86f2f6
MS
62static ssize_t cups_raster_read(cups_raster_t *r, unsigned char *buf,
63 size_t bytes);
ef416fc2 64static void cups_raster_update(cups_raster_t *r);
7e86f2f6 65static ssize_t cups_raster_write(cups_raster_t *r,
c8fef167
MS
66 const unsigned char *pixels);
67static ssize_t cups_read_fd(void *ctx, unsigned char *buf, size_t bytes);
7e86f2f6 68static void cups_swap(unsigned char *buf, size_t bytes);
c8fef167 69static ssize_t cups_write_fd(void *ctx, unsigned char *buf, size_t bytes);
ef416fc2 70
71
72/*
73 * 'cupsRasterClose()' - Close a raster stream.
db0bd74a
MS
74 *
75 * The file descriptor associated with the raster stream must be closed
76 * separately as needed.
ef416fc2 77 */
78
79void
80cupsRasterClose(cups_raster_t *r) /* I - Stream to close */
81{
82 if (r != NULL)
83 {
ed486911 84 if (r->buffer)
85 free(r->buffer);
86
ef416fc2 87 if (r->pixels)
88 free(r->pixels);
89
90 free(r);
91 }
92}
93
94
95/*
c8fef167 96 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor.
db0bd74a
MS
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 *
c8fef167
MS
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.
ef416fc2 107 */
108
109cups_raster_t * /* O - New stream */
110cupsRasterOpen(int fd, /* I - File descriptor */
c8fef167
MS
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
135cups_raster_t * /* O - New stream */
136cupsRasterOpenIO(
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@ */
ef416fc2 143{
144 cups_raster_t *r; /* New stream */
145
146
f7deaa1a 147 _cupsRasterClearError();
148
ef416fc2 149 if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL)
f7deaa1a 150 {
151 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n",
152 strerror(errno));
ef416fc2 153 return (NULL);
f7deaa1a 154 }
ef416fc2 155
c8fef167
MS
156 r->ctx = ctx;
157 r->iocb = iocb;
158 r->mode = mode;
ef416fc2 159
160 if (mode == CUPS_RASTER_READ)
161 {
162 /*
163 * Open for read - get sync word...
164 */
165
f14324a7 166 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) !=
c8fef167 167 sizeof(r->sync))
ef416fc2 168 {
f7deaa1a 169 _cupsRasterAddError("Unable to read header from raster stream: %s\n",
170 strerror(errno));
ef416fc2 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 &&
ed486911 178 r->sync != CUPS_RASTER_REVSYNCv1 &&
179 r->sync != CUPS_RASTER_SYNCv2 &&
180 r->sync != CUPS_RASTER_REVSYNCv2)
ef416fc2 181 {
f7deaa1a 182 _cupsRasterAddError("Unknown raster format %08x!\n", r->sync);
ef416fc2 183 free(r);
184 return (NULL);
185 }
ed486911 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;
09a101d6 195
196 DEBUG_printf(("r->swapped=%d, r->sync=%08x\n", r->swapped, r->sync));
ef416fc2 197 }
198 else
199 {
200 /*
201 * Open for write - put sync word...
202 */
203
c8fef167 204 switch (mode)
f7deaa1a 205 {
c8fef167
MS
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;
f7deaa1a 221 }
ed486911 222
7e86f2f6 223 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) < (ssize_t)sizeof(r->sync))
ef416fc2 224 {
f7deaa1a 225 _cupsRasterAddError("Unable to write raster stream header: %s\n",
226 strerror(errno));
ef416fc2 227 free(r);
228 return (NULL);
229 }
230 }
231
232 return (r);
233}
234
235
236/*
b423cd4c 237 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a
db0bd74a
MS
238 * version 1 page header structure.
239 *
240 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead.
241 *
79e1d494
MS
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 *
db0bd74a 246 * @deprecated@
ef416fc2 247 */
248
79e1d494 249unsigned /* O - 1 on success, 0 on failure/end-of-file */
ef416fc2 250cupsRasterReadHeader(
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);
f14324a7 260
ef416fc2 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/*
b423cd4c 272 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a
db0bd74a 273 * version 2 page header structure.
ef416fc2 274 *
f3c17241 275 * @since CUPS 1.2/OS X 10.5@
ef416fc2 276 */
277
79e1d494 278unsigned /* O - 1 on success, 0 on failure/end-of-file */
ef416fc2 279cupsRasterReadHeader2(
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);
f14324a7 289
ef416fc2 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.
79e1d494
MS
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.
ef416fc2 306 */
307
308unsigned /* O - Number of bytes read */
309cupsRasterReadPixels(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{
7e86f2f6 313 ssize_t bytes; /* Bytes read */
ed486911 314 unsigned cupsBytesPerLine; /* cupsBytesPerLine value */
ef416fc2 315 unsigned remaining; /* Bytes remaining */
316 unsigned char *ptr, /* Pointer to read buffer */
ed486911 317 byte, /* Byte from file */
318 *temp; /* Pointer into buffer */
7e86f2f6 319 unsigned count; /* Repetition count */
ef416fc2 320
321
a4845881
MS
322 if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0 ||
323 r->header.cupsBytesPerLine == 0)
ef416fc2 324 return (0);
325
ed486911 326 if (!r->compressed)
327 {
328 /*
329 * Read without compression...
330 */
331
332 r->remaining -= len / r->header.cupsBytesPerLine;
333
f14324a7 334 if (cups_raster_io(r, p, len) < (ssize_t)len)
ed486911 335 return (0);
336
337 /*
338 * Swap bytes as needed...
339 */
340
c8fef167
MS
341 if (r->swapped &&
342 (r->header.cupsBitsPerColor == 16 ||
ed486911 343 r->header.cupsBitsPerPixel == 12 ||
c8fef167 344 r->header.cupsBitsPerPixel == 16))
ed486911 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;
ef416fc2 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
ed486911 369 if (remaining == cupsBytesPerLine)
ef416fc2 370 ptr = p;
371 else
372 ptr = r->pixels;
373
ed486911 374 /*
c8fef167 375 * Read using a modified PackBits compression...
ed486911 376 */
ef416fc2 377
ed486911 378 if (!cups_raster_read(r, &byte, 1))
379 return (0);
ef416fc2 380
7d5824d6 381 r->count = (unsigned)byte + 1;
ed486911 382
383 if (r->count > 1)
384 ptr = r->pixels;
385
386 temp = ptr;
7e86f2f6 387 bytes = (ssize_t)cupsBytesPerLine;
ed486911 388
389 while (bytes > 0)
ef416fc2 390 {
391 /*
ed486911 392 * Get a new repeat count...
ef416fc2 393 */
394
ed486911 395 if (!cups_raster_read(r, &byte, 1))
ef416fc2 396 return (0);
397
ed486911 398 if (byte & 128)
ef416fc2 399 {
400 /*
ed486911 401 * Copy N literal pixels...
ef416fc2 402 */
403
7e86f2f6 404 count = (unsigned)(257 - byte) * r->bpp;
ef416fc2 405
7e86f2f6
MS
406 if (count > (unsigned)bytes)
407 count = (unsigned)bytes;
ef416fc2 408
ed486911 409 if (!cups_raster_read(r, temp, count))
410 return (0);
ef416fc2 411
ed486911 412 temp += count;
413 bytes -= count;
414 }
415 else
416 {
417 /*
418 * Repeat the next N bytes...
419 */
ef416fc2 420
7d5824d6 421 count = ((unsigned)byte + 1) * r->bpp;
7e86f2f6
MS
422 if (count > (unsigned)bytes)
423 count = (unsigned)bytes;
ef416fc2 424
ed486911 425 if (count < r->bpp)
426 break;
ef416fc2 427
ed486911 428 bytes -= count;
ef416fc2 429
ed486911 430 if (!cups_raster_read(r, temp, r->bpp))
431 return (0);
ef416fc2 432
ed486911 433 temp += r->bpp;
434 count -= r->bpp;
ef416fc2 435
ed486911 436 while (count > 0)
437 {
438 memcpy(temp, temp - r->bpp, r->bpp);
ef416fc2 439 temp += r->bpp;
440 count -= r->bpp;
ed486911 441 }
ef416fc2 442 }
443 }
444
ed486911 445 /*
446 * Swap bytes as needed...
447 */
448
f301802f 449 if ((r->header.cupsBitsPerColor == 16 ||
450 r->header.cupsBitsPerPixel == 12 ||
451 r->header.cupsBitsPerPixel == 16) &&
ed486911 452 r->swapped)
7e86f2f6 453 cups_swap(ptr, (size_t)bytes);
ef416fc2 454
ed486911 455 /*
456 * Update pointers...
457 */
ef416fc2 458
ed486911 459 if (remaining >= cupsBytesPerLine)
ef416fc2 460 {
7e86f2f6 461 bytes = (ssize_t)cupsBytesPerLine;
ef416fc2 462 r->pcurrent = r->pixels;
463 r->count --;
464 r->remaining --;
465 }
466 else
467 {
7e86f2f6 468 bytes = (ssize_t)remaining;
ef416fc2 469 r->pcurrent = r->pixels + bytes;
470 }
471
ed486911 472 /*
473 * Copy data as needed...
474 */
475
ef416fc2 476 if (ptr != p)
07623986 477 memcpy(p, ptr, (size_t)bytes);
ef416fc2 478 }
479 else
480 {
481 /*
482 * Copy fragment from buffer...
483 */
484
a2326b5b 485 if ((unsigned)(bytes = (int)(r->pend - r->pcurrent)) > remaining)
7e86f2f6 486 bytes = (ssize_t)remaining;
ef416fc2 487
07623986 488 memcpy(p, r->pcurrent, (size_t)bytes);
ef416fc2 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
7e86f2f6 499 remaining -= (unsigned)bytes;
ef416fc2 500 p += bytes;
501 }
502
503 return (len);
504}
505
506
507/*
db0bd74a 508 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page
b423cd4c 509 * header structure.
db0bd74a
MS
510 *
511 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead.
512 *
513 * @deprecated@
ef416fc2 514 */
f14324a7 515
ef416fc2 516unsigned /* O - 1 on success, 0 on failure */
517cupsRasterWriteHeader(
518 cups_raster_t *r, /* I - Raster stream */
519 cups_page_header_t *h) /* I - Raster page header */
520{
c8fef167 521 if (r == NULL || r->mode == CUPS_RASTER_READ)
ef416fc2 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
c8fef167
MS
538 if (r->mode == CUPS_RASTER_WRITE_PWG)
539 {
540 /*
10ddcf65 541 * PWG raster data is always network byte order with much of the page header
c8fef167
MS
542 * zeroed.
543 */
544
545 cups_page_header2_t fh; /* File page header */
546
547 memset(&fh, 0, sizeof(fh));
10ddcf65
MS
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
cf1d7281
MS
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));
10ddcf65
MS
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));
c8fef167 615
f14324a7 616 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
c8fef167
MS
617 }
618 else
f14324a7 619 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
c8fef167 620 == sizeof(r->header));
ef416fc2 621}
622
623
624/*
db0bd74a
MS
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@.
ef416fc2 629 *
f3c17241 630 * @since CUPS 1.2/OS X 10.5@
ef416fc2 631 */
f14324a7 632
ef416fc2 633unsigned /* O - 1 on success, 0 on failure */
634cupsRasterWriteHeader2(
635 cups_raster_t *r, /* I - Raster stream */
636 cups_page_header2_t *h) /* I - Raster page header */
637{
c8fef167 638 if (r == NULL || r->mode == CUPS_RASTER_READ)
ef416fc2 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
c8fef167
MS
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));
771bd8cb
MS
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]);
83e08001
MS
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]));
771bd8cb 711 fh.cupsInteger[7] = htonl(0xffffff);
c8fef167 712
f14324a7 713 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh));
c8fef167
MS
714 }
715 else
f14324a7 716 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header))
c8fef167 717 == sizeof(r->header));
ef416fc2 718}
719
720
721/*
722 * 'cupsRasterWritePixels()' - Write raster pixels.
79e1d494
MS
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.
ef416fc2 727 */
728
729unsigned /* O - Number of bytes written */
730cupsRasterWritePixels(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{
7e86f2f6 734 ssize_t bytes; /* Bytes read */
f7deaa1a 735 unsigned remaining; /* Bytes remaining */
736
737
09a101d6 738 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u\n",
739 r, p, len, r->remaining));
f301802f 740
c8fef167 741 if (r == NULL || r->mode == CUPS_RASTER_READ || r->remaining == 0)
ef416fc2 742 return (0);
743
f7deaa1a 744 if (!r->compressed)
745 {
746 /*
c8fef167
MS
747 * Without compression, just write the raster data raw unless the data needs
748 * to be swapped...
f7deaa1a 749 */
750
751 r->remaining -= len / r->header.cupsBytesPerLine;
752
c8fef167
MS
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
7e86f2f6 796 return ((unsigned)cups_raster_io(r, r->buffer, len));
c8fef167
MS
797 }
798 else
7e86f2f6 799 return ((unsigned)cups_raster_io(r, p, len));
f7deaa1a 800 }
801
ed486911 802 /*
f7deaa1a 803 * Otherwise, compress each line...
ed486911 804 */
ef416fc2 805
7e86f2f6 806 for (remaining = len; remaining > 0; remaining -= (unsigned)bytes, p += bytes)
f7deaa1a 807 {
808 /*
809 * Figure out the number of remaining bytes on the current line...
810 */
811
7e86f2f6
MS
812 if ((bytes = (ssize_t)remaining) > (ssize_t)(r->pend - r->pcurrent))
813 bytes = (ssize_t)(r->pend - r->pcurrent);
f7deaa1a 814
815 if (r->count > 0)
816 {
817 /*
818 * Check to see if this line is the same as the previous line...
819 */
820
7e86f2f6 821 if (memcmp(p, r->pcurrent, (size_t)bytes))
f7deaa1a 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)
7e86f2f6 852 return ((unsigned)cups_raster_write(r, r->pixels));
f7deaa1a 853 else if (r->count == 256)
854 {
855 if (cups_raster_write(r, r->pixels) == 0)
856 return (0);
f301802f 857
f7deaa1a 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
07623986 872 memcpy(r->pcurrent, p, (size_t)bytes);
f7deaa1a 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)
7e86f2f6 892 return ((unsigned)cups_raster_write(r, r->pixels));
f7deaa1a 893 }
894 }
895 }
896
897 return (len);
ef416fc2 898}
899
900
901/*
902 * 'cups_raster_read_header()' - Read a raster page header.
903 */
904
905static unsigned /* O - 1 on success, 0 on fail */
906cups_raster_read_header(
907 cups_raster_t *r) /* I - Raster stream */
908{
7e86f2f6 909 size_t len; /* Length for read/swap */
ef416fc2 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
7e86f2f6 930 if (cups_raster_read(r, (unsigned char *)&(r->header), len) < (ssize_t)len)
ef416fc2 931 return (0);
932
933 /*
934 * Swap bytes as needed...
935 */
936
ed486911 937 if (r->swapped)
09a101d6 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);
ef416fc2 946 len > 0;
947 len --, s ++)
09a101d6 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 }
ef416fc2 960
961 /*
962 * Update the header and row count...
963 */
964
965 cups_raster_update(r);
966
a4845881 967 return (r->header.cupsBytesPerLine != 0 && r->header.cupsHeight != 0);
ef416fc2 968}
969
970
f14324a7
MS
971/*
972 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions.
973 */
974
7e86f2f6 975static ssize_t /* O - Bytes read/write or -1 */
83e08001 976cups_raster_io(cups_raster_t *r, /* I - Raster stream */
7e86f2f6
MS
977 unsigned char *buf, /* I - Buffer for read/write */
978 size_t bytes) /* I - Number of bytes to read/write */
f14324a7 979{
7e86f2f6
MS
980 ssize_t count, /* Number of bytes read/written */
981 total; /* Total bytes read/written */
f14324a7
MS
982
983
7e86f2f6 984 DEBUG_printf(("4cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT ")", r, buf, CUPS_LLCAST bytes));
f14324a7 985
7e86f2f6 986 for (total = 0; total < (ssize_t)bytes; total += count, buf += count)
f14324a7 987 {
7e86f2f6 988 count = (*r->iocb)(r->ctx, buf, bytes - (size_t)total);
f14324a7
MS
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
7e86f2f6 998 return (total);
f14324a7
MS
999}
1000
1001
ed486911 1002/*
1003 * 'cups_raster_read()' - Read through the raster buffer.
1004 */
1005
7e86f2f6 1006static ssize_t /* O - Number of bytes read */
ed486911 1007cups_raster_read(cups_raster_t *r, /* I - Raster stream */
1008 unsigned char *buf, /* I - Buffer */
7e86f2f6 1009 size_t bytes) /* I - Number of bytes to read */
ed486911 1010{
7e86f2f6 1011 ssize_t count, /* Number of bytes read */
ed486911 1012 remaining, /* Remaining bytes in buffer */
1013 total; /* Total bytes read */
1014
1015
7e86f2f6 1016 DEBUG_printf(("cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT ")\n", r, buf, CUPS_LLCAST bytes));
ed486911 1017
1018 if (!r->compressed)
f14324a7 1019 return (cups_raster_io(r, buf, bytes));
ed486911 1020
1021 /*
1022 * Allocate a read buffer as needed...
1023 */
1024
7e86f2f6 1025 count = (ssize_t)(2 * r->header.cupsBytesPerLine);
ed486911 1026
c8fef167 1027 if ((size_t)count > r->bufsize)
ed486911 1028 {
7e86f2f6 1029 ssize_t offset = r->bufptr - r->buffer;
a2326b5b 1030 /* Offset to current start of buffer */
7e86f2f6 1031 ssize_t end = r->bufend - r->buffer;/* Offset to current end of buffer */
ed486911 1032 unsigned char *rptr; /* Pointer in read buffer */
1033
1034 if (r->buffer)
7e86f2f6 1035 rptr = realloc(r->buffer, (size_t)count);
ed486911 1036 else
7e86f2f6 1037 rptr = malloc((size_t)count);
ed486911 1038
1039 if (!rptr)
1040 return (0);
1041
1042 r->buffer = rptr;
1043 r->bufptr = rptr + offset;
1044 r->bufend = rptr + end;
7e86f2f6 1045 r->bufsize = (size_t)count;
ed486911 1046 }
1047
1048 /*
1049 * Loop until we have read everything...
1050 */
1051
a2326b5b 1052 for (total = 0, remaining = (int)(r->bufend - r->bufptr);
7e86f2f6 1053 total < (ssize_t)bytes;
ed486911 1054 total += count, buf += count)
1055 {
7e86f2f6 1056 count = (ssize_t)bytes - total;
ed486911 1057
7e86f2f6 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));
ed486911 1059
1060 if (remaining == 0)
1061 {
1062 if (count < 16)
1063 {
1064 /*
1065 * Read into the raster buffer and then copy...
1066 */
1067
c8fef167 1068 remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize);
ed486911 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
7e86f2f6 1081 count = (*r->iocb)(r->ctx, buf, (size_t)count);
ed486911 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
ed486911 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
07623986 1129 memcpy(buf, r->bufptr, (size_t)count);
ed486911 1130 r->bufptr += count;
1131 remaining -= count;
1132 }
1133 }
1134
1135 return (total);
1136}
1137
1138
ef416fc2 1139/*
1140 * 'cups_raster_update()' - Update the raster header and row count for the
1141 * current page.
1142 */
1143
1144static void
1145cups_raster_update(cups_raster_t *r) /* I - Raster stream */
1146{
f301802f 1147 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 ||
1148 r->header.cupsNumColors == 0)
ef416fc2 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 :
c7017ecc 1161 case CUPS_CSPACE_SW :
ef416fc2 1162 r->header.cupsNumColors = 1;
1163 break;
1164
ef416fc2 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 :
c7017ecc
MS
1170 case CUPS_CSPACE_SRGB :
1171 case CUPS_CSPACE_ADOBERGB :
f301802f 1172 case CUPS_CSPACE_ICC1 :
1173 case CUPS_CSPACE_ICC2 :
ef416fc2 1174 case CUPS_CSPACE_ICC3 :
f301802f 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 :
ef416fc2 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 :
ef416fc2 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;
c7017ecc
MS
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;
ef416fc2 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 /*
ed486911 1247 * Allocate the compression buffer...
ef416fc2 1248 */
1249
ed486911 1250 if (r->compressed)
1251 {
1252 if (r->pixels != NULL)
1253 free(r->pixels);
ef416fc2 1254
ed486911 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 }
ef416fc2 1260}
1261
1262
f7deaa1a 1263/*
1264 * 'cups_raster_write()' - Write a row of compressed raster data...
1265 */
1266
7e86f2f6 1267static ssize_t /* O - Number of bytes written */
f7deaa1a 1268cups_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 */
7e86f2f6 1277 unsigned bpp, /* Bytes per pixel */
1f0275e3 1278 count; /* Count */
f7deaa1a 1279
1280
09a101d6 1281 DEBUG_printf(("cups_raster_write(r=%p, pixels=%p)\n", r, pixels));
f7deaa1a 1282
1283 /*
1284 * Allocate a write buffer as needed...
1285 */
1286
1287 count = r->header.cupsBytesPerLine * 2;
c8fef167 1288 if ((size_t)count > r->bufsize)
f7deaa1a 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;
7e86f2f6 1310 *wptr++ = (unsigned char)(r->count - 1);
f7deaa1a 1311
1312 /*
07ed0e9a 1313 * Write using a modified PackBits compression...
f7deaa1a 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
7e86f2f6 1341 *wptr++ = (unsigned char)(count - 1);
f7deaa1a 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
07ed0e9a 1351 for (count = 1; count < 128 && ptr < plast; count ++, ptr += bpp)
f7deaa1a 1352 if (!memcmp(ptr, ptr + bpp, bpp))
1353 break;
1354
1355 if (ptr >= plast && count < 128)
1356 {
1357 count ++;
1358 ptr += bpp;
1359 }
f14324a7 1360
7e86f2f6 1361 *wptr++ = (unsigned char)(257 - count);
f7deaa1a 1362
1363 count *= bpp;
1364 memcpy(wptr, start, count);
1365 wptr += count;
1366 }
1367 }
1368
7e86f2f6 1369 return (cups_raster_io(r, r->buffer, (size_t)(wptr - r->buffer)));
f7deaa1a 1370}
1371
1372
ef416fc2 1373/*
c8fef167 1374 * 'cups_read_fd()' - Read bytes from a file.
ef416fc2 1375 */
1376
c8fef167
MS
1377static ssize_t /* O - Bytes read or -1 */
1378cups_read_fd(void *ctx, /* I - File descriptor as pointer */
1379 unsigned char *buf, /* I - Buffer for read */
f14324a7 1380 size_t bytes) /* I - Maximum number of bytes to read */
ef416fc2 1381{
c8fef167
MS
1382 int fd = (int)((intptr_t)ctx);
1383 /* File descriptor */
1384 ssize_t count; /* Number of bytes read */
ef416fc2 1385
ef416fc2 1386
a2326b5b
MS
1387#ifdef WIN32 /* Sigh */
1388 while ((count = read(fd, buf, (unsigned)bytes)) < 0)
1389#else
f14324a7 1390 while ((count = read(fd, buf, bytes)) < 0)
a2326b5b 1391#endif /* WIN32 */
f14324a7
MS
1392 if (errno != EINTR && errno != EAGAIN)
1393 return (-1);
ef416fc2 1394
f14324a7 1395 return (count);
ef416fc2 1396}
1397
1398
ed486911 1399/*
1400 * 'cups_swap()' - Swap bytes in raster data...
1401 */
1402
1403static void
1404cups_swap(unsigned char *buf, /* I - Buffer to swap */
7e86f2f6 1405 size_t bytes) /* I - Number of bytes to swap */
ed486911 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
ef416fc2 1425/*
c8fef167 1426 * 'cups_write_fd()' - Write bytes to a file.
ef416fc2 1427 */
1428
c8fef167
MS
1429static ssize_t /* O - Bytes written or -1 */
1430cups_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 */
ef416fc2 1433{
c8fef167
MS
1434 int fd = (int)((intptr_t)ctx);
1435 /* File descriptor */
1436 ssize_t count; /* Number of bytes written */
ef416fc2 1437
ef416fc2 1438
a2326b5b
MS
1439#ifdef WIN32 /* Sigh */
1440 while ((count = write(fd, buf, (unsigned)bytes)) < 0)
1441#else
f14324a7 1442 while ((count = write(fd, buf, bytes)) < 0)
a2326b5b 1443#endif /* WIN32 */
f14324a7
MS
1444 if (errno != EINTR && errno != EAGAIN)
1445 return (-1);
ef416fc2 1446
f14324a7 1447 return (count);
ef416fc2 1448}
1449
1450
1451/*
f2d18633 1452 * End of "$Id$".
ef416fc2 1453 */