summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorCedric BAIL <cedric.bail@free.fr>2019-06-13 15:34:09 -0700
committerCedric BAIL <cedric.bail@free.fr>2019-07-12 09:54:16 -0700
commit6a93e2ef3da17c8548d149535f2f39faf18fa46c (patch)
treeabff64113d4f79fe872fc5526c70217ec1b6298e
parentce076d1323ef89cad5d9b4fe185d14101e8d5d3e (diff)
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
-rw-r--r--src/lib/evas/Evas_Loader.h37
-rw-r--r--src/lib/evas/canvas/evas_image_private.h3
-rw-r--r--src/lib/evas/canvas/evas_object_image.c95
-rw-r--r--src/lib/evas/common/evas_image_load.c13
-rw-r--r--src/lib/evas/include/evas_common_private.h9
-rw-r--r--src/lib/evas/include/evas_private.h2
-rw-r--r--src/modules/evas/engines/software_generic/evas_engine.c44
7 files changed, 200 insertions, 3 deletions
diff --git a/src/lib/evas/Evas_Loader.h b/src/lib/evas/Evas_Loader.h
index 220deabb9b..94ec424209 100644
--- a/src/lib/evas/Evas_Loader.h
+++ b/src/lib/evas/Evas_Loader.h
@@ -135,6 +135,17 @@ typedef struct _Evas_Image_Property Evas_Image_Property;
135struct _Evas_Image_Property 135struct _Evas_Image_Property
136{ 136{
137 Emile_Image_Property info; 137 Emile_Image_Property info;
138 // Stretch region are directly encoded the way Evas excpect them internally
139 // 8bits is used for each step. The lower bits indicate how long the stretch region
140 // span. Masking with 0x80 will be true if the region is stretchable. If false, it
141 // will be fixed size.
142 struct {
143 struct {
144 uint8_t *region;
145 } horizontal, vertical;
146 } stretch;
147 // Where inside the image are we supposed to overlay data
148 Eina_Rectangle content;
138 // need_data is set to True when to get accurate property, data need to be loaded 149 // need_data is set to True when to get accurate property, data need to be loaded
139 Eina_Bool need_data; 150 Eina_Bool need_data;
140}; 151};
@@ -253,6 +264,32 @@ EAPI Eina_Bool evas_module_task_cancelled (void); /**< @since 1.19 */
253 EINA_MODULE_INIT(evas_##Tn##_##Name##_init); \ 264 EINA_MODULE_INIT(evas_##Tn##_##Name##_init); \
254 EINA_MODULE_SHUTDOWN(evas_##Tn##_##Name##_shutdown); 265 EINA_MODULE_SHUTDOWN(evas_##Tn##_##Name##_shutdown);
255 266
267static inline Eina_Bool
268evas_loader_helper_stretch_region_push(uint8_t **region,
269 uint8_t *offset,
270 Eina_Bool stretchable)
271{
272 uint32_t length = 0;
273 void *tmp;
274
275 if (*offset == 0) return EINA_TRUE;
276
277 while (*region && (*region)[length] != 0)
278 length++;
279
280 // +1 for termination and +1 for the region being pushed
281 tmp = realloc(*region, sizeof (uint8_t) * (length + 2));
282 if (!tmp) return EINA_FALSE;
283
284 *region = (uint8_t *) tmp;
285 (*region)[length] = (*offset) | (stretchable ? 0x80 : 0);
286 (*region)[length + 1] = 0;
287
288 *offset = 0;
289
290 return EINA_TRUE;
291}
292
256#ifdef __cplusplus 293#ifdef __cplusplus
257} 294}
258#endif 295#endif
diff --git a/src/lib/evas/canvas/evas_image_private.h b/src/lib/evas/canvas/evas_image_private.h
index 21b989aae0..664d60e684 100644
--- a/src/lib/evas/canvas/evas_image_private.h
+++ b/src/lib/evas/canvas/evas_image_private.h
@@ -98,6 +98,9 @@ struct _Evas_Object_Image_State
98 Eina_Bool has_alpha :1; 98 Eina_Bool has_alpha :1;
99 Eina_Bool opaque_valid : 1; 99 Eina_Bool opaque_valid : 1;
100 Eina_Bool opaque : 1; 100 Eina_Bool opaque : 1;
101
102 Eina_Bool free_stretch : 1; // Should we free stretch region?
103 Eina_Bool stretch_loaded : 1; // Is the stretch region loaded from file?
101}; 104};
102 105
103#define EVAS_IMAGE_PRELOAD_NONE 0x00 106#define EVAS_IMAGE_PRELOAD_NONE 0x00
diff --git a/src/lib/evas/canvas/evas_object_image.c b/src/lib/evas/canvas/evas_object_image.c
index ac4665e7b2..50a064a287 100644
--- a/src/lib/evas/canvas/evas_object_image.c
+++ b/src/lib/evas/canvas/evas_object_image.c
@@ -465,12 +465,77 @@ _efl_canvas_image_internal_efl_object_dbg_info_get(Eo *eo_obj, Evas_Image_Data *
465 (uint64_t)(uintptr_t)evas_object_image_source_get(eo_obj)); 465 (uint64_t)(uintptr_t)evas_object_image_source_get(eo_obj));
466} 466}
467 467
468static void
469_stretch_region_load(Evas_Object_Protected_Data *obj, Evas_Image_Data *o)
470{
471 unsigned int i;
472 uint8_t *horizontal = NULL;
473 uint8_t *vertical = NULL;
474 uint32_t total, stretchable;
475
476 if (o->cur->stretch_loaded == EINA_TRUE ||
477 (o->cur->stretch.horizontal.region && o->cur->stretch.vertical.region))
478 return ;
479
480 ENFN->image_stretch_region_get(ENC, o->engine_data,
481 &horizontal,
482 &vertical);
483
484 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
485 {
486 state_write->stretch.horizontal.region = horizontal;
487 state_write->stretch.vertical.region = vertical;
488 state_write->free_stretch = EINA_FALSE;
489 state_write->stretch_loaded = EINA_TRUE;
490 }
491 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
492
493 if (!o->cur->stretch.horizontal.region || !o->cur->stretch.vertical.region)
494 return ;
495
496 stretchable = 0;
497 total = 0;
498 for (i = 0; o->cur->stretch.horizontal.region[i]; i++)
499 {
500 total += o->cur->stretch.horizontal.region[i] & 0x7F;
501 if (o->cur->stretch.horizontal.region[i] & 0x80)
502 stretchable += o->cur->stretch.horizontal.region[i] & 0x7F;
503 }
504
505 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
506 {
507 state_write->stretch.horizontal.stretchable = stretchable;
508 state_write->stretch.horizontal.total = total;
509 }
510 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
511
512 stretchable = 0;
513 total = 0;
514 for (i = 0; o->cur->stretch.vertical.region[i]; i++)
515 {
516 total += o->cur->stretch.vertical.region[i] & 0x7F;
517 if (o->cur->stretch.vertical.region[i] & 0x80)
518 stretchable += o->cur->stretch.vertical.region[i] & 0x7F;
519 }
520
521 EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
522 {
523 state_write->stretch.vertical.stretchable = stretchable;
524 state_write->stretch.vertical.total = total;
525 }
526 EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
527}
528
468static Eina_Rect 529static Eina_Rect
469_efl_canvas_image_internal_efl_gfx_image_content_region_get(const Eo *eo_obj, Evas_Image_Data *o) 530_efl_canvas_image_internal_efl_gfx_image_content_region_get(const Eo *eo_obj, Evas_Image_Data *o)
470{ 531{
471 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS); 532 Evas_Object_Protected_Data *obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
472 Eina_Rect r; 533 Eina_Rect r;
473 534
535 if (!o->cur->stretch.horizontal.region &&
536 !o->cur->stretch.vertical.region)
537 _stretch_region_load(obj, o);
538
474 if (o->cur->stretch.horizontal.region && 539 if (o->cur->stretch.horizontal.region &&
475 o->cur->stretch.vertical.region) 540 o->cur->stretch.vertical.region)
476 { 541 {
@@ -478,6 +543,15 @@ _efl_canvas_image_internal_efl_gfx_image_content_region_get(const Eo *eo_obj, Ev
478 uint32_t hi = 0; 543 uint32_t hi = 0;
479 uint32_t vi = 0; 544 uint32_t vi = 0;
480 545
546 // If the file come with a defined content zone, then return it
547 if (ENFN->image_content_region_get(ENC, o->engine_data, &r.rect))
548 {
549 // Correct bottom right corner coordinate to be resized with object size
550 r.w = obj->cur->geometry.w - (o->cur->image.w - r.w);
551 r.h = obj->cur->geometry.h - (o->cur->image.h - r.h);
552 return r;
553 }
554
481 r.x = _stretch_region_accumulate(o->cur->stretch.horizontal.region, 0, &hi); 555 r.x = _stretch_region_accumulate(o->cur->stretch.horizontal.region, 0, &hi);
482 r.w = o->cur->stretch.horizontal.stretchable + obj->cur->geometry.w - o->cur->image.w; 556 r.w = o->cur->stretch.horizontal.stretchable + obj->cur->geometry.w - o->cur->image.w;
483 557
@@ -681,11 +755,14 @@ _efl_canvas_image_internal_efl_gfx_image_stretch_region_set(Eo *eo_obj, Evas_Ima
681 evas_object_async_block(obj); 755 evas_object_async_block(obj);
682 EINA_COW_IMAGE_STATE_WRITE_BEGIN(pd, state_write) 756 EINA_COW_IMAGE_STATE_WRITE_BEGIN(pd, state_write)
683 { 757 {
684 free(state_write->stretch.horizontal.region); 758 if (state_write->free_stretch) free(state_write->stretch.horizontal.region);
685 state_write->stretch.horizontal.region = NULL; 759 state_write->stretch.horizontal.region = NULL;
686 760
687 free(state_write->stretch.vertical.region); 761 if (state_write->free_stretch) free(state_write->stretch.vertical.region);
688 state_write->stretch.vertical.region = NULL; 762 state_write->stretch.vertical.region = NULL;
763
764 state_write->free_stretch = EINA_FALSE;
765 state_write->stretch_loaded = EINA_FALSE;
689 } 766 }
690 EINA_COW_IMAGE_STATE_WRITE_END(pd, state_write); 767 EINA_COW_IMAGE_STATE_WRITE_END(pd, state_write);
691 768
@@ -722,6 +799,8 @@ _efl_canvas_image_internal_efl_gfx_image_stretch_region_set(Eo *eo_obj, Evas_Ima
722 state_write->stretch.vertical.region = fvsz; 799 state_write->stretch.vertical.region = fvsz;
723 state_write->stretch.vertical.stretchable = vstretch; 800 state_write->stretch.vertical.stretchable = vstretch;
724 state_write->stretch.vertical.total = vtotal; 801 state_write->stretch.vertical.total = vtotal;
802 state_write->free_stretch = EINA_TRUE;
803 state_write->stretch_loaded = EINA_TRUE;
725 } 804 }
726 EINA_COW_IMAGE_STATE_WRITE_END(pd, state_write); 805 EINA_COW_IMAGE_STATE_WRITE_END(pd, state_write);
727 806
@@ -795,6 +874,15 @@ _efl_canvas_image_internal_efl_gfx_image_stretch_region_get(const Eo *eo_obj,
795{ 874{
796 Efl_Gfx_Image_Stretch_Region_Iterator *it; 875 Efl_Gfx_Image_Stretch_Region_Iterator *it;
797 876
877 if (!pd->cur->stretch.vertical.region &&
878 !pd->cur->stretch.horizontal.region)
879 {
880 Evas_Object_Protected_Data *obj;
881
882 obj = efl_data_scope_get(eo_obj, EFL_CANVAS_OBJECT_CLASS);
883 _stretch_region_load(obj, pd);
884 }
885
798 if (!horizontal) goto vertical_only; 886 if (!horizontal) goto vertical_only;
799 if (!pd->cur->stretch.horizontal.region) 887 if (!pd->cur->stretch.horizontal.region)
800 { 888 {
@@ -1596,6 +1684,7 @@ _efl_canvas_image_internal_efl_object_destructor(Eo *eo_obj, Evas_Image_Data *o
1596 if (obj->legacy.ctor) 1684 if (obj->legacy.ctor)
1597 evas_object_image_video_surface_set(eo_obj, NULL); 1685 evas_object_image_video_surface_set(eo_obj, NULL);
1598 evas_object_image_free(eo_obj, obj); 1686 evas_object_image_free(eo_obj, obj);
1687 efl_gfx_image_stretch_region_set(eo_obj, NULL, NULL);
1599 efl_destructor(efl_super(eo_obj, MY_CLASS)); 1688 efl_destructor(efl_super(eo_obj, MY_CLASS));
1600} 1689}
1601 1690
@@ -2384,6 +2473,8 @@ _evas_image_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
2384 return; 2473 return;
2385 } 2474 }
2386 2475
2476 _stretch_region_load(obj, o);
2477
2387 ENFN->image_scale_hint_set(engine, pixels, o->scale_hint); 2478 ENFN->image_scale_hint_set(engine, pixels, o->scale_hint);
2388 idx = evas_object_image_figure_x_fill(eo_obj, obj, o->cur->fill.x, o->cur->fill.w, &idw); 2479 idx = evas_object_image_figure_x_fill(eo_obj, obj, o->cur->fill.x, o->cur->fill.w, &idw);
2389 idy = evas_object_image_figure_y_fill(eo_obj, obj, o->cur->fill.y, o->cur->fill.h, &idh); 2480 idy = evas_object_image_figure_y_fill(eo_obj, obj, o->cur->fill.y, o->cur->fill.h, &idh);
diff --git a/src/lib/evas/common/evas_image_load.c b/src/lib/evas/common/evas_image_load.c
index f8d00cc292..611767448e 100644
--- a/src/lib/evas/common/evas_image_load.c
+++ b/src/lib/evas/common/evas_image_load.c
@@ -223,6 +223,7 @@ _evas_image_file_header(Evas_Module *em, Image_Entry *ie, int *error)
223 ie->borders.b = property.info.borders.b; 223 ie->borders.b = property.info.borders.b;
224 ie->scale = property.info.scale; 224 ie->scale = property.info.scale;
225 ie->flags.alpha = property.info.alpha; 225 ie->flags.alpha = property.info.alpha;
226 ie->need_data = property.need_data;
226 if (property.info.cspaces) ie->cspaces = property.info.cspaces; 227 if (property.info.cspaces) ie->cspaces = property.info.cspaces;
227 ie->flags.rotated = property.info.rotated; 228 ie->flags.rotated = property.info.rotated;
228 ie->flags.flipped = property.info.flipped; 229 ie->flags.flipped = property.info.flipped;
@@ -470,7 +471,17 @@ end:
470 return EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED; 471 return EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
471 } 472 }
472 473
473 evas_image_load_func->file_data(ie->loader_data, &property, pixels, &ret); 474 if (ie->need_data)
475 {
476 evas_image_load_func->file_head_with_data(ie->loader_data, &property, pixels, &ret);
477 memcpy(&ie->content, &property.content, sizeof (Eina_Rectangle));
478 ie->stretch.horizontal.region = property.stretch.horizontal.region;
479 ie->stretch.vertical.region = property.stretch.vertical.region;
480 }
481 else
482 {
483 evas_image_load_func->file_data(ie->loader_data, &property, pixels, &ret);
484 }
474 485
475 ie->flags.alpha_sparse = property.info.alpha_sparse; 486 ie->flags.alpha_sparse = property.info.alpha_sparse;
476 487
diff --git a/src/lib/evas/include/evas_common_private.h b/src/lib/evas/include/evas_common_private.h
index 825d83ab77..59eb800724 100644
--- a/src/lib/evas/include/evas_common_private.h
+++ b/src/lib/evas/include/evas_common_private.h
@@ -598,6 +598,7 @@ struct _Image_Entry
598 598
599 unsigned char need_unload : 1; 599 unsigned char need_unload : 1;
600 unsigned char load_failed : 1; 600 unsigned char load_failed : 1;
601 unsigned char need_data : 1;
601 602
602 struct 603 struct
603 { 604 {
@@ -633,6 +634,14 @@ struct _Image_Entry
633 int connect_num; 634 int connect_num;
634 int channel; 635 int channel;
635 Evas_Load_Error load_error; 636 Evas_Load_Error load_error;
637
638 struct {
639 struct {
640 uint8_t *region;
641 } horizontal, vertical;
642 } stretch;
643
644 Eina_Rectangle content;
636}; 645};
637 646
638struct _Engine_Image_Entry 647struct _Engine_Image_Entry
diff --git a/src/lib/evas/include/evas_private.h b/src/lib/evas/include/evas_private.h
index d6b53bc210..751f81cd07 100644
--- a/src/lib/evas/include/evas_private.h
+++ b/src/lib/evas/include/evas_private.h
@@ -1354,6 +1354,8 @@ struct _Evas_Func
1354 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); 1354 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);
1355 Eina_Bool (*image_data_unmap) (void *engine, void *image, const Eina_Rw_Slice *slice); 1355 Eina_Bool (*image_data_unmap) (void *engine, void *image, const Eina_Rw_Slice *slice);
1356 int (*image_data_maps_get) (void *engine, const void *image, const Eina_Rw_Slice **slices); 1356 int (*image_data_maps_get) (void *engine, const void *image, const Eina_Rw_Slice **slices);
1357 Eina_Bool (*image_content_region_get) (void *engine, void *image, Eina_Rectangle *content);
1358 Eina_Bool (*image_stretch_region_get) (void *engine, void *image, uint8_t **horizontal, uint8_t **vertical);
1357 1359
1358 /* new api for direct data set (not put) */ 1360 /* new api for direct data set (not put) */
1359 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); 1361 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);
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c
index 6ae8224e47..59391c4f6e 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -1051,6 +1051,48 @@ eng_image_file_colorspace_get(void *data EINA_UNUSED, void *image)
1051} 1051}
1052 1052
1053static Eina_Bool 1053static Eina_Bool
1054eng_image_content_region_get(void *engine EINA_UNUSED, void *image, Eina_Rectangle *content)
1055{
1056 RGBA_Image *im = image;
1057
1058 if (!im) return EINA_FALSE;
1059
1060 if (!im->cache_entry.need_data) return EINA_FALSE;
1061
1062 if (!im->image.data) evas_cache_image_load_data(&im->cache_entry);
1063
1064 if (!im->cache_entry.content.w ||
1065 !im->cache_entry.content.h)
1066 return EINA_FALSE;
1067
1068 if (!content) return EINA_FALSE;
1069
1070 memcpy(content, &im->cache_entry.content, sizeof (Eina_Rectangle));
1071 return EINA_TRUE;
1072}
1073
1074static Eina_Bool
1075eng_image_stretch_region_get(void *engine EINA_UNUSED, void *image,
1076 uint8_t **horizontal, uint8_t **vertical)
1077{
1078 RGBA_Image *im = image;
1079
1080 if (!im) return EINA_FALSE;
1081
1082 if (!im->cache_entry.need_data) return EINA_FALSE;
1083
1084 if (!im->image.data) evas_cache_image_load_data(&im->cache_entry);
1085
1086 if (!im->cache_entry.stretch.horizontal.region ||
1087 !im->cache_entry.stretch.vertical.region)
1088 return EINA_FALSE;
1089
1090 *horizontal = im->cache_entry.stretch.horizontal.region;
1091 *vertical = im->cache_entry.stretch.vertical.region;
1092 return EINA_TRUE;
1093}
1094
1095static Eina_Bool
1054eng_image_data_direct_get(void *data EINA_UNUSED, void *image, int plane, 1096eng_image_data_direct_get(void *data EINA_UNUSED, void *image, int plane,
1055 Eina_Slice *slice, Evas_Colorspace *cspace, 1097 Eina_Slice *slice, Evas_Colorspace *cspace,
1056 Eina_Bool load, Eina_Bool *tofree) 1098 Eina_Bool load, Eina_Bool *tofree)
@@ -4611,6 +4653,8 @@ static Evas_Func func =
4611 eng_image_data_map, 4653 eng_image_data_map,
4612 eng_image_data_unmap, 4654 eng_image_data_unmap,
4613 eng_image_data_maps_get, 4655 eng_image_data_maps_get,
4656 eng_image_content_region_get,
4657 eng_image_stretch_region_get,
4614 eng_image_data_slice_add, 4658 eng_image_data_slice_add,
4615 eng_image_prepare, 4659 eng_image_prepare,
4616 eng_image_surface_noscale_new, 4660 eng_image_surface_noscale_new,