]>
Commit | Line | Data |
---|---|---|
1 | /* | |
2 | * Copyright (C) 1989-94 GROUPE BULL | |
3 | * | |
4 | * Permission is hereby granted, free of charge, to any person obtaining a copy | |
5 | * of this software and associated documentation files (the "Software"), to | |
6 | * deal in the Software without restriction, including without limitation the | |
7 | * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or | |
8 | * sell copies of the Software, and to permit persons to whom the Software is | |
9 | * furnished to do so, subject to the following conditions: | |
10 | * | |
11 | * The above copyright notice and this permission notice shall be included in | |
12 | * all copies or substantial portions of the Software. | |
13 | * | |
14 | * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | |
15 | * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | |
16 | * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL | |
17 | * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN | |
18 | * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN | |
19 | * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. | |
20 | * | |
21 | * Except as contained in this notice, the name of GROUPE BULL shall not be | |
22 | * used in advertising or otherwise to promote the sale, use or other dealings | |
23 | * in this Software without prior written authorization from GROUPE BULL. | |
24 | */ | |
25 | ||
26 | /*****************************************************************************\ | |
27 | * create.c: * | |
28 | * * | |
29 | * XPM library * | |
30 | * Create an X image and possibly its related shape mask * | |
31 | * from the given xpmInternAttrib. * | |
32 | * * | |
33 | * Developed by Arnaud Le Hors * | |
34 | \*****************************************************************************/ | |
35 | ||
36 | /* | |
37 | * The code related to FOR_MSW has been added by | |
38 | * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94 | |
39 | */ | |
40 | ||
41 | #include "xpm34p.h" | |
42 | #ifdef VMS | |
43 | #include "sys$library:ctype.h" | |
44 | #else | |
45 | #include <ctype.h> | |
46 | #endif | |
47 | ||
48 | LFUNC(xpmVisualType, int, (Visual *visual)); | |
49 | ||
50 | #ifndef FOR_MSW | |
51 | LFUNC(SetCloseColor, int, (Display *display, Colormap colormap, | |
52 | Visual *visual, XColor *col, | |
53 | Pixel *image_pixel, Pixel *mask_pixel, | |
54 | Pixel **pixels, unsigned int *npixels, | |
55 | XpmAttributes *attributes, | |
56 | XColor *cols, int ncols)); | |
57 | #else | |
58 | /* let the window system take care of close colors */ | |
59 | #endif | |
60 | ||
61 | LFUNC(SetColor, int, (Display *display, Colormap colormap, Visual *visual, | |
62 | char *colorname, unsigned int color_index, | |
63 | Pixel *image_pixel, Pixel *mask_pixel, | |
64 | unsigned int *mask_pixel_index, Pixel **pixels, | |
65 | unsigned int *npixels, XpmAttributes *attributes, | |
66 | XColor *cols, int ncols)); | |
67 | ||
68 | LFUNC(CreateXImage, int, (Display *display, Visual *visual, | |
69 | unsigned int depth, unsigned int width, | |
70 | unsigned int height, XImage **image_return)); | |
71 | ||
72 | LFUNC(CreateColors, int, (Display *display, XpmAttributes *attributes, | |
73 | XpmColor *ct, unsigned int ncolors, Pixel *ip, | |
74 | Pixel *mp, unsigned int *mask_pixel, | |
75 | Pixel **pixels, unsigned int *npixels)); | |
76 | ||
77 | #ifndef FOR_MSW | |
78 | /* XImage pixel routines */ | |
79 | LFUNC(SetImagePixels, void, (XImage *image, unsigned int width, | |
80 | unsigned int height, unsigned int *pixelindex, | |
81 | Pixel *pixels)); | |
82 | ||
83 | LFUNC(SetImagePixels32, void, (XImage *image, unsigned int width, | |
84 | unsigned int height, unsigned int *pixelindex, | |
85 | Pixel *pixels)); | |
86 | ||
87 | LFUNC(SetImagePixels16, void, (XImage *image, unsigned int width, | |
88 | unsigned int height, unsigned int *pixelindex, | |
89 | Pixel *pixels)); | |
90 | ||
91 | LFUNC(SetImagePixels8, void, (XImage *image, unsigned int width, | |
92 | unsigned int height, unsigned int *pixelindex, | |
93 | Pixel *pixels)); | |
94 | ||
95 | LFUNC(SetImagePixels1, void, (XImage *image, unsigned int width, | |
96 | unsigned int height, unsigned int *pixelindex, | |
97 | Pixel *pixels)); | |
98 | #else /* ndef FOR_MSW */ | |
99 | /* FOR_MSW pixel routine */ | |
100 | LFUNC(MSWSetImagePixels, void, (Display *dc, XImage *image, | |
101 | unsigned int width, unsigned int height, | |
102 | unsigned int *pixelindex, Pixel *pixels)); | |
103 | #endif /* ndef FOR_MSW */ | |
104 | ||
105 | #ifdef NEED_STRCASECMP | |
106 | FUNC(strcasecmp, int, (char *s1, char *s2)); | |
107 | ||
108 | /* | |
109 | * in case strcasecmp is not provided by the system here is one | |
110 | * which does the trick | |
111 | */ | |
112 | int | |
113 | strcasecmp(register char *s1, register char *s2) | |
114 | { | |
115 | register int c1, c2; | |
116 | ||
117 | while (*s1 && *s2) { | |
118 | c1 = tolower(*s1); | |
119 | c2 = tolower(*s2); | |
120 | if (c1 != c2) | |
121 | return (c1 - c2); | |
122 | s1++; | |
123 | s2++; | |
124 | } | |
125 | return (int) (*s1 - *s2); | |
126 | } | |
127 | ||
128 | #endif | |
129 | ||
130 | /* | |
131 | * return the default color key related to the given visual | |
132 | */ | |
133 | static int | |
134 | xpmVisualType(Visual *visual) | |
135 | { | |
136 | #ifndef FOR_MSW | |
137 | /* Xlib.h defines this to be c_class or class, depending | |
138 | * on whether we're doing C++ or C | |
139 | */ | |
140 | #if defined(__cplusplus) || defined(c_plusplus) | |
141 | switch (visual->c_class) | |
142 | #else | |
143 | switch (visual->class) | |
144 | #endif | |
145 | { | |
146 | case StaticGray: | |
147 | case GrayScale: | |
148 | switch (visual->map_entries) { | |
149 | case 2: | |
150 | return (XPM_MONO); | |
151 | case 4: | |
152 | return (XPM_GRAY4); | |
153 | default: | |
154 | return (XPM_GRAY); | |
155 | } | |
156 | default: | |
157 | return (XPM_COLOR); | |
158 | } | |
159 | #else | |
160 | /* there should be a similar switch for MSW */ | |
161 | return (XPM_COLOR); | |
162 | #endif | |
163 | } | |
164 | ||
165 | ||
166 | typedef struct { | |
167 | int cols_index; | |
168 | long closeness; | |
169 | } CloseColor; | |
170 | ||
171 | static int | |
172 | closeness_cmp(const void *a, const void *b) | |
173 | { | |
174 | CloseColor *x = (CloseColor *) a, *y = (CloseColor *) b; | |
175 | ||
176 | /* cast to int as qsort requires */ | |
177 | return (int) (x->closeness - y->closeness); | |
178 | } | |
179 | ||
180 | #ifndef FOR_MSW | |
181 | /* | |
182 | * set a close color in case the exact one can't be set | |
183 | * return 0 if success, 1 otherwise. | |
184 | */ | |
185 | ||
186 | static int | |
187 | SetCloseColor(Display *display, Colormap colormap, Visual *visual, XColor *col, | |
188 | Pixel *image_pixel, Pixel *mask_pixel, Pixel **pixels, unsigned int *npixels, XpmAttributes *attributes, | |
189 | XColor *cols, int ncols) | |
190 | { | |
191 | ||
192 | /* | |
193 | * Allocation failed, so try close colors. To get here the visual must | |
194 | * be GreyScale, PseudoColor or DirectColor (or perhaps StaticColor? | |
195 | * What about sharing systems like QDSS?). Beware: we have to treat | |
196 | * DirectColor differently. | |
197 | */ | |
198 | ||
199 | ||
200 | long int red_closeness, green_closeness, blue_closeness; | |
201 | int n; | |
202 | ||
203 | if (attributes && (attributes->valuemask & XpmCloseness)) | |
204 | red_closeness = green_closeness = blue_closeness = | |
205 | attributes->closeness; | |
206 | else { | |
207 | red_closeness = attributes->red_closeness; | |
208 | green_closeness = attributes->green_closeness; | |
209 | blue_closeness = attributes->blue_closeness; | |
210 | } | |
211 | ||
212 | ||
213 | /* | |
214 | * We sort the colormap by closeness and try to allocate the color | |
215 | * closest to the target. If the allocation of this close color fails, | |
216 | * which almost never happens, then one of two scenarios is possible. | |
217 | * Either the colormap must have changed (since the last close color | |
218 | * allocation or possibly while we were sorting the colormap), or the | |
219 | * color is allocated as Read/Write by some other client. (Note: X | |
220 | * _should_ allow clients to check if a particular color is Read/Write, | |
221 | * but it doesn't! :-( ). We cannot determine which of these scenarios | |
222 | * occurred, so we try the next closest color, and so on, until no more | |
223 | * colors are within closeness of the target. If we knew that the | |
224 | * colormap had changed, we could skip this sequence. | |
225 | * | |
226 | * If _none_ of the colors within closeness of the target can be allocated, | |
227 | * then we can finally be pretty sure that the colormap has actually | |
228 | * changed. In this case we try to allocate the original color (again), | |
229 | * then try the closecolor stuff (again)... | |
230 | * | |
231 | * In theory it would be possible for an infinite loop to occur if another | |
232 | * process kept changing the colormap every time we sorted it, so we set | |
233 | * a maximum on the number of iterations. After this many tries, we use | |
234 | * XGrabServer() to ensure that the colormap remains unchanged. | |
235 | * | |
236 | * This approach gives particularly bad worst case performance - as many as | |
237 | * <MaximumIterations> colormap reads and sorts may be needed, and as | |
238 | * many as <MaximumIterations> * <ColormapSize> attempted allocations | |
239 | * may fail. On an 8-bit system, this means as many as 3 colormap reads, | |
240 | * 3 sorts and 768 failed allocations per execution of this code! | |
241 | * Luckily, my experiments show that in general use in a typical 8-bit | |
242 | * color environment only about 1 in every 10000 allocations fails to | |
243 | * succeed in the fastest possible time. So virtually every time what | |
244 | * actually happens is a single sort followed by a successful allocate. | |
245 | * The very first allocation also costs a colormap read, but no further | |
246 | * reads are usually necessary. | |
247 | */ | |
248 | ||
249 | #define ITERATIONS 2 /* more than one is almost never | |
250 | * necessary */ | |
251 | ||
252 | for (n = 0; n <= ITERATIONS; ++n) { | |
253 | CloseColor *closenesses = | |
254 | (CloseColor *) XpmCalloc(ncols, sizeof(CloseColor)); | |
255 | int i, c; | |
256 | ||
257 | for (i = 0; i < ncols; ++i) { /* build & sort closenesses table */ | |
258 | #define COLOR_FACTOR 3 | |
259 | #define BRIGHTNESS_FACTOR 1 | |
260 | ||
261 | closenesses[i].cols_index = i; | |
262 | closenesses[i].closeness = | |
263 | COLOR_FACTOR * (abs((long) col->red - (long) cols[i].red) | |
264 | + abs((long) col->green - (long) cols[i].green) | |
265 | + abs((long) col->blue - (long) cols[i].blue)) | |
266 | + BRIGHTNESS_FACTOR * abs(((long) col->red + | |
267 | (long) col->green + | |
268 | (long) col->blue) | |
269 | - ((long) cols[i].red + | |
270 | (long) cols[i].green + | |
271 | (long) cols[i].blue)); | |
272 | } | |
273 | qsort(closenesses, ncols, sizeof(CloseColor), closeness_cmp); | |
274 | ||
275 | i = 0; | |
276 | c = closenesses[i].cols_index; | |
277 | while ((long) cols[c].red >= (long) col->red - red_closeness && | |
278 | (long) cols[c].red <= (long) col->red + red_closeness && | |
279 | (long) cols[c].green >= (long) col->green - green_closeness && | |
280 | (long) cols[c].green <= (long) col->green + green_closeness && | |
281 | (long) cols[c].blue >= (long) col->blue - blue_closeness && | |
282 | (long) cols[c].blue <= (long) col->blue + blue_closeness) { | |
283 | if (XAllocColor(display, colormap, &cols[c])) { | |
284 | if (n == ITERATIONS) | |
285 | XUngrabServer(display); | |
286 | XpmFree(closenesses); | |
287 | *image_pixel = cols[c].pixel; | |
288 | *mask_pixel = 1; | |
289 | (*pixels)[*npixels] = cols[c].pixel; | |
290 | (*npixels)++; | |
291 | return (0); | |
292 | } else { | |
293 | ++i; | |
294 | if (i == ncols) | |
295 | break; | |
296 | c = closenesses[i].cols_index; | |
297 | } | |
298 | } | |
299 | ||
300 | /* Couldn't allocate _any_ of the close colors! */ | |
301 | ||
302 | if (n == ITERATIONS) | |
303 | XUngrabServer(display); | |
304 | XpmFree(closenesses); | |
305 | ||
306 | if (i == 0 || i == ncols) /* no color close enough or cannot */ | |
307 | return (1); /* alloc any color (full of r/w's) */ | |
308 | ||
309 | if (XAllocColor(display, colormap, col)) { | |
310 | *image_pixel = col->pixel; | |
311 | *mask_pixel = 1; | |
312 | (*pixels)[*npixels] = col->pixel; | |
313 | (*npixels)++; | |
314 | return (0); | |
315 | } else { /* colormap has probably changed, so | |
316 | * re-read... */ | |
317 | if (n == ITERATIONS - 1) | |
318 | XGrabServer(display); | |
319 | ||
320 | #if 0 | |
321 | if (visual->c_class == DirectColor) { | |
322 | /* TODO */ | |
323 | } else | |
324 | #endif | |
325 | XQueryColors(display, colormap, cols, ncols); | |
326 | } | |
327 | } | |
328 | return (1); | |
329 | } | |
330 | ||
331 | #define USE_CLOSECOLOR attributes && \ | |
332 | (((attributes->valuemask & XpmCloseness) && attributes->closeness != 0) \ | |
333 | || ((attributes->valuemask & XpmRGBCloseness) && \ | |
334 | attributes->red_closeness != 0 \ | |
335 | && attributes->green_closeness != 0 \ | |
336 | && attributes->blue_closeness != 0)) | |
337 | ||
338 | #else | |
339 | /* FOR_MSW part */ | |
340 | /* nothing to do here, the window system does it */ | |
341 | #endif | |
342 | ||
343 | /* | |
344 | * set the color pixel related to the given colorname, | |
345 | * return 0 if success, 1 otherwise. | |
346 | */ | |
347 | ||
348 | static int | |
349 | SetColor(Display *display, Colormap colormap, Visual *visual, char *colorname, unsigned int color_index, | |
350 | Pixel *image_pixel, Pixel *mask_pixel, unsigned int *mask_pixel_index, | |
351 | Pixel **pixels, unsigned int *npixels, XpmAttributes *attributes, XColor *cols, int ncols) | |
352 | { | |
353 | XColor xcolor; | |
354 | ||
355 | if (strcasecmp(colorname, TRANSPARENT_COLOR)) { | |
356 | #ifdef wx_msw | |
357 | if (!XParseColor(display, (Colormap *)colormap, colorname, &xcolor)) | |
358 | #else | |
359 | if (!XParseColor(display, (Colormap)colormap, colorname, &xcolor)) | |
360 | #endif | |
361 | return (1); | |
362 | #ifdef wx_msw | |
363 | if (!XAllocColor(display, (Colormap *)colormap, &xcolor)) { | |
364 | #else | |
365 | if (!XAllocColor(display, (Colormap)colormap, &xcolor)) { | |
366 | #endif | |
367 | #ifndef FOR_MSW | |
368 | if (USE_CLOSECOLOR) | |
369 | return (SetCloseColor(display, colormap, visual, &xcolor, | |
370 | image_pixel, mask_pixel, pixels, npixels, | |
371 | attributes, cols, ncols)); | |
372 | else | |
373 | #endif /* ndef FOR_MSW */ | |
374 | return (1); | |
375 | } | |
376 | *image_pixel = xcolor.pixel; | |
377 | *mask_pixel = 1; | |
378 | (*pixels)[*npixels] = xcolor.pixel; | |
379 | (*npixels)++; | |
380 | } else { | |
381 | *image_pixel = 0; | |
382 | *mask_pixel = 0; | |
383 | *mask_pixel_index = color_index; /* store the color table index */ | |
384 | } | |
385 | return (0); | |
386 | } | |
387 | ||
388 | ||
389 | static int | |
390 | CreateColors(Display *display, XpmAttributes *attributes, XpmColor *ct, unsigned int ncolors, | |
391 | Pixel *ip, Pixel *mp, unsigned int *mask_pixel, Pixel **pixels, unsigned int *npixels) | |
392 | { | |
393 | /* variables stored in the XpmAttributes structure */ | |
394 | Visual *visual; | |
395 | Colormap colormap; | |
396 | XpmColorSymbol *colorsymbols; | |
397 | unsigned int numsymbols; | |
398 | ||
399 | char *colorname; | |
400 | unsigned int a, b, l; | |
401 | int pixel_defined; | |
402 | unsigned int key; | |
403 | XpmColorSymbol *symbol; | |
404 | char **defaults; | |
405 | int ErrorStatus = XpmSuccess; | |
406 | char *s; | |
407 | int default_index; | |
408 | ||
409 | XColor *cols = NULL; | |
410 | unsigned int ncols = 0; | |
411 | ||
412 | /* | |
413 | * retrieve information from the XpmAttributes | |
414 | */ | |
415 | if (attributes && attributes->valuemask & XpmColorSymbols) { | |
416 | colorsymbols = attributes->colorsymbols; | |
417 | numsymbols = attributes->numsymbols; | |
418 | } else | |
419 | numsymbols = 0; | |
420 | ||
421 | if (attributes && attributes->valuemask & XpmVisual) | |
422 | visual = attributes->visual; | |
423 | else | |
424 | visual = XDefaultVisual(display, XDefaultScreen(display)); | |
425 | ||
426 | if (attributes && attributes->valuemask & XpmColormap) | |
427 | colormap = attributes->colormap; | |
428 | else | |
429 | colormap = XDefaultColormap(display, XDefaultScreen(display)); | |
430 | ||
431 | if (attributes && attributes->valuemask & XpmColorKey) | |
432 | key = attributes->color_key; | |
433 | else | |
434 | key = xpmVisualType(visual); | |
435 | ||
436 | #ifndef FOR_MSW | |
437 | if (USE_CLOSECOLOR) { | |
438 | /* originally from SetCloseColor */ | |
439 | #if 0 | |
440 | if (visual->c_class == DirectColor) { | |
441 | ||
442 | /* | |
443 | * TODO: Implement close colors for DirectColor visuals. This is | |
444 | * difficult situation. Chances are that we will never get here, | |
445 | * because any machine that supports DirectColor will probably | |
446 | * also support TrueColor (and probably PseudoColor). Also, | |
447 | * DirectColor colormaps can be very large, so looking for close | |
448 | * colors may be too slow. | |
449 | */ | |
450 | } else { | |
451 | #endif | |
452 | int i; | |
453 | ||
454 | ncols = visual->map_entries; | |
455 | cols = (XColor *) XpmCalloc(ncols, sizeof(XColor)); | |
456 | for (i = 0; i < ncols; ++i) | |
457 | cols[i].pixel = i; | |
458 | XQueryColors(display, colormap, cols, ncols); | |
459 | #if 0 | |
460 | } | |
461 | #endif | |
462 | } | |
463 | #endif /* ndef FOR_MSW */ | |
464 | ||
465 | switch (key) { | |
466 | case XPM_MONO: | |
467 | default_index = 2; | |
468 | break; | |
469 | case XPM_GRAY4: | |
470 | default_index = 3; | |
471 | break; | |
472 | case XPM_GRAY: | |
473 | default_index = 4; | |
474 | break; | |
475 | case XPM_COLOR: | |
476 | default: | |
477 | default_index = 5; | |
478 | break; | |
479 | } | |
480 | ||
481 | for (a = 0; a < ncolors; a++, ct++, ip++, mp++) { | |
482 | colorname = NULL; | |
483 | pixel_defined = False; | |
484 | defaults = (char **) ct; | |
485 | ||
486 | /* | |
487 | * look for a defined symbol | |
488 | */ | |
489 | if (numsymbols) { | |
490 | s = defaults[1]; | |
491 | for (l = 0, symbol = colorsymbols; l < numsymbols; l++, symbol++) { | |
492 | if (symbol->name && s && !strcmp(symbol->name, s)) | |
493 | /* override name */ | |
494 | break; | |
495 | if (!symbol->name && symbol->value) { /* override value */ | |
496 | int def_index = default_index; | |
497 | ||
498 | while (defaults[def_index] == NULL) /* find defined | |
499 | * colorname */ | |
500 | --def_index; | |
501 | if (def_index < 2) {/* nothing towards mono, so try | |
502 | * towards color */ | |
503 | def_index = default_index + 1; | |
504 | while (def_index <= 5 && defaults[def_index] == NULL) | |
505 | ++def_index; | |
506 | } | |
507 | if (def_index >= 2 && defaults[def_index] != NULL && | |
508 | !strcasecmp(symbol->value, defaults[def_index])) | |
509 | break; | |
510 | } | |
511 | } | |
512 | if (l != numsymbols) { | |
513 | if (symbol->name && symbol->value) | |
514 | colorname = symbol->value; | |
515 | else | |
516 | pixel_defined = True; | |
517 | } | |
518 | } | |
519 | if (!pixel_defined) { /* pixel not given as symbol value */ | |
520 | if (colorname) { /* colorname given as symbol value */ | |
521 | if (!SetColor(display, colormap, visual, colorname, a, ip, mp, | |
522 | mask_pixel, pixels, npixels, attributes, | |
523 | cols, ncols)) | |
524 | pixel_defined = True; | |
525 | else | |
526 | ErrorStatus = XpmColorError; | |
527 | } | |
528 | b = key; | |
529 | while (!pixel_defined && b > 1) { | |
530 | if (defaults[b]) { | |
531 | if (!SetColor(display, colormap, visual, defaults[b], | |
532 | a, ip, mp, mask_pixel, pixels, npixels, | |
533 | attributes, cols, ncols)) { | |
534 | pixel_defined = True; | |
535 | break; | |
536 | } else | |
537 | ErrorStatus = XpmColorError; | |
538 | } | |
539 | b--; | |
540 | } | |
541 | b = key + 1; | |
542 | while (!pixel_defined && b < NKEYS + 1) { | |
543 | if (defaults[b]) { | |
544 | if (!SetColor(display, colormap, visual, defaults[b], | |
545 | a, ip, mp, mask_pixel, pixels, npixels, | |
546 | attributes, cols, ncols)) { | |
547 | pixel_defined = True; | |
548 | break; | |
549 | } else | |
550 | ErrorStatus = XpmColorError; | |
551 | } | |
552 | b++; | |
553 | } | |
554 | if (!pixel_defined) { | |
555 | if (cols) | |
556 | XpmFree(cols); | |
557 | return (XpmColorFailed); | |
558 | } | |
559 | } else { | |
560 | *ip = colorsymbols[l].pixel; | |
561 | if (symbol->value | |
562 | && !strcasecmp(symbol->value, TRANSPARENT_COLOR)) { | |
563 | *mp = 0; | |
564 | *mask_pixel = 0; | |
565 | } else | |
566 | *mp = 1; | |
567 | } | |
568 | } | |
569 | if (cols) | |
570 | XpmFree(cols); | |
571 | return (ErrorStatus); | |
572 | } | |
573 | ||
574 | ||
575 | /* function call in case of error, frees only locally allocated variables */ | |
576 | #undef RETURN | |
577 | #define RETURN(status) \ | |
578 | { \ | |
579 | if (ximage) XDestroyImage(ximage); \ | |
580 | if (shapeimage) XDestroyImage(shapeimage); \ | |
581 | if (ximage_pixels) XpmFree(ximage_pixels); \ | |
582 | if (mask_pixels) XpmFree(mask_pixels); \ | |
583 | if (npixels) XFreeColors(display, colormap, pixels, npixels, 0); \ | |
584 | if (pixels) XpmFree(pixels); \ | |
585 | return (status); \ | |
586 | } | |
587 | ||
588 | int | |
589 | XpmCreateImageFromXpmImage(Display *display, XpmImage *image, | |
590 | XImage **image_return, XImage **shapeimage_return, XpmAttributes *attributes) | |
591 | { | |
592 | /* variables stored in the XpmAttributes structure */ | |
593 | Visual *visual; | |
594 | Colormap colormap; | |
595 | unsigned int depth; | |
596 | ||
597 | /* variables to return */ | |
598 | XImage *ximage = NULL; | |
599 | XImage *shapeimage = NULL; | |
600 | unsigned int mask_pixel; | |
601 | int ErrorStatus; | |
602 | ||
603 | /* calculation variables */ | |
604 | Pixel *ximage_pixels = NULL; | |
605 | Pixel *mask_pixels = NULL; | |
606 | Pixel *pixels = NULL; /* allocated pixels */ | |
607 | unsigned int npixels = 0; /* number of allocated pixels */ | |
608 | ||
609 | /* initialize return values */ | |
610 | if (image_return) | |
611 | *image_return = NULL; | |
612 | if (shapeimage_return) | |
613 | *shapeimage_return = NULL; | |
614 | ||
615 | /* retrieve information from the XpmAttributes */ | |
616 | if (attributes && (attributes->valuemask & XpmVisual)) | |
617 | visual = attributes->visual; | |
618 | else | |
619 | visual = XDefaultVisual(display, XDefaultScreen(display)); | |
620 | ||
621 | if (attributes && (attributes->valuemask & XpmColormap)) | |
622 | colormap = attributes->colormap; | |
623 | else | |
624 | colormap = XDefaultColormap(display, XDefaultScreen(display)); | |
625 | ||
626 | if (attributes && (attributes->valuemask & XpmDepth)) | |
627 | depth = attributes->depth; | |
628 | else | |
629 | depth = XDefaultDepth(display, XDefaultScreen(display)); | |
630 | ||
631 | ErrorStatus = XpmSuccess; | |
632 | ||
633 | /* malloc pixels index tables */ | |
634 | ximage_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); | |
635 | if (!ximage_pixels) | |
636 | return (XpmNoMemory); | |
637 | ||
638 | mask_pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); | |
639 | if (!mask_pixels) | |
640 | RETURN(XpmNoMemory); | |
641 | ||
642 | mask_pixel = XpmUndefPixel; | |
643 | ||
644 | /* maximum of allocated pixels will be the number of colors */ | |
645 | pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * image->ncolors); | |
646 | if (!pixels) | |
647 | RETURN(XpmNoMemory); | |
648 | ||
649 | /* get pixel colors, store them in index tables */ | |
650 | ErrorStatus = CreateColors(display, attributes, image->colorTable, | |
651 | image->ncolors, ximage_pixels, mask_pixels, | |
652 | &mask_pixel, &pixels, &npixels); | |
653 | ||
654 | if (ErrorStatus != XpmSuccess | |
655 | && (ErrorStatus < 0 || (attributes | |
656 | && (attributes->valuemask & XpmExactColors) | |
657 | && attributes->exactColors))) | |
658 | RETURN(ErrorStatus); | |
659 | ||
660 | /* create the ximage */ | |
661 | if (image_return) { | |
662 | ErrorStatus = CreateXImage(display, visual, depth, | |
663 | image->width, image->height, &ximage); | |
664 | if (ErrorStatus != XpmSuccess) | |
665 | RETURN(ErrorStatus); | |
666 | ||
667 | #ifndef FOR_MSW | |
668 | ||
669 | /* | |
670 | * set the ximage data | |
671 | * | |
672 | * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use | |
673 | * optimized functions, otherwise use slower but sure general one. | |
674 | * | |
675 | */ | |
676 | ||
677 | if (ximage->depth == 1) | |
678 | SetImagePixels1(ximage, image->width, image->height, | |
679 | image->data, ximage_pixels); | |
680 | else if (ximage->bits_per_pixel == 8) | |
681 | SetImagePixels8(ximage, image->width, image->height, | |
682 | image->data, ximage_pixels); | |
683 | else if (ximage->bits_per_pixel == 16) | |
684 | SetImagePixels16(ximage, image->width, image->height, | |
685 | image->data, ximage_pixels); | |
686 | else if (ximage->bits_per_pixel == 32) | |
687 | SetImagePixels32(ximage, image->width, image->height, | |
688 | image->data, ximage_pixels); | |
689 | else | |
690 | SetImagePixels(ximage, image->width, image->height, | |
691 | image->data, ximage_pixels); | |
692 | #else /* FOR_MSW */ | |
693 | MSWSetImagePixels(display, ximage, image->width, image->height, | |
694 | image->data, ximage_pixels); | |
695 | #endif | |
696 | } | |
697 | /* create the shape mask image */ | |
698 | if (mask_pixel != XpmUndefPixel && shapeimage_return) { | |
699 | ErrorStatus = CreateXImage(display, visual, 1, image->width, | |
700 | image->height, &shapeimage); | |
701 | if (ErrorStatus != XpmSuccess) | |
702 | RETURN(ErrorStatus); | |
703 | ||
704 | #ifndef FOR_MSW | |
705 | SetImagePixels1(shapeimage, image->width, image->height, | |
706 | image->data, mask_pixels); | |
707 | #else | |
708 | MSWSetImagePixels(display, shapeimage, image->width, image->height, | |
709 | image->data, mask_pixels); | |
710 | #endif | |
711 | ||
712 | } | |
713 | XpmFree(mask_pixels); | |
714 | XpmFree(pixels); | |
715 | ||
716 | /* if requested store alloc'ed pixels in the XpmAttributes structure */ | |
717 | if (attributes) { | |
718 | if (attributes->valuemask & XpmReturnPixels || | |
719 | /* 3.2 backward compatibility code */ | |
720 | attributes->valuemask & XpmReturnInfos) { | |
721 | /* end 3.2 bc */ | |
722 | if (mask_pixel != XpmUndefPixel) { | |
723 | Pixel *pixels, *p1, *p2; | |
724 | unsigned int a; | |
725 | ||
726 | attributes->npixels = image->ncolors - 1; | |
727 | pixels = (Pixel *) XpmMalloc(sizeof(Pixel) | |
728 | * attributes->npixels); | |
729 | if (pixels) { | |
730 | p1 = ximage_pixels; | |
731 | p2 = pixels; | |
732 | for (a = 0; a < image->ncolors; a++, p1++) | |
733 | if (a != mask_pixel) | |
734 | *p2++ = *p1; | |
735 | attributes->pixels = pixels; | |
736 | } else { | |
737 | /* if error just say we can't return requested data */ | |
738 | attributes->valuemask &= ~XpmReturnPixels; | |
739 | /* 3.2 backward compatibility code */ | |
740 | attributes->valuemask &= ~XpmReturnInfos; | |
741 | /* end 3.2 bc */ | |
742 | attributes->pixels = NULL; | |
743 | attributes->npixels = 0; | |
744 | } | |
745 | XpmFree(ximage_pixels); | |
746 | } else { | |
747 | attributes->pixels = ximage_pixels; | |
748 | attributes->npixels = image->ncolors; | |
749 | } | |
750 | attributes->mask_pixel = mask_pixel; | |
751 | } else | |
752 | XpmFree(ximage_pixels); | |
753 | } else | |
754 | XpmFree(ximage_pixels); | |
755 | ||
756 | /* return created images */ | |
757 | if (image_return) | |
758 | *image_return = ximage; | |
759 | if (shapeimage_return) | |
760 | *shapeimage_return = shapeimage; | |
761 | ||
762 | return (ErrorStatus); | |
763 | } | |
764 | ||
765 | ||
766 | /* | |
767 | * Create an XImage | |
768 | */ | |
769 | static int | |
770 | CreateXImage(Display *display, Visual *visual, unsigned int depth, | |
771 | unsigned int width, unsigned int height, XImage **image_return) | |
772 | { | |
773 | int bitmap_pad; | |
774 | ||
775 | /* first get bitmap_pad */ | |
776 | if (depth > 16) | |
777 | bitmap_pad = 32; | |
778 | else if (depth > 8) | |
779 | bitmap_pad = 16; | |
780 | else | |
781 | bitmap_pad = 8; | |
782 | ||
783 | /* then create the XImage with data = NULL and bytes_per_line = 0 */ | |
784 | *image_return = XCreateImage(display, visual, depth, ZPixmap, 0, 0, | |
785 | width, height, bitmap_pad, 0); | |
786 | if (!*image_return) | |
787 | return (XpmNoMemory); | |
788 | ||
789 | #ifndef FOR_MSW | |
790 | /* now that bytes_per_line must have been set properly alloc data */ | |
791 | (*image_return)->data = | |
792 | (char *) XpmMalloc((*image_return)->bytes_per_line * height); | |
793 | ||
794 | if (!(*image_return)->data) { | |
795 | XDestroyImage(*image_return); | |
796 | *image_return = NULL; | |
797 | return (XpmNoMemory); | |
798 | } | |
799 | #else | |
800 | /* under FOR_MSW XCreateImage has done it all */ | |
801 | #endif | |
802 | return (XpmSuccess); | |
803 | } | |
804 | ||
805 | #ifndef FOR_MSW | |
806 | /* | |
807 | * The functions below are written from X11R5 MIT's code (XImUtil.c) | |
808 | * | |
809 | * The idea is to have faster functions than the standard XPutPixel function | |
810 | * to build the image data. Indeed we can speed up things by suppressing tests | |
811 | * performed for each pixel. We do the same tests but at the image level. | |
812 | * We also assume that we use only ZPixmap images with null offsets. | |
813 | */ | |
814 | ||
815 | LFUNC(_putbits, void, (register char *src, int dstoffset, | |
816 | register int numbits, register char *dst)); | |
817 | ||
818 | LFUNC(_XReverse_Bytes, int, (register unsigned char *bpt, register int nb)); | |
819 | ||
820 | static unsigned char Const _reverse_byte[0x100] = { | |
821 | 0x00, 0x80, 0x40, 0xc0, 0x20, 0xa0, 0x60, 0xe0, | |
822 | 0x10, 0x90, 0x50, 0xd0, 0x30, 0xb0, 0x70, 0xf0, | |
823 | 0x08, 0x88, 0x48, 0xc8, 0x28, 0xa8, 0x68, 0xe8, | |
824 | 0x18, 0x98, 0x58, 0xd8, 0x38, 0xb8, 0x78, 0xf8, | |
825 | 0x04, 0x84, 0x44, 0xc4, 0x24, 0xa4, 0x64, 0xe4, | |
826 | 0x14, 0x94, 0x54, 0xd4, 0x34, 0xb4, 0x74, 0xf4, | |
827 | 0x0c, 0x8c, 0x4c, 0xcc, 0x2c, 0xac, 0x6c, 0xec, | |
828 | 0x1c, 0x9c, 0x5c, 0xdc, 0x3c, 0xbc, 0x7c, 0xfc, | |
829 | 0x02, 0x82, 0x42, 0xc2, 0x22, 0xa2, 0x62, 0xe2, | |
830 | 0x12, 0x92, 0x52, 0xd2, 0x32, 0xb2, 0x72, 0xf2, | |
831 | 0x0a, 0x8a, 0x4a, 0xca, 0x2a, 0xaa, 0x6a, 0xea, | |
832 | 0x1a, 0x9a, 0x5a, 0xda, 0x3a, 0xba, 0x7a, 0xfa, | |
833 | 0x06, 0x86, 0x46, 0xc6, 0x26, 0xa6, 0x66, 0xe6, | |
834 | 0x16, 0x96, 0x56, 0xd6, 0x36, 0xb6, 0x76, 0xf6, | |
835 | 0x0e, 0x8e, 0x4e, 0xce, 0x2e, 0xae, 0x6e, 0xee, | |
836 | 0x1e, 0x9e, 0x5e, 0xde, 0x3e, 0xbe, 0x7e, 0xfe, | |
837 | 0x01, 0x81, 0x41, 0xc1, 0x21, 0xa1, 0x61, 0xe1, | |
838 | 0x11, 0x91, 0x51, 0xd1, 0x31, 0xb1, 0x71, 0xf1, | |
839 | 0x09, 0x89, 0x49, 0xc9, 0x29, 0xa9, 0x69, 0xe9, | |
840 | 0x19, 0x99, 0x59, 0xd9, 0x39, 0xb9, 0x79, 0xf9, | |
841 | 0x05, 0x85, 0x45, 0xc5, 0x25, 0xa5, 0x65, 0xe5, | |
842 | 0x15, 0x95, 0x55, 0xd5, 0x35, 0xb5, 0x75, 0xf5, | |
843 | 0x0d, 0x8d, 0x4d, 0xcd, 0x2d, 0xad, 0x6d, 0xed, | |
844 | 0x1d, 0x9d, 0x5d, 0xdd, 0x3d, 0xbd, 0x7d, 0xfd, | |
845 | 0x03, 0x83, 0x43, 0xc3, 0x23, 0xa3, 0x63, 0xe3, | |
846 | 0x13, 0x93, 0x53, 0xd3, 0x33, 0xb3, 0x73, 0xf3, | |
847 | 0x0b, 0x8b, 0x4b, 0xcb, 0x2b, 0xab, 0x6b, 0xeb, | |
848 | 0x1b, 0x9b, 0x5b, 0xdb, 0x3b, 0xbb, 0x7b, 0xfb, | |
849 | 0x07, 0x87, 0x47, 0xc7, 0x27, 0xa7, 0x67, 0xe7, | |
850 | 0x17, 0x97, 0x57, 0xd7, 0x37, 0xb7, 0x77, 0xf7, | |
851 | 0x0f, 0x8f, 0x4f, 0xcf, 0x2f, 0xaf, 0x6f, 0xef, | |
852 | 0x1f, 0x9f, 0x5f, 0xdf, 0x3f, 0xbf, 0x7f, 0xff | |
853 | }; | |
854 | ||
855 | static int | |
856 | _XReverse_Bytes(register unsigned char *bpt, register int nb) | |
857 | { | |
858 | do { | |
859 | *bpt = _reverse_byte[*bpt]; | |
860 | bpt++; | |
861 | } while (--nb > 0); | |
862 | return 0; | |
863 | } | |
864 | ||
865 | ||
866 | void | |
867 | xpm_xynormalizeimagebits(register unsigned char *bp, register XImage *img) | |
868 | { | |
869 | register unsigned char c; | |
870 | ||
871 | if (img->byte_order != img->bitmap_bit_order) { | |
872 | switch (img->bitmap_unit) { | |
873 | ||
874 | case 16: | |
875 | c = *bp; | |
876 | *bp = *(bp + 1); | |
877 | *(bp + 1) = c; | |
878 | break; | |
879 | ||
880 | case 32: | |
881 | c = *(bp + 3); | |
882 | *(bp + 3) = *bp; | |
883 | *bp = c; | |
884 | c = *(bp + 2); | |
885 | *(bp + 2) = *(bp + 1); | |
886 | *(bp + 1) = c; | |
887 | break; | |
888 | } | |
889 | } | |
890 | if (img->bitmap_bit_order == MSBFirst) | |
891 | _XReverse_Bytes(bp, img->bitmap_unit >> 3); | |
892 | } | |
893 | ||
894 | void | |
895 | xpm_znormalizeimagebits(register unsigned char *bp, register XImage *img) | |
896 | { | |
897 | register unsigned char c; | |
898 | ||
899 | switch (img->bits_per_pixel) { | |
900 | ||
901 | case 2: | |
902 | _XReverse_Bytes(bp, 1); | |
903 | break; | |
904 | ||
905 | case 4: | |
906 | *bp = ((*bp >> 4) & 0xF) | ((*bp << 4) & ~0xF); | |
907 | break; | |
908 | ||
909 | case 16: | |
910 | c = *bp; | |
911 | *bp = *(bp + 1); | |
912 | *(bp + 1) = c; | |
913 | break; | |
914 | ||
915 | case 24: | |
916 | c = *(bp + 2); | |
917 | *(bp + 2) = *bp; | |
918 | *bp = c; | |
919 | break; | |
920 | ||
921 | case 32: | |
922 | c = *(bp + 3); | |
923 | *(bp + 3) = *bp; | |
924 | *bp = c; | |
925 | c = *(bp + 2); | |
926 | *(bp + 2) = *(bp + 1); | |
927 | *(bp + 1) = c; | |
928 | break; | |
929 | } | |
930 | } | |
931 | ||
932 | static unsigned char Const _lomask[0x09] = { | |
933 | 0x00, 0x01, 0x03, 0x07, 0x0f, 0x1f, 0x3f, 0x7f, 0xff}; | |
934 | static unsigned char Const _himask[0x09] = { | |
935 | 0xff, 0xfe, 0xfc, 0xf8, 0xf0, 0xe0, 0xc0, 0x80, 0x00}; | |
936 | ||
937 | static void | |
938 | _putbits(register char *src, int dstoffset, register int numbits, register char *dst) | |
939 | ||
940 | /* register char *src; */ /* address of source bit string */ | |
941 | /* int dstoffset; */ /* bit offset into destination; | |
942 | * range is 0-31 */ | |
943 | /* register int numbits; */ /* number of bits to copy to | |
944 | * destination */ | |
945 | /* register char *dst; */ /* address of destination bit string */ | |
946 | { | |
947 | register unsigned char chlo, chhi; | |
948 | int hibits; | |
949 | ||
950 | dst = dst + (dstoffset >> 3); | |
951 | dstoffset = dstoffset & 7; | |
952 | hibits = 8 - dstoffset; | |
953 | chlo = *dst & _lomask[dstoffset]; | |
954 | for (;;) { | |
955 | chhi = (*src << dstoffset) & _himask[dstoffset]; | |
956 | if (numbits <= hibits) { | |
957 | chhi = chhi & _lomask[dstoffset + numbits]; | |
958 | *dst = (*dst & _himask[dstoffset + numbits]) | chlo | chhi; | |
959 | break; | |
960 | } | |
961 | *dst = chhi | chlo; | |
962 | dst++; | |
963 | numbits = numbits - hibits; | |
964 | chlo = (unsigned char) (*src & _himask[hibits]) >> hibits; | |
965 | src++; | |
966 | if (numbits <= dstoffset) { | |
967 | chlo = chlo & _lomask[numbits]; | |
968 | *dst = (*dst & _himask[numbits]) | chlo; | |
969 | break; | |
970 | } | |
971 | numbits = numbits - dstoffset; | |
972 | } | |
973 | } | |
974 | ||
975 | /* | |
976 | * Default method to write pixels into a Z image data structure. | |
977 | * The algorithm used is: | |
978 | * | |
979 | * copy the destination bitmap_unit or Zpixel to temp | |
980 | * normalize temp if needed | |
981 | * copy the pixel bits into the temp | |
982 | * renormalize temp if needed | |
983 | * copy the temp back into the destination image data | |
984 | */ | |
985 | ||
986 | static void | |
987 | SetImagePixels(XImage *image, unsigned int width, unsigned int height, unsigned int *pixelindex, Pixel *pixels) | |
988 | { | |
989 | register char *src; | |
990 | register char *dst; | |
991 | register unsigned int *iptr; | |
992 | register int x, y, i; | |
993 | register char *data; | |
994 | Pixel pixel, px; | |
995 | int nbytes, depth, ibu, ibpp; | |
996 | ||
997 | data = image->data; | |
998 | iptr = pixelindex; | |
999 | depth = image->depth; | |
1000 | if (depth == 1) { | |
1001 | ibu = image->bitmap_unit; | |
1002 | for (y = 0; y < height; y++) | |
1003 | for (x = 0; x < width; x++, iptr++) { | |
1004 | pixel = pixels[*iptr]; | |
1005 | for (i = 0, px = pixel; i < sizeof(unsigned long); | |
1006 | i++, px >>= 8) | |
1007 | ((unsigned char *) &pixel)[i] = px; | |
1008 | src = &data[XYINDEX(x, y, image)]; | |
1009 | dst = (char *) &px; | |
1010 | px = 0; | |
1011 | nbytes = ibu >> 3; | |
1012 | for (i = nbytes; --i >= 0;) | |
1013 | *dst++ = *src++; | |
1014 | XYNORMALIZE(&px, image); | |
1015 | _putbits((char *) &pixel, (x % ibu), 1, (char *) &px); | |
1016 | XYNORMALIZE(&px, image); | |
1017 | src = (char *) &px; | |
1018 | dst = &data[XYINDEX(x, y, image)]; | |
1019 | for (i = nbytes; --i >= 0;) | |
1020 | *dst++ = *src++; | |
1021 | } | |
1022 | } else { | |
1023 | ibpp = image->bits_per_pixel; | |
1024 | for (y = 0; y < height; y++) | |
1025 | for (x = 0; x < width; x++, iptr++) { | |
1026 | pixel = pixels[*iptr]; | |
1027 | if (depth == 4) | |
1028 | pixel &= 0xf; | |
1029 | for (i = 0, px = pixel; i < sizeof(unsigned long); i++, | |
1030 | px >>= 8) | |
1031 | ((unsigned char *) &pixel)[i] = px; | |
1032 | src = &data[ZINDEX(x, y, image)]; | |
1033 | dst = (char *) &px; | |
1034 | px = 0; | |
1035 | nbytes = (ibpp + 7) >> 3; | |
1036 | for (i = nbytes; --i >= 0;) | |
1037 | *dst++ = *src++; | |
1038 | ZNORMALIZE(&px, image); | |
1039 | _putbits((char *) &pixel, (x * ibpp) & 7, ibpp, (char *) &px); | |
1040 | ZNORMALIZE(&px, image); | |
1041 | src = (char *) &px; | |
1042 | dst = &data[ZINDEX(x, y, image)]; | |
1043 | for (i = nbytes; --i >= 0;) | |
1044 | *dst++ = *src++; | |
1045 | } | |
1046 | } | |
1047 | } | |
1048 | ||
1049 | /* | |
1050 | * write pixels into a 32-bits Z image data structure | |
1051 | */ | |
1052 | ||
1053 | #ifndef WORD64 | |
1054 | /* this item is static but deterministic so let it slide; doesn't | |
1055 | * hurt re-entrancy of this library. Note if it is actually const then would | |
1056 | * be OK under rules of ANSI-C but probably not C++ which may not | |
1057 | * want to allocate space for it. | |
1058 | */ | |
1059 | static unsigned long /* constant */ RTXpm_byteorderpixel = MSBFirst << 24; | |
1060 | ||
1061 | #endif | |
1062 | ||
1063 | /* | |
1064 | WITHOUT_SPEEDUPS is a flag to be turned on if you wish to use the original | |
1065 | 3.2e code - by default you get the speeded-up version. | |
1066 | */ | |
1067 | ||
1068 | static void | |
1069 | SetImagePixels32(XImage *image, unsigned int width, unsigned int height, unsigned int *pixelindex, Pixel *pixels) | |
1070 | { | |
1071 | unsigned char *data; | |
1072 | unsigned int *iptr; | |
1073 | int y; | |
1074 | Pixel pixel; | |
1075 | ||
1076 | #ifdef WITHOUT_SPEEDUPS | |
1077 | ||
1078 | int x; | |
1079 | unsigned char *addr; | |
1080 | ||
1081 | data = (unsigned char *) image->data; | |
1082 | iptr = pixelindex; | |
1083 | #ifndef WORD64 | |
1084 | if (*((char *) &RTXpm_byteorderpixel) == image->byte_order) { | |
1085 | for (y = 0; y < height; y++) | |
1086 | for (x = 0; x < width; x++, iptr++) { | |
1087 | addr = &data[ZINDEX32(x, y, image)]; | |
1088 | *((unsigned long *) addr) = pixels[*iptr]; | |
1089 | } | |
1090 | } else | |
1091 | #endif | |
1092 | if (image->byte_order == MSBFirst) | |
1093 | for (y = 0; y < height; y++) | |
1094 | for (x = 0; x < width; x++, iptr++) { | |
1095 | addr = &data[ZINDEX32(x, y, image)]; | |
1096 | pixel = pixels[*iptr]; | |
1097 | addr[0] = pixel >> 24; | |
1098 | addr[1] = pixel >> 16; | |
1099 | addr[2] = pixel >> 8; | |
1100 | addr[3] = pixel; | |
1101 | } | |
1102 | else | |
1103 | for (y = 0; y < height; y++) | |
1104 | for (x = 0; x < width; x++, iptr++) { | |
1105 | addr = &data[ZINDEX32(x, y, image)]; | |
1106 | pixel = pixels[*iptr]; | |
1107 | addr[0] = pixel; | |
1108 | addr[1] = pixel >> 8; | |
1109 | addr[2] = pixel >> 16; | |
1110 | addr[3] = pixel >> 24; | |
1111 | } | |
1112 | ||
1113 | #else /* WITHOUT_SPEEDUPS */ | |
1114 | ||
1115 | int bpl = image->bytes_per_line; | |
1116 | unsigned char *data_ptr, *max_data; | |
1117 | ||
1118 | data = (unsigned char *) image->data; | |
1119 | iptr = pixelindex; | |
1120 | #ifndef WORD64 | |
1121 | if (*((char *) &RTXpm_byteorderpixel) == image->byte_order) { | |
1122 | for (y = 0; y < height; y++) { | |
1123 | data_ptr = data; | |
1124 | max_data = data_ptr + (width << 2); | |
1125 | ||
1126 | while (data_ptr < max_data) { | |
1127 | *((unsigned long *) data_ptr) = pixels[*(iptr++)]; | |
1128 | data_ptr += (1 << 2); | |
1129 | } | |
1130 | data += bpl; | |
1131 | } | |
1132 | } else | |
1133 | #endif | |
1134 | if (image->byte_order == MSBFirst) | |
1135 | for (y = 0; y < height; y++) { | |
1136 | data_ptr = data; | |
1137 | max_data = data_ptr + (width << 2); | |
1138 | ||
1139 | while (data_ptr < max_data) { | |
1140 | pixel = pixels[*(iptr++)]; | |
1141 | ||
1142 | *data_ptr++ = pixel >> 24; | |
1143 | *data_ptr++ = pixel >> 16; | |
1144 | *data_ptr++ = pixel >> 8; | |
1145 | *data_ptr++ = pixel; | |
1146 | ||
1147 | } | |
1148 | data += bpl; | |
1149 | } | |
1150 | else | |
1151 | for (y = 0; y < height; y++) { | |
1152 | data_ptr = data; | |
1153 | max_data = data_ptr + (width << 2); | |
1154 | ||
1155 | while (data_ptr < max_data) { | |
1156 | pixel = pixels[*(iptr++)]; | |
1157 | ||
1158 | *data_ptr++ = pixel; | |
1159 | *data_ptr++ = pixel >> 8; | |
1160 | *data_ptr++ = pixel >> 16; | |
1161 | *data_ptr++ = pixel >> 24; | |
1162 | } | |
1163 | data += bpl; | |
1164 | } | |
1165 | ||
1166 | #endif /* WITHOUT_SPEEDUPS */ | |
1167 | } | |
1168 | ||
1169 | /* | |
1170 | * write pixels into a 16-bits Z image data structure | |
1171 | */ | |
1172 | ||
1173 | static void | |
1174 | SetImagePixels16(XImage *image, unsigned int width, unsigned int height, unsigned int *pixelindex, Pixel *pixels) | |
1175 | { | |
1176 | unsigned char *data; | |
1177 | unsigned int *iptr; | |
1178 | int y; | |
1179 | ||
1180 | #ifdef WITHOUT_SPEEDUPS | |
1181 | ||
1182 | int x; | |
1183 | unsigned char *addr; | |
1184 | ||
1185 | data = (unsigned char *) image->data; | |
1186 | iptr = pixelindex; | |
1187 | if (image->byte_order == MSBFirst) | |
1188 | for (y = 0; y < height; y++) | |
1189 | for (x = 0; x < width; x++, iptr++) { | |
1190 | addr = &data[ZINDEX16(x, y, image)]; | |
1191 | addr[0] = pixels[*iptr] >> 8; | |
1192 | addr[1] = pixels[*iptr]; | |
1193 | } | |
1194 | else | |
1195 | for (y = 0; y < height; y++) | |
1196 | for (x = 0; x < width; x++, iptr++) { | |
1197 | addr = &data[ZINDEX16(x, y, image)]; | |
1198 | addr[0] = pixels[*iptr]; | |
1199 | addr[1] = pixels[*iptr] >> 8; | |
1200 | } | |
1201 | ||
1202 | #else /* WITHOUT_SPEEDUPS */ | |
1203 | ||
1204 | Pixel pixel; | |
1205 | ||
1206 | int bpl = image->bytes_per_line; | |
1207 | unsigned char *data_ptr, *max_data; | |
1208 | ||
1209 | data = (unsigned char *) image->data; | |
1210 | iptr = pixelindex; | |
1211 | if (image->byte_order == MSBFirst) | |
1212 | for (y = 0; y < height; y++) { | |
1213 | data_ptr = data; | |
1214 | max_data = data_ptr + (width << 1); | |
1215 | ||
1216 | while (data_ptr < max_data) { | |
1217 | pixel = pixels[*(iptr++)]; | |
1218 | ||
1219 | data_ptr[0] = pixel >> 8; | |
1220 | data_ptr[1] = pixel; | |
1221 | ||
1222 | data_ptr += (1 << 1); | |
1223 | } | |
1224 | data += bpl; | |
1225 | } | |
1226 | else | |
1227 | for (y = 0; y < height; y++) { | |
1228 | data_ptr = data; | |
1229 | max_data = data_ptr + (width << 1); | |
1230 | ||
1231 | while (data_ptr < max_data) { | |
1232 | pixel = pixels[*(iptr++)]; | |
1233 | ||
1234 | data_ptr[0] = pixel; | |
1235 | data_ptr[1] = pixel >> 8; | |
1236 | ||
1237 | data_ptr += (1 << 1); | |
1238 | } | |
1239 | data += bpl; | |
1240 | } | |
1241 | ||
1242 | #endif /* WITHOUT_SPEEDUPS */ | |
1243 | } | |
1244 | ||
1245 | /* | |
1246 | * write pixels into a 8-bits Z image data structure | |
1247 | */ | |
1248 | ||
1249 | static void | |
1250 | SetImagePixels8(XImage *image, unsigned int width, unsigned int height, unsigned int *pixelindex, Pixel *pixels) | |
1251 | { | |
1252 | char *data; | |
1253 | unsigned int *iptr; | |
1254 | int y; | |
1255 | ||
1256 | #ifdef WITHOUT_SPEEDUPS | |
1257 | ||
1258 | int x; | |
1259 | ||
1260 | data = image->data; | |
1261 | iptr = pixelindex; | |
1262 | for (y = 0; y < height; y++) | |
1263 | for (x = 0; x < width; x++, iptr++) | |
1264 | data[ZINDEX8(x, y, image)] = pixels[*iptr]; | |
1265 | ||
1266 | #else /* WITHOUT_SPEEDUPS */ | |
1267 | ||
1268 | int bpl = image->bytes_per_line; | |
1269 | char *data_ptr, *max_data; | |
1270 | ||
1271 | data = image->data; | |
1272 | iptr = pixelindex; | |
1273 | ||
1274 | for (y = 0; y < height; y++) { | |
1275 | data_ptr = data; | |
1276 | max_data = data_ptr + width; | |
1277 | ||
1278 | while (data_ptr < max_data) | |
1279 | *(data_ptr++) = pixels[*(iptr++)]; | |
1280 | ||
1281 | data += bpl; | |
1282 | } | |
1283 | ||
1284 | #endif /* WITHOUT_SPEEDUPS */ | |
1285 | } | |
1286 | ||
1287 | /* | |
1288 | * write pixels into a 1-bit depth image data structure and **offset null** | |
1289 | */ | |
1290 | ||
1291 | static void | |
1292 | SetImagePixels1(XImage *image, unsigned int width, unsigned int height, unsigned int *pixelindex, Pixel *pixels) | |
1293 | { | |
1294 | if (image->byte_order != image->bitmap_bit_order) | |
1295 | SetImagePixels(image, width, height, pixelindex, pixels); | |
1296 | else { | |
1297 | unsigned int *iptr; | |
1298 | int y; | |
1299 | char *data; | |
1300 | ||
1301 | #ifdef WITHOUT_SPEEDUPS | |
1302 | ||
1303 | int x; | |
1304 | ||
1305 | data = image->data; | |
1306 | iptr = pixelindex; | |
1307 | if (image->bitmap_bit_order == MSBFirst) | |
1308 | for (y = 0; y < height; y++) | |
1309 | for (x = 0; x < width; x++, iptr++) { | |
1310 | if (pixels[*iptr] & 1) | |
1311 | data[ZINDEX1(x, y, image)] |= 0x80 >> (x & 7); | |
1312 | else | |
1313 | data[ZINDEX1(x, y, image)] &= ~(0x80 >> (x & 7)); | |
1314 | } | |
1315 | else | |
1316 | for (y = 0; y < height; y++) | |
1317 | for (x = 0; x < width; x++, iptr++) { | |
1318 | if (pixels[*iptr] & 1) | |
1319 | data[ZINDEX1(x, y, image)] |= 1 << (x & 7); | |
1320 | else | |
1321 | data[ZINDEX1(x, y, image)] &= ~(1 << (x & 7)); | |
1322 | } | |
1323 | ||
1324 | #else /* WITHOUT_SPEEDUPS */ | |
1325 | ||
1326 | char value; | |
1327 | char *data_ptr, *max_data; | |
1328 | int bpl = image->bytes_per_line; | |
1329 | int diff, count; | |
1330 | ||
1331 | data = image->data; | |
1332 | iptr = pixelindex; | |
1333 | ||
1334 | diff = width & 7; | |
1335 | width >>= 3; | |
1336 | ||
1337 | if (image->bitmap_bit_order == MSBFirst) | |
1338 | for (y = 0; y < height; y++) { | |
1339 | data_ptr = data; | |
1340 | max_data = data_ptr + width; | |
1341 | while (data_ptr < max_data) { | |
1342 | value = 0; | |
1343 | ||
1344 | value = (value << 1) | (pixels[*(iptr++)] & 1); | |
1345 | value = (value << 1) | (pixels[*(iptr++)] & 1); | |
1346 | value = (value << 1) | (pixels[*(iptr++)] & 1); | |
1347 | value = (value << 1) | (pixels[*(iptr++)] & 1); | |
1348 | value = (value << 1) | (pixels[*(iptr++)] & 1); | |
1349 | value = (value << 1) | (pixels[*(iptr++)] & 1); | |
1350 | value = (value << 1) | (pixels[*(iptr++)] & 1); | |
1351 | value = (value << 1) | (pixels[*(iptr++)] & 1); | |
1352 | ||
1353 | *(data_ptr++) = value; | |
1354 | } | |
1355 | if (diff) { | |
1356 | value = 0; | |
1357 | for (count = 0; count < diff; count++) { | |
1358 | if (pixels[*(iptr++)] & 1) | |
1359 | value |= (0x80 >> count); | |
1360 | } | |
1361 | *(data_ptr) = value; | |
1362 | } | |
1363 | data += bpl; | |
1364 | } | |
1365 | else | |
1366 | for (y = 0; y < height; y++) { | |
1367 | data_ptr = data; | |
1368 | max_data = data_ptr + width; | |
1369 | while (data_ptr < max_data) { | |
1370 | value = 0; | |
1371 | iptr += 8; | |
1372 | ||
1373 | value = (value << 1) | (pixels[*(--iptr)] & 1); | |
1374 | value = (value << 1) | (pixels[*(--iptr)] & 1); | |
1375 | value = (value << 1) | (pixels[*(--iptr)] & 1); | |
1376 | value = (value << 1) | (pixels[*(--iptr)] & 1); | |
1377 | value = (value << 1) | (pixels[*(--iptr)] & 1); | |
1378 | value = (value << 1) | (pixels[*(--iptr)] & 1); | |
1379 | value = (value << 1) | (pixels[*(--iptr)] & 1); | |
1380 | value = (value << 1) | (pixels[*(--iptr)] & 1); | |
1381 | ||
1382 | iptr += 8; | |
1383 | *(data_ptr++) = value; | |
1384 | } | |
1385 | if (diff) { | |
1386 | value = 0; | |
1387 | for (count = 0; count < diff; count++) { | |
1388 | if (pixels[*(iptr++)] & 1) | |
1389 | value |= (1 << count); | |
1390 | } | |
1391 | *(data_ptr) = value; | |
1392 | } | |
1393 | data += bpl; | |
1394 | } | |
1395 | ||
1396 | #endif /* WITHOUT_SPEEDUPS */ | |
1397 | } | |
1398 | } | |
1399 | ||
1400 | int | |
1401 | XpmCreatePixmapFromXpmImage(Display *display, Drawable d, XpmImage *image, | |
1402 | Pixmap *pixmap_return, Pixmap *shapemask_return, XpmAttributes *attributes) | |
1403 | { | |
1404 | XImage *ximage, *shapeimage; | |
1405 | int ErrorStatus; | |
1406 | ||
1407 | /* initialize return values */ | |
1408 | if (pixmap_return) | |
1409 | *pixmap_return = 0; | |
1410 | if (shapemask_return) | |
1411 | *shapemask_return = 0; | |
1412 | ||
1413 | /* create the ximages */ | |
1414 | ErrorStatus = XpmCreateImageFromXpmImage(display, image, | |
1415 | (pixmap_return ? &ximage : NULL), | |
1416 | (shapemask_return ? | |
1417 | &shapeimage : NULL), | |
1418 | attributes); | |
1419 | if (ErrorStatus < 0) | |
1420 | return (ErrorStatus); | |
1421 | ||
1422 | /* create the pixmaps and destroy images */ | |
1423 | if (pixmap_return && ximage) { | |
1424 | xpmCreatePixmapFromImage(display, d, ximage, pixmap_return); | |
1425 | XDestroyImage(ximage); | |
1426 | } | |
1427 | if (shapemask_return && shapeimage) { | |
1428 | xpmCreatePixmapFromImage(display, d, shapeimage, shapemask_return); | |
1429 | XDestroyImage(shapeimage); | |
1430 | } | |
1431 | return (ErrorStatus); | |
1432 | } | |
1433 | ||
1434 | #else /* FOR_MSW part follows */ | |
1435 | static void | |
1436 | MSWSetImagePixels(Display *dc, XImage *image, unsigned int width, unsigned int height, | |
1437 | unsigned int *pixelindex, Pixel *pixels) | |
1438 | { | |
1439 | unsigned int *data = pixelindex; | |
1440 | unsigned int x, y; | |
1441 | ||
1442 | SelectObject(*dc, image->bitmap); | |
1443 | if (image->depth == 1) | |
1444 | { | |
1445 | for (y = 0; y < height; y++) { | |
1446 | for (x = 0; x < width; x++) { | |
1447 | SetPixel(*dc, x, y, (pixels[*(data++)] ? RGB(255,255,255) : 0)); /* data is [x+y*width] */ | |
1448 | } | |
1449 | } | |
1450 | } | |
1451 | else | |
1452 | { | |
1453 | for (y = 0; y < height; y++) { | |
1454 | for (x = 0; x < width; x++) { | |
1455 | SetPixel(*dc, x, y, pixels[*(data++)]); /* data is [x+y*width] */ | |
1456 | } | |
1457 | } | |
1458 | } | |
1459 | } | |
1460 | ||
1461 | #endif /* FOR_MSW */ |