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