]> git.saurik.com Git - wxWidgets.git/blob - src/xpm/scan.c
added tests for filled rects
[wxWidgets.git] / src / xpm / scan.c
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 * scan.c: *
28 * *
29 * XPM library *
30 * Scanning utility for XPM file format *
31 * *
32 * Developed by Arnaud Le Hors *
33 \*****************************************************************************/
34
35 /*
36 * The code related to FOR_MSW has been added by
37 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
38 */
39
40 /*
41 * The code related to AMIGA has been added by
42 * Lorens Younes (d93-hyo@nada.kth.se) 4/96
43 */
44
45 #include "XpmI.h"
46
47 #define MAXPRINTABLE 92 /* number of printable ascii chars
48 * minus \ and " for string compat
49 * and ? to avoid ANSI trigraphs. */
50
51 static char *printable =
52 " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
53 ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
54
55 /*
56 * printable begin with a space, so in most case, due to my algorithm, when
57 * the number of different colors is less than MAXPRINTABLE, it will give a
58 * char follow by "nothing" (a space) in the readable xpm file
59 */
60
61
62 typedef struct {
63 Pixel *pixels;
64 unsigned int *pixelindex;
65 unsigned int size;
66 unsigned int ncolors;
67 unsigned int mask_pixel; /* whether there is or not */
68 } PixelsMap;
69
70 LFUNC(storePixel, int, (Pixel pixel, PixelsMap *pmap,
71 unsigned int *index_return));
72
73 LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap *pmap,
74 unsigned int *index_return));
75
76 #ifndef FOR_MSW
77 # ifndef AMIGA
78 LFUNC(GetImagePixels, int, (XImage *image, unsigned int width,
79 unsigned int height, PixelsMap *pmap));
80
81 LFUNC(GetImagePixels32, int, (XImage *image, unsigned int width,
82 unsigned int height, PixelsMap *pmap));
83
84 LFUNC(GetImagePixels16, int, (XImage *image, unsigned int width,
85 unsigned int height, PixelsMap *pmap));
86
87 LFUNC(GetImagePixels8, int, (XImage *image, unsigned int width,
88 unsigned int height, PixelsMap *pmap));
89
90 LFUNC(GetImagePixels1, int, (XImage *image, unsigned int width,
91 unsigned int height, PixelsMap *pmap,
92 int (*storeFunc) ()));
93 # else /* AMIGA */
94 LFUNC(AGetImagePixels, int, (XImage *image, unsigned int width,
95 unsigned int height, PixelsMap *pmap,
96 int (*storeFunc) ()));
97 # endif/* AMIGA */
98 #else /* ndef FOR_MSW */
99 LFUNC(MSWGetImagePixels, int, (Display *d, XImage *image, unsigned int width,
100 unsigned int height, PixelsMap *pmap,
101 int (*storeFunc) ()));
102 #endif
103 LFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp,
104 XpmAttributes *attributes));
105
106 LFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors, int ncolors,
107 Pixel *pixels, unsigned int mask,
108 unsigned int cpp, XpmAttributes *attributes));
109
110 /*
111 * This function stores the given pixel in the given arrays which are grown
112 * if not large enough.
113 */
114 #ifdef __OS2__
115 /* Visual Age cannot deal with old, non-ansi, code */
116 static int storePixel(Pixel pixel, PixelsMap* pmap, unsigned int* index_return)
117 #else
118 static int
119 storePixel(pixel, pmap, index_return)
120 Pixel pixel;
121 PixelsMap *pmap;
122 unsigned int *index_return;
123 #endif
124 {
125 unsigned int i;
126 Pixel *p;
127 unsigned int ncolors;
128
129 if (*index_return) { /* this is a transparent pixel! */
130 *index_return = 0;
131 return 0;
132 }
133 ncolors = pmap->ncolors;
134 p = pmap->pixels + pmap->mask_pixel;
135 for (i = pmap->mask_pixel; i < ncolors; i++, p++)
136 if (*p == pixel)
137 break;
138 if (i == ncolors) {
139 if (ncolors >= pmap->size) {
140 pmap->size *= 2;
141 p = (Pixel *) XpmRealloc(pmap->pixels, sizeof(Pixel) * pmap->size);
142 if (!p)
143 return (1);
144 pmap->pixels = p;
145
146 }
147 (pmap->pixels)[ncolors] = pixel;
148 pmap->ncolors++;
149 }
150 *index_return = i;
151 return 0;
152 }
153
154 #ifdef __OS2__
155 /* Visual Age cannot deal with old, non-ansi, code */
156 static int storeMaskPixel(Pixel pixel, PixelsMap* pmap, unsigned int* index_return)
157 #else
158 static int
159 storeMaskPixel(pixel, pmap, index_return)
160 Pixel pixel;
161 PixelsMap *pmap;
162 unsigned int *index_return;
163 #endif
164 {
165 if (!pixel) {
166 if (!pmap->ncolors) {
167 pmap->ncolors = 1;
168 (pmap->pixels)[0] = 0;
169 pmap->mask_pixel = 1;
170 }
171 *index_return = 1;
172 } else
173 *index_return = 0;
174 return 0;
175 }
176
177 /* function call in case of error */
178 #undef RETURN
179 #define RETURN(status) \
180 { \
181 ErrorStatus = status; \
182 goto error; \
183 }
184
185 /*
186 * This function scans the given image and stores the found informations in
187 * the given XpmImage structure.
188 */
189 #ifdef __OS2__
190 /* Visual Age cannot deal with old, non-ansi, code */
191 int XpmCreateXpmImageFromImage(
192 Display* display
193 , XImage* image
194 , XImage* shapeimage
195 , XpmImage* xpmimage
196 , XpmAttributes* attributes
197 )
198 #else
199 int
200 XpmCreateXpmImageFromImage(display, image, shapeimage,
201 xpmimage, attributes)
202 Display *display;
203 XImage *image;
204 XImage *shapeimage;
205 XpmImage *xpmimage;
206 XpmAttributes *attributes;
207 #endif
208 {
209 /* variables stored in the XpmAttributes structure */
210 unsigned int cpp;
211
212 /* variables to return */
213 PixelsMap pmap;
214 XpmColor *colorTable = NULL;
215 int ErrorStatus;
216
217 /* calculation variables */
218 unsigned int width = 0;
219 unsigned int height = 0;
220 unsigned int cppm; /* minimum chars per pixel */
221 unsigned int c;
222
223 /* initialize pmap */
224 pmap.pixels = NULL;
225 pmap.pixelindex = NULL;
226 pmap.size = 256; /* should be enough most of the time */
227 pmap.ncolors = 0;
228 pmap.mask_pixel = 0;
229
230 /*
231 * get geometry
232 */
233 if (image) {
234 width = image->width;
235 height = image->height;
236 } else if (shapeimage) {
237 width = shapeimage->width;
238 height = shapeimage->height;
239 }
240
241 /*
242 * retrieve information from the XpmAttributes
243 */
244 if (attributes && (attributes->valuemask & XpmCharsPerPixel
245 /* 3.2 backward compatibility code */
246 || attributes->valuemask & XpmInfos))
247 /* end 3.2 bc */
248 cpp = attributes->cpp;
249 else
250 cpp = 0;
251
252 pmap.pixelindex =
253 (unsigned int *) XpmCalloc(width * height, sizeof(unsigned int));
254 if (!pmap.pixelindex)
255 RETURN(XpmNoMemory);
256
257 pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size);
258 if (!pmap.pixels)
259 RETURN(XpmNoMemory);
260
261 /*
262 * scan shape mask if any
263 */
264 if (shapeimage) {
265 #ifndef FOR_MSW
266 # ifndef AMIGA
267 ErrorStatus = GetImagePixels1(shapeimage, width, height, &pmap,
268 storeMaskPixel);
269 # else
270 ErrorStatus = AGetImagePixels(shapeimage, width, height, &pmap,
271 storeMaskPixel);
272 # endif
273 #else
274
275 #ifndef __OS2__
276 ErrorStatus = MSWGetImagePixels(display, shapeimage, width, height,
277 &pmap, storeMaskPixel);
278 /* calling convention all messed up OS/2 -- figure out later */
279 #endif
280
281 #endif
282 if (ErrorStatus != XpmSuccess)
283 RETURN(ErrorStatus);
284 }
285
286 /*
287 * scan the image data
288 *
289 * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
290 * functions, otherwise use slower but sure general one.
291 *
292 */
293
294 if (image) {
295 #ifndef FOR_MSW
296 # ifndef AMIGA
297 if (((image->bits_per_pixel | image->depth) == 1) &&
298 (image->byte_order == image->bitmap_bit_order))
299 ErrorStatus = GetImagePixels1(image, width, height, &pmap,
300 storePixel);
301 else if (image->format == ZPixmap) {
302 if (image->bits_per_pixel == 8)
303 ErrorStatus = GetImagePixels8(image, width, height, &pmap);
304 else if (image->bits_per_pixel == 16)
305 ErrorStatus = GetImagePixels16(image, width, height, &pmap);
306 else if (image->bits_per_pixel == 32)
307 ErrorStatus = GetImagePixels32(image, width, height, &pmap);
308 } else
309 ErrorStatus = GetImagePixels(image, width, height, &pmap);
310 # else
311 ErrorStatus = AGetImagePixels(image, width, height, &pmap,
312 storePixel);
313 # endif
314 #else
315
316 #ifndef __OS2__
317 ErrorStatus = MSWGetImagePixels(display, image, width, height, &pmap,
318 storePixel);
319 #endif
320
321 #endif
322 if (ErrorStatus != XpmSuccess)
323 RETURN(ErrorStatus);
324 }
325
326 /*
327 * get rgb values and a string of char, and possibly a name for each
328 * color
329 */
330
331 colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor));
332 if (!colorTable)
333 RETURN(XpmNoMemory);
334
335 /* compute the minimal cpp */
336 for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++)
337 c *= MAXPRINTABLE;
338 if (cpp < cppm)
339 cpp = cppm;
340
341 if (pmap.mask_pixel) {
342 ErrorStatus = ScanTransparentColor(colorTable, cpp, attributes);
343 if (ErrorStatus != XpmSuccess)
344 RETURN(ErrorStatus);
345 }
346
347 ErrorStatus = ScanOtherColors(display, colorTable, pmap.ncolors,
348 pmap.pixels, pmap.mask_pixel, cpp,
349 attributes);
350 if (ErrorStatus != XpmSuccess)
351 RETURN(ErrorStatus);
352
353 /*
354 * store found informations in the XpmImage structure
355 */
356 xpmimage->width = width;
357 xpmimage->height = height;
358 xpmimage->cpp = cpp;
359 xpmimage->ncolors = pmap.ncolors;
360 xpmimage->colorTable = colorTable;
361 xpmimage->data = pmap.pixelindex;
362
363 XpmFree(pmap.pixels);
364 return (XpmSuccess);
365
366 /* exit point in case of error, free only locally allocated variables */
367 error:
368 if (pmap.pixelindex)
369 XpmFree(pmap.pixelindex);
370 if (pmap.pixels)
371 XpmFree(pmap.pixels);
372 if (colorTable)
373 xpmFreeColorTable(colorTable, pmap.ncolors);
374
375 return (ErrorStatus);
376 }
377
378 #ifdef __OS2__
379 /* Visual Age cannot deal with old, non-ansi, code */
380 static int ScanTransparentColor(XpmColor* color, unsigned int cpp, XpmAttributes* attributes)
381 #else
382 static int
383 ScanTransparentColor(color, cpp, attributes)
384 XpmColor *color;
385 unsigned int cpp;
386 XpmAttributes *attributes;
387 #endif
388 {
389 char *s;
390 unsigned int a, b, c;
391
392 /* first get a character string */
393 a = 0;
394 if (!(s = color->string = (char *) XpmMalloc(cpp + 1)))
395 return (XpmNoMemory);
396 *s++ = printable[c = a % MAXPRINTABLE];
397 for (b = 1; b < cpp; b++, s++)
398 *s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE];
399 *s = '\0';
400
401 /* then retreive related info from the attributes if any */
402 if (attributes && (attributes->valuemask & XpmColorTable
403 /* 3.2 backward compatibility code */
404 || attributes->valuemask & XpmInfos)
405 /* end 3.2 bc */
406 && attributes->mask_pixel != XpmUndefPixel) {
407
408 unsigned int key;
409 char **defaults = (char **) color;
410 char **mask_defaults;
411
412 /* 3.2 backward compatibility code */
413 if (attributes->valuemask & XpmColorTable)
414 /* end 3.2 bc */
415 mask_defaults = (char **) (
416 attributes->colorTable + attributes->mask_pixel);
417 /* 3.2 backward compatibility code */
418 else
419 mask_defaults = (char **)
420 ((XpmColor **) attributes->colorTable)[attributes->mask_pixel];
421 /* end 3.2 bc */
422 for (key = 1; key <= NKEYS; key++) {
423 if (s = mask_defaults[key]) {
424 defaults[key] = (char *) xpmstrdup(s);
425 if (!defaults[key])
426 return (XpmNoMemory);
427 }
428 }
429 } else {
430 color->c_color = (char *) xpmstrdup(TRANSPARENT_COLOR);
431 if (!color->c_color)
432 return (XpmNoMemory);
433 }
434 return (XpmSuccess);
435 }
436
437 #ifdef __OS2__
438 /* Visual Age cannot deal with old, non-ansi, code */
439 static int ScanOtherColors(
440 Display* display
441 , XpmColor* colors
442 , int ncolors
443 , Pixel* pixels
444 , unsigned int mask
445 , unsigned int cpp
446 , XpmAttributes* attributes
447 )
448 #else
449 static int
450 ScanOtherColors(display, colors, ncolors, pixels, mask, cpp, attributes)
451 Display *display;
452 XpmColor *colors;
453 int ncolors;
454 Pixel *pixels;
455 unsigned int mask;
456 unsigned int cpp;
457 XpmAttributes *attributes;
458 #endif
459 {
460 /* variables stored in the XpmAttributes structure */
461 Colormap colormap;
462 char *rgb_fname;
463
464 #ifndef FOR_MSW
465 xpmRgbName rgbn[MAX_RGBNAMES];
466 #else
467 xpmRgbName *rgbn = NULL;
468 #endif
469 int rgbn_max = 0;
470 unsigned int i, j, c, i2;
471 XpmColor *color;
472 XColor *xcolors = NULL, *xcolor;
473 char *colorname, *s;
474 XpmColor *colorTable, **oldColorTable = NULL;
475 unsigned int ancolors = 0;
476 Pixel *apixels;
477 unsigned int mask_pixel;
478 Bool found;
479
480 /* retrieve information from the XpmAttributes */
481 if (attributes && (attributes->valuemask & XpmColormap))
482 colormap = attributes->colormap;
483 else
484 colormap = XDefaultColormap(display, XDefaultScreen(display));
485 if (attributes && (attributes->valuemask & XpmRgbFilename))
486 rgb_fname = attributes->rgb_fname;
487 else
488 rgb_fname = NULL;
489
490 /* start from the right element */
491 if (mask) {
492 colors++;
493 ncolors--;
494 pixels++;
495 }
496
497 /* first get character strings and rgb values */
498 xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors);
499 if (!xcolors)
500 return (XpmNoMemory);
501
502 for (i = 0, i2 = mask, color = colors, xcolor = xcolors;
503 i < ncolors; i++, i2++, color++, xcolor++, pixels++) {
504
505 if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) {
506 XpmFree(xcolors);
507 return (XpmNoMemory);
508 }
509 *s++ = printable[c = i2 % MAXPRINTABLE];
510 for (j = 1; j < cpp; j++, s++)
511 *s = printable[c = ((i2 - c) / MAXPRINTABLE) % MAXPRINTABLE];
512 *s = '\0';
513
514 xcolor->pixel = *pixels;
515 }
516 #ifdef __OS2__
517 XQueryColors(display, &colormap, xcolors, ncolors);
518 #else
519 XQueryColors(display, colormap, xcolors, ncolors);
520 #endif
521
522 #ifndef FOR_MSW
523 /* read the rgb file if any was specified */
524 if (rgb_fname)
525 rgbn_max = xpmReadRgbNames(attributes->rgb_fname, rgbn);
526 #else
527 /* FOR_MSW: rgb names and values are hardcoded in rgbtab.h */
528 rgbn_max = xpmReadRgbNames(NULL, NULL);
529 #endif
530
531 if (attributes && attributes->valuemask & XpmColorTable) {
532 colorTable = attributes->colorTable;
533 ancolors = attributes->ncolors;
534 apixels = attributes->pixels;
535 mask_pixel = attributes->mask_pixel;
536 }
537 /* 3.2 backward compatibility code */
538 else if (attributes && attributes->valuemask & XpmInfos) {
539 oldColorTable = (XpmColor **) attributes->colorTable;
540 ancolors = attributes->ncolors;
541 apixels = attributes->pixels;
542 mask_pixel = attributes->mask_pixel;
543 }
544 /* end 3.2 bc */
545
546 for (i = 0, color = colors, xcolor = xcolors; i < ncolors;
547 i++, color++, xcolor++) {
548
549 /* look for related info from the attributes if any */
550 found = False;
551 if (ancolors) {
552 unsigned int offset = 0;
553
554 for (j = 0; j < ancolors; j++) {
555 if (j == mask_pixel) {
556 offset = 1;
557 continue;
558 }
559 if (apixels[j - offset] == xcolor->pixel)
560 break;
561 }
562 if (j != ancolors) {
563 unsigned int key;
564 char **defaults = (char **) color;
565 char **adefaults;
566
567 /* 3.2 backward compatibility code */
568 if (oldColorTable)
569 adefaults = (char **) oldColorTable[j];
570 else
571 /* end 3.2 bc */
572 adefaults = (char **) (colorTable + j);
573
574 found = True;
575 for (key = 1; key <= NKEYS; key++) {
576 if (s = adefaults[key])
577 defaults[key] = (char *) xpmstrdup(s);
578 }
579 }
580 }
581 if (!found) {
582 /* if nothing found look for a color name */
583 colorname = NULL;
584 if (rgbn_max)
585 colorname = xpmGetRgbName(rgbn, rgbn_max, xcolor->red,
586 xcolor->green, xcolor->blue);
587 if (colorname)
588 color->c_color = (char *) xpmstrdup(colorname);
589 else {
590 /* at last store the rgb value */
591 char buf[BUFSIZ];
592 #ifndef FOR_MSW
593 sprintf(buf, "#%04X%04X%04X",
594 xcolor->red, xcolor->green, xcolor->blue);
595 #else
596 sprintf(buf, "#%02x%02x%02x",
597 xcolor->red, xcolor->green, xcolor->blue);
598 #endif
599 color->c_color = (char *) xpmstrdup(buf);
600 }
601 if (!color->c_color) {
602 XpmFree(xcolors);
603 xpmFreeRgbNames(rgbn, rgbn_max);
604 return (XpmNoMemory);
605 }
606 }
607 }
608
609 XpmFree(xcolors);
610 xpmFreeRgbNames(rgbn, rgbn_max);
611 return (XpmSuccess);
612 }
613
614 #ifndef FOR_MSW
615 # ifndef AMIGA
616 /*
617 * The functions below are written from X11R5 MIT's code (XImUtil.c)
618 *
619 * The idea is to have faster functions than the standard XGetPixel function
620 * to scan the image data. Indeed we can speed up things by suppressing tests
621 * performed for each pixel. We do exactly the same tests but at the image
622 * level.
623 */
624
625 static unsigned long Const low_bits_table[] = {
626 0x00000000, 0x00000001, 0x00000003, 0x00000007,
627 0x0000000f, 0x0000001f, 0x0000003f, 0x0000007f,
628 0x000000ff, 0x000001ff, 0x000003ff, 0x000007ff,
629 0x00000fff, 0x00001fff, 0x00003fff, 0x00007fff,
630 0x0000ffff, 0x0001ffff, 0x0003ffff, 0x0007ffff,
631 0x000fffff, 0x001fffff, 0x003fffff, 0x007fffff,
632 0x00ffffff, 0x01ffffff, 0x03ffffff, 0x07ffffff,
633 0x0fffffff, 0x1fffffff, 0x3fffffff, 0x7fffffff,
634 0xffffffff
635 };
636
637 /*
638 * Default method to scan pixels of an image data structure.
639 * The algorithm used is:
640 *
641 * copy the source bitmap_unit or Zpixel into temp
642 * normalize temp if needed
643 * extract the pixel bits into return value
644 *
645 */
646
647 #ifdef __OS2__
648 /* Visual Age cannot deal with old, non-ansi, code */
649 static int GetImagePixels(
650 XImage* image
651 , unsigned int width
652 , unsigned int height
653 , PixelsMap* pmap
654 )
655 #else
656 static int
657 GetImagePixels(image, width, height, pmap)
658 XImage *image;
659 unsigned int width;
660 unsigned int height;
661 PixelsMap *pmap;
662 #endif
663 {
664 char *src;
665 char *dst;
666 unsigned int *iptr;
667 char *data;
668 int x, y, i;
669 int bits, depth, ibu, ibpp, offset;
670 unsigned long lbt;
671 Pixel pixel, px;
672
673 data = image->data;
674 iptr = pmap->pixelindex;
675 depth = image->depth;
676 lbt = low_bits_table[depth];
677 ibpp = image->bits_per_pixel;
678 offset = image->xoffset;
679
680 if ((image->bits_per_pixel | image->depth) == 1) {
681 ibu = image->bitmap_unit;
682 for (y = 0; y < height; y++)
683 for (x = 0; x < width; x++, iptr++) {
684 src = &data[XYINDEX(x, y, image)];
685 dst = (char *) &pixel;
686 pixel = 0;
687 for (i = ibu >> 3; --i >= 0;)
688 *dst++ = *src++;
689 XYNORMALIZE(&pixel, image);
690 bits = (x + offset) % ibu;
691 pixel = ((((char *) &pixel)[bits >> 3]) >> (bits & 7)) & 1;
692 if (ibpp != depth)
693 pixel &= lbt;
694 if (storePixel(pixel, pmap, iptr))
695 return (XpmNoMemory);
696 }
697 } else if (image->format == XYPixmap) {
698 int nbytes, bpl, j;
699 long plane = 0;
700 ibu = image->bitmap_unit;
701 nbytes = ibu >> 3;
702 bpl = image->bytes_per_line;
703 for (y = 0; y < height; y++)
704 for (x = 0; x < width; x++, iptr++) {
705 pixel = 0;
706 plane = 0;
707 for (i = depth; --i >= 0;) {
708 src = &data[XYINDEX(x, y, image) + plane];
709 dst = (char *) &px;
710 px = 0;
711 for (j = nbytes; --j >= 0;)
712 *dst++ = *src++;
713 XYNORMALIZE(&px, image);
714 bits = (x + offset) % ibu;
715 pixel = (pixel << 1) |
716 (((((char *) &px)[bits >> 3]) >> (bits & 7)) & 1);
717 plane = plane + (bpl * height);
718 }
719 if (ibpp != depth)
720 pixel &= lbt;
721 if (storePixel(pixel, pmap, iptr))
722 return (XpmNoMemory);
723 }
724 } else if (image->format == ZPixmap) {
725 for (y = 0; y < height; y++)
726 for (x = 0; x < width; x++, iptr++) {
727 src = &data[ZINDEX(x, y, image)];
728 dst = (char *) &px;
729 px = 0;
730 for (i = (ibpp + 7) >> 3; --i >= 0;)
731 *dst++ = *src++;
732 ZNORMALIZE(&px, image);
733 pixel = 0;
734 for (i = sizeof(unsigned long); --i >= 0;)
735 pixel = (pixel << 8) | ((unsigned char *) &px)[i];
736 if (ibpp == 4) {
737 if (x & 1)
738 pixel >>= 4;
739 else
740 pixel &= 0xf;
741 }
742 if (ibpp != depth)
743 pixel &= lbt;
744 if (storePixel(pixel, pmap, iptr))
745 return (XpmNoMemory);
746 }
747 } else
748 return (XpmColorError); /* actually a bad image */
749 return (XpmSuccess);
750 }
751
752 /*
753 * scan pixels of a 32-bits Z image data structure
754 */
755
756 #if !defined(WORD64) && !defined(LONG64)
757 static unsigned long byteorderpixel = MSBFirst << 24;
758 #endif
759
760 #ifdef __OS2__
761 /* Visual Age cannot deal with old, non-ansi, code */
762 static int GetImagePixels32(
763 XImage* image
764 , unsigned int width
765 , unsigned int height
766 , PixelsMap* pmap
767 )
768 #else
769 static int
770 GetImagePixels32(image, width, height, pmap)
771 XImage *image;
772 unsigned int width;
773 unsigned int height;
774 PixelsMap *pmap;
775 #endif
776 {
777 unsigned char *addr;
778 unsigned char *data;
779 unsigned int *iptr;
780 int x, y;
781 unsigned long lbt;
782 Pixel pixel;
783 int depth;
784
785 data = (unsigned char *) image->data;
786 iptr = pmap->pixelindex;
787 depth = image->depth;
788 lbt = low_bits_table[depth];
789 #if !defined(WORD64) && !defined(LONG64)
790 if (*((char *) &byteorderpixel) == image->byte_order) {
791 for (y = 0; y < height; y++)
792 for (x = 0; x < width; x++, iptr++) {
793 addr = &data[ZINDEX32(x, y, image)];
794 pixel = *((unsigned long *) addr);
795 if (depth != 32)
796 pixel &= lbt;
797 if (storePixel(pixel, pmap, iptr))
798 return (XpmNoMemory);
799 }
800 } else
801 #endif
802 if (image->byte_order == MSBFirst)
803 for (y = 0; y < height; y++)
804 for (x = 0; x < width; x++, iptr++) {
805 addr = &data[ZINDEX32(x, y, image)];
806 pixel = ((unsigned long) addr[0] << 24 |
807 (unsigned long) addr[1] << 16 |
808 (unsigned long) addr[2] << 8 |
809 addr[3]);
810 if (depth != 32)
811 pixel &= lbt;
812 if (storePixel(pixel, pmap, iptr))
813 return (XpmNoMemory);
814 }
815 else
816 for (y = 0; y < height; y++)
817 for (x = 0; x < width; x++, iptr++) {
818 addr = &data[ZINDEX32(x, y, image)];
819 pixel = (addr[0] |
820 (unsigned long) addr[1] << 8 |
821 (unsigned long) addr[2] << 16 |
822 (unsigned long) addr[3] << 24);
823 if (depth != 32)
824 pixel &= lbt;
825 if (storePixel(pixel, pmap, iptr))
826 return (XpmNoMemory);
827 }
828 return (XpmSuccess);
829 }
830
831 /*
832 * scan pixels of a 16-bits Z image data structure
833 */
834
835 #ifdef __OS2__
836 /* Visual Age cannot deal with old, non-ansi, code */
837 static int GetImagePixels16(
838 XImage* image
839 , unsigned int width
840 , unsigned int height
841 , PixelsMap* pmap
842 )
843 #else
844 static int
845 GetImagePixels16(image, width, height, pmap)
846 XImage *image;
847 unsigned int width;
848 unsigned int height;
849 PixelsMap *pmap;
850 #endif
851 {
852 unsigned char *addr;
853 unsigned char *data;
854 unsigned int *iptr;
855 int x, y;
856 unsigned long lbt;
857 Pixel pixel;
858 int depth;
859
860 data = (unsigned char *) image->data;
861 iptr = pmap->pixelindex;
862 depth = image->depth;
863 lbt = low_bits_table[depth];
864 if (image->byte_order == MSBFirst)
865 for (y = 0; y < height; y++)
866 for (x = 0; x < width; x++, iptr++) {
867 addr = &data[ZINDEX16(x, y, image)];
868 pixel = addr[0] << 8 | addr[1];
869 if (depth != 16)
870 pixel &= lbt;
871 if (storePixel(pixel, pmap, iptr))
872 return (XpmNoMemory);
873 }
874 else
875 for (y = 0; y < height; y++)
876 for (x = 0; x < width; x++, iptr++) {
877 addr = &data[ZINDEX16(x, y, image)];
878 pixel = addr[0] | addr[1] << 8;
879 if (depth != 16)
880 pixel &= lbt;
881 if (storePixel(pixel, pmap, iptr))
882 return (XpmNoMemory);
883 }
884 return (XpmSuccess);
885 }
886
887 /*
888 * scan pixels of a 8-bits Z image data structure
889 */
890
891 #ifdef __OS2__
892 /* Visual Age cannot deal with old, non-ansi, code */
893 static int
894 GetImagePixels8(image, width, height, pmap)
895 XImage* image
896 , unsigned int width
897 , unsigned int height
898 , PixelsMap* pmap
899 )
900 #else
901 static int
902 GetImagePixels8(image, width, height, pmap)
903 XImage *image;
904 unsigned int width;
905 unsigned int height;
906 PixelsMap *pmap;
907 #endif
908 {
909 unsigned int *iptr;
910 unsigned char *data;
911 int x, y;
912 unsigned long lbt;
913 Pixel pixel;
914 int depth;
915
916 data = (unsigned char *) image->data;
917 iptr = pmap->pixelindex;
918 depth = image->depth;
919 lbt = low_bits_table[depth];
920 for (y = 0; y < height; y++)
921 for (x = 0; x < width; x++, iptr++) {
922 pixel = data[ZINDEX8(x, y, image)];
923 if (depth != 8)
924 pixel &= lbt;
925 if (storePixel(pixel, pmap, iptr))
926 return (XpmNoMemory);
927 }
928 return (XpmSuccess);
929 }
930
931 /*
932 * scan pixels of a 1-bit depth Z image data structure
933 */
934
935 #ifdef __OS2__
936 /* Visual Age cannot deal with old, non-ansi, code */
937 static int
938 GetImagePixels1(
939 XImage* image
940 , unsigned int width
941 , unsigned int height
942 , PixelsMap* pmap
943 , int (*storeFunc) ()
944 )
945 #else
946 static int
947 GetImagePixels1(image, width, height, pmap, storeFunc)
948 XImage *image;
949 unsigned int width;
950 unsigned int height;
951 PixelsMap *pmap;
952 int (*storeFunc) ();
953 #endif
954 {
955 unsigned int *iptr;
956 int x, y;
957 char *data;
958 Pixel pixel;
959 int xoff, yoff, offset, bpl;
960
961 data = image->data;
962 iptr = pmap->pixelindex;
963 offset = image->xoffset;
964 bpl = image->bytes_per_line;
965
966 if (image->bitmap_bit_order == MSBFirst)
967 for (y = 0; y < height; y++)
968 for (x = 0; x < width; x++, iptr++) {
969 xoff = x + offset;
970 yoff = y * bpl + (xoff >> 3);
971 xoff &= 7;
972 pixel = (data[yoff] & (0x80 >> xoff)) ? 1 : 0;
973 if ((*storeFunc) (pixel, pmap, iptr))
974 return (XpmNoMemory);
975 }
976 else
977 for (y = 0; y < height; y++)
978 for (x = 0; x < width; x++, iptr++) {
979 xoff = x + offset;
980 yoff = y * bpl + (xoff >> 3);
981 xoff &= 7;
982 pixel = (data[yoff] & (1 << xoff)) ? 1 : 0;
983 if ((*storeFunc) (pixel, pmap, iptr))
984 return (XpmNoMemory);
985 }
986 return (XpmSuccess);
987 }
988
989 # else /* AMIGA */
990
991 #define CLEAN_UP(status) \
992 {\
993 if (pixels) XpmFree (pixels);\
994 if (tmp_img) FreeXImage (tmp_img);\
995 return (status);\
996 }
997
998 static int
999 AGetImagePixels (
1000 XImage *image,
1001 unsigned int width,
1002 unsigned int height,
1003 PixelsMap *pmap,
1004 int (*storeFunc) ())
1005 {
1006 unsigned int *iptr;
1007 unsigned int x, y;
1008 unsigned char *pixels;
1009 XImage *tmp_img;
1010
1011 pixels = XpmMalloc ((((width+15)>>4)<<4)*sizeof (*pixels));
1012 if (pixels == NULL)
1013 return XpmNoMemory;
1014
1015 tmp_img = AllocXImage ((((width+15)>>4)<<4), 1, image->rp->BitMap->Depth);
1016 if (tmp_img == NULL)
1017 CLEAN_UP (XpmNoMemory)
1018
1019 iptr = pmap->pixelindex;
1020 for (y = 0; y < height; ++y)
1021 {
1022 ReadPixelLine8 (image->rp, 0, y, width, pixels, tmp_img->rp);
1023 for (x = 0; x < width; ++x, ++iptr)
1024 {
1025 if ((*storeFunc) (pixels[x], pmap, iptr))
1026 CLEAN_UP (XpmNoMemory)
1027 }
1028 }
1029
1030 CLEAN_UP (XpmSuccess)
1031 }
1032
1033 #undef CLEAN_UP
1034
1035 # endif/* AMIGA */
1036 #else /* ndef FOR_MSW */
1037 #ifdef __OS2__
1038 /* Visual Age cannot deal with old, non-ansi, code */
1039 static int
1040 MSWGetImagePixels(
1041 Display* display
1042 , XImage* image
1043 , unsigned int width
1044 , unsigned int height
1045 , PixelsMap* pmap
1046 , int (*storeFunc) ()
1047 )
1048 #else
1049 static int
1050 MSWGetImagePixels(display, image, width, height, pmap, storeFunc)
1051 Display *display;
1052 XImage *image;
1053 unsigned int width;
1054 unsigned int height;
1055 PixelsMap *pmap;
1056 int (*storeFunc) ();
1057 #endif
1058 {
1059 unsigned int *iptr;
1060 unsigned int x, y;
1061 Pixel pixel;
1062 #ifdef __OS2__
1063 HAB hab;
1064 HPS hps;
1065 DEVOPENSTRUC dop = {NULL, "DISPLAY", NULL, NULL, NULL, NULL, NULL, NULL, NULL};
1066 SIZEL sizl = {0, 0};
1067 POINTL point;
1068 #endif
1069
1070 iptr = pmap->pixelindex;
1071
1072 #ifdef __OS2__
1073 hps = GpiCreatePS(hab, *display, &sizl, GPIA_ASSOC | PU_PELS);
1074 GpiSetBitmap(hps, image->bitmap);
1075 #else
1076 SelectObject(*display, image->bitmap);
1077 #endif
1078
1079 for (y = 0; y < height; y++) {
1080 for (x = 0; x < width; x++, iptr++) {
1081 #ifdef __OS2__
1082 point.x = x;
1083 point.y = y;
1084 pixel = GpiQueryPel(hps, &point);
1085 #else
1086 pixel = GetPixel(*display, x, y);
1087 #endif
1088 #ifndef __OS2__
1089 /* calling convention all messed up under OS/2 */
1090 if ((*storeFunc) (pixel, pmap, iptr))
1091 return (XpmNoMemory);
1092 #endif
1093 }
1094 }
1095 return (XpmSuccess);
1096 }
1097
1098 #endif
1099
1100 #ifndef FOR_MSW
1101 # ifndef AMIGA
1102 int
1103 XpmCreateXpmImageFromPixmap(display, pixmap, shapemask,
1104 xpmimage, attributes)
1105 Display *display;
1106 Pixmap pixmap;
1107 Pixmap shapemask;
1108 XpmImage *xpmimage;
1109 XpmAttributes *attributes;
1110 {
1111 XImage *ximage = NULL;
1112 XImage *shapeimage = NULL;
1113 unsigned int width = 0;
1114 unsigned int height = 0;
1115 int ErrorStatus;
1116
1117 /* get geometry */
1118 if (attributes && attributes->valuemask & XpmSize) {
1119 width = attributes->width;
1120 height = attributes->height;
1121 }
1122 /* get the ximages */
1123 if (pixmap)
1124 xpmCreateImageFromPixmap(display, pixmap, &ximage, &width, &height);
1125 if (shapemask)
1126 xpmCreateImageFromPixmap(display, shapemask, &shapeimage,
1127 &width, &height);
1128
1129 /* create the related XpmImage */
1130 ErrorStatus = XpmCreateXpmImageFromImage(display, ximage, shapeimage,
1131 xpmimage, attributes);
1132
1133 /* destroy the ximages */
1134 if (ximage)
1135 XDestroyImage(ximage);
1136 if (shapeimage)
1137 XDestroyImage(shapeimage);
1138
1139 return (ErrorStatus);
1140 }
1141
1142 # endif/* not AMIGA */
1143 #endif /* ndef FOR_MSW */