]>
Commit | Line | Data |
---|---|---|
cfbe03c9 JS |
1 | /* |
2 | * Copyright (C) 1989-94 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 | * XpmCrBufFrI.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 | ||
35 | #include "xpm34p.h" | |
36 | #ifdef VMS | |
37 | #include "sys$library:string.h" | |
38 | #else | |
39 | #if defined(SYSV) || defined(SVR4) | |
40 | #include <string.h> | |
41 | #else | |
42 | #include <strings.h> | |
43 | #endif | |
44 | #endif | |
45 | ||
46 | LFUNC(WriteColors, int, (char **dataptr, unsigned int *data_size, | |
47 | unsigned int *used_size, XpmColor *colors, | |
48 | unsigned int ncolors, unsigned int cpp)); | |
49 | ||
50 | LFUNC(WritePixels, void, (char *dataptr, unsigned int *used_size, | |
51 | unsigned int width, unsigned int height, | |
52 | unsigned int cpp, unsigned int *pixels, | |
53 | XpmColor *colors)); | |
54 | ||
55 | LFUNC(WriteExtensions, void, (char *dataptr, unsigned int *used_size, | |
56 | XpmExtension *ext, unsigned int num)); | |
57 | ||
58 | LFUNC(ExtensionsSize, int, (XpmExtension *ext, unsigned int num)); | |
59 | LFUNC(CommentsSize, int, (XpmInfo *info)); | |
60 | ||
61 | int | |
62 | XpmCreateBufferFromImage(Display *display, char **buffer_return, XImage *image, | |
63 | XImage *shapeimage, XpmAttributes *attributes) | |
64 | { | |
65 | XpmImage xpmimage; | |
66 | XpmInfo info; | |
67 | int ErrorStatus; | |
68 | ||
69 | /* initialize return value */ | |
70 | if (buffer_return) | |
71 | *buffer_return = NULL; | |
72 | ||
73 | /* create an XpmImage from the image */ | |
74 | ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, | |
75 | &xpmimage, attributes); | |
76 | if (ErrorStatus != XpmSuccess) | |
77 | return (ErrorStatus); | |
78 | ||
79 | /* create the buffer from the XpmImage */ | |
80 | if (attributes) { | |
81 | xpmSetInfo(&info, attributes); | |
82 | ErrorStatus = | |
83 | XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, &info); | |
84 | } else | |
85 | ErrorStatus = | |
86 | XpmCreateBufferFromXpmImage(buffer_return, &xpmimage, NULL); | |
87 | ||
88 | /* free the XpmImage */ | |
89 | XpmFreeXpmImage(&xpmimage); | |
90 | ||
91 | return (ErrorStatus); | |
92 | } | |
93 | ||
94 | ||
95 | #undef RETURN | |
96 | #define RETURN(status) \ | |
97 | { \ | |
98 | if (ptr) \ | |
99 | XpmFree(ptr); \ | |
100 | return(status); \ | |
101 | } | |
102 | ||
103 | int | |
104 | XpmCreateBufferFromXpmImage(char **buffer_return, XpmImage *image, XpmInfo *info) | |
105 | { | |
106 | /* calculation variables */ | |
107 | int ErrorStatus; | |
108 | char buf[BUFSIZ]; | |
109 | unsigned int cmts, extensions, ext_size = 0; | |
110 | unsigned int l, cmt_size = 0; | |
111 | char *ptr = NULL, *p; | |
112 | unsigned int ptr_size, used_size; | |
113 | ||
114 | *buffer_return = NULL; | |
115 | ||
116 | cmts = info && (info->valuemask & XpmComments); | |
117 | extensions = info && (info->valuemask & XpmExtensions) | |
118 | && info->nextensions; | |
119 | ||
120 | /* compute the extensions and comments size */ | |
121 | if (extensions) | |
122 | ext_size = ExtensionsSize(info->extensions, info->nextensions); | |
123 | if (cmts) | |
124 | cmt_size = CommentsSize(info); | |
125 | ||
126 | /* write the header line */ | |
127 | sprintf(buf, "/* XPM */\nstatic char * image_name[] = {\n"); | |
128 | used_size = strlen(buf); | |
129 | ptr_size = used_size + ext_size + cmt_size + 1; | |
130 | ptr = (char *) XpmMalloc(ptr_size); | |
131 | if (!ptr) | |
132 | return XpmNoMemory; | |
133 | strcpy(ptr, buf); | |
134 | ||
135 | /* write the values line */ | |
136 | if (cmts && info->hints_cmt) { | |
137 | sprintf(ptr + used_size, "/*%s*/\n", info->hints_cmt); | |
138 | used_size += strlen(info->hints_cmt) + 5; | |
139 | } | |
140 | sprintf(buf, "\"%d %d %d %d", image->width, image->height, | |
141 | image->ncolors, image->cpp); | |
142 | l = strlen(buf); | |
143 | ||
144 | if (info && (info->valuemask & XpmHotspot)) { | |
145 | sprintf(buf + l, " %d %d", info->x_hotspot, info->y_hotspot); | |
146 | l = strlen(buf); | |
147 | } | |
148 | if (extensions) { | |
149 | sprintf(buf + l, " XPMEXT"); | |
150 | l = strlen(buf); | |
151 | } | |
152 | sprintf(buf + l, "\",\n"); | |
153 | l = strlen(buf); | |
154 | ptr_size += l; | |
155 | p = (char *) XpmRealloc(ptr, ptr_size); | |
156 | if (!p) | |
157 | RETURN(XpmNoMemory); | |
158 | ptr = p; | |
159 | strcpy(ptr + used_size, buf); | |
160 | used_size += l; | |
161 | ||
162 | /* write colors */ | |
163 | if (cmts && info->colors_cmt) { | |
164 | sprintf(ptr + used_size, "/*%s*/\n", info->colors_cmt); | |
165 | used_size += strlen(info->colors_cmt) + 5; | |
166 | } | |
167 | ErrorStatus = WriteColors(&ptr, &ptr_size, &used_size, | |
168 | image->colorTable, image->ncolors, image->cpp); | |
169 | ||
170 | if (ErrorStatus != XpmSuccess) | |
171 | RETURN(ErrorStatus); | |
172 | ||
173 | /* | |
174 | * now we know the exact size we needed, realloc the data 4 = 1 (for | |
175 | * '"') + 3 (for '",\n') 1 = - 2 is because the last line does not end | |
176 | * with ',\n' + 3 (for '};\n') | |
177 | */ | |
178 | ptr_size += image->height * (image->width * image->cpp + 4) + 1; | |
179 | ||
180 | p = (char *) XpmRealloc(ptr, ptr_size); | |
181 | if (!p) | |
182 | RETURN(XpmNoMemory); | |
183 | ptr = p; | |
184 | ||
185 | /* print pixels */ | |
186 | if (cmts && info->pixels_cmt) { | |
187 | sprintf(ptr + used_size, "/*%s*/\n", info->pixels_cmt); | |
188 | used_size += strlen(info->pixels_cmt) + 5; | |
189 | } | |
190 | WritePixels(ptr + used_size, &used_size, image->width, image->height, | |
191 | image->cpp, image->data, image->colorTable); | |
192 | ||
193 | /* print extensions */ | |
194 | if (extensions) | |
195 | WriteExtensions(ptr + used_size, &used_size, | |
196 | info->extensions, info->nextensions); | |
197 | ||
198 | /* close the array */ | |
199 | sprintf(ptr + used_size, "};\n"); | |
200 | ||
201 | *buffer_return = ptr; | |
202 | ||
203 | return (XpmSuccess); | |
204 | } | |
205 | ||
206 | static int | |
207 | WriteColors(char **dataptr, unsigned int *data_size, unsigned int *used_size, | |
208 | XpmColor *colors, unsigned int ncolors, unsigned int cpp) | |
209 | { | |
210 | char buf[BUFSIZ]; | |
211 | unsigned int a, key, l; | |
212 | char *s, *s2; | |
213 | char **defaults; | |
214 | ||
215 | *buf = '"'; | |
216 | for (a = 0; a < ncolors; a++, colors++) { | |
217 | ||
218 | defaults = (char **) colors; | |
219 | s = buf + 1; | |
220 | strncpy(s, *defaults++, cpp); | |
221 | s += cpp; | |
222 | ||
223 | for (key = 1; key <= NKEYS; key++, defaults++) { | |
224 | if (s2 = *defaults) { | |
225 | sprintf(s, "\t%s %s", xpmColorKeys[key - 1], s2); | |
226 | s += strlen(s); | |
227 | } | |
228 | } | |
229 | strcpy(s, "\",\n"); | |
230 | l = strlen(buf); | |
231 | s = (char *) XpmRealloc(*dataptr, *data_size + l); | |
232 | if (!s) | |
233 | return (XpmNoMemory); | |
234 | *data_size += l; | |
235 | strcpy(s + *used_size, buf); | |
236 | *used_size += l; | |
237 | *dataptr = s; | |
238 | } | |
239 | return (XpmSuccess); | |
240 | } | |
241 | ||
242 | static void | |
243 | WritePixels(char *dataptr, unsigned int *used_size, unsigned int width, unsigned int height, | |
244 | unsigned int cpp, unsigned int *pixels, XpmColor *colors) | |
245 | { | |
246 | char *s = dataptr; | |
247 | unsigned int x, y, h; | |
248 | ||
249 | h = height - 1; | |
250 | for (y = 0; y < h; y++) { | |
251 | *s++ = '"'; | |
252 | for (x = 0; x < width; x++, pixels++) { | |
253 | strncpy(s, colors[*pixels].string, cpp); | |
254 | s += cpp; | |
255 | } | |
256 | strcpy(s, "\",\n"); | |
257 | s += 3; | |
258 | } | |
259 | /* duplicate some code to avoid a test in the loop */ | |
260 | *s++ = '"'; | |
261 | for (x = 0; x < width; x++, pixels++) { | |
262 | strncpy(s, colors[*pixels].string, cpp); | |
263 | s += cpp; | |
264 | } | |
265 | *s++ = '"'; | |
266 | *used_size += s - dataptr; | |
267 | } | |
268 | ||
269 | static int | |
270 | ExtensionsSize(XpmExtension *ext, unsigned int num) | |
271 | { | |
272 | unsigned int x, y, a, size; | |
273 | char **line; | |
274 | ||
275 | size = 0; | |
276 | for (x = 0; x < num; x++, ext++) { | |
277 | /* 11 = 10 (for ',\n"XPMEXT ') + 1 (for '"') */ | |
278 | size += strlen(ext->name) + 11; | |
279 | a = ext->nlines; | |
280 | for (y = 0, line = ext->lines; y < a; y++, line++) | |
281 | /* 4 = 3 (for ',\n"') + 1 (for '"') */ | |
282 | size += strlen(*line) + 4; | |
283 | } | |
284 | /* 13 is for ',\n"XPMENDEXT"' */ | |
285 | return size + 13; | |
286 | } | |
287 | ||
288 | static void | |
289 | WriteExtensions(char *dataptr, unsigned int *used_size, XpmExtension *ext, unsigned int num) | |
290 | { | |
291 | unsigned int x, y, a; | |
292 | char **line; | |
293 | char *s = dataptr; | |
294 | ||
295 | for (x = 0; x < num; x++, ext++) { | |
296 | sprintf(s, ",\n\"XPMEXT %s\"", ext->name); | |
297 | s += strlen(ext->name) + 11; | |
298 | a = ext->nlines; | |
299 | for (y = 0, line = ext->lines; y < a; y++, line++) { | |
300 | sprintf(s, ",\n\"%s\"", *line); | |
301 | s += strlen(*line) + 4; | |
302 | } | |
303 | } | |
304 | strcpy(s, ",\n\"XPMENDEXT\""); | |
305 | *used_size += s - dataptr + 13; | |
306 | } | |
307 | ||
308 | static int | |
309 | CommentsSize(XpmInfo *info) | |
310 | { | |
311 | int size = 0; | |
312 | ||
313 | /* 5 = 2 (for "/_*") + 3 (for "*_/\n") */ | |
314 | if (info->hints_cmt) | |
315 | size += 5 + strlen(info->hints_cmt); | |
316 | ||
317 | if (info->colors_cmt) | |
318 | size += 5 + strlen(info->colors_cmt); | |
319 | ||
320 | if (info->pixels_cmt) | |
321 | size += 5 + strlen(info->pixels_cmt); | |
322 | ||
323 | return size; | |
324 | } |