Code refactoring: replaced macro 'HAVE_XRANDR' by 'USE_XRANDR' for consistency
[wmaker-crm.git] / wrlib / load_xpm_normalized.c
blob09371d1fa5441f9176720bf9a1730c5c74c41f81
1 /* nxpm.c - load "normalized" XPM image
3 * Raster graphics library
5 * Copyright (c) 1997-2003 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., 51 Franklin St, Fifth Floor, Boston,
20 * MA 02110-1301, USA.
23 #include <config.h>
25 #include <stdlib.h>
26 #include <stdio.h>
27 #include <string.h>
28 #include <assert.h>
29 #include <errno.h>
31 #include "wraster.h"
32 #include "imgformat.h"
35 * Restricted support for XPM images.
37 * The images must be in the following "normalized" format:
40 * line content
41 * 1 signature comment
42 * 2 ignored ( normally "static char *xpm[] = {" )
43 * 3 "width height color_count chars" where chars is 1 or 2
44 * 4 color definitions. Only c values with #rrggbb or #rrrrggggbbb
45 * format OR None
46 * n data
48 * - no comments or blank lines are allowed, except for the signature
49 * - all lines must have at most 256 characters
50 * - no white spaces allowed at left of each line
53 #define LINEWIDTH 64
56 static void free_color_symbol_table(unsigned char *color_table[],
57 unsigned short *symbol_table)
59 if (color_table[0])
60 free(color_table[0]);
61 if (color_table[1])
62 free(color_table[1]);
63 if (color_table[2])
64 free(color_table[2]);
65 if (color_table[3])
66 free(color_table[3]);
67 if (symbol_table)
68 free(symbol_table);
71 RImage *RGetImageFromXPMData(RContext * context, char **data)
73 RImage *image = NULL;
74 unsigned char *color_table[4] = { NULL, NULL, NULL, NULL };
75 unsigned short *symbol_table = NULL;
76 unsigned char *r, *g, *b, *a;
77 int i, j, k, line = 0;
78 int transp;
79 unsigned short color;
80 int bsize;
81 int w, h, ccount, csize;
84 * When using libXpm we need the context argument but the code here does
85 * not, so tell the compiler to not warn about it
87 (void) context;
89 if (sscanf(data[line++], "%i %i %i %i", &w, &h, &ccount, &csize) != 4
90 || w <= 0 || h <= 0 || ccount <= 0 || csize <= 0)
91 goto bad_format;
93 if (csize != 1 && csize != 2)
94 goto bad_format;
96 color_table[0] = malloc(ccount);
97 color_table[1] = malloc(ccount);
98 color_table[2] = malloc(ccount);
99 color_table[3] = malloc(ccount);
100 symbol_table = malloc(ccount * sizeof(unsigned short));
102 bsize = csize * w + 16;
104 if (!color_table[0] || !color_table[1] || !color_table[2] || !color_table[3] || !symbol_table || !bsize) {
105 RErrorCode = RERR_NOMEMORY;
106 free_color_symbol_table(color_table, symbol_table);
107 return NULL;
110 transp = 0;
111 /* get color table */
112 for (i = 0; i < ccount; i++) {
113 symbol_table[i] = data[line][0];
114 if (csize == 2)
115 symbol_table[i] |= data[line][1] << 8;
117 j = csize;
118 while (data[line][j] != '#' && data[line][j] != 0 && data[line][j] != 'N')
119 j++;
121 if (data[line][j] == '#') {
122 unsigned int red, green, blue;
124 k = 0;
125 j++;
126 while (data[line][j + k] != 0)
127 k++;
128 if (k == 6) {
129 if (sscanf(&(data[line][j]), "%2x%2x%2x", &red, &green, &blue) != 3)
130 goto bad_format;
131 } else if (k == 12) {
132 if (sscanf(&(data[line][j]), "%4x%4x%4x", &red, &green, &blue) != 3)
133 goto bad_format;
134 red >>= 8;
135 green >>= 8;
136 blue >>= 8;
137 } else
138 goto bad_format;
140 color_table[0][i] = red;
141 color_table[1][i] = green;
142 color_table[2][i] = blue;
143 color_table[3][i] = 255;
144 } else if (strncmp(&(data[line][j]), "None", 4) == 0 || strncmp(&(data[line][j]), "none", 4) == 0) {
145 color_table[3][i] = 0;
146 transp = 1;
147 } else {
148 goto bad_format;
150 line++;
153 image = RCreateImage(w, h, transp);
154 if (!image) {
155 free_color_symbol_table(color_table, symbol_table);
156 return NULL;
159 r = image->data;
160 g = image->data + 1;
161 b = image->data + 2;
162 if (image->format == RRGBAFormat)
163 a = image->data + 3;
164 else
165 a = NULL;
167 for (i = 0; i < h; i++) {
168 if (csize == 1) {
169 for (j = 0; j < w; j++) {
170 color = data[line][j];
172 for (k = 0; k < ccount; k++) {
173 if (symbol_table[k] == color)
174 break;
176 if (k == ccount)
177 k = 0;
179 *r = color_table[0][k];
180 *g = color_table[1][k];
181 *b = color_table[2][k];
182 if (a) {
183 *a = color_table[3][k];
184 r += 4;
185 g += 4;
186 b += 4;
187 a += 4;
188 } else {
189 r += 3;
190 g += 3;
191 b += 3;
194 } else {
195 for (j = 0; j < w * 2; j++) {
196 color = data[line][j++];
197 color |= data[line][j];
199 for (k = 0; k < ccount; k++) {
200 if (symbol_table[k] == color)
201 break;
203 if (k == ccount)
204 k = 0;
206 *r = color_table[0][k];
207 *g = color_table[1][k];
208 *b = color_table[2][k];
209 if (a) {
210 *a = color_table[3][k];
211 r += 4;
212 g += 4;
213 b += 4;
214 a += 4;
215 } else {
216 r += 3;
217 g += 3;
218 b += 3;
222 line++;
225 free_color_symbol_table(color_table, symbol_table);
226 return image;
228 bad_format:
229 RErrorCode = RERR_BADIMAGEFILE;
230 free_color_symbol_table(color_table, symbol_table);
231 if (image)
232 RReleaseImage(image);
233 return NULL;
236 RImage *RLoadXPM(RContext * context, const char *file)
238 RImage *image = NULL;
239 char line[LINEWIDTH + 1];
240 char *buffer = NULL;
241 unsigned char *color_table[4] = { NULL, NULL, NULL, NULL };
242 unsigned short *symbol_table = NULL;
243 unsigned char *r, *g, *b, *a;
244 int i, j, k;
245 int transp;
246 unsigned short color;
247 int bsize;
248 int w, h, ccount, csize;
249 FILE *f;
252 * When using libXpm we need the context argument but the code here does
253 * not, so tell the compiler to not warn about it
255 (void) context;
257 f = fopen(file, "rb");
258 if (!f) {
259 RErrorCode = RERR_OPEN;
260 return NULL;
262 /* sig */
263 if (!fgets(line, LINEWIDTH, f))
264 goto bad_file;
265 /* declaration */
266 if (!fgets(line, LINEWIDTH, f))
267 goto bad_file;
269 /* data */
270 if (!fgets(line, LINEWIDTH, f))
271 goto bad_file;
273 if (line[0] == '/')
274 if (!fgets(line, LINEWIDTH, f))
275 goto bad_file;
277 if (sscanf(line, "\"%i %i %i %i\"", &w, &h, &ccount, &csize) != 4
278 || w <= 0 || h <= 0 || ccount <= 0 || csize <= 0)
279 goto bad_file;
281 if (csize != 1 && csize != 2)
282 goto bad_format;
284 color_table[0] = malloc(ccount);
285 color_table[1] = malloc(ccount);
286 color_table[2] = malloc(ccount);
287 color_table[3] = malloc(ccount);
288 symbol_table = malloc(ccount * sizeof(unsigned short));
290 bsize = csize * w + 16;
291 buffer = malloc(bsize);
293 if (!color_table[0] || !color_table[1] || !color_table[2] ||
294 !color_table[3] || !symbol_table || !bsize || !buffer) {
295 RErrorCode = RERR_NOMEMORY;
296 fclose(f);
297 free_color_symbol_table(color_table, symbol_table);
298 if (buffer)
299 free(buffer);
300 return NULL;
303 transp = 0;
304 /* get color table */
305 for (i = 0; i < ccount; i++) {
306 if (!fgets(line, LINEWIDTH, f))
307 goto bad_file;
308 if (line[0] == '/')
309 if (!fgets(line, LINEWIDTH, f))
310 goto bad_file;
312 symbol_table[i] = line[1];
313 if (csize == 2)
314 symbol_table[i] |= line[2] << 8;
316 j = csize + 1;
317 while (line[j] != '#' && line[j] != '"' && line[j] != 0 && line[j] != 'N')
318 j++;
320 if (line[j] == '#') {
321 unsigned int red, green, blue;
323 k = 0;
324 j++;
325 while (line[j + k] != '"' && line[j + k] != 0)
326 k++;
327 if (k == 6) {
328 if (sscanf(&(line[j]), "%2x%2x%2x", &red, &green, &blue) != 3)
329 goto bad_format;
330 } else if (k == 12) {
331 if (sscanf(&(line[j]), "%4x%4x%4x", &red, &green, &blue) != 3)
332 goto bad_format;
333 red >>= 8;
334 green >>= 8;
335 blue >>= 8;
336 } else
337 goto bad_format;
339 color_table[0][i] = red;
340 color_table[1][i] = green;
341 color_table[2][i] = blue;
342 color_table[3][i] = 255;
343 } else if (strncmp(&(line[j]), "None", 4) == 0 || strncmp(&(line[j]), "none", 4) == 0) {
344 color_table[3][i] = 0;
345 transp = 1;
346 } else {
347 goto bad_format;
351 image = RCreateImage(w, h, transp);
352 if (!image) {
353 fclose(f);
354 free_color_symbol_table(color_table, symbol_table);
355 if (buffer)
356 free(buffer);
357 return NULL;
360 r = image->data;
361 g = image->data + 1;
362 b = image->data + 2;
363 if (image->format == RRGBAFormat)
364 a = image->data + 3;
365 else
366 a = NULL;
368 for (i = 0; i < h; i++) {
369 if (!fgets(buffer, bsize, f))
370 goto bad_file;
371 if (buffer[0] == '/')
372 if (!fgets(buffer, bsize, f))
373 goto bad_file;
375 if (csize == 1) {
376 for (j = 1; j <= w; j++) {
377 color = buffer[j];
379 for (k = 0; k < ccount; k++) {
380 if (symbol_table[k] == color)
381 break;
383 if (k == ccount)
384 k = 0;
386 *r = color_table[0][k];
387 *g = color_table[1][k];
388 *b = color_table[2][k];
389 if (a) {
390 *a = color_table[3][k];
391 r += 4;
392 g += 4;
393 b += 4;
394 a += 4;
395 } else {
396 r += 3;
397 g += 3;
398 b += 3;
401 } else {
402 for (j = 1; j <= w * 2; j++) {
403 color = buffer[j++];
404 color |= buffer[j] << 8;
406 for (k = 0; k < ccount; k++) {
407 if (symbol_table[k] == color)
408 break;
410 if (k == ccount) {
411 k = 0;
414 *r = color_table[0][k];
415 *g = color_table[1][k];
416 *b = color_table[2][k];
417 if (a) {
418 *a = color_table[3][k];
419 r += 4;
420 g += 4;
421 b += 4;
422 a += 4;
423 } else {
424 r += 3;
425 g += 3;
426 b += 3;
432 fclose(f);
433 free_color_symbol_table(color_table, symbol_table);
434 if (buffer)
435 free(buffer);
436 return image;
438 bad_format:
439 RErrorCode = RERR_BADIMAGEFILE;
440 fclose(f);
441 free_color_symbol_table(color_table, symbol_table);
442 if (buffer)
443 free(buffer);
444 if (image)
445 RReleaseImage(image);
446 return NULL;
448 bad_file:
449 RErrorCode = RERR_BADIMAGEFILE;
450 fclose(f);
451 free_color_symbol_table(color_table, symbol_table);
452 if (buffer)
453 free(buffer);
454 if (image)
455 RReleaseImage(image);
456 return NULL;