forked from enlightenment/efl
evas: add infrastructure to feed 9 patch information from file loader to image object.
This is just the plumbing that feed data provided along android 9 patch image for example into Evas object image new stretch and content region infrastructure for rendering them properly. Reviewed-by: Hermet Park <hermetpark@gmail.com> Differential Revision: https://phab.enlightenment.org/D9102
This commit is contained in:
parent
ce076d1323
commit
6a93e2ef3d
|
@ -135,6 +135,17 @@ typedef struct _Evas_Image_Property Evas_Image_Property;
|
|||
struct _Evas_Image_Property
|
||||
{
|
||||
Emile_Image_Property info;
|
||||
// Stretch region are directly encoded the way Evas excpect them internally
|
||||
// 8bits is used for each step. The lower bits indicate how long the stretch region
|
||||
// span. Masking with 0x80 will be true if the region is stretchable. If false, it
|
||||
// will be fixed size.
|
||||
struct {
|
||||
struct {
|
||||
uint8_t *region;
|
||||
} horizontal, vertical;
|
||||
} stretch;
|
||||
// Where inside the image are we supposed to overlay data
|
||||
Eina_Rectangle content;
|
||||
// need_data is set to True when to get accurate property, data need to be loaded
|
||||
Eina_Bool need_data;
|
||||
};
|
||||
|
@ -253,6 +264,32 @@ EAPI Eina_Bool evas_module_task_cancelled (void); /**< @since 1.19 */
|
|||
EINA_MODULE_INIT(evas_##Tn##_##Name##_init); \
|
||||
EINA_MODULE_SHUTDOWN(evas_##Tn##_##Name##_shutdown);
|
||||
|
||||
static inline Eina_Bool
|
||||
evas_loader_helper_stretch_region_push(uint8_t **region,
|
||||
uint8_t *offset,
|
||||
Eina_Bool stretchable)
|
||||
{
|
||||
uint32_t length = 0;
|
||||
void *tmp;
|
||||
|
||||
if (*offset == 0) return EINA_TRUE;
|
||||
|
||||
while (*region && (*region)[length] != 0)
|
||||
length++;
|
||||
|
||||
// +1 for termination and +1 for the region being pushed
|
||||
tmp = realloc(*region, sizeof (uint8_t) * (length + 2));
|
||||
if (!tmp) return EINA_FALSE;
|
||||
|
||||
*region = (uint8_t *) tmp;
|
||||
(*region)[length] = (*offset) | (stretchable ? 0x80 : 0);
|
||||
(*region)[length + 1] = 0;
|
||||
|
||||
*offset = 0;
|
||||
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -98,6 +98,9 @@ struct _Evas_Object_Image_State
|
|||
Eina_Bool has_alpha :1;
|
||||
Eina_Bool opaque_valid : 1;
|
||||
Eina_Bool opaque : 1;
|
||||
|
||||
Eina_Bool free_stretch : 1; // Should we free stretch region?
|
||||
Eina_Bool stretch_loaded : 1; // Is the stretch region loaded from file?
|
||||
};
|
||||
|
||||
#define EVAS_IMAGE_PRELOAD_NONE 0x00
|
||||
|
|
|
@ -465,12 +465,77 @@ _efl_canvas_image_internal_efl_object_dbg_info_get(Eo *eo_obj, Evas_Image_Data *
|
|||
(uint64_t)(uintptr_t)evas_object_image_source_get(eo_obj));
|
||||
}
|
||||
|
||||
static void
|
||||
_stretch_region_load(Evas_Object_Protected_Data *obj, Evas_Image_Data *o)
|
||||
{
|
||||
unsigned int i;
|
||||
uint8_t *horizontal = NULL;
|
||||
uint8_t *vertical = NULL;
|
||||
uint32_t total, stretchable;
|
||||
|
||||
if (o->cur->stretch_loaded == EINA_TRUE ||
|
||||
(o->cur->stretch.horizontal.region && o->cur->stretch.vertical.region))
|
||||
return ;
|
||||
|
||||
ENFN->image_stretch_region_get(ENC, o->engine_data,
|
||||
&horizontal,
|
||||
&vertical);
|
||||
|
||||
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||
{
|
||||
state_write->stretch.horizontal.region = horizontal;
|
||||
state_write->stretch.vertical.region = vertical;
|
||||
state_write->free_stretch = EINA_FALSE;
|
||||
state_write->stretch_loaded = EINA_TRUE;
|
||||
}
|
||||
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
|
||||
|
||||
if (!o->cur->stretch.horizontal.region || !o->cur->stretch.vertical.region)
|
||||
return ;
|
||||
|
||||
stretchable = 0;
|
||||
total = 0;
|
||||
for (i = 0; o->cur->stretch.horizontal.region[i]; i++)
|
||||
{
|
||||
total += o->cur->stretch.horizontal.region[i] & 0x7F;
|
||||
if (o->cur->stretch.horizontal.region[i] & 0x80)
|
||||
stretchable += o->cur->stretch.horizontal.region[i] & 0x7F;
|
||||
}
|
||||
|
||||
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||
{
|
||||
state_write->stretch.horizontal.stretchable = stretchable;
|
||||
state_write->stretch.horizontal.total = total;
|
||||
}
|
||||
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
|
||||
|
||||
stretchable = 0;
|
||||
total = 0;
|
||||
for (i = 0; o->cur->stretch.vertical.region[i]; i++)
|
||||
{
|
||||
total += o->cur->stretch.vertical.region[i] & 0x7F;
|
||||
if (o->cur->stretch.vertical.region[i] & 0x80)
|
||||
stretchable += o->cur->stretch.vertical.region[i] & 0x7F;
|
||||
}
|
||||
|
||||
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||
{
|
||||
state_write->stretch.vertical.stretchable = stretchable;
|
||||
state_write->stretch.vertical.total = total;
|
||||
}
|
||||
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
|
||||
}
|
||||
|
||||
static Eina_Rect
|
||||
_efl_canvas_image_internal_efl_gfx_image_content_region_get(const Eo *eo_obj, Evas_Image_Data *o)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||
Eina_Rect r;
|
||||
|
||||
if (!o->cur->stretch.horizontal.region &&
|
||||
!o->cur->stretch.vertical.region)
|
||||
_stretch_region_load(obj, o);
|
||||
|
||||
if (o->cur->stretch.horizontal.region &&
|
||||
o->cur->stretch.vertical.region)
|
||||
{
|
||||
|
@ -478,6 +543,15 @@ _efl_canvas_image_internal_efl_gfx_image_content_region_get(const Eo *eo_obj, Ev
|
|||
uint32_t hi = 0;
|
||||
uint32_t vi = 0;
|
||||
|
||||
// If the file come with a defined content zone, then return it
|
||||
if (ENFN->image_content_region_get(ENC, o->engine_data, &r.rect))
|
||||
{
|
||||
// Correct bottom right corner coordinate to be resized with object size
|
||||
r.w = obj->cur->geometry.w - (o->cur->image.w - r.w);
|
||||
r.h = obj->cur->geometry.h - (o->cur->image.h - r.h);
|
||||
return r;
|
||||
}
|
||||
|
||||
r.x = _stretch_region_accumulate(o->cur->stretch.horizontal.region, 0, &hi);
|
||||
r.w = o->cur->stretch.horizontal.stretchable + obj->cur->geometry.w - o->cur->image.w;
|
||||
|
||||
|
@ -681,11 +755,14 @@ _efl_canvas_image_internal_efl_gfx_image_stretch_region_set(Eo *eo_obj, Evas_Ima
|
|||
evas_object_async_block(obj);
|
||||
EINA_COW_IMAGE_STATE_WRITE_BEGIN(pd, state_write)
|
||||
{
|
||||
free(state_write->stretch.horizontal.region);
|
||||
if (state_write->free_stretch) free(state_write->stretch.horizontal.region);
|
||||
state_write->stretch.horizontal.region = NULL;
|
||||
|
||||
free(state_write->stretch.vertical.region);
|
||||
if (state_write->free_stretch) free(state_write->stretch.vertical.region);
|
||||
state_write->stretch.vertical.region = NULL;
|
||||
|
||||
state_write->free_stretch = EINA_FALSE;
|
||||
state_write->stretch_loaded = EINA_FALSE;
|
||||
}
|
||||
EINA_COW_IMAGE_STATE_WRITE_END(pd, state_write);
|
||||
|
||||
|
@ -722,6 +799,8 @@ _efl_canvas_image_internal_efl_gfx_image_stretch_region_set(Eo *eo_obj, Evas_Ima
|
|||
state_write->stretch.vertical.region = fvsz;
|
||||
state_write->stretch.vertical.stretchable = vstretch;
|
||||
state_write->stretch.vertical.total = vtotal;
|
||||
state_write->free_stretch = EINA_TRUE;
|
||||
state_write->stretch_loaded = EINA_TRUE;
|
||||
}
|
||||
EINA_COW_IMAGE_STATE_WRITE_END(pd, state_write);
|
||||
|
||||
|
@ -795,6 +874,15 @@ _efl_canvas_image_internal_efl_gfx_image_stretch_region_get(const Eo *eo_obj,
|
|||
{
|
||||
Efl_Gfx_Image_Stretch_Region_Iterator *it;
|
||||
|
||||
if (!pd->cur->stretch.vertical.region &&
|
||||
!pd->cur->stretch.horizontal.region)
|
||||
{
|
||||
Evas_Object_Protected_Data *obj;
|
||||
|
||||
obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
|
||||
_stretch_region_load(obj, pd);
|
||||
}
|
||||
|
||||
if (!horizontal) goto vertical_only;
|
||||
if (!pd->cur->stretch.horizontal.region)
|
||||
{
|
||||
|
@ -1596,6 +1684,7 @@ _efl_canvas_image_internal_efl_object_destructor(Eo *eo_obj, Evas_Image_Data *o
|
|||
if (obj->legacy.ctor)
|
||||
evas_object_image_video_surface_set(eo_obj, NULL);
|
||||
evas_object_image_free(eo_obj, obj);
|
||||
efl_gfx_image_stretch_region_set(eo_obj, NULL, NULL);
|
||||
efl_destructor(efl_super(eo_obj, MY_CLASS));
|
||||
}
|
||||
|
||||
|
@ -2384,6 +2473,8 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
|
|||
return;
|
||||
}
|
||||
|
||||
_stretch_region_load(obj, o);
|
||||
|
||||
ENFN->image_scale_hint_set(engine, pixels, o->scale_hint);
|
||||
idx = evas_object_image_figure_x_fill(eo_obj, obj, o->cur->fill.x, o->cur->fill.w, &idw);
|
||||
idy = evas_object_image_figure_y_fill(eo_obj, obj, o->cur->fill.y, o->cur->fill.h, &idh);
|
||||
|
|
|
@ -223,6 +223,7 @@ _evas_image_file_header(Evas_Module *em, Image_Entry *ie, int *error)
|
|||
ie->borders.b = property.info.borders.b;
|
||||
ie->scale = property.info.scale;
|
||||
ie->flags.alpha = property.info.alpha;
|
||||
ie->need_data = property.need_data;
|
||||
if (property.info.cspaces) ie->cspaces = property.info.cspaces;
|
||||
ie->flags.rotated = property.info.rotated;
|
||||
ie->flags.flipped = property.info.flipped;
|
||||
|
@ -470,7 +471,17 @@ end:
|
|||
return EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
|
||||
}
|
||||
|
||||
if (ie->need_data)
|
||||
{
|
||||
evas_image_load_func->file_head_with_data(ie->loader_data, &property, pixels, &ret);
|
||||
memcpy(&ie->content, &property.content, sizeof (Eina_Rectangle));
|
||||
ie->stretch.horizontal.region = property.stretch.horizontal.region;
|
||||
ie->stretch.vertical.region = property.stretch.vertical.region;
|
||||
}
|
||||
else
|
||||
{
|
||||
evas_image_load_func->file_data(ie->loader_data, &property, pixels, &ret);
|
||||
}
|
||||
|
||||
ie->flags.alpha_sparse = property.info.alpha_sparse;
|
||||
|
||||
|
|
|
@ -598,6 +598,7 @@ struct _Image_Entry
|
|||
|
||||
unsigned char need_unload : 1;
|
||||
unsigned char load_failed : 1;
|
||||
unsigned char need_data : 1;
|
||||
|
||||
struct
|
||||
{
|
||||
|
@ -633,6 +634,14 @@ struct _Image_Entry
|
|||
int connect_num;
|
||||
int channel;
|
||||
Evas_Load_Error load_error;
|
||||
|
||||
struct {
|
||||
struct {
|
||||
uint8_t *region;
|
||||
} horizontal, vertical;
|
||||
} stretch;
|
||||
|
||||
Eina_Rectangle content;
|
||||
};
|
||||
|
||||
struct _Engine_Image_Entry
|
||||
|
|
|
@ -1354,6 +1354,8 @@ struct _Evas_Func
|
|||
Eina_Bool (*image_data_map) (void *engine, void **image, Eina_Rw_Slice *slice, int *stride, int x, int y, int w, int h, Evas_Colorspace cspace, Efl_Gfx_Buffer_Access_Mode mode, int plane);
|
||||
Eina_Bool (*image_data_unmap) (void *engine, void *image, const Eina_Rw_Slice *slice);
|
||||
int (*image_data_maps_get) (void *engine, const void *image, const Eina_Rw_Slice **slices);
|
||||
Eina_Bool (*image_content_region_get) (void *engine, void *image, Eina_Rectangle *content);
|
||||
Eina_Bool (*image_stretch_region_get) (void *engine, void *image, uint8_t **horizontal, uint8_t **vertical);
|
||||
|
||||
/* new api for direct data set (not put) */
|
||||
void *(*image_data_slice_add) (void *engine, void *image, const Eina_Slice *slice, Eina_Bool copy, int w, int h, int stride, Evas_Colorspace space, int plane, Eina_Bool alpha);
|
||||
|
|
|
@ -1050,6 +1050,48 @@ eng_image_file_colorspace_get(void *data EINA_UNUSED, void *image)
|
|||
return im->cache_entry.space;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
eng_image_content_region_get(void *engine EINA_UNUSED, void *image, Eina_Rectangle *content)
|
||||
{
|
||||
RGBA_Image *im = image;
|
||||
|
||||
if (!im) return EINA_FALSE;
|
||||
|
||||
if (!im->cache_entry.need_data) return EINA_FALSE;
|
||||
|
||||
if (!im->image.data) evas_cache_image_load_data(&im->cache_entry);
|
||||
|
||||
if (!im->cache_entry.content.w ||
|
||||
!im->cache_entry.content.h)
|
||||
return EINA_FALSE;
|
||||
|
||||
if (!content) return EINA_FALSE;
|
||||
|
||||
memcpy(content, &im->cache_entry.content, sizeof (Eina_Rectangle));
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
eng_image_stretch_region_get(void *engine EINA_UNUSED, void *image,
|
||||
uint8_t **horizontal, uint8_t **vertical)
|
||||
{
|
||||
RGBA_Image *im = image;
|
||||
|
||||
if (!im) return EINA_FALSE;
|
||||
|
||||
if (!im->cache_entry.need_data) return EINA_FALSE;
|
||||
|
||||
if (!im->image.data) evas_cache_image_load_data(&im->cache_entry);
|
||||
|
||||
if (!im->cache_entry.stretch.horizontal.region ||
|
||||
!im->cache_entry.stretch.vertical.region)
|
||||
return EINA_FALSE;
|
||||
|
||||
*horizontal = im->cache_entry.stretch.horizontal.region;
|
||||
*vertical = im->cache_entry.stretch.vertical.region;
|
||||
return EINA_TRUE;
|
||||
}
|
||||
|
||||
static Eina_Bool
|
||||
eng_image_data_direct_get(void *data EINA_UNUSED, void *image, int plane,
|
||||
Eina_Slice *slice, Evas_Colorspace *cspace,
|
||||
|
@ -4611,6 +4653,8 @@ static Evas_Func func =
|
|||
eng_image_data_map,
|
||||
eng_image_data_unmap,
|
||||
eng_image_data_maps_get,
|
||||
eng_image_content_region_get,
|
||||
eng_image_stretch_region_get,
|
||||
eng_image_data_slice_add,
|
||||
eng_image_prepare,
|
||||
eng_image_surface_noscale_new,
|
||||
|
|
Loading…
Reference in New Issue