2 * Copyright (C) 1989-95 GROUPE BULL
4 * Permission is hereby granted, free of charge, to any person obtaining a copy
5 * of this software and associated documentation files (the "Software"), to
6 * deal in the Software without restriction, including without limitation the
7 * rights to use, copy, modify, merge, publish, distribute, sublicense, and/or
8 * sell copies of the Software, and to permit persons to whom the Software is
9 * furnished to do so, subject to the following conditions:
11 * The above copyright notice and this permission notice shall be included in
12 * all copies or substantial portions of the Software.
14 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
17 * GROUPE BULL BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
18 * AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
19 * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21 * Except as contained in this notice, the name of GROUPE BULL shall not be
22 * used in advertising or otherwise to promote the sale, use or other dealings
23 * in this Software without prior written authorization from GROUPE BULL.
26 /*****************************************************************************\
30 * Scan an image and possibly its mask and create an XPM buffer *
32 * Developed by Arnaud Le Hors *
33 \*****************************************************************************/
35 /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
42 LFUNC(WriteColors, int, (char **dataptr, unsigned int *data_size,
43 unsigned int *used_size, XpmColor *colors,
44 unsigned int ncolors, unsigned int cpp));
46 LFUNC(WritePixels, void, (char *dataptr, unsigned int data_size,
47 unsigned int *used_size,
48 unsigned int width, unsigned int height,
49 unsigned int cpp, unsigned int *pixels,
52 LFUNC(WriteExtensions, void, (char *dataptr, unsigned int data_size,
53 unsigned int *used_size,
54 XpmExtension *ext, unsigned int num));
56 LFUNC(ExtensionsSize, unsigned int, (XpmExtension *ext, unsigned int num));
57 LFUNC(CommentsSize, int, (XpmInfo *info));
60 XpmCreateBufferFromImage(
65 XpmAttributes *attributes)
71 /* initialize return value */
73 *buffer_return = NULL;
75 /* create an XpmImage from the image */
76 ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
77 &xpmimage, attributes);
78 if (ErrorStatus != XpmSuccess)
81 /* create the buffer from the XpmImage */
83 xpmSetInfo(&info, attributes);
85 XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, &info);
88 XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, NULL);
90 /* free the XpmImage */
91 XpmFreeXpmImage(&xpmimage);
98 #define RETURN(status) \
101 ErrorStatus = status; \
106 XpmCreateBufferFromXpmImage(
107 char **buffer_return,
111 /* calculation variables */
114 unsigned int cmts, extensions, ext_size = 0;
115 unsigned int l, cmt_size = 0;
116 char *ptr = NULL, *p;
117 unsigned int ptr_size, used_size, tmp;
119 *buffer_return = NULL;
121 cmts = info && (info->valuemask & XpmComments);
122 extensions = info && (info->valuemask & XpmExtensions)
123 && info->nextensions;
125 /* compute the extensions and comments size */
127 ext_size = ExtensionsSize(info->extensions, info->nextensions);
129 cmt_size = CommentsSize(info);
131 /* write the header line */
135 sprintf(buf, "/* XPM */\nstatic char * image_name[] = {\n");
137 used_size = strlen(buf);
139 ptr_size = used_size + ext_size + cmt_size + 1; /* ptr_size can't be 0 */
140 if(ptr_size <= used_size ||
141 ptr_size <= ext_size ||
142 ptr_size <= cmt_size)
146 ptr = (char *) XpmMalloc(ptr_size);
151 /* write the values line */
152 if (cmts && info->hints_cmt) {
156 snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->hints_cmt);
158 used_size += strlen(info->hints_cmt) + 5;
164 sprintf(buf, "\"%d %d %d %d", image->width, image->height,
165 image->ncolors, image->cpp);
170 if (info && (info->valuemask & XpmHotspot)) {
174 snprintf(buf + l, sizeof(buf)-l, " %d %d", info->x_hotspot, info->y_hotspot);
183 sprintf(buf + l, " XPMEXT");
191 sprintf(buf + l, "\",\n");
198 p = (char *) XpmRealloc(ptr, ptr_size);
202 strcpy(ptr + used_size, buf);
206 if (cmts && info->colors_cmt) {
210 snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->colors_cmt);
212 used_size += strlen(info->colors_cmt) + 5;
215 ErrorStatus = WriteColors(&ptr, &ptr_size, &used_size,
216 image->colorTable, image->ncolors, image->cpp);
218 if (ErrorStatus != XpmSuccess)
222 * now we know the exact size we need, realloc the data
223 * 4 = 1 (for '"') + 3 (for '",\n')
224 * 1 = - 2 (because the last line does not end with ',\n') + 3 (for '};\n')
226 if(image->width > UINT_MAX / image->cpp ||
227 (tmp = image->width * image->cpp + 4) <= 4 ||
228 image->height > UINT_MAX / tmp ||
229 (tmp = image->height * tmp + 1) <= 1 ||
230 (ptr_size += tmp) <= tmp)
233 p = (char *) XpmRealloc(ptr, ptr_size);
239 if (cmts && info->pixels_cmt) {
243 snprintf(ptr + used_size, ptr_size-used_size, "/*%s*/\n", info->pixels_cmt);
245 used_size += strlen(info->pixels_cmt) + 5;
248 WritePixels(ptr + used_size, ptr_size - used_size, &used_size, image->width, image->height,
249 image->cpp, image->data, image->colorTable);
251 /* print extensions */
253 WriteExtensions(ptr + used_size, ptr_size-used_size, &used_size,
254 info->extensions, info->nextensions);
256 /* close the array */
257 strcpy(ptr + used_size, "};\n");
259 *buffer_return = ptr;
263 /* exit point in case of error, free only locally allocated variables */
267 return (ErrorStatus);
274 unsigned int *data_size,
275 unsigned int *used_size,
277 unsigned int ncolors,
280 char buf[BUFSIZ] = {0};
281 unsigned int a, key, l;
286 for (a = 0; a < ncolors; a++, colors++) {
288 defaults = (char **) colors;
290 if(cpp > (sizeof(buf) - (s-buf)))
292 strncpy(s, *defaults++, cpp);
295 for (key = 1; key <= NKEYS; key++, defaults++) {
296 if ((s2 = *defaults)) {
300 /* assume C99 compliance */
301 snprintf(s, sizeof(buf) - (s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
305 /* now let's check if s points out-of-bounds */
306 if((s-buf) > sizeof(buf))
310 if(sizeof(buf) - (s-buf) < 4)
314 if( *data_size >= UINT_MAX-l ||
315 *data_size + l <= *used_size ||
316 (*data_size + l - *used_size) <= sizeof(buf))
318 s = (char *) XpmRealloc(*dataptr, *data_size + l);
320 return (XpmNoMemory);
322 strcpy(s + *used_size, buf);
332 unsigned int data_size,
333 unsigned int *used_size,
337 unsigned int *pixels,
341 unsigned int x, y, h;
347 for (y = 0; y < h; y++) {
349 for (x = 0; x < width; x++, pixels++) {
350 if(cpp >= (data_size - (s-dataptr)))
352 strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? :-\ */
355 if((data_size - (s-dataptr)) < 4)
360 /* duplicate some code to avoid a test in the loop */
362 for (x = 0; x < width; x++, pixels++) {
363 if(cpp >= (data_size - (s-dataptr)))
365 strncpy(s, colors[*pixels].string, cpp); /* how can we trust *pixels? */
369 *used_size += s - dataptr;
377 unsigned int x, y, a, size;
383 for (x = 0; x < num; x++, ext++) {
384 /* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */
385 size += strlen(ext->name) + 11;
386 a = ext->nlines; /* how can we trust ext->nlines to be not out-of-bounds? */
387 for (y = 0, line = ext->lines; y < a; y++, line++)
388 /* 4 = 3 (for ',\n"') + 1 (for '"') */
389 size += strlen(*line) + 4;
391 /* 13 is for ',\n"XPMENDEXT"' */
392 if(size > UINT_MAX - 13) /* unlikely */
400 unsigned int data_size,
401 unsigned int *used_size,
405 unsigned int x, y, a;
409 for (x = 0; x < num; x++, ext++) {
413 snprintf(s, data_size - (s-dataptr), ",\n\"XPMEXT %s\"", ext->name);
415 s += strlen(ext->name) + 11;
418 for (y = 0, line = ext->lines; y < a; y++, line++) {
422 snprintf(s, data_size - (s-dataptr), ",\n\"%s\"", *line);
424 s += strlen(*line) + 4;
428 strncpy(s, ",\n\"XPMENDEXT\"", data_size - (s-dataptr)-1);
429 *used_size += s - dataptr + 13;
433 CommentsSize(XpmInfo *info)
437 /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */
438 /* wrap possible but *very* unlikely */
440 size += 5 + strlen(info->hints_cmt);
442 if (info->colors_cmt)
443 size += 5 + strlen(info->colors_cmt);
445 if (info->pixels_cmt)
446 size += 5 + strlen(info->pixels_cmt);