]>
Commit | Line | Data |
---|---|---|
cfbe03c9 | 1 | /* |
e6ed776f | 2 | * Copyright (C) 1989-95 GROUPE BULL |
cfbe03c9 JS |
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 | /*****************************************************************************\ | |
e6ed776f | 27 | * CrBufFrI.c: * |
cfbe03c9 JS |
28 | * * |
29 | * XPM library * | |
30 | * Scan an image and possibly its mask and create an XPM buffer * | |
31 | * * | |
32 | * Developed by Arnaud Le Hors * | |
33 | \*****************************************************************************/ | |
34 | ||
e6ed776f | 35 | #include "XpmI.h" |
cfbe03c9 JS |
36 | |
37 | LFUNC(WriteColors, int, (char **dataptr, unsigned int *data_size, | |
38 | unsigned int *used_size, XpmColor *colors, | |
39 | unsigned int ncolors, unsigned int cpp)); | |
40 | ||
41 | LFUNC(WritePixels, void, (char *dataptr, unsigned int *used_size, | |
42 | unsigned int width, unsigned int height, | |
43 | unsigned int cpp, unsigned int *pixels, | |
44 | XpmColor *colors)); | |
45 | ||
46 | LFUNC(WriteExtensions, void, (char *dataptr, unsigned int *used_size, | |
47 | XpmExtension *ext, unsigned int num)); | |
48 | ||
49 | LFUNC(ExtensionsSize, int, (XpmExtension *ext, unsigned int num)); | |
50 | LFUNC(CommentsSize, int, (XpmInfo *info)); | |
51 | ||
52 | int | |
e6ed776f GRG |
53 | XpmCreateBufferFromImage(display, buffer_return, image, shapeimage, attributes) |
54 | Display *display; | |
55 | char **buffer_return; | |
56 | XImage *image; | |
57 | XImage *shapeimage; | |
58 | XpmAttributes *attributes; | |
cfbe03c9 JS |
59 | { |
60 | XpmImage xpmimage; | |
61 | XpmInfo info; | |
62 | int ErrorStatus; | |
63 | ||
64 | /* initialize return value */ | |
65 | if (buffer_return) | |
66 | *buffer_return = NULL; | |
67 | ||
68 | /* create an XpmImage from the image */ | |
69 | ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, | |
70 | &xpmimage, attributes); | |
71 | if (ErrorStatus != XpmSuccess) | |
72 | return (ErrorStatus); | |
73 | ||
74 | /* create the buffer from the XpmImage */ | |
75 | if (attributes) { | |
76 | xpmSetInfo(&info, attributes); | |
77 | ErrorStatus = | |
78 | XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, &info); | |
79 | } else | |
80 | ErrorStatus = | |
81 | XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, NULL); | |
82 | ||
83 | /* free the XpmImage */ | |
84 | XpmFreeXpmImage(&xpmimage); | |
85 | ||
86 | return (ErrorStatus); | |
87 | } | |
88 | ||
89 | ||
90 | #undef RETURN | |
91 | #define RETURN(status) \ | |
92 | { \ | |
e6ed776f GRG |
93 | ErrorStatus = status; \ |
94 | goto error; \ | |
cfbe03c9 JS |
95 | } |
96 | ||
97 | int | |
e6ed776f GRG |
98 | XpmCreateBufferFromXpmImage(buffer_return, image, info) |
99 | char **buffer_return; | |
100 | XpmImage *image; | |
101 | XpmInfo *info; | |
cfbe03c9 JS |
102 | { |
103 | /* calculation variables */ | |
104 | int ErrorStatus; | |
105 | char buf[BUFSIZ]; | |
106 | unsigned int cmts, extensions, ext_size = 0; | |
107 | unsigned int l, cmt_size = 0; | |
108 | char *ptr = NULL, *p; | |
109 | unsigned int ptr_size, used_size; | |
110 | ||
111 | *buffer_return = NULL; | |
112 | ||
113 | cmts = info && (info->valuemask & XpmComments); | |
114 | extensions = info && (info->valuemask & XpmExtensions) | |
115 | && info->nextensions; | |
116 | ||
117 | /* compute the extensions and comments size */ | |
118 | if (extensions) | |
119 | ext_size = ExtensionsSize(info->extensions, info->nextensions); | |
120 | if (cmts) | |
121 | cmt_size = CommentsSize(info); | |
122 | ||
123 | /* write the header line */ | |
e6ed776f GRG |
124 | #ifndef VOID_SPRINTF |
125 | used_size = | |
126 | #endif | |
cfbe03c9 | 127 | sprintf(buf, "/* XPM */\nstatic char * image_name[] = {\n"); |
e6ed776f | 128 | #ifdef VOID_SPRINTF |
cfbe03c9 | 129 | used_size = strlen(buf); |
e6ed776f | 130 | #endif |
cfbe03c9 JS |
131 | ptr_size = used_size + ext_size + cmt_size + 1; |
132 | ptr = (char *) XpmMalloc(ptr_size); | |
133 | if (!ptr) | |
134 | return XpmNoMemory; | |
135 | strcpy(ptr, buf); | |
136 | ||
137 | /* write the values line */ | |
138 | if (cmts && info->hints_cmt) { | |
e6ed776f GRG |
139 | #ifndef VOID_SPRINTF |
140 | used_size += | |
141 | #endif | |
cfbe03c9 | 142 | sprintf(ptr + used_size, "/*%s*/\n", info->hints_cmt); |
e6ed776f | 143 | #ifdef VOID_SPRINTF |
cfbe03c9 | 144 | used_size += strlen(info->hints_cmt) + 5; |
e6ed776f | 145 | #endif |
cfbe03c9 | 146 | } |
e6ed776f GRG |
147 | #ifndef VOID_SPRINTF |
148 | l = | |
149 | #endif | |
cfbe03c9 JS |
150 | sprintf(buf, "\"%d %d %d %d", image->width, image->height, |
151 | image->ncolors, image->cpp); | |
e6ed776f | 152 | #ifdef VOID_SPRINTF |
cfbe03c9 | 153 | l = strlen(buf); |
e6ed776f | 154 | #endif |
cfbe03c9 JS |
155 | |
156 | if (info && (info->valuemask & XpmHotspot)) { | |
e6ed776f GRG |
157 | #ifndef VOID_SPRINTF |
158 | l += | |
159 | #endif | |
cfbe03c9 | 160 | sprintf(buf + l, " %d %d", info->x_hotspot, info->y_hotspot); |
e6ed776f | 161 | #ifdef VOID_SPRINTF |
cfbe03c9 | 162 | l = strlen(buf); |
e6ed776f | 163 | #endif |
cfbe03c9 JS |
164 | } |
165 | if (extensions) { | |
e6ed776f GRG |
166 | #ifndef VOID_SPRINTF |
167 | l += | |
168 | #endif | |
cfbe03c9 | 169 | sprintf(buf + l, " XPMEXT"); |
e6ed776f | 170 | #ifdef VOID_SPRINTF |
cfbe03c9 | 171 | l = strlen(buf); |
e6ed776f | 172 | #endif |
cfbe03c9 | 173 | } |
e6ed776f GRG |
174 | #ifndef VOID_SPRINTF |
175 | l += | |
176 | #endif | |
cfbe03c9 | 177 | sprintf(buf + l, "\",\n"); |
e6ed776f | 178 | #ifdef VOID_SPRINTF |
cfbe03c9 | 179 | l = strlen(buf); |
e6ed776f | 180 | #endif |
cfbe03c9 JS |
181 | ptr_size += l; |
182 | p = (char *) XpmRealloc(ptr, ptr_size); | |
183 | if (!p) | |
184 | RETURN(XpmNoMemory); | |
185 | ptr = p; | |
186 | strcpy(ptr + used_size, buf); | |
187 | used_size += l; | |
188 | ||
189 | /* write colors */ | |
190 | if (cmts && info->colors_cmt) { | |
e6ed776f GRG |
191 | #ifndef VOID_SPRINTF |
192 | used_size += | |
193 | #endif | |
cfbe03c9 | 194 | sprintf(ptr + used_size, "/*%s*/\n", info->colors_cmt); |
e6ed776f | 195 | #ifdef VOID_SPRINTF |
cfbe03c9 | 196 | used_size += strlen(info->colors_cmt) + 5; |
e6ed776f | 197 | #endif |
cfbe03c9 JS |
198 | } |
199 | ErrorStatus = WriteColors(&ptr, &ptr_size, &used_size, | |
200 | image->colorTable, image->ncolors, image->cpp); | |
201 | ||
202 | if (ErrorStatus != XpmSuccess) | |
203 | RETURN(ErrorStatus); | |
204 | ||
205 | /* | |
e6ed776f GRG |
206 | * now we know the exact size we need, realloc the data |
207 | * 4 = 1 (for '"') + 3 (for '",\n') | |
208 | * 1 = - 2 (because the last line does not end with ',\n') + 3 (for '};\n') | |
cfbe03c9 JS |
209 | */ |
210 | ptr_size += image->height * (image->width * image->cpp + 4) + 1; | |
211 | ||
212 | p = (char *) XpmRealloc(ptr, ptr_size); | |
213 | if (!p) | |
214 | RETURN(XpmNoMemory); | |
215 | ptr = p; | |
216 | ||
217 | /* print pixels */ | |
218 | if (cmts && info->pixels_cmt) { | |
e6ed776f GRG |
219 | #ifndef VOID_SPRINTF |
220 | used_size += | |
221 | #endif | |
cfbe03c9 | 222 | sprintf(ptr + used_size, "/*%s*/\n", info->pixels_cmt); |
e6ed776f | 223 | #ifdef VOID_SPRINTF |
cfbe03c9 | 224 | used_size += strlen(info->pixels_cmt) + 5; |
e6ed776f | 225 | #endif |
cfbe03c9 JS |
226 | } |
227 | WritePixels(ptr + used_size, &used_size, image->width, image->height, | |
228 | image->cpp, image->data, image->colorTable); | |
229 | ||
230 | /* print extensions */ | |
231 | if (extensions) | |
232 | WriteExtensions(ptr + used_size, &used_size, | |
233 | info->extensions, info->nextensions); | |
234 | ||
235 | /* close the array */ | |
e6ed776f | 236 | strcpy(ptr + used_size, "};\n"); |
cfbe03c9 JS |
237 | |
238 | *buffer_return = ptr; | |
239 | ||
240 | return (XpmSuccess); | |
e6ed776f GRG |
241 | |
242 | /* exit point in case of error, free only locally allocated variables */ | |
243 | error: | |
244 | if (ptr) | |
245 | XpmFree(ptr); | |
246 | return (ErrorStatus); | |
cfbe03c9 JS |
247 | } |
248 | ||
249 | static int | |
e6ed776f GRG |
250 | WriteColors(dataptr, data_size, used_size, colors, ncolors, cpp) |
251 | char **dataptr; | |
252 | unsigned int *data_size; | |
253 | unsigned int *used_size; | |
254 | XpmColor *colors; | |
255 | unsigned int ncolors; | |
256 | unsigned int cpp; | |
cfbe03c9 JS |
257 | { |
258 | char buf[BUFSIZ]; | |
259 | unsigned int a, key, l; | |
260 | char *s, *s2; | |
261 | char **defaults; | |
262 | ||
263 | *buf = '"'; | |
264 | for (a = 0; a < ncolors; a++, colors++) { | |
265 | ||
266 | defaults = (char **) colors; | |
267 | s = buf + 1; | |
268 | strncpy(s, *defaults++, cpp); | |
269 | s += cpp; | |
270 | ||
271 | for (key = 1; key <= NKEYS; key++, defaults++) { | |
272 | if (s2 = *defaults) { | |
e6ed776f GRG |
273 | #ifndef VOID_SPRINTF |
274 | s += | |
275 | #endif | |
cfbe03c9 | 276 | sprintf(s, "\t%s %s", xpmColorKeys[key - 1], s2); |
e6ed776f | 277 | #ifdef VOID_SPRINTF |
cfbe03c9 | 278 | s += strlen(s); |
e6ed776f | 279 | #endif |
cfbe03c9 JS |
280 | } |
281 | } | |
282 | strcpy(s, "\",\n"); | |
e6ed776f | 283 | l = s + 3 - buf; |
cfbe03c9 JS |
284 | s = (char *) XpmRealloc(*dataptr, *data_size + l); |
285 | if (!s) | |
286 | return (XpmNoMemory); | |
287 | *data_size += l; | |
288 | strcpy(s + *used_size, buf); | |
289 | *used_size += l; | |
290 | *dataptr = s; | |
291 | } | |
292 | return (XpmSuccess); | |
293 | } | |
294 | ||
295 | static void | |
e6ed776f GRG |
296 | WritePixels(dataptr, used_size, width, height, cpp, pixels, colors) |
297 | char *dataptr; | |
298 | unsigned int *used_size; | |
299 | unsigned int width; | |
300 | unsigned int height; | |
301 | unsigned int cpp; | |
302 | unsigned int *pixels; | |
303 | XpmColor *colors; | |
cfbe03c9 JS |
304 | { |
305 | char *s = dataptr; | |
306 | unsigned int x, y, h; | |
307 | ||
308 | h = height - 1; | |
309 | for (y = 0; y < h; y++) { | |
310 | *s++ = '"'; | |
311 | for (x = 0; x < width; x++, pixels++) { | |
312 | strncpy(s, colors[*pixels].string, cpp); | |
313 | s += cpp; | |
314 | } | |
315 | strcpy(s, "\",\n"); | |
316 | s += 3; | |
317 | } | |
318 | /* duplicate some code to avoid a test in the loop */ | |
319 | *s++ = '"'; | |
320 | for (x = 0; x < width; x++, pixels++) { | |
321 | strncpy(s, colors[*pixels].string, cpp); | |
322 | s += cpp; | |
323 | } | |
324 | *s++ = '"'; | |
325 | *used_size += s - dataptr; | |
326 | } | |
327 | ||
328 | static int | |
e6ed776f GRG |
329 | ExtensionsSize(ext, num) |
330 | XpmExtension *ext; | |
331 | unsigned int num; | |
cfbe03c9 JS |
332 | { |
333 | unsigned int x, y, a, size; | |
334 | char **line; | |
335 | ||
336 | size = 0; | |
337 | for (x = 0; x < num; x++, ext++) { | |
338 | /* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */ | |
339 | size += strlen(ext->name) + 11; | |
340 | a = ext->nlines; | |
341 | for (y = 0, line = ext->lines; y < a; y++, line++) | |
342 | /* 4 = 3 (for ',\n"') + 1 (for '"') */ | |
343 | size += strlen(*line) + 4; | |
344 | } | |
345 | /* 13 is for ',\n"XPMENDEXT"' */ | |
346 | return size + 13; | |
347 | } | |
348 | ||
349 | static void | |
e6ed776f GRG |
350 | WriteExtensions(dataptr, used_size, ext, num) |
351 | char *dataptr; | |
352 | unsigned int *used_size; | |
353 | XpmExtension *ext; | |
354 | unsigned int num; | |
cfbe03c9 JS |
355 | { |
356 | unsigned int x, y, a; | |
357 | char **line; | |
358 | char *s = dataptr; | |
359 | ||
360 | for (x = 0; x < num; x++, ext++) { | |
e6ed776f GRG |
361 | #ifndef VOID_SPRINTF |
362 | s += | |
363 | #endif | |
cfbe03c9 | 364 | sprintf(s, ",\n\"XPMEXT %s\"", ext->name); |
e6ed776f | 365 | #ifdef VOID_SPRINTF |
cfbe03c9 | 366 | s += strlen(ext->name) + 11; |
e6ed776f | 367 | #endif |
cfbe03c9 JS |
368 | a = ext->nlines; |
369 | for (y = 0, line = ext->lines; y < a; y++, line++) { | |
e6ed776f GRG |
370 | #ifndef VOID_SPRINTF |
371 | s += | |
372 | #endif | |
cfbe03c9 | 373 | sprintf(s, ",\n\"%s\"", *line); |
e6ed776f | 374 | #ifdef VOID_SPRINTF |
cfbe03c9 | 375 | s += strlen(*line) + 4; |
e6ed776f | 376 | #endif |
cfbe03c9 JS |
377 | } |
378 | } | |
379 | strcpy(s, ",\n\"XPMENDEXT\""); | |
380 | *used_size += s - dataptr + 13; | |
381 | } | |
382 | ||
383 | static int | |
e6ed776f GRG |
384 | CommentsSize(info) |
385 | XpmInfo *info; | |
cfbe03c9 JS |
386 | { |
387 | int size = 0; | |
388 | ||
389 | /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */ | |
390 | if (info->hints_cmt) | |
391 | size += 5 + strlen(info->hints_cmt); | |
392 | ||
393 | if (info->colors_cmt) | |
394 | size += 5 + strlen(info->colors_cmt); | |
395 | ||
396 | if (info->pixels_cmt) | |
397 | size += 5 + strlen(info->pixels_cmt); | |
398 | ||
399 | return size; | |
400 | } |