efl/legacy/evas/src/lib/engines/common_8/evas_soft8_main.c

656 lines
18 KiB
C

#include "evas_common_soft8.h"
static Evas_Cache_Image *eci = NULL;
static int reference = 0;
static Image_Entry *_evas_common_soft8_image_new(void);
static void _evas_common_soft8_image_delete(Image_Entry * ie);
static int _evas_common_soft8_image_surface_alloc(Image_Entry * ie, unsigned int w, unsigned int h);
static void _evas_common_soft8_image_surface_delete(Image_Entry * ie);
static DATA32 *_evas_common_soft8_image_surface_pixels(Image_Entry * ie);
static int _evas_common_load_soft8_image_from_file(Image_Entry * ie);
static void _evas_common_soft8_image_unload(Image_Entry * ie);
static void _evas_common_soft8_image_dirty_region(Image_Entry * im, unsigned int x, unsigned int y, unsigned int w, unsigned int h);
static int _evas_common_soft8_image_dirty(Image_Entry * ie_dst,
const Image_Entry * ie_src);
static int _evas_common_soft8_image_ram_usage(Image_Entry * ie);
static int _evas_common_soft8_image_size_set(Image_Entry * ie_dst,
const Image_Entry * ie_im, unsigned int w, unsigned int h);
static int _evas_common_soft8_image_from_copied_data(Image_Entry * ie_dst, unsigned int w, unsigned int h, DATA32 * image_data, int alpha, int cspace);
static int _evas_common_soft8_image_from_data(Image_Entry * ie_dst, unsigned int w, unsigned int h, DATA32 * image_data, int alpha, int cspace);
static int _evas_common_soft8_image_colorspace_set(Image_Entry * ie_dst,
int cspace);
static int _evas_common_load_soft8_image_data_from_file(Image_Entry * ie);
/*
static void
_evas_common_soft8_image_debug(const char* context, Image_Entry *eim)
{
DBG("[8] %p = [%s] {%s,%s} %i [%i|%i]", eim, context, eim->file, eim->key, eim->references, eim->w, eim->h);
}
*/
static const Evas_Cache_Image_Func _evas_common_soft8_image_func = {
_evas_common_soft8_image_new,
_evas_common_soft8_image_delete,
_evas_common_soft8_image_surface_alloc,
_evas_common_soft8_image_surface_delete,
_evas_common_soft8_image_surface_pixels,
_evas_common_load_soft8_image_from_file,
_evas_common_soft8_image_unload,
_evas_common_soft8_image_dirty_region,
_evas_common_soft8_image_dirty,
_evas_common_soft8_image_size_set,
_evas_common_soft8_image_from_copied_data,
_evas_common_soft8_image_from_data,
_evas_common_soft8_image_colorspace_set,
_evas_common_load_soft8_image_data_from_file,
_evas_common_soft8_image_ram_usage,
/* _evas_common_soft8_image_debug */
NULL
};
EAPI void
evas_common_soft8_image_init(void)
{
if (!eci)
eci = evas_cache_image_init(&_evas_common_soft8_image_func);
reference++;
}
EAPI void
evas_common_soft8_image_shutdown(void)
{
if (--reference == 0)
{
// DISABLE for now - something wrong with cache shutdown freeing things
// still in use - rage_thumb segv's now.
//
// actually - i think i see it. cache ref goes to 0 (and thus gets freed)
// because in eng_setup() when a buffer changes size it is FIRST freed
// THEN allocated again - thus brignhjing ref to 0 then back to 1 immediately
// where it should stay at 1. - see evas_engine.c in the buffer enigne for
// example. eng_output_free() is called BEFORE _output_setup(). although this
// is only a SIGNE of the problem. we can patch this up with either freeing
// after the setup (so we just pt a ref of 2 then back to 1), or just
// evas_common_image_init() at the start and evas_common_image_shutdown()
// after it all. really ref 0 should only be reached when no more canvases
// with no more objects exist anywhere.
// ENABLE IT AGAIN, hope it is fixed. Gustavo @ January 22nd, 2009.
//evas_cache_image_shutdown(eci);
//eci = NULL;
}
}
EAPI Evas_Cache_Image *
evas_common_soft8_image_cache_get(void)
{
return eci;
}
static Image_Entry *
_evas_common_soft8_image_new(void)
{
Soft8_Image *im;
im = calloc(1, sizeof(Soft8_Image));
if (!im)
return NULL;
im->stride = -1;
return (Image_Entry *) im;
}
static void
_evas_common_soft8_image_delete(Image_Entry * ie)
{
memset(ie, 0xFF, sizeof(Soft8_Image));
free(ie);
}
static int
_evas_common_soft8_image_surface_alloc(Image_Entry * ie, unsigned int w, unsigned int h)
{
Soft8_Image *im = (Soft8_Image *) ie;
if (im->stride < 0)
im->stride = _calc_stride(w);
im->pixels =
realloc(im->pixels, IMG_BYTE_SIZE(im->stride, h, ie->flags.alpha));
if (!im->pixels)
return -1;
if (ie->flags.alpha)
{
im->alpha = (DATA8 *) (im->pixels + (im->stride * h));
im->flags.free_alpha = 0;
}
im->flags.free_pixels = 1;
return 0;
}
static void
_evas_common_soft8_image_surface_delete(Image_Entry * ie)
{
Soft8_Image *im = (Soft8_Image *) ie;
if (im->flags.free_pixels)
free(im->pixels);
im->pixels = NULL;
im->flags.free_pixels = 0;
if (im->flags.free_alpha)
free(im->alpha);
im->alpha = NULL;
im->flags.free_alpha = 0;
}
static DATA32 *
_evas_common_soft8_image_surface_pixels(Image_Entry * ie __UNUSED__)
{
abort();
return NULL;
}
static int
_evas_common_load_soft8_image_from_file(Image_Entry * ie)
{
Soft8_Image *sim = (Soft8_Image *) ie;
RGBA_Image *im;
int error = 0;
im = (RGBA_Image *) evas_cache_image_request(evas_common_image_cache_get(),
sim->cache_entry.file,
sim->cache_entry.key,
&sim->cache_entry.load_opts,
&error);
sim->source = im;
if (!sim->source)
return -1;
sim->cache_entry.w = sim->source->cache_entry.w;
sim->cache_entry.h = sim->source->cache_entry.h;
ie->flags.alpha = im->cache_entry.flags.alpha;
if (sim->stride < 0)
sim->stride = _calc_stride(sim->cache_entry.w);
return 0;
}
static void
_evas_common_soft8_image_unload(Image_Entry * ie __UNUSED__)
{
}
static void
_evas_common_soft8_image_dirty_region(Image_Entry * im __UNUSED__,
unsigned int x __UNUSED__,
unsigned int y __UNUSED__,
unsigned int w __UNUSED__,
unsigned int h __UNUSED__)
{
}
static int
_evas_common_soft8_image_dirty(Image_Entry * ie_dst, const Image_Entry * ie_src)
{
Soft8_Image *dst = (Soft8_Image *) ie_dst;
Soft8_Image *src = (Soft8_Image *) ie_src;
evas_cache_image_load_data(&src->cache_entry);
evas_cache_image_surface_alloc(&dst->cache_entry,
src->cache_entry.w, src->cache_entry.h);
/* evas_common_blit_rectangle(src, dst, 0, 0, src->cache_entry.w, src->cache_entry.h, 0, 0); */
return 0;
}
static int
_evas_common_soft8_image_ram_usage(Image_Entry * ie)
{
Soft8_Image *im = (Soft8_Image *) ie;
if (im->pixels && im->flags.free_pixels)
return IMG_BYTE_SIZE(im->stride, im->cache_entry.h, ie->flags.alpha);
return 0;
}
static int
_evas_common_soft8_image_size_set(Image_Entry * ie_dst,
const Image_Entry * ie_im,
unsigned int w __UNUSED__,
unsigned int h __UNUSED__)
{
Soft8_Image *dst = (Soft8_Image *) ie_dst;
Soft8_Image *im = (Soft8_Image *) ie_im;
dst->flags = im->flags;
return 0;
}
static int
_evas_common_soft8_image_from_data(Image_Entry * ie_dst,
unsigned int w, unsigned int h,
DATA32 * image_data, int alpha,
int cspace __UNUSED__)
{
Soft8_Image *im = (Soft8_Image *) ie_dst;
/* FIXME: handle colorspace */
ie_dst->w = w;
ie_dst->h = h;
ie_dst->flags.alpha = alpha;
im->flags.free_pixels = 0;
im->flags.free_alpha = 0;
if (im->stride < 0)
im->stride = _calc_stride(w);
/* FIXME: That's bad, the application must be aware of the engine internal. */
im->pixels = (DATA8 *) image_data;
if (ie_dst->flags.alpha)
im->alpha = (DATA8 *) (im->pixels + (im->stride * h));
return 0;
}
static int
_evas_common_soft8_image_from_copied_data(Image_Entry * ie_dst,
unsigned int w __UNUSED__,
unsigned int h,
DATA32 * image_data,
int alpha __UNUSED__,
int cspace __UNUSED__)
{
Soft8_Image *im = (Soft8_Image *) ie_dst;
/* FIXME: handle colorspace */
if (image_data)
memcpy(im->pixels, image_data,
IMG_BYTE_SIZE(im->stride, h, ie_dst->flags.alpha));
else
memset(im->pixels, 0, IMG_BYTE_SIZE(im->stride, h, ie_dst->flags.alpha));
return 0;
}
static int
_evas_common_soft8_image_colorspace_set(Image_Entry * ie_dst __UNUSED__,
int cspace __UNUSED__)
{
/* FIXME: handle colorspace */
return 0;
}
static int
_evas_common_load_soft8_image_data_from_file(Image_Entry * ie)
{
Soft8_Image *im = (Soft8_Image *) ie;
if (im->pixels)
return 0;
if (!im->source)
return -1;
evas_cache_image_load_data(&im->source->cache_entry);
if (im->source->image.data)
{
DATA32 *sp;
evas_cache_image_surface_alloc(&im->cache_entry,
im->source->cache_entry.w,
im->source->cache_entry.h);
sp = im->source->image.data;
if (im->alpha)
evas_common_soft8_image_convert_from_rgba(im, sp);
else
evas_common_soft8_image_convert_from_rgb(im, sp);
}
evas_cache_image_drop(&im->source->cache_entry);
im->source = NULL;
return 0;
}
/* Soft16_Image * */
/* evas_common_soft16_image_new(int w, unsigned int h, unsigned int stride, int have_alpha, DATA16 *pixels, */
/* int copy) */
/* { */
/* Soft16_Image *im; */
/* if (stride < 0) stride = _calc_stride(w); */
/* im = evas_common_soft16_image_alloc(w, h, stride, have_alpha, copy); */
/* if (!im) return NULL; */
/* if (pixels) */
/* { */
/* if (copy) */
/* memcpy(im->pixels, pixels, IMG_BYTE_SIZE(stride, h, have_alpha)); */
/* else */
/* { */
/* im->pixels = pixels; */
/* if (have_alpha) im->alpha = (DATA8 *)(im->pixels + (stride * h)); */
/* } */
/* } */
/* return im; */
/* } */
static inline void
_get_clip(const RGBA_Draw_Context * dc, const Soft8_Image * im,
Eina_Rectangle * clip)
{
if (dc->clip.use)
{
EINA_RECTANGLE_SET(clip, dc->clip.x, dc->clip.y, dc->clip.w,
dc->clip.h);
if (clip->x < 0)
{
clip->w += clip->x;
clip->x = 0;
}
if (clip->y < 0)
{
clip->h += clip->y;
clip->y = 0;
}
if ((clip->x + clip->w) > (int)im->cache_entry.w)
clip->w = im->cache_entry.w - clip->x;
if ((clip->y + clip->h) > (int)im->cache_entry.h)
clip->h = im->cache_entry.h - clip->y;
}
else
{
EINA_RECTANGLE_SET(clip, 0, 0, im->cache_entry.w, im->cache_entry.h);
}
}
static inline int
_is_empty_rectangle(const Eina_Rectangle * r)
{
return (r->w < 1) || (r->h < 1);
}
static inline void
_shrink(int *s_pos, int *s_size, int pos, int size)
{
int d;
d = (*s_pos) - pos;
if (d < 0)
{
(*s_size) += d;
(*s_pos) = pos;
}
d = size + pos - (*s_pos);
if ((*s_size) > d)
(*s_size) = d;
}
static int
_soft8_adjust_areas(Eina_Rectangle * src,
int src_max_x, int src_max_y, Eina_Rectangle * dst,
int dst_max_x, int dst_max_y, Eina_Rectangle * dst_clip)
{
if (_is_empty_rectangle(src) ||
_is_empty_rectangle(dst) || _is_empty_rectangle(dst_clip))
return 0;
/* shrink clip */
_shrink(&dst_clip->x, &dst_clip->w, dst->x, dst->w);
_shrink(&dst_clip->y, &dst_clip->h, dst->y, dst->h);
if (_is_empty_rectangle(dst_clip))
return 0;
/* sanitise x */
if (src->x < 0)
{
dst->x -= (src->x * dst->w) / src->w;
dst->w += (src->x * dst->w) / src->w;
src->w += src->x;
src->x = 0;
}
if (src->x >= src_max_x)
return 0;
if ((src->x + src->w) > src_max_x)
{
dst->w = (dst->w * (src_max_x - src->x)) / (src->w);
src->w = src_max_x - src->x;
}
if (dst->w <= 0)
return 0;
if (src->w <= 0)
return 0;
if (dst_clip->x < 0)
{
dst_clip->w += dst_clip->x;
dst_clip->x = 0;
}
if (dst_clip->w <= 0)
return 0;
if (dst_clip->x >= dst_max_x)
return 0;
_shrink(&dst_clip->x, &dst_clip->w, 0, dst_max_x);
if (dst_clip->w <= 0)
return 0;
/* sanitise y */
if (src->y < 0)
{
dst->y -= (src->y * dst->h) / src->h;
dst->h += (src->y * dst->h) / src->h;
src->h += src->y;
src->y = 0;
}
if (src->y >= src_max_y)
return 0;
if ((src->y + src->h) > src_max_y)
{
dst->h = (dst->h * (src_max_y - src->y)) / (src->h);
src->h = src_max_y - src->y;
}
if (dst->h <= 0)
return 0;
if (src->h <= 0)
return 0;
if (dst_clip->y < 0)
{
dst_clip->h += dst_clip->y;
dst_clip->y = 0;
}
if (dst_clip->h <= 0)
return 0;
if (dst_clip->y >= dst_max_y)
return 0;
_shrink(&dst_clip->y, &dst_clip->h, 0, dst_max_y);
if (dst_clip->h <= 0)
return 0;
return 1;
}
static void
_soft8_image_draw_sampled_int(Soft8_Image * src, Soft8_Image * dst,
RGBA_Draw_Context * dc,
Eina_Rectangle sr, Eina_Rectangle dr)
{
Eina_Rectangle cr;
if (!
(RECTS_INTERSECT
(dr.x, dr.y, dr.w, dr.h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
return;
if (!
(RECTS_INTERSECT
(sr.x, sr.y, sr.w, sr.h, 0, 0, src->cache_entry.w, src->cache_entry.h)))
return;
_get_clip(dc, dst, &cr);
if (!_soft8_adjust_areas
(&sr, src->cache_entry.w, src->cache_entry.h, &dr, dst->cache_entry.w,
dst->cache_entry.h, &cr))
return;
if ((dr.w == sr.w) && (dr.h == sr.h))
evas_common_soft8_image_draw_unscaled(src, dst, dc, sr, dr, cr);
else
evas_common_soft8_image_draw_scaled_sampled(src, dst, dc, sr, dr, cr);
}
EAPI void
evas_common_soft8_image_draw(Soft8_Image * src, Soft8_Image * dst,
RGBA_Draw_Context * dc,
int src_region_x, int src_region_y,
int src_region_w, int src_region_h,
int dst_region_x, int dst_region_y,
int dst_region_w, int dst_region_h,
int smooth __UNUSED__)
{
static Cutout_Rects *rects = NULL;
Eina_Rectangle sr, dr;
Cutout_Rect *r;
struct RGBA_Draw_Context_clip clip_bkp;
int i;
/* handle cutouts here! */
EINA_RECTANGLE_SET(&dr, dst_region_x, dst_region_y, dst_region_w,
dst_region_h);
if (_is_empty_rectangle(&dr))
return;
if (!
(RECTS_INTERSECT
(dr.x, dr.y, dr.w, dr.h, 0, 0, dst->cache_entry.w, dst->cache_entry.h)))
return;
EINA_RECTANGLE_SET(&sr, src_region_x, src_region_y, src_region_w,
src_region_h);
if (_is_empty_rectangle(&sr))
return;
if (!
(RECTS_INTERSECT
(sr.x, sr.y, sr.w, sr.h, 0, 0, src->cache_entry.w, src->cache_entry.h)))
return;
/* no cutouts - cut right to the chase */
if (!dc->cutout.rects)
{
_soft8_image_draw_sampled_int(src, dst, dc, sr, dr);
return;
}
/* save out clip info */
clip_bkp = dc->clip;
evas_common_draw_context_clip_clip(dc, 0, 0, dst->cache_entry.w,
dst->cache_entry.h);
evas_common_draw_context_clip_clip(dc, dst_region_x, dst_region_y,
dst_region_w, dst_region_h);
/* our clip is 0 size.. abort */
if ((dc->clip.w <= 0) || (dc->clip.h <= 0))
{
dc->clip = clip_bkp;
return;
}
rects = evas_common_draw_context_apply_cutouts(dc, rects);
for (i = 0; i < rects->active; i++)
{
r = rects->rects + i;
evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
_soft8_image_draw_sampled_int(src, dst, dc, sr, dr);
}
dc->clip = clip_bkp;
}
EAPI Soft8_Image *
evas_common_soft8_image_alpha_set(Soft8_Image * im, int have_alpha)
{
Soft8_Image *new_im;
if (im->cache_entry.flags.alpha == have_alpha)
return im;
new_im = (Soft8_Image *) evas_cache_image_alone(&im->cache_entry);
new_im->cache_entry.flags.alpha = have_alpha;
if (im->cache_entry.w > 0 && im->cache_entry.h)
new_im =
(Soft8_Image *) evas_cache_image_size_set(&new_im->cache_entry,
im->cache_entry.w,
im->cache_entry.h);
return new_im;
}
/* Soft16_Image * */
/* evas_common_soft16_image_size_set(Soft16_Image *old_im, unsigned int w, unsigned int h) */
/* { */
/* Soft16_Image *new_im; */
/* DATA16 *dp, *sp; */
/* int i, cw, ch, ew; */
/* if ((old_im->cache_entry.w == w) && (old_im->cache_entry.h == h)) return old_im; */
/* new_im = evas_common_soft16_image_new(w, h, -1, old_im->flags.have_alpha, NULL, 1); */
/* if (old_im->cache_entry.w < new_im->cache_entry.w) */
/* cw = old_im->cache_entry.w; */
/* else */
/* cw = new_im->cache_entry.w; */
/* ew = new_im->cache_entry.w - cw; */
/* if (old_im->cache_entry.h < new_im->cache_entry.h) */
/* ch = old_im->cache_entry.h; */
/* else */
/* ch = new_im->cache_entry.h; */
/* dp = new_im->pixels; */
/* sp = old_im->pixels; */
/* for (i = 0; i < ch; i++) */
/* { */
/* memcpy(dp, sp, cw * sizeof(DATA16)); */
/* if (ew > 0) memset(dp, 0, ew * sizeof(DATA16)); */
/* dp += new_im->stride; */
/* sp += old_im->stride; */
/* } */
/* if (old_im->flags.have_alpha) */
/* { */
/* DATA8 *dp, *sp; */
/* dp = new_im->alpha; */
/* sp = old_im->alpha; */
/* for (i = 0; i < ch; i++) */
/* { */
/* memcpy(dp, sp, cw * sizeof(DATA8)); */
/* if (ew > 0) memset(dp, 0, ew * sizeof(DATA8)); */
/* dp += new_im->stride; */
/* sp += old_im->stride; */
/* } */
/* } */
/* evas_cache_image_drop(&old_im->cache_entry); */
/* return new_im; */
/* } */