1 /* 2 * Raster file routines for CUPS. 3 * 4 * Copyright 2007-2016 by Apple Inc. 5 * Copyright 1997-2006 by Easy Software Products. 6 * 7 * This file is part of the CUPS Imaging library. 8 * 9 * These coded instructions, statements, and computer programs are the 10 * property of Apple Inc. and are protected by Federal copyright 11 * law. Distribution and use rights are outlined in the file "LICENSE.txt" 12 * which should have been included with this file. If this file is 13 * missing or damaged, see the license at "http://www.cups.org/". 14 * 15 * This file is subject to the Apple OS-Developed Software exception. 16 */ 17 18 /* 19 * Include necessary headers... 20 */ 21 22 #include <cups/raster-private.h> 23 #ifdef HAVE_STDINT_H 24 # include <stdint.h> 25 #endif /* HAVE_STDINT_H */ 26 27 28 /* 29 * Private structures... 30 */ 31 32 struct _cups_raster_s /**** Raster stream data ****/ 33 { 34 unsigned sync; /* Sync word from start of stream */ 35 void *ctx; /* File descriptor */ 36 cups_raster_iocb_t iocb; /* IO callback */ 37 cups_mode_t mode; /* Read/write mode */ 38 cups_page_header2_t header; /* Raster header for current page */ 39 unsigned rowheight, /* Row height in lines */ 40 count, /* Current row run-length count */ 41 remaining, /* Remaining rows in page image */ 42 bpp; /* Bytes per pixel/color */ 43 unsigned char *pixels, /* Pixels for current row */ 44 *pend, /* End of pixel buffer */ 45 *pcurrent; /* Current byte in pixel buffer */ 46 int compressed, /* Non-zero if data is compressed */ 47 swapped; /* Non-zero if data is byte-swapped */ 48 unsigned char *buffer, /* Read/write buffer */ 49 *bufptr, /* Current (read) position in buffer */ 50 *bufend; /* End of current (read) buffer */ 51 size_t bufsize; /* Buffer size */ 52 #ifdef DEBUG 53 size_t iocount; /* Number of bytes read/written */ 54 #endif /* DEBUG */ 55 unsigned apple_page_count;/* Apple raster page count */ 56 }; 57 58 59 /* 60 * Local functions... 61 */ 62 63 static ssize_t cups_raster_io(cups_raster_t *r, unsigned char *buf, size_t bytes); 64 static unsigned cups_raster_read_header(cups_raster_t *r); 65 static ssize_t cups_raster_read(cups_raster_t *r, unsigned char *buf, 66 size_t bytes); 67 static int cups_raster_update(cups_raster_t *r); 68 static ssize_t cups_raster_write(cups_raster_t *r, 69 const unsigned char *pixels); 70 static ssize_t cups_read_fd(void *ctx, unsigned char *buf, size_t bytes); 71 static void cups_swap(unsigned char *buf, size_t bytes); 72 static ssize_t cups_write_fd(void *ctx, unsigned char *buf, size_t bytes); 73 74 75 /* 76 * 'cupsRasterClose()' - Close a raster stream. 77 * 78 * The file descriptor associated with the raster stream must be closed 79 * separately as needed. 80 */ 81 82 void 83 cupsRasterClose(cups_raster_t *r) /* I - Stream to close */ 84 { 85 if (r != NULL) 86 { 87 if (r->buffer) 88 free(r->buffer); 89 90 if (r->pixels) 91 free(r->pixels); 92 93 free(r); 94 } 95 } 96 97 98 /* 99 * 'cupsRasterInitPWGHeader()' - Initialize a page header for PWG Raster output. 100 * 101 * The "media" argument specifies the media to use. 102 * 103 * The "type" argument specifies a "pwg-raster-document-type-supported" value 104 * that controls the color space and bit depth of the raster data. 105 * 106 * The "xres" and "yres" arguments specify the raster resolution in dots per 107 * inch. 108 * 109 * The "sheet_back" argument specifies a "pwg-raster-document-sheet-back" value 110 * to apply for the back side of a page. Pass @code NULL@ for the front side. 111 * 112 * @since CUPS 2.2/macOS 10.12@ 113 */ 114 115 int /* O - 1 on success, 0 on failure */ 116 cupsRasterInitPWGHeader( 117 cups_page_header2_t *h, /* I - Page header */ 118 pwg_media_t *media, /* I - PWG media information */ 119 const char *type, /* I - PWG raster type string */ 120 int xdpi, /* I - Cross-feed direction (horizontal) resolution */ 121 int ydpi, /* I - Feed direction (vertical) resolution */ 122 const char *sides, /* I - IPP "sides" option value */ 123 const char *sheet_back) /* I - Transform for back side or @code NULL@ for none */ 124 { 125 if (!h || !media || !type || xdpi <= 0 || ydpi <= 0) 126 { 127 _cupsRasterAddError("%s", strerror(EINVAL)); 128 return (0); 129 } 130 131 /* 132 * Initialize the page header... 133 */ 134 135 memset(h, 0, sizeof(cups_page_header2_t)); 136 137 strlcpy(h->cupsPageSizeName, media->pwg, sizeof(h->cupsPageSizeName)); 138 139 h->PageSize[0] = (unsigned)(72 * media->width / 2540); 140 h->PageSize[1] = (unsigned)(72 * media->length / 2540); 141 142 /* This never gets written but is needed for some applications */ 143 h->cupsPageSize[0] = 72.0f * media->width / 2540.0f; 144 h->cupsPageSize[1] = 72.0f * media->length / 2540.0f; 145 146 h->ImagingBoundingBox[2] = h->PageSize[0]; 147 h->ImagingBoundingBox[3] = h->PageSize[1]; 148 149 h->HWResolution[0] = (unsigned)xdpi; 150 h->HWResolution[1] = (unsigned)ydpi; 151 152 h->cupsWidth = (unsigned)(media->width * xdpi / 2540); 153 h->cupsHeight = (unsigned)(media->length * ydpi / 2540); 154 155 if (h->cupsWidth > 0x00ffffff || h->cupsHeight > 0x00ffffff) 156 { 157 _cupsRasterAddError("Raster dimensions too large."); 158 return (0); 159 } 160 161 h->cupsInteger[CUPS_RASTER_PWG_ImageBoxRight] = h->cupsWidth; 162 h->cupsInteger[CUPS_RASTER_PWG_ImageBoxBottom] = h->cupsHeight; 163 164 /* 165 * Colorspace and bytes per line... 166 */ 167 168 if (!strcmp(type, "adobe-rgb_8")) 169 { 170 h->cupsBitsPerColor = 8; 171 h->cupsBitsPerPixel = 24; 172 h->cupsColorSpace = CUPS_CSPACE_ADOBERGB; 173 } 174 else if (!strcmp(type, "adobe-rgb_16")) 175 { 176 h->cupsBitsPerColor = 16; 177 h->cupsBitsPerPixel = 48; 178 h->cupsColorSpace = CUPS_CSPACE_ADOBERGB; 179 } 180 else if (!strcmp(type, "black_1")) 181 { 182 h->cupsBitsPerColor = 1; 183 h->cupsBitsPerPixel = 1; 184 h->cupsColorSpace = CUPS_CSPACE_K; 185 } 186 else if (!strcmp(type, "black_8")) 187 { 188 h->cupsBitsPerColor = 8; 189 h->cupsBitsPerPixel = 8; 190 h->cupsColorSpace = CUPS_CSPACE_K; 191 } 192 else if (!strcmp(type, "black_16")) 193 { 194 h->cupsBitsPerColor = 16; 195 h->cupsBitsPerPixel = 16; 196 h->cupsColorSpace = CUPS_CSPACE_K; 197 } 198 else if (!strcmp(type, "cmyk_8")) 199 { 200 h->cupsBitsPerColor = 8; 201 h->cupsBitsPerPixel = 32; 202 h->cupsColorSpace = CUPS_CSPACE_CMYK; 203 } 204 else if (!strcmp(type, "cmyk_16")) 205 { 206 h->cupsBitsPerColor = 16; 207 h->cupsBitsPerPixel = 64; 208 h->cupsColorSpace = CUPS_CSPACE_CMYK; 209 } 210 else if (!strncmp(type, "device", 6) && type[6] >= '1' && type[6] <= '9') 211 { 212 int ncolors, bits; /* Number of colors and bits */ 213 214 215 if (sscanf(type, "device%d_%d", &ncolors, &bits) != 2 || ncolors > 15 || (bits != 8 && bits != 16)) 216 { 217 _cupsRasterAddError("Unsupported raster type \'%s\'.", type); 218 return (0); 219 } 220 221 h->cupsBitsPerColor = (unsigned)bits; 222 h->cupsBitsPerPixel = (unsigned)(ncolors * bits); 223 h->cupsColorSpace = (cups_cspace_t)(CUPS_CSPACE_DEVICE1 + ncolors - 1); 224 } 225 else if (!strcmp(type, "rgb_8")) 226 { 227 h->cupsBitsPerColor = 8; 228 h->cupsBitsPerPixel = 24; 229 h->cupsColorSpace = CUPS_CSPACE_RGB; 230 } 231 else if (!strcmp(type, "rgb_16")) 232 { 233 h->cupsBitsPerColor = 16; 234 h->cupsBitsPerPixel = 48; 235 h->cupsColorSpace = CUPS_CSPACE_RGB; 236 } 237 else if (!strcmp(type, "sgray_1")) 238 { 239 h->cupsBitsPerColor = 1; 240 h->cupsBitsPerPixel = 1; 241 h->cupsColorSpace = CUPS_CSPACE_SW; 242 } 243 else if (!strcmp(type, "sgray_8")) 244 { 245 h->cupsBitsPerColor = 8; 246 h->cupsBitsPerPixel = 8; 247 h->cupsColorSpace = CUPS_CSPACE_SW; 248 } 249 else if (!strcmp(type, "sgray_16")) 250 { 251 h->cupsBitsPerColor = 16; 252 h->cupsBitsPerPixel = 16; 253 h->cupsColorSpace = CUPS_CSPACE_SW; 254 } 255 else if (!strcmp(type, "srgb_8")) 256 { 257 h->cupsBitsPerColor = 8; 258 h->cupsBitsPerPixel = 24; 259 h->cupsColorSpace = CUPS_CSPACE_SRGB; 260 } 261 else if (!strcmp(type, "srgb_16")) 262 { 263 h->cupsBitsPerColor = 16; 264 h->cupsBitsPerPixel = 48; 265 h->cupsColorSpace = CUPS_CSPACE_SRGB; 266 } 267 else 268 { 269 _cupsRasterAddError("Unsupported raster type \'%s\'.", type); 270 return (0); 271 } 272 273 h->cupsColorOrder = CUPS_ORDER_CHUNKED; 274 h->cupsNumColors = h->cupsBitsPerPixel / h->cupsBitsPerColor; 275 h->cupsBytesPerLine = (h->cupsWidth * h->cupsBitsPerPixel + 7) / 8; 276 277 /* 278 * Duplex support... 279 */ 280 281 h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 1; 282 h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 1; 283 284 if (sides) 285 { 286 if (!strcmp(sides, "two-sided-long-edge")) 287 { 288 h->Duplex = 1; 289 } 290 else if (!strcmp(sides, "two-sided-short-edge")) 291 { 292 h->Duplex = 1; 293 h->Tumble = 1; 294 } 295 else if (strcmp(sides, "one-sided")) 296 { 297 _cupsRasterAddError("Unsupported sides value \'%s\'.", sides); 298 return (0); 299 } 300 301 if (sheet_back) 302 { 303 if (!strcmp(sheet_back, "flipped")) 304 { 305 if (h->Tumble) 306 h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU; 307 else 308 h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 0xffffffffU; 309 } 310 else if (!strcmp(sheet_back, "manual-tumble")) 311 { 312 if (h->Tumble) 313 { 314 h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU; 315 h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 0xffffffffU; 316 } 317 } 318 else if (!strcmp(sheet_back, "rotated")) 319 { 320 if (!h->Tumble) 321 { 322 h->cupsInteger[CUPS_RASTER_PWG_CrossFeedTransform] = 0xffffffffU; 323 h->cupsInteger[CUPS_RASTER_PWG_FeedTransform] = 0xffffffffU; 324 } 325 } 326 else if (strcmp(sheet_back, "normal")) 327 { 328 _cupsRasterAddError("Unsupported sheet_back value \'%s\'.", sheet_back); 329 return (0); 330 } 331 } 332 } 333 334 return (1); 335 } 336 337 338 /* 339 * 'cupsRasterOpen()' - Open a raster stream using a file descriptor. 340 * 341 * This function associates a raster stream with the given file descriptor. 342 * For most printer driver filters, "fd" will be 0 (stdin). For most raster 343 * image processor (RIP) filters that generate raster data, "fd" will be 1 344 * (stdout). 345 * 346 * When writing raster data, the @code CUPS_RASTER_WRITE@, 347 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can 348 * be used - compressed and PWG output is generally 25-50% smaller but adds a 349 * 100-300% execution time overhead. 350 */ 351 352 cups_raster_t * /* O - New stream */ 353 cupsRasterOpen(int fd, /* I - File descriptor */ 354 cups_mode_t mode) /* I - Mode - @code CUPS_RASTER_READ@, 355 @code CUPS_RASTER_WRITE@, 356 @code CUPS_RASTER_WRITE_COMPRESSED@, 357 or @code CUPS_RASTER_WRITE_PWG@ */ 358 { 359 if (mode == CUPS_RASTER_READ) 360 return (cupsRasterOpenIO(cups_read_fd, (void *)((intptr_t)fd), mode)); 361 else 362 return (cupsRasterOpenIO(cups_write_fd, (void *)((intptr_t)fd), mode)); 363 } 364 365 366 /* 367 * 'cupsRasterOpenIO()' - Open a raster stream using a callback function. 368 * 369 * This function associates a raster stream with the given callback function and 370 * context pointer. 371 * 372 * When writing raster data, the @code CUPS_RASTER_WRITE@, 373 * @code CUPS_RASTER_WRITE_COMPRESS@, or @code CUPS_RASTER_WRITE_PWG@ mode can 374 * be used - compressed and PWG output is generally 25-50% smaller but adds a 375 * 100-300% execution time overhead. 376 */ 377 378 cups_raster_t * /* O - New stream */ 379 cupsRasterOpenIO( 380 cups_raster_iocb_t iocb, /* I - Read/write callback */ 381 void *ctx, /* I - Context pointer for callback */ 382 cups_mode_t mode) /* I - Mode - @code CUPS_RASTER_READ@, 383 @code CUPS_RASTER_WRITE@, 384 @code CUPS_RASTER_WRITE_COMPRESSED@, 385 or @code CUPS_RASTER_WRITE_PWG@ */ 386 { 387 cups_raster_t *r; /* New stream */ 388 389 390 _cupsRasterClearError(); 391 392 if ((r = calloc(sizeof(cups_raster_t), 1)) == NULL) 393 { 394 _cupsRasterAddError("Unable to allocate memory for raster stream: %s\n", 395 strerror(errno)); 396 return (NULL); 397 } 398 399 r->ctx = ctx; 400 r->iocb = iocb; 401 r->mode = mode; 402 403 if (mode == CUPS_RASTER_READ) 404 { 405 /* 406 * Open for read - get sync word... 407 */ 408 409 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) != 410 sizeof(r->sync)) 411 { 412 _cupsRasterAddError("Unable to read header from raster stream: %s\n", 413 strerror(errno)); 414 free(r); 415 return (NULL); 416 } 417 418 if (r->sync != CUPS_RASTER_SYNC && 419 r->sync != CUPS_RASTER_REVSYNC && 420 r->sync != CUPS_RASTER_SYNCv1 && 421 r->sync != CUPS_RASTER_REVSYNCv1 && 422 r->sync != CUPS_RASTER_SYNCv2 && 423 r->sync != CUPS_RASTER_REVSYNCv2 && 424 r->sync != CUPS_RASTER_SYNCapple && 425 r->sync != CUPS_RASTER_REVSYNCapple) 426 { 427 _cupsRasterAddError("Unknown raster format %08x!\n", r->sync); 428 free(r); 429 return (NULL); 430 } 431 432 if (r->sync == CUPS_RASTER_SYNCv2 || 433 r->sync == CUPS_RASTER_REVSYNCv2 || 434 r->sync == CUPS_RASTER_SYNCapple || 435 r->sync == CUPS_RASTER_REVSYNCapple) 436 r->compressed = 1; 437 438 if (r->sync == CUPS_RASTER_REVSYNC || 439 r->sync == CUPS_RASTER_REVSYNCv1 || 440 r->sync == CUPS_RASTER_REVSYNCv2 || 441 r->sync == CUPS_RASTER_REVSYNCapple) 442 r->swapped = 1; 443 444 if (r->sync == CUPS_RASTER_SYNCapple || 445 r->sync == CUPS_RASTER_REVSYNCapple) 446 { 447 unsigned char header[8]; /* File header */ 448 449 if (cups_raster_io(r, (unsigned char *)header, sizeof(header)) != 450 sizeof(header)) 451 { 452 _cupsRasterAddError("Unable to read header from raster stream: %s\n", 453 strerror(errno)); 454 free(r); 455 return (NULL); 456 } 457 458 } 459 460 DEBUG_printf(("1cupsRasterOpenIO: r->swapped=%d, r->sync=%08x\n", r->swapped, r->sync)); 461 } 462 else 463 { 464 /* 465 * Open for write - put sync word... 466 */ 467 468 switch (mode) 469 { 470 default : 471 case CUPS_RASTER_WRITE : 472 r->sync = CUPS_RASTER_SYNC; 473 break; 474 475 case CUPS_RASTER_WRITE_COMPRESSED : 476 r->compressed = 1; 477 r->sync = CUPS_RASTER_SYNCv2; 478 break; 479 480 case CUPS_RASTER_WRITE_PWG : 481 r->compressed = 1; 482 r->sync = htonl(CUPS_RASTER_SYNC_PWG); 483 r->swapped = r->sync != CUPS_RASTER_SYNC_PWG; 484 break; 485 486 case CUPS_RASTER_WRITE_APPLE : 487 r->compressed = 1; 488 r->sync = htonl(CUPS_RASTER_SYNCapple); 489 r->swapped = r->sync != CUPS_RASTER_SYNCapple; 490 r->apple_page_count = 0xffffffffU; 491 break; 492 } 493 494 if (cups_raster_io(r, (unsigned char *)&(r->sync), sizeof(r->sync)) < (ssize_t)sizeof(r->sync)) 495 { 496 _cupsRasterAddError("Unable to write raster stream header: %s\n", 497 strerror(errno)); 498 free(r); 499 return (NULL); 500 } 501 } 502 503 return (r); 504 } 505 506 507 /* 508 * 'cupsRasterReadHeader()' - Read a raster page header and store it in a 509 * version 1 page header structure. 510 * 511 * This function is deprecated. Use @link cupsRasterReadHeader2@ instead. 512 * 513 * Version 1 page headers were used in CUPS 1.0 and 1.1 and contain a subset 514 * of the version 2 page header data. This function handles reading version 2 515 * page headers and copying only the version 1 data into the provided buffer. 516 * 517 * @deprecated@ 518 */ 519 520 unsigned /* O - 1 on success, 0 on failure/end-of-file */ 521 cupsRasterReadHeader( 522 cups_raster_t *r, /* I - Raster stream */ 523 cups_page_header_t *h) /* I - Pointer to header data */ 524 { 525 /* 526 * Get the raster header... 527 */ 528 529 if (!cups_raster_read_header(r)) 530 { 531 memset(h, 0, sizeof(cups_page_header_t)); 532 return (0); 533 } 534 535 /* 536 * Copy the header to the user-supplied buffer... 537 */ 538 539 memcpy(h, &(r->header), sizeof(cups_page_header_t)); 540 541 return (1); 542 } 543 544 545 /* 546 * 'cupsRasterReadHeader2()' - Read a raster page header and store it in a 547 * version 2 page header structure. 548 * 549 * @since CUPS 1.2/macOS 10.5@ 550 */ 551 552 unsigned /* O - 1 on success, 0 on failure/end-of-file */ 553 cupsRasterReadHeader2( 554 cups_raster_t *r, /* I - Raster stream */ 555 cups_page_header2_t *h) /* I - Pointer to header data */ 556 { 557 /* 558 * Get the raster header... 559 */ 560 561 DEBUG_printf(("cupsRasterReadHeader2(r=%p, h=%p)", (void *)r, (void *)h)); 562 563 if (!cups_raster_read_header(r)) 564 { 565 memset(h, 0, sizeof(cups_page_header2_t)); 566 return (0); 567 } 568 569 /* 570 * Copy the header to the user-supplied buffer... 571 */ 572 573 memcpy(h, &(r->header), sizeof(cups_page_header2_t)); 574 575 return (1); 576 } 577 578 579 /* 580 * 'cupsRasterReadPixels()' - Read raster pixels. 581 * 582 * For best performance, filters should read one or more whole lines. 583 * The "cupsBytesPerLine" value from the page header can be used to allocate 584 * the line buffer and as the number of bytes to read. 585 */ 586 587 unsigned /* O - Number of bytes read */ 588 cupsRasterReadPixels(cups_raster_t *r, /* I - Raster stream */ 589 unsigned char *p, /* I - Pointer to pixel buffer */ 590 unsigned len) /* I - Number of bytes to read */ 591 { 592 ssize_t bytes; /* Bytes read */ 593 unsigned cupsBytesPerLine; /* cupsBytesPerLine value */ 594 unsigned remaining; /* Bytes remaining */ 595 unsigned char *ptr, /* Pointer to read buffer */ 596 byte, /* Byte from file */ 597 *temp; /* Pointer into buffer */ 598 unsigned count; /* Repetition count */ 599 600 601 DEBUG_printf(("cupsRasterReadPixels(r=%p, p=%p, len=%u)", (void *)r, (void *)p, len)); 602 603 if (r == NULL || r->mode != CUPS_RASTER_READ || r->remaining == 0 || 604 r->header.cupsBytesPerLine == 0) 605 { 606 DEBUG_puts("1cupsRasterReadPixels: Returning 0."); 607 return (0); 608 } 609 610 DEBUG_printf(("1cupsRasterReadPixels: compressed=%d, remaining=%u", r->compressed, r->remaining)); 611 612 if (!r->compressed) 613 { 614 /* 615 * Read without compression... 616 */ 617 618 r->remaining -= len / r->header.cupsBytesPerLine; 619 620 if (cups_raster_io(r, p, len) < (ssize_t)len) 621 { 622 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0."); 623 return (0); 624 } 625 626 /* 627 * Swap bytes as needed... 628 */ 629 630 if (r->swapped && 631 (r->header.cupsBitsPerColor == 16 || 632 r->header.cupsBitsPerPixel == 12 || 633 r->header.cupsBitsPerPixel == 16)) 634 cups_swap(p, len); 635 636 /* 637 * Return... 638 */ 639 640 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len)); 641 642 return (len); 643 } 644 645 /* 646 * Read compressed data... 647 */ 648 649 remaining = len; 650 cupsBytesPerLine = r->header.cupsBytesPerLine; 651 652 while (remaining > 0 && r->remaining > 0) 653 { 654 if (r->count == 0) 655 { 656 /* 657 * Need to read a new row... 658 */ 659 660 if (remaining == cupsBytesPerLine) 661 ptr = p; 662 else 663 ptr = r->pixels; 664 665 /* 666 * Read using a modified PackBits compression... 667 */ 668 669 if (!cups_raster_read(r, &byte, 1)) 670 { 671 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0."); 672 return (0); 673 } 674 675 r->count = (unsigned)byte + 1; 676 677 if (r->count > 1) 678 ptr = r->pixels; 679 680 temp = ptr; 681 bytes = (ssize_t)cupsBytesPerLine; 682 683 while (bytes > 0) 684 { 685 /* 686 * Get a new repeat count... 687 */ 688 689 if (!cups_raster_read(r, &byte, 1)) 690 { 691 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0."); 692 return (0); 693 } 694 695 if (byte == 128) 696 { 697 /* 698 * Clear to end of line... 699 */ 700 701 switch (r->header.cupsColorSpace) 702 { 703 case CUPS_CSPACE_W : 704 case CUPS_CSPACE_RGB : 705 case CUPS_CSPACE_SW : 706 case CUPS_CSPACE_SRGB : 707 case CUPS_CSPACE_RGBW : 708 case CUPS_CSPACE_ADOBERGB : 709 memset(temp, 0xff, (size_t)bytes); 710 break; 711 default : 712 memset(temp, 0x00, (size_t)bytes); 713 break; 714 } 715 716 temp += bytes; 717 bytes = 0; 718 } 719 else if (byte & 128) 720 { 721 /* 722 * Copy N literal pixels... 723 */ 724 725 count = (unsigned)(257 - byte) * r->bpp; 726 727 if (count > (unsigned)bytes) 728 count = (unsigned)bytes; 729 730 if (!cups_raster_read(r, temp, count)) 731 { 732 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0."); 733 return (0); 734 } 735 736 temp += count; 737 bytes -= (ssize_t)count; 738 } 739 else 740 { 741 /* 742 * Repeat the next N bytes... 743 */ 744 745 count = ((unsigned)byte + 1) * r->bpp; 746 if (count > (unsigned)bytes) 747 count = (unsigned)bytes; 748 749 if (count < r->bpp) 750 break; 751 752 bytes -= (ssize_t)count; 753 754 if (!cups_raster_read(r, temp, r->bpp)) 755 { 756 DEBUG_puts("1cupsRasterReadPixels: Read error, returning 0."); 757 return (0); 758 } 759 760 temp += r->bpp; 761 count -= r->bpp; 762 763 while (count > 0) 764 { 765 memcpy(temp, temp - r->bpp, r->bpp); 766 temp += r->bpp; 767 count -= r->bpp; 768 } 769 } 770 } 771 772 /* 773 * Swap bytes as needed... 774 */ 775 776 if ((r->header.cupsBitsPerColor == 16 || 777 r->header.cupsBitsPerPixel == 12 || 778 r->header.cupsBitsPerPixel == 16) && 779 r->swapped) 780 cups_swap(ptr, (size_t)bytes); 781 782 /* 783 * Update pointers... 784 */ 785 786 if (remaining >= cupsBytesPerLine) 787 { 788 bytes = (ssize_t)cupsBytesPerLine; 789 r->pcurrent = r->pixels; 790 r->count --; 791 r->remaining --; 792 } 793 else 794 { 795 bytes = (ssize_t)remaining; 796 r->pcurrent = r->pixels + bytes; 797 } 798 799 /* 800 * Copy data as needed... 801 */ 802 803 if (ptr != p) 804 memcpy(p, ptr, (size_t)bytes); 805 } 806 else 807 { 808 /* 809 * Copy fragment from buffer... 810 */ 811 812 if ((unsigned)(bytes = (int)(r->pend - r->pcurrent)) > remaining) 813 bytes = (ssize_t)remaining; 814 815 memcpy(p, r->pcurrent, (size_t)bytes); 816 r->pcurrent += bytes; 817 818 if (r->pcurrent >= r->pend) 819 { 820 r->pcurrent = r->pixels; 821 r->count --; 822 r->remaining --; 823 } 824 } 825 826 remaining -= (unsigned)bytes; 827 p += bytes; 828 } 829 830 DEBUG_printf(("1cupsRasterReadPixels: Returning %u", len)); 831 832 return (len); 833 } 834 835 836 /* 837 * 'cupsRasterWriteHeader()' - Write a raster page header from a version 1 page 838 * header structure. 839 * 840 * This function is deprecated. Use @link cupsRasterWriteHeader2@ instead. 841 * 842 * @deprecated@ 843 */ 844 845 unsigned /* O - 1 on success, 0 on failure */ 846 cupsRasterWriteHeader( 847 cups_raster_t *r, /* I - Raster stream */ 848 cups_page_header_t *h) /* I - Raster page header */ 849 { 850 if (r == NULL || r->mode == CUPS_RASTER_READ) 851 return (0); 852 853 /* 854 * Make a copy of the header, and compute the number of raster 855 * lines in the page image... 856 */ 857 858 memset(&(r->header), 0, sizeof(r->header)); 859 memcpy(&(r->header), h, sizeof(cups_page_header_t)); 860 861 if (!cups_raster_update(r)) 862 return (0); 863 864 /* 865 * Write the raster header... 866 */ 867 868 if (r->mode == CUPS_RASTER_WRITE_PWG) 869 { 870 /* 871 * PWG raster data is always network byte order with much of the page header 872 * zeroed. 873 */ 874 875 cups_page_header2_t fh; /* File page header */ 876 877 memset(&fh, 0, sizeof(fh)); 878 879 strlcpy(fh.MediaClass, "PwgRaster", sizeof(fh.MediaClass)); 880 /* PwgRaster */ 881 strlcpy(fh.MediaColor, r->header.MediaColor, sizeof(fh.MediaColor)); 882 strlcpy(fh.MediaType, r->header.MediaType, sizeof(fh.MediaType)); 883 strlcpy(fh.OutputType, r->header.OutputType, sizeof(fh.OutputType)); 884 /* PrintContentType */ 885 886 fh.CutMedia = htonl(r->header.CutMedia); 887 fh.Duplex = htonl(r->header.Duplex); 888 fh.HWResolution[0] = htonl(r->header.HWResolution[0]); 889 fh.HWResolution[1] = htonl(r->header.HWResolution[1]); 890 fh.ImagingBoundingBox[0] = htonl(r->header.ImagingBoundingBox[0]); 891 fh.ImagingBoundingBox[1] = htonl(r->header.ImagingBoundingBox[1]); 892 fh.ImagingBoundingBox[2] = htonl(r->header.ImagingBoundingBox[2]); 893 fh.ImagingBoundingBox[3] = htonl(r->header.ImagingBoundingBox[3]); 894 fh.InsertSheet = htonl(r->header.InsertSheet); 895 fh.Jog = htonl(r->header.Jog); 896 fh.LeadingEdge = htonl(r->header.LeadingEdge); 897 fh.ManualFeed = htonl(r->header.ManualFeed); 898 fh.MediaPosition = htonl(r->header.MediaPosition); 899 fh.MediaWeight = htonl(r->header.MediaWeight); 900 fh.NumCopies = htonl(r->header.NumCopies); 901 fh.Orientation = htonl(r->header.Orientation); 902 fh.PageSize[0] = htonl(r->header.PageSize[0]); 903 fh.PageSize[1] = htonl(r->header.PageSize[1]); 904 fh.Tumble = htonl(r->header.Tumble); 905 fh.cupsWidth = htonl(r->header.cupsWidth); 906 fh.cupsHeight = htonl(r->header.cupsHeight); 907 fh.cupsBitsPerColor = htonl(r->header.cupsBitsPerColor); 908 fh.cupsBitsPerPixel = htonl(r->header.cupsBitsPerPixel); 909 fh.cupsBytesPerLine = htonl(r->header.cupsBytesPerLine); 910 fh.cupsColorOrder = htonl(r->header.cupsColorOrder); 911 fh.cupsColorSpace = htonl(r->header.cupsColorSpace); 912 fh.cupsNumColors = htonl(r->header.cupsNumColors); 913 fh.cupsInteger[0] = htonl(r->header.cupsInteger[0]); 914 /* TotalPageCount */ 915 fh.cupsInteger[1] = htonl(r->header.cupsInteger[1]); 916 /* CrossFeedTransform */ 917 fh.cupsInteger[2] = htonl(r->header.cupsInteger[2]); 918 /* FeedTransform */ 919 fh.cupsInteger[3] = htonl(r->header.cupsInteger[3]); 920 /* ImageBoxLeft */ 921 fh.cupsInteger[4] = htonl(r->header.cupsInteger[4]); 922 /* ImageBoxTop */ 923 fh.cupsInteger[5] = htonl(r->header.cupsInteger[5]); 924 /* ImageBoxRight */ 925 fh.cupsInteger[6] = htonl(r->header.cupsInteger[6]); 926 /* ImageBoxBottom */ 927 fh.cupsInteger[7] = htonl(r->header.cupsInteger[7]); 928 /* BlackPrimary */ 929 fh.cupsInteger[8] = htonl(r->header.cupsInteger[8]); 930 /* PrintQuality */ 931 fh.cupsInteger[14] = htonl(r->header.cupsInteger[14]); 932 /* VendorIdentifier */ 933 fh.cupsInteger[15] = htonl(r->header.cupsInteger[15]); 934 /* VendorLength */ 935 936 void *dst = fh.cupsReal; /* Bypass bogus compiler warning */ 937 void *src = r->header.cupsReal; 938 memcpy(dst, src, sizeof(fh.cupsReal) + sizeof(fh.cupsString)); 939 /* VendorData */ 940 941 strlcpy(fh.cupsRenderingIntent, r->header.cupsRenderingIntent, 942 sizeof(fh.cupsRenderingIntent)); 943 strlcpy(fh.cupsPageSizeName, r->header.cupsPageSizeName, 944 sizeof(fh.cupsPageSizeName)); 945 946 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh)); 947 } 948 else if (r->mode == CUPS_RASTER_WRITE_APPLE) 949 { 950 /* 951 * Raw raster data is always network byte order with most of the page header 952 * zeroed. 953 */ 954 955 unsigned char appleheader[32]; /* Raw page header */ 956 957 if (r->apple_page_count == 0xffffffffU) 958 { 959 /* 960 * Write raw page count from raster page header... 961 */ 962 963 r->apple_page_count = r->header.cupsInteger[0]; 964 965 appleheader[0] = 'A'; 966 appleheader[1] = 'S'; 967 appleheader[2] = 'T'; 968 appleheader[3] = 0; 969 appleheader[4] = (unsigned char)(r->apple_page_count >> 24); 970 appleheader[5] = (unsigned char)(r->apple_page_count >> 16); 971 appleheader[6] = (unsigned char)(r->apple_page_count >> 8); 972 appleheader[7] = (unsigned char)(r->apple_page_count); 973 974 if (cups_raster_io(r, appleheader, 8) != 8) 975 return (0); 976 } 977 978 memset(appleheader, 0, sizeof(appleheader)); 979 980 appleheader[0] = (unsigned char)r->header.cupsBitsPerPixel; 981 appleheader[1] = r->header.cupsColorSpace == CUPS_CSPACE_SRGB ? 1 : 982 r->header.cupsColorSpace == CUPS_CSPACE_RGBW ? 2 : 983 r->header.cupsColorSpace == CUPS_CSPACE_ADOBERGB ? 3 : 984 r->header.cupsColorSpace == CUPS_CSPACE_W ? 4 : 985 r->header.cupsColorSpace == CUPS_CSPACE_RGB ? 5 : 986 r->header.cupsColorSpace == CUPS_CSPACE_CMYK ? 6 : 0; 987 appleheader[12] = (unsigned char)(r->header.cupsWidth >> 24); 988 appleheader[13] = (unsigned char)(r->header.cupsWidth >> 16); 989 appleheader[14] = (unsigned char)(r->header.cupsWidth >> 8); 990 appleheader[15] = (unsigned char)(r->header.cupsWidth); 991 appleheader[16] = (unsigned char)(r->header.cupsHeight >> 24); 992 appleheader[17] = (unsigned char)(r->header.cupsHeight >> 16); 993 appleheader[18] = (unsigned char)(r->header.cupsHeight >> 8); 994 appleheader[19] = (unsigned char)(r->header.cupsHeight); 995 appleheader[20] = (unsigned char)(r->header.HWResolution[0] >> 24); 996 appleheader[21] = (unsigned char)(r->header.HWResolution[0] >> 16); 997 appleheader[22] = (unsigned char)(r->header.HWResolution[0] >> 8); 998 appleheader[23] = (unsigned char)(r->header.HWResolution[0]); 999 1000 return (cups_raster_io(r, appleheader, sizeof(appleheader)) == sizeof(appleheader)); 1001 } 1002 else 1003 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header)) 1004 == sizeof(r->header)); 1005 } 1006 1007 1008 /* 1009 * 'cupsRasterWriteHeader2()' - Write a raster page header from a version 2 1010 * page header structure. 1011 * 1012 * The page header can be initialized using @link cupsRasterInitPWGHeader@. 1013 * 1014 * @since CUPS 1.2/macOS 10.5@ 1015 */ 1016 1017 unsigned /* O - 1 on success, 0 on failure */ 1018 cupsRasterWriteHeader2( 1019 cups_raster_t *r, /* I - Raster stream */ 1020 cups_page_header2_t *h) /* I - Raster page header */ 1021 { 1022 if (r == NULL || r->mode == CUPS_RASTER_READ) 1023 return (0); 1024 1025 /* 1026 * Make a copy of the header, and compute the number of raster 1027 * lines in the page image... 1028 */ 1029 1030 memcpy(&(r->header), h, sizeof(cups_page_header2_t)); 1031 1032 if (!cups_raster_update(r)) 1033 return (0); 1034 1035 if (r->mode == CUPS_RASTER_WRITE_APPLE) 1036 { 1037 r->rowheight = h->HWResolution[0] / h->HWResolution[1]; 1038 1039 if (h->HWResolution[0] != (r->rowheight * h->HWResolution[1])) 1040 return (0); 1041 } 1042 else 1043 r->rowheight = 1; 1044 1045 /* 1046 * Write the raster header... 1047 */ 1048 1049 if (r->mode == CUPS_RASTER_WRITE_PWG) 1050 { 1051 /* 1052 * PWG raster data is always network byte order with most of the page header 1053 * zeroed. 1054 */ 1055 1056 cups_page_header2_t fh; /* File page header */ 1057 1058 memset(&fh, 0, sizeof(fh)); 1059 strlcpy(fh.MediaClass, "PwgRaster", sizeof(fh.MediaClass)); 1060 strlcpy(fh.MediaColor, r->header.MediaColor, sizeof(fh.MediaColor)); 1061 strlcpy(fh.MediaType, r->header.MediaType, sizeof(fh.MediaType)); 1062 strlcpy(fh.OutputType, r->header.OutputType, sizeof(fh.OutputType)); 1063 strlcpy(fh.cupsRenderingIntent, r->header.cupsRenderingIntent, 1064 sizeof(fh.cupsRenderingIntent)); 1065 strlcpy(fh.cupsPageSizeName, r->header.cupsPageSizeName, 1066 sizeof(fh.cupsPageSizeName)); 1067 1068 fh.CutMedia = htonl(r->header.CutMedia); 1069 fh.Duplex = htonl(r->header.Duplex); 1070 fh.HWResolution[0] = htonl(r->header.HWResolution[0]); 1071 fh.HWResolution[1] = htonl(r->header.HWResolution[1]); 1072 fh.ImagingBoundingBox[0] = htonl(r->header.ImagingBoundingBox[0]); 1073 fh.ImagingBoundingBox[1] = htonl(r->header.ImagingBoundingBox[1]); 1074 fh.ImagingBoundingBox[2] = htonl(r->header.ImagingBoundingBox[2]); 1075 fh.ImagingBoundingBox[3] = htonl(r->header.ImagingBoundingBox[3]); 1076 fh.InsertSheet = htonl(r->header.InsertSheet); 1077 fh.Jog = htonl(r->header.Jog); 1078 fh.LeadingEdge = htonl(r->header.LeadingEdge); 1079 fh.ManualFeed = htonl(r->header.ManualFeed); 1080 fh.MediaPosition = htonl(r->header.MediaPosition); 1081 fh.MediaWeight = htonl(r->header.MediaWeight); 1082 fh.NumCopies = htonl(r->header.NumCopies); 1083 fh.Orientation = htonl(r->header.Orientation); 1084 fh.PageSize[0] = htonl(r->header.PageSize[0]); 1085 fh.PageSize[1] = htonl(r->header.PageSize[1]); 1086 fh.Tumble = htonl(r->header.Tumble); 1087 fh.cupsWidth = htonl(r->header.cupsWidth); 1088 fh.cupsHeight = htonl(r->header.cupsHeight); 1089 fh.cupsBitsPerColor = htonl(r->header.cupsBitsPerColor); 1090 fh.cupsBitsPerPixel = htonl(r->header.cupsBitsPerPixel); 1091 fh.cupsBytesPerLine = htonl(r->header.cupsBytesPerLine); 1092 fh.cupsColorOrder = htonl(r->header.cupsColorOrder); 1093 fh.cupsColorSpace = htonl(r->header.cupsColorSpace); 1094 fh.cupsNumColors = htonl(r->header.cupsNumColors); 1095 fh.cupsInteger[0] = htonl(r->header.cupsInteger[0]); 1096 fh.cupsInteger[1] = htonl(r->header.cupsInteger[1]); 1097 fh.cupsInteger[2] = htonl(r->header.cupsInteger[2]); 1098 fh.cupsInteger[3] = htonl((unsigned)(r->header.cupsImagingBBox[0] * r->header.HWResolution[0] / 72.0)); 1099 fh.cupsInteger[4] = htonl((unsigned)(r->header.cupsImagingBBox[1] * r->header.HWResolution[1] / 72.0)); 1100 fh.cupsInteger[5] = htonl((unsigned)(r->header.cupsImagingBBox[2] * r->header.HWResolution[0] / 72.0)); 1101 fh.cupsInteger[6] = htonl((unsigned)(r->header.cupsImagingBBox[3] * r->header.HWResolution[1] / 72.0)); 1102 fh.cupsInteger[7] = htonl(0xffffff); 1103 1104 return (cups_raster_io(r, (unsigned char *)&fh, sizeof(fh)) == sizeof(fh)); 1105 } 1106 else if (r->mode == CUPS_RASTER_WRITE_APPLE) 1107 { 1108 /* 1109 * Raw raster data is always network byte order with most of the page header 1110 * zeroed. 1111 */ 1112 1113 unsigned char appleheader[32]; /* Raw page header */ 1114 unsigned height = r->header.cupsHeight * r->rowheight; 1115 /* Computed page height */ 1116 1117 if (r->apple_page_count == 0xffffffffU) 1118 { 1119 /* 1120 * Write raw page count from raster page header... 1121 */ 1122 1123 r->apple_page_count = r->header.cupsInteger[0]; 1124 1125 appleheader[0] = 'A'; 1126 appleheader[1] = 'S'; 1127 appleheader[2] = 'T'; 1128 appleheader[3] = 0; 1129 appleheader[4] = (unsigned char)(r->apple_page_count >> 24); 1130 appleheader[5] = (unsigned char)(r->apple_page_count >> 16); 1131 appleheader[6] = (unsigned char)(r->apple_page_count >> 8); 1132 appleheader[7] = (unsigned char)(r->apple_page_count); 1133 1134 if (cups_raster_io(r, appleheader, 8) != 8) 1135 return (0); 1136 } 1137 1138 memset(appleheader, 0, sizeof(appleheader)); 1139 1140 appleheader[0] = (unsigned char)r->header.cupsBitsPerPixel; 1141 appleheader[1] = r->header.cupsColorSpace == CUPS_CSPACE_SRGB ? 1 : 1142 r->header.cupsColorSpace == CUPS_CSPACE_RGBW ? 2 : 1143 r->header.cupsColorSpace == CUPS_CSPACE_ADOBERGB ? 3 : 1144 r->header.cupsColorSpace == CUPS_CSPACE_W ? 4 : 1145 r->header.cupsColorSpace == CUPS_CSPACE_RGB ? 5 : 1146 r->header.cupsColorSpace == CUPS_CSPACE_CMYK ? 6 : 0; 1147 appleheader[12] = (unsigned char)(r->header.cupsWidth >> 24); 1148 appleheader[13] = (unsigned char)(r->header.cupsWidth >> 16); 1149 appleheader[14] = (unsigned char)(r->header.cupsWidth >> 8); 1150 appleheader[15] = (unsigned char)(r->header.cupsWidth); 1151 appleheader[16] = (unsigned char)(height >> 24); 1152 appleheader[17] = (unsigned char)(height >> 16); 1153 appleheader[18] = (unsigned char)(height >> 8); 1154 appleheader[19] = (unsigned char)(height); 1155 appleheader[20] = (unsigned char)(r->header.HWResolution[0] >> 24); 1156 appleheader[21] = (unsigned char)(r->header.HWResolution[0] >> 16); 1157 appleheader[22] = (unsigned char)(r->header.HWResolution[0] >> 8); 1158 appleheader[23] = (unsigned char)(r->header.HWResolution[0]); 1159 1160 return (cups_raster_io(r, appleheader, sizeof(appleheader)) == sizeof(appleheader)); 1161 } 1162 else 1163 return (cups_raster_io(r, (unsigned char *)&(r->header), sizeof(r->header)) 1164 == sizeof(r->header)); 1165 } 1166 1167 1168 /* 1169 * 'cupsRasterWritePixels()' - Write raster pixels. 1170 * 1171 * For best performance, filters should write one or more whole lines. 1172 * The "cupsBytesPerLine" value from the page header can be used to allocate 1173 * the line buffer and as the number of bytes to write. 1174 */ 1175 1176 unsigned /* O - Number of bytes written */ 1177 cupsRasterWritePixels(cups_raster_t *r, /* I - Raster stream */ 1178 unsigned char *p, /* I - Bytes to write */ 1179 unsigned len)/* I - Number of bytes to write */ 1180 { 1181 ssize_t bytes; /* Bytes read */ 1182 unsigned remaining; /* Bytes remaining */ 1183 1184 1185 DEBUG_printf(("cupsRasterWritePixels(r=%p, p=%p, len=%u), remaining=%u", (void *)r, (void *)p, len, r->remaining)); 1186 1187 if (r == NULL || r->mode == CUPS_RASTER_READ || r->remaining == 0) 1188 return (0); 1189 1190 if (!r->compressed) 1191 { 1192 /* 1193 * Without compression, just write the raster data raw unless the data needs 1194 * to be swapped... 1195 */ 1196 1197 r->remaining -= len / r->header.cupsBytesPerLine; 1198 1199 if (r->swapped && 1200 (r->header.cupsBitsPerColor == 16 || 1201 r->header.cupsBitsPerPixel == 12 || 1202 r->header.cupsBitsPerPixel == 16)) 1203 { 1204 unsigned char *bufptr; /* Pointer into write buffer */ 1205 unsigned count; /* Remaining count */ 1206 1207 /* 1208 * Allocate a write buffer as needed... 1209 */ 1210 1211 if ((size_t)len > r->bufsize) 1212 { 1213 if (r->buffer) 1214 bufptr = realloc(r->buffer, len); 1215 else 1216 bufptr = malloc(len); 1217 1218 if (!bufptr) 1219 return (0); 1220 1221 r->buffer = bufptr; 1222 r->bufsize = len; 1223 } 1224 1225 /* 1226 * Byte swap the pixels... 1227 */ 1228 1229 for (bufptr = r->buffer, count = len; count > 1; count -= 2, bufptr += 2) 1230 { 1231 bufptr[1] = *p++; 1232 bufptr[0] = *p++; 1233 } 1234 1235 if (count) /* This should never happen... */ 1236 *bufptr = *p; 1237 1238 /* 1239 * Write the byte-swapped buffer... 1240 */ 1241 1242 bytes = cups_raster_io(r, r->buffer, len); 1243 } 1244 else 1245 bytes = cups_raster_io(r, p, len); 1246 1247 if (bytes < len) 1248 return (0); 1249 else 1250 return (len); 1251 } 1252 1253 /* 1254 * Otherwise, compress each line... 1255 */ 1256 1257 for (remaining = len; remaining > 0; remaining -= (unsigned)bytes, p += bytes) 1258 { 1259 /* 1260 * Figure out the number of remaining bytes on the current line... 1261 */ 1262 1263 if ((bytes = (ssize_t)remaining) > (ssize_t)(r->pend - r->pcurrent)) 1264 bytes = (ssize_t)(r->pend - r->pcurrent); 1265 1266 if (r->count > 0) 1267 { 1268 /* 1269 * Check to see if this line is the same as the previous line... 1270 */ 1271 1272 if (memcmp(p, r->pcurrent, (size_t)bytes)) 1273 { 1274 if (cups_raster_write(r, r->pixels) <= 0) 1275 return (0); 1276 1277 r->count = 0; 1278 } 1279 else 1280 { 1281 /* 1282 * Mark more bytes as the same... 1283 */ 1284 1285 r->pcurrent += bytes; 1286 1287 if (r->pcurrent >= r->pend) 1288 { 1289 /* 1290 * Increase the repeat count... 1291 */ 1292 1293 r->count += r->rowheight; 1294 r->pcurrent = r->pixels; 1295 1296 /* 1297 * Flush out this line if it is the last one... 1298 */ 1299 1300 r->remaining --; 1301 1302 if (r->remaining == 0) 1303 { 1304 if (cups_raster_write(r, r->pixels) <= 0) 1305 return (0); 1306 else 1307 return (len); 1308 } 1309 else if (r->count > (256 - r->rowheight)) 1310 { 1311 if (cups_raster_write(r, r->pixels) <= 0) 1312 return (0); 1313 1314 r->count = 0; 1315 } 1316 } 1317 1318 continue; 1319 } 1320 } 1321 1322 if (r->count == 0) 1323 { 1324 /* 1325 * Copy the raster data to the buffer... 1326 */ 1327 1328 memcpy(r->pcurrent, p, (size_t)bytes); 1329 1330 r->pcurrent += bytes; 1331 1332 if (r->pcurrent >= r->pend) 1333 { 1334 /* 1335 * Increase the repeat count... 1336 */ 1337 1338 r->count += r->rowheight; 1339 r->pcurrent = r->pixels; 1340 1341 /* 1342 * Flush out this line if it is the last one... 1343 */ 1344 1345 r->remaining --; 1346 1347 if (r->remaining == 0) 1348 { 1349 if (cups_raster_write(r, r->pixels) <= 0) 1350 return (0); 1351 } 1352 } 1353 } 1354 } 1355 1356 return (len); 1357 } 1358 1359 1360 /* 1361 * 'cups_raster_read_header()' - Read a raster page header. 1362 */ 1363 1364 static unsigned /* O - 1 on success, 0 on fail */ 1365 cups_raster_read_header( 1366 cups_raster_t *r) /* I - Raster stream */ 1367 { 1368 size_t len; /* Length for read/swap */ 1369 1370 1371 DEBUG_printf(("3cups_raster_read_header(r=%p), r->mode=%d", (void *)r, r ? r->mode : 0)); 1372 1373 if (r == NULL || r->mode != CUPS_RASTER_READ) 1374 return (0); 1375 1376 DEBUG_printf(("4cups_raster_read_header: r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount)); 1377 1378 memset(&(r->header), 0, sizeof(r->header)); 1379 1380 /* 1381 * Read the header... 1382 */ 1383 1384 switch (r->sync) 1385 { 1386 default : 1387 /* 1388 * Get the length of the raster header... 1389 */ 1390 1391 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1) 1392 len = sizeof(cups_page_header_t); 1393 else 1394 len = sizeof(cups_page_header2_t); 1395 1396 DEBUG_printf(("4cups_raster_read_header: len=%d", (int)len)); 1397 1398 /* 1399 * Read it... 1400 */ 1401 1402 if (cups_raster_read(r, (unsigned char *)&(r->header), len) < (ssize_t)len) 1403 { 1404 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount)); 1405 return (0); 1406 } 1407 1408 /* 1409 * Swap bytes as needed... 1410 */ 1411 1412 if (r->swapped) 1413 { 1414 unsigned *s, /* Current word */ 1415 temp; /* Temporary copy */ 1416 1417 1418 DEBUG_puts("4cups_raster_read_header: Swapping header bytes."); 1419 1420 for (len = 81, s = &(r->header.AdvanceDistance); 1421 len > 0; 1422 len --, s ++) 1423 { 1424 temp = *s; 1425 *s = ((temp & 0xff) << 24) | 1426 ((temp & 0xff00) << 8) | 1427 ((temp & 0xff0000) >> 8) | 1428 ((temp & 0xff000000) >> 24); 1429 1430 DEBUG_printf(("4cups_raster_read_header: %08x => %08x", temp, *s)); 1431 } 1432 } 1433 break; 1434 1435 case CUPS_RASTER_SYNCapple : 1436 case CUPS_RASTER_REVSYNCapple : 1437 { 1438 unsigned char appleheader[32]; /* Raw header */ 1439 static const unsigned rawcspace[] = 1440 { 1441 CUPS_CSPACE_SW, 1442 CUPS_CSPACE_SRGB, 1443 CUPS_CSPACE_RGBW, 1444 CUPS_CSPACE_ADOBERGB, 1445 CUPS_CSPACE_W, 1446 CUPS_CSPACE_RGB, 1447 CUPS_CSPACE_CMYK 1448 }; 1449 static const unsigned rawnumcolors[] = 1450 { 1451 1, 1452 3, 1453 4, 1454 3, 1455 1, 1456 3, 1457 4 1458 }; 1459 1460 if (cups_raster_read(r, appleheader, sizeof(appleheader)) < (ssize_t)sizeof(appleheader)) 1461 { 1462 DEBUG_printf(("4cups_raster_read_header: EOF, r->iocount=" CUPS_LLFMT, CUPS_LLCAST r->iocount)); 1463 return (0); 1464 } 1465 1466 strlcpy(r->header.MediaClass, "PwgRaster", sizeof(r->header.MediaClass)); 1467 /* PwgRaster */ 1468 r->header.cupsBitsPerPixel = appleheader[0]; 1469 r->header.cupsColorSpace = appleheader[1] >= (sizeof(rawcspace) / sizeof(rawcspace[0])) ? CUPS_CSPACE_DEVICE1 : rawcspace[appleheader[1]]; 1470 r->header.cupsNumColors = appleheader[1] >= (sizeof(rawnumcolors) / sizeof(rawnumcolors[0])) ? 1 : rawnumcolors[appleheader[1]]; 1471 r->header.cupsBitsPerColor = r->header.cupsBitsPerPixel / r->header.cupsNumColors; 1472 r->header.cupsWidth = ((((((unsigned)appleheader[12] << 8) | (unsigned)appleheader[13]) << 8) | (unsigned)appleheader[14]) << 8) | (unsigned)appleheader[15]; 1473 r->header.cupsHeight = ((((((unsigned)appleheader[16] << 8) | (unsigned)appleheader[17]) << 8) | (unsigned)appleheader[18]) << 8) | (unsigned)appleheader[19]; 1474 r->header.cupsBytesPerLine = r->header.cupsWidth * r->header.cupsBitsPerPixel / 8; 1475 r->header.cupsColorOrder = CUPS_ORDER_CHUNKED; 1476 r->header.HWResolution[0] = r->header.HWResolution[1] = ((((((unsigned)appleheader[20] << 8) | (unsigned)appleheader[21]) << 8) | (unsigned)appleheader[22]) << 8) | (unsigned)appleheader[23]; 1477 1478 if (r->header.HWResolution[0] > 0) 1479 { 1480 r->header.PageSize[0] = (unsigned)(r->header.cupsWidth * 72 / r->header.HWResolution[0]); 1481 r->header.PageSize[1] = (unsigned)(r->header.cupsHeight * 72 / r->header.HWResolution[1]); 1482 r->header.cupsPageSize[0] = (float)(r->header.cupsWidth * 72.0 / r->header.HWResolution[0]); 1483 r->header.cupsPageSize[1] = (float)(r->header.cupsHeight * 72.0 / r->header.HWResolution[1]); 1484 } 1485 1486 r->header.cupsInteger[0] = r->apple_page_count; 1487 r->header.cupsInteger[7] = 0xffffff; 1488 } 1489 break; 1490 } 1491 1492 /* 1493 * Update the header and row count... 1494 */ 1495 1496 if (!cups_raster_update(r)) 1497 return (0); 1498 1499 DEBUG_printf(("4cups_raster_read_header: cupsBitsPerPixel=%u, cupsBitsPerColor=%u, cupsBytesPerLine=%u, cupsWidth=%u, cupsHeight=%u, r->bpp=%d", r->header.cupsBitsPerPixel, r->header.cupsBitsPerColor, r->header.cupsBytesPerLine, r->header.cupsWidth, r->header.cupsHeight, r->bpp)); 1500 1501 return (r->header.cupsBitsPerPixel > 0 && r->header.cupsBitsPerPixel <= 240 && r->header.cupsBitsPerColor > 0 && r->header.cupsBitsPerColor <= 16 && r->header.cupsBytesPerLine > 0 && r->header.cupsBytesPerLine <= 0x7fffffff && r->header.cupsHeight != 0 && (r->header.cupsBytesPerLine % r->bpp) == 0); 1502 } 1503 1504 1505 /* 1506 * 'cups_raster_io()' - Read/write bytes from a context, handling interruptions. 1507 */ 1508 1509 static ssize_t /* O - Bytes read/write or -1 */ 1510 cups_raster_io(cups_raster_t *r, /* I - Raster stream */ 1511 unsigned char *buf, /* I - Buffer for read/write */ 1512 size_t bytes) /* I - Number of bytes to read/write */ 1513 { 1514 ssize_t count, /* Number of bytes read/written */ 1515 total; /* Total bytes read/written */ 1516 1517 1518 DEBUG_printf(("5cups_raster_io(r=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)r, (void *)buf, CUPS_LLCAST bytes)); 1519 1520 for (total = 0; total < (ssize_t)bytes; total += count, buf += count) 1521 { 1522 count = (*r->iocb)(r->ctx, buf, bytes - (size_t)total); 1523 1524 DEBUG_printf(("6cups_raster_io: count=%d, total=%d", (int)count, (int)total)); 1525 if (count == 0) 1526 { 1527 DEBUG_puts("6cups_raster_io: Returning 0."); 1528 return (0); 1529 } 1530 else if (count < 0) 1531 { 1532 DEBUG_puts("6cups_raster_io: Returning -1 on error."); 1533 return (-1); 1534 } 1535 1536 #ifdef DEBUG 1537 r->iocount += (size_t)count; 1538 #endif /* DEBUG */ 1539 } 1540 1541 DEBUG_printf(("6cups_raster_io: Returning " CUPS_LLFMT ".", CUPS_LLCAST total)); 1542 1543 return (total); 1544 } 1545 1546 1547 /* 1548 * 'cups_raster_read()' - Read through the raster buffer. 1549 */ 1550 1551 static ssize_t /* O - Number of bytes read */ 1552 cups_raster_read(cups_raster_t *r, /* I - Raster stream */ 1553 unsigned char *buf, /* I - Buffer */ 1554 size_t bytes) /* I - Number of bytes to read */ 1555 { 1556 ssize_t count, /* Number of bytes read */ 1557 remaining, /* Remaining bytes in buffer */ 1558 total; /* Total bytes read */ 1559 1560 1561 DEBUG_printf(("5cups_raster_read(r=%p, buf=%p, bytes=" CUPS_LLFMT ")", (void *)r, (void *)buf, CUPS_LLCAST bytes)); 1562 1563 if (!r->compressed) 1564 return (cups_raster_io(r, buf, bytes)); 1565 1566 /* 1567 * Allocate a read buffer as needed... 1568 */ 1569 1570 count = (ssize_t)(2 * r->header.cupsBytesPerLine); 1571 if (count < 65536) 1572 count = 65536; 1573 1574 if ((size_t)count > r->bufsize) 1575 { 1576 ssize_t offset = r->bufptr - r->buffer; 1577 /* Offset to current start of buffer */ 1578 ssize_t end = r->bufend - r->buffer;/* Offset to current end of buffer */ 1579 unsigned char *rptr; /* Pointer in read buffer */ 1580 1581 if (r->buffer) 1582 rptr = realloc(r->buffer, (size_t)count); 1583 else 1584 rptr = malloc((size_t)count); 1585 1586 if (!rptr) 1587 return (0); 1588 1589 r->buffer = rptr; 1590 r->bufptr = rptr + offset; 1591 r->bufend = rptr + end; 1592 r->bufsize = (size_t)count; 1593 } 1594 1595 /* 1596 * Loop until we have read everything... 1597 */ 1598 1599 for (total = 0, remaining = (int)(r->bufend - r->bufptr); 1600 total < (ssize_t)bytes; 1601 total += count, buf += count) 1602 { 1603 count = (ssize_t)bytes - total; 1604 1605 DEBUG_printf(("6cups_raster_read: count=" CUPS_LLFMT ", remaining=" CUPS_LLFMT ", buf=%p, bufptr=%p, bufend=%p", CUPS_LLCAST count, CUPS_LLCAST remaining, (void *)buf, (void *)r->bufptr, (void *)r->bufend)); 1606 1607 if (remaining == 0) 1608 { 1609 if (count < 16) 1610 { 1611 /* 1612 * Read into the raster buffer and then copy... 1613 */ 1614 1615 remaining = (*r->iocb)(r->ctx, r->buffer, r->bufsize); 1616 if (remaining <= 0) 1617 return (0); 1618 1619 r->bufptr = r->buffer; 1620 r->bufend = r->buffer + remaining; 1621 1622 #ifdef DEBUG 1623 r->iocount += (size_t)remaining; 1624 #endif /* DEBUG */ 1625 } 1626 else 1627 { 1628 /* 1629 * Read directly into "buf"... 1630 */ 1631 1632 count = (*r->iocb)(r->ctx, buf, (size_t)count); 1633 1634 if (count <= 0) 1635 return (0); 1636 1637 #ifdef DEBUG 1638 r->iocount += (size_t)count; 1639 #endif /* DEBUG */ 1640 1641 continue; 1642 } 1643 } 1644 1645 /* 1646 * Copy bytes from raster buffer to "buf"... 1647 */ 1648 1649 if (count > remaining) 1650 count = remaining; 1651 1652 if (count == 1) 1653 { 1654 /* 1655 * Copy 1 byte... 1656 */ 1657 1658 *buf = *(r->bufptr)++; 1659 remaining --; 1660 } 1661 else if (count < 128) 1662 { 1663 /* 1664 * Copy up to 127 bytes without using memcpy(); this is 1665 * faster because it avoids an extra function call and is 1666 * often further optimized by the compiler... 1667 */ 1668 1669 unsigned char *bufptr; /* Temporary buffer pointer */ 1670 1671 remaining -= count; 1672 1673 for (bufptr = r->bufptr; count > 0; count --, total ++) 1674 *buf++ = *bufptr++; 1675 1676 r->bufptr = bufptr; 1677 } 1678 else 1679 { 1680 /* 1681 * Use memcpy() for a large read... 1682 */ 1683 1684 memcpy(buf, r->bufptr, (size_t)count); 1685 r->bufptr += count; 1686 remaining -= count; 1687 } 1688 } 1689 1690 DEBUG_printf(("6cups_raster_read: Returning %ld", (long)total)); 1691 1692 return (total); 1693 } 1694 1695 1696 /* 1697 * 'cups_raster_update()' - Update the raster header and row count for the 1698 * current page. 1699 */ 1700 1701 static int /* O - 1 on success, 0 on failure */ 1702 cups_raster_update(cups_raster_t *r) /* I - Raster stream */ 1703 { 1704 if (r->sync == CUPS_RASTER_SYNCv1 || r->sync == CUPS_RASTER_REVSYNCv1 || 1705 r->header.cupsNumColors == 0) 1706 { 1707 /* 1708 * Set the "cupsNumColors" field according to the colorspace... 1709 */ 1710 1711 switch (r->header.cupsColorSpace) 1712 { 1713 case CUPS_CSPACE_W : 1714 case CUPS_CSPACE_K : 1715 case CUPS_CSPACE_WHITE : 1716 case CUPS_CSPACE_GOLD : 1717 case CUPS_CSPACE_SILVER : 1718 case CUPS_CSPACE_SW : 1719 r->header.cupsNumColors = 1; 1720 break; 1721 1722 case CUPS_CSPACE_RGB : 1723 case CUPS_CSPACE_CMY : 1724 case CUPS_CSPACE_YMC : 1725 case CUPS_CSPACE_CIEXYZ : 1726 case CUPS_CSPACE_CIELab : 1727 case CUPS_CSPACE_SRGB : 1728 case CUPS_CSPACE_ADOBERGB : 1729 case CUPS_CSPACE_ICC1 : 1730 case CUPS_CSPACE_ICC2 : 1731 case CUPS_CSPACE_ICC3 : 1732 case CUPS_CSPACE_ICC4 : 1733 case CUPS_CSPACE_ICC5 : 1734 case CUPS_CSPACE_ICC6 : 1735 case CUPS_CSPACE_ICC7 : 1736 case CUPS_CSPACE_ICC8 : 1737 case CUPS_CSPACE_ICC9 : 1738 case CUPS_CSPACE_ICCA : 1739 case CUPS_CSPACE_ICCB : 1740 case CUPS_CSPACE_ICCC : 1741 case CUPS_CSPACE_ICCD : 1742 case CUPS_CSPACE_ICCE : 1743 case CUPS_CSPACE_ICCF : 1744 r->header.cupsNumColors = 3; 1745 break; 1746 1747 case CUPS_CSPACE_RGBA : 1748 case CUPS_CSPACE_RGBW : 1749 case CUPS_CSPACE_CMYK : 1750 case CUPS_CSPACE_YMCK : 1751 case CUPS_CSPACE_KCMY : 1752 case CUPS_CSPACE_GMCK : 1753 case CUPS_CSPACE_GMCS : 1754 r->header.cupsNumColors = 4; 1755 break; 1756 1757 case CUPS_CSPACE_KCMYcm : 1758 if (r->header.cupsBitsPerPixel < 8) 1759 r->header.cupsNumColors = 6; 1760 else 1761 r->header.cupsNumColors = 4; 1762 break; 1763 1764 case CUPS_CSPACE_DEVICE1 : 1765 case CUPS_CSPACE_DEVICE2 : 1766 case CUPS_CSPACE_DEVICE3 : 1767 case CUPS_CSPACE_DEVICE4 : 1768 case CUPS_CSPACE_DEVICE5 : 1769 case CUPS_CSPACE_DEVICE6 : 1770 case CUPS_CSPACE_DEVICE7 : 1771 case CUPS_CSPACE_DEVICE8 : 1772 case CUPS_CSPACE_DEVICE9 : 1773 case CUPS_CSPACE_DEVICEA : 1774 case CUPS_CSPACE_DEVICEB : 1775 case CUPS_CSPACE_DEVICEC : 1776 case CUPS_CSPACE_DEVICED : 1777 case CUPS_CSPACE_DEVICEE : 1778 case CUPS_CSPACE_DEVICEF : 1779 r->header.cupsNumColors = r->header.cupsColorSpace - 1780 CUPS_CSPACE_DEVICE1 + 1; 1781 break; 1782 1783 default : 1784 /* Unknown color space */ 1785 return (0); 1786 } 1787 } 1788 1789 /* 1790 * Set the number of bytes per pixel/color... 1791 */ 1792 1793 if (r->header.cupsColorOrder == CUPS_ORDER_CHUNKED) 1794 r->bpp = (r->header.cupsBitsPerPixel + 7) / 8; 1795 else 1796 r->bpp = (r->header.cupsBitsPerColor + 7) / 8; 1797 1798 if (r->bpp == 0) 1799 r->bpp = 1; 1800 1801 /* 1802 * Set the number of remaining rows... 1803 */ 1804 1805 if (r->header.cupsColorOrder == CUPS_ORDER_PLANAR) 1806 r->remaining = r->header.cupsHeight * r->header.cupsNumColors; 1807 else 1808 r->remaining = r->header.cupsHeight; 1809 1810 /* 1811 * Allocate the compression buffer... 1812 */ 1813 1814 if (r->compressed) 1815 { 1816 if (r->pixels != NULL) 1817 free(r->pixels); 1818 1819 if ((r->pixels = calloc(r->header.cupsBytesPerLine, 1)) == NULL) 1820 { 1821 r->pcurrent = NULL; 1822 r->pend = NULL; 1823 r->count = 0; 1824 1825 return (0); 1826 } 1827 1828 r->pcurrent = r->pixels; 1829 r->pend = r->pixels + r->header.cupsBytesPerLine; 1830 r->count = 0; 1831 } 1832 1833 return (1); 1834 } 1835 1836 1837 /* 1838 * 'cups_raster_write()' - Write a row of compressed raster data... 1839 */ 1840 1841 static ssize_t /* O - Number of bytes written */ 1842 cups_raster_write( 1843 cups_raster_t *r, /* I - Raster stream */ 1844 const unsigned char *pixels) /* I - Pixel data to write */ 1845 { 1846 const unsigned char *start, /* Start of sequence */ 1847 *ptr, /* Current pointer in sequence */ 1848 *pend, /* End of raster buffer */ 1849 *plast; /* Pointer to last pixel */ 1850 unsigned char *wptr; /* Pointer into write buffer */ 1851 unsigned bpp, /* Bytes per pixel */ 1852 count; /* Count */ 1853 1854 1855 DEBUG_printf(("3cups_raster_write(r=%p, pixels=%p)", (void *)r, (void *)pixels)); 1856 1857 /* 1858 * Allocate a write buffer as needed... 1859 */ 1860 1861 count = r->header.cupsBytesPerLine * 2; 1862 if (count < 65536) 1863 count = 65536; 1864 1865 if ((size_t)count > r->bufsize) 1866 { 1867 if (r->buffer) 1868 wptr = realloc(r->buffer, count); 1869 else 1870 wptr = malloc(count); 1871 1872 if (!wptr) 1873 { 1874 DEBUG_printf(("4cups_raster_write: Unable to allocate " CUPS_LLFMT " bytes for raster buffer: %s", CUPS_LLCAST count, strerror(errno))); 1875 return (-1); 1876 } 1877 1878 r->buffer = wptr; 1879 r->bufsize = count; 1880 } 1881 1882 /* 1883 * Write the row repeat count... 1884 */ 1885 1886 bpp = r->bpp; 1887 pend = pixels + r->header.cupsBytesPerLine; 1888 plast = pend - bpp; 1889 wptr = r->buffer; 1890 *wptr++ = (unsigned char)(r->count - 1); 1891 1892 /* 1893 * Write using a modified PackBits compression... 1894 */ 1895 1896 for (ptr = pixels; ptr < pend;) 1897 { 1898 start = ptr; 1899 ptr += bpp; 1900 1901 if (ptr == pend) 1902 { 1903 /* 1904 * Encode a single pixel at the end... 1905 */ 1906 1907 *wptr++ = 0; 1908 for (count = bpp; count > 0; count --) 1909 *wptr++ = *start++; 1910 } 1911 else if (!memcmp(start, ptr, bpp)) 1912 { 1913 /* 1914 * Encode a sequence of repeating pixels... 1915 */ 1916 1917 for (count = 2; count < 128 && ptr < plast; count ++, ptr += bpp) 1918 if (memcmp(ptr, ptr + bpp, bpp)) 1919 break; 1920 1921 *wptr++ = (unsigned char)(count - 1); 1922 for (count = bpp; count > 0; count --) 1923 *wptr++ = *ptr++; 1924 } 1925 else 1926 { 1927 /* 1928 * Encode a sequence of non-repeating pixels... 1929 */ 1930 1931 for (count = 1; count < 128 && ptr < plast; count ++, ptr += bpp) 1932 if (!memcmp(ptr, ptr + bpp, bpp)) 1933 break; 1934 1935 if (ptr >= plast && count < 128) 1936 { 1937 count ++; 1938 ptr += bpp; 1939 } 1940 1941 *wptr++ = (unsigned char)(257 - count); 1942 1943 count *= bpp; 1944 memcpy(wptr, start, count); 1945 wptr += count; 1946 } 1947 } 1948 1949 DEBUG_printf(("4cups_raster_write: Writing " CUPS_LLFMT " bytes.", CUPS_LLCAST (wptr - r->buffer))); 1950 1951 return (cups_raster_io(r, r->buffer, (size_t)(wptr - r->buffer))); 1952 } 1953 1954 1955 /* 1956 * 'cups_read_fd()' - Read bytes from a file. 1957 */ 1958 1959 static ssize_t /* O - Bytes read or -1 */ 1960 cups_read_fd(void *ctx, /* I - File descriptor as pointer */ 1961 unsigned char *buf, /* I - Buffer for read */ 1962 size_t bytes) /* I - Maximum number of bytes to read */ 1963 { 1964 int fd = (int)((intptr_t)ctx); 1965 /* File descriptor */ 1966 ssize_t count; /* Number of bytes read */ 1967 1968 1969 #ifdef WIN32 /* Sigh */ 1970 while ((count = read(fd, buf, (unsigned)bytes)) < 0) 1971 #else 1972 while ((count = read(fd, buf, bytes)) < 0) 1973 #endif /* WIN32 */ 1974 if (errno != EINTR && errno != EAGAIN) 1975 { 1976 DEBUG_printf(("4cups_read_fd: %s", strerror(errno))); 1977 return (-1); 1978 } 1979 1980 DEBUG_printf(("4cups_read_fd: Returning %d bytes.", (int)count)); 1981 1982 return (count); 1983 } 1984 1985 1986 /* 1987 * 'cups_swap()' - Swap bytes in raster data... 1988 */ 1989 1990 static void 1991 cups_swap(unsigned char *buf, /* I - Buffer to swap */ 1992 size_t bytes) /* I - Number of bytes to swap */ 1993 { 1994 unsigned char even, odd; /* Temporary variables */ 1995 1996 1997 bytes /= 2; 1998 1999 while (bytes > 0) 2000 { 2001 even = buf[0]; 2002 odd = buf[1]; 2003 buf[0] = odd; 2004 buf[1] = even; 2005 2006 buf += 2; 2007 bytes --; 2008 } 2009 } 2010 2011 2012 /* 2013 * 'cups_write_fd()' - Write bytes to a file. 2014 */ 2015 2016 static ssize_t /* O - Bytes written or -1 */ 2017 cups_write_fd(void *ctx, /* I - File descriptor pointer */ 2018 unsigned char *buf, /* I - Bytes to write */ 2019 size_t bytes) /* I - Number of bytes to write */ 2020 { 2021 int fd = (int)((intptr_t)ctx); 2022 /* File descriptor */ 2023 ssize_t count; /* Number of bytes written */ 2024 2025 2026 #ifdef WIN32 /* Sigh */ 2027 while ((count = write(fd, buf, (unsigned)bytes)) < 0) 2028 #else 2029 while ((count = write(fd, buf, bytes)) < 0) 2030 #endif /* WIN32 */ 2031 if (errno != EINTR && errno != EAGAIN) 2032 { 2033 DEBUG_printf(("4cups_write_fd: %s", strerror(errno))); 2034 return (-1); 2035 } 2036 2037 return (count); 2038 } 2039