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