Initial revision
[wmaker-crm.git] / wrlib / nxpm.c
blob59e4f090bec638bc2e9738271ee33b40cf624346
1 /* nxpm.c - load "normalized" XPM image
2 *
3 * Raster graphics library
4 *
5 * Copyright (c) 1997 Alfredo K. Kojima
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Library General Public
9 * License as published by the Free Software Foundation; either
10 * version 2 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Library General Public License for more details.
17 * You should have received a copy of the GNU Library General Public
18 * License along with this library; if not, write to the Free
19 * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
22 #include <config.h>
24 /* AIX requires this to be the first thing in the file. */
25 #ifdef __GNUC__
26 # define alloca __builtin_alloca
27 #else
28 # if HAVE_ALLOCA_H
29 # include <alloca.h>
30 # else
31 # ifdef _AIX
32 # pragma alloca
33 # else
34 # ifndef alloca /* predefined by HP cc +Olibcalls */
35 char *alloca ();
36 # endif
37 # endif
38 # endif
39 #endif
42 #include <stdlib.h>
43 #include <stdio.h>
44 #include <string.h>
46 #include "wraster.h"
50 * Restricted support for XPM images.
52 * The images must be in the following "normalized" format:
55 * line content
56 * 1 signature comment
57 * 2 ignored ( normally "static char *xpm[] = {" )
58 * 3 "width height color_count chars" where chars is 1 or 2
59 * 4 color definitions. Only c values with #rrggbb or #rrrrggggbbb
60 * format OR None
61 * n data
63 * - no comments or blank lines are allowed, except for the signature
64 * - all lines must have at most 256 characters
65 * - no white spaces allowed at left of each line
68 #define LINEWIDTH 64
70 #ifndef USE_XPM
73 RImage*
74 RGetImageFromXPMData(RContext *context, char **data)
76 RImage *image = NULL;
77 unsigned char *color_table[4];
78 unsigned short *symbol_table;
79 unsigned char *r, *g, *b, *a;
80 int i, j, k, line = 0;
81 int transp;
82 unsigned short color;
83 int bsize;
84 int w, h, ccount, csize;
86 if (sscanf(data[line++], "%i %i %i %i", &w, &h, &ccount, &csize)!=4
87 || w <= 0 || h <= 0 || ccount <= 0 || csize <= 0)
88 goto bad_format;
90 if (csize!=1 && csize!=2)
91 goto bad_format;
93 color_table[0] = alloca(ccount);
94 color_table[1] = alloca(ccount);
95 color_table[2] = alloca(ccount);
96 color_table[3] = alloca(ccount);
97 symbol_table = alloca(ccount * sizeof(unsigned short));
99 bsize = csize * w + 16;
101 if (!color_table[0] || !color_table[1] || !color_table[2] ||
102 !color_table[3] || !symbol_table || !bsize) {
103 sprintf(RErrorString, "out of memory while converting XPM data");
104 alloca(0);
105 return NULL;
108 transp = 0;
109 /* get color table */
110 for (i=0; i<ccount; i++) {
111 symbol_table[i] = data[line][0];
112 if (csize==2)
113 symbol_table[i] |= data[line][1]<<8;
115 j = csize;
116 while (data[line][j]!='#' && data[line][j]!=0
117 && data[line][j]!='N') j++;
119 if (data[line][j]=='#') {
120 unsigned int red, green, blue;
122 k = 0;
123 j++;
124 while (data[line][j+k]!=0) k++;
125 if (k==6) {
126 if (sscanf(&(data[line][j]), "%2x%2x%2x", &red, &green, &blue)!=3)
127 goto bad_format;
128 } else if (k==12) {
129 if (sscanf(&(data[line][j]), "%4x%4x%4x", &red, &green, &blue)!=3)
130 goto bad_format;
131 red >>= 8;
132 green >>= 8;
133 blue >>= 8;
134 } else
135 goto bad_format;
137 color_table[0][i] = red;
138 color_table[1][i] = green;
139 color_table[2][i] = blue;
140 color_table[3][i] = 255;
141 } else if (strncmp(&(data[line][j]), "None", 4)==0) {
142 color_table[3][i] = 0;
143 transp = 1;
144 } else {
145 goto bad_format;
147 line++;
150 image = RCreateImage(w, h, transp);
151 if (!image) {
152 sprintf(RErrorString, "out of memory while converting XPM data");
153 alloca(0);
154 return NULL;
157 r = image->data[0];
158 g = image->data[1];
159 b = image->data[2];
160 a = image->data[3];
162 for (i=0; i<h; i++) {
163 if (csize==1) {
164 for (j=0; j<w; j++) {
165 color = data[line][j];
167 for (k=0; k<ccount; k++) {
168 if (symbol_table[k] == color)
169 break;
171 if (k==ccount)
172 k = 0;
174 *(r++) = color_table[0][k];
175 *(g++) = color_table[1][k];
176 *(b++) = color_table[2][k];
177 if (a)
178 *(a++) = color_table[3][k];
180 } else {
181 for (j=0; j<w*2; j++) {
182 color = data[line][j++];
183 color |= data[line][j];
185 for (k=0; k<ccount; k++) {
186 if (symbol_table[k] == color)
187 break;
189 if (k==ccount)
190 k = 0;
192 *(r++) = color_table[0][k];
193 *(g++) = color_table[1][k];
194 *(b++) = color_table[2][k];
195 if (a)
196 *(a++) = color_table[3][k];
199 line++;
202 #ifdef C_ALLOCA
203 alloca(0);
204 #endif
205 return image;
207 bad_format:
208 sprintf(RErrorString, "XPM data is not in the normalized format");
209 #ifdef C_ALLOCA
210 alloca(0);
211 #endif
212 if (image)
213 RDestroyImage(image);
214 return NULL;
219 RImage*
220 RLoadXPM(RContext *context, char *file, int index)
222 RImage *image = NULL;
223 char line[LINEWIDTH+1];
224 char *buffer;
225 unsigned char *color_table[4];
226 unsigned short *symbol_table;
227 unsigned char *r, *g, *b, *a;
228 int i, j, k;
229 int transp;
230 unsigned short color;
231 int bsize;
232 int w, h, ccount, csize;
233 FILE *f;
235 f = fopen(file, "r");
236 if (!f) {
237 sprintf(RErrorString, "can't open XPM file \"%s\"", file);
238 return NULL;
240 /* sig */
241 if (!fgets(line, LINEWIDTH, f))
242 goto bad_file;
243 /* declaration */
244 if (!fgets(line, LINEWIDTH, f))
245 goto bad_file;
247 /* data */
248 if (!fgets(line, LINEWIDTH, f))
249 goto bad_file;
251 if (line[0]=='/')
252 if (!fgets(line, LINEWIDTH, f))
253 goto bad_file;
255 if (sscanf(line, "\"%i %i %i %i\"", &w, &h, &ccount, &csize)!=4
256 || w <= 0 || h <= 0 || ccount <= 0 || csize <= 0)
257 goto bad_file;
259 if (csize!=1 && csize!=2)
260 goto bad_format;
262 color_table[0] = alloca(ccount);
263 color_table[1] = alloca(ccount);
264 color_table[2] = alloca(ccount);
265 color_table[3] = alloca(ccount);
266 symbol_table = alloca(ccount * sizeof(unsigned short));
268 bsize = csize * w + 16;
269 buffer = alloca(bsize);
271 if (!color_table[0] || !color_table[1] || !color_table[2] ||
272 !color_table[3] || !symbol_table || !bsize) {
273 sprintf(RErrorString, "out of memory while loading XPM file \"%s\"",
274 file);
275 fclose(f);
276 alloca(0);
277 return NULL;
280 transp = 0;
281 /* get color table */
282 for (i=0; i<ccount; i++) {
283 if (!fgets(line, LINEWIDTH, f))
284 goto bad_file;
285 if (line[0]=='/')
286 if (!fgets(line, LINEWIDTH, f))
287 goto bad_file;
289 symbol_table[i] = line[1];
290 if (csize==2)
291 symbol_table[i] |= line[2]<<8;
293 j = csize+1;
294 while (line[j]!='#' && line[j]!='"' && line[j]!=0 && line[j]!='N') j++;
296 if (line[j]=='#') {
297 unsigned int red, green, blue;
299 k = 0;
300 j++;
301 while (line[j+k]!='"' && line[j+k]!=0) k++;
302 if (k==6) {
303 if (sscanf(&(line[j]), "%2x%2x%2x", &red, &green, &blue)!=3)
304 goto bad_format;
305 } else if (k==12) {
306 if (sscanf(&(line[j]), "%4x%4x%4x", &red, &green, &blue)!=3)
307 goto bad_format;
308 red >>= 8;
309 green >>= 8;
310 blue >>= 8;
311 } else
312 goto bad_format;
314 color_table[0][i] = red;
315 color_table[1][i] = green;
316 color_table[2][i] = blue;
317 color_table[3][i] = 255;
318 } else if (strncmp(&(line[j]), "None", 4)==0) {
319 color_table[3][i] = 0;
320 transp = 1;
321 } else {
322 goto bad_format;
326 image = RCreateImage(w, h, transp);
327 if (!image) {
328 sprintf(RErrorString, "out of memory while loading XPM file \"%s\"",
329 file);
330 fclose(f);
331 alloca(0);
332 return NULL;
335 r = image->data[0];
336 g = image->data[1];
337 b = image->data[2];
338 a = image->data[3];
340 for (i=0; i<h; i++) {
341 if (!fgets(buffer, bsize, f))
342 goto bad_file;
343 if (buffer[0]=='/')
344 if (!fgets(buffer, bsize, f))
345 goto bad_file;
347 if (csize==1) {
348 for (j=1; j<=w; j++) {
349 color = buffer[j];
351 for (k=0; k<ccount; k++) {
352 if (symbol_table[k] == color)
353 break;
355 if (k==ccount)
356 k = 0;
358 *(r++) = color_table[0][k];
359 *(g++) = color_table[1][k];
360 *(b++) = color_table[2][k];
361 if (a)
362 *(a++) = color_table[3][k];
364 } else {
365 for (j=1; j<=w*2; j++) {
366 color = buffer[j++];
367 color |= buffer[j] << 8;
369 for (k=0; k<ccount; k++) {
370 if (symbol_table[k] == color)
371 break;
373 if (k==ccount) {
374 k = 0;
377 *(r++) = color_table[0][k];
378 *(g++) = color_table[1][k];
379 *(b++) = color_table[2][k];
380 if (a)
381 *(a++) = color_table[3][k];
386 fclose(f);
387 #ifdef C_ALLOCA
388 alloca(0);
389 #endif
390 return image;
392 bad_format:
393 sprintf(RErrorString, "XPM file \"%s\" is not in the normalized format", file);
394 fclose(f);
395 #ifdef C_ALLOCA
396 alloca(0);
397 #endif
398 if (image)
399 RDestroyImage(image);
400 return NULL;
402 bad_file:
403 sprintf(RErrorString, "bad XPM file \"%s\"", file);
404 fclose(f);
405 #ifdef C_ALLOCA
406 alloca(0);
407 #endif
408 if (image)
409 RDestroyImage(image);
410 return NULL;
413 #endif