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