]>
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 | * CrDataFI.c: * | |
28 | * * | |
29 | * XPM library * | |
30 | * Scan an image and possibly its mask and create an XPM array * | |
31 | * * | |
32 | * Developed by Arnaud Le Hors * | |
33 | \*****************************************************************************/ | |
34 | ||
2f1ae414 | 35 | #include "XpmI.h" |
0240e8b1 SC |
36 | |
37 | LFUNC(CreateColors, int, (char **dataptr, unsigned int *data_size, | |
38 | XpmColor *colors, unsigned int ncolors, | |
39 | unsigned int cpp)); | |
40 | ||
41 | LFUNC(CreatePixels, void, (char **dataptr, unsigned int width, | |
42 | unsigned int height, unsigned int cpp, | |
43 | unsigned int *pixels, XpmColor *colors)); | |
44 | ||
45 | LFUNC(CountExtensions, void, (XpmExtension *ext, unsigned int num, | |
46 | unsigned int *ext_size, | |
47 | unsigned int *ext_nlines)); | |
48 | ||
49 | LFUNC(CreateExtensions, void, (char **dataptr, unsigned int offset, | |
50 | XpmExtension *ext, unsigned int num, | |
51 | unsigned int ext_nlines)); | |
52 | ||
53 | int | |
54 | XpmCreateDataFromImage(display, data_return, image, shapeimage, attributes) | |
55 | Display *display; | |
56 | char ***data_return; | |
57 | XImage *image; | |
58 | XImage *shapeimage; | |
59 | XpmAttributes *attributes; | |
60 | { | |
61 | XpmImage xpmimage; | |
62 | XpmInfo info; | |
63 | int ErrorStatus; | |
64 | ||
65 | /* initialize return value */ | |
66 | if (data_return) | |
67 | *data_return = NULL; | |
68 | ||
69 | /* create an XpmImage from the image */ | |
70 | ErrorStatus = XpmCreateXpmImageFromImage(display, image, shapeimage, | |
71 | &xpmimage, attributes); | |
72 | if (ErrorStatus != XpmSuccess) | |
73 | return (ErrorStatus); | |
74 | ||
75 | /* create the data from the XpmImage */ | |
76 | if (attributes) { | |
77 | xpmSetInfo(&info, attributes); | |
78 | ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, &info); | |
79 | } else | |
80 | ErrorStatus = XpmCreateDataFromXpmImage(data_return, &xpmimage, NULL); | |
81 | ||
82 | /* free the XpmImage */ | |
83 | XpmFreeXpmImage(&xpmimage); | |
84 | ||
85 | return (ErrorStatus); | |
86 | } | |
87 | ||
88 | #undef RETURN | |
89 | #define RETURN(status) \ | |
90 | { \ | |
91 | ErrorStatus = status; \ | |
92 | goto exit; \ | |
93 | } | |
94 | ||
95 | int | |
96 | XpmCreateDataFromXpmImage(data_return, image, info) | |
97 | char ***data_return; | |
98 | XpmImage *image; | |
99 | XpmInfo *info; | |
100 | { | |
101 | /* calculation variables */ | |
102 | int ErrorStatus; | |
103 | char buf[BUFSIZ]; | |
104 | char **header = NULL, **data, **sptr, **sptr2, *s; | |
105 | unsigned int header_size, header_nlines; | |
106 | unsigned int data_size, data_nlines; | |
107 | unsigned int extensions = 0, ext_size = 0, ext_nlines = 0; | |
108 | unsigned int offset, l, n; | |
109 | ||
110 | *data_return = NULL; | |
111 | ||
112 | extensions = info && (info->valuemask & XpmExtensions) | |
113 | && info->nextensions; | |
114 | ||
115 | /* compute the number of extensions lines and size */ | |
116 | if (extensions) | |
117 | CountExtensions(info->extensions, info->nextensions, | |
118 | &ext_size, &ext_nlines); | |
119 | ||
120 | /* | |
121 | * alloc a temporary array of char pointer for the header section which | |
122 | * is the hints line + the color table lines | |
123 | */ | |
124 | header_nlines = 1 + image->ncolors; | |
125 | header_size = sizeof(char *) * header_nlines; | |
126 | header = (char **) XpmCalloc(header_size, sizeof(char *)); | |
127 | if (!header) | |
128 | return (XpmNoMemory); | |
129 | ||
130 | /* print the hints line */ | |
131 | s = buf; | |
132 | #ifndef VOID_SPRINTF | |
133 | s += | |
134 | #endif | |
135 | sprintf(s, "%d %d %d %d", image->width, image->height, | |
136 | image->ncolors, image->cpp); | |
137 | #ifdef VOID_SPRINTF | |
138 | s += strlen(s); | |
139 | #endif | |
140 | ||
141 | if (info && (info->valuemask & XpmHotspot)) { | |
142 | #ifndef VOID_SPRINTF | |
143 | s += | |
144 | #endif | |
145 | sprintf(s, " %d %d", info->x_hotspot, info->y_hotspot); | |
146 | #ifdef VOID_SPRINTF | |
147 | s += strlen(s); | |
148 | #endif | |
149 | } | |
150 | if (extensions) { | |
151 | strcpy(s, " XPMEXT"); | |
152 | s += 7; | |
153 | } | |
154 | l = s - buf + 1; | |
155 | *header = (char *) XpmMalloc(l); | |
156 | if (!*header) | |
157 | RETURN(XpmNoMemory); | |
158 | header_size += l; | |
159 | strcpy(*header, buf); | |
160 | ||
161 | /* print colors */ | |
162 | ErrorStatus = CreateColors(header + 1, &header_size, | |
163 | image->colorTable, image->ncolors, image->cpp); | |
164 | ||
165 | if (ErrorStatus != XpmSuccess) | |
166 | RETURN(ErrorStatus); | |
167 | ||
168 | /* now we know the size needed, alloc the data and copy the header lines */ | |
169 | offset = image->width * image->cpp + 1; | |
170 | data_size = header_size + (image->height + ext_nlines) * sizeof(char *) | |
171 | + image->height * offset + ext_size; | |
172 | ||
173 | data = (char **) XpmMalloc(data_size); | |
174 | if (!data) | |
175 | RETURN(XpmNoMemory); | |
176 | ||
177 | data_nlines = header_nlines + image->height + ext_nlines; | |
178 | *data = (char *) (data + data_nlines); | |
179 | n = image->ncolors; | |
180 | for (l = 0, sptr = data, sptr2 = header; l <= n; l++, sptr++, sptr2++) { | |
181 | strcpy(*sptr, *sptr2); | |
182 | *(sptr + 1) = *sptr + strlen(*sptr2) + 1; | |
183 | } | |
184 | ||
185 | /* print pixels */ | |
186 | data[header_nlines] = (char *) data + header_size | |
187 | + (image->height + ext_nlines) * sizeof(char *); | |
188 | ||
189 | CreatePixels(data + header_nlines, image->width, image->height, | |
190 | image->cpp, image->data, image->colorTable); | |
191 | ||
192 | /* print extensions */ | |
193 | if (extensions) | |
194 | CreateExtensions(data + header_nlines + image->height - 1, offset, | |
195 | info->extensions, info->nextensions, | |
196 | ext_nlines); | |
197 | ||
198 | *data_return = data; | |
199 | ErrorStatus = XpmSuccess; | |
200 | ||
201 | /* exit point, free only locally allocated variables */ | |
202 | exit: | |
203 | if (header) { | |
204 | for (l = 0; l < header_nlines; l++) | |
205 | if (header[l]) | |
206 | XpmFree(header[l]); | |
207 | XpmFree(header); | |
208 | } | |
209 | return(ErrorStatus); | |
210 | } | |
211 | ||
212 | static int | |
213 | CreateColors(dataptr, data_size, colors, ncolors, cpp) | |
214 | char **dataptr; | |
215 | unsigned int *data_size; | |
216 | XpmColor *colors; | |
217 | unsigned int ncolors; | |
218 | unsigned int cpp; | |
219 | { | |
220 | char buf[BUFSIZ]; | |
221 | unsigned int a, key, l; | |
222 | char *s, *s2; | |
223 | char **defaults; | |
224 | ||
225 | for (a = 0; a < ncolors; a++, colors++, dataptr++) { | |
226 | ||
227 | defaults = (char **) colors; | |
228 | strncpy(buf, *defaults++, cpp); | |
229 | s = buf + cpp; | |
230 | ||
231 | for (key = 1; key <= NKEYS; key++, defaults++) { | |
232 | if ((s2 = *defaults)!=NULL) { | |
233 | #ifndef VOID_SPRINTF | |
234 | s += | |
235 | #endif | |
236 | sprintf(s, "\t%s %s", xpmColorKeys[key - 1], s2); | |
237 | #ifdef VOID_SPRINTF | |
238 | s += strlen(s); | |
239 | #endif | |
240 | } | |
241 | } | |
242 | l = s - buf + 1; | |
243 | s = (char *) XpmMalloc(l); | |
244 | if (!s) | |
245 | return (XpmNoMemory); | |
246 | *data_size += l; | |
247 | *dataptr = strcpy(s, buf); | |
248 | } | |
249 | return (XpmSuccess); | |
250 | } | |
251 | ||
252 | static void | |
253 | CreatePixels(dataptr, width, height, cpp, pixels, colors) | |
254 | char **dataptr; | |
255 | unsigned int width; | |
256 | unsigned int height; | |
257 | unsigned int cpp; | |
258 | unsigned int *pixels; | |
259 | XpmColor *colors; | |
260 | { | |
261 | char *s; | |
262 | unsigned int x, y, h, offset; | |
263 | ||
264 | h = height - 1; | |
265 | offset = width * cpp + 1; | |
266 | for (y = 0; y < h; y++, dataptr++) { | |
267 | s = *dataptr; | |
268 | for (x = 0; x < width; x++, pixels++) { | |
269 | strncpy(s, colors[*pixels].string, cpp); | |
270 | s += cpp; | |
271 | } | |
272 | *s = '\0'; | |
273 | *(dataptr + 1) = *dataptr + offset; | |
274 | } | |
275 | /* duplicate some code to avoid a test in the loop */ | |
276 | s = *dataptr; | |
277 | for (x = 0; x < width; x++, pixels++) { | |
278 | strncpy(s, colors[*pixels].string, cpp); | |
279 | s += cpp; | |
280 | } | |
281 | *s = '\0'; | |
282 | } | |
283 | ||
284 | static void | |
285 | CountExtensions(ext, num, ext_size, ext_nlines) | |
286 | XpmExtension *ext; | |
287 | unsigned int num; | |
288 | unsigned int *ext_size; | |
289 | unsigned int *ext_nlines; | |
290 | { | |
291 | unsigned int x, y, a, size, nlines; | |
292 | char **line; | |
293 | ||
294 | size = 0; | |
295 | nlines = 0; | |
296 | for (x = 0; x < num; x++, ext++) { | |
297 | /* 1 for the name */ | |
298 | nlines += ext->nlines + 1; | |
299 | /* 8 = 7 (for "XPMEXT ") + 1 (for 0) */ | |
300 | size += strlen(ext->name) + 8; | |
301 | a = ext->nlines; | |
302 | for (y = 0, line = ext->lines; y < a; y++, line++) | |
303 | size += strlen(*line) + 1; | |
304 | } | |
305 | /* 10 and 1 are for the ending "XPMENDEXT" */ | |
306 | *ext_size = size + 10; | |
307 | *ext_nlines = nlines + 1; | |
308 | } | |
309 | ||
310 | static void | |
311 | CreateExtensions(dataptr, offset, ext, num, ext_nlines) | |
312 | char **dataptr; | |
313 | unsigned int offset; | |
314 | XpmExtension *ext; | |
315 | unsigned int num; | |
316 | unsigned int ext_nlines; | |
317 | { | |
318 | unsigned int x, y, a, b; | |
319 | char **line; | |
320 | ||
321 | *(dataptr + 1) = *dataptr + offset; | |
322 | dataptr++; | |
323 | a = 0; | |
324 | for (x = 0; x < num; x++, ext++) { | |
325 | sprintf(*dataptr, "XPMEXT %s", ext->name); | |
326 | a++; | |
327 | if (a < ext_nlines) | |
328 | *(dataptr + 1) = *dataptr + strlen(ext->name) + 8; | |
329 | dataptr++; | |
330 | b = ext->nlines; | |
331 | for (y = 0, line = ext->lines; y < b; y++, line++) { | |
332 | strcpy(*dataptr, *line); | |
333 | a++; | |
334 | if (a < ext_nlines) | |
335 | *(dataptr + 1) = *dataptr + strlen(*line) + 1; | |
336 | dataptr++; | |
337 | } | |
338 | } | |
339 | strcpy(*dataptr, "XPMENDEXT"); | |
340 | } |