assert(eim->src);
assert(eim->cache);
- if (eim->flags.loaded) return ;
+ if (eim->flags.loaded) return;
if (eim->src)
evas_cache_image_load_data(eim->src);
static Eina_Bool running = EINA_FALSE;
-static void* _evas_cache_background_load(void *);
+static void *_evas_cache_background_load(void *);
#endif
#define FREESTRC(Var) \
while (im->targets)
{
Evas_Cache_Target *tmp = im->targets;
-
+
evas_async_events_put(tmp->target, EVAS_CALLBACK_IMAGE_PRELOADED, NULL,
(void (*)(void*, Evas_Callback_Type, void*))evas_object_event_callback_call);
im->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(im->targets), EINA_INLIST_GET(im->targets));
if (l->ie == ie)
{
Evas_Cache_Target *tg;
-
- if (target) {
- EINA_INLIST_FOREACH(ie->targets, tg)
- {
- if (tg->target == target) {
- ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
- free(tg);
- break;
- }
- }
- } else {
- _evas_cache_image_async_call__locked(ie);
-
- while (ie->targets)
- {
- tg = ie->targets;
- ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
- free(tg);
- }
- }
-
+
+ if (target)
+ {
+ EINA_INLIST_FOREACH(ie->targets, tg)
+ {
+ if (tg->target == target)
+ {
+ ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
+ free(tg);
+ break;
+ }
+ }
+ }
+ else
+ {
+ _evas_cache_image_async_call__locked(ie);
+
+ while (ie->targets)
+ {
+ tg = ie->targets;
+ ie->targets = (Evas_Cache_Target*) eina_inlist_remove(EINA_INLIST_GET(ie->targets), EINA_INLIST_GET(tg));
+ free(tg);
+ }
+ }
+
if (!ie->targets)
{
preload = eina_inlist_remove(preload,
EINA_INLIST_GET(l));
free(l);
}
-
+
break;
}
}
file_length = strlen(file);
key_length = key ? strlen(key) : 6;
- size = file_length + key_length + 64;
+ size = file_length + key_length + 128;
hkey = alloca(sizeof (char) * size);
memcpy(hkey, file, file_length);
(lo &&
(lo->scale_down_by == 0) &&
(lo->dpi == 0.0) &&
- ((lo->w == 0) || (lo->h == 0))))
+ ((lo->w == 0) || (lo->h == 0)) &&
+ ((lo->region.w == 0) || (lo->region.w == 0))
+ ))
{
lo = &prevent;
- if (key)
- format = "%s//://%s";
- else
- format = "%s//://%p";
+// if (key)
+// format = "%s//://%s";
+// else
+// format = "%s//://%p";
}
else
{
size += 1;
size += eina_convert_xtoa(lo->h, hkey + size);
+
+ hkey[size] = '/';
+ size += 1;
+
+ size += eina_convert_xtoa(lo->region.x, hkey + size);
+
+ hkey[size] = '+';
+ size += 1;
+
+ size += eina_convert_xtoa(lo->region.y, hkey + size);
+
+ hkey[size] = '.';
+ size += 1;
+
+ size += eina_convert_xtoa(lo->region.w, hkey + size);
+
+ hkey[size] = 'x';
+ size += 1;
+
+ size += eina_convert_xtoa(lo->region.h, hkey + size);
}
hkey[size] = '\0';
_evas_cache_background_load(void *data)
{
(void) data;
-
- restart:
+
+ restart:
while (preload)
{
pthread_mutex_lock(&mutex);
if (preload)
{
Evas_Cache_Preload *tmp = (Evas_Cache_Preload*) preload;
-
+
current = tmp->ie;
preload = eina_inlist_remove(preload, preload);
current->channel++;
cache = current->cache;
- error = cache->func.load(current);
- if (cache->func.debug)
- cache->func.debug("load", current);
-
- if (error)
- {
- _evas_cache_image_entry_surface_alloc(cache, current,
- current->w, current->h);
- current->flags.loaded = 0;
- }
- else
- {
- current->flags.loaded = 1;
- }
-
+ if (!current->flags.loaded)
+ {
+ error = cache->func.load(current);
+ if (cache->func.debug)
+ cache->func.debug("load", current);
+
+ if (error)
+ {
+ _evas_cache_image_entry_surface_alloc(cache, current,
+ current->w, current->h);
+ current->flags.loaded = 0;
+ }
+ else
+ {
+ current->flags.loaded = 1;
+ }
+ }
+
current->flags.preload = 0;
current->channel = pchannel;
evas_module_use(em);
if (evas_image_load_func && evas_image_load_func->file_head(ie, ie->file, ie->key))
{
- ie->info.module = (void*) em;
- ie->info.loader = (void*) evas_image_load_func;
- evas_module_ref((Evas_Module*) ie->info.module);
+ ie->info.module = (void *)em;
+ ie->info.loader = (void *)evas_image_load_func;
+ evas_module_ref((Evas_Module *)ie->info.module);
return EINA_FALSE;
}
{
for (i = 0, ++dot; i < (sizeof (loaders) / sizeof (struct ext_loader_s)); ++i)
{
- if (!strcasecmp (dot, loaders[i].extention))
+ if (!strcasecmp(dot, loaders[i].extention))
{
loader = loaders[i].loader;
break;
/* This is our last chance, try all known image loader. */
/* FIXME: We could use eina recursive module search ability. */
- for (i = 0; i < sizeof (loaders_name) / sizeof (char *); ++i)
+ for (i = 0; i < sizeof (loaders_name) / sizeof (char *); i++)
{
em = evas_module_find_type(EVAS_MODULE_TYPE_IMAGE_LOADER, loaders_name[i]);
if (em)
evas_image_load_func = ie->info.loader;
evas_module_use((Evas_Module*) ie->info.module);
if (!evas_image_load_func->file_data(ie, ie->file, ie->key))
- return -1;
+ {
+ return -1;
+ }
// evas_module_unref((Evas_Module*) ie->info.module);
// ie->info.module = NULL;
if (!ie->flags.loaded) return;
if ((!ie->info.module) && (!ie->data1)) return;
if (!ie->file) return;
-
+
ie->flags.loaded = 0;
if ((im->cs.data) && (im->image.data))
/* use exact rects for updates not tiles */
/* #define RECTUPDATE */
#define TILESIZE 8
-#define IMG_MAX_SIZE 65536
+#define IMG_MAX_SIZE 65000
+
+#define IMG_TOO_BIG(w, h) \
+ ((((unsigned long long)w) * ((unsigned long long)h)) > \
+ (1 << (29 * (sizeof(void *) / 4))))
#ifdef BUILD_SMALL_DITHER_MASK
# define DM_TABLE _evas_dither_44
}
w = header[1];
h = header[2];
- if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
+ if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
+ IMG_TOO_BIG(w, h))
{
free(ret);
e_db_close(db);
}
w = header[1];
h = header[2];
- if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
+ if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
+ IMG_TOO_BIG(w, h))
{
free(ret);
e_db_close(db);
if (!ef) return 0;
ok = eet_data_image_header_read(ef, key,
&w, &h, &alpha, &compression, &quality, &lossy);
+ if (IMG_TOO_BIG(w, h)) goto on_error;
if (!ok) goto on_error;
if (alpha) ie->flags.alpha = 1;
ie->w = w;
if (!ef) return 0;
ok = eet_data_image_header_read(ef, key,
&w, &h, &alpha, &compression, &quality, &lossy);
+ if (IMG_TOO_BIG(w, h)) goto on_error;
if (!ok) goto on_error;
evas_cache_image_surface_alloc(ie, w, h);
ok = eet_data_image_read_to_surface(ef, key, 0, 0,
}
w = gif->Image.Width;
h = gif->Image.Height;
- if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
+ if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
+ IMG_TOO_BIG(w, h))
{
DGifCloseFile(gif);
return 0;
/* head decoding */
w = cinfo.output_width;
h = cinfo.output_height;
- if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0))
- {
- RECTS_CLIP_TO_RECT(ie->load_opts.region.x, ie->load_opts.region.y,
- ie->load_opts.region.w, ie->load_opts.region.h,
- 0, 0, w, h);
- }
- if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
+ if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
+ (IMG_TOO_BIG(w, h)))
{
jpeg_destroy_decompress(&cinfo);
return 0;
jpeg_start_decompress(&cinfo);
}
- // FIXME: handle region if specified
ie->w = cinfo.output_width;
ie->h = cinfo.output_height;
+
+ // be nice and clip region to image. if its totally outside, fail load
+ if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0))
+ {
+ RECTS_CLIP_TO_RECT(ie->load_opts.region.x, ie->load_opts.region.y,
+ ie->load_opts.region.w, ie->load_opts.region.h,
+ 0, 0, ie->w, ie->h);
+ if ((ie->load_opts.region.w <= 0) || (ie->load_opts.region.h <= 0))
+ {
+ jpeg_destroy_decompress(&cinfo);
+ return 0;
+ }
+ ie->w = ie->load_opts.region.w;
+ ie->h = ie->load_opts.region.h;
+ }
/* end head decoding */
jpeg_destroy_decompress(&cinfo);
DATA8 *ptr, *line[16], *data;
DATA32 *ptr2;
int x, y, l, i, scans, count;
+ int region = 0;
if (!f) return 0;
cinfo.err = jpeg_std_error(&(jerr.pub));
w = cinfo.output_width;
h = cinfo.output_height;
+ if ((ie->load_opts.region.w > 0) && (ie->load_opts.region.h > 0))
+ region = 1;
if ((w != ie->w) || (h != ie->h))
{
- jpeg_destroy_decompress(&cinfo);
- return 0;
+ // OK. region decode happening. a sub-set of the image
+// jpeg_destroy_decompress(&cinfo);
+// return 0;
+ }
+ if ((region) &&
+ ((ie->w != ie->load_opts.region.w) || (ie->h != ie->load_opts.region.h)))
+ {
+ ie->w = ie->load_opts.region.w;
+ ie->h = ie->load_opts.region.h;
}
if (!(((cinfo.out_color_space == JCS_RGB) &&
return 0;
}
data = alloca(w * 16 * cinfo.output_components);
- evas_cache_image_surface_alloc(ie, w, h);
+ evas_cache_image_surface_alloc(ie, ie->w, ie->h);
if (ie->flags.loaded)
{
jpeg_destroy_decompress(&cinfo);
- return 0;
+ return 1;
}
ptr2 = evas_cache_image_pixels(ie);
count = 0;
/* We handle first CMYK (4 components) */
if (cinfo.output_components == 4)
{
+ // FIXME: handle region
for (i = 0; i < cinfo.rec_outbuf_height; i++)
line[i] = data + (i * w * 4);
for (l = 0; l < h; l += cinfo.rec_outbuf_height)
/* We handle then RGB with 3 components */
else if (cinfo.output_components == 3)
{
+ if (region)
+ {
+ printf("R| %p %5ix%5i %s: %5i %5i %5ix%5i\n",
+ ie,
+ ie->w, ie->h,
+ ie->file,
+ ie->load_opts.region.x,
+ ie->load_opts.region.y,
+ ie->load_opts.region.w,
+ ie->load_opts.region.h);
+ }
for (i = 0; i < cinfo.rec_outbuf_height; i++)
line[i] = data + (i * w * 3);
for (l = 0; l < h; l += cinfo.rec_outbuf_height)
scans = cinfo.rec_outbuf_height;
if ((h - l) < scans) scans = h - l;
ptr = data;
- for (y = 0; y < scans; y++)
- {
- for (x = 0; x < w; x++)
- {
- *ptr2 =
- (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
- ptr += 3;
- ptr2++;
- }
+ if (!region)
+ {
+ for (y = 0; y < scans; y++)
+ {
+ for (x = 0; x < w; x++)
+ {
+ *ptr2 =
+ (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
+ ptr += 3;
+ ptr2++;
+ }
+ }
}
+ else
+ {
+ // if line # > region last line, break
+ if (l >= (ie->load_opts.region.y + ie->load_opts.region.h))
+ {
+ jpeg_destroy_decompress(&cinfo);
+ return 1;
+ }
+ // els if scan block intersects region start or later
+ else if ((l + scans) >
+ (ie->load_opts.region.y))
+ {
+ for (y = 0; y < scans; y++)
+ {
+ if (((y + l) >= ie->load_opts.region.y) &&
+ ((y + l) < (ie->load_opts.region.y + ie->load_opts.region.h)))
+ {
+ ptr += (3 * ie->load_opts.region.x);
+ for (x = 0; x < ie->load_opts.region.w; x++)
+ {
+ *ptr2 =
+ (0xff000000) | ((ptr[0]) << 16) | ((ptr[1]) << 8) | (ptr[2]);
+ ptr += 3;
+ ptr2++;
+ }
+ ptr += (3 * (w - (ie->load_opts.region.x + ie->load_opts.region.w)));
+ }
+ else
+ ptr += (3 * w);
+ }
+ }
+ }
}
}
/* We finally handle RGB with 1 component */
png_get_IHDR(png_ptr, info_ptr, (png_uint_32 *) (&w32),
(png_uint_32 *) (&h32), &bit_depth, &color_type,
&interlace_type, NULL, NULL);
- if ((w32 < 1) || (h32 < 1) || (w32 > IMG_MAX_SIZE) || (h32 > IMG_MAX_SIZE))
+ if ((w32 < 1) || (h32 < 1) || (w32 > IMG_MAX_SIZE) || (h32 > IMG_MAX_SIZE) ||
+ IMG_TOO_BIG(w32, h32))
{
png_destroy_read_struct(&png_ptr, &info_ptr, NULL);
goto close_file;
rsvg_handle_get_dimensions(rsvg, &dim);
w = dim.width;
h = dim.height;
- if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE))
+ if ((w < 1) || (h < 1) || (w > IMG_MAX_SIZE) || (h > IMG_MAX_SIZE) ||
+ IMG_TOO_BIG(w, h))
{
// rsvg_handle_close(rsvg, NULL);
g_object_unref(rsvg);
if (tiff_image.alpha != EXTRASAMPLE_UNSPECIFIED)
ie->flags.alpha = 1;
if ((tiff_image.width < 1) || (tiff_image.height < 1) ||
- (tiff_image.width > IMG_MAX_SIZE) || (tiff_image.height > IMG_MAX_SIZE))
+ (tiff_image.width > IMG_MAX_SIZE) || (tiff_image.height > IMG_MAX_SIZE) ||
+ IMG_TOO_BIG(tiff_image.width, tiff_image.height))
{
TIFFClose(tif);
return 0;
xpm_parse_done();
return 0;
}
+ if (IMG_TOO_BIG(w, h))
+ {
+ fprintf(stderr,
+ "XPM ERROR: Image just too big to ever allocate\n");
+ free(line);
+ fclose(f);
+ xpm_parse_done();
+ return 0;
+ }
if (!cmap)
{