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