1
/* $XConsortium: Xpmcreate.c /main/8 1996/09/20 08:15:02 pascale $ */
3
* Copyright (C) 1989-95 GROUPE BULL
5
* Permission is hereby granted, free of charge, to any person obtaining a copy
6
* of this software and associated documentation files (the "Software"), to
7
* deal in the Software without restriction, including without limitation the
8
* rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
9
* sell copies of the Software, and to permit persons to whom the Software is
10
* furnished to do so, subject to the following conditions:
12
* The above copyright notice and this permission notice shall be included in
13
* all copies or substantial portions of the Software.
15
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18
* GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
19
* AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
20
* CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
* Except as contained in this notice, the name of GROUPE BULL shall not be
23
* used in advertising or otherwise to promote the sale, use or other dealings
24
* in this Software without prior written authorization from GROUPE BULL.
27
/*****************************************************************************\
31
* Create an X image and possibly its related shape mask *
32
* from the given XpmImage. *
34
* Developed by Arnaud Le Hors *
35
\*****************************************************************************/
38
* The code related to FOR_MSW has been added by
39
* HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
47
/* October 2004, source code review by Thomas Biege <thomas@suse.de> */
52
LFUNC(xpmVisualType, int, (Visual *visual));
54
LFUNC(AllocColor, int, (Display *display, Colormap colormap,
55
char *colorname, XColor *xcolor, void *closure));
56
LFUNC(FreeColors, int, (Display *display, Colormap colormap,
57
Pixel *pixels, int n, void *closure));
60
LFUNC(SetCloseColor, int, (Display *display, Colormap colormap,
61
Visual *visual, XColor *col,
62
Pixel *image_pixel, Pixel *mask_pixel,
63
Pixel *alloc_pixels, unsigned int *nalloc_pixels,
64
XpmAttributes *attributes, XColor *cols, int ncols,
65
XpmAllocColorFunc allocColor, void *closure));
67
/* let the window system take care of close colors */
70
LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual,
71
char *colorname, unsigned int color_index,
72
Pixel *image_pixel, Pixel *mask_pixel,
73
unsigned int *mask_pixel_index,
74
Pixel *alloc_pixels, unsigned int *nalloc_pixels,
75
Pixel *used_pixels, unsigned int *nused_pixels,
76
XpmAttributes *attributes, XColor *cols, int ncols,
77
XpmAllocColorFunc allocColor, void *closure));
79
LFUNC(CreateXImage, int, (Display *display, Visual *visual,
80
unsigned int depth, int format, unsigned int width,
81
unsigned int height, XImage **image_return));
83
LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes,
84
XpmColor *colors, unsigned int ncolors,
85
Pixel *image_pixels, Pixel *mask_pixels,
86
unsigned int *mask_pixel_index,
87
Pixel *alloc_pixels, unsigned int *nalloc_pixels,
88
Pixel *used_pixels, unsigned int *nused_pixels));
91
LFUNC(ParseAndPutPixels, int, (xpmData *data, unsigned int width,
92
unsigned int height, unsigned int ncolors,
93
unsigned int cpp, XpmColor *colorTable,
94
xpmHashTable *hashtable,
95
XImage *image, Pixel *image_pixels,
96
XImage *mask, Pixel *mask_pixels));
98
LFUNC(ParseAndPutPixels, int, (Display *dc, xpmData *data, unsigned int width,
99
unsigned int height, unsigned int ncolors,
100
unsigned int cpp, XpmColor *colorTable,
101
xpmHashTable *hashtable,
102
XImage *image, Pixel *image_pixels,
103
XImage *mask, Pixel *mask_pixels));
107
/* XImage pixel routines */
108
LFUNC(PutImagePixels, void, (XImage *image, unsigned int width,
109
unsigned int height, unsigned int *pixelindex,
112
LFUNC(PutImagePixels32, void, (XImage *image, unsigned int width,
113
unsigned int height, unsigned int *pixelindex,
116
LFUNC(PutImagePixels16, void, (XImage *image, unsigned int width,
117
unsigned int height, unsigned int *pixelindex,
120
LFUNC(PutImagePixels8, void, (XImage *image, unsigned int width,
121
unsigned int height, unsigned int *pixelindex,
124
LFUNC(PutImagePixels1, void, (XImage *image, unsigned int width,
125
unsigned int height, unsigned int *pixelindex,
128
LFUNC(PutPixel1, int, (XImage *ximage, int x, int y, unsigned long pixel));
129
LFUNC(PutPixel, int, (XImage *ximage, int x, int y, unsigned long pixel));
130
LFUNC(PutPixel32, int, (XImage *ximage, int x, int y, unsigned long pixel));
131
LFUNC(PutPixel32MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
132
LFUNC(PutPixel32LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
133
LFUNC(PutPixel16MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
134
LFUNC(PutPixel16LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
135
LFUNC(PutPixel8, int, (XImage *ximage, int x, int y, unsigned long pixel));
136
LFUNC(PutPixel1MSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
137
LFUNC(PutPixel1LSB, int, (XImage *ximage, int x, int y, unsigned long pixel));
139
#else /* ndef FOR_MSW */
140
/* FOR_MSW pixel routine */
141
LFUNC(MSWPutImagePixels, void, (Display *dc, XImage *image,
142
unsigned int width, unsigned int height,
143
unsigned int *pixelindex, Pixel *pixels));
144
#endif /* ndef FOR_MSW */
146
#ifdef NEED_STRCASECMP
147
FUNC(xpmstrcasecmp, int, (char *s1, char *s2));
150
* in case strcasecmp is not provided by the system here is one
151
* which does the trick
154
xpmstrcasecmp(s1, s2)
155
register char *s1, *s2;
167
return (int) (*s1 - *s2);
173
* return the default color key related to the given visual
176
xpmVisualType(visual)
180
switch (visual->class) {
183
switch (visual->map_entries) {
195
/* there should be a similar switch for MSW */
210
CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b;
212
/* cast to int as qsort requires */
213
return (int) (x->closeness - y->closeness);
217
/* default AllocColor function:
218
* call XParseColor if colorname is given, return negative value if failure
219
* call XAllocColor and return 0 if failure, positive otherwise
222
AllocColor(display, colormap, colorname, xcolor, closure)
227
void *closure; /* not used */
231
if (!XParseColor(display, colormap, colorname, xcolor))
233
status = XAllocColor(display, colormap, xcolor);
234
return status != 0 ? 1 : 0;
240
* set a close color in case the exact one can't be set
241
* return 0 if success, 1 otherwise.
245
SetCloseColor(display, colormap, visual, col, image_pixel, mask_pixel,
246
alloc_pixels, nalloc_pixels, attributes, cols, ncols,
252
Pixel *image_pixel, *mask_pixel;
254
unsigned int *nalloc_pixels;
255
XpmAttributes *attributes;
258
XpmAllocColorFunc allocColor;
263
* Allocation failed, so try close colors. To get here the visual must
264
* be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor?
265
* What about sharing systems like QDSS?). Beware: we have to treat
266
* DirectColor differently.
270
long int red_closeness, green_closeness, blue_closeness;
274
if (attributes && (attributes->valuemask & XpmCloseness))
275
red_closeness = green_closeness = blue_closeness =
276
attributes->closeness;
278
red_closeness = attributes->red_closeness;
279
green_closeness = attributes->green_closeness;
280
blue_closeness = attributes->blue_closeness;
282
if (attributes && (attributes->valuemask & XpmAllocCloseColors))
283
alloc_color = attributes->alloc_close_colors;
288
* We sort the colormap by closeness and try to allocate the color
289
* closest to the target. If the allocation of this close color fails,
290
* which almost never happens, then one of two scenarios is possible.
291
* Either the colormap must have changed (since the last close color
292
* allocation or possibly while we were sorting the colormap), or the
293
* color is allocated as Read/Write by some other client. (Note: X
294
* _should_ allow clients to check if a particular color is Read/Write,
295
* but it doesn't! :-( ). We cannot determine which of these scenarios
296
* occurred, so we try the next closest color, and so on, until no more
297
* colors are within closeness of the target. If we knew that the
298
* colormap had changed, we could skip this sequence.
300
* If _none_ of the colors within closeness of the target can be allocated,
301
* then we can finally be pretty sure that the colormap has actually
302
* changed. In this case we try to allocate the original color (again),
303
* then try the closecolor stuff (again)...
305
* In theory it would be possible for an infinite loop to occur if another
306
* process kept changing the colormap every time we sorted it, so we set
307
* a maximum on the number of iterations. After this many tries, we use
308
* XGrabServer() to ensure that the colormap remains unchanged.
310
* This approach gives particularly bad worst case performance - as many as
311
* <MaximumIterations> colormap reads and sorts may be needed, and as
312
* many as <MaximumIterations> * <ColormapSize> attempted allocations
313
* may fail. On an 8-bit system, this means as many as 3 colormap reads,
314
* 3 sorts and 768 failed allocations per execution of this code!
315
* Luckily, my experiments show that in general use in a typical 8-bit
316
* color environment only about 1 in every 10000 allocations fails to
317
* succeed in the fastest possible time. So virtually every time what
318
* actually happens is a single sort followed by a successful allocate.
319
* The very first allocation also costs a colormap read, but no further
320
* reads are usually necessary.
323
#define ITERATIONS 2 /* more than one is almost never
326
for (n = 0; n <= ITERATIONS; ++n) {
327
CloseColor *closenesses =
328
(CloseColor *) XpmCalloc(ncols, sizeof(CloseColor));
331
for (i = 0; i < ncols; ++i) { /* build & sort closenesses table */
332
#define COLOR_FACTOR 3
333
#define BRIGHTNESS_FACTOR 1
335
closenesses[i].cols_index = i;
336
closenesses[i].closeness =
337
COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red)
338
+ abs((long) col->green - (long) cols[i].green)
339
+ abs((long) col->blue - (long) cols[i].blue))
340
+ BRIGHTNESS_FACTOR * abs(((long) col->red +
343
- ((long) cols[i].red +
344
(long) cols[i].green +
345
(long) cols[i].blue));
347
qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp);
350
c = closenesses[i].cols_index;
351
while ((long) cols[c].red >= (long) col->red - red_closeness &&
352
(long) cols[c].red <= (long) col->red + red_closeness &&
353
(long) cols[c].green >= (long) col->green - green_closeness &&
354
(long) cols[c].green <= (long) col->green + green_closeness &&
355
(long) cols[c].blue >= (long) col->blue - blue_closeness &&
356
(long) cols[c].blue <= (long) col->blue + blue_closeness) {
358
if ((*allocColor)(display, colormap, NULL, &cols[c], closure)){
360
XUngrabServer(display);
361
XpmFree(closenesses);
362
*image_pixel = cols[c].pixel;
364
alloc_pixels[(*nalloc_pixels)++] = cols[c].pixel;
370
c = closenesses[i].cols_index;
374
XUngrabServer(display);
375
XpmFree(closenesses);
376
*image_pixel = cols[c].pixel;
382
/* Couldn't allocate _any_ of the close colors! */
385
XUngrabServer(display);
386
XpmFree(closenesses);
388
if (i == 0 || i == ncols) /* no color close enough or cannot */
389
return (1); /* alloc any color (full of r/w's) */
391
if ((*allocColor)(display, colormap, NULL, col, closure)) {
392
*image_pixel = col->pixel;
394
alloc_pixels[(*nalloc_pixels)++] = col->pixel;
396
} else { /* colormap has probably changed, so
398
if (n == ITERATIONS - 1)
399
XGrabServer(display);
402
if (visual->class == DirectColor) {
406
XQueryColors(display, colormap, cols, ncols);
412
#define USE_CLOSECOLOR attributes && \
413
(((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \
414
|| ((attributes->valuemask & XpmRGBCloseness) && \
415
(attributes->red_closeness != 0 \
416
|| attributes->green_closeness != 0 \
417
|| attributes->blue_closeness != 0)))
421
/* nothing to do here, the window system does it */
425
* set the color pixel related to the given colorname,
426
* return 0 if success, 1 otherwise.
430
SetColor(display, colormap, visual, colorname, color_index,
431
image_pixel, mask_pixel, mask_pixel_index,
432
alloc_pixels, nalloc_pixels, used_pixels, nused_pixels,
433
attributes, cols, ncols, allocColor, closure)
438
unsigned int color_index;
439
Pixel *image_pixel, *mask_pixel;
440
unsigned int *mask_pixel_index;
442
unsigned int *nalloc_pixels;
444
unsigned int *nused_pixels;
445
XpmAttributes *attributes;
448
XpmAllocColorFunc allocColor;
454
if (xpmstrcasecmp(colorname, TRANSPARENT_COLOR)) {
455
status = (*allocColor)(display, colormap, colorname, &xcolor, closure);
456
if (status < 0) /* parse color failed */
462
return (SetCloseColor(display, colormap, visual, &xcolor,
463
image_pixel, mask_pixel,
464
alloc_pixels, nalloc_pixels,
465
attributes, cols, ncols,
466
allocColor, closure));
468
#endif /* ndef FOR_MSW */
471
alloc_pixels[(*nalloc_pixels)++] = xcolor.pixel;
472
*image_pixel = xcolor.pixel;
474
used_pixels[(*nused_pixels)++] = xcolor.pixel;
478
/* store the color table index */
479
*mask_pixel_index = color_index;
486
CreateColors(display, attributes, colors, ncolors, image_pixels, mask_pixels,
487
mask_pixel_index, alloc_pixels, nalloc_pixels,
488
used_pixels, nused_pixels)
490
XpmAttributes *attributes;
492
unsigned int ncolors;
495
unsigned int *mask_pixel_index;
497
unsigned int *nalloc_pixels;
499
unsigned int *nused_pixels;
501
/* variables stored in the XpmAttributes structure */
504
XpmColorSymbol *colorsymbols = NULL;
505
unsigned int numsymbols;
506
XpmAllocColorFunc allocColor;
510
unsigned int color, key;
512
XpmColorSymbol *symbol = NULL;
514
int ErrorStatus = XpmSuccess;
519
unsigned int ncols = 0;
522
* retrieve information from the XpmAttributes
524
if (attributes && attributes->valuemask & XpmColorSymbols) {
525
colorsymbols = attributes->colorsymbols;
526
numsymbols = attributes->numsymbols;
530
if (attributes && attributes->valuemask & XpmVisual)
531
visual = attributes->visual;
533
visual = XDefaultVisual(display, XDefaultScreen(display));
535
if (attributes && (attributes->valuemask & XpmColormap))
536
colormap = attributes->colormap;
538
colormap = XDefaultColormap(display, XDefaultScreen(display));
540
if (attributes && (attributes->valuemask & XpmColorKey))
541
key = attributes->color_key;
543
key = xpmVisualType(visual);
545
if (attributes && (attributes->valuemask & XpmAllocColor))
546
allocColor = attributes->alloc_color;
548
allocColor = AllocColor;
549
if (attributes && (attributes->valuemask & XpmColorClosure))
550
closure = attributes->color_closure;
555
if (USE_CLOSECOLOR) {
556
/* originally from SetCloseColor */
558
if (visual->class == DirectColor) {
561
* TODO: Implement close colors for DirectColor visuals. This is
562
* difficult situation. Chances are that we will never get here,
563
* because any machine that supports DirectColor will probably
564
* also support TrueColor (and probably PseudoColor). Also,
565
* DirectColor colormaps can be very large, so looking for close
566
* colors may be too slow.
572
ncols = visual->map_entries;
573
cols = (XColor *) XpmCalloc(ncols, sizeof(XColor));
574
for (i = 0; i < ncols; ++i)
576
XQueryColors(display, colormap, cols, ncols);
581
#endif /* ndef FOR_MSW */
599
for (color = 0; color < ncolors; color++, colors++,
600
image_pixels++, mask_pixels++) {
602
pixel_defined = False;
603
defaults = (char **) colors;
606
* look for a defined symbol
613
for (n = 0, symbol = colorsymbols; n < numsymbols; n++, symbol++) {
614
if (symbol->name && s && !strcmp(symbol->name, s))
617
if (!symbol->name && symbol->value) { /* override value */
618
int def_index = default_index;
620
while (defaults[def_index] == NULL) /* find defined
623
if (def_index < 2) {/* nothing towards mono, so try
625
def_index = default_index + 1;
626
while (def_index <= 5 && defaults[def_index] == NULL)
629
if (def_index >= 2 && defaults[def_index] != NULL &&
630
!xpmstrcasecmp(symbol->value, defaults[def_index]))
634
if (n != numsymbols) {
635
if (symbol->name && symbol->value)
636
colorname = symbol->value;
638
pixel_defined = True;
641
if (!pixel_defined) { /* pixel not given as symbol value */
645
if (colorname) { /* colorname given as symbol value */
646
if (!SetColor(display, colormap, visual, colorname, color,
647
image_pixels, mask_pixels, mask_pixel_index,
648
alloc_pixels, nalloc_pixels, used_pixels,
649
nused_pixels, attributes, cols, ncols,
650
allocColor, closure))
651
pixel_defined = True;
653
ErrorStatus = XpmColorError;
656
while (!pixel_defined && k > 1) {
658
if (!SetColor(display, colormap, visual, defaults[k],
659
color, image_pixels, mask_pixels,
660
mask_pixel_index, alloc_pixels,
661
nalloc_pixels, used_pixels, nused_pixels,
662
attributes, cols, ncols,
663
allocColor, closure)) {
664
pixel_defined = True;
667
ErrorStatus = XpmColorError;
672
while (!pixel_defined && k < NKEYS + 1) {
674
if (!SetColor(display, colormap, visual, defaults[k],
675
color, image_pixels, mask_pixels,
676
mask_pixel_index, alloc_pixels,
677
nalloc_pixels, used_pixels, nused_pixels,
678
attributes, cols, ncols,
679
allocColor, closure)) {
680
pixel_defined = True;
683
ErrorStatus = XpmColorError;
687
if (!pixel_defined) {
690
return (XpmColorFailed);
693
/* simply use the given pixel */
694
*image_pixels = symbol->pixel;
695
/* the following makes the mask to be built even if none
696
is given a particular pixel */
698
&& !xpmstrcasecmp(symbol->value, TRANSPARENT_COLOR)) {
700
*mask_pixel_index = color;
703
used_pixels[(*nused_pixels)++] = *image_pixels;
708
return (ErrorStatus);
712
/* default FreeColors function, simply call XFreeColors */
714
FreeColors(display, colormap, pixels, n, closure)
719
void *closure; /* not used */
721
return XFreeColors(display, colormap, pixels, n, 0);
725
/* function call in case of error, frees only locally allocated variables */
727
#define RETURN(status) \
729
if (ximage) XDestroyImage(ximage); \
730
if (shapeimage) XDestroyImage(shapeimage); \
731
if (image_pixels) XpmFree(image_pixels); \
732
if (mask_pixels) XpmFree(mask_pixels); \
734
(*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); \
735
if (alloc_pixels) XpmFree(alloc_pixels); \
736
if (used_pixels) XpmFree(used_pixels); \
741
XpmCreateImageFromXpmImage(display, image,
742
image_return, shapeimage_return, attributes)
745
XImage **image_return;
746
XImage **shapeimage_return;
747
XpmAttributes *attributes;
749
/* variables stored in the XpmAttributes structure */
754
XpmFreeColorsFunc freeColors;
757
/* variables to return */
758
XImage *ximage = NULL;
759
XImage *shapeimage = NULL;
760
unsigned int mask_pixel_index = XpmUndefPixel;
763
/* calculation variables */
764
Pixel *image_pixels = NULL;
765
Pixel *mask_pixels = NULL;
766
Pixel *alloc_pixels = NULL;
767
Pixel *used_pixels = NULL;
768
unsigned int nalloc_pixels = 0;
769
unsigned int nused_pixels = 0;
771
/* initialize return values */
773
*image_return = NULL;
774
if (shapeimage_return)
775
*shapeimage_return = NULL;
777
/* retrieve information from the XpmAttributes */
778
if (attributes && (attributes->valuemask & XpmVisual))
779
visual = attributes->visual;
781
visual = XDefaultVisual(display, XDefaultScreen(display));
783
if (attributes && (attributes->valuemask & XpmColormap))
784
colormap = attributes->colormap;
786
colormap = XDefaultColormap(display, XDefaultScreen(display));
788
if (attributes && (attributes->valuemask & XpmDepth))
789
depth = attributes->depth;
791
depth = XDefaultDepth(display, XDefaultScreen(display));
793
if (attributes && (attributes->valuemask & XpmBitmapFormat))
794
bitmap_format = attributes->bitmap_format;
796
bitmap_format = ZPixmap;
798
if (attributes && (attributes->valuemask & XpmFreeColors))
799
freeColors = attributes->free_colors;
801
freeColors = FreeColors;
802
if (attributes && (attributes->valuemask & XpmColorClosure))
803
closure = attributes->color_closure;
807
ErrorStatus = XpmSuccess;
809
if (image->ncolors >= UINT_MAX / sizeof(Pixel))
810
return (XpmNoMemory);
812
/* malloc pixels index tables */
813
image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
815
return (XpmNoMemory);
817
mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
821
/* maximum of allocated pixels will be the number of colors */
822
alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
826
/* maximum of allocated pixels will be the number of colors */
827
used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors);
831
/* get pixel colors, store them in index tables */
832
ErrorStatus = CreateColors(display, attributes, image->colorTable,
833
image->ncolors, image_pixels, mask_pixels,
834
&mask_pixel_index, alloc_pixels, &nalloc_pixels,
835
used_pixels, &nused_pixels);
837
if (ErrorStatus != XpmSuccess
838
&& (ErrorStatus < 0 || (attributes
839
&& (attributes->valuemask & XpmExactColors)
840
&& attributes->exactColors)))
843
/* create the ximage */
845
ErrorStatus = CreateXImage(display, visual, depth,
846
(depth == 1 ? bitmap_format : ZPixmap),
847
image->width, image->height, &ximage);
848
if (ErrorStatus != XpmSuccess)
854
* set the ximage data using optimized functions for ZPixmap
857
if (ximage->bits_per_pixel == 8)
858
PutImagePixels8(ximage, image->width, image->height,
859
image->data, image_pixels);
860
else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
861
(ximage->byte_order == ximage->bitmap_bit_order))
862
PutImagePixels1(ximage, image->width, image->height,
863
image->data, image_pixels);
864
else if (ximage->bits_per_pixel == 16)
865
PutImagePixels16(ximage, image->width, image->height,
866
image->data, image_pixels);
867
else if (ximage->bits_per_pixel == 32)
868
PutImagePixels32(ximage, image->width, image->height,
869
image->data, image_pixels);
871
PutImagePixels(ximage, image->width, image->height,
872
image->data, image_pixels);
874
MSWPutImagePixels(display, ximage, image->width, image->height,
875
image->data, image_pixels);
878
/* create the shape mask image */
879
if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
880
ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
881
image->width, image->height, &shapeimage);
882
if (ErrorStatus != XpmSuccess)
886
PutImagePixels1(shapeimage, image->width, image->height,
887
image->data, mask_pixels);
889
MSWPutImagePixels(display, shapeimage, image->width, image->height,
890
image->data, mask_pixels);
894
XpmFree(image_pixels);
895
XpmFree(mask_pixels);
897
/* if requested return used pixels in the XpmAttributes structure */
898
if (attributes && (attributes->valuemask & XpmReturnPixels ||
899
/* 3.2 backward compatibility code */
900
attributes->valuemask & XpmReturnInfos)) {
902
attributes->pixels = used_pixels;
903
attributes->npixels = nused_pixels;
904
attributes->mask_pixel = mask_pixel_index;
906
XpmFree(used_pixels);
908
/* if requested return alloc'ed pixels in the XpmAttributes structure */
909
if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
910
attributes->alloc_pixels = alloc_pixels;
911
attributes->nalloc_pixels = nalloc_pixels;
913
XpmFree(alloc_pixels);
915
/* return created images */
917
*image_return = ximage;
918
if (shapeimage_return)
919
*shapeimage_return = shapeimage;
921
return (ErrorStatus);
926
* Create an XImage with its data
929
CreateXImage(display, visual, depth, format, width, height, image_return)
936
XImage **image_return;
940
/* first get bitmap_pad */
948
/* then create the XImage with data = NULL and bytes_per_line = 0 */
949
*image_return = XCreateImage(display, visual, depth, format, 0, 0,
950
width, height, bitmap_pad, 0);
952
return (XpmNoMemory);
955
if (height != 0 && (*image_return)->bytes_per_line >= INT_MAX / height) {
956
XDestroyImage(*image_return);
957
return (XpmNoMemory);
959
if((*image_return)->bytes_per_line == 0 || height == 0)
961
/* now that bytes_per_line must have been set properly alloc data */
962
(*image_return)->data =
963
(char *) XpmMalloc((*image_return)->bytes_per_line * height);
965
if (!(*image_return)->data) {
966
XDestroyImage(*image_return);
967
*image_return = NULL;
968
return (XpmNoMemory);
971
/* under FOR_MSW XCreateImage has done it all */
978
* The functions below are written from X11R5 MIT's code (XImUtil.c)
980
* The idea is to have faster functions than the standard XPutPixel function
981
* to build the image data. Indeed we can speed up things by suppressing tests
982
* performed for each pixel. We do the same tests but at the image level.
983
* We also assume that we use only ZPixmap images with null offsets.
986
LFUNC(_putbits, void, (register char *src, int dstoffset,
987
register int numbits, register char *dst));
989
LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register unsigned int nb));
991
static unsigned char Const _reverse_byte[0x100] = {
992
0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0,
993
0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0,
994
0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8,
995
0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8,
996
0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4,
997
0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4,
998
0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec,
999
0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc,
1000
0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2,
1001
0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2,
1002
0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea,
1003
0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa,
1004
0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6,
1005
0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6,
1006
0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee,
1007
0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe,
1008
0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1,
1009
0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1,
1010
0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9,
1011
0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9,
1012
0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5,
1013
0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5,
1014
0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed,
1015
0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd,
1016
0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3,
1017
0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3,
1018
0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb,
1019
0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb,
1020
0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7,
1021
0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7,
1022
0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef,
1023
0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff
1027
_XReverse_Bytes(bpt, nb)
1028
register unsigned char *bpt;
1029
register unsigned int nb;
1032
*bpt = _reverse_byte[*bpt];
1034
} while (--nb > 0); /* is nb user-controled? */
1040
xpm_xynormalizeimagebits(bp, img)
1041
register unsigned char *bp;
1042
register XImage *img;
1044
register unsigned char c;
1046
if (img->byte_order != img->bitmap_bit_order) {
1047
switch (img->bitmap_unit) {
1060
*(bp + 2) = *(bp + 1);
1065
if (img->bitmap_bit_order == MSBFirst)
1066
_XReverse_Bytes(bp, img->bitmap_unit >> 3);
1070
xpm_znormalizeimagebits(bp, img)
1071
register unsigned char *bp;
1072
register XImage *img;
1074
register unsigned char c;
1076
switch (img->bits_per_pixel) {
1079
_XReverse_Bytes(bp, 1);
1083
*bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF);
1103
*(bp + 2) = *(bp + 1);
1109
static unsigned char Const _lomask[0x09] = {
1110
0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff};
1111
static unsigned char Const _himask[0x09] = {
1112
0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00};
1115
_putbits(src, dstoffset, numbits, dst)
1116
register char *src; /* address of source bit string */
1117
int dstoffset; /* bit offset into destination;
1119
register int numbits; /* number of bits to copy to
1121
register char *dst; /* address of destination bit string */
1123
register unsigned char chlo, chhi;
1126
dst = dst + (dstoffset >> 3);
1127
dstoffset = dstoffset & 7;
1128
hibits = 8 - dstoffset;
1129
chlo = *dst & _lomask[dstoffset];
1131
chhi = (*src << dstoffset) & _himask[dstoffset];
1132
if (numbits <= hibits) {
1133
chhi = chhi & _lomask[dstoffset + numbits];
1134
*dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi;
1139
numbits = numbits - hibits;
1140
chlo = (unsigned char) (*src & _himask[hibits]) >> hibits;
1142
if (numbits <= dstoffset) {
1143
chlo = chlo & _lomask[numbits];
1144
*dst = (*dst & _himask[numbits]) | chlo;
1147
numbits = numbits - dstoffset;
1152
* Default method to write pixels into a Z image data structure.
1153
* The algorithm used is:
1155
* copy the destination bitmap_unit or Zpixel to temp
1156
* normalize temp if needed
1157
* copy the pixel bits into the temp
1158
* renormalize temp if needed
1159
* copy the temp back into the destination image data
1163
PutImagePixels(image, width, height, pixelindex, pixels)
1166
unsigned int height;
1167
unsigned int *pixelindex;
1172
register unsigned int *iptr;
1173
register unsigned int x, y;
1174
register char *data;
1176
int nbytes, depth, ibu, ibpp, i;
1180
depth = image->depth;
1182
ibu = image->bitmap_unit;
1183
for (y = 0; y < height; y++) /* how can we trust height */
1184
for (x = 0; x < width; x++, iptr++) { /* how can we trust width */
1185
pixel = pixels[*iptr];
1186
for (i = 0, px = pixel; i < sizeof(unsigned long);
1188
((unsigned char *) &pixel)[i] = px;
1189
src = &data[XYINDEX(x, y, image)];
1193
for (i = nbytes; --i >= 0;)
1195
XYNORMALIZE(&px, image);
1196
_putbits((char *) &pixel, (x % ibu), 1, (char *) &px);
1197
XYNORMALIZE(&px, image);
1199
dst = &data[XYINDEX(x, y, image)];
1200
for (i = nbytes; --i >= 0;)
1204
ibpp = image->bits_per_pixel;
1205
for (y = 0; y < height; y++)
1206
for (x = 0; x < width; x++, iptr++) {
1207
pixel = pixels[*iptr];
1210
for (i = 0, px = pixel; i < sizeof(unsigned long); i++,
1212
((unsigned char *) &pixel)[i] = px;
1213
src = &data[ZINDEX(x, y, image)];
1216
nbytes = (ibpp + 7) >> 3;
1217
for (i = nbytes; --i >= 0;)
1219
ZNORMALIZE(&px, image);
1220
_putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1221
ZNORMALIZE(&px, image);
1223
dst = &data[ZINDEX(x, y, image)];
1224
for (i = nbytes; --i >= 0;)
1231
* write pixels into a 32-bits Z image data structure
1234
#if !defined(WORD64) && !defined(LONG64)
1235
/* this item is static but deterministic so let it slide; doesn't
1236
* hurt re-entrancy of this library. Note if it is actually const then would
1237
* be OK under rules of ANSI-C but probably not C++ which may not
1238
* want to allocate space for it.
1240
static unsigned long byteorderpixel = MSBFirst << 24;
1245
WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original
1246
3.2e code - by default you get the speeded-up version.
1250
PutImagePixels32(image, width, height, pixelindex, pixels)
1253
unsigned int height;
1254
unsigned int *pixelindex;
1257
unsigned char *data;
1262
#ifdef WITHOUT_SPEEDUPS
1265
unsigned char *addr;
1267
data = (unsigned char *) image->data;
1269
#if !defined(WORD64) && !defined(LONG64)
1270
if (*((char *) &byteorderpixel) == image->byte_order) {
1271
for (y = 0; y < height; y++)
1272
for (x = 0; x < width; x++, iptr++) {
1273
addr = &data[ZINDEX32(x, y, image)];
1274
*((unsigned long *) addr) = pixels[*iptr];
1278
if (image->byte_order == MSBFirst)
1279
for (y = 0; y < height; y++)
1280
for (x = 0; x < width; x++, iptr++) {
1281
addr = &data[ZINDEX32(x, y, image)];
1282
pixel = pixels[*iptr];
1283
addr[0] = pixel >> 24;
1284
addr[1] = pixel >> 16;
1285
addr[2] = pixel >> 8;
1289
for (y = 0; y < height; y++)
1290
for (x = 0; x < width; x++, iptr++) {
1291
addr = &data[ZINDEX32(x, y, image)];
1292
pixel = pixels[*iptr];
1294
addr[1] = pixel >> 8;
1295
addr[2] = pixel >> 16;
1296
addr[3] = pixel >> 24;
1299
#else /* WITHOUT_SPEEDUPS */
1301
unsigned int bpl = image->bytes_per_line;
1302
unsigned char *data_ptr, *max_data;
1304
data = (unsigned char *) image->data;
1306
#if !defined(WORD64) && !defined(LONG64)
1307
if (*((char *) &byteorderpixel) == image->byte_order) {
1308
for (y = 0; y < height; y++) {
1310
max_data = data_ptr + (width << 2);
1312
while (data_ptr < max_data) {
1313
*((unsigned long *) data_ptr) = pixels[*(iptr++)];
1314
data_ptr += (1 << 2);
1320
if (image->byte_order == MSBFirst)
1321
for (y = 0; y < height; y++) {
1323
max_data = data_ptr + (width << 2);
1325
while (data_ptr < max_data) {
1326
pixel = pixels[*(iptr++)];
1328
*data_ptr++ = pixel >> 24;
1329
*data_ptr++ = pixel >> 16;
1330
*data_ptr++ = pixel >> 8;
1331
*data_ptr++ = pixel;
1337
for (y = 0; y < height; y++) {
1339
max_data = data_ptr + (width << 2);
1341
while (data_ptr < max_data) {
1342
pixel = pixels[*(iptr++)];
1344
*data_ptr++ = pixel;
1345
*data_ptr++ = pixel >> 8;
1346
*data_ptr++ = pixel >> 16;
1347
*data_ptr++ = pixel >> 24;
1352
#endif /* WITHOUT_SPEEDUPS */
1356
* write pixels into a 16-bits Z image data structure
1360
PutImagePixels16(image, width, height, pixelindex, pixels)
1363
unsigned int height;
1364
unsigned int *pixelindex;
1367
unsigned char *data;
1371
#ifdef WITHOUT_SPEEDUPS
1374
unsigned char *addr;
1376
data = (unsigned char *) image->data;
1378
if (image->byte_order == MSBFirst)
1379
for (y = 0; y < height; y++)
1380
for (x = 0; x < width; x++, iptr++) {
1381
addr = &data[ZINDEX16(x, y, image)];
1382
addr[0] = pixels[*iptr] >> 8;
1383
addr[1] = pixels[*iptr];
1386
for (y = 0; y < height; y++)
1387
for (x = 0; x < width; x++, iptr++) {
1388
addr = &data[ZINDEX16(x, y, image)];
1389
addr[0] = pixels[*iptr];
1390
addr[1] = pixels[*iptr] >> 8;
1393
#else /* WITHOUT_SPEEDUPS */
1397
unsigned int bpl = image->bytes_per_line;
1398
unsigned char *data_ptr, *max_data;
1400
data = (unsigned char *) image->data;
1402
if (image->byte_order == MSBFirst)
1403
for (y = 0; y < height; y++) {
1405
max_data = data_ptr + (width << 1);
1407
while (data_ptr < max_data) {
1408
pixel = pixels[*(iptr++)];
1410
data_ptr[0] = pixel >> 8;
1411
data_ptr[1] = pixel;
1413
data_ptr += (1 << 1);
1418
for (y = 0; y < height; y++) {
1420
max_data = data_ptr + (width << 1);
1422
while (data_ptr < max_data) {
1423
pixel = pixels[*(iptr++)];
1425
data_ptr[0] = pixel;
1426
data_ptr[1] = pixel >> 8;
1428
data_ptr += (1 << 1);
1433
#endif /* WITHOUT_SPEEDUPS */
1437
* write pixels into a 8-bits Z image data structure
1441
PutImagePixels8(image, width, height, pixelindex, pixels)
1444
unsigned int height;
1445
unsigned int *pixelindex;
1452
#ifdef WITHOUT_SPEEDUPS
1458
for (y = 0; y < height; y++)
1459
for (x = 0; x < width; x++, iptr++)
1460
data[ZINDEX8(x, y, image)] = pixels[*iptr];
1462
#else /* WITHOUT_SPEEDUPS */
1464
unsigned int bpl = image->bytes_per_line;
1465
char *data_ptr, *max_data;
1470
for (y = 0; y < height; y++) {
1472
max_data = data_ptr + width;
1474
while (data_ptr < max_data)
1475
*(data_ptr++) = pixels[*(iptr++)];
1480
#endif /* WITHOUT_SPEEDUPS */
1484
* write pixels into a 1-bit depth image data structure and **offset null**
1488
PutImagePixels1(image, width, height, pixelindex, pixels)
1491
unsigned int height;
1492
unsigned int *pixelindex;
1495
if (image->byte_order != image->bitmap_bit_order)
1496
PutImagePixels(image, width, height, pixelindex, pixels);
1502
#ifdef WITHOUT_SPEEDUPS
1508
if (image->bitmap_bit_order == MSBFirst)
1509
for (y = 0; y < height; y++)
1510
for (x = 0; x < width; x++, iptr++) {
1511
if (pixels[*iptr] & 1)
1512
data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7);
1514
data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7));
1517
for (y = 0; y < height; y++)
1518
for (x = 0; x < width; x++, iptr++) {
1519
if (pixels[*iptr] & 1)
1520
data[ZINDEX1(x, y, image)] |= 1 << (x & 7);
1522
data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7));
1525
#else /* WITHOUT_SPEEDUPS */
1528
char *data_ptr, *max_data;
1529
int bpl = image->bytes_per_line;
1538
if (image->bitmap_bit_order == MSBFirst)
1539
for (y = 0; y < height; y++) {
1541
max_data = data_ptr + width;
1542
while (data_ptr < max_data) {
1545
value = (value << 1) | (pixels[*(iptr++)] & 1);
1546
value = (value << 1) | (pixels[*(iptr++)] & 1);
1547
value = (value << 1) | (pixels[*(iptr++)] & 1);
1548
value = (value << 1) | (pixels[*(iptr++)] & 1);
1549
value = (value << 1) | (pixels[*(iptr++)] & 1);
1550
value = (value << 1) | (pixels[*(iptr++)] & 1);
1551
value = (value << 1) | (pixels[*(iptr++)] & 1);
1552
value = (value << 1) | (pixels[*(iptr++)] & 1);
1554
*(data_ptr++) = value;
1558
for (count = 0; count < diff; count++) {
1559
if (pixels[*(iptr++)] & 1)
1560
value |= (0x80 >> count);
1562
*(data_ptr) = value;
1567
for (y = 0; y < height; y++) {
1569
max_data = data_ptr + width;
1570
while (data_ptr < max_data) {
1574
value = (value << 1) | (pixels[*(--iptr)] & 1);
1575
value = (value << 1) | (pixels[*(--iptr)] & 1);
1576
value = (value << 1) | (pixels[*(--iptr)] & 1);
1577
value = (value << 1) | (pixels[*(--iptr)] & 1);
1578
value = (value << 1) | (pixels[*(--iptr)] & 1);
1579
value = (value << 1) | (pixels[*(--iptr)] & 1);
1580
value = (value << 1) | (pixels[*(--iptr)] & 1);
1581
value = (value << 1) | (pixels[*(--iptr)] & 1);
1584
*(data_ptr++) = value;
1588
for (count = 0; count < diff; count++) {
1589
if (pixels[*(iptr++)] & 1)
1590
value |= (1 << count);
1592
*(data_ptr) = value;
1597
#endif /* WITHOUT_SPEEDUPS */
1602
XpmCreatePixmapFromXpmImage(display, d, image,
1603
pixmap_return, shapemask_return, attributes)
1607
Pixmap *pixmap_return;
1608
Pixmap *shapemask_return;
1609
XpmAttributes *attributes;
1611
XImage *ximage, *shapeimage;
1614
/* initialize return values */
1617
if (shapemask_return)
1618
*shapemask_return = 0;
1620
/* create the ximages */
1621
ErrorStatus = XpmCreateImageFromXpmImage(display, image,
1622
(pixmap_return ? &ximage : NULL),
1624
&shapeimage : NULL),
1626
if (ErrorStatus < 0)
1627
return (ErrorStatus);
1629
/* create the pixmaps and destroy images */
1630
if (pixmap_return && ximage) {
1631
xpmCreatePixmapFromImage(display, d, ximage, pixmap_return);
1632
XDestroyImage(ximage);
1634
if (shapemask_return && shapeimage) {
1635
xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return);
1636
XDestroyImage(shapeimage);
1638
return (ErrorStatus);
1641
#else /* FOR_MSW part follows */
1643
MSWPutImagePixels(dc, image, width, height, pixelindex, pixels)
1647
unsigned int height;
1648
unsigned int *pixelindex;
1651
unsigned int *data = pixelindex;
1654
SelectObject(*dc, image->bitmap);
1655
for (y = 0; y < height; y++) {
1656
for (x = 0; x < width; x++) {
1657
SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */
1662
#endif /* FOR_MSW */
1669
PutPixel1(ximage, x, y, pixel)
1670
register XImage *ximage;
1673
unsigned long pixel;
1678
register char *data;
1685
for (i=0, px=pixel; i<sizeof(unsigned long); i++, px>>=8)
1686
((unsigned char *)&pixel)[i] = px;
1687
src = &ximage->data[XYINDEX(x, y, ximage)];
1690
nbytes = ximage->bitmap_unit >> 3;
1691
for (i = nbytes; --i >= 0; ) *dst++ = *src++;
1692
XYNORMALIZE(&px, ximage);
1693
i = ((x + ximage->xoffset) % ximage->bitmap_unit);
1694
_putbits ((char *)&pixel, i, 1, (char *)&px);
1695
XYNORMALIZE(&px, ximage);
1697
dst = &ximage->data[XYINDEX(x, y, ximage)];
1698
for (i = nbytes; --i >= 0; )
1705
PutPixel(ximage, x, y, pixel)
1706
register XImage *ximage;
1709
unsigned long pixel;
1714
register char *data;
1716
unsigned int nbytes, ibpp;
1721
ibpp = ximage->bits_per_pixel;
1722
if (ximage->depth == 4)
1724
for (i = 0, px = pixel; i < sizeof(unsigned long); i++, px >>= 8)
1725
((unsigned char *) &pixel)[i] = px;
1726
src = &ximage->data[ZINDEX(x, y, ximage)];
1729
nbytes = (ibpp + 7) >> 3;
1730
for (i = nbytes; --i >= 0;)
1732
ZNORMALIZE(&px, ximage);
1733
_putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px);
1734
ZNORMALIZE(&px, ximage);
1736
dst = &ximage->data[ZINDEX(x, y, ximage)];
1737
for (i = nbytes; --i >= 0;)
1744
PutPixel32(ximage, x, y, pixel)
1745
register XImage *ximage;
1748
unsigned long pixel;
1750
unsigned char *addr;
1755
addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1756
*((unsigned long *)addr) = pixel;
1761
PutPixel32MSB(ximage, x, y, pixel)
1762
register XImage *ximage;
1765
unsigned long pixel;
1767
unsigned char *addr;
1772
addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1773
addr[0] = pixel >> 24;
1774
addr[1] = pixel >> 16;
1775
addr[2] = pixel >> 8;
1781
PutPixel32LSB(ximage, x, y, pixel)
1782
register XImage *ximage;
1785
unsigned long pixel;
1787
unsigned char *addr;
1792
addr = &((unsigned char *)ximage->data) [ZINDEX32(x, y, ximage)];
1793
addr[3] = pixel >> 24;
1794
addr[2] = pixel >> 16;
1795
addr[1] = pixel >> 8;
1801
PutPixel16MSB(ximage, x, y, pixel)
1802
register XImage *ximage;
1805
unsigned long pixel;
1807
unsigned char *addr;
1812
addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1813
addr[0] = pixel >> 8;
1819
PutPixel16LSB(ximage, x, y, pixel)
1820
register XImage *ximage;
1823
unsigned long pixel;
1825
unsigned char *addr;
1830
addr = &((unsigned char *)ximage->data) [ZINDEX16(x, y, ximage)];
1831
addr[1] = pixel >> 8;
1837
PutPixel8(ximage, x, y, pixel)
1838
register XImage *ximage;
1841
unsigned long pixel;
1846
ximage->data[ZINDEX8(x, y, ximage)] = pixel;
1851
PutPixel1MSB(ximage, x, y, pixel)
1852
register XImage *ximage;
1855
unsigned long pixel;
1861
ximage->data[ZINDEX1(x, y, ximage)] |= 0x80 >> (x & 7);
1863
ximage->data[ZINDEX1(x, y, ximage)] &= ~(0x80 >> (x & 7));
1868
PutPixel1LSB(ximage, x, y, pixel)
1869
register XImage *ximage;
1872
unsigned long pixel;
1878
ximage->data[ZINDEX1(x, y, ximage)] |= 1 << (x & 7);
1880
ximage->data[ZINDEX1(x, y, ximage)] &= ~(1 << (x & 7));
1884
#endif /* FOR_MSW */
1886
/* function call in case of error, frees only locally allocated variables */
1888
#define RETURN(status) \
1890
if (USE_HASHTABLE) xpmHashTableFree(&hashtable); \
1891
if (colorTable) xpmFreeColorTable(colorTable, ncolors); \
1892
if (hints_cmt) XpmFree(hints_cmt); \
1893
if (colors_cmt) XpmFree(colors_cmt); \
1894
if (pixels_cmt) XpmFree(pixels_cmt); \
1895
if (ximage) XDestroyImage(ximage); \
1896
if (shapeimage) XDestroyImage(shapeimage); \
1897
if (image_pixels) XpmFree(image_pixels); \
1898
if (mask_pixels) XpmFree(mask_pixels); \
1899
if (nalloc_pixels) \
1900
(*freeColors)(display, colormap, alloc_pixels, nalloc_pixels, NULL); \
1901
if (alloc_pixels) XpmFree(alloc_pixels); \
1902
if (used_pixels) XpmFree(used_pixels); \
1907
* This function parses an Xpm file or data and directly create an XImage
1910
xpmParseDataAndCreate(display, data, image_return, shapeimage_return,
1911
image, info, attributes)
1914
XImage **image_return;
1915
XImage **shapeimage_return;
1918
XpmAttributes *attributes;
1920
/* variables stored in the XpmAttributes structure */
1925
XpmFreeColorsFunc freeColors;
1928
/* variables to return */
1929
XImage *ximage = NULL;
1930
XImage *shapeimage = NULL;
1931
unsigned int mask_pixel_index = XpmUndefPixel;
1933
/* calculation variables */
1934
Pixel *image_pixels = NULL;
1935
Pixel *mask_pixels = NULL;
1936
Pixel *alloc_pixels = NULL;
1937
Pixel *used_pixels = NULL;
1938
unsigned int nalloc_pixels = 0;
1939
unsigned int nused_pixels = 0;
1940
unsigned int width, height, ncolors, cpp;
1941
unsigned int x_hotspot, y_hotspot, hotspot = 0, extensions = 0;
1942
XpmColor *colorTable = NULL;
1943
char *hints_cmt = NULL;
1944
char *colors_cmt = NULL;
1945
char *pixels_cmt = NULL;
1949
xpmHashTable hashtable;
1952
/* initialize return values */
1954
*image_return = NULL;
1955
if (shapeimage_return)
1956
*shapeimage_return = NULL;
1959
/* retrieve information from the XpmAttributes */
1960
if (attributes && (attributes->valuemask & XpmVisual))
1961
visual = attributes->visual;
1963
visual = XDefaultVisual(display, XDefaultScreen(display));
1965
if (attributes && (attributes->valuemask & XpmColormap))
1966
colormap = attributes->colormap;
1968
colormap = XDefaultColormap(display, XDefaultScreen(display));
1970
if (attributes && (attributes->valuemask & XpmDepth))
1971
depth = attributes->depth;
1973
depth = XDefaultDepth(display, XDefaultScreen(display));
1975
if (attributes && (attributes->valuemask & XpmBitmapFormat))
1976
bitmap_format = attributes->bitmap_format;
1978
bitmap_format = ZPixmap;
1980
if (attributes && (attributes->valuemask & XpmFreeColors))
1981
freeColors = attributes->free_colors;
1983
freeColors = FreeColors;
1984
if (attributes && (attributes->valuemask & XpmColorClosure))
1985
closure = attributes->color_closure;
1989
cmts = info && (info->valuemask & XpmReturnComments);
1994
ErrorStatus = xpmParseHeader(data);
1995
if (ErrorStatus != XpmSuccess)
1996
return (ErrorStatus);
2001
ErrorStatus = xpmParseValues(data, &width, &height, &ncolors, &cpp,
2002
&x_hotspot, &y_hotspot, &hotspot,
2004
if (ErrorStatus != XpmSuccess)
2005
return (ErrorStatus);
2008
* store the hints comment line
2011
xpmGetCmt(data, &hints_cmt);
2016
if (USE_HASHTABLE) {
2017
ErrorStatus = xpmHashTableInit(&hashtable);
2018
if (ErrorStatus != XpmSuccess)
2019
return (ErrorStatus);
2025
ErrorStatus = xpmParseColors(data, ncolors, cpp, &colorTable, &hashtable);
2026
if (ErrorStatus != XpmSuccess)
2027
RETURN(ErrorStatus);
2030
* store the colors comment line
2033
xpmGetCmt(data, &colors_cmt);
2035
/* malloc pixels index tables */
2036
if (ncolors >= UINT_MAX / sizeof(Pixel))
2037
RETURN (XpmNoMemory);
2039
image_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2041
RETURN(XpmNoMemory);
2043
mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2045
RETURN(XpmNoMemory);
2047
/* maximum of allocated pixels will be the number of colors */
2048
alloc_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2050
RETURN(XpmNoMemory);
2052
/* maximum of allocated pixels will be the number of colors */
2053
used_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * ncolors);
2055
RETURN(XpmNoMemory);
2057
/* get pixel colors, store them in index tables */
2058
ErrorStatus = CreateColors(display, attributes, colorTable, ncolors,
2059
image_pixels, mask_pixels, &mask_pixel_index,
2060
alloc_pixels, &nalloc_pixels, used_pixels,
2063
if (ErrorStatus != XpmSuccess
2064
&& (ErrorStatus < 0 || (attributes
2065
&& (attributes->valuemask & XpmExactColors)
2066
&& attributes->exactColors)))
2067
RETURN(ErrorStatus);
2069
/* now create the ximage */
2071
ErrorStatus = CreateXImage(display, visual, depth,
2072
(depth == 1 ? bitmap_format : ZPixmap),
2073
width, height, &ximage);
2074
if (ErrorStatus != XpmSuccess)
2075
RETURN(ErrorStatus);
2080
* set the XImage pointer function, to be used with XPutPixel,
2081
* to an internal optimized function
2084
if (ximage->bits_per_pixel == 8)
2085
ximage->f.put_pixel = PutPixel8;
2086
else if (((ximage->bits_per_pixel | ximage->depth) == 1) &&
2087
(ximage->byte_order == ximage->bitmap_bit_order))
2088
if (ximage->bitmap_bit_order == MSBFirst)
2089
ximage->f.put_pixel = PutPixel1MSB;
2091
ximage->f.put_pixel = PutPixel1LSB;
2092
else if (ximage->bits_per_pixel == 16)
2093
if (ximage->bitmap_bit_order == MSBFirst)
2094
ximage->f.put_pixel = PutPixel16MSB;
2096
ximage->f.put_pixel = PutPixel16LSB;
2097
else if (ximage->bits_per_pixel == 32)
2098
#if !defined(WORD64) && !defined(LONG64)
2099
if (*((char *)&byteorderpixel) == ximage->byte_order)
2100
ximage->f.put_pixel = PutPixel32;
2103
if (ximage->bitmap_bit_order == MSBFirst)
2104
ximage->f.put_pixel = PutPixel32MSB;
2106
ximage->f.put_pixel = PutPixel32LSB;
2107
else if ((ximage->bits_per_pixel | ximage->depth) == 1)
2108
ximage->f.put_pixel = PutPixel1;
2110
ximage->f.put_pixel = PutPixel;
2113
/* create the shape mask image */
2114
if (mask_pixel_index != XpmUndefPixel && shapeimage_return) {
2115
ErrorStatus = CreateXImage(display, visual, 1, bitmap_format,
2116
width, height, &shapeimage);
2117
if (ErrorStatus != XpmSuccess)
2118
RETURN(ErrorStatus);
2121
if (shapeimage->bitmap_bit_order == MSBFirst)
2122
shapeimage->f.put_pixel = PutPixel1MSB;
2124
shapeimage->f.put_pixel = PutPixel1LSB;
2129
* read pixels and put them in the XImage
2132
ErrorStatus = ParseAndPutPixels(data, width, height, ncolors, cpp,
2134
ErrorStatus = ParseAndPutPixels(display, data, width, height, ncolors, cpp,
2136
colorTable, &hashtable,
2137
ximage, image_pixels,
2138
shapeimage, mask_pixels);
2139
XpmFree(image_pixels);
2140
image_pixels = NULL;
2141
XpmFree(mask_pixels);
2147
if (ErrorStatus != XpmSuccess)
2149
else if (USE_HASHTABLE)
2150
xpmHashTableFree(&hashtable);
2153
* store the pixels comment line
2156
xpmGetCmt(data, &pixels_cmt);
2161
if (info && (info->valuemask & XpmReturnExtensions))
2164
ErrorStatus = xpmParseExtensions(data, &info->extensions,
2165
&info->nextensions);
2166
if (ErrorStatus != XpmSuccess)
2167
RETURN(ErrorStatus);
2169
info->extensions = NULL;
2170
info->nextensions = 0;
2175
* store found informations in the XpmImage structure
2177
image->width = width;
2178
image->height = height;
2180
image->ncolors = ncolors;
2181
image->colorTable = colorTable;
2186
info->hints_cmt = hints_cmt;
2187
info->colors_cmt = colors_cmt;
2188
info->pixels_cmt = pixels_cmt;
2191
info->x_hotspot = x_hotspot;
2192
info->y_hotspot = y_hotspot;
2193
info->valuemask |= XpmHotspot;
2196
/* if requested return used pixels in the XpmAttributes structure */
2197
if (attributes && (attributes->valuemask & XpmReturnPixels ||
2198
/* 3.2 backward compatibility code */
2199
attributes->valuemask & XpmReturnInfos)) {
2201
attributes->pixels = used_pixels;
2202
attributes->npixels = nused_pixels;
2203
attributes->mask_pixel = mask_pixel_index;
2205
XpmFree(used_pixels);
2207
/* if requested return alloc'ed pixels in the XpmAttributes structure */
2208
if (attributes && (attributes->valuemask & XpmReturnAllocPixels)) {
2209
attributes->alloc_pixels = alloc_pixels;
2210
attributes->nalloc_pixels = nalloc_pixels;
2212
XpmFree(alloc_pixels);
2214
/* return created images */
2216
*image_return = ximage;
2217
if (shapeimage_return)
2218
*shapeimage_return = shapeimage;
2220
return (XpmSuccess);
2225
ParseAndPutPixels(data, width, height, ncolors, cpp, colorTable, hashtable,
2226
image, image_pixels, shapeimage, shape_pixels)
2229
ParseAndPutPixels(dc, data, width, height, ncolors, cpp, colorTable, hashtable,
2230
image, image_pixels, shapeimage, shape_pixels)
2235
unsigned int height;
2236
unsigned int ncolors;
2238
XpmColor *colorTable;
2239
xpmHashTable *hashtable;
2241
Pixel *image_pixels;
2243
Pixel *shape_pixels;
2245
unsigned int a, x, y;
2249
case (1): /* Optimize for single character
2252
unsigned short colidx[256];
2255
return (XpmFileInvalid);
2257
bzero((char *)colidx, 256 * sizeof(short));
2258
for (a = 0; a < ncolors; a++)
2259
colidx[(unsigned char)colorTable[a].string[0]] = a + 1;
2261
for (y = 0; y < height; y++) {
2262
xpmNextString(data);
2263
for (x = 0; x < width; x++) {
2264
int c = xpmGetC(data);
2266
if (c > 0 && c < 256 && colidx[c] != 0) {
2268
XPutPixel(image, x, y, image_pixels[colidx[c] - 1]);
2270
XPutPixel(shapeimage, x, y,
2271
shape_pixels[colidx[c] - 1]);
2273
SelectObject(*dc, image->bitmap);
2274
SetPixel(*dc, x, y, image_pixels[colidx[c] - 1]);
2276
SelectObject(*dc, shapeimage->bitmap);
2277
SetPixel(*dc, x, y, shape_pixels[colidx[c] - 1]);
2281
return (XpmFileInvalid);
2287
case (2): /* Optimize for double character
2291
/* free all allocated pointers at all exits */
2292
#define FREE_CIDX {int f; for (f = 0; f < 256; f++) \
2293
if (cidx[f]) XpmFree(cidx[f]);}
2295
/* array of pointers malloced by need */
2296
unsigned short *cidx[256];
2299
bzero((char *)cidx, 256 * sizeof(unsigned short *)); /* init */
2300
for (a = 0; a < ncolors; a++) {
2301
char1 = (unsigned char) colorTable[a].string[0];
2302
if (cidx[char1] == NULL) { /* get new memory */
2303
cidx[char1] = (unsigned short *)
2304
XpmCalloc(256, sizeof(unsigned short));
2305
if (cidx[char1] == NULL) { /* new block failed */
2307
return (XpmNoMemory);
2310
cidx[char1][(unsigned char)colorTable[a].string[1]] = a + 1;
2313
for (y = 0; y < height; y++) {
2314
xpmNextString(data);
2315
for (x = 0; x < width; x++) {
2316
int cc1 = xpmGetC(data);
2317
if (cc1 > 0 && cc1 < 256) {
2318
int cc2 = xpmGetC(data);
2319
if (cc2 > 0 && cc2 < 256 && cidx[cc1][cc2] != 0) {
2321
XPutPixel(image, x, y,
2322
image_pixels[cidx[cc1][cc2] - 1]);
2324
XPutPixel(shapeimage, x, y,
2325
shape_pixels[cidx[cc1][cc2] - 1]);
2327
SelectObject(*dc, image->bitmap);
2328
SetPixel(*dc, x, y, image_pixels[cidx[cc1][cc2] - 1]);
2330
SelectObject(*dc, shapeimage->bitmap);
2332
shape_pixels[cidx[cc1][cc2] - 1]);
2337
return (XpmFileInvalid);
2341
return (XpmFileInvalid);
2349
default: /* Non-optimized case of long color
2355
if (cpp >= sizeof(buf))
2356
return (XpmFileInvalid);
2359
if (USE_HASHTABLE) {
2362
for (y = 0; y < height; y++) {
2363
xpmNextString(data);
2364
for (x = 0; x < width; x++) {
2365
for (a = 0, s = buf; a < cpp; a++, s++)
2367
slot = xpmHashSlot(hashtable, buf);
2368
if (!*slot) /* no color matches */
2369
return (XpmFileInvalid);
2371
XPutPixel(image, x, y,
2372
image_pixels[HashColorIndex(slot)]);
2374
XPutPixel(shapeimage, x, y,
2375
shape_pixels[HashColorIndex(slot)]);
2377
SelectObject(*dc, image->bitmap);
2379
image_pixels[HashColorIndex(slot)]);
2381
SelectObject(*dc, shapeimage->bitmap);
2383
shape_pixels[HashColorIndex(slot)]);
2389
for (y = 0; y < height; y++) {
2390
xpmNextString(data);
2391
for (x = 0; x < width; x++) {
2392
for (a = 0, s = buf; a < cpp; a++, s++)
2394
for (a = 0; a < ncolors; a++)
2395
if (!strcmp(colorTable[a].string, buf))
2397
if (a == ncolors) /* no color matches */
2398
return (XpmFileInvalid);
2400
XPutPixel(image, x, y, image_pixels[a]);
2402
XPutPixel(shapeimage, x, y, shape_pixels[a]);
2404
SelectObject(*dc, image->bitmap);
2405
SetPixel(*dc, x, y, image_pixels[a]);
2407
SelectObject(*dc, shapeimage->bitmap);
2408
SetPixel(*dc, x, y, shape_pixels[a]);
2417
return (XpmSuccess);