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 array *
32 * Developed by Arnaud Le Hors *
33 \*****************************************************************************/
35 /* October 2004, source code review by Thomas Biege <thomas@suse.de> */
42 LFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size,
43 XpmColor *colors, unsigned int ncolors,
46 LFUNC(CreatePixels, void, (char **dataptr, unsigned int data_size,
48 unsigned int height, unsigned int cpp,
49 unsigned int *pixels, XpmColor *colors));
51 LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num,
52 unsigned int *ext_size,
53 unsigned int *ext_nlines));
55 LFUNC(CreateExtensions, void, (char **dataptr, unsigned int data_size,
57 XpmExtension *ext, unsigned int num,
58 unsigned int ext_nlines));
61 XpmCreateDataFromImage(
66 XpmAttributes *attributes)
72 /* initialize return value */
76 /* create an XpmImage from the image */
77 ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage,
78 &xpmimage, attributes);
79 if (ErrorStatus != XpmSuccess)
82 /* create the data from the XpmImage */
84 xpmSetInfo(&info, attributes);
85 ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info);
87 ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL);
89 /* free the XpmImage */
90 XpmFreeXpmImage(&xpmimage);
96 #define RETURN(status) \
99 ErrorStatus = status; \
104 XpmCreateDataFromXpmImage(
109 /* calculation variables */
112 char **header = NULL, **data, **sptr, **sptr2, *s;
113 unsigned int header_size, header_nlines;
114 unsigned int data_size, data_nlines;
115 unsigned int extensions = 0, ext_size = 0, ext_nlines = 0;
116 unsigned int offset, l, n;
120 extensions = info && (info->valuemask & XpmExtensions)
121 && info->nextensions;
123 /* compute the number of extensions lines and size */
125 CountExtensions(info->extensions, info->nextensions,
126 &ext_size, &ext_nlines);
129 * alloc a temporary array of char pointer for the header section which
130 * is the hints line + the color table lines
132 header_nlines = 1 + image->ncolors; /* this may wrap and/or become 0 */
134 /* 2nd check superfluous if we do not need header_nlines any further */
135 if(header_nlines <= image->ncolors ||
136 header_nlines >= UINT_MAX / sizeof(char *))
139 header_size = sizeof(char *) * header_nlines;
140 if (header_size >= UINT_MAX / sizeof(char *))
141 return (XpmNoMemory);
142 header = (char **) XpmCalloc(header_size, sizeof(char *)); /* can we trust image->ncolors */
144 return (XpmNoMemory);
146 /* print the hints line */
151 sprintf(s, "%d %d %d %d", image->width, image->height,
152 image->ncolors, image->cpp);
157 if (info && (info->valuemask & XpmHotspot)) {
161 sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot);
167 strcpy(s, " XPMEXT");
171 *header = (char *) XpmMalloc(l);
175 strcpy(*header, buf);
178 ErrorStatus = CreateColors(header + 1, &header_size,
179 image->colorTable, image->ncolors, image->cpp);
181 if (ErrorStatus != XpmSuccess)
184 /* now we know the size needed, alloc the data and copy the header lines */
185 offset = image->width * image->cpp + 1;
187 if(offset <= image->width || offset <= image->cpp)
190 if( (image->height + ext_nlines) >= UINT_MAX / sizeof(char *))
192 data_size = (image->height + ext_nlines) * sizeof(char *);
194 if (image->height > UINT_MAX / offset ||
195 image->height * offset > UINT_MAX - data_size)
197 data_size += image->height * offset;
199 if( (header_size + ext_size) >= (UINT_MAX - data_size) )
201 data_size += header_size + ext_size;
203 data = (char **) XpmMalloc(data_size);
207 data_nlines = header_nlines + image->height + ext_nlines;
208 *data = (char *) (data + data_nlines);
210 /* can header have less elements then n suggests? */
212 for (l = 0, sptr = data, sptr2 = header; l <= n && sptr && sptr2; l++, sptr++, sptr2++) {
213 strcpy(*sptr, *sptr2);
214 *(sptr + 1) = *sptr + strlen(*sptr2) + 1;
218 data[header_nlines] = (char *) data + header_size
219 + (image->height + ext_nlines) * sizeof(char *);
221 CreatePixels(data + header_nlines, data_size-header_nlines, image->width, image->height,
222 image->cpp, image->data, image->colorTable);
224 /* print extensions */
226 CreateExtensions(data + header_nlines + image->height - 1,
227 data_size - header_nlines - image->height + 1, offset,
228 info->extensions, info->nextensions,
232 ErrorStatus = XpmSuccess;
234 /* exit point, free only locally allocated variables */
237 for (l = 0; l < header_nlines; l++)
248 unsigned int *data_size,
250 unsigned int ncolors,
254 unsigned int a, key, l;
258 /* can ncolors be trusted here? */
259 for (a = 0; a < ncolors; a++, colors++, dataptr++) {
261 defaults = (char **) colors;
262 if(sizeof(buf) <= cpp)
264 strncpy(buf, *defaults++, cpp);
267 if(sizeof(buf) <= (s-buf))
270 for (key = 1; key <= NKEYS; key++, defaults++) {
271 if ((s2 = *defaults)) {
275 /* assume C99 compliance */
276 snprintf(s, sizeof(buf)-(s-buf), "\t%s %s", xpmColorKeys[key - 1], s2);
280 /* does s point out-of-bounds? */
281 if(sizeof(buf) < (s-buf))
285 /* what about using strdup()? */
287 s = (char *) XpmMalloc(l);
289 return (XpmNoMemory);
291 *dataptr = strcpy(s, buf);
299 unsigned int data_size,
303 unsigned int *pixels,
307 unsigned int x, y, h, offset;
314 offset = width * cpp + 1;
316 if(offset <= width || offset <= cpp)
320 for (y = 0; y < h; y++, dataptr++) {
322 /* why trust width? */
323 for (x = 0; x < width; x++, pixels++) {
324 if(cpp > (data_size - (s - *dataptr)))
326 strncpy(s, colors[*pixels].string, cpp); /* why trust pixel? */
330 if(offset > data_size)
332 *(dataptr + 1) = *dataptr + offset;
334 /* duplicate some code to avoid a test in the loop */
336 /* why trust width? */
337 for (x = 0; x < width; x++, pixels++) {
338 if(cpp > data_size - (s - *dataptr))
340 strncpy(s, colors[*pixels].string, cpp); /* why should we trust *pixel? */
350 unsigned int *ext_size,
351 unsigned int *ext_nlines)
353 unsigned int x, y, a, size, nlines;
358 for (x = 0; x < num; x++, ext++) {
360 nlines += ext->nlines + 1;
361 /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */
362 size += strlen(ext->name) + 8;
364 for (y = 0, line = ext->lines; y < a; y++, line++)
365 size += strlen(*line) + 1;
367 /* 10 and 1 are for the ending "XPMENDEXT" */
368 *ext_size = size + 10;
369 *ext_nlines = nlines + 1;
375 unsigned int data_size,
379 unsigned int ext_nlines)
381 unsigned int x, y, a, b;
384 *(dataptr + 1) = *dataptr + offset;
387 for (x = 0; x < num; x++, ext++) {
388 snprintf(*dataptr, data_size, "XPMEXT %s", ext->name);
391 *(dataptr + 1) = *dataptr + strlen(ext->name) + 8;
393 b = ext->nlines; /* can we trust these values? */
394 for (y = 0, line = ext->lines; y < b; y++, line++) {
395 strcpy(*dataptr, *line);
398 *(dataptr + 1) = *dataptr + strlen(*line) + 1;
402 strcpy(*dataptr, "XPMENDEXT");