2 * Copyright (C) 1989-95 GROUPE BULL
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:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
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.
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.
26 /*****************************************************************************\
30 * Create an X image and possibly its related shape mask *
31 * from the given XpmImage. *
33 * Developed by Arnaud Le Hors *
34 \*****************************************************************************/
37 * The code related to FOR_MSW has been added by
38 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
42 * The code related to AMIGA has been added by
43 * Lorens Younes (d93-hyo@nada.kth.se) 4/96
49 LFUNC(xpmVisualType
, int, (Visual
*visual
));
51 LFUNC(AllocColor
, int, (Display
*display
, Colormap colormap
,
52 char *colorname
, XColor
*xcolor
, void *closure
));
53 LFUNC(FreeColors
, int, (Display
*display
, Colormap colormap
,
54 Pixel
*pixels
, int n
, void *closure
));
57 LFUNC(SetCloseColor
, int, (Display
*display
, Colormap colormap
,
58 Visual
*visual
, XColor
*col
,
59 Pixel
*image_pixel
, Pixel
*mask_pixel
,
60 Pixel
*alloc_pixels
, unsigned int *nalloc_pixels
,
61 XpmAttributes
*attributes
, XColor
*cols
, int ncols
,
62 XpmAllocColorFunc allocColor
, void *closure
));
64 /* let the window system take care of close colors */
67 LFUNC(SetColor
, int, (Display
*display
, Colormap colormap
, Visual
*visual
,
68 char *colorname
, unsigned int color_index
,
69 Pixel
*image_pixel
, Pixel
*mask_pixel
,
70 unsigned int *mask_pixel_index
,
71 Pixel
*alloc_pixels
, unsigned int *nalloc_pixels
,
72 Pixel
*used_pixels
, unsigned int *nused_pixels
,
73 XpmAttributes
*attributes
, XColor
*cols
, int ncols
,
74 XpmAllocColorFunc allocColor
, void *closure
));
76 LFUNC(CreateXImage
, int, (Display
*display
, Visual
*visual
,
77 unsigned int depth
, int format
, unsigned int width
,
78 unsigned int height
, XImage
**image_return
));
80 LFUNC(CreateColors
, int, (Display
*display
, XpmAttributes
*attributes
,
81 XpmColor
*colors
, unsigned int ncolors
,
82 Pixel
*image_pixels
, Pixel
*mask_pixels
,
83 unsigned int *mask_pixel_index
,
84 Pixel
*alloc_pixels
, unsigned int *nalloc_pixels
,
85 Pixel
*used_pixels
, unsigned int *nused_pixels
));
88 LFUNC(ParseAndPutPixels
, int, (xpmData
*data
, unsigned int width
,
89 unsigned int height
, unsigned int ncolors
,
90 unsigned int cpp
, XpmColor
*colorTable
,
91 xpmHashTable
*hashtable
,
92 XImage
*image
, Pixel
*image_pixels
,
93 XImage
*mask
, Pixel
*mask_pixels
));
95 LFUNC(ParseAndPutPixels
, int, (Display
*dc
, xpmData
*data
, unsigned int width
,
96 unsigned int height
, unsigned int ncolors
,
97 unsigned int cpp
, XpmColor
*colorTable
,
98 xpmHashTable
*hashtable
,
99 XImage
*image
, Pixel
*image_pixels
,
100 XImage
*mask
, Pixel
*mask_pixels
));
105 /* XImage pixel routines */
106 LFUNC(PutImagePixels
, void, (XImage
*image
, unsigned int width
,
107 unsigned int height
, unsigned int *pixelindex
,
110 LFUNC(PutImagePixels32
, void, (XImage
*image
, unsigned int width
,
111 unsigned int height
, unsigned int *pixelindex
,
114 LFUNC(PutImagePixels16
, void, (XImage
*image
, unsigned int width
,
115 unsigned int height
, unsigned int *pixelindex
,
118 LFUNC(PutImagePixels8
, void, (XImage
*image
, unsigned int width
,
119 unsigned int height
, unsigned int *pixelindex
,
122 LFUNC(PutImagePixels1
, void, (XImage
*image
, unsigned int width
,
123 unsigned int height
, unsigned int *pixelindex
,
126 LFUNC(PutPixel1
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
127 LFUNC(PutPixel
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
128 LFUNC(PutPixel32
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
129 LFUNC(PutPixel32MSB
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
130 LFUNC(PutPixel32LSB
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
131 LFUNC(PutPixel16MSB
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
132 LFUNC(PutPixel16LSB
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
133 LFUNC(PutPixel8
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
134 LFUNC(PutPixel1MSB
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
135 LFUNC(PutPixel1LSB
, int, (XImage
*ximage
, int x
, int y
, unsigned long pixel
));
138 LFUNC(APutImagePixels
, void, (XImage
*ximage
, unsigned int width
,
139 unsigned int height
, unsigned int *pixelindex
,
143 /* FOR_MSW pixel routine */
144 LFUNC(MSWPutImagePixels
, void, (Display
*dc
, XImage
*image
,
145 unsigned int width
, unsigned int height
,
146 unsigned int *pixelindex
, Pixel
*pixels
));
149 #ifdef NEED_STRCASECMP
150 FUNC(xpmstrcasecmp
, int, (char *s1
, char *s2
));
153 * in case strcasecmp is not provided by the system here is one
154 * which does the trick
157 xpmstrcasecmp(s1
, s2
)
158 register char *s1
, *s2
;
170 return (int) (*s1
- *s2
);
176 * return the default color key related to the given visual
179 xpmVisualType(visual
)
184 switch (visual
->class) {
187 switch (visual
->map_entries
) {
199 /* set the key explicitly in the XpmAttributes to override this */
203 /* there should be a similar switch for MSW */
218 CloseColor
*x
= (CloseColor
*) a
, *y
= (CloseColor
*) b
;
220 /* cast to int as qsort requires */
221 return (int) (x
->closeness
- y
->closeness
);
225 /* default AllocColor function:
226 * call XParseColor if colorname is given, return negative value if failure
227 * call XAllocColor and return 0 if failure, positive otherwise
230 AllocColor(display
, colormap
, colorname
, xcolor
, closure
)
235 void *closure
; /* not used */
239 if (!XParseColor(display
, colormap
, colorname
, xcolor
))
241 status
= XAllocColor(display
, colormap
, xcolor
);
242 return status
!= 0 ? 1 : 0;
248 * set a close color in case the exact one can't be set
249 * return 0 if success, 1 otherwise.
253 SetCloseColor(display
, colormap
, visual
, col
, image_pixel
, mask_pixel
,
254 alloc_pixels
, nalloc_pixels
, attributes
, cols
, ncols
,
260 Pixel
*image_pixel
, *mask_pixel
;
262 unsigned int *nalloc_pixels
;
263 XpmAttributes
*attributes
;
266 XpmAllocColorFunc allocColor
;
271 * Allocation failed, so try close colors. To get here the visual must
272 * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
273 * What about sharing systems like QDSS?). Beware: we have to treat
274 * DirectColor differently.
278 long int red_closeness
, green_closeness
, blue_closeness
;
282 if (attributes
&& (attributes
->valuemask
& XpmCloseness
))
283 red_closeness
= green_closeness
= blue_closeness
=
284 attributes
->closeness
;
286 red_closeness
= attributes
->red_closeness
;
287 green_closeness
= attributes
->green_closeness
;
288 blue_closeness
= attributes
->blue_closeness
;
290 if (attributes
&& (attributes
->valuemask
& XpmAllocCloseColors
))
291 alloc_color
= attributes
->alloc_close_colors
;
296 * We sort the colormap by closeness and try to allocate the color
297 * closest to the target. If the allocation of this close color fails,
298 * which almost never happens, then one of two scenarios is possible.
299 * Either the colormap must have changed (since the last close color
300 * allocation or possibly while we were sorting the colormap), or the
301 * color is allocated as Read/Write by some other client. (Note: X
302 * _should_ allow clients to check if a particular color is Read/Write,
303 * but it doesn't! :-( ). We cannot determine which of these scenarios
304 * occurred, so we try the next closest color, and so on, until no more
305 * colors are within closeness of the target. If we knew that the
306 * colormap had changed, we could skip this sequence.
308 * If _none_ of the colors within closeness of the target can be allocated,
309 * then we can finally be pretty sure that the colormap has actually
310 * changed. In this case we try to allocate the original color (again),
311 * then try the closecolor stuff (again)...
313 * In theory it would be possible for an infinite loop to occur if another
314 * process kept changing the colormap every time we sorted it, so we set
315 * a maximum on the number of iterations. After this many tries, we use
316 * XGrabServer() to ensure that the colormap remains unchanged.
318 * This approach gives particularly bad worst case performance - as many as
319 * <MaximumIterations> colormap reads and sorts may be needed, and as
320 * many as <MaximumIterations> * <ColormapSize> attempted allocations
321 * may fail. On an 8-bit system, this means as many as 3 colormap reads,
322 * 3 sorts and 768 failed allocations per execution of this code!
323 * Luckily, my experiments show that in general use in a typical 8-bit
324 * color environment only about 1 in every 10000 allocations fails to
325 * succeed in the fastest possible time. So virtually every time what
326 * actually happens is a single sort followed by a successful allocate.
327 * The very first allocation also costs a colormap read, but no further
328 * reads are usually necessary.
331 #define ITERATIONS 2 /* more than one is almost never
334 for (n
= 0; n
<= ITERATIONS
; ++n
) {
335 CloseColor
*closenesses
=
336 (CloseColor
*) XpmCalloc(ncols
, sizeof(CloseColor
));
339 for (i
= 0; i
< ncols
; ++i
) { /* build & sort closenesses table */
340 #define COLOR_FACTOR 3
341 #define BRIGHTNESS_FACTOR 1
343 closenesses
[i
].cols_index
= i
;
344 closenesses
[i
].closeness
=
345 COLOR_FACTOR
* (abs((long) col
->red
- (long) cols
[i
].red
)
346 + abs((long) col
->green
- (long) cols
[i
].green
)
347 + abs((long) col
->blue
- (long) cols
[i
].blue
))
348 + BRIGHTNESS_FACTOR
* abs(((long) col
->red
+
351 - ((long) cols
[i
].red
+
352 (long) cols
[i
].green
+
353 (long) cols
[i
].blue
));
355 qsort(closenesses
, ncols
, sizeof(CloseColor
), closeness_cmp
);
358 c
= closenesses
[i
].cols_index
;
359 while ((long) cols
[c
].red
>= (long) col
->red
- red_closeness
&&
360 (long) cols
[c
].red
<= (long) col
->red
+ red_closeness
&&
361 (long) cols
[c
].green
>= (long) col
->green
- green_closeness
&&
362 (long) cols
[c
].green
<= (long) col
->green
+ green_closeness
&&
363 (long) cols
[c
].blue
>= (long) col
->blue
- blue_closeness
&&
364 (long) cols
[c
].blue
<= (long) col
->blue
+ blue_closeness
) {
366 if ((*allocColor
)(display
, colormap
, NULL
, &cols
[c
], closure
)){
368 XUngrabServer(display
);
369 XpmFree(closenesses
);
370 *image_pixel
= cols
[c
].pixel
;
372 alloc_pixels
[(*nalloc_pixels
)++] = cols
[c
].pixel
;
378 c
= closenesses
[i
].cols_index
;
382 XUngrabServer(display
);
383 XpmFree(closenesses
);
384 *image_pixel
= cols
[c
].pixel
;
390 /* Couldn't allocate _any_ of the close colors! */
393 XUngrabServer(display
);
394 XpmFree(closenesses
);
396 if (i
== 0 || i
== ncols
) /* no color close enough or cannot */
397 return (1); /* alloc any color (full of r/w's) */
399 if ((*allocColor
)(display
, colormap
, NULL
, col
, closure
)) {
400 *image_pixel
= col
->pixel
;
402 alloc_pixels
[(*nalloc_pixels
)++] = col
->pixel
;
404 } else { /* colormap has probably changed, so
406 if (n
== ITERATIONS
- 1)
407 XGrabServer(display
);
410 if (visual
->class == DirectColor
) {
414 XQueryColors(display
, colormap
, cols
, ncols
);
420 #define USE_CLOSECOLOR attributes && \
421 (((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
422 || ((attributes->valuemask & XpmRGBCloseness) && \
423 (attributes->red_closeness != 0 \
424 || attributes->green_closeness != 0 \
425 || attributes->blue_closeness != 0)))
429 /* nothing to do here, the window system does it */
433 * set the color pixel related to the given colorname,
434 * return 0 if success, 1 otherwise.
438 SetColor(display
, colormap
, visual
, colorname
, color_index
,
439 image_pixel
, mask_pixel
, mask_pixel_index
,
440 alloc_pixels
, nalloc_pixels
, used_pixels
, nused_pixels
,
441 attributes
, cols
, ncols
, allocColor
, closure
)
446 unsigned int color_index
;
447 Pixel
*image_pixel
, *mask_pixel
;
448 unsigned int *mask_pixel_index
;
450 unsigned int *nalloc_pixels
;
452 unsigned int *nused_pixels
;
453 XpmAttributes
*attributes
;
456 XpmAllocColorFunc allocColor
;
462 if (xpmstrcasecmp(colorname
, TRANSPARENT_COLOR
)) {
463 status
= (*allocColor
)(display
, colormap
, colorname
, &xcolor
, closure
);
464 if (status
< 0) /* parse color failed */
470 return (SetCloseColor(display
, colormap
, visual
, &xcolor
,
471 image_pixel
, mask_pixel
,
472 alloc_pixels
, nalloc_pixels
,
473 attributes
, cols
, ncols
,
474 allocColor
, closure
));
476 #endif /* ndef FOR_MSW */
479 alloc_pixels
[(*nalloc_pixels
)++] = xcolor
.pixel
;
480 *image_pixel
= xcolor
.pixel
;
484 *mask_pixel
= RGB(0,0,0);
486 used_pixels
[(*nused_pixels
)++] = xcolor
.pixel
;
492 *mask_pixel
= RGB(255,255,255);
494 /* store the color table index */
495 *mask_pixel_index
= color_index
;
502 CreateColors(display
, attributes
, colors
, ncolors
, image_pixels
, mask_pixels
,
503 mask_pixel_index
, alloc_pixels
, nalloc_pixels
,
504 used_pixels
, nused_pixels
)
506 XpmAttributes
*attributes
;
508 unsigned int ncolors
;
511 unsigned int *mask_pixel_index
;
513 unsigned int *nalloc_pixels
;
515 unsigned int *nused_pixels
;
517 /* variables stored in the XpmAttributes structure */
520 XpmColorSymbol
*colorsymbols
;
521 unsigned int numsymbols
;
522 XpmAllocColorFunc allocColor
;
526 unsigned int color
, key
;
528 XpmColorSymbol
*symbol
;
530 int ErrorStatus
= XpmSuccess
;
535 unsigned int ncols
= 0;
538 * retrieve information from the XpmAttributes
540 if (attributes
&& attributes
->valuemask
& XpmColorSymbols
) {
541 colorsymbols
= attributes
->colorsymbols
;
542 numsymbols
= attributes
->numsymbols
;
546 if (attributes
&& attributes
->valuemask
& XpmVisual
)
547 visual
= attributes
->visual
;
549 visual
= XDefaultVisual(display
, XDefaultScreen(display
));
551 if (attributes
&& (attributes
->valuemask
& XpmColormap
))
552 colormap
= attributes
->colormap
;
554 colormap
= XDefaultColormap(display
, XDefaultScreen(display
));
556 if (attributes
&& (attributes
->valuemask
& XpmColorKey
))
557 key
= attributes
->color_key
;
559 key
= xpmVisualType(visual
);
561 if (attributes
&& (attributes
->valuemask
& XpmAllocColor
))
562 allocColor
= attributes
->alloc_color
;
564 allocColor
= AllocColor
;
565 if (attributes
&& (attributes
->valuemask
& XpmColorClosure
))
566 closure
= attributes
->color_closure
;
571 if (USE_CLOSECOLOR
) {
572 /* originally from SetCloseColor */
574 if (visual
->class == DirectColor
) {
577 * TODO: Implement close colors for DirectColor visuals. This is
578 * difficult situation. Chances are that we will never get here,
579 * because any machine that supports DirectColor will probably
580 * also support TrueColor (and probably PseudoColor). Also,
581 * DirectColor colormaps can be very large, so looking for close
582 * colors may be too slow.
589 ncols
= visual
->map_entries
;
591 ncols
= colormap
->Count
;
593 cols
= (XColor
*) XpmCalloc(ncols
, sizeof(XColor
));
594 for (i
= 0; i
< ncols
; ++i
)
596 XQueryColors(display
, colormap
, cols
, ncols
);
601 #endif /* ndef FOR_MSW */
619 for (color
= 0; color
< ncolors
; color
++, colors
++,
620 image_pixels
++, mask_pixels
++) {
622 pixel_defined
= False
;
623 defaults
= (char **) colors
;
626 * look for a defined symbol
633 for (n
= 0, symbol
= colorsymbols
; n
< numsymbols
; n
++, symbol
++) {
634 if (symbol
->name
&& s
&& !strcmp(symbol
->name
, s
))
637 if (!symbol
->name
&& symbol
->value
) { /* override value */
638 int def_index
= default_index
;
640 while (defaults
[def_index
] == NULL
) /* find defined
643 if (def_index
< 2) {/* nothing towards mono, so try
645 def_index
= default_index
+ 1;
646 while (def_index
<= 5 && defaults
[def_index
] == NULL
)
649 if (def_index
>= 2 && defaults
[def_index
] != NULL
&&
650 !xpmstrcasecmp(symbol
->value
, defaults
[def_index
]))
654 if (n
!= numsymbols
) {
655 if (symbol
->name
&& symbol
->value
)
656 colorname
= symbol
->value
;
658 pixel_defined
= True
;
661 if (!pixel_defined
) { /* pixel not given as symbol value */
665 if (colorname
) { /* colorname given as symbol value */
666 if (!SetColor(display
, colormap
, visual
, colorname
, color
,
667 image_pixels
, mask_pixels
, mask_pixel_index
,
668 alloc_pixels
, nalloc_pixels
, used_pixels
,
669 nused_pixels
, attributes
, cols
, ncols
,
670 allocColor
, closure
))
671 pixel_defined
= True
;
673 ErrorStatus
= XpmColorError
;
676 while (!pixel_defined
&& k
> 1) {
678 if (!SetColor(display
, colormap
, visual
, defaults
[k
],
679 color
, image_pixels
, mask_pixels
,
680 mask_pixel_index
, alloc_pixels
,
681 nalloc_pixels
, used_pixels
, nused_pixels
,
682 attributes
, cols
, ncols
,
683 allocColor
, closure
)) {
684 pixel_defined
= True
;
687 ErrorStatus
= XpmColorError
;
692 while (!pixel_defined
&& k
< NKEYS
+ 1) {
694 if (!SetColor(display
, colormap
, visual
, defaults
[k
],
695 color
, image_pixels
, mask_pixels
,
696 mask_pixel_index
, alloc_pixels
,
697 nalloc_pixels
, used_pixels
, nused_pixels
,
698 attributes
, cols
, ncols
,
699 allocColor
, closure
)) {
700 pixel_defined
= True
;
703 ErrorStatus
= XpmColorError
;
707 if (!pixel_defined
) {
710 return (XpmColorFailed
);
713 /* simply use the given pixel */
714 *image_pixels
= symbol
->pixel
;
715 /* the following makes the mask to be built even if none
716 is given a particular pixel */
718 && !xpmstrcasecmp(symbol
->value
, TRANSPARENT_COLOR
)) {
720 *mask_pixel_index
= color
;
723 used_pixels
[(*nused_pixels
)++] = *image_pixels
;
728 return (ErrorStatus
);
732 /* default FreeColors function, simply call XFreeColors */
734 FreeColors(display
, colormap
, pixels
, n
, closure
)
739 void *closure
; /* not used */
741 return XFreeColors(display
, colormap
, pixels
, n
, 0);
745 /* function call in case of error */
747 #define RETURN(status) \
749 ErrorStatus = status; \
754 XpmCreateImageFromXpmImage(display
, image
,
755 image_return
, shapeimage_return
, attributes
)
758 XImage
**image_return
;
759 XImage
**shapeimage_return
;
760 XpmAttributes
*attributes
;
762 /* variables stored in the XpmAttributes structure */
767 XpmFreeColorsFunc freeColors
;
770 /* variables to return */
771 XImage
*ximage
= NULL
;
772 XImage
*shapeimage
= NULL
;
773 unsigned int mask_pixel_index
= XpmUndefPixel
;
776 /* calculation variables */
777 Pixel
*image_pixels
= NULL
;
778 Pixel
*mask_pixels
= NULL
;
779 Pixel
*alloc_pixels
= NULL
;
780 Pixel
*used_pixels
= NULL
;
781 unsigned int nalloc_pixels
= 0;
782 unsigned int nused_pixels
= 0;
784 /* initialize return values */
786 *image_return
= NULL
;
787 if (shapeimage_return
)
788 *shapeimage_return
= NULL
;
790 /* retrieve information from the XpmAttributes */
791 if (attributes
&& (attributes
->valuemask
& XpmVisual
))
792 visual
= attributes
->visual
;
794 visual
= XDefaultVisual(display
, XDefaultScreen(display
));
796 if (attributes
&& (attributes
->valuemask
& XpmColormap
))
797 colormap
= attributes
->colormap
;
799 colormap
= XDefaultColormap(display
, XDefaultScreen(display
));
801 if (attributes
&& (attributes
->valuemask
& XpmDepth
))
802 depth
= attributes
->depth
;
804 depth
= XDefaultDepth(display
, XDefaultScreen(display
));
806 if (attributes
&& (attributes
->valuemask
& XpmBitmapFormat
))
807 bitmap_format
= attributes
->bitmap_format
;
809 bitmap_format
= ZPixmap
;
811 if (attributes
&& (attributes
->valuemask
& XpmFreeColors
))
812 freeColors
= attributes
->free_colors
;
814 freeColors
= FreeColors
;
815 if (attributes
&& (attributes
->valuemask
& XpmColorClosure
))
816 closure
= attributes
->color_closure
;
820 ErrorStatus
= XpmSuccess
;
822 /* malloc pixels index tables */
823 image_pixels
= (Pixel
*) XpmMalloc(sizeof(Pixel
) * image
->ncolors
);
825 return (XpmNoMemory
);
827 mask_pixels
= (Pixel
*) XpmMalloc(sizeof(Pixel
) * image
->ncolors
);
831 /* maximum of allocated pixels will be the number of colors */
832 alloc_pixels
= (Pixel
*) XpmMalloc(sizeof(Pixel
) * image
->ncolors
);
836 /* maximum of allocated pixels will be the number of colors */
837 used_pixels
= (Pixel
*) XpmMalloc(sizeof(Pixel
) * image
->ncolors
);
841 /* get pixel colors, store them in index tables */
842 ErrorStatus
= CreateColors(display
, attributes
, image
->colorTable
,
843 image
->ncolors
, image_pixels
, mask_pixels
,
844 &mask_pixel_index
, alloc_pixels
, &nalloc_pixels
,
845 used_pixels
, &nused_pixels
);
847 if (ErrorStatus
!= XpmSuccess
848 && (ErrorStatus
< 0 || (attributes
849 && (attributes
->valuemask
& XpmExactColors
)
850 && attributes
->exactColors
)))
853 /* create the ximage */
855 ErrorStatus
= CreateXImage(display
, visual
, depth
,
856 (depth
== 1 ? bitmap_format
: ZPixmap
),
857 image
->width
, image
->height
, &ximage
);
858 if (ErrorStatus
!= XpmSuccess
)
865 * set the ximage data using optimized functions for ZPixmap
868 if (ximage
->bits_per_pixel
== 8)
869 PutImagePixels8(ximage
, image
->width
, image
->height
,
870 image
->data
, image_pixels
);
871 else if (((ximage
->bits_per_pixel
| ximage
->depth
) == 1) &&
872 (ximage
->byte_order
== ximage
->bitmap_bit_order
))
873 PutImagePixels1(ximage
, image
->width
, image
->height
,
874 image
->data
, image_pixels
);
875 else if (ximage
->bits_per_pixel
== 16)
876 PutImagePixels16(ximage
, image
->width
, image
->height
,
877 image
->data
, image_pixels
);
878 else if (ximage
->bits_per_pixel
== 32)
879 PutImagePixels32(ximage
, image
->width
, image
->height
,
880 image
->data
, image_pixels
);
882 PutImagePixels(ximage
, image
->width
, image
->height
,
883 image
->data
, image_pixels
);
885 APutImagePixels(ximage
, image
->width
, image
->height
,
886 image
->data
, image_pixels
);
889 MSWPutImagePixels(display
, ximage
, image
->width
, image
->height
,
890 image
->data
, image_pixels
);
893 /* create the shape mask image */
894 if (mask_pixel_index
!= XpmUndefPixel
&& shapeimage_return
) {
895 ErrorStatus
= CreateXImage(display
, visual
, 1, bitmap_format
,
896 image
->width
, image
->height
, &shapeimage
);
897 if (ErrorStatus
!= XpmSuccess
)
902 PutImagePixels1(shapeimage
, image
->width
, image
->height
,
903 image
->data
, mask_pixels
);
905 APutImagePixels(shapeimage
, image
->width
, image
->height
,
906 image
->data
, mask_pixels
);
909 MSWPutImagePixels(display
, shapeimage
, image
->width
, image
->height
,
910 image
->data
, mask_pixels
);
914 XpmFree(image_pixels
);
915 XpmFree(mask_pixels
);
917 /* if requested return used pixels in the XpmAttributes structure */
918 if (attributes
&& (attributes
->valuemask
& XpmReturnPixels
||
919 /* 3.2 backward compatibility code */
920 attributes
->valuemask
& XpmReturnInfos
)) {
922 attributes
->pixels
= used_pixels
;
923 attributes
->npixels
= nused_pixels
;
924 attributes
->mask_pixel
= mask_pixel_index
;
926 XpmFree(used_pixels
);
928 /* if requested return alloc'ed pixels in the XpmAttributes structure */
929 if (attributes
&& (attributes
->valuemask
& XpmReturnAllocPixels
)) {
930 attributes
->alloc_pixels
= alloc_pixels
;
931 attributes
->nalloc_pixels
= nalloc_pixels
;
933 XpmFree(alloc_pixels
);
935 /* return created images */
937 *image_return
= ximage
;
938 if (shapeimage_return
)
939 *shapeimage_return
= shapeimage
;
941 return (ErrorStatus
);
943 /* exit point in case of error, free only locally allocated variables */
946 XDestroyImage(ximage
);
948 XDestroyImage(shapeimage
);
950 XpmFree(image_pixels
);
952 XpmFree(mask_pixels
);
954 (*freeColors
)(display
, colormap
, alloc_pixels
, nalloc_pixels
, NULL
);
956 XpmFree(alloc_pixels
);
958 XpmFree(used_pixels
);
960 return (ErrorStatus
);
965 * Create an XImage with its data
968 CreateXImage(display
, visual
, depth
, format
, width
, height
, image_return
)
975 XImage
**image_return
;
979 /* first get bitmap_pad */
987 /* then create the XImage with data = NULL and bytes_per_line = 0 */
988 *image_return
= XCreateImage(display
, visual
, depth
, format
, 0, 0,
989 width
, height
, bitmap_pad
, 0);
991 return (XpmNoMemory
);
993 #if !defined(FOR_MSW) && !defined(AMIGA)
994 /* now that bytes_per_line must have been set properly alloc data */
995 (*image_return
)->data
=
996 (char *) XpmMalloc((*image_return
)->bytes_per_line
* height
);
998 if (!(*image_return
)->data
) {
999 XDestroyImage(*image_return
);
1000 *image_return
= NULL
;
1001 return (XpmNoMemory
);
1004 /* under FOR_MSW and AMIGA XCreateImage has done it all */
1006 return (XpmSuccess
);
1012 * The functions below are written from X11R5 MIT's code (XImUtil.c)
1014 * The idea is to have faster functions than the standard XPutPixel function
1015 * to build the image data. Indeed we can speed up things by suppressing tests
1016 * performed for each pixel. We do the same tests but at the image level.
1017 * We also assume that we use only ZPixmap images with null offsets.
1020 LFUNC(_putbits
, void, (register char *src
, int dstoffset
,
1021 register int numbits
, register char *dst
));
1023 LFUNC(_XReverse_Bytes
, int, (register unsigned char *bpt
, register int nb
));
1025 static unsigned char Const _reverse_byte
[0x100] = {
1026 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
1027 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
1028 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
1029 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
1030 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
1031 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
1032 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
1033 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1034 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1035 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1036 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1037 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1038 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1039 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1040 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1041 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1042 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1043 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1044 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1045 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1046 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1047 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1048 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1049 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1050 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1051 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1052 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1053 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1054 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1055 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1056 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1057 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1061 _XReverse_Bytes(bpt
, nb
)
1062 register unsigned char *bpt
;
1066 *bpt
= _reverse_byte
[*bpt
];
1074 xpm_xynormalizeimagebits(bp
, img
)
1075 register unsigned char *bp
;
1076 register XImage
*img
;
1078 register unsigned char c
;
1080 if (img
->byte_order
!= img
->bitmap_bit_order
) {
1081 switch (img
->bitmap_unit
) {
1094 *(bp
+ 2) = *(bp
+ 1);
1099 if (img
->bitmap_bit_order
== MSBFirst
)
1100 _XReverse_Bytes(bp
, img
->bitmap_unit
>> 3);
1104 xpm_znormalizeimagebits(bp
, img
)
1105 register unsigned char *bp
;
1106 register XImage
*img
;
1108 register unsigned char c
;
1110 switch (img
->bits_per_pixel
) {
1113 _XReverse_Bytes(bp
, 1);
1117 *bp
= ((*bp
>> 4) & 0xF) | ((*bp
<< 4) & ~0xF);
1137 *(bp
+ 2) = *(bp
+ 1);
1143 static unsigned char Const _lomask
[0x09] = {
1144 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
1145 static unsigned char Const _himask
[0x09] = {
1146 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
1149 _putbits(src
, dstoffset
, numbits
, dst
)
1150 register char *src
; /* address of source bit string */
1151 int dstoffset
; /* bit offset into destination;
1153 register int numbits
; /* number of bits to copy to
1155 register char *dst
; /* address of destination bit string */
1157 register unsigned char chlo
, chhi
;
1160 dst
= dst
+ (dstoffset
>> 3);
1161 dstoffset
= dstoffset
& 7;
1162 hibits
= 8 - dstoffset
;
1163 chlo
= *dst
& _lomask
[dstoffset
];
1165 chhi
= (*src
<< dstoffset
) & _himask
[dstoffset
];
1166 if (numbits
<= hibits
) {
1167 chhi
= chhi
& _lomask
[dstoffset
+ numbits
];
1168 *dst
= (*dst
& _himask
[dstoffset
+ numbits
]) | chlo
| chhi
;
1173 numbits
= numbits
- hibits
;
1174 chlo
= (unsigned char) (*src
& _himask
[hibits
]) >> hibits
;
1176 if (numbits
<= dstoffset
) {
1177 chlo
= chlo
& _lomask
[numbits
];
1178 *dst
= (*dst
& _himask
[numbits
]) | chlo
;
1181 numbits
= numbits
- dstoffset
;
1186 * Default method to write pixels into a Z image data structure.
1187 * The algorithm used is:
1189 * copy the destination bitmap_unit or Zpixel to temp
1190 * normalize temp if needed
1191 * copy the pixel bits into the temp
1192 * renormalize temp if needed
1193 * copy the temp back into the destination image data
1197 PutImagePixels(image
, width
, height
, pixelindex
, pixels
)
1200 unsigned int height
;
1201 unsigned int *pixelindex
;
1206 register unsigned int *iptr
;
1207 register int x
, y
, i
;
1208 register char *data
;
1210 int nbytes
, depth
, ibu
, ibpp
;
1214 depth
= image
->depth
;
1216 ibu
= image
->bitmap_unit
;
1217 for (y
= 0; y
< height
; y
++)
1218 for (x
= 0; x
< width
; x
++, iptr
++) {
1219 pixel
= pixels
[*iptr
];
1220 for (i
= 0, px
= pixel
; i
< sizeof(unsigned long);
1222 ((unsigned char *) &pixel
)[i
] = px
;
1223 src
= &data
[XYINDEX(x
, y
, image
)];
1227 for (i
= nbytes
; --i
>= 0;)
1229 XYNORMALIZE(&px
, image
);
1230 _putbits((char *) &pixel
, (x
% ibu
), 1, (char *) &px
);
1231 XYNORMALIZE(&px
, image
);
1233 dst
= &data
[XYINDEX(x
, y
, image
)];
1234 for (i
= nbytes
; --i
>= 0;)
1238 ibpp
= image
->bits_per_pixel
;
1239 for (y
= 0; y
< height
; y
++)
1240 for (x
= 0; x
< width
; x
++, iptr
++) {
1241 pixel
= pixels
[*iptr
];
1244 for (i
= 0, px
= pixel
; i
< sizeof(unsigned long); i
++,
1246 ((unsigned char *) &pixel
)[i
] = px
;
1247 src
= &data
[ZINDEX(x
, y
, image
)];
1250 nbytes
= (ibpp
+ 7) >> 3;
1251 for (i
= nbytes
; --i
>= 0;)
1253 ZNORMALIZE(&px
, image
);
1254 _putbits((char *) &pixel
, (x
* ibpp
) & 7, ibpp
, (char *) &px
);
1255 ZNORMALIZE(&px
, image
);
1257 dst
= &data
[ZINDEX(x
, y
, image
)];
1258 for (i
= nbytes
; --i
>= 0;)
1265 * write pixels into a 32-bits Z image data structure
1268 #if !defined(WORD64) && !defined(LONG64)
1269 /* this item is static but deterministic so let it slide; doesn't
1270 * hurt re-entrancy of this library. Note if it is actually const then would
1271 * be OK under rules of ANSI-C but probably not C++ which may not
1272 * want to allocate space for it.
1274 static unsigned long byteorderpixel
= MSBFirst
<< 24;
1279 WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
1280 3.2e code - by default you get the speeded-up version.
1284 PutImagePixels32(image
, width
, height
, pixelindex
, pixels
)
1287 unsigned int height
;
1288 unsigned int *pixelindex
;
1291 unsigned char *data
;
1296 #ifdef WITHOUT_SPEEDUPS
1299 unsigned char *addr
;
1301 data
= (unsigned char *) image
->data
;
1303 #if !defined(WORD64) && !defined(LONG64)
1304 if (*((char *) &byteorderpixel
) == image
->byte_order
) {
1305 for (y
= 0; y
< height
; y
++)
1306 for (x
= 0; x
< width
; x
++, iptr
++) {
1307 addr
= &data
[ZINDEX32(x
, y
, image
)];
1308 *((unsigned long *) addr
) = pixels
[*iptr
];
1312 if (image
->byte_order
== MSBFirst
)
1313 for (y
= 0; y
< height
; y
++)
1314 for (x
= 0; x
< width
; x
++, iptr
++) {
1315 addr
= &data
[ZINDEX32(x
, y
, image
)];
1316 pixel
= pixels
[*iptr
];
1317 addr
[0] = pixel
>> 24;
1318 addr
[1] = pixel
>> 16;
1319 addr
[2] = pixel
>> 8;
1323 for (y
= 0; y
< height
; y
++)
1324 for (x
= 0; x
< width
; x
++, iptr
++) {
1325 addr
= &data
[ZINDEX32(x
, y
, image
)];
1326 pixel
= pixels
[*iptr
];
1328 addr
[1] = pixel
>> 8;
1329 addr
[2] = pixel
>> 16;
1330 addr
[3] = pixel
>> 24;
1333 #else /* WITHOUT_SPEEDUPS */
1335 int bpl
= image
->bytes_per_line
;
1336 unsigned char *data_ptr
, *max_data
;
1338 data
= (unsigned char *) image
->data
;
1340 #if !defined(WORD64) && !defined(LONG64)
1341 if (*((char *) &byteorderpixel
) == image
->byte_order
) {
1342 for (y
= 0; y
< height
; y
++) {
1344 max_data
= data_ptr
+ (width
<< 2);
1346 while (data_ptr
< max_data
) {
1347 *((unsigned long *) data_ptr
) = pixels
[*(iptr
++)];
1348 data_ptr
+= (1 << 2);
1354 if (image
->byte_order
== MSBFirst
)
1355 for (y
= 0; y
< height
; y
++) {
1357 max_data
= data_ptr
+ (width
<< 2);
1359 while (data_ptr
< max_data
) {
1360 pixel
= pixels
[*(iptr
++)];
1362 *data_ptr
++ = pixel
>> 24;
1363 *data_ptr
++ = pixel
>> 16;
1364 *data_ptr
++ = pixel
>> 8;
1365 *data_ptr
++ = pixel
;
1371 for (y
= 0; y
< height
; y
++) {
1373 max_data
= data_ptr
+ (width
<< 2);
1375 while (data_ptr
< max_data
) {
1376 pixel
= pixels
[*(iptr
++)];
1378 *data_ptr
++ = pixel
;
1379 *data_ptr
++ = pixel
>> 8;
1380 *data_ptr
++ = pixel
>> 16;
1381 *data_ptr
++ = pixel
>> 24;
1386 #endif /* WITHOUT_SPEEDUPS */
1390 * write pixels into a 16-bits Z image data structure
1394 PutImagePixels16(image
, width
, height
, pixelindex
, pixels
)
1397 unsigned int height
;
1398 unsigned int *pixelindex
;
1401 unsigned char *data
;
1405 #ifdef WITHOUT_SPEEDUPS
1408 unsigned char *addr
;
1410 data
= (unsigned char *) image
->data
;
1412 if (image
->byte_order
== MSBFirst
)
1413 for (y
= 0; y
< height
; y
++)
1414 for (x
= 0; x
< width
; x
++, iptr
++) {
1415 addr
= &data
[ZINDEX16(x
, y
, image
)];
1416 addr
[0] = pixels
[*iptr
] >> 8;
1417 addr
[1] = pixels
[*iptr
];
1420 for (y
= 0; y
< height
; y
++)
1421 for (x
= 0; x
< width
; x
++, iptr
++) {
1422 addr
= &data
[ZINDEX16(x
, y
, image
)];
1423 addr
[0] = pixels
[*iptr
];
1424 addr
[1] = pixels
[*iptr
] >> 8;
1427 #else /* WITHOUT_SPEEDUPS */
1431 int bpl
= image
->bytes_per_line
;
1432 unsigned char *data_ptr
, *max_data
;
1434 data
= (unsigned char *) image
->data
;
1436 if (image
->byte_order
== MSBFirst
)
1437 for (y
= 0; y
< height
; y
++) {
1439 max_data
= data_ptr
+ (width
<< 1);
1441 while (data_ptr
< max_data
) {
1442 pixel
= pixels
[*(iptr
++)];
1444 data_ptr
[0] = pixel
>> 8;
1445 data_ptr
[1] = pixel
;
1447 data_ptr
+= (1 << 1);
1452 for (y
= 0; y
< height
; y
++) {
1454 max_data
= data_ptr
+ (width
<< 1);
1456 while (data_ptr
< max_data
) {
1457 pixel
= pixels
[*(iptr
++)];
1459 data_ptr
[0] = pixel
;
1460 data_ptr
[1] = pixel
>> 8;
1462 data_ptr
+= (1 << 1);
1467 #endif /* WITHOUT_SPEEDUPS */
1471 * write pixels into a 8-bits Z image data structure
1475 PutImagePixels8(image
, width
, height
, pixelindex
, pixels
)
1478 unsigned int height
;
1479 unsigned int *pixelindex
;
1486 #ifdef WITHOUT_SPEEDUPS
1492 for (y
= 0; y
< height
; y
++)
1493 for (x
= 0; x
< width
; x
++, iptr
++)
1494 data
[ZINDEX8(x
, y
, image
)] = pixels
[*iptr
];
1496 #else /* WITHOUT_SPEEDUPS */
1498 int bpl
= image
->bytes_per_line
;
1499 char *data_ptr
, *max_data
;
1504 for (y
= 0; y
< height
; y
++) {
1506 max_data
= data_ptr
+ width
;
1508 while (data_ptr
< max_data
)
1509 *(data_ptr
++) = pixels
[*(iptr
++)];
1514 #endif /* WITHOUT_SPEEDUPS */
1518 * write pixels into a 1-bit depth image data structure and **offset null**
1522 PutImagePixels1(image
, width
, height
, pixelindex
, pixels
)
1525 unsigned int height
;
1526 unsigned int *pixelindex
;
1529 if (image
->byte_order
!= image
->bitmap_bit_order
)
1530 PutImagePixels(image
, width
, height
, pixelindex
, pixels
);
1536 #ifdef WITHOUT_SPEEDUPS
1542 if (image
->bitmap_bit_order
== MSBFirst
)
1543 for (y
= 0; y
< height
; y
++)
1544 for (x
= 0; x
< width
; x
++, iptr
++) {
1545 if (pixels
[*iptr
] & 1)
1546 data
[ZINDEX1(x
, y
, image
)] |= 0x80 >> (x
& 7);
1548 data
[ZINDEX1(x
, y
, image
)] &= ~(0x80 >> (x
& 7));
1551 for (y
= 0; y
< height
; y
++)
1552 for (x
= 0; x
< width
; x
++, iptr
++) {
1553 if (pixels
[*iptr
] & 1)
1554 data
[ZINDEX1(x
, y
, image
)] |= 1 << (x
& 7);
1556 data
[ZINDEX1(x
, y
, image
)] &= ~(1 << (x
& 7));
1559 #else /* WITHOUT_SPEEDUPS */
1562 char *data_ptr
, *max_data
;
1563 int bpl
= image
->bytes_per_line
;
1572 if (image
->bitmap_bit_order
== MSBFirst
)
1573 for (y
= 0; y
< height
; y
++) {
1575 max_data
= data_ptr
+ width
;
1576 while (data_ptr
< max_data
) {
1579 value
= (value
<< 1) | (pixels
[*(iptr
++)] & 1);
1580 value
= (value
<< 1) | (pixels
[*(iptr
++)] & 1);
1581 value
= (value
<< 1) | (pixels
[*(iptr
++)] & 1);
1582 value
= (value
<< 1) | (pixels
[*(iptr
++)] & 1);
1583 value
= (value
<< 1) | (pixels
[*(iptr
++)] & 1);
1584 value
= (value
<< 1) | (pixels
[*(iptr
++)] & 1);
1585 value
= (value
<< 1) | (pixels
[*(iptr
++)] & 1);
1586 value
= (value
<< 1) | (pixels
[*(iptr
++)] & 1);
1588 *(data_ptr
++) = value
;
1592 for (count
= 0; count
< diff
; count
++) {
1593 if (pixels
[*(iptr
++)] & 1)
1594 value
|= (0x80 >> count
);
1596 *(data_ptr
) = value
;
1601 for (y
= 0; y
< height
; y
++) {
1603 max_data
= data_ptr
+ width
;
1604 while (data_ptr
< max_data
) {
1608 value
= (value
<< 1) | (pixels
[*(--iptr
)] & 1);
1609 value
= (value
<< 1) | (pixels
[*(--iptr
)] & 1);
1610 value
= (value
<< 1) | (pixels
[*(--iptr
)] & 1);
1611 value
= (value
<< 1) | (pixels
[*(--iptr
)] & 1);
1612 value
= (value
<< 1) | (pixels
[*(--iptr
)] & 1);
1613 value
= (value
<< 1) | (pixels
[*(--iptr
)] & 1);
1614 value
= (value
<< 1) | (pixels
[*(--iptr
)] & 1);
1615 value
= (value
<< 1) | (pixels
[*(--iptr
)] & 1);
1618 *(data_ptr
++) = value
;
1622 for (count
= 0; count
< diff
; count
++) {
1623 if (pixels
[*(iptr
++)] & 1)
1624 value
|= (1 << count
);
1626 *(data_ptr
) = value
;
1631 #endif /* WITHOUT_SPEEDUPS */
1636 XpmCreatePixmapFromXpmImage(display
, d
, image
,
1637 pixmap_return
, shapemask_return
, attributes
)
1641 Pixmap
*pixmap_return
;
1642 Pixmap
*shapemask_return
;
1643 XpmAttributes
*attributes
;
1645 XImage
*ximage
, *shapeimage
;
1648 /* initialize return values */
1651 if (shapemask_return
)
1652 *shapemask_return
= 0;
1654 /* create the ximages */
1655 ErrorStatus
= XpmCreateImageFromXpmImage(display
, image
,
1656 (pixmap_return
? &ximage
: NULL
),
1658 &shapeimage
: NULL
),
1660 if (ErrorStatus
< 0)
1661 return (ErrorStatus
);
1663 /* create the pixmaps and destroy images */
1664 if (pixmap_return
&& ximage
) {
1665 xpmCreatePixmapFromImage(display
, d
, ximage
, pixmap_return
);
1666 XDestroyImage(ximage
);
1668 if (shapemask_return
&& shapeimage
) {
1669 xpmCreatePixmapFromImage(display
, d
, shapeimage
, shapemask_return
);
1670 XDestroyImage(shapeimage
);
1672 return (ErrorStatus
);
1681 unsigned int height
,
1682 unsigned int *pixelindex
,
1685 unsigned int *data
= pixelindex
;
1687 unsigned char *array
;
1689 BOOL success
= FALSE
;
1691 array
= XpmMalloc ((((width
+15)>>4)<<4)*sizeof (*array
));
1694 tmp_img
= AllocXImage ((((width
+15)>>4)<<4), 1,
1695 image
->rp
->BitMap
->Depth
);
1696 if (tmp_img
!= NULL
)
1698 for (y
= 0; y
< height
; ++y
)
1700 for (x
= 0; x
< width
; ++x
)
1701 array
[x
] = pixels
[*(data
++)];
1702 WritePixelLine8 (image
->rp
, 0, y
, width
, array
, tmp_img
->rp
);
1704 FreeXImage (tmp_img
);
1712 for (y
= 0; y
< height
; ++y
)
1713 for (x
= 0; x
< width
; ++x
)
1714 XPutPixel (image
, x
, y
, pixels
[*(data
++)]);
1719 #else /* FOR_MSW part follows */
1721 MSWPutImagePixels(dc
, image
, width
, height
, pixelindex
, pixels
)
1725 unsigned int height
;
1726 unsigned int *pixelindex
;
1729 unsigned int *data
= pixelindex
;
1733 obm
= SelectObject(*dc
, image
->bitmap
);
1734 for (y
= 0; y
< height
; y
++) {
1735 for (x
= 0; x
< width
; x
++) {
1736 SetPixel(*dc
, x
, y
, pixels
[*(data
++)]); /* data is [x+y*width] */
1739 SelectObject(*dc
, obm
);
1742 #endif /* FOR_MSW */
1746 #if !defined(FOR_MSW) && !defined(AMIGA)
1749 PutPixel1(ximage
, x
, y
, pixel
)
1750 register XImage
*ximage
;
1753 unsigned long pixel
;
1758 register char *data
;
1762 for (i
=0, px
=pixel
; i
<sizeof(unsigned long); i
++, px
>>=8)
1763 ((unsigned char *)&pixel
)[i
] = px
;
1764 src
= &ximage
->data
[XYINDEX(x
, y
, ximage
)];
1767 nbytes
= ximage
->bitmap_unit
>> 3;
1768 for (i
= nbytes
; --i
>= 0; ) *dst
++ = *src
++;
1769 XYNORMALIZE(&px
, ximage
);
1770 i
= ((x
+ ximage
->xoffset
) % ximage
->bitmap_unit
);
1771 _putbits ((char *)&pixel
, i
, 1, (char *)&px
);
1772 XYNORMALIZE(&px
, ximage
);
1774 dst
= &ximage
->data
[XYINDEX(x
, y
, ximage
)];
1775 for (i
= nbytes
; --i
>= 0; )
1782 PutPixel(ximage
, x
, y
, pixel
)
1783 register XImage
*ximage
;
1786 unsigned long pixel
;
1791 register char *data
;
1795 ibpp
= ximage
->bits_per_pixel
;
1796 if (ximage
->depth
== 4)
1798 for (i
= 0, px
= pixel
; i
< sizeof(unsigned long); i
++, px
>>= 8)
1799 ((unsigned char *) &pixel
)[i
] = px
;
1800 src
= &ximage
->data
[ZINDEX(x
, y
, ximage
)];
1803 nbytes
= (ibpp
+ 7) >> 3;
1804 for (i
= nbytes
; --i
>= 0;)
1806 ZNORMALIZE(&px
, ximage
);
1807 _putbits((char *) &pixel
, (x
* ibpp
) & 7, ibpp
, (char *) &px
);
1808 ZNORMALIZE(&px
, ximage
);
1810 dst
= &ximage
->data
[ZINDEX(x
, y
, ximage
)];
1811 for (i
= nbytes
; --i
>= 0;)
1818 PutPixel32(ximage
, x
, y
, pixel
)
1819 register XImage
*ximage
;
1822 unsigned long pixel
;
1824 unsigned char *addr
;
1826 addr
= &((unsigned char *)ximage
->data
) [ZINDEX32(x
, y
, ximage
)];
1827 *((unsigned long *)addr
) = pixel
;
1832 PutPixel32MSB(ximage
, x
, y
, pixel
)
1833 register XImage
*ximage
;
1836 unsigned long pixel
;
1838 unsigned char *addr
;
1840 addr
= &((unsigned char *)ximage
->data
) [ZINDEX32(x
, y
, ximage
)];
1841 addr
[0] = pixel
>> 24;
1842 addr
[1] = pixel
>> 16;
1843 addr
[2] = pixel
>> 8;
1849 PutPixel32LSB(ximage
, x
, y
, pixel
)
1850 register XImage
*ximage
;
1853 unsigned long pixel
;
1855 unsigned char *addr
;
1857 addr
= &((unsigned char *)ximage
->data
) [ZINDEX32(x
, y
, ximage
)];
1858 addr
[3] = pixel
>> 24;
1859 addr
[2] = pixel
>> 16;
1860 addr
[1] = pixel
>> 8;
1866 PutPixel16MSB(ximage
, x
, y
, pixel
)
1867 register XImage
*ximage
;
1870 unsigned long pixel
;
1872 unsigned char *addr
;
1874 addr
= &((unsigned char *)ximage
->data
) [ZINDEX16(x
, y
, ximage
)];
1875 addr
[0] = pixel
>> 8;
1881 PutPixel16LSB(ximage
, x
, y
, pixel
)
1882 register XImage
*ximage
;
1885 unsigned long pixel
;
1887 unsigned char *addr
;
1889 addr
= &((unsigned char *)ximage
->data
) [ZINDEX16(x
, y
, ximage
)];
1890 addr
[1] = pixel
>> 8;
1896 PutPixel8(ximage
, x
, y
, pixel
)
1897 register XImage
*ximage
;
1900 unsigned long pixel
;
1902 ximage
->data
[ZINDEX8(x
, y
, ximage
)] = pixel
;
1907 PutPixel1MSB(ximage
, x
, y
, pixel
)
1908 register XImage
*ximage
;
1911 unsigned long pixel
;
1914 ximage
->data
[ZINDEX1(x
, y
, ximage
)] |= 0x80 >> (x
& 7);
1916 ximage
->data
[ZINDEX1(x
, y
, ximage
)] &= ~(0x80 >> (x
& 7));
1921 PutPixel1LSB(ximage
, x
, y
, pixel
)
1922 register XImage
*ximage
;
1925 unsigned long pixel
;
1928 ximage
->data
[ZINDEX1(x
, y
, ximage
)] |= 1 << (x
& 7);
1930 ximage
->data
[ZINDEX1(x
, y
, ximage
)] &= ~(1 << (x
& 7));
1934 #endif /* not FOR_MSW && not AMIGA */
1937 * This function parses an Xpm file or data and directly create an XImage
1940 xpmParseDataAndCreate(display
, data
, image_return
, shapeimage_return
,
1941 image
, info
, attributes
)
1944 XImage
**image_return
;
1945 XImage
**shapeimage_return
;
1948 XpmAttributes
*attributes
;
1950 /* variables stored in the XpmAttributes structure */
1955 XpmFreeColorsFunc freeColors
;
1958 /* variables to return */
1959 XImage
*ximage
= NULL
;
1960 XImage
*shapeimage
= NULL
;
1961 unsigned int mask_pixel_index
= XpmUndefPixel
;
1963 /* calculation variables */
1964 Pixel
*image_pixels
= NULL
;
1965 Pixel
*mask_pixels
= NULL
;
1966 Pixel
*alloc_pixels
= NULL
;
1967 Pixel
*used_pixels
= NULL
;
1968 unsigned int nalloc_pixels
= 0;
1969 unsigned int nused_pixels
= 0;
1970 unsigned int width
, height
, ncolors
, cpp
;
1971 unsigned int x_hotspot
, y_hotspot
, hotspot
= 0, extensions
= 0;
1972 XpmColor
*colorTable
= NULL
;
1973 char *hints_cmt
= NULL
;
1974 char *colors_cmt
= NULL
;
1975 char *pixels_cmt
= NULL
;
1979 xpmHashTable hashtable
;
1982 /* initialize return values */
1984 *image_return
= NULL
;
1985 if (shapeimage_return
)
1986 *shapeimage_return
= NULL
;
1989 /* retrieve information from the XpmAttributes */
1990 if (attributes
&& (attributes
->valuemask
& XpmVisual
))
1991 visual
= attributes
->visual
;
1993 visual
= XDefaultVisual(display
, XDefaultScreen(display
));
1995 if (attributes
&& (attributes
->valuemask
& XpmColormap
))
1996 colormap
= attributes
->colormap
;
1998 colormap
= XDefaultColormap(display
, XDefaultScreen(display
));
2000 if (attributes
&& (attributes
->valuemask
& XpmDepth
))
2001 depth
= attributes
->depth
;
2003 depth
= XDefaultDepth(display
, XDefaultScreen(display
));
2005 if (attributes
&& (attributes
->valuemask
& XpmBitmapFormat
))
2006 bitmap_format
= attributes
->bitmap_format
;
2008 bitmap_format
= ZPixmap
;
2010 if (attributes
&& (attributes
->valuemask
& XpmFreeColors
))
2011 freeColors
= attributes
->free_colors
;
2013 freeColors
= FreeColors
;
2014 if (attributes
&& (attributes
->valuemask
& XpmColorClosure
))
2015 closure
= attributes
->color_closure
;
2019 cmts
= info
&& (info
->valuemask
& XpmReturnComments
);
2024 ErrorStatus
= xpmParseHeader(data
);
2025 if (ErrorStatus
!= XpmSuccess
)
2026 return (ErrorStatus
);
2031 ErrorStatus
= xpmParseValues(data
, &width
, &height
, &ncolors
, &cpp
,
2032 &x_hotspot
, &y_hotspot
, &hotspot
,
2034 if (ErrorStatus
!= XpmSuccess
)
2035 return (ErrorStatus
);
2038 * store the hints comment line
2041 xpmGetCmt(data
, &hints_cmt
);
2046 if (USE_HASHTABLE
) {
2047 ErrorStatus
= xpmHashTableInit(&hashtable
);
2048 if (ErrorStatus
!= XpmSuccess
)
2049 return (ErrorStatus
);
2055 ErrorStatus
= xpmParseColors(data
, ncolors
, cpp
, &colorTable
, &hashtable
);
2056 if (ErrorStatus
!= XpmSuccess
)
2057 RETURN(ErrorStatus
);
2060 * store the colors comment line
2063 xpmGetCmt(data
, &colors_cmt
);
2065 /* malloc pixels index tables */
2066 image_pixels
= (Pixel
*) XpmMalloc(sizeof(Pixel
) * ncolors
);
2068 RETURN(XpmNoMemory
);
2070 mask_pixels
= (Pixel
*) XpmMalloc(sizeof(Pixel
) * ncolors
);
2072 RETURN(XpmNoMemory
);
2074 /* maximum of allocated pixels will be the number of colors */
2075 alloc_pixels
= (Pixel
*) XpmMalloc(sizeof(Pixel
) * ncolors
);
2077 RETURN(XpmNoMemory
);
2079 /* maximum of allocated pixels will be the number of colors */
2080 used_pixels
= (Pixel
*) XpmMalloc(sizeof(Pixel
) * ncolors
);
2082 RETURN(XpmNoMemory
);
2084 /* get pixel colors, store them in index tables */
2085 ErrorStatus
= CreateColors(display
, attributes
, colorTable
, ncolors
,
2086 image_pixels
, mask_pixels
, &mask_pixel_index
,
2087 alloc_pixels
, &nalloc_pixels
, used_pixels
,
2090 if (ErrorStatus
!= XpmSuccess
2091 && (ErrorStatus
< 0 || (attributes
2092 && (attributes
->valuemask
& XpmExactColors
)
2093 && attributes
->exactColors
)))
2094 RETURN(ErrorStatus
);
2096 /* now create the ximage */
2098 ErrorStatus
= CreateXImage(display
, visual
, depth
,
2099 (depth
== 1 ? bitmap_format
: ZPixmap
),
2100 width
, height
, &ximage
);
2101 if (ErrorStatus
!= XpmSuccess
)
2102 RETURN(ErrorStatus
);
2104 #if !defined(FOR_MSW) && !defined(AMIGA)
2107 * set the XImage pointer function, to be used with XPutPixel,
2108 * to an internal optimized function
2111 if (ximage
->bits_per_pixel
== 8)
2112 ximage
->f
.put_pixel
= PutPixel8
;
2113 else if (((ximage
->bits_per_pixel
| ximage
->depth
) == 1) &&
2114 (ximage
->byte_order
== ximage
->bitmap_bit_order
))
2115 if (ximage
->bitmap_bit_order
== MSBFirst
)
2116 ximage
->f
.put_pixel
= PutPixel1MSB
;
2118 ximage
->f
.put_pixel
= PutPixel1LSB
;
2119 else if (ximage
->bits_per_pixel
== 16)
2120 if (ximage
->bitmap_bit_order
== MSBFirst
)
2121 ximage
->f
.put_pixel
= PutPixel16MSB
;
2123 ximage
->f
.put_pixel
= PutPixel16LSB
;
2124 else if (ximage
->bits_per_pixel
== 32)
2125 #if !defined(WORD64) && !defined(LONG64)
2126 if (*((char *)&byteorderpixel
) == ximage
->byte_order
)
2127 ximage
->f
.put_pixel
= PutPixel32
;
2130 if (ximage
->bitmap_bit_order
== MSBFirst
)
2131 ximage
->f
.put_pixel
= PutPixel32MSB
;
2133 ximage
->f
.put_pixel
= PutPixel32LSB
;
2134 else if ((ximage
->bits_per_pixel
| ximage
->depth
) == 1)
2135 ximage
->f
.put_pixel
= PutPixel1
;
2137 ximage
->f
.put_pixel
= PutPixel
;
2138 #endif /* not FOR_MSW && not AMIGA */
2141 /* create the shape mask image */
2142 if (mask_pixel_index
!= XpmUndefPixel
&& shapeimage_return
) {
2143 ErrorStatus
= CreateXImage(display
, visual
, 1, bitmap_format
,
2144 width
, height
, &shapeimage
);
2145 if (ErrorStatus
!= XpmSuccess
)
2146 RETURN(ErrorStatus
);
2148 #if !defined(FOR_MSW) && !defined(AMIGA)
2149 if (shapeimage
->bitmap_bit_order
== MSBFirst
)
2150 shapeimage
->f
.put_pixel
= PutPixel1MSB
;
2152 shapeimage
->f
.put_pixel
= PutPixel1LSB
;
2157 * read pixels and put them in the XImage
2159 ErrorStatus
= ParseAndPutPixels(
2163 data
, width
, height
, ncolors
, cpp
,
2164 colorTable
, &hashtable
,
2165 ximage
, image_pixels
,
2166 shapeimage
, mask_pixels
);
2167 XpmFree(image_pixels
);
2168 image_pixels
= NULL
;
2169 XpmFree(mask_pixels
);
2175 if (ErrorStatus
!= XpmSuccess
)
2177 else if (USE_HASHTABLE
)
2178 xpmHashTableFree(&hashtable
);
2181 * store the pixels comment line
2184 xpmGetCmt(data
, &pixels_cmt
);
2189 if (info
&& (info
->valuemask
& XpmReturnExtensions
))
2191 ErrorStatus
= xpmParseExtensions(data
, &info
->extensions
,
2192 &info
->nextensions
);
2193 if (ErrorStatus
!= XpmSuccess
)
2194 RETURN(ErrorStatus
);
2196 info
->extensions
= NULL
;
2197 info
->nextensions
= 0;
2201 * store found informations in the XpmImage structure
2203 image
->width
= width
;
2204 image
->height
= height
;
2206 image
->ncolors
= ncolors
;
2207 image
->colorTable
= colorTable
;
2212 info
->hints_cmt
= hints_cmt
;
2213 info
->colors_cmt
= colors_cmt
;
2214 info
->pixels_cmt
= pixels_cmt
;
2217 info
->x_hotspot
= x_hotspot
;
2218 info
->y_hotspot
= y_hotspot
;
2219 info
->valuemask
|= XpmHotspot
;
2222 /* if requested return used pixels in the XpmAttributes structure */
2223 if (attributes
&& (attributes
->valuemask
& XpmReturnPixels
||
2224 /* 3.2 backward compatibility code */
2225 attributes
->valuemask
& XpmReturnInfos
)) {
2227 attributes
->pixels
= used_pixels
;
2228 attributes
->npixels
= nused_pixels
;
2229 attributes
->mask_pixel
= mask_pixel_index
;
2231 XpmFree(used_pixels
);
2233 /* if requested return alloc'ed pixels in the XpmAttributes structure */
2234 if (attributes
&& (attributes
->valuemask
& XpmReturnAllocPixels
)) {
2235 attributes
->alloc_pixels
= alloc_pixels
;
2236 attributes
->nalloc_pixels
= nalloc_pixels
;
2238 XpmFree(alloc_pixels
);
2240 /* return created images */
2242 *image_return
= ximage
;
2243 if (shapeimage_return
)
2244 *shapeimage_return
= shapeimage
;
2246 return (XpmSuccess
);
2248 /* exit point in case of error, free only locally allocated variables */
2251 xpmHashTableFree(&hashtable
);
2253 xpmFreeColorTable(colorTable
, ncolors
);
2257 XpmFree(colors_cmt
);
2259 XpmFree(pixels_cmt
);
2261 XDestroyImage(ximage
);
2263 XDestroyImage(shapeimage
);
2265 XpmFree(image_pixels
);
2267 XpmFree(mask_pixels
);
2269 (*freeColors
)(display
, colormap
, alloc_pixels
, nalloc_pixels
, NULL
);
2271 XpmFree(alloc_pixels
);
2273 XpmFree(used_pixels
);
2275 return (ErrorStatus
);
2283 data
, width
, height
, ncolors
, cpp
, colorTable
, hashtable
,
2284 image
, image_pixels
, shapeimage
, shape_pixels
)
2290 unsigned int height
;
2291 unsigned int ncolors
;
2293 XpmColor
*colorTable
;
2294 xpmHashTable
*hashtable
;
2296 Pixel
*image_pixels
;
2298 Pixel
*shape_pixels
;
2300 unsigned int a
, x
, y
;
2304 case (1): /* Optimize for single character
2307 unsigned short colidx
[256];
2313 shapedc
= CreateCompatibleDC(*dc
);
2314 sobm
= SelectObject(shapedc
, shapeimage
->bitmap
);
2318 obm
= SelectObject(*dc
, image
->bitmap
);
2322 bzero((char *)colidx
, 256 * sizeof(short));
2323 for (a
= 0; a
< ncolors
; a
++)
2324 colidx
[(unsigned char)colorTable
[a
].string
[0]] = a
+ 1;
2326 for (y
= 0; y
< height
; y
++) {
2327 xpmNextString(data
);
2328 for (x
= 0; x
< width
; x
++) {
2329 int c
= xpmGetC(data
);
2331 if (c
> 0 && c
< 256 && colidx
[c
] != 0) {
2333 XPutPixel(image
, x
, y
, image_pixels
[colidx
[c
] - 1]);
2335 XPutPixel(shapeimage
, x
, y
,
2336 shape_pixels
[colidx
[c
] - 1]);
2338 SetPixel(*dc
, x
, y
, image_pixels
[colidx
[c
] - 1]);
2340 SetPixel(shapedc
, x
, y
, shape_pixels
[colidx
[c
] - 1]);
2344 return (XpmFileInvalid
);
2349 SelectObject(shapedc
, sobm
);
2352 SelectObject(*dc
, obm
);
2357 case (2): /* Optimize for double character
2361 /* free all allocated pointers at all exits */
2362 #define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
2363 if (cidx[f]) XpmFree(cidx[f]);}
2365 /* array of pointers malloced by need */
2366 unsigned short *cidx
[256];
2369 bzero((char *)cidx
, 256 * sizeof(unsigned short *)); /* init */
2370 for (a
= 0; a
< ncolors
; a
++) {
2371 char1
= colorTable
[a
].string
[0];
2372 if (cidx
[char1
] == NULL
) { /* get new memory */
2373 cidx
[char1
] = (unsigned short *)
2374 XpmCalloc(256, sizeof(unsigned short));
2375 if (cidx
[char1
] == NULL
) { /* new block failed */
2377 return (XpmNoMemory
);
2380 cidx
[char1
][(unsigned char)colorTable
[a
].string
[1]] = a
+ 1;
2383 for (y
= 0; y
< height
; y
++) {
2384 xpmNextString(data
);
2385 for (x
= 0; x
< width
; x
++) {
2386 int cc1
= xpmGetC(data
);
2387 if (cc1
> 0 && cc1
< 256) {
2388 int cc2
= xpmGetC(data
);
2389 if (cc2
> 0 && cc2
< 256 &&
2390 cidx
[cc1
] && cidx
[cc1
][cc2
] != 0) {
2392 XPutPixel(image
, x
, y
,
2393 image_pixels
[cidx
[cc1
][cc2
] - 1]);
2395 XPutPixel(shapeimage
, x
, y
,
2396 shape_pixels
[cidx
[cc1
][cc2
] - 1]);
2398 SelectObject(*dc
, image
->bitmap
);
2399 SetPixel(*dc
, x
, y
, image_pixels
[cidx
[cc1
][cc2
] - 1]);
2401 SelectObject(*dc
, shapeimage
->bitmap
);
2403 shape_pixels
[cidx
[cc1
][cc2
] - 1]);
2408 return (XpmFileInvalid
);
2412 return (XpmFileInvalid
);
2420 default: /* Non-optimized case of long color
2427 if (USE_HASHTABLE
) {
2430 for (y
= 0; y
< height
; y
++) {
2431 xpmNextString(data
);
2432 for (x
= 0; x
< width
; x
++) {
2433 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
2435 slot
= xpmHashSlot(hashtable
, buf
);
2436 if (!*slot
) /* no color matches */
2437 return (XpmFileInvalid
);
2439 XPutPixel(image
, x
, y
,
2440 image_pixels
[HashColorIndex(slot
)]);
2442 XPutPixel(shapeimage
, x
, y
,
2443 shape_pixels
[HashColorIndex(slot
)]);
2445 SelectObject(*dc
, image
->bitmap
);
2447 image_pixels
[HashColorIndex(slot
)]);
2449 SelectObject(*dc
, shapeimage
->bitmap
);
2451 shape_pixels
[HashColorIndex(slot
)]);
2457 for (y
= 0; y
< height
; y
++) {
2458 xpmNextString(data
);
2459 for (x
= 0; x
< width
; x
++) {
2460 for (a
= 0, s
= buf
; a
< cpp
; a
++, s
++)
2462 for (a
= 0; a
< ncolors
; a
++)
2463 if (!strcmp(colorTable
[a
].string
, buf
))
2465 if (a
== ncolors
) /* no color matches */
2466 return (XpmFileInvalid
);
2468 XPutPixel(image
, x
, y
, image_pixels
[a
]);
2470 XPutPixel(shapeimage
, x
, y
, shape_pixels
[a
]);
2472 SelectObject(*dc
, image
->bitmap
);
2473 SetPixel(*dc
, x
, y
, image_pixels
[a
]);
2475 SelectObject(*dc
, shapeimage
->bitmap
);
2476 SetPixel(*dc
, x
, y
, shape_pixels
[a
]);
2485 return (XpmSuccess
);