9 #include "evas_common.h"
10 #include "evas_private.h"
13 #include <sys/types.h>
19 static Eina_Bool evas_image_load_file_head_generic(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
20 static Eina_Bool evas_image_load_file_data_generic(Image_Entry *ie, const char *file, const char *key, int *error) EINA_ARG_NONNULL(1, 2, 4);
22 Evas_Image_Load_Func evas_image_load_generic_func =
25 evas_image_load_file_head_generic,
26 evas_image_load_file_data_generic,
31 illegal_char(const char *str)
35 for (p = str; *p; p++)
37 if (*p < '-') return EINA_TRUE;
38 if (*p == '/') return EINA_TRUE;
39 if (*p == ';') return EINA_TRUE;
40 if (*p == ':') return EINA_TRUE;
41 if (*p == '<') return EINA_TRUE;
42 if (*p == '>') return EINA_TRUE;
43 if (*p == '?') return EINA_TRUE;
44 if (*p == '[') return EINA_TRUE;
45 if (*p == '\\') return EINA_TRUE;
46 if (*p == ']') return EINA_TRUE;
47 if (*p == '`') return EINA_TRUE;
48 if (*p == '{') return EINA_TRUE;
49 if (*p == '|') return EINA_TRUE;
50 if (*p == '}') return EINA_TRUE;
51 if (*p == '~') return EINA_TRUE;
52 if (*p == 0x7f) return EINA_TRUE;
58 escape_copy(const char *src, char *dst)
63 for (s = src, d = dst; *s; s++, d++)
65 // FIXME: escape tab, newline linefeed and friends
95 dotcat(char *dest, const char *src)
97 int len = strlen(dest);
101 for (d = dest + len, s = src; *s; d++, s++) *d = tolower(*s);
106 _load(Image_Entry *ie, const char *file, const char *key, int *error, Eina_Bool get_data)
108 Eina_Bool res = EINA_FALSE;
109 int w = 0, h = 0, alpha = 0;
110 const char *dot1 = NULL, *dot2 = NULL, *end, *p;
111 char *cmd = NULL, decoders[3][128], buf[4096];
112 char *loader = "/evas/utils/evas_image_loader";
113 char *img_loader = NULL;
115 // eg $libdir/evas/generic_loaders
116 int cmd_len, len, decoders_num = 0, try_count = 0;
118 char *tmpfname = NULL, *shmfname = NULL;
122 libdir = _evas_module_libdir_get();
123 cmd_len = strlen(libdir);
124 cmd_len += strlen(loader);
125 img_loader = alloca(cmd_len + 1);
126 strcpy(img_loader, libdir);
127 strcat(img_loader, loader);
128 // params excluding file, key and loadopts
130 cmd_len += strlen(file) * 2;
131 if (key) cmd_len += strlen(key) * 2;
132 cmd = alloca(cmd_len + 1);
137 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
141 for (p = end - 1; p >= file; p--)
143 if ((!dot1) && (*p == '.')) dot1 = p;
144 else if ((!dot2) && (*p == '.')) dot2 = p;
145 else if ((dot1) && (dot2)) break;
149 // double extn not too long
150 if (((end - dot2) <= 10) && (!illegal_char(dot2)))
152 strcpy(&(decoders[decoders_num][0]), img_loader);
153 dotcat(&(decoders[decoders_num][0]), dot2);
156 // single extn not too long
157 if (((end - dot1) <= 5) && (!illegal_char(dot1)))
159 strcpy(&(decoders[decoders_num][0]), img_loader);
160 dotcat(&(decoders[decoders_num][0]), dot1);
163 strcpy(decoders[decoders_num], img_loader);
168 // single extn not too long
169 if (((end - dot1) <= 5) && (!illegal_char(dot1)))
171 strcpy(&(decoders[decoders_num][0]), img_loader);
172 dotcat(&(decoders[decoders_num][0]), dot1);
175 strcpy(decoders[decoders_num], img_loader);
180 strcpy(decoders[decoders_num], img_loader);
184 for (try_count = 0; try_count < decoders_num; try_count++)
186 // FIXME: strcats could be more efficient, not that it matters much
187 // here as we are about to build a cmd to exec via a shell that
188 // will interpret shell stuff and path hunt that will then exec the
189 // program itself that will dynamically link that will again
190 // parse the arguments and finally do something...
191 strcpy(cmd, decoders[try_count]);
193 // filename first arg
195 escape_copy(file, cmd + len);
198 strcat(cmd, " -head ");
202 strcat(cmd, " -key ");
204 escape_copy(key, cmd + len);
206 if (ie->load_opts.scale_down_by > 1)
208 strcat(cmd, " -opt-scale-down-by ");
209 snprintf(buf, sizeof(buf), "%i", ie->load_opts.scale_down_by);
212 if (ie->load_opts.dpi > 0.0)
214 strcat(cmd, " -opt-dpi ");
215 snprintf(buf, sizeof(buf), "%i", (int)(ie->load_opts.dpi * 1000.0));
218 if ((ie->load_opts.w > 0) &&
219 (ie->load_opts.h > 0))
221 strcat(cmd, " -opt-size ");
222 snprintf(buf, sizeof(buf), "%i %i", ie->load_opts.w, ie->load_opts.h);
230 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
233 while (fgets(buf, sizeof(buf), f))
238 if ((buf[len - 1] == '\n')) buf[len - 1] = 0;
239 if (!strncmp(buf, "size ", 5))
243 len = sscanf(buf, "%*s %i %i", &tw, &th);
246 if ((tw > 0) && (th > 0))
253 else if (!strncmp(buf, "alpha ", 6))
257 len = sscanf(buf, "%*s %i", &ta);
263 else if (!strncmp(buf, "tmpfile ", 8))
269 else if (!strncmp(buf, "shmfile ", 8))
275 else if (!strncmp(buf, "data", 4))
280 else if (!strncmp(buf, "done", 4))
288 if ((!read_data) && (!tmpfname) && (!shmfname))
290 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
293 if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
296 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
299 body = evas_cache_image_pixels(ie);
302 if ((w != (int)ie->w) || (h != (int)ie->h))
304 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
308 if (alpha) ie->flags.alpha = 1;
314 if (!body) evas_cache_image_surface_alloc(ie, ie->w, ie->h);
315 body = evas_cache_image_pixels(ie);
318 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
322 if ((tmpfname) || (shmfname))
328 fd = open(tmpfname, O_RDONLY, S_IRUSR);
331 fd = shm_open(shmfname, O_RDONLY, S_IRUSR);
337 eina_mmap_safety_enabled_set(EINA_TRUE);
340 addr = mmap(NULL, w * h * sizeof(DATA32),
341 PROT_READ, MAP_SHARED, fd, 0);
342 if (addr != MAP_FAILED)
344 memcpy(body, addr, w * h * sizeof(DATA32));
345 munmap(addr, w * h * sizeof(DATA32));
357 shm_unlink(shmfname);
363 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
369 if (fread(body, w * h * sizeof(DATA32), 1, f) != 1)
371 *error = EVAS_LOAD_ERROR_CORRUPT_FILE;
378 *error = EVAS_LOAD_ERROR_NONE;
386 evas_image_load_file_head_generic(Image_Entry *ie, const char *file, const char *key, int *error)
388 return _load(ie, file, key, error, EINA_FALSE);
392 evas_image_load_file_data_generic(Image_Entry *ie, const char *file, const char *key, int *error)
396 body = evas_cache_image_pixels(ie);
397 if (!body) return _load(ie, file, key, error, EINA_TRUE);
398 *error = EVAS_LOAD_ERROR_NONE;
403 module_open(Evas_Module *em)
406 em->functions = (void *)(&evas_image_load_generic_func);
411 module_close(Evas_Module *em __UNUSED__)
415 static Evas_Module_Api evas_modapi =
417 EVAS_MODULE_API_VERSION,
426 EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, generic);
428 #ifndef EVAS_STATIC_BUILD_GENERIC
429 EVAS_EINA_MODULE_DEFINE(image_loader, generic);