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