]> git.saurik.com Git - wxWidgets.git/blob - src/mac/xpm/scan.c
corrections for final release of Mac OS X
[wxWidgets.git] / src / mac / xpm / scan.c
1 /*
2 * Copyright (C) 1989-95 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 * scan.c: *
28 * *
29 * XPM library *
30 * Scanning utility for XPM file format *
31 * *
32 * Developed by Arnaud Le Hors *
33 \*****************************************************************************/
34
35 /*
36 * The code related to FOR_MSW has been added by
37 * HeDu (hedu@cul-ipn.uni-kiel.de) 4/94
38 */
39
40 /*
41 * The code related to AMIGA has been added by
42 * Lorens Younes (d93-hyo@nada.kth.se) 4/96
43 */
44
45 #include "XpmI.h"
46
47 #define MAXPRINTABLE 92 /* number of printable ascii chars
48 * minus \ and " for string compat
49 * and ? to avoid ANSI trigraphs. */
50
51 static char *printable =
52 " .XoO+@#$%&*=-;:>,<1234567890qwertyuipasdfghjklzxcvbnmMNBVCZ\
53 ASDFGHJKLPIUYTREWQ!~^/()_`'][{}|";
54
55 /*
56 * printable begin with a space, so in most case, due to my algorithm, when
57 * the number of different colors is less than MAXPRINTABLE, it will give a
58 * char follow by "nothing" (a space) in the readable xpm file
59 */
60
61
62 typedef struct {
63 Pixel *pixels;
64 unsigned int *pixelindex;
65 unsigned int size;
66 unsigned int ncolors;
67 unsigned int mask_pixel; /* whether there is or not */
68 } PixelsMap;
69
70 LFUNC(storePixel, int, (Pixel pixel, PixelsMap *pmap,
71 unsigned int *index_return));
72
73 LFUNC(storeMaskPixel, int, (Pixel pixel, PixelsMap *pmap,
74 unsigned int *index_return));
75
76 LFUNC(PlatformGetImagePixels, int, (Display *d, XImage *image, unsigned int width,
77 unsigned int height, PixelsMap *pmap,
78 int (*storeFunc) ()));
79 LFUNC(ScanTransparentColor, int, (XpmColor *color, unsigned int cpp,
80 XpmAttributes *attributes));
81
82 LFUNC(ScanOtherColors, int, (Display *display, XpmColor *colors, int ncolors,
83 Pixel *pixels, unsigned int mask,
84 unsigned int cpp, XpmAttributes *attributes));
85
86 /*
87 * This function stores the given pixel in the given arrays which are grown
88 * if not large enough.
89 */
90 static int
91 storePixel(pixel, pmap, index_return)
92 Pixel pixel;
93 PixelsMap *pmap;
94 unsigned int *index_return;
95 {
96 unsigned int i;
97 Pixel *p;
98 unsigned int ncolors;
99
100 if (*index_return) { /* this is a transparent pixel! */
101 *index_return = 0;
102 return 0;
103 }
104 ncolors = pmap->ncolors;
105 p = pmap->pixels + pmap->mask_pixel;
106 for (i = pmap->mask_pixel; i < ncolors; i++, p++)
107 if ( IS_EQUAL_PIXEL(*p , pixel) )
108 break;
109 if (i == ncolors) {
110 if (ncolors >= pmap->size) {
111 pmap->size *= 2;
112 p = (Pixel *) XpmRealloc(pmap->pixels, sizeof(Pixel) * pmap->size);
113 if (!p)
114 return (1);
115 pmap->pixels = p;
116
117 }
118 (pmap->pixels)[ncolors] = pixel;
119 pmap->ncolors++;
120 }
121 *index_return = i;
122 return 0;
123 }
124
125 static int
126 storeMaskPixel(pixel, pmap, index_return)
127 Pixel pixel;
128 PixelsMap *pmap;
129 unsigned int *index_return;
130 {
131 if (IS_ZERO_PIXEL(pixel)) {
132 if (!pmap->ncolors) {
133 pmap->ncolors = 1;
134 SET_ZERO_PIXEL((pmap->pixels)[0]);
135 pmap->mask_pixel = 1;
136 }
137 *index_return = 1;
138 } else
139 *index_return = 0;
140 return 0;
141 }
142
143 /* function call in case of error */
144 #undef RETURN
145 #define RETURN(status) \
146 { \
147 ErrorStatus = status; \
148 goto error; \
149 }
150
151 /*
152 * This function scans the given image and stores the found informations in
153 * the given XpmImage structure.
154 */
155 int
156 XpmCreateXpmImageFromImage(display, image, shapeimage,
157 xpmimage, attributes)
158 Display *display;
159 XImage *image;
160 XImage *shapeimage;
161 XpmImage *xpmimage;
162 XpmAttributes *attributes;
163 {
164 /* variables stored in the XpmAttributes structure */
165 unsigned int cpp;
166
167 /* variables to return */
168 PixelsMap pmap;
169 XpmColor *colorTable = NULL;
170 int ErrorStatus;
171
172 /* calculation variables */
173 unsigned int width = 0;
174 unsigned int height = 0;
175 unsigned int cppm; /* minimum chars per pixel */
176 unsigned int c;
177
178 /* initialize pmap */
179 pmap.pixels = NULL;
180 pmap.pixelindex = NULL;
181 pmap.size = 256; /* should be enough most of the time */
182 pmap.ncolors = 0;
183 pmap.mask_pixel = 0;
184
185 /*
186 * get geometry
187 */
188 if (image) {
189 width = image->width;
190 height = image->height;
191 } else if (shapeimage) {
192 width = shapeimage->width;
193 height = shapeimage->height;
194 }
195
196 /*
197 * retrieve information from the XpmAttributes
198 */
199 if (attributes && (attributes->valuemask & XpmCharsPerPixel
200 /* 3.2 backward compatibility code */
201 || attributes->valuemask & XpmInfos))
202 /* end 3.2 bc */
203 cpp = attributes->cpp;
204 else
205 cpp = 0;
206
207 pmap.pixelindex =
208 (unsigned int *) XpmCalloc(width * height, sizeof(unsigned int));
209 if (!pmap.pixelindex)
210 RETURN(XpmNoMemory);
211
212 pmap.pixels = (Pixel *) XpmMalloc(sizeof(Pixel) * pmap.size);
213 if (!pmap.pixels)
214 RETURN(XpmNoMemory);
215
216 /*
217 * scan shape mask if any
218 */
219 if (shapeimage) {
220
221 ErrorStatus = PlatformGetImagePixels(display, shapeimage, width, height,
222 &pmap, storeMaskPixel);
223
224 if (ErrorStatus != XpmSuccess)
225 RETURN(ErrorStatus);
226 }
227
228 /*
229 * scan the image data
230 *
231 * In case depth is 1 or bits_per_pixel is 4, 6, 8, 24 or 32 use optimized
232 * functions, otherwise use slower but sure general one.
233 *
234 */
235
236 if (image) {
237
238 ErrorStatus = PlatformGetImagePixels(display, image, width, height, &pmap,
239 storePixel);
240
241 if (ErrorStatus != XpmSuccess)
242 RETURN(ErrorStatus);
243 }
244
245 /*
246 * get rgb values and a string of char, and possibly a name for each
247 * color
248 */
249
250 colorTable = (XpmColor *) XpmCalloc(pmap.ncolors, sizeof(XpmColor));
251 if (!colorTable)
252 RETURN(XpmNoMemory);
253
254 /* compute the minimal cpp */
255 for (cppm = 1, c = MAXPRINTABLE; pmap.ncolors > c; cppm++)
256 c *= MAXPRINTABLE;
257 if (cpp < cppm)
258 cpp = cppm;
259
260 if (pmap.mask_pixel) {
261 ErrorStatus = ScanTransparentColor(colorTable, cpp, attributes);
262 if (ErrorStatus != XpmSuccess)
263 RETURN(ErrorStatus);
264 }
265
266 ErrorStatus = ScanOtherColors(display, colorTable, pmap.ncolors,
267 pmap.pixels, pmap.mask_pixel, cpp,
268 attributes);
269 if (ErrorStatus != XpmSuccess)
270 RETURN(ErrorStatus);
271
272 /*
273 * store found informations in the XpmImage structure
274 */
275 xpmimage->width = width;
276 xpmimage->height = height;
277 xpmimage->cpp = cpp;
278 xpmimage->ncolors = pmap.ncolors;
279 xpmimage->colorTable = colorTable;
280 xpmimage->data = pmap.pixelindex;
281
282 XpmFree(pmap.pixels);
283 return (XpmSuccess);
284
285 /* exit point in case of error, free only locally allocated variables */
286 error:
287 if (pmap.pixelindex)
288 XpmFree(pmap.pixelindex);
289 if (pmap.pixels)
290 XpmFree(pmap.pixels);
291 if (colorTable)
292 xpmFreeColorTable(colorTable, pmap.ncolors);
293
294 return (ErrorStatus);
295 }
296
297 static int
298 ScanTransparentColor(color, cpp, attributes)
299 XpmColor *color;
300 unsigned int cpp;
301 XpmAttributes *attributes;
302 {
303 char *s;
304 unsigned int a, b, c;
305
306 /* first get a character string */
307 a = 0;
308 if (!(s = color->string = (char *) XpmMalloc(cpp + 1)))
309 return (XpmNoMemory);
310 *s++ = printable[c = a % MAXPRINTABLE];
311 for (b = 1; b < cpp; b++, s++)
312 *s = printable[c = ((a - c) / MAXPRINTABLE) % MAXPRINTABLE];
313 *s = '\0';
314
315 /* then retreive related info from the attributes if any */
316 if (attributes && (attributes->valuemask & XpmColorTable
317 /* 3.2 backward compatibility code */
318 || attributes->valuemask & XpmInfos)
319 /* end 3.2 bc */
320 && attributes->mask_pixel != XpmUndefPixel) {
321
322 unsigned int key;
323 char **defaults = (char **) color;
324 char **mask_defaults;
325
326 /* 3.2 backward compatibility code */
327 if (attributes->valuemask & XpmColorTable)
328 /* end 3.2 bc */
329 mask_defaults = (char **) (
330 attributes->colorTable + attributes->mask_pixel);
331 /* 3.2 backward compatibility code */
332 else
333 mask_defaults = (char **)
334 ((XpmColor **) attributes->colorTable)[attributes->mask_pixel];
335 /* end 3.2 bc */
336 for (key = 1; key <= NKEYS; key++) {
337 if (s = mask_defaults[key]) {
338 defaults[key] = (char *) xpmstrdup(s);
339 if (!defaults[key])
340 return (XpmNoMemory);
341 }
342 }
343 } else {
344 color->c_color = (char *) xpmstrdup(TRANSPARENT_COLOR);
345 if (!color->c_color)
346 return (XpmNoMemory);
347 }
348 return (XpmSuccess);
349 }
350
351 static int
352 ScanOtherColors(display, colors, ncolors, pixels, mask, cpp, attributes)
353 Display *display;
354 XpmColor *colors;
355 int ncolors;
356 Pixel *pixels;
357 unsigned int mask;
358 unsigned int cpp;
359 XpmAttributes *attributes;
360 {
361 /* variables stored in the XpmAttributes structure */
362 Colormap colormap;
363 char *rgb_fname;
364
365 xpmRgbName *rgbn = NULL;
366
367 int rgbn_max = 0;
368 unsigned int i, j, c, i2;
369 XpmColor *color;
370 XColor *xcolors = NULL, *xcolor;
371 char *colorname, *s;
372 XpmColor *colorTable, **oldColorTable = NULL;
373 unsigned int ancolors = 0;
374 Pixel *apixels;
375 unsigned int mask_pixel;
376 Bool found;
377
378 /* retrieve information from the XpmAttributes */
379 if (attributes && (attributes->valuemask & XpmColormap))
380 colormap = attributes->colormap;
381 else
382 colormap = XDefaultColormap(display, XDefaultScreen(display));
383 if (attributes && (attributes->valuemask & XpmRgbFilename))
384 rgb_fname = attributes->rgb_fname;
385 else
386 rgb_fname = NULL;
387
388 /* start from the right element */
389 if (mask) {
390 colors++;
391 ncolors--;
392 pixels++;
393 }
394
395 /* first get character strings and rgb values */
396 xcolors = (XColor *) XpmMalloc(sizeof(XColor) * ncolors);
397 if (!xcolors)
398 return (XpmNoMemory);
399
400 for (i = 0, i2 = mask, color = colors, xcolor = xcolors;
401 i < ncolors; i++, i2++, color++, xcolor++, pixels++) {
402
403 if (!(s = color->string = (char *) XpmMalloc(cpp + 1))) {
404 XpmFree(xcolors);
405 return (XpmNoMemory);
406 }
407 *s++ = printable[c = i2 % MAXPRINTABLE];
408 for (j = 1; j < cpp; j++, s++)
409 *s = printable[c = ((i2 - c) / MAXPRINTABLE) % MAXPRINTABLE];
410 *s = '\0';
411
412 xcolor->pixel = *pixels;
413 }
414 XQueryColors(display, colormap, xcolors, ncolors);
415
416 rgbn_max = xpmReadRgbNames(NULL, NULL);
417
418 if (attributes && attributes->valuemask & XpmColorTable) {
419 colorTable = attributes->colorTable;
420 ancolors = attributes->ncolors;
421 apixels = attributes->pixels;
422 mask_pixel = attributes->mask_pixel;
423 }
424 /* 3.2 backward compatibility code */
425 else if (attributes && attributes->valuemask & XpmInfos) {
426 oldColorTable = (XpmColor **) attributes->colorTable;
427 ancolors = attributes->ncolors;
428 apixels = attributes->pixels;
429 mask_pixel = attributes->mask_pixel;
430 }
431 /* end 3.2 bc */
432
433 for (i = 0, color = colors, xcolor = xcolors; i < ncolors;
434 i++, color++, xcolor++) {
435
436 /* look for related info from the attributes if any */
437 found = False;
438 if (ancolors) {
439 unsigned int offset = 0;
440
441 for (j = 0; j < ancolors; j++) {
442 if (j == mask_pixel) {
443 offset = 1;
444 continue;
445 }
446 if (IS_EQUAL_PIXEL( apixels[j - offset] , xcolor->pixel) )
447 break;
448 }
449 if (j != ancolors) {
450 unsigned int key;
451 char **defaults = (char **) color;
452 char **adefaults;
453
454 /* 3.2 backward compatibility code */
455 if (oldColorTable)
456 adefaults = (char **) oldColorTable[j];
457 else
458 /* end 3.2 bc */
459 adefaults = (char **) (colorTable + j);
460
461 found = True;
462 for (key = 1; key <= NKEYS; key++) {
463 if (s = adefaults[key])
464 defaults[key] = (char *) xpmstrdup(s);
465 }
466 }
467 }
468 if (!found) {
469 /* if nothing found look for a color name */
470 colorname = NULL;
471 if (rgbn_max)
472 colorname = xpmGetRgbName(rgbn, rgbn_max, xcolor->red,
473 xcolor->green, xcolor->blue);
474 if (colorname)
475 color->c_color = (char *) xpmstrdup(colorname);
476 else {
477 /* at last store the rgb value */
478 char buf[BUFSIZ];
479 // sprintf(buf, "#%04X%04X%04X",
480 sprintf(buf, "#%02x%02x%02x",
481 xcolor->red, xcolor->green, xcolor->blue);
482
483 color->c_color = (char *) xpmstrdup(buf);
484 }
485 if (!color->c_color) {
486 XpmFree(xcolors);
487 xpmFreeRgbNames(rgbn, rgbn_max);
488 return (XpmNoMemory);
489 }
490 }
491 }
492
493 XpmFree(xcolors);
494 xpmFreeRgbNames(rgbn, rgbn_max);
495 return (XpmSuccess);
496 }
497
498
499 static int
500 PlatformGetImagePixels(display, image, width, height, pmap, storeFunc)
501 Display *display;
502 XImage *image;
503 unsigned int width;
504 unsigned int height;
505 PixelsMap *pmap;
506 int (*storeFunc) ();
507 {
508 #if FOR_MSW
509 unsigned int *iptr;
510 unsigned int x, y;
511 Pixel pixel;
512
513 iptr = pmap->pixelindex;
514
515 SelectObject(*display, image->bitmap);
516 for (y = 0; y < height; y++) {
517 for (x = 0; x < width; x++, iptr++) {
518 pixel = GetPixel(*display, x, y);
519 if ((*storeFunc) (pixel, pmap, iptr))
520 return (XpmNoMemory);
521 }
522 }
523 #elif macintosh
524 #endif
525 return (XpmSuccess);
526 }