1 /* 2 * Copyright (C) 1989-95 GROUPE BULL 3 * 4 * Permission is hereby granted, free of charge, to any person obtaining a copy 5 * of this software and associated documentation files (the "Software"), to 6 * deal in the Software without restriction, including without limitation the 7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or 8 * sell copies of the Software, and to permit persons to whom the Software is 9 * furnished to do so, subject to the following conditions: 10 * 11 * The above copyright notice and this permission notice shall be included in 12 * all copies or substantial portions of the Software. 13 * 14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL 17 * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN 18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 20 * 21 * Except as contained in this notice, the name of GROUPE BULL shall not be 22 * used in advertising or otherwise to promote the sale, use or other dealings 23 * in this Software without prior written authorization from GROUPE BULL. 24 */ 25 26 /*****************************************************************************\ 27 * create.c: * 28 * * 29 * XPM library * 30 * Create an X image and possibly its related shape mask * 31 * from the given XpmImage. * 32 * * 33 * Developed by Arnaud Le Hors * 34 \*****************************************************************************/ 35 36 /* October 2004, source code review by Thomas Biege <thomas (at) suse.de> */ 37 38 #ifdef HAVE_CONFIG_H 39 #include <config.h> 40 #endif 41 #include "XpmI.h" 42 #include <ctype.h> 43 44 #if defined(_MSC_VER) 45 #define strcasecmp _stricmp 46 #endif 47 48 LFUNC(xpmVisualType, int, (Visual *visual)); 49 50 LFUNC(AllocColor, int, (Display *display, Colormap colormap, 51 char *colorname, XColor *xcolor, void *closure)); 52 LFUNC(FreeColors, int, (Display *display, Colormap colormap, 53 Pixel *pixels, int n, void *closure)); 54 55 LFUNC(SetCloseColor, int, (Display *display, Colormap colormap, 56 Visual *visual, XColor *col, 57 Pixel *image_pixel, Pixel *mask_pixel, 58 Pixel *alloc_pixels, unsigned int *nalloc_pixels, 59 XpmAttributes *attributes, XColor *cols, int ncols, 60 XpmAllocColorFunc allocColor, void *closure)); 61 62 LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual, 63 char *colorname, unsigned int color_index, 64 Pixel *image_pixel, Pixel *mask_pixel, 65 unsigned int *mask_pixel_index, 66 Pixel *alloc_pixels, unsigned int *nalloc_pixels, 67 Pixel *used_pixels, unsigned int *nused_pixels, 68 XpmAttributes *attributes, XColor *cols, int ncols, 69 XpmAllocColorFunc allocColor, void *closure)); 70 71 LFUNC(CreateXImage, int, (Display *display, Visual *visual, 72 unsigned int depth, int format, unsigned int width, 73 unsigned int height, XImage **image_return)); 74 75 LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes, 76 XpmColor *colors, unsigned int ncolors, 77 Pixel *image_pixels, Pixel *mask_pixels, 78 unsigned int *mask_pixel_index, 79 Pixel *alloc_pixels, unsigned int *nalloc_pixels, 80 Pixel *used_pixels, unsigned int *nused_pixels)); 81 82 LFUNC(ParseAndPutPixels, int, (xpmData *data, unsigned int width, 83 unsigned int height, unsigned int ncolors, 84 unsigned int cpp, XpmColor *colorTable, 85 xpmHashTable *hashtable, 86 XImage *image, Pixel *image_pixels, 87 XImage *mask, Pixel *mask_pixels)); 88 89 /* XImage pixel routines */ 90 LFUNC(PutImagePixels, void, (XImage *image, unsigned int width, 91 unsigned int height, unsigned int *pixelindex, 92 Pixel *pixels)); 93 94 LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width, 95 unsigned int height, unsigned int *pixelindex, 96 Pixel *pixels)); 97 98 LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width, 99 unsigned int height, unsigned int *pixelindex, 100 Pixel *pixels)); 101 102 LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width, 103 unsigned int height, unsigned int *pixelindex, 104 Pixel *pixels)); 105 106 LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width, 107 unsigned int height, unsigned int *pixelindex, 108 Pixel *pixels)); 109 110 LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel)); 111 LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel)); 112 #if !defined(WORD64) && !defined(LONG64) 113 LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel)); 114 #endif 115 LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); 116 LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); 117 LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); 118 LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); 119 LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel)); 120 LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); 121 LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel)); 122 123 /* 124 * return the default color key related to the given visual 125 */ 126 static int 127 xpmVisualType(Visual *visual) 128 { 129 switch (visual->class) { 130 case StaticGray: 131 case GrayScale: 132 switch (visual->map_entries) { 133 case 2: 134 return (XPM_MONO); 135 case 4: 136 return (XPM_GRAY4); 137 default: 138 return (XPM_GRAY); 139 } 140 default: 141 return (XPM_COLOR); 142 } 143 } 144 145 146 typedef struct { 147 int cols_index; 148 long closeness; 149 } CloseColor; 150 151 static int 152 closeness_cmp(const void *a, const void *b) 153 { 154 const CloseColor *x = (const CloseColor *) a, *y = (const CloseColor *) b; 155 156 /* cast to int as qsort requires */ 157 return (int) (x->closeness - y->closeness); 158 } 159 160 161 /* default AllocColor function: 162 * call XParseColor if colorname is given, return negative value if failure 163 * call XAllocColor and return 0 if failure, positive otherwise 164 */ 165 static int 166 AllocColor( 167 Display *display, 168 Colormap colormap, 169 char *colorname, 170 XColor *xcolor, 171 void *closure) /* not used */ 172 { 173 int status; 174 if (colorname) 175 if (!XParseColor(display, colormap, colorname, xcolor)) 176 return -1; 177 status = XAllocColor(display, colormap, xcolor); 178 return status != 0 ? 1 : 0; 179 } 180 181 182 /* 183 * set a close color in case the exact one can't be set 184 * return 0 if success, 1 otherwise. 185 */ 186 187 static int 188 SetCloseColor( 189 Display *display, 190 Colormap colormap, 191 Visual *visual, 192 XColor *col, 193 Pixel *image_pixel, 194 Pixel *mask_pixel, 195 Pixel *alloc_pixels, 196 unsigned int *nalloc_pixels, 197 XpmAttributes *attributes, 198 XColor *cols, 199 int ncols, 200 XpmAllocColorFunc allocColor, 201 void *closure) 202 { 203 204 /* 205 * Allocation failed, so try close colors. To get here the visual must 206 * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor? 207 * What about sharing systems like QDSS?). Beware: we have to treat 208 * DirectColor differently. 209 */ 210 211 212 long int red_closeness, green_closeness, blue_closeness; 213 int n; 214 Bool alloc_color; 215 216 if (attributes && (attributes->valuemask & XpmCloseness)) 217 red_closeness = green_closeness = blue_closeness = 218 attributes->closeness; 219 else { 220 red_closeness = attributes->red_closeness; 221 green_closeness = attributes->green_closeness; 222 blue_closeness = attributes->blue_closeness; 223 } 224 if (attributes && (attributes->valuemask & XpmAllocCloseColors)) 225 alloc_color = attributes->alloc_close_colors; 226 else 227 alloc_color = True; 228 229 /* 230 * We sort the colormap by closeness and try to allocate the color 231 * closest to the target. If the allocation of this close color fails, 232 * which almost never happens, then one of two scenarios is possible. 233 * Either the colormap must have changed (since the last close color 234 * allocation or possibly while we were sorting the colormap), or the 235 * color is allocated as Read/Write by some other client. (Note: X 236 * _should_ allow clients to check if a particular color is Read/Write, 237 * but it doesn't! :-( ). We cannot determine which of these scenarios 238 * occurred, so we try the next closest color, and so on, until no more 239 * colors are within closeness of the target. If we knew that the 240 * colormap had changed, we could skip this sequence. 241 * 242 * If _none_ of the colors within closeness of the target can be allocated, 243 * then we can finally be pretty sure that the colormap has actually 244 * changed. In this case we try to allocate the original color (again), 245 * then try the closecolor stuff (again)... 246 * 247 * In theory it would be possible for an infinite loop to occur if another 248 * process kept changing the colormap every time we sorted it, so we set 249 * a maximum on the number of iterations. After this many tries, we use 250 * XGrabServer() to ensure that the colormap remains unchanged. 251 * 252 * This approach gives particularly bad worst case performance - as many as 253 * <MaximumIterations> colormap reads and sorts may be needed, and as 254 * many as <MaximumIterations> * <ColormapSize> attempted allocations 255 * may fail. On an 8-bit system, this means as many as 3 colormap reads, 256 * 3 sorts and 768 failed allocations per execution of this code! 257 * Luckily, my experiments show that in general use in a typical 8-bit 258 * color environment only about 1 in every 10000 allocations fails to 259 * succeed in the fastest possible time. So virtually every time what 260 * actually happens is a single sort followed by a successful allocate. 261 * The very first allocation also costs a colormap read, but no further 262 * reads are usually necessary. 263 */ 264 265 #define ITERATIONS 2 /* more than one is almost never 266 * necessary */ 267 268 for (n = 0; n <= ITERATIONS; ++n) { 269 CloseColor *closenesses = 270 (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor)); 271 int i, c; 272 273 for (i = 0; i < ncols; ++i) { /* build & sort closenesses table */ 274 #define COLOR_FACTOR 3 275 #define BRIGHTNESS_FACTOR 1 276 277 closenesses[i].cols_index = i; 278 closenesses[i].closeness = 279 COLOR_FACTOR * (labs((long) col->red - (long) cols[i].red) 280 + labs((long) col->green - (long) cols[i].green) 281 + labs((long) col->blue - (long) cols[i].blue)) 282 + BRIGHTNESS_FACTOR * labs(((long) col->red + 283 (long) col->green + 284 (long) col->blue) 285 - ((long) cols[i].red + 286 (long) cols[i].green + 287 (long) cols[i].blue)); 288 } 289 qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp); 290 291 i = 0; 292 c = closenesses[i].cols_index; 293 while ((long) cols[c].red >= (long) col->red - red_closeness && 294 (long) cols[c].red <= (long) col->red + red_closeness && 295 (long) cols[c].green >= (long) col->green - green_closeness && 296 (long) cols[c].green <= (long) col->green + green_closeness && 297 (long) cols[c].blue >= (long) col->blue - blue_closeness && 298 (long) cols[c].blue <= (long) col->blue + blue_closeness) { 299 if (alloc_color) { 300 if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){ 301 if (n == ITERATIONS) 302 XUngrabServer(display); 303 XpmFree(closenesses); 304 *image_pixel = cols[c].pixel; 305 *mask_pixel = 1; 306 alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel; 307 return (0); 308 } else { 309 ++i; 310 if (i == ncols) 311 break; 312 c = closenesses[i].cols_index; 313 } 314 } else { 315 if (n == ITERATIONS) 316 XUngrabServer(display); 317 XpmFree(closenesses); 318 *image_pixel = cols[c].pixel; 319 *mask_pixel = 1; 320 return (0); 321 } 322 } 323 324 /* Couldn't allocate _any_ of the close colors! */ 325 326 if (n == ITERATIONS) 327 XUngrabServer(display); 328 XpmFree(closenesses); 329 330 if (i == 0 || i == ncols) /* no color close enough or cannot */ 331 return (1); /* alloc any color (full of r/w's) */ 332 333 if ((*allocColor)(display, colormap, NULL, col, closure)) { 334 *image_pixel = col->pixel; 335 *mask_pixel = 1; 336 alloc_pixels[(*nalloc_pixels)++] = col->pixel; 337 return (0); 338 } else { /* colormap has probably changed, so 339 * re-read... */ 340 if (n == ITERATIONS - 1) 341 XGrabServer(display); 342 343 #if 0 344 if (visual->class == DirectColor) { 345 /* TODO */ 346 } else 347 #endif 348 XQueryColors(display, colormap, cols, ncols); 349 } 350 } 351 return (1); 352 } 353 354 #define USE_CLOSECOLOR attributes && \ 355 (((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \ 356 || ((attributes->valuemask & XpmRGBCloseness) && \ 357 (attributes->red_closeness != 0 \ 358 || attributes->green_closeness != 0 \ 359 || attributes->blue_closeness != 0))) 360 361 362 /* 363 * set the color pixel related to the given colorname, 364 * return 0 if success, 1 otherwise. 365 */ 366 367 static int 368 SetColor( 369 Display *display, 370 Colormap colormap, 371 Visual *visual, 372 char *colorname, 373 unsigned int color_index, 374 Pixel *image_pixel, 375 Pixel *mask_pixel, 376 unsigned int *mask_pixel_index, 377 Pixel *alloc_pixels, 378 unsigned int *nalloc_pixels, 379 Pixel *used_pixels, 380 unsigned int *nused_pixels, 381 XpmAttributes *attributes, 382 XColor *cols, 383 int ncols, 384 XpmAllocColorFunc allocColor, 385 void *closure) 386 { 387 XColor xcolor; 388 int status; 389 390 if (strcasecmp(colorname, TRANSPARENT_COLOR)) { 391 status = (*allocColor)(display, colormap, colorname, &xcolor, closure); 392 if (status < 0) /* parse color failed */ 393 return (1); 394 395 if (status == 0) { 396 if (USE_CLOSECOLOR) 397 return (SetCloseColor(display, colormap, visual, &xcolor, 398 image_pixel, mask_pixel, 399 alloc_pixels, nalloc_pixels, 400 attributes, cols, ncols, 401 allocColor, closure)); 402 else 403 return (1); 404 } else 405 alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel; 406 *image_pixel = xcolor.pixel; 407 *mask_pixel = 1; 408 used_pixels[(*nused_pixels)++] = xcolor.pixel; 409 } else { 410 *image_pixel = 0; 411 *mask_pixel = 0; 412 /* store the color table index */ 413 *mask_pixel_index = color_index; 414 } 415 return (0); 416 } 417 418 419 static int 420 CreateColors( 421 Display *display, 422 XpmAttributes *attributes, 423 XpmColor *colors, 424 unsigned int ncolors, 425 Pixel *image_pixels, 426 Pixel *mask_pixels, 427 unsigned int *mask_pixel_index, 428 Pixel *alloc_pixels, 429 unsigned int *nalloc_pixels, 430 Pixel *used_pixels, 431 unsigned int *nused_pixels) 432 { 433 /* variables stored in the XpmAttributes structure */ 434 Visual *visual; 435 Colormap colormap; 436 XpmColorSymbol *colorsymbols = NULL; 437 unsigned int numsymbols; 438 XpmAllocColorFunc allocColor; 439 void *closure; 440 441 char *colorname; 442 unsigned int color, key; 443 Bool pixel_defined; 444 XpmColorSymbol *symbol = NULL; 445 char **defaults; 446 int ErrorStatus = XpmSuccess; 447 char *s; 448 int default_index; 449 450 XColor *cols = NULL; 451 unsigned int ncols = 0; 452 453 /* 454 * retrieve information from the XpmAttributes 455 */ 456 if (attributes && attributes->valuemask & XpmColorSymbols) { 457 colorsymbols = attributes->colorsymbols; 458 numsymbols = attributes->numsymbols; 459 } else 460 numsymbols = 0; 461 462 if (attributes && attributes->valuemask & XpmVisual) 463 visual = attributes->visual; 464 else 465 visual = XDefaultVisual(display, XDefaultScreen(display)); 466 467 if (attributes && (attributes->valuemask & XpmColormap)) 468 colormap = attributes->colormap; 469 else 470 colormap = XDefaultColormap(display, XDefaultScreen(display)); 471 472 if (attributes && (attributes->valuemask & XpmColorKey)) 473 key = attributes->color_key; 474 else 475 key = xpmVisualType(visual); 476 477 if (attributes && (attributes->valuemask & XpmAllocColor)) 478 allocColor = attributes->alloc_color; 479 else 480 allocColor = AllocColor; 481 if (attributes && (attributes->valuemask & XpmColorClosure)) 482 closure = attributes->color_closure; 483 else 484 closure = NULL; 485 486 if (USE_CLOSECOLOR) { 487 /* originally from SetCloseColor */ 488 #if 0 489 if (visual->class == DirectColor) { 490 491 /* 492 * TODO: Implement close colors for DirectColor visuals. This is 493 * difficult situation. Chances are that we will never get here, 494 * because any machine that supports DirectColor will probably 495 * also support TrueColor (and probably PseudoColor). Also, 496 * DirectColor colormaps can be very large, so looking for close 497 * colors may be too slow. 498 */ 499 } else { 500 #endif 501 unsigned int i; 502 503 ncols = visual->map_entries; 504 cols = (XColor *) XpmCalloc(ncols, sizeof(XColor)); 505 for (i = 0; i < ncols; ++i) 506 cols[i].pixel = i; 507 XQueryColors(display, colormap, cols, ncols); 508 #if 0 509 } 510 #endif 511 } 512 513 switch (key) { 514 case XPM_MONO: 515 default_index = 2; 516 break; 517 case XPM_GRAY4: 518 default_index = 3; 519 break; 520 case XPM_GRAY: 521 default_index = 4; 522 break; 523 case XPM_COLOR: 524 default: 525 default_index = 5; 526 break; 527 } 528 529 for (color = 0; color < ncolors; color++, colors++, 530 image_pixels++, mask_pixels++) { 531 colorname = NULL; 532 pixel_defined = False; 533 defaults = (char **) colors; 534 535 /* 536 * look for a defined symbol 537 */ 538 if (numsymbols) { 539 540 unsigned int n; 541 542 s = defaults[1]; 543 for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) { 544 if (symbol->name && s && !strcmp(symbol->name, s)) 545 /* override name */ 546 break; 547 if (!symbol->name && symbol->value) { /* override value */ 548 int def_index = default_index; 549 550 while (defaults[def_index] == NULL) /* find defined 551 * colorname */ 552 --def_index; 553 if (def_index < 2) {/* nothing towards mono, so try 554 * towards color */ 555 def_index = default_index + 1; 556 while (def_index <= 5 && defaults[def_index] == NULL) 557 ++def_index; 558 } 559 if (def_index >= 2 && def_index <= 5 && 560 defaults[def_index] != NULL && 561 !strcasecmp(symbol->value, defaults[def_index])) 562 break; 563 } 564 } 565 if (n != numsymbols) { 566 if (symbol->name && symbol->value) 567 colorname = symbol->value; 568 else 569 pixel_defined = True; 570 } 571 } 572 if (!pixel_defined) { /* pixel not given as symbol value */ 573 574 unsigned int k; 575 576 if (colorname) { /* colorname given as symbol value */ 577 if (!SetColor(display, colormap, visual, colorname, color, 578 image_pixels, mask_pixels, mask_pixel_index, 579 alloc_pixels, nalloc_pixels, used_pixels, 580 nused_pixels, attributes, cols, ncols, 581 allocColor, closure)) 582 pixel_defined = True; 583 else 584 ErrorStatus = XpmColorError; 585 } 586 k = key; 587 while (!pixel_defined && k > 1) { 588 if (defaults[k]) { 589 if (!SetColor(display, colormap, visual, defaults[k], 590 color, image_pixels, mask_pixels, 591 mask_pixel_index, alloc_pixels, 592 nalloc_pixels, used_pixels, nused_pixels, 593 attributes, cols, ncols, 594 allocColor, closure)) { 595 pixel_defined = True; 596 break; 597 } else 598 ErrorStatus = XpmColorError; 599 } 600 k--; 601 } 602 k = key + 1; 603 while (!pixel_defined && k < NKEYS + 1) { 604 if (defaults[k]) { 605 if (!SetColor(display, colormap, visual, defaults[k], 606 color, image_pixels, mask_pixels, 607 mask_pixel_index, alloc_pixels, 608 nalloc_pixels, used_pixels, nused_pixels, 609 attributes, cols, ncols, 610 allocColor, closure)) { 611 pixel_defined = True; 612 break; 613 } else 614 ErrorStatus = XpmColorError; 615 } 616 k++; 617 } 618 if (!pixel_defined) { 619 if (cols) 620 XpmFree(cols); 621 return (XpmColorFailed); 622 } 623 } else { 624 /* simply use the given pixel */ 625 *image_pixels = symbol->pixel; 626 /* the following makes the mask to be built even if none 627 is given a particular pixel */ 628 if (symbol->value 629 && !strcasecmp(symbol->value, TRANSPARENT_COLOR)) { 630 *mask_pixels = 0; 631 *mask_pixel_index = color; 632 } else 633 *mask_pixels = 1; 634 used_pixels[(*nused_pixels)++] = *image_pixels; 635 } 636 } 637 if (cols) 638 XpmFree(cols); 639 return (ErrorStatus); 640 } 641 642 643 /* default FreeColors function, simply call XFreeColors */ 644 static int 645 FreeColors( 646 Display *display, 647 Colormap colormap, 648 Pixel *pixels, 649 int n, 650 void *closure) /* not used */ 651 { 652 return XFreeColors(display, colormap, pixels, n, 0); 653 } 654 655 656 /* function call in case of error */ 657 658 #undef RETURN 659 #define RETURN(status) \ 660 do \ 661 { \ 662 ErrorStatus = status; \ 663 goto error; \ 664 } while(0) 665 666 int 667 XpmCreateImageFromXpmImage( 668 Display *display, 669 XpmImage *image, 670 XImage **image_return, 671 XImage **shapeimage_return, 672 XpmAttributes *attributes) 673 { 674 /* variables stored in the XpmAttributes structure */ 675 Visual *visual; 676 Colormap colormap; 677 unsigned int depth; 678 int bitmap_format; 679 XpmFreeColorsFunc freeColors; 680 681 /* variables to return */ 682 XImage *ximage = NULL; 683 XImage *shapeimage = NULL; 684 unsigned int mask_pixel_index = XpmUndefPixel; 685 int ErrorStatus; 686 687 /* calculation variables */ 688 Pixel *image_pixels = NULL; 689 Pixel *mask_pixels = NULL; 690 Pixel *alloc_pixels = NULL; 691 Pixel *used_pixels = NULL; 692 unsigned int nalloc_pixels = 0; 693 unsigned int nused_pixels = 0; 694 695 /* initialize return values */ 696 if (image_return) 697 *image_return = NULL; 698 if (shapeimage_return) 699 *shapeimage_return = NULL; 700 701 /* retrieve information from the XpmAttributes */ 702 if (attributes && (attributes->valuemask & XpmVisual)) 703 visual = attributes->visual; 704 else 705 visual = XDefaultVisual(display, XDefaultScreen(display)); 706 707 if (attributes && (attributes->valuemask & XpmColormap)) 708 colormap = attributes->colormap; 709 else 710 colormap = XDefaultColormap(display, XDefaultScreen(display)); 711 712 if (attributes && (attributes->valuemask & XpmDepth)) 713 depth = attributes->depth; 714 else 715 depth = XDefaultDepth(display, XDefaultScreen(display)); 716 717 if (attributes && (attributes->valuemask & XpmBitmapFormat)) 718 bitmap_format = attributes->bitmap_format; 719 else 720 bitmap_format = ZPixmap; 721 722 if (attributes && (attributes->valuemask & XpmFreeColors)) 723 freeColors = attributes->free_colors; 724 else 725 freeColors = FreeColors; 726 727 ErrorStatus = XpmSuccess; 728 729 if (image->ncolors >= UINT_MAX / sizeof(Pixel)) 730 return (XpmNoMemory); 731 732 /* malloc pixels index tables */ 733 image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); 734 if (!image_pixels) 735 return (XpmNoMemory); 736 737 mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); 738 if (!mask_pixels) 739 RETURN(XpmNoMemory); 740 741 /* maximum of allocated pixels will be the number of colors */ 742 alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); 743 if (!alloc_pixels) 744 RETURN(XpmNoMemory); 745 746 /* maximum of allocated pixels will be the number of colors */ 747 used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); 748 if (!used_pixels) 749 RETURN(XpmNoMemory); 750 751 /* get pixel colors, store them in index tables */ 752 ErrorStatus = CreateColors(display, attributes, image->colorTable, 753 image->ncolors, image_pixels, mask_pixels, 754 &mask_pixel_index, alloc_pixels, &nalloc_pixels, 755 used_pixels, &nused_pixels); 756 757 if (ErrorStatus != XpmSuccess 758 && (ErrorStatus < 0 || (attributes 759 && (attributes->valuemask & XpmExactColors) 760 && attributes->exactColors))) 761 RETURN(ErrorStatus); 762 763 /* create the ximage */ 764 if (image_return) { 765 ErrorStatus = CreateXImage(display, visual, depth, 766 (depth == 1 ? bitmap_format : ZPixmap), 767 image->width, image->height, &ximage); 768 if (ErrorStatus != XpmSuccess) 769 RETURN(ErrorStatus); 770 771 /* 772 * set the ximage data using optimized functions for ZPixmap 773 */ 774 775 if (ximage->bits_per_pixel == 8) 776 PutImagePixels8(ximage, image->width, image->height, 777 image->data, image_pixels); 778 else if (((ximage->bits_per_pixel | ximage->depth) == 1) && 779 (ximage->byte_order == ximage->bitmap_bit_order)) 780 PutImagePixels1(ximage, image->width, image->height, 781 image->data, image_pixels); 782 else if (ximage->bits_per_pixel == 16) 783 PutImagePixels16(ximage, image->width, image->height, 784 image->data, image_pixels); 785 else if (ximage->bits_per_pixel == 32) 786 PutImagePixels32(ximage, image->width, image->height, 787 image->data, image_pixels); 788 else 789 PutImagePixels(ximage, image->width, image->height, 790 image->data, image_pixels); 791 } 792 /* create the shape mask image */ 793 if (mask_pixel_index != XpmUndefPixel && shapeimage_return) { 794 ErrorStatus = CreateXImage(display, visual, 1, bitmap_format, 795 image->width, image->height, &shapeimage); 796 if (ErrorStatus != XpmSuccess) 797 RETURN(ErrorStatus); 798 799 PutImagePixels1(shapeimage, image->width, image->height, 800 image->data, mask_pixels); 801 802 } 803 XpmFree(image_pixels); 804 XpmFree(mask_pixels); 805 806 /* if requested return used pixels in the XpmAttributes structure */ 807 if (attributes && (attributes->valuemask & XpmReturnPixels || 808 /* 3.2 backward compatibility code */ 809 attributes->valuemask & XpmReturnInfos)) { 810 /* end 3.2 bc */ 811 attributes->pixels = used_pixels; 812 attributes->npixels = nused_pixels; 813 attributes->mask_pixel = mask_pixel_index; 814 } else 815 XpmFree(used_pixels); 816 817 /* if requested return alloc'ed pixels in the XpmAttributes structure */ 818 if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) { 819 attributes->alloc_pixels = alloc_pixels; 820 attributes->nalloc_pixels = nalloc_pixels; 821 } else 822 XpmFree(alloc_pixels); 823 824 /* return created images */ 825 if (image_return) 826 *image_return = ximage; 827 if (shapeimage_return) 828 *shapeimage_return = shapeimage; 829 830 return (ErrorStatus); 831 832 /* exit point in case of error, free only locally allocated variables */ 833 error: 834 if (ximage) 835 XDestroyImage(ximage); 836 if (shapeimage) 837 XDestroyImage(shapeimage); 838 if (image_pixels) 839 XpmFree(image_pixels); 840 if (mask_pixels) 841 XpmFree(mask_pixels); 842 if (nalloc_pixels) 843 (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); 844 if (alloc_pixels) 845 XpmFree(alloc_pixels); 846 if (used_pixels) 847 XpmFree(used_pixels); 848 849 return (ErrorStatus); 850 } 851 852 853 /* 854 * Create an XImage with its data 855 */ 856 static int 857 CreateXImage( 858 Display *display, 859 Visual *visual, 860 unsigned int depth, 861 int format, 862 unsigned int width, 863 unsigned int height, 864 XImage **image_return) 865 { 866 int bitmap_pad; 867 868 /* first get bitmap_pad */ 869 if (depth > 16) 870 bitmap_pad = 32; 871 else if (depth > 8) 872 bitmap_pad = 16; 873 else 874 bitmap_pad = 8; 875 876 /* then create the XImage with data = NULL and bytes_per_line = 0 */ 877 *image_return = XCreateImage(display, visual, depth, format, 0, 0, 878 width, height, bitmap_pad, 0); 879 if (!*image_return) 880 return (XpmNoMemory); 881 882 if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) { 883 XDestroyImage(*image_return); 884 *image_return = NULL; 885 return XpmNoMemory; 886 } 887 if (width != 0 && (*image_return)->bits_per_pixel >= INT_MAX / width) { 888 XDestroyImage(*image_return); 889 *image_return = NULL; 890 return XpmNoMemory; 891 } 892 /* now that bytes_per_line must have been set properly alloc data */ 893 if((*image_return)->bytes_per_line == 0 || height == 0) { 894 XDestroyImage(*image_return); 895 *image_return = NULL; 896 return XpmNoMemory; 897 } 898 (*image_return)->data = 899 (char *) XpmMalloc((*image_return)->bytes_per_line * height); 900 901 if (!(*image_return)->data) { 902 XDestroyImage(*image_return); 903 *image_return = NULL; 904 return (XpmNoMemory); 905 } 906 return (XpmSuccess); 907 } 908 909 /* 910 * The functions below are written from X11R5 MIT's code (XImUtil.c) 911 * 912 * The idea is to have faster functions than the standard XPutPixel function 913 * to build the image data. Indeed we can speed up things by suppressing tests 914 * performed for each pixel. We do the same tests but at the image level. 915 * We also assume that we use only ZPixmap images with null offsets. 916 */ 917 918 LFUNC(_putbits, void, (register char *src, int dstoffset, 919 register int numbits, register char *dst)); 920 921 LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb)); 922 923 static unsigned char const _reverse_byte[0x100] = { 924 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, 925 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, 926 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, 927 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, 928 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, 929 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, 930 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, 931 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, 932 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, 933 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, 934 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, 935 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, 936 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, 937 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, 938 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, 939 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, 940 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, 941 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, 942 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, 943 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, 944 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, 945 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, 946 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, 947 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, 948 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, 949 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, 950 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, 951 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, 952 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, 953 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, 954 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, 955 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff 956 }; 957 958 static int 959 _XReverse_Bytes( 960 register unsigned char *bpt, 961 register unsigned int nb) 962 { 963 do { 964 *bpt = _reverse_byte[*bpt]; 965 bpt++; 966 } while (--nb > 0); /* is nb user-controled? */ 967 return 0; 968 } 969 970 971 void 972 xpm_xynormalizeimagebits( 973 register unsigned char *bp, 974 register XImage *img) 975 { 976 register unsigned char c; 977 978 if (img->byte_order != img->bitmap_bit_order) { 979 switch (img->bitmap_unit) { 980 981 case 16: 982 c = *bp; 983 *bp = *(bp + 1); 984 *(bp + 1) = c; 985 break; 986 987 case 32: 988 c = *(bp + 3); 989 *(bp + 3) = *bp; 990 *bp = c; 991 c = *(bp + 2); 992 *(bp + 2) = *(bp + 1); 993 *(bp + 1) = c; 994 break; 995 } 996 } 997 if (img->bitmap_bit_order == MSBFirst) 998 _XReverse_Bytes(bp, img->bitmap_unit >> 3); 999 } 1000 1001 void 1002 xpm_znormalizeimagebits( 1003 register unsigned char *bp, 1004 register XImage *img) 1005 { 1006 register unsigned char c; 1007 1008 switch (img->bits_per_pixel) { 1009 1010 case 2: 1011 _XReverse_Bytes(bp, 1); 1012 break; 1013 1014 case 4: 1015 *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF); 1016 break; 1017 1018 case 16: 1019 c = *bp; 1020 *bp = *(bp + 1); 1021 *(bp + 1) = c; 1022 break; 1023 1024 case 24: 1025 c = *(bp + 2); 1026 *(bp + 2) = *bp; 1027 *bp = c; 1028 break; 1029 1030 case 32: 1031 c = *(bp + 3); 1032 *(bp + 3) = *bp; 1033 *bp = c; 1034 c = *(bp + 2); 1035 *(bp + 2) = *(bp + 1); 1036 *(bp + 1) = c; 1037 break; 1038 } 1039 } 1040 1041 static unsigned char const _lomask[0x09] = { 1042 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; 1043 static unsigned char const _himask[0x09] = { 1044 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; 1045 1046 static void 1047 _putbits( 1048 register char *src, /* address of source bit string */ 1049 int dstoffset, /* bit offset into destination; 1050 * range is 0-31 */ 1051 register int numbits, /* number of bits to copy to 1052 * destination */ 1053 register char *dst) /* address of destination bit string */ 1054 { 1055 register unsigned char chlo, chhi; 1056 int hibits; 1057 1058 dst = dst + (dstoffset >> 3); 1059 dstoffset = dstoffset & 7; 1060 hibits = 8 - dstoffset; 1061 chlo = *dst & _lomask[dstoffset]; 1062 for (;;) { 1063 chhi = (*src << dstoffset) & _himask[dstoffset]; 1064 if (numbits <= hibits) { 1065 chhi = chhi & _lomask[dstoffset + numbits]; 1066 *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi; 1067 break; 1068 } 1069 *dst = chhi | chlo; 1070 dst++; 1071 numbits = numbits - hibits; 1072 chlo = (unsigned char) (*src & _himask[hibits]) >> hibits; 1073 src++; 1074 if (numbits <= dstoffset) { 1075 chlo = chlo & _lomask[numbits]; 1076 *dst = (*dst & _himask[numbits]) | chlo; 1077 break; 1078 } 1079 numbits = numbits - dstoffset; 1080 } 1081 } 1082 1083 /* 1084 * Default method to write pixels into a Z image data structure. 1085 * The algorithm used is: 1086 * 1087 * copy the destination bitmap_unit or Zpixel to temp 1088 * normalize temp if needed 1089 * copy the pixel bits into the temp 1090 * renormalize temp if needed 1091 * copy the temp back into the destination image data 1092 */ 1093 1094 static void 1095 PutImagePixels( 1096 XImage *image, 1097 unsigned int width, 1098 unsigned int height, 1099 unsigned int *pixelindex, 1100 Pixel *pixels) 1101 { 1102 register char *src; 1103 register char *dst; 1104 register unsigned int *iptr; 1105 register unsigned int x, y; 1106 register char *data; 1107 Pixel pixel, px; 1108 int nbytes, depth, ibu, ibpp, i; 1109 1110 data = image->data; 1111 iptr = pixelindex; 1112 depth = image->depth; 1113 if (depth == 1) { 1114 ibu = image->bitmap_unit; 1115 for (y = 0; y < height; y++) /* how can we trust height */ 1116 for (x = 0; x < width; x++, iptr++) { /* how can we trust width */ 1117 pixel = pixels[*iptr]; 1118 for (i = 0, px = pixel; i < sizeof(unsigned long); 1119 i++, px >>= 8) 1120 ((unsigned char *) &pixel)[i] = px; 1121 src = &data[XYINDEX(x, y, image)]; 1122 dst = (char *) &px; 1123 px = 0; 1124 nbytes = ibu >> 3; 1125 for (i = nbytes; --i >= 0;) 1126 *dst++ = *src++; 1127 XYNORMALIZE(&px, image); 1128 _putbits((char *) &pixel, (x % ibu), 1, (char *) &px); 1129 XYNORMALIZE(&px, image); 1130 src = (char *) &px; 1131 dst = &data[XYINDEX(x, y, image)]; 1132 for (i = nbytes; --i >= 0;) 1133 *dst++ = *src++; 1134 } 1135 } else { 1136 ibpp = image->bits_per_pixel; 1137 for (y = 0; y < height; y++) 1138 for (x = 0; x < width; x++, iptr++) { 1139 pixel = pixels[*iptr]; 1140 if (depth == 4) 1141 pixel &= 0xf; 1142 for (i = 0, px = pixel; i < sizeof(unsigned long); i++, 1143 px >>= 8) 1144 ((unsigned char *) &pixel)[i] = px; 1145 src = &data[ZINDEX(x, y, image)]; 1146 dst = (char *) &px; 1147 px = 0; 1148 nbytes = (ibpp + 7) >> 3; 1149 for (i = nbytes; --i >= 0;) 1150 *dst++ = *src++; 1151 ZNORMALIZE(&px, image); 1152 _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px); 1153 ZNORMALIZE(&px, image); 1154 src = (char *) &px; 1155 dst = &data[ZINDEX(x, y, image)]; 1156 for (i = nbytes; --i >= 0;) 1157 *dst++ = *src++; 1158 } 1159 } 1160 } 1161 1162 /* 1163 * write pixels into a 32-bits Z image data structure 1164 */ 1165 1166 #if !defined(WORD64) && !defined(LONG64) 1167 /* this item is static but deterministic so let it slide; doesn't 1168 * hurt re-entrancy of this library. Note if it is actually const then would 1169 * be OK under rules of ANSI-C but probably not C++ which may not 1170 * want to allocate space for it. 1171 */ 1172 static unsigned long byteorderpixel = MSBFirst << 24; 1173 1174 #endif 1175 1176 /* 1177 WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original 1178 3.2e code - by default you get the speeded-up version. 1179 */ 1180 1181 static void 1182 PutImagePixels32( 1183 XImage *image, 1184 unsigned int width, 1185 unsigned int height, 1186 unsigned int *pixelindex, 1187 Pixel *pixels) 1188 { 1189 unsigned char *data; 1190 unsigned int *iptr; 1191 unsigned int y; 1192 Pixel pixel; 1193 1194 #ifdef WITHOUT_SPEEDUPS 1195 1196 unsigned int x; 1197 unsigned char *addr; 1198 1199 data = (unsigned char *) image->data; 1200 iptr = pixelindex; 1201 #if !defined(WORD64) && !defined(LONG64) 1202 if (*((char *) &byteorderpixel) == image->byte_order) { 1203 for (y = 0; y < height; y++) 1204 for (x = 0; x < width; x++, iptr++) { 1205 addr = &data[ZINDEX32(x, y, image)]; 1206 *((unsigned long *) addr) = pixels[*iptr]; 1207 } 1208 } else 1209 #endif 1210 if (image->byte_order == MSBFirst) 1211 for (y = 0; y < height; y++) 1212 for (x = 0; x < width; x++, iptr++) { 1213 addr = &data[ZINDEX32(x, y, image)]; 1214 pixel = pixels[*iptr]; 1215 addr[0] = pixel >> 24; 1216 addr[1] = pixel >> 16; 1217 addr[2] = pixel >> 8; 1218 addr[3] = pixel; 1219 } 1220 else 1221 for (y = 0; y < height; y++) 1222 for (x = 0; x < width; x++, iptr++) { 1223 addr = &data[ZINDEX32(x, y, image)]; 1224 pixel = pixels[*iptr]; 1225 addr[0] = pixel; 1226 addr[1] = pixel >> 8; 1227 addr[2] = pixel >> 16; 1228 addr[3] = pixel >> 24; 1229 } 1230 1231 #else /* WITHOUT_SPEEDUPS */ 1232 1233 unsigned int bpl = image->bytes_per_line; 1234 unsigned char *data_ptr, *max_data; 1235 1236 data = (unsigned char *) image->data; 1237 iptr = pixelindex; 1238 #if !defined(WORD64) && !defined(LONG64) 1239 if (*((char *) &byteorderpixel) == image->byte_order) { 1240 for (y = 0; y < height; y++) { 1241 data_ptr = data; 1242 max_data = data_ptr + (width << 2); 1243 1244 while (data_ptr < max_data) { 1245 *((unsigned long *) data_ptr) = pixels[*(iptr++)]; 1246 data_ptr += (1 << 2); 1247 } 1248 data += bpl; 1249 } 1250 } else 1251 #endif 1252 if (image->byte_order == MSBFirst) 1253 for (y = 0; y < height; y++) { 1254 data_ptr = data; 1255 max_data = data_ptr + (width << 2); 1256 1257 while (data_ptr < max_data) { 1258 pixel = pixels[*(iptr++)]; 1259 1260 *data_ptr++ = pixel >> 24; 1261 *data_ptr++ = pixel >> 16; 1262 *data_ptr++ = pixel >> 8; 1263 *data_ptr++ = pixel; 1264 1265 } 1266 data += bpl; 1267 } 1268 else 1269 for (y = 0; y < height; y++) { 1270 data_ptr = data; 1271 max_data = data_ptr + (width << 2); 1272 1273 while (data_ptr < max_data) { 1274 pixel = pixels[*(iptr++)]; 1275 1276 *data_ptr++ = pixel; 1277 *data_ptr++ = pixel >> 8; 1278 *data_ptr++ = pixel >> 16; 1279 *data_ptr++ = pixel >> 24; 1280 } 1281 data += bpl; 1282 } 1283 1284 #endif /* WITHOUT_SPEEDUPS */ 1285 } 1286 1287 /* 1288 * write pixels into a 16-bits Z image data structure 1289 */ 1290 1291 static void 1292 PutImagePixels16( 1293 XImage *image, 1294 unsigned int width, 1295 unsigned int height, 1296 unsigned int *pixelindex, 1297 Pixel *pixels) 1298 { 1299 unsigned char *data; 1300 unsigned int *iptr; 1301 unsigned int y; 1302 1303 #ifdef WITHOUT_SPEEDUPS 1304 1305 unsigned int x; 1306 unsigned char *addr; 1307 1308 data = (unsigned char *) image->data; 1309 iptr = pixelindex; 1310 if (image->byte_order == MSBFirst) 1311 for (y = 0; y < height; y++) 1312 for (x = 0; x < width; x++, iptr++) { 1313 addr = &data[ZINDEX16(x, y, image)]; 1314 addr[0] = pixels[*iptr] >> 8; 1315 addr[1] = pixels[*iptr]; 1316 } 1317 else 1318 for (y = 0; y < height; y++) 1319 for (x = 0; x < width; x++, iptr++) { 1320 addr = &data[ZINDEX16(x, y, image)]; 1321 addr[0] = pixels[*iptr]; 1322 addr[1] = pixels[*iptr] >> 8; 1323 } 1324 1325 #else /* WITHOUT_SPEEDUPS */ 1326 1327 Pixel pixel; 1328 1329 unsigned int bpl = image->bytes_per_line; 1330 unsigned char *data_ptr, *max_data; 1331 1332 data = (unsigned char *) image->data; 1333 iptr = pixelindex; 1334 if (image->byte_order == MSBFirst) 1335 for (y = 0; y < height; y++) { 1336 data_ptr = data; 1337 max_data = data_ptr + (width << 1); 1338 1339 while (data_ptr < max_data) { 1340 pixel = pixels[*(iptr++)]; 1341 1342 data_ptr[0] = pixel >> 8; 1343 data_ptr[1] = pixel; 1344 1345 data_ptr += (1 << 1); 1346 } 1347 data += bpl; 1348 } 1349 else 1350 for (y = 0; y < height; y++) { 1351 data_ptr = data; 1352 max_data = data_ptr + (width << 1); 1353 1354 while (data_ptr < max_data) { 1355 pixel = pixels[*(iptr++)]; 1356 1357 data_ptr[0] = pixel; 1358 data_ptr[1] = pixel >> 8; 1359 1360 data_ptr += (1 << 1); 1361 } 1362 data += bpl; 1363 } 1364 1365 #endif /* WITHOUT_SPEEDUPS */ 1366 } 1367 1368 /* 1369 * write pixels into a 8-bits Z image data structure 1370 */ 1371 1372 static void 1373 PutImagePixels8( 1374 XImage *image, 1375 unsigned int width, 1376 unsigned int height, 1377 unsigned int *pixelindex, 1378 Pixel *pixels) 1379 { 1380 char *data; 1381 unsigned int *iptr; 1382 unsigned int y; 1383 1384 #ifdef WITHOUT_SPEEDUPS 1385 1386 unsigned int x; 1387 1388 data = image->data; 1389 iptr = pixelindex; 1390 for (y = 0; y < height; y++) 1391 for (x = 0; x < width; x++, iptr++) 1392 data[ZINDEX8(x, y, image)] = pixels[*iptr]; 1393 1394 #else /* WITHOUT_SPEEDUPS */ 1395 1396 unsigned int bpl = image->bytes_per_line; 1397 char *data_ptr, *max_data; 1398 1399 data = image->data; 1400 iptr = pixelindex; 1401 1402 for (y = 0; y < height; y++) { 1403 data_ptr = data; 1404 max_data = data_ptr + width; 1405 1406 while (data_ptr < max_data) 1407 *(data_ptr++) = pixels[*(iptr++)]; 1408 1409 data += bpl; 1410 } 1411 1412 #endif /* WITHOUT_SPEEDUPS */ 1413 } 1414 1415 /* 1416 * write pixels into a 1-bit depth image data structure and **offset null** 1417 */ 1418 1419 static void 1420 PutImagePixels1( 1421 XImage *image, 1422 unsigned int width, 1423 unsigned int height, 1424 unsigned int *pixelindex, 1425 Pixel *pixels) 1426 { 1427 if (image->byte_order != image->bitmap_bit_order) 1428 PutImagePixels(image, width, height, pixelindex, pixels); 1429 else { 1430 unsigned int *iptr; 1431 unsigned int y; 1432 char *data; 1433 1434 #ifdef WITHOUT_SPEEDUPS 1435 1436 unsigned int x; 1437 1438 data = image->data; 1439 iptr = pixelindex; 1440 if (image->bitmap_bit_order == MSBFirst) 1441 for (y = 0; y < height; y++) 1442 for (x = 0; x < width; x++, iptr++) { 1443 if (pixels[*iptr] & 1) 1444 data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7); 1445 else 1446 data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7)); 1447 } 1448 else 1449 for (y = 0; y < height; y++) 1450 for (x = 0; x < width; x++, iptr++) { 1451 if (pixels[*iptr] & 1) 1452 data[ZINDEX1(x, y, image)] |= 1 << (x & 7); 1453 else 1454 data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7)); 1455 } 1456 1457 #else /* WITHOUT_SPEEDUPS */ 1458 1459 char value; 1460 char *data_ptr, *max_data; 1461 int bpl = image->bytes_per_line; 1462 int diff, count; 1463 1464 data = image->data; 1465 iptr = pixelindex; 1466 1467 diff = width & 7; 1468 width >>= 3; 1469 1470 if (image->bitmap_bit_order == MSBFirst) 1471 for (y = 0; y < height; y++) { 1472 data_ptr = data; 1473 max_data = data_ptr + width; 1474 while (data_ptr < max_data) { 1475 value = 0; 1476 1477 value = (value << 1) | (pixels[*(iptr++)] & 1); 1478 value = (value << 1) | (pixels[*(iptr++)] & 1); 1479 value = (value << 1) | (pixels[*(iptr++)] & 1); 1480 value = (value << 1) | (pixels[*(iptr++)] & 1); 1481 value = (value << 1) | (pixels[*(iptr++)] & 1); 1482 value = (value << 1) | (pixels[*(iptr++)] & 1); 1483 value = (value << 1) | (pixels[*(iptr++)] & 1); 1484 value = (value << 1) | (pixels[*(iptr++)] & 1); 1485 1486 *(data_ptr++) = value; 1487 } 1488 if (diff) { 1489 value = 0; 1490 for (count = 0; count < diff; count++) { 1491 if (pixels[*(iptr++)] & 1) 1492 value |= (0x80 >> count); 1493 } 1494 *(data_ptr) = value; 1495 } 1496 data += bpl; 1497 } 1498 else 1499 for (y = 0; y < height; y++) { 1500 data_ptr = data; 1501 max_data = data_ptr + width; 1502 while (data_ptr < max_data) { 1503 value = 0; 1504 iptr += 8; 1505 1506 value = (value << 1) | (pixels[*(--iptr)] & 1); 1507 value = (value << 1) | (pixels[*(--iptr)] & 1); 1508 value = (value << 1) | (pixels[*(--iptr)] & 1); 1509 value = (value << 1) | (pixels[*(--iptr)] & 1); 1510 value = (value << 1) | (pixels[*(--iptr)] & 1); 1511 value = (value << 1) | (pixels[*(--iptr)] & 1); 1512 value = (value << 1) | (pixels[*(--iptr)] & 1); 1513 value = (value << 1) | (pixels[*(--iptr)] & 1); 1514 1515 iptr += 8; 1516 *(data_ptr++) = value; 1517 } 1518 if (diff) { 1519 value = 0; 1520 for (count = 0; count < diff; count++) { 1521 if (pixels[*(iptr++)] & 1) 1522 value |= (1 << count); 1523 } 1524 *(data_ptr) = value; 1525 } 1526 data += bpl; 1527 } 1528 1529 #endif /* WITHOUT_SPEEDUPS */ 1530 } 1531 } 1532 1533 int 1534 XpmCreatePixmapFromXpmImage( 1535 Display *display, 1536 Drawable d, 1537 XpmImage *image, 1538 Pixmap *pixmap_return, 1539 Pixmap *shapemask_return, 1540 XpmAttributes *attributes) 1541 { 1542 XImage *ximage = NULL, *shapeimage = NULL; 1543 int ErrorStatus; 1544 1545 /* initialize return values */ 1546 if (pixmap_return) 1547 *pixmap_return = 0; 1548 if (shapemask_return) 1549 *shapemask_return = 0; 1550 1551 /* create the ximages */ 1552 ErrorStatus = XpmCreateImageFromXpmImage(display, image, 1553 (pixmap_return ? &ximage : NULL), 1554 (shapemask_return ? 1555 &shapeimage : NULL), 1556 attributes); 1557 if (ErrorStatus < 0) 1558 goto cleanup; 1559 1560 /* create the pixmaps and destroy images */ 1561 if (pixmap_return && ximage) { 1562 ErrorStatus = 1563 xpmCreatePixmapFromImage(display, d, ximage, pixmap_return); 1564 if (ErrorStatus < 0) /* fatal error */ 1565 goto cleanup; 1566 } 1567 if (shapemask_return && shapeimage) { 1568 ErrorStatus = 1569 xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return); 1570 } 1571 1572 cleanup: 1573 if (ximage != NULL) 1574 XDestroyImage(ximage); 1575 if (shapeimage != NULL) 1576 XDestroyImage(shapeimage); 1577 if (ErrorStatus < 0) { 1578 if (pixmap_return && *pixmap_return) { 1579 XFreePixmap(display, *pixmap_return); 1580 *pixmap_return = 0; 1581 } 1582 if (shapemask_return && *shapemask_return) { 1583 XFreePixmap(display, *shapemask_return); 1584 *shapemask_return = 0; 1585 } 1586 } 1587 return (ErrorStatus); 1588 } 1589 1590 static int 1591 PutPixel1( 1592 register XImage *ximage, 1593 int x, 1594 int y, 1595 unsigned long pixel) 1596 { 1597 register char *src; 1598 register char *dst; 1599 register int i; 1600 Pixel px; 1601 int nbytes; 1602 1603 if(x < 0 || y < 0) 1604 return 0; 1605 1606 for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8) 1607 ((unsigned char *)&pixel)[i] = px; 1608 src = &ximage->data[XYINDEX(x, y, ximage)]; 1609 dst = (char *)&px; 1610 px = 0; 1611 nbytes = ximage->bitmap_unit >> 3; 1612 for (i = nbytes; --i >= 0; ) *dst++ = *src++; 1613 XYNORMALIZE(&px, ximage); 1614 i = ((x + ximage->xoffset) % ximage->bitmap_unit); 1615 _putbits ((char *)&pixel, i, 1, (char *)&px); 1616 XYNORMALIZE(&px, ximage); 1617 src = (char *) &px; 1618 dst = &ximage->data[XYINDEX(x, y, ximage)]; 1619 for (i = nbytes; --i >= 0; ) 1620 *dst++ = *src++; 1621 1622 return 1; 1623 } 1624 1625 static int 1626 PutPixel( 1627 register XImage *ximage, 1628 int x, 1629 int y, 1630 unsigned long pixel) 1631 { 1632 register char *src; 1633 register char *dst; 1634 register int i; 1635 Pixel px; 1636 unsigned int nbytes, ibpp; 1637 1638 if(x < 0 || y < 0) 1639 return 0; 1640 1641 ibpp = ximage->bits_per_pixel; 1642 if (ximage->depth == 4) 1643 pixel &= 0xf; 1644 for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8) 1645 ((unsigned char *) &pixel)[i] = px; 1646 src = &ximage->data[ZINDEX(x, y, ximage)]; 1647 dst = (char *) &px; 1648 px = 0; 1649 nbytes = (ibpp + 7) >> 3; 1650 for (i = nbytes; --i >= 0;) 1651 *dst++ = *src++; 1652 ZNORMALIZE(&px, ximage); 1653 _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px); 1654 ZNORMALIZE(&px, ximage); 1655 src = (char *) &px; 1656 dst = &ximage->data[ZINDEX(x, y, ximage)]; 1657 for (i = nbytes; --i >= 0;) 1658 *dst++ = *src++; 1659 1660 return 1; 1661 } 1662 1663 #if !defined(WORD64) && !defined(LONG64) 1664 static int 1665 PutPixel32( 1666 register XImage *ximage, 1667 int x, 1668 int y, 1669 unsigned long pixel) 1670 { 1671 unsigned char *addr; 1672 1673 if(x < 0 || y < 0) 1674 return 0; 1675 1676 addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)]; 1677 *((unsigned long *)addr) = pixel; 1678 return 1; 1679 } 1680 #endif 1681 1682 static int 1683 PutPixel32MSB( 1684 register XImage *ximage, 1685 int x, 1686 int y, 1687 unsigned long pixel) 1688 { 1689 unsigned char *addr; 1690 1691 if(x < 0 || y < 0) 1692 return 0; 1693 1694 addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)]; 1695 addr[0] = pixel >> 24; 1696 addr[1] = pixel >> 16; 1697 addr[2] = pixel >> 8; 1698 addr[3] = pixel; 1699 return 1; 1700 } 1701 1702 static int 1703 PutPixel32LSB( 1704 register XImage *ximage, 1705 int x, 1706 int y, 1707 unsigned long pixel) 1708 { 1709 unsigned char *addr; 1710 1711 if(x < 0 || y < 0) 1712 return 0; 1713 1714 addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)]; 1715 addr[3] = pixel >> 24; 1716 addr[2] = pixel >> 16; 1717 addr[1] = pixel >> 8; 1718 addr[0] = pixel; 1719 return 1; 1720 } 1721 1722 static int 1723 PutPixel16MSB( 1724 register XImage *ximage, 1725 int x, 1726 int y, 1727 unsigned long pixel) 1728 { 1729 unsigned char *addr; 1730 1731 if(x < 0 || y < 0) 1732 return 0; 1733 1734 addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)]; 1735 addr[0] = pixel >> 8; 1736 addr[1] = pixel; 1737 return 1; 1738 } 1739 1740 static int 1741 PutPixel16LSB( 1742 register XImage *ximage, 1743 int x, 1744 int y, 1745 unsigned long pixel) 1746 { 1747 unsigned char *addr; 1748 1749 if(x < 0 || y < 0) 1750 return 0; 1751 1752 addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)]; 1753 addr[1] = pixel >> 8; 1754 addr[0] = pixel; 1755 return 1; 1756 } 1757 1758 static int 1759 PutPixel8( 1760 register XImage *ximage, 1761 int x, 1762 int y, 1763 unsigned long pixel) 1764 { 1765 if(x < 0 || y < 0) 1766 return 0; 1767 1768 ximage->data[ZINDEX8(x, y, ximage)] = pixel; 1769 return 1; 1770 } 1771 1772 static int 1773 PutPixel1MSB( 1774 register XImage *ximage, 1775 int x, 1776 int y, 1777 unsigned long pixel) 1778 { 1779 if(x < 0 || y < 0) 1780 return 0; 1781 1782 if (pixel & 1) 1783 ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7); 1784 else 1785 ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7)); 1786 return 1; 1787 } 1788 1789 static int 1790 PutPixel1LSB( 1791 register XImage *ximage, 1792 int x, 1793 int y, 1794 unsigned long pixel) 1795 { 1796 if(x < 0 || y < 0) 1797 return 0; 1798 1799 if (pixel & 1) 1800 ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7); 1801 else 1802 ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7)); 1803 return 1; 1804 } 1805 1806 1807 /* 1808 * This function parses an Xpm file or data and directly create an XImage 1809 */ 1810 int 1811 xpmParseDataAndCreate( 1812 Display *display, 1813 xpmData *data, 1814 XImage **image_return, 1815 XImage **shapeimage_return, 1816 XpmImage *image, 1817 XpmInfo *info, 1818 XpmAttributes *attributes) 1819 { 1820 /* variables stored in the XpmAttributes structure */ 1821 Visual *visual; 1822 Colormap colormap; 1823 unsigned int depth; 1824 int bitmap_format; 1825 XpmFreeColorsFunc freeColors; 1826 1827 /* variables to return */ 1828 XImage *ximage = NULL; 1829 XImage *shapeimage = NULL; 1830 unsigned int mask_pixel_index = XpmUndefPixel; 1831 1832 /* calculation variables */ 1833 Pixel *image_pixels = NULL; 1834 Pixel *mask_pixels = NULL; 1835 Pixel *alloc_pixels = NULL; 1836 Pixel *used_pixels = NULL; 1837 unsigned int nalloc_pixels = 0; 1838 unsigned int nused_pixels = 0; 1839 unsigned int width, height, ncolors, cpp; 1840 unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0; 1841 XpmColor *colorTable = NULL; 1842 char *hints_cmt = NULL; 1843 char *colors_cmt = NULL; 1844 char *pixels_cmt = NULL; 1845 1846 unsigned int cmts; 1847 int ErrorStatus; 1848 xpmHashTable hashtable; 1849 1850 1851 /* initialize return values */ 1852 if (image_return) 1853 *image_return = NULL; 1854 if (shapeimage_return) 1855 *shapeimage_return = NULL; 1856 1857 1858 /* retrieve information from the XpmAttributes */ 1859 if (attributes && (attributes->valuemask & XpmVisual)) 1860 visual = attributes->visual; 1861 else 1862 visual = XDefaultVisual(display, XDefaultScreen(display)); 1863 1864 if (attributes && (attributes->valuemask & XpmColormap)) 1865 colormap = attributes->colormap; 1866 else 1867 colormap = XDefaultColormap(display, XDefaultScreen(display)); 1868 1869 if (attributes && (attributes->valuemask & XpmDepth)) 1870 depth = attributes->depth; 1871 else 1872 depth = XDefaultDepth(display, XDefaultScreen(display)); 1873 1874 if (attributes && (attributes->valuemask & XpmBitmapFormat)) 1875 bitmap_format = attributes->bitmap_format; 1876 else 1877 bitmap_format = ZPixmap; 1878 1879 if (attributes && (attributes->valuemask & XpmFreeColors)) 1880 freeColors = attributes->free_colors; 1881 else 1882 freeColors = FreeColors; 1883 1884 cmts = info && (info->valuemask & XpmReturnComments); 1885 1886 /* 1887 * parse the header 1888 */ 1889 ErrorStatus = xpmParseHeader(data); 1890 if (ErrorStatus != XpmSuccess) 1891 return (ErrorStatus); 1892 1893 /* 1894 * read values 1895 */ 1896 ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp, 1897 &x_hotspot, &y_hotspot, &hotspot, 1898 &extensions); 1899 if (ErrorStatus != XpmSuccess) 1900 return (ErrorStatus); 1901 1902 /* 1903 * store the hints comment line 1904 */ 1905 if (cmts) 1906 xpmGetCmt(data, &hints_cmt); 1907 1908 /* 1909 * init the hashtable 1910 */ 1911 if (USE_HASHTABLE) { 1912 ErrorStatus = xpmHashTableInit(&hashtable); 1913 if (ErrorStatus != XpmSuccess) 1914 RETURN(ErrorStatus); 1915 } 1916 1917 /* 1918 * read colors 1919 */ 1920 ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable); 1921 if (ErrorStatus != XpmSuccess) 1922 RETURN(ErrorStatus); 1923 1924 /* 1925 * store the colors comment line 1926 */ 1927 if (cmts) 1928 xpmGetCmt(data, &colors_cmt); 1929 1930 /* malloc pixels index tables */ 1931 if (ncolors >= UINT_MAX / sizeof(Pixel)) 1932 RETURN(XpmNoMemory); 1933 1934 image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); 1935 if (!image_pixels) 1936 RETURN(XpmNoMemory); 1937 1938 mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); 1939 if (!mask_pixels) 1940 RETURN(XpmNoMemory); 1941 1942 /* maximum of allocated pixels will be the number of colors */ 1943 alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); 1944 if (!alloc_pixels) 1945 RETURN(XpmNoMemory); 1946 1947 /* maximum of allocated pixels will be the number of colors */ 1948 used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors); 1949 if (!used_pixels) 1950 RETURN(XpmNoMemory); 1951 1952 /* get pixel colors, store them in index tables */ 1953 ErrorStatus = CreateColors(display, attributes, colorTable, ncolors, 1954 image_pixels, mask_pixels, &mask_pixel_index, 1955 alloc_pixels, &nalloc_pixels, used_pixels, 1956 &nused_pixels); 1957 1958 if (ErrorStatus != XpmSuccess 1959 && (ErrorStatus < 0 || (attributes 1960 && (attributes->valuemask & XpmExactColors) 1961 && attributes->exactColors))) 1962 RETURN(ErrorStatus); 1963 1964 /* now create the ximage */ 1965 if (image_return) { 1966 ErrorStatus = CreateXImage(display, visual, depth, 1967 (depth == 1 ? bitmap_format : ZPixmap), 1968 width, height, &ximage); 1969 if (ErrorStatus != XpmSuccess) 1970 RETURN(ErrorStatus); 1971 1972 1973 /* 1974 * set the XImage pointer function, to be used with XPutPixel, 1975 * to an internal optimized function 1976 */ 1977 1978 if (ximage->bits_per_pixel == 8) 1979 ximage->f.put_pixel = PutPixel8; 1980 else if (((ximage->bits_per_pixel | ximage->depth) == 1) && 1981 (ximage->byte_order == ximage->bitmap_bit_order)) 1982 if (ximage->bitmap_bit_order == MSBFirst) 1983 ximage->f.put_pixel = PutPixel1MSB; 1984 else 1985 ximage->f.put_pixel = PutPixel1LSB; 1986 else if (ximage->bits_per_pixel == 16) 1987 if (ximage->bitmap_bit_order == MSBFirst) 1988 ximage->f.put_pixel = PutPixel16MSB; 1989 else 1990 ximage->f.put_pixel = PutPixel16LSB; 1991 else if (ximage->bits_per_pixel == 32) 1992 #if !defined(WORD64) && !defined(LONG64) 1993 if (*((char *)&byteorderpixel) == ximage->byte_order) 1994 ximage->f.put_pixel = PutPixel32; 1995 else 1996 #endif 1997 if (ximage->bitmap_bit_order == MSBFirst) 1998 ximage->f.put_pixel = PutPixel32MSB; 1999 else 2000 ximage->f.put_pixel = PutPixel32LSB; 2001 else if ((ximage->bits_per_pixel | ximage->depth) == 1) 2002 ximage->f.put_pixel = PutPixel1; 2003 else 2004 ximage->f.put_pixel = PutPixel; 2005 } 2006 2007 /* create the shape mask image */ 2008 if (mask_pixel_index != XpmUndefPixel && shapeimage_return) { 2009 ErrorStatus = CreateXImage(display, visual, 1, bitmap_format, 2010 width, height, &shapeimage); 2011 if (ErrorStatus != XpmSuccess) 2012 RETURN(ErrorStatus); 2013 2014 if (shapeimage->bitmap_bit_order == MSBFirst) 2015 shapeimage->f.put_pixel = PutPixel1MSB; 2016 else 2017 shapeimage->f.put_pixel = PutPixel1LSB; 2018 } 2019 2020 /* 2021 * read pixels and put them in the XImage 2022 */ 2023 ErrorStatus = ParseAndPutPixels(data, width, height, ncolors, cpp, 2024 colorTable, &hashtable, 2025 ximage, image_pixels, 2026 shapeimage, mask_pixels); 2027 XpmFree(image_pixels); 2028 image_pixels = NULL; 2029 XpmFree(mask_pixels); 2030 mask_pixels = NULL; 2031 2032 /* 2033 * free the hastable 2034 */ 2035 if (ErrorStatus != XpmSuccess) 2036 RETURN(ErrorStatus); 2037 else if (USE_HASHTABLE) 2038 xpmHashTableFree(&hashtable); 2039 2040 /* 2041 * store the pixels comment line 2042 */ 2043 if (cmts) 2044 xpmGetCmt(data, &pixels_cmt); 2045 2046 /* 2047 * parse extensions 2048 */ 2049 if (info && (info->valuemask & XpmReturnExtensions)) { 2050 if (extensions) { 2051 ErrorStatus = xpmParseExtensions(data, &info->extensions, 2052 &info->nextensions); 2053 if (ErrorStatus != XpmSuccess) 2054 RETURN(ErrorStatus); 2055 } else { 2056 info->extensions = NULL; 2057 info->nextensions = 0; 2058 } 2059 } 2060 /* 2061 * store found information in the XpmImage structure 2062 */ 2063 image->width = width; 2064 image->height = height; 2065 image->cpp = cpp; 2066 image->ncolors = ncolors; 2067 image->colorTable = colorTable; 2068 image->data = NULL; 2069 2070 if (info) { 2071 if (cmts) { 2072 info->hints_cmt = hints_cmt; 2073 info->colors_cmt = colors_cmt; 2074 info->pixels_cmt = pixels_cmt; 2075 } 2076 if (hotspot) { 2077 info->x_hotspot = x_hotspot; 2078 info->y_hotspot = y_hotspot; 2079 info->valuemask |= XpmHotspot; 2080 } 2081 } 2082 /* if requested return used pixels in the XpmAttributes structure */ 2083 if (attributes && (attributes->valuemask & XpmReturnPixels || 2084 /* 3.2 backward compatibility code */ 2085 attributes->valuemask & XpmReturnInfos)) { 2086 /* end 3.2 bc */ 2087 attributes->pixels = used_pixels; 2088 attributes->npixels = nused_pixels; 2089 attributes->mask_pixel = mask_pixel_index; 2090 } else 2091 XpmFree(used_pixels); 2092 2093 /* if requested return alloc'ed pixels in the XpmAttributes structure */ 2094 if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) { 2095 attributes->alloc_pixels = alloc_pixels; 2096 attributes->nalloc_pixels = nalloc_pixels; 2097 } else 2098 XpmFree(alloc_pixels); 2099 2100 /* return created images */ 2101 if (image_return) 2102 *image_return = ximage; 2103 if (shapeimage_return) 2104 *shapeimage_return = shapeimage; 2105 2106 return (XpmSuccess); 2107 2108 /* exit point in case of error, free only locally allocated variables */ 2109 error: 2110 if (USE_HASHTABLE) 2111 xpmHashTableFree(&hashtable); 2112 if (colorTable) 2113 xpmFreeColorTable(colorTable, ncolors); 2114 if (hints_cmt) 2115 XpmFree(hints_cmt); 2116 if (colors_cmt) 2117 XpmFree(colors_cmt); 2118 if (pixels_cmt) 2119 XpmFree(pixels_cmt); 2120 if (ximage) 2121 XDestroyImage(ximage); 2122 if (shapeimage) 2123 XDestroyImage(shapeimage); 2124 if (image_pixels) 2125 XpmFree(image_pixels); 2126 if (mask_pixels) 2127 XpmFree(mask_pixels); 2128 if (nalloc_pixels) 2129 (*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); 2130 if (alloc_pixels) 2131 XpmFree(alloc_pixels); 2132 if (used_pixels) 2133 XpmFree(used_pixels); 2134 2135 return (ErrorStatus); 2136 } 2137 2138 static int 2139 ParseAndPutPixels( 2140 xpmData *data, 2141 unsigned int width, 2142 unsigned int height, 2143 unsigned int ncolors, 2144 unsigned int cpp, 2145 XpmColor *colorTable, 2146 xpmHashTable *hashtable, 2147 XImage *image, 2148 Pixel *image_pixels, 2149 XImage *shapeimage, 2150 Pixel *shape_pixels) 2151 { 2152 unsigned int a, x, y; 2153 2154 switch (cpp) { 2155 2156 case (1): /* Optimize for single character 2157 * colors */ 2158 { 2159 unsigned short colidx[256]; 2160 2161 if (ncolors > 256) 2162 return (XpmFileInvalid); 2163 2164 bzero((char *)colidx, 256 * sizeof(short)); 2165 for (a = 0; a < ncolors; a++) 2166 colidx[(unsigned char)colorTable[a].string[0]] = a + 1; 2167 2168 for (y = 0; y < height; y++) { 2169 xpmNextString(data); 2170 for (x = 0; x < width; x++) { 2171 int c = xpmGetC(data); 2172 2173 if (c > 0 && c < 256 && colidx[c] != 0) { 2174 XPutPixel(image, x, y, image_pixels[colidx[c] - 1]); 2175 if (shapeimage) 2176 XPutPixel(shapeimage, x, y, 2177 shape_pixels[colidx[c] - 1]); 2178 } else 2179 return (XpmFileInvalid); 2180 } 2181 } 2182 } 2183 break; 2184 2185 case (2): /* Optimize for double character 2186 * colors */ 2187 { 2188 2189 /* free all allocated pointers at all exits */ 2190 #define FREE_CIDX do {int f; for (f = 0; f < 256; f++) \ 2191 if (cidx[f]) XpmFree(cidx[f]);} while(0) 2192 2193 /* array of pointers malloced by need */ 2194 unsigned short *cidx[256]; 2195 unsigned int char1; 2196 2197 bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */ 2198 for (a = 0; a < ncolors; a++) { 2199 char1 = (unsigned char) colorTable[a].string[0]; 2200 if (cidx[char1] == NULL) { /* get new memory */ 2201 cidx[char1] = (unsigned short *) 2202 XpmCalloc(256, sizeof(unsigned short)); 2203 if (cidx[char1] == NULL) { /* new block failed */ 2204 FREE_CIDX; 2205 return (XpmNoMemory); 2206 } 2207 } 2208 cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1; 2209 } 2210 2211 for (y = 0; y < height; y++) { 2212 xpmNextString(data); 2213 for (x = 0; x < width; x++) { 2214 int cc1 = xpmGetC(data); 2215 if (cc1 > 0 && cc1 < 256) { 2216 int cc2 = xpmGetC(data); 2217 if (cc2 > 0 && cc2 < 256 && 2218 cidx[cc1] && cidx[cc1][cc2] != 0) { 2219 XPutPixel(image, x, y, 2220 image_pixels[cidx[cc1][cc2] - 1]); 2221 if (shapeimage) 2222 XPutPixel(shapeimage, x, y, 2223 shape_pixels[cidx[cc1][cc2] - 1]); 2224 } else { 2225 FREE_CIDX; 2226 return (XpmFileInvalid); 2227 } 2228 } else { 2229 FREE_CIDX; 2230 return (XpmFileInvalid); 2231 } 2232 } 2233 } 2234 FREE_CIDX; 2235 } 2236 break; 2237 2238 default: /* Non-optimized case of long color 2239 * names */ 2240 { 2241 char *s; 2242 char buf[BUFSIZ]; 2243 2244 if (cpp >= sizeof(buf)) 2245 return (XpmFileInvalid); 2246 2247 buf[cpp] = '\0'; 2248 if (USE_HASHTABLE) { 2249 xpmHashAtom *slot; 2250 2251 for (y = 0; y < height; y++) { 2252 xpmNextString(data); 2253 for (x = 0; x < width; x++) { 2254 for (a = 0, s = buf; a < cpp; a++, s++) 2255 *s = xpmGetC(data); 2256 slot = xpmHashSlot(hashtable, buf); 2257 if (!*slot) /* no color matches */ 2258 return (XpmFileInvalid); 2259 XPutPixel(image, x, y, 2260 image_pixels[HashColorIndex(slot)]); 2261 if (shapeimage) 2262 XPutPixel(shapeimage, x, y, 2263 shape_pixels[HashColorIndex(slot)]); 2264 } 2265 } 2266 } else { 2267 for (y = 0; y < height; y++) { 2268 xpmNextString(data); 2269 for (x = 0; x < width; x++) { 2270 for (a = 0, s = buf; a < cpp; a++, s++) 2271 *s = xpmGetC(data); 2272 for (a = 0; a < ncolors; a++) 2273 if (!strcmp(colorTable[a].string, buf)) 2274 break; 2275 if (a == ncolors) /* no color matches */ 2276 return (XpmFileInvalid); 2277 XPutPixel(image, x, y, image_pixels[a]); 2278 if (shapeimage) 2279 XPutPixel(shapeimage, x, y, shape_pixels[a]); 2280 } 2281 } 2282 } 2283 } 2284 break; 2285 } 2286 return (XpmSuccess); 2287 } 2288