]>
Commit | Line | Data |
---|---|---|
0240e8b1 SC |
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 | * CrBufFrI.c: * | |
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 | ||
2f1ae414 | 35 | #include "XpmI.h" |
0240e8b1 SC |
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 | |
53 | XpmCreateBufferFromImage(display, buffer_return, image, shapeimage, attributes) | |
54 | Display *display; | |
55 | char **buffer_return; | |
56 | XImage *image; | |
57 | XImage *shapeimage; | |
58 | XpmAttributes *attributes; | |
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 | { \ | |
93 | ErrorStatus = status; \ | |
94 | goto error; \ | |
95 | } | |
96 | ||
97 | int | |
98 | XpmCreateBufferFromXpmImage(buffer_return, image, info) | |
99 | char **buffer_return; | |
100 | XpmImage *image; | |
101 | XpmInfo *info; | |
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 */ | |
124 | #ifndef VOID_SPRINTF | |
125 | used_size = | |
126 | #endif | |
127 | sprintf(buf, "/* XPM */\nstatic char * image_name[] = {\n"); | |
128 | #ifdef VOID_SPRINTF | |
129 | used_size = strlen(buf); | |
130 | #endif | |
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) { | |
139 | #ifndef VOID_SPRINTF | |
140 | used_size += | |
141 | #endif | |
142 | sprintf(ptr + used_size, "/*%s*/\n", info->hints_cmt); | |
143 | #ifdef VOID_SPRINTF | |
144 | used_size += strlen(info->hints_cmt) + 5; | |
145 | #endif | |
146 | } | |
147 | #ifndef VOID_SPRINTF | |
148 | l = | |
149 | #endif | |
150 | sprintf(buf, "\"%d %d %d %d", image->width, image->height, | |
151 | image->ncolors, image->cpp); | |
152 | #ifdef VOID_SPRINTF | |
153 | l = strlen(buf); | |
154 | #endif | |
155 | ||
156 | if (info && (info->valuemask & XpmHotspot)) { | |
157 | #ifndef VOID_SPRINTF | |
158 | l += | |
159 | #endif | |
160 | sprintf(buf + l, " %d %d", info->x_hotspot, info->y_hotspot); | |
161 | #ifdef VOID_SPRINTF | |
162 | l = strlen(buf); | |
163 | #endif | |
164 | } | |
165 | if (extensions) { | |
166 | #ifndef VOID_SPRINTF | |
167 | l += | |
168 | #endif | |
169 | sprintf(buf + l, " XPMEXT"); | |
170 | #ifdef VOID_SPRINTF | |
171 | l = strlen(buf); | |
172 | #endif | |
173 | } | |
174 | #ifndef VOID_SPRINTF | |
175 | l += | |
176 | #endif | |
177 | sprintf(buf + l, "\",\n"); | |
178 | #ifdef VOID_SPRINTF | |
179 | l = strlen(buf); | |
180 | #endif | |
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) { | |
191 | #ifndef VOID_SPRINTF | |
192 | used_size += | |
193 | #endif | |
194 | sprintf(ptr + used_size, "/*%s*/\n", info->colors_cmt); | |
195 | #ifdef VOID_SPRINTF | |
196 | used_size += strlen(info->colors_cmt) + 5; | |
197 | #endif | |
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 | /* | |
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') | |
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) { | |
219 | #ifndef VOID_SPRINTF | |
220 | used_size += | |
221 | #endif | |
222 | sprintf(ptr + used_size, "/*%s*/\n", info->pixels_cmt); | |
223 | #ifdef VOID_SPRINTF | |
224 | used_size += strlen(info->pixels_cmt) + 5; | |
225 | #endif | |
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 */ | |
236 | strcpy(ptr + used_size, "};\n"); | |
237 | ||
238 | *buffer_return = ptr; | |
239 | ||
240 | return (XpmSuccess); | |
241 | ||
242 | /* exit point in case of error, free only locally allocated variables */ | |
243 | error: | |
244 | if (ptr) | |
245 | XpmFree(ptr); | |
246 | return (ErrorStatus); | |
247 | } | |
248 | ||
249 | static int | |
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; | |
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)!=NULL) | |
273 | { | |
274 | #ifndef VOID_SPRINTF | |
275 | s += | |
276 | #endif | |
277 | sprintf(s, "\t%s %s", xpmColorKeys[key - 1], s2); | |
278 | #ifdef VOID_SPRINTF | |
279 | s += strlen(s); | |
280 | #endif | |
281 | } | |
282 | } | |
283 | strcpy(s, "\",\n"); | |
284 | l = s + 3 - buf; | |
285 | s = (char *) XpmRealloc(*dataptr, *data_size + l); | |
286 | if (!s) | |
287 | return (XpmNoMemory); | |
288 | *data_size += l; | |
289 | strcpy(s + *used_size, buf); | |
290 | *used_size += l; | |
291 | *dataptr = s; | |
292 | } | |
293 | return (XpmSuccess); | |
294 | } | |
295 | ||
296 | static void | |
297 | WritePixels(dataptr, used_size, width, height, cpp, pixels, colors) | |
298 | char *dataptr; | |
299 | unsigned int *used_size; | |
300 | unsigned int width; | |
301 | unsigned int height; | |
302 | unsigned int cpp; | |
303 | unsigned int *pixels; | |
304 | XpmColor *colors; | |
305 | { | |
306 | char *s = dataptr; | |
307 | unsigned int x, y, h; | |
308 | ||
309 | h = height - 1; | |
310 | for (y = 0; y < h; y++) { | |
311 | *s++ = '"'; | |
312 | for (x = 0; x < width; x++, pixels++) { | |
313 | strncpy(s, colors[*pixels].string, cpp); | |
314 | s += cpp; | |
315 | } | |
316 | strcpy(s, "\",\n"); | |
317 | s += 3; | |
318 | } | |
319 | /* duplicate some code to avoid a test in the loop */ | |
320 | *s++ = '"'; | |
321 | for (x = 0; x < width; x++, pixels++) { | |
322 | strncpy(s, colors[*pixels].string, cpp); | |
323 | s += cpp; | |
324 | } | |
325 | *s++ = '"'; | |
326 | *used_size += s - dataptr; | |
327 | } | |
328 | ||
329 | static int | |
330 | ExtensionsSize(ext, num) | |
331 | XpmExtension *ext; | |
332 | unsigned int num; | |
333 | { | |
334 | unsigned int x, y, a, size; | |
335 | char **line; | |
336 | ||
337 | size = 0; | |
338 | for (x = 0; x < num; x++, ext++) { | |
339 | /* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */ | |
340 | size += strlen(ext->name) + 11; | |
341 | a = ext->nlines; | |
342 | for (y = 0, line = ext->lines; y < a; y++, line++) | |
343 | /* 4 = 3 (for ',\n"') + 1 (for '"') */ | |
344 | size += strlen(*line) + 4; | |
345 | } | |
346 | /* 13 is for ',\n"XPMENDEXT"' */ | |
347 | return size + 13; | |
348 | } | |
349 | ||
350 | static void | |
351 | WriteExtensions(dataptr, used_size, ext, num) | |
352 | char *dataptr; | |
353 | unsigned int *used_size; | |
354 | XpmExtension *ext; | |
355 | unsigned int num; | |
356 | { | |
357 | unsigned int x, y, a; | |
358 | char **line; | |
359 | char *s = dataptr; | |
360 | ||
361 | for (x = 0; x < num; x++, ext++) { | |
362 | #ifndef VOID_SPRINTF | |
363 | s += | |
364 | #endif | |
365 | sprintf(s, ",\n\"XPMEXT %s\"", ext->name); | |
366 | #ifdef VOID_SPRINTF | |
367 | s += strlen(ext->name) + 11; | |
368 | #endif | |
369 | a = ext->nlines; | |
370 | for (y = 0, line = ext->lines; y < a; y++, line++) { | |
371 | #ifndef VOID_SPRINTF | |
372 | s += | |
373 | #endif | |
374 | sprintf(s, ",\n\"%s\"", *line); | |
375 | #ifdef VOID_SPRINTF | |
376 | s += strlen(*line) + 4; | |
377 | #endif | |
378 | } | |
379 | } | |
380 | strcpy(s, ",\n\"XPMENDEXT\""); | |
381 | *used_size += s - dataptr + 13; | |
382 | } | |
383 | ||
384 | static int | |
385 | CommentsSize(info) | |
386 | XpmInfo *info; | |
387 | { | |
388 | int size = 0; | |
389 | ||
390 | /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */ | |
391 | if (info->hints_cmt) | |
392 | size += 5 + strlen(info->hints_cmt); | |
393 | ||
394 | if (info->colors_cmt) | |
395 | size += 5 + strlen(info->colors_cmt); | |
396 | ||
397 | if (info->pixels_cmt) | |
398 | size += 5 + strlen(info->pixels_cmt); | |
399 | ||
400 | return size; | |
401 | } |