aboutsummaryrefslogtreecommitdiffstatshomepage
path: root/libraries/evas/src/modules/loaders/xpm/evas_image_load_xpm.c
diff options
context:
space:
mode:
authorDavid Walter Seikel2012-01-04 18:41:13 +1000
committerDavid Walter Seikel2012-01-04 18:41:13 +1000
commitdd7595a3475407a7fa96a97393bae8c5220e8762 (patch)
treee341e911d7eb911a51684a7412ef7f7c7605d28e /libraries/evas/src/modules/loaders/xpm/evas_image_load_xpm.c
parentAdd the skeleton. (diff)
downloadSledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.zip
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.gz
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.bz2
SledjHamr-dd7595a3475407a7fa96a97393bae8c5220e8762.tar.xz
Add the base Enlightenment Foundation Libraries - eina, eet, evas, ecore, embryo, and edje.
Note that embryo wont be used, but I'm not sure yet if you can build edje without it.
Diffstat (limited to '')
-rw-r--r--libraries/evas/src/modules/loaders/xpm/evas_image_load_xpm.c691
1 files changed, 691 insertions, 0 deletions
diff --git a/libraries/evas/src/modules/loaders/xpm/evas_image_load_xpm.c b/libraries/evas/src/modules/loaders/xpm/evas_image_load_xpm.c
new file mode 100644
index 0000000..3a04f84
--- /dev/null
+++ b/libraries/evas/src/modules/loaders/xpm/evas_image_load_xpm.c
@@ -0,0 +1,691 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#ifdef HAVE_EVIL
6# include <Evil.h>
7#endif
8
9#include "evas_common.h"
10#include "evas_private.h"
11
12static int _evas_loader_xpm_log_dom = -1;
13
14#ifdef ERR
15# undef ERR
16#endif
17#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_xpm_log_dom, __VA_ARGS__)
18
19static Eina_Bool evas_image_load_file_head_xpm(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
20static Eina_Bool evas_image_load_file_data_xpm(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
21
22static Evas_Image_Load_Func evas_image_load_xpm_func =
23{
24 EINA_FALSE,
25 evas_image_load_file_head_xpm,
26 evas_image_load_file_data_xpm,
27 NULL
28};
29
30// TODO: REWRITE THIS WITH THREAD SAFE VERSION NOT USING THIS HANDLE!!!!
31static FILE *rgb_txt = NULL;
32
33static void
34xpm_parse_color(char *color, int *r, int *g, int *b)
35{
36 char buf[4096];
37
38 /* is a #ff00ff like color */
39 if (color[0] == '#')
40 {
41 int len;
42 char val[32];
43
44 len = strlen(color) - 1;
45 if (len < 96)
46 {
47 int i;
48
49 len /= 3;
50 for (i = 0; i < len; i++)
51 val[i] = color[1 + i + (0 * len)];
52 val[i] = 0;
53 sscanf(val, "%x", r);
54 for (i = 0; i < len; i++)
55 val[i] = color[1 + i + (1 * len)];
56 val[i] = 0;
57 sscanf(val, "%x", g);
58 for (i = 0; i < len; i++)
59 val[i] = color[1 + i + (2 * len)];
60 val[i] = 0;
61 sscanf(val, "%x", b);
62 if (len == 1)
63 {
64 *r = (*r << 4) | *r;
65 *g = (*g << 4) | *g;
66 *b = (*b << 4) | *b;
67 }
68 else if (len > 2)
69 {
70 *r >>= (len - 2) * 4;
71 *g >>= (len - 2) * 4;
72 *b >>= (len - 2) * 4;
73 }
74 }
75 return;
76 }
77 /* look in rgb txt database */
78 if (!rgb_txt) rgb_txt = fopen("/usr/lib/X11/rgb.txt", "r");
79 if (!rgb_txt) rgb_txt = fopen("/usr/X11/lib/X11/rgb.txt", "r");
80 if (!rgb_txt) rgb_txt = fopen("/usr/X11R6/lib/X11/rgb.txt", "r");
81 if (!rgb_txt) rgb_txt = fopen("/usr/openwin/lib/X11/rgb.txt", "r");
82 if (!rgb_txt) return;
83 fseek(rgb_txt, 0, SEEK_SET);
84 while (fgets(buf, sizeof(buf), rgb_txt))
85 {
86 buf[sizeof(buf) - 1] = 0;
87 if (buf[0] != '!')
88 {
89 int rr, gg, bb;
90 char name[4096];
91
92 if (sscanf(buf, "%i %i %i %[^\n]", &rr, &gg, &bb, name) == 4)
93 {
94 if (!strcasecmp(name, color))
95 {
96 *r = rr;
97 *g = gg;
98 *b = bb;
99 return;
100 }
101 }
102 }
103 }
104}
105
106static void
107xpm_parse_done(void)
108{
109 if (rgb_txt) fclose(rgb_txt);
110 rgb_txt = NULL;
111}
112
113
114/** FIXME: clean this up and make more efficient **/
115static Eina_Bool
116evas_image_load_file_xpm(Image_Entry *ie, const char *file, const char *key __UNUSED__, int load_data, int *error)
117{
118 DATA32 *ptr, *end;
119 FILE *f;
120
121 int pc, c, i, j, k, w, h, ncolors, cpp, comment, transp,
122 quote, context, len, done, r, g, b, backslash, lu1, lu2;
123 char *line, s[256], tok[128], col[256], *tl;
124 int lsz = 256;
125 struct _cmap {
126 char str[6];
127 unsigned char transp;
128 short r, g, b;
129 } *cmap;
130
131 short lookup[128 - 32][128 - 32];
132 int count, pixels;
133
134 done = 0;
135// transp = -1;
136 transp = 1;
137
138 /* if immediate_load is 1, then dont delay image laoding as below, or */
139 /* already data in this image - dont load it again */
140
141 f = fopen(file, "rb");
142 if (!f)
143 {
144 xpm_parse_done();
145 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
146 return EINA_FALSE;
147 }
148 if (fread(s, 9, 1, f) != 1)
149 {
150 fclose(f);
151 xpm_parse_done();
152 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
153 return EINA_FALSE;
154 }
155 rewind(f);
156 s[9] = 0;
157 if (strcmp("/* XPM */", s))
158 {
159 fclose(f);
160 xpm_parse_done();
161 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
162 return EINA_FALSE;
163 }
164
165 i = 0;
166 j = 0;
167 cmap = NULL;
168 w = 10;
169 h = 10;
170 ptr = NULL;
171 end = NULL;
172 c = ' ';
173 comment = 0;
174 quote = 0;
175 context = 0;
176 pixels = 0;
177 count = 0;
178 line = malloc(lsz);
179 if (!line)
180 {
181 fclose(f);
182 xpm_parse_done();
183 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
184 return EINA_FALSE;
185 }
186
187 backslash = 0;
188 memset(lookup, 0, sizeof(lookup));
189 while (!done)
190 {
191 pc = c;
192 c = fgetc(f);
193 if (c == EOF) break;
194 if (!quote)
195 {
196 if ((pc == '/') && (c == '*'))
197 comment = 1;
198 else if ((pc == '*') && (c == '/') && (comment))
199 comment = 0;
200 }
201 if (!comment)
202 {
203 if ((!quote) && (c == '"'))
204 {
205 quote = 1;
206 i = 0;
207 }
208 else if ((quote) && (c == '"'))
209 {
210 line[i] = 0;
211 quote = 0;
212 if (context == 0)
213 {
214 /* Header */
215 if (sscanf(line, "%i %i %i %i", &w, &h, &ncolors, &cpp) != 4)
216 {
217 ERR("XPM ERROR: XPM file malformed header");
218 free(line);
219 fclose(f);
220 xpm_parse_done();
221 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
222 return EINA_FALSE;
223 }
224 if ((ncolors > 32766) || (ncolors < 1))
225 {
226 ERR("XPM ERROR: XPM files with colors > 32766 or < 1 not supported");
227 free(line);
228 fclose(f);
229 xpm_parse_done();
230 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
231 return EINA_FALSE;
232 }
233 if ((cpp > 5) || (cpp < 1))
234 {
235 ERR("XPM ERROR: XPM files with characters per pixel > 5 or < 1not supported");
236 free(line);
237 fclose(f);
238 xpm_parse_done();
239 *error = EVAS_LOAD_ERROR_UNKNOWN_FORMAT;
240 return EINA_FALSE;
241 }
242 if ((w > IMG_MAX_SIZE) || (w < 1))
243 {
244 ERR("XPM ERROR: Image width > IMG_MAX_SIZE or < 1 pixels for file");
245 free(line);
246 fclose(f);
247 xpm_parse_done();
248 *error = EVAS_LOAD_ERROR_GENERIC;
249 return EINA_FALSE;
250 }
251 if ((h > IMG_MAX_SIZE) || (h < 1))
252 {
253 ERR("XPM ERROR: Image height > IMG_MAX_SIZE or < 1 pixels for file");
254 free(line);
255 fclose(f);
256 xpm_parse_done();
257 *error = EVAS_LOAD_ERROR_GENERIC;
258 return EINA_FALSE;
259 }
260 if (IMG_TOO_BIG(w, h))
261 {
262 ERR("XPM ERROR: Image just too big to ever allocate");
263 free(line);
264 fclose(f);
265 xpm_parse_done();
266 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
267 return EINA_FALSE;
268 }
269
270 if (!cmap)
271 {
272 cmap = malloc(sizeof(struct _cmap) * ncolors);
273 if (!cmap)
274 {
275 free(line);
276 fclose(f);
277 xpm_parse_done();
278 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
279 return EINA_FALSE;
280 }
281 }
282 ie->w = w;
283 ie->h = h;
284
285 j = 0;
286 context++;
287 }
288 else if (context == 1)
289 {
290 /* Color Table */
291 if (j < ncolors)
292 {
293 int slen;
294 int hascolor, iscolor;
295
296 iscolor = 0;
297 hascolor = 0;
298 tok[0] = 0;
299 col[0] = 0;
300 s[0] = 0;
301 len = strlen(line);
302 strncpy(cmap[j].str, line, cpp);
303 cmap[j].str[cpp] = 0;
304 for (slen = 0; slen < cpp; slen++)
305 {
306 /* fix the ascii of the color string - if its < 32 - just limit to 32 */
307 if (cmap[j].str[slen] < 32) cmap[j].str[slen] = 0;
308 }
309 cmap[j].r = -1;
310 cmap[j].transp = 0;
311 for (k = cpp; k < len; k++)
312 {
313 if (line[k] != ' ')
314 {
315 s[0] = 0;
316 sscanf(&line[k], "%255s", s);
317 slen = strlen(s);
318 k += slen;
319 if (!strcmp(s, "c")) iscolor = 1;
320 if ((!strcmp(s, "m")) || (!strcmp(s, "s"))
321 || (!strcmp(s, "g4")) || (!strcmp(s, "g"))
322 || (!strcmp(s, "c")) || (k >= len))
323 {
324 if (k >= len)
325 {
326 if (col[0])
327 {
328 if (strlen(col) < (sizeof(col) - 2))
329 strcat(col, " ");
330 else
331 done = 1;
332 }
333 if ((strlen(col) + strlen(s)) < (sizeof(col) - 1))
334 strcat(col, s);
335 }
336 if (col[0])
337 {
338 if (!strcasecmp(col, "none"))
339 {
340 transp = 1;
341 cmap[j].transp = 1;
342 cmap[j].r = 0;
343 cmap[j].g = 0;
344 cmap[j].b = 0;
345 }
346 else
347 {
348 if ((((cmap[j].r < 0) || (!strcmp(tok, "c"))) && (!hascolor)))
349 {
350 r = g = b = 0;
351 xpm_parse_color(col, &r, &g, &b);
352 cmap[j].r = r;
353 cmap[j].g = g;
354 cmap[j].b = b;
355 if (iscolor) hascolor = 1;
356 }
357 }
358 }
359 strcpy(tok, s);
360 col[0] = 0;
361 }
362 else
363 {
364 if (col[0])
365 {
366 if (strlen(col) < ( sizeof(col) - 2))
367 strcat(col, " ");
368 else
369 done = 1;
370 }
371 if ((strlen(col) + strlen(s)) < (sizeof(col) - 1))
372 strcat(col, s);
373 }
374 }
375 }
376 }
377 j++;
378 if (j >= ncolors)
379 {
380 if (cpp == 1)
381 {
382 for (i = 0; i < ncolors; i++)
383 lookup[(int)cmap[i].str[0] - 32][0] = i;
384 }
385 if (cpp == 2)
386 {
387 for (i = 0; i < ncolors; i++)
388 lookup[(int)cmap[i].str[0] - 32][(int)cmap[i].str[1] - 32] = i;
389 }
390 context++;
391 }
392
393 if (transp) ie->flags.alpha = 1;
394
395 if (load_data)
396 {
397 evas_cache_image_surface_alloc(ie, w, h);
398 ptr = evas_cache_image_pixels(ie);
399 if (!ptr)
400 {
401 free(cmap);
402 free(line);
403 fclose(f);
404 xpm_parse_done();
405 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
406 return EINA_FALSE;
407 }
408 pixels = w * h;
409 end = ptr + pixels;
410 }
411 else
412 {
413 free(cmap);
414 free(line);
415 fclose(f);
416 xpm_parse_done();
417 *error = EVAS_LOAD_ERROR_NONE;
418 return EINA_TRUE;
419 }
420 }
421 else
422 {
423 /* Image Data */
424 i = 0;
425 if (cpp == 0)
426 {
427 /* Chars per pixel = 0? well u never know */
428 }
429 /* it's xpm - don't care about speed too much. still faster
430 * that most xpm loaders anyway */
431 else if (cpp == 1)
432 {
433 if (transp)
434 {
435 for (i = 0;
436 ((i < 65536) && (ptr < end) && (line[i]));
437 i++)
438 {
439 lu1 = (int)line[i] - 32;
440 if (lu1 < 0) continue;
441 if (cmap[lookup[lu1][0]].transp)
442 {
443 r = (unsigned char)cmap[lookup[lu1][0]].r;
444 g = (unsigned char)cmap[lookup[lu1][0]].g;
445 b = (unsigned char)cmap[lookup[lu1][0]].b;
446 *ptr = RGB_JOIN(r, g, b);
447 ptr++;
448 count++;
449 }
450 else
451 {
452 r = (unsigned char)cmap[lookup[lu1][0]].r;
453 g = (unsigned char)cmap[lookup[lu1][0]].g;
454 b = (unsigned char)cmap[lookup[lu1][0]].b;
455 *ptr = ARGB_JOIN(0xff, r, g, b);
456 ptr++;
457 count++;
458 }
459 }
460 }
461 else
462 {
463 for (i = 0;
464 ((i < 65536) && (ptr < end) && (line[i]));
465 i++)
466 {
467 lu1 = (int)line[i] - 32;
468 if (lu1 < 0) continue;
469 r = (unsigned char)cmap[lookup[lu1][0]].r;
470 g = (unsigned char)cmap[lookup[lu1][0]].g;
471 b = (unsigned char)cmap[lookup[lu1][0]].b;
472 *ptr = ARGB_JOIN(0xff, r, g, b);
473 ptr++;
474 count++;
475 }
476 }
477 }
478 else if (cpp == 2)
479 {
480 if (transp)
481 {
482 for (i = 0;
483 ((i < 65536) && (ptr < end) && (line[i]));
484 i++)
485 {
486 lu1 = (int)line[i] - 32;
487 i++;
488 lu2 = (int)line[i] - 32;
489 if (lu1 < 0) continue;
490 if (lu2 < 0) continue;
491 if (cmap[lookup[lu1][lu2]].transp)
492 {
493 r = (unsigned char)cmap[lookup[lu1][lu2]].r;
494 g = (unsigned char)cmap[lookup[lu1][lu2]].g;
495 b = (unsigned char)cmap[lookup[lu1][lu2]].b;
496 *ptr = RGB_JOIN(r, g, b);
497 ptr++;
498 count++;
499 }
500 else
501 {
502 r = (unsigned char)cmap[lookup[lu1][lu2]].r;
503 g = (unsigned char)cmap[lookup[lu1][lu2]].g;
504 b = (unsigned char)cmap[lookup[lu1][lu2]].b;
505 *ptr = ARGB_JOIN(0xff, r, g, b);
506 ptr++;
507 count++;
508 }
509 }
510 }
511 else
512 {
513 for (i = 0;
514 ((i < 65536) && (ptr < end) && (line[i]));
515 i++)
516 {
517 lu1 = (int)line[i] - 32;
518 i++;
519 lu2 = (int)line[i] - 32;
520 if (lu1 < 0) continue;
521 if (lu2 < 0) continue;
522 r = (unsigned char)cmap[lookup[lu1][lu2]].r;
523 g = (unsigned char)cmap[lookup[lu1][lu2]].g;
524 b = (unsigned char)cmap[lookup[lu1][lu2]].b;
525 *ptr = ARGB_JOIN(0xff, r, g, b);
526 ptr++;
527 count++;
528 }
529 }
530 }
531 else
532 {
533 if (transp)
534 {
535 for (i = 0;
536 ((i < 65536) && (ptr < end) && (line[i]));
537 i++)
538 {
539 for (j = 0; j < cpp; j++, i++)
540 {
541 col[j] = line[i];
542 if (col[j] < 32) col[j] = 32;
543 }
544 col[j] = 0;
545 i--;
546 for (j = 0; j < ncolors; j++)
547 {
548 if (!strcmp(col, cmap[j].str))
549 {
550 if (cmap[j].transp)
551 {
552 r = (unsigned char)cmap[j].r;
553 g = (unsigned char)cmap[j].g;
554 b = (unsigned char)cmap[j].b;
555 *ptr = RGB_JOIN(r, g, b);
556 ptr++;
557 count++;
558 }
559 else
560 {
561 r = (unsigned char)cmap[j].r;
562 g = (unsigned char)cmap[j].g;
563 b = (unsigned char)cmap[j].b;
564 *ptr = ARGB_JOIN(0xff, r, g, b);
565 ptr++;
566 count++;
567 }
568 break;
569 }
570 }
571 }
572 }
573 else
574 {
575 for (i = 0;
576 ((i < 65536) && (ptr < end) && (line[i]));
577 i++)
578 {
579 for (j = 0; j < cpp; j++, i++)
580 {
581 col[j] = line[i];
582 }
583 col[j] = 0;
584 i--;
585 for (j = 0; j < ncolors; j++)
586 {
587 if (!strcmp(col, cmap[j].str))
588 {
589 r = (unsigned char)cmap[j].r;
590 g = (unsigned char)cmap[j].g;
591 b = (unsigned char)cmap[j].b;
592 *ptr = ARGB_JOIN(0xff, r, g, b);
593 ptr++;
594 count++;
595 break;
596 }
597 }
598 }
599 }
600 }
601 }
602 }
603 }
604 /* Scan in line from XPM file */
605 if ((!comment) && (quote) && (c != '"'))
606 {
607 if (c < 32) c = 32;
608 else if (c > 127) c = 127;
609 if (c =='\\')
610 {
611 if (++backslash < 2)
612 line[i++] = c;
613 else
614 backslash = 0;
615 }
616 else
617 {
618 backslash = 0;
619 line[i++] = c;
620 }
621 }
622 if (i >= lsz)
623 {
624 lsz += 256;
625 tl = realloc(line, lsz);
626 if (!tl) break;
627 line = tl;
628 }
629 if (((ptr) && ((ptr - evas_cache_image_pixels(ie)) >= (w * h * (int)sizeof(DATA32)))) ||
630 ((context > 1) && (count >= pixels)))
631 break;
632 }
633
634 free(cmap);
635 free(line);
636 fclose(f);
637
638 xpm_parse_done();
639 *error = EVAS_LOAD_ERROR_NONE;
640 return EINA_TRUE;
641}
642
643static Eina_Bool
644evas_image_load_file_head_xpm(Image_Entry *ie, const char *file, const char *key, int *error)
645{
646 return evas_image_load_file_xpm(ie, file, key, 0, error);
647}
648
649static Eina_Bool
650evas_image_load_file_data_xpm(Image_Entry *ie, const char *file, const char *key, int *error)
651{
652 return evas_image_load_file_xpm(ie, file, key, 1, error);
653}
654
655static int
656module_open(Evas_Module *em)
657{
658 if (!em) return 0;
659 _evas_loader_xpm_log_dom = eina_log_domain_register
660 ("evas-xpm", EVAS_DEFAULT_LOG_COLOR);
661 if (_evas_loader_xpm_log_dom < 0)
662 {
663 EINA_LOG_ERR("Can not create a module log domain.");
664 return 0;
665 }
666 em->functions = (void *)(&evas_image_load_xpm_func);
667 return 1;
668}
669
670static void
671module_close(Evas_Module *em __UNUSED__)
672{
673 eina_log_domain_unregister(_evas_loader_xpm_log_dom);
674}
675
676static Evas_Module_Api evas_modapi =
677{
678 EVAS_MODULE_API_VERSION,
679 "xpm",
680 "none",
681 {
682 module_open,
683 module_close
684 }
685};
686
687EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, xpm);
688
689#ifndef EVAS_STATIC_BUILD_XPM
690EVAS_EINA_MODULE_DEFINE(image_loader, xpm);
691#endif