summaryrefslogtreecommitdiff
path: root/src/modules
diff options
context:
space:
mode:
Diffstat (limited to 'src/modules')
-rw-r--r--src/modules/ecore_evas/engines/extn/ecore_evas_extn.c4
-rw-r--r--src/modules/ecore_evas/engines/fb/ecore_evas_fb.c4
-rw-r--r--src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c2
-rw-r--r--src/modules/ecore_evas/engines/x/ecore_evas_x.c7
-rw-r--r--src/modules/ecore_imf/scim/meson.build2
-rw-r--r--src/modules/ecore_imf/xim/meson.build2
-rw-r--r--src/modules/elementary/web/none/elm_web_none_eo.h2
-rw-r--r--src/modules/ethumb/emotion/emotion.c5
-rw-r--r--src/modules/evas/engines/buffer/evas_outbuf.c6
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_common.h3
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_core.c8
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_font.c26
-rw-r--r--src/modules/evas/engines/gl_common/evas_gl_texture.c5
-rw-r--r--src/modules/evas/engines/gl_generic/evas_engine.c52
-rw-r--r--src/modules/evas/engines/software_generic/evas_ector_software_buffer.c2
-rw-r--r--src/modules/evas/engines/software_generic/evas_engine.c139
-rw-r--r--src/modules/evas/engines/software_x11/meson.build2
-rw-r--r--src/modules/evas/engines/wayland_shm/evas_engine.c2
-rw-r--r--src/modules/evas/image_loaders/avif/evas_image_load_avif.c382
-rw-r--r--src/modules/evas/image_loaders/gif/evas_image_load_gif.c2
-rw-r--r--src/modules/evas/image_loaders/png/evas_image_load_png.c2
-rw-r--r--src/modules/evas/image_loaders/psd/evas_image_load_psd.c38
-rw-r--r--src/modules/evas/image_savers/avif/evas_image_save_avif.c181
-rw-r--r--src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c116
24 files changed, 870 insertions, 124 deletions
diff --git a/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c b/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c
index e7d3e298a9..37963fe664 100644
--- a/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c
+++ b/src/modules/ecore_evas/engines/extn/ecore_evas_extn.c
@@ -753,7 +753,7 @@ _ecore_evas_extn_cb_focus_in(void *data, Evas *e EINA_UNUSED, Evas_Object *obj E
753 Extn *extn; 753 Extn *extn;
754 Evas_Device *dev; 754 Evas_Device *dev;
755 755
756 dev = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_SEAT); 756 dev = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_SEAT);
757 if (ecore_evas_focus_device_get(ee, dev)) return; 757 if (ecore_evas_focus_device_get(ee, dev)) return;
758 ee->prop.focused_by = eina_list_append(ee->prop.focused_by, dev); 758 ee->prop.focused_by = eina_list_append(ee->prop.focused_by, dev);
759 extn = bdata->data; 759 extn = bdata->data;
@@ -770,7 +770,7 @@ _ecore_evas_extn_cb_focus_out(void *data, Evas *e EINA_UNUSED, Evas_Object *obj
770 Extn *extn; 770 Extn *extn;
771 771
772 ee->prop.focused_by = eina_list_remove(ee->prop.focused_by, 772 ee->prop.focused_by = eina_list_remove(ee->prop.focused_by,
773 evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_SEAT)); 773 evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_SEAT));
774 extn = bdata->data; 774 extn = bdata->data;
775 if (!extn) return; 775 if (!extn) return;
776 if (!extn->ipc.server) return; 776 if (!extn->ipc.server) return;
diff --git a/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c b/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c
index 17bf83f7c1..ce671e2e3e 100644
--- a/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c
+++ b/src/modules/ecore_evas/engines/fb/ecore_evas_fb.c
@@ -61,7 +61,7 @@ _ecore_evas_mouse_move_process_fb(Ecore_Evas *ee, int x, int y)
61 61
62 ecore_fb_size_get(&fbw, &fbh); 62 ecore_fb_size_get(&fbw, &fbh);
63 63
64 pointer = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_MOUSE); 64 pointer = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_MOUSE);
65 pointer = evas_device_parent_get(pointer); 65 pointer = evas_device_parent_get(pointer);
66 cursor = eina_hash_find(ee->prop.cursors, &pointer); 66 cursor = eina_hash_find(ee->prop.cursors, &pointer);
67 EINA_SAFETY_ON_NULL_RETURN(cursor); 67 EINA_SAFETY_ON_NULL_RETURN(cursor);
@@ -330,7 +330,7 @@ _ecore_evas_rotation_set(Ecore_Evas *ee, int rotation, int resize EINA_UNUSED)
330 Evas_Engine_Info_FB *einfo; 330 Evas_Engine_Info_FB *einfo;
331 int rot_dif; 331 int rot_dif;
332 332
333 pointer = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_MOUSE); 333 pointer = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_MOUSE);
334 pointer = evas_device_parent_get(pointer); 334 pointer = evas_device_parent_get(pointer);
335 cursor = eina_hash_find(ee->prop.cursors, &pointer); 335 cursor = eina_hash_find(ee->prop.cursors, &pointer);
336 EINA_SAFETY_ON_NULL_RETURN(cursor); 336 EINA_SAFETY_ON_NULL_RETURN(cursor);
diff --git a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
index 947ac2de7e..ab4190a1a8 100644
--- a/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
+++ b/src/modules/ecore_evas/engines/wayland/ecore_evas_wayland_common.c
@@ -2427,7 +2427,7 @@ _reeval_seat(unsigned int *seat, Ecore_Evas *ee)
2427 { 2427 {
2428 *seat = 2428 *seat =
2429 evas_device_seat_id_get(evas_default_device_get 2429 evas_device_seat_id_get(evas_default_device_get
2430 (ee->evas, EFL_INPUT_DEVICE_TYPE_SEAT)); 2430 (ee->evas, EVAS_DEVICE_CLASS_SEAT));
2431 } 2431 }
2432} 2432}
2433 2433
diff --git a/src/modules/ecore_evas/engines/x/ecore_evas_x.c b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
index 91cd012388..bb5f02c853 100644
--- a/src/modules/ecore_evas/engines/x/ecore_evas_x.c
+++ b/src/modules/ecore_evas/engines/x/ecore_evas_x.c
@@ -1596,7 +1596,7 @@ _ecore_evas_x_event_window_configure(void *data EINA_UNUSED, int type EINA_UNUSE
1596 } 1596 }
1597 if (edata->direct_resize) return ECORE_CALLBACK_PASS_ON; 1597 if (edata->direct_resize) return ECORE_CALLBACK_PASS_ON;
1598 1598
1599 pointer = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_MOUSE); 1599 pointer = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_MOUSE);
1600 pointer = evas_device_parent_get(pointer); 1600 pointer = evas_device_parent_get(pointer);
1601 cursor = eina_hash_find(ee->prop.cursors, &pointer); 1601 cursor = eina_hash_find(ee->prop.cursors, &pointer);
1602 EINA_SAFETY_ON_NULL_RETURN_VAL(cursor, ECORE_CALLBACK_PASS_ON); 1602 EINA_SAFETY_ON_NULL_RETURN_VAL(cursor, ECORE_CALLBACK_PASS_ON);
@@ -2330,7 +2330,7 @@ _ecore_evas_x_rotation_set_internal(Ecore_Evas *ee, int rotation, int resize,
2330 Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data; 2330 Ecore_Evas_Engine_Data_X11 *edata = ee->engine.data;
2331 int fw = 0, fh = 0; 2331 int fw = 0, fh = 0;
2332 2332
2333 pointer = evas_default_device_get(ee->evas, EFL_INPUT_DEVICE_TYPE_MOUSE); 2333 pointer = evas_default_device_get(ee->evas, EVAS_DEVICE_CLASS_MOUSE);
2334 pointer = evas_device_parent_get(pointer); 2334 pointer = evas_device_parent_get(pointer);
2335 cursor = eina_hash_find(ee->prop.cursors, &pointer); 2335 cursor = eina_hash_find(ee->prop.cursors, &pointer);
2336 EINA_SAFETY_ON_NULL_RETURN(cursor); 2336 EINA_SAFETY_ON_NULL_RETURN(cursor);
@@ -4196,8 +4196,7 @@ _ecore_evas_x_dnd_position(void *udata EINA_UNUSED, int type EINA_UNUSED, void *
4196 EINA_SAFETY_ON_NULL_GOTO(ee, end); 4196 EINA_SAFETY_ON_NULL_GOTO(ee, end);
4197 ecore_evas_geometry_get(ee, &x, &y, &w, &h); 4197 ecore_evas_geometry_get(ee, &x, &y, &w, &h);
4198 Eina_Bool used = ecore_evas_dnd_position_set(ee, 1, EINA_POSITION2D(pos->position.x - x, pos->position.y - y)); 4198 Eina_Bool used = ecore_evas_dnd_position_set(ee, 1, EINA_POSITION2D(pos->position.x - x, pos->position.y - y));
4199 if (used) 4199 ecore_x_dnd_send_status(used, EINA_FALSE, (Ecore_X_Rectangle){x,y,w,h}, pos->action);
4200 ecore_x_dnd_send_status(EINA_TRUE, EINA_FALSE, (Ecore_X_Rectangle){x,y,w,h}, pos->action);
4201end: 4200end:
4202 return ECORE_CALLBACK_PASS_ON; 4201 return ECORE_CALLBACK_PASS_ON;
4203} 4202}
diff --git a/src/modules/ecore_imf/scim/meson.build b/src/modules/ecore_imf/scim/meson.build
index 6f67ebc69d..68d94793e5 100644
--- a/src/modules/ecore_imf/scim/meson.build
+++ b/src/modules/ecore_imf/scim/meson.build
@@ -9,7 +9,7 @@ if not scim_dep.found()
9 scim_dep = dependency('scim-1.0') 9 scim_dep = dependency('scim-1.0')
10endif 10endif
11 11
12mod_deps = [ecore, ecore_imf, ecore_x, ecore_x_deps, ecore_evas, scim_dep, dependency('glib-2.0')] 12mod_deps = [ecore, ecore_imf, ecore_x, ecore_x_ext_deps, ecore_evas, scim_dep, dependency('glib-2.0')]
13 13
14shared_module(mod_name, 14shared_module(mod_name,
15 mod_src, 15 mod_src,
diff --git a/src/modules/ecore_imf/xim/meson.build b/src/modules/ecore_imf/xim/meson.build
index d5411c77d9..928f396a10 100644
--- a/src/modules/ecore_imf/xim/meson.build
+++ b/src/modules/ecore_imf/xim/meson.build
@@ -2,7 +2,7 @@ mod_src = files([
2 'ecore_imf_xim.c', 2 'ecore_imf_xim.c',
3]) 3])
4 4
5mod_deps = [ecore, ecore_imf, ecore_input, ecore_x, ecore_x_deps, ecore_evas] 5mod_deps = [ecore, ecore_imf, ecore_input, ecore_x, ecore_x_ext_deps, ecore_evas]
6 6
7shared_module(mod_name, 7shared_module(mod_name,
8 mod_src, 8 mod_src,
diff --git a/src/modules/elementary/web/none/elm_web_none_eo.h b/src/modules/elementary/web/none/elm_web_none_eo.h
index 8bf39b1461..df91907d17 100644
--- a/src/modules/elementary/web/none/elm_web_none_eo.h
+++ b/src/modules/elementary/web/none/elm_web_none_eo.h
@@ -19,6 +19,6 @@ typedef Eo Elm_Web_None;
19 */ 19 */
20#define ELM_WEB_NONE_CLASS elm_web_none_class_get() 20#define ELM_WEB_NONE_CLASS elm_web_none_class_get()
21 21
22EWAPI const Efl_Class *elm_web_none_class_get(void); 22EWAPI const Efl_Class *elm_web_none_class_get(void) EINA_CONST;
23 23
24#endif 24#endif
diff --git a/src/modules/ethumb/emotion/emotion.c b/src/modules/ethumb/emotion/emotion.c
index ccad1c9074..0a8447f49b 100644
--- a/src/modules/ethumb/emotion/emotion.c
+++ b/src/modules/ethumb/emotion/emotion.c
@@ -319,8 +319,9 @@ _frame_grab(void *data)
319 319
320 pixels = ecore_evas_buffer_pixels_get(ee); 320 pixels = ecore_evas_buffer_pixels_get(ee);
321 snprintf(buf, sizeof(buf), "images/%d", _plugin->frnum); 321 snprintf(buf, sizeof(buf), "images/%d", _plugin->frnum);
322 eet_data_image_write(_plugin->ef, buf, pixels, _plugin->w, _plugin->h, 322 if (!eet_data_image_write(_plugin->ef, buf, pixels, _plugin->w, _plugin->h,
323 0, compress, quality, quality); 323 0, compress, quality, quality))
324 return EINA_TRUE;
324 _plugin->frnum++; 325 _plugin->frnum++;
325 } 326 }
326 327
diff --git a/src/modules/evas/engines/buffer/evas_outbuf.c b/src/modules/evas/engines/buffer/evas_outbuf.c
index 545ff096ed..d143179f21 100644
--- a/src/modules/evas/engines/buffer/evas_outbuf.c
+++ b/src/modules/evas/engines/buffer/evas_outbuf.c
@@ -45,8 +45,9 @@ evas_buffer_outbuf_buf_update_fb(Outbuf *buf, int w, int h, Outbuf_Depth depth,
45 if ((buf->depth == OUTBUF_DEPTH_ARGB_32BPP_8888_8888) && 45 if ((buf->depth == OUTBUF_DEPTH_ARGB_32BPP_8888_8888) &&
46 (buf->dest) && (buf->dest_row_bytes == (buf->w * sizeof(DATA32)))) 46 (buf->dest) && (buf->dest_row_bytes == (buf->w * sizeof(DATA32))))
47 { 47 {
48 memset(buf->dest, 0, h * buf->dest_row_bytes); 48 memset(buf->dest, 0, h * buf->dest_row_bytes);
49 buf->priv.back_buf = 49 if (buf->priv.back_buf) evas_cache_image_drop(&buf->priv.back_buf->cache_entry);
50 buf->priv.back_buf =
50 (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(), 51 (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(),
51 w, h, buf->dest, 52 w, h, buf->dest,
52 1, EVAS_COLORSPACE_ARGB8888); 53 1, EVAS_COLORSPACE_ARGB8888);
@@ -54,6 +55,7 @@ evas_buffer_outbuf_buf_update_fb(Outbuf *buf, int w, int h, Outbuf_Depth depth,
54 else if ((buf->depth == OUTBUF_DEPTH_RGB_32BPP_888_8888) && 55 else if ((buf->depth == OUTBUF_DEPTH_RGB_32BPP_888_8888) &&
55 (buf->dest) && (buf->dest_row_bytes == (buf->w * sizeof(DATA32)))) 56 (buf->dest) && (buf->dest_row_bytes == (buf->w * sizeof(DATA32))))
56 { 57 {
58 if (buf->priv.back_buf) evas_cache_image_drop(&buf->priv.back_buf->cache_entry);
57 buf->priv.back_buf = 59 buf->priv.back_buf =
58 (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(), 60 (RGBA_Image *) evas_cache_image_data(evas_common_image_cache_get(),
59 w, h, buf->dest, 61 w, h, buf->dest,
diff --git a/src/modules/evas/engines/gl_common/evas_gl_common.h b/src/modules/evas/engines/gl_common/evas_gl_common.h
index 5873b93fb6..c7b4d22150 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -368,6 +368,9 @@ struct _Evas_Engine_GL_Context
368 Eina_List *font_glyph_images; 368 Eina_List *font_glyph_images;
369 Evas_GL_Image *def_surface; 369 Evas_GL_Image *def_surface;
370 RGBA_Image *font_surface; 370 RGBA_Image *font_surface;
371 int font_glyph_textures_size;
372 int font_glyph_atlas_size;
373 Eina_Bool font_glyph_gc_requested :1;
371 374
372#ifdef GL_GLES 375#ifdef GL_GLES
373 // FIXME: hack. expose egl display to gl core for egl image sec extn. 376 // FIXME: hack. expose egl display to gl core for egl image sec extn.
diff --git a/src/modules/evas/engines/gl_common/evas_gl_core.c b/src/modules/evas/engines/gl_common/evas_gl_core.c
index 96d0807c39..786c54c825 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_core.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_core.c
@@ -88,7 +88,13 @@ error:
88static void 88static void
89_internal_resources_destroy(void *eng_data, EVGL_Resource *rsc) 89_internal_resources_destroy(void *eng_data, EVGL_Resource *rsc)
90{ 90{
91 if ((!eng_data) || (!rsc)) return; 91 if (!rsc) return;
92
93 if (!eng_data)
94 {
95 free(rsc);
96 return;
97 }
92 98
93 if (rsc->context) 99 if (rsc->context)
94 evgl_engine->funcs->context_destroy(eng_data, rsc->context); 100 evgl_engine->funcs->context_destroy(eng_data, rsc->context);
diff --git a/src/modules/evas/engines/gl_common/evas_gl_font.c b/src/modules/evas/engines/gl_common/evas_gl_font.c
index 53260d971d..4a5f428487 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_font.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_font.c
@@ -218,13 +218,37 @@ void
218evas_gl_font_image_draw(void *gc, void *gl_image, int dx, int dy, int dw, int dh, int smooth) 218evas_gl_font_image_draw(void *gc, void *gl_image, int dx, int dy, int dw, int dh, int smooth)
219{ 219{
220 Evas_GL_Image *im = (Evas_GL_Image *)gl_image; 220 Evas_GL_Image *im = (Evas_GL_Image *)gl_image;
221 Evas_Engine_GL_Context *gl_context = gc;
222 Eina_Bool is_cached = EINA_FALSE;
223 Eina_Bool is_new_atlas = EINA_FALSE;
221 224
222 if (!im || !im->fglyph) return; 225 if (!im || !im->fglyph) return;
223 226
224 evas_gl_common_image_draw((Evas_Engine_GL_Context *)gc, 227 is_cached = (im->tex != NULL) && (im->tex->pt != NULL);
228
229 evas_gl_common_image_draw(gl_context,
225 im, 0, 0, 230 im, 0, 0,
226 (unsigned int)im->fglyph->glyph_out->bitmap.width, 231 (unsigned int)im->fglyph->glyph_out->bitmap.width,
227 (unsigned int)im->fglyph->glyph_out->bitmap.rows, 232 (unsigned int)im->fglyph->glyph_out->bitmap.rows,
228 dx, dy, dw, dh, 233 dx, dy, dw, dh,
229 smooth); 234 smooth);
235
236 // Move latest used glyph image to the back, because GC will start freeing from the beginning
237 gl_context->font_glyph_images = eina_list_remove(gl_context->font_glyph_images, im);
238 gl_context->font_glyph_images = eina_list_append(gl_context->font_glyph_images, im);
239
240 if (!is_cached)
241 {
242 gl_context->font_glyph_textures_size += im->w * im->h * 4;
243 }
244
245 is_new_atlas = (!is_cached) && (im->tex != NULL) && (im->tex->pt) && (im->tex->pt->references == 1);
246 if (is_new_atlas)
247 {
248 int size = (im->tex->pt->w * im->tex->pt->h * 4);
249 gl_context->font_glyph_atlas_size += size;
250 if ((evas_font_data_cache_get(EVAS_FONT_DATA_CACHE_TEXTURE) >= 0) &&
251 (evas_font_data_cache_get(EVAS_FONT_DATA_CACHE_TEXTURE) * 0.95 < gl_context->font_glyph_atlas_size))
252 gl_context->font_glyph_gc_requested = EINA_TRUE;
253 }
230} 254}
diff --git a/src/modules/evas/engines/gl_common/evas_gl_texture.c b/src/modules/evas/engines/gl_common/evas_gl_texture.c
index 1aa9d3ccb0..47dd8305a8 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_texture.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_texture.c
@@ -1565,6 +1565,7 @@ evas_gl_common_texture_free(Evas_GL_Texture *tex, Eina_Bool force)
1565 if (tex->references != 0) return; 1565 if (tex->references != 0) return;
1566 if (tex->fglyph) 1566 if (tex->fglyph)
1567 { 1567 {
1568 tex->gc->font_glyph_textures_size -= tex->w * tex->h * 4;
1568 tex->gc->font_glyph_textures = eina_list_remove(tex->gc->font_glyph_textures, tex); 1569 tex->gc->font_glyph_textures = eina_list_remove(tex->gc->font_glyph_textures, tex);
1569 tex->fglyph->ext_dat = NULL; 1570 tex->fglyph->ext_dat = NULL;
1570 tex->fglyph->ext_dat_free = NULL; 1571 tex->fglyph->ext_dat_free = NULL;
@@ -1575,6 +1576,10 @@ evas_gl_common_texture_free(Evas_GL_Texture *tex, Eina_Bool force)
1575 tex->pt->allocations = eina_list_remove(tex->pt->allocations, tex->apt); 1576 tex->pt->allocations = eina_list_remove(tex->pt->allocations, tex->apt);
1576 if (tex->apt) eina_rectangle_pool_release(tex->apt); 1577 if (tex->apt) eina_rectangle_pool_release(tex->apt);
1577 tex->apt = NULL; 1578 tex->apt = NULL;
1579 if (tex->fglyph && (tex->pt->references == 1))
1580 {
1581 tex->gc->font_glyph_atlas_size -= tex->pt->w * tex->pt->h * 4;
1582 }
1578 pt_unref(tex->pt); 1583 pt_unref(tex->pt);
1579 tex->pt = NULL; 1584 tex->pt = NULL;
1580 } 1585 }
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c b/src/modules/evas/engines/gl_generic/evas_engine.c
index 0fc241643d..b413436efd 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -2467,7 +2467,8 @@ eng_ector_buffer_new(void *engine, Evas *evas, int w, int h,
2467 2467
2468 // alloc buffer 2468 // alloc buffer
2469 ie = evas_cache_image_copied_data(evas_common_image_cache_get(), w, h, 2469 ie = evas_cache_image_copied_data(evas_common_image_cache_get(), w, h,
2470 NULL, EINA_TRUE, cspace); 2470 NULL, EINA_TRUE,
2471 (Evas_Colorspace)cspace);
2471 if (!ie) return NULL; 2472 if (!ie) return NULL;
2472 pixels = ((RGBA_Image *) ie)->image.data; 2473 pixels = ((RGBA_Image *) ie)->image.data;
2473 memset(pixels, 0, w * h * pxs); 2474 memset(pixels, 0, w * h * pxs);
@@ -2758,15 +2759,15 @@ eng_image_data_maps_get(void *engine EINA_UNUSED, const void *image, const Eina_
2758} 2759}
2759 2760
2760static inline Eina_Bool 2761static inline Eina_Bool
2761_is_yuv(Efl_Gfx_Colorspace cspace) 2762_is_yuv(Evas_Colorspace cspace)
2762{ 2763{
2763 switch (cspace) 2764 switch (cspace)
2764 { 2765 {
2765 case EFL_GFX_COLORSPACE_YCBCR422P601_PL: 2766 case EVAS_COLORSPACE_YCBCR422P601_PL:
2766 case EFL_GFX_COLORSPACE_YCBCR422P709_PL: 2767 case EVAS_COLORSPACE_YCBCR422P709_PL:
2767 case EFL_GFX_COLORSPACE_YCBCR422601_PL: 2768 case EVAS_COLORSPACE_YCBCR422601_PL:
2768 case EFL_GFX_COLORSPACE_YCBCR420NV12601_PL: 2769 case EVAS_COLORSPACE_YCBCR420NV12601_PL:
2769 case EFL_GFX_COLORSPACE_YCBCR420TM12601_PL: 2770 case EVAS_COLORSPACE_YCBCR420TM12601_PL:
2770 return EINA_TRUE; 2771 return EINA_TRUE;
2771 2772
2772 default: 2773 default:
@@ -3023,6 +3024,42 @@ eng_gfx_filter_process(void *engine, Evas_Filter_Command *cmd)
3023 return pfunc.gfx_filter_process(&re->software, cmd); 3024 return pfunc.gfx_filter_process(&re->software, cmd);
3024} 3025}
3025 3026
3027static void
3028eng_font_glyphs_gc_collect(void *data EINA_UNUSED, float ratio EINA_UNUSED, int *texture_size EINA_UNUSED, int *atlas_size EINA_UNUSED, Eina_Bool only_when_requested EINA_UNUSED)
3029{
3030 Evas_Engine_GL_Context *gl_context;
3031 gl_context = gl_generic_context_find(data, 1);
3032
3033 if ((only_when_requested && gl_context->font_glyph_gc_requested) || (!only_when_requested))
3034 {
3035 if (ratio > 0.0)
3036 {
3037 int requested_size = ratio * gl_context->font_glyph_textures_size;
3038
3039 Eina_List *l;
3040 Eina_List *ll;
3041 Evas_GL_Image *im;
3042 EINA_LIST_FOREACH_SAFE(gl_context->font_glyph_images, l, ll, im)
3043 {
3044 int size = im->w * im->h * 4;
3045 gl_context->font_glyph_textures_size -= size;
3046 requested_size -= size;
3047 if ((im->tex != NULL) && (im->tex->pt) && (im->tex->pt->references == 1))
3048 {
3049 gl_context->font_glyph_atlas_size -= im->tex->pt->w * im->tex->pt->h * 4;
3050 }
3051 evas_gl_common_image_free(im);
3052 if (requested_size <= 0)
3053 break;
3054 }
3055 }
3056
3057 gl_context->font_glyph_gc_requested = EINA_FALSE;
3058 }
3059 if (texture_size) *texture_size = gl_context->font_glyph_textures_size;
3060 if (atlas_size) *atlas_size = gl_context->font_glyph_atlas_size;
3061}
3062
3026//------------------------------------------------// 3063//------------------------------------------------//
3027 3064
3028static int 3065static int
@@ -3178,6 +3215,7 @@ module_open(Evas_Module *em)
3178 ORD(ector_surface_cache_drop); 3215 ORD(ector_surface_cache_drop);
3179 ORD(gfx_filter_supports); 3216 ORD(gfx_filter_supports);
3180 ORD(gfx_filter_process); 3217 ORD(gfx_filter_process);
3218 ORD(font_glyphs_gc_collect);
3181 3219
3182 /* now advertise out own api */ 3220 /* now advertise out own api */
3183 em->functions = (void *)(&func); 3221 em->functions = (void *)(&func);
diff --git a/src/modules/evas/engines/software_generic/evas_ector_software_buffer.c b/src/modules/evas/engines/software_generic/evas_ector_software_buffer.c
index 41730d7298..ba33e72cd4 100644
--- a/src/modules/evas/engines/software_generic/evas_ector_software_buffer.c
+++ b/src/modules/evas/engines/software_generic/evas_ector_software_buffer.c
@@ -32,7 +32,7 @@ _evas_ector_software_buffer_evas_ector_buffer_engine_image_set(Eo *obj,
32 evas_cache_image_ref(&im->cache_entry); 32 evas_cache_image_ref(&im->cache_entry);
33 pd->image = im; 33 pd->image = im;
34 34
35 ector_buffer_pixels_set(obj, im->image.data, im->cache_entry.w, im->cache_entry.h, 0, im->cache_entry.space, EINA_TRUE); 35 ector_buffer_pixels_set(obj, im->image.data, im->cache_entry.w, im->cache_entry.h, 0, (Efl_Gfx_Colorspace)im->cache_entry.space, EINA_TRUE);
36} 36}
37 37
38EOLIAN static void * 38EOLIAN static void *
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c b/src/modules/evas/engines/software_generic/evas_engine.c
index a942a96f02..78d8172b93 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -1518,11 +1518,15 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image, Eina_Rw_Slice *slice
1518 void *src_data; 1518 void *src_data;
1519 int dst_stride, dst_len, dst_offset = 0; 1519 int dst_stride, dst_len, dst_offset = 0;
1520 1520
1521 cs_func = efl_draw_convert_func_get(ie->space, cspace, &can_region); 1521 cs_func = efl_draw_convert_func_get((Efl_Gfx_Colorspace)ie->space,
1522 (Efl_Gfx_Colorspace)cspace,
1523 &can_region);
1522 if (!cs_func) return EINA_FALSE; 1524 if (!cs_func) return EINA_FALSE;
1523 1525
1524 // make sure we can convert back, if map for writing 1526 // make sure we can convert back, if map for writing
1525 if (to_write && !efl_draw_convert_func_get(cspace, ie->space, NULL)) 1527 if (to_write && !efl_draw_convert_func_get((Efl_Gfx_Colorspace)cspace,
1528 (Efl_Gfx_Colorspace)ie->space,
1529 NULL))
1526 return EINA_FALSE; 1530 return EINA_FALSE;
1527 1531
1528 if (can_region) 1532 if (can_region)
@@ -1554,7 +1558,10 @@ eng_image_data_map(void *engdata EINA_UNUSED, void **image, Eina_Rw_Slice *slice
1554 data = malloc(dst_len); 1558 data = malloc(dst_len);
1555 if (!data) return EINA_FALSE; 1559 if (!data) return EINA_FALSE;
1556 1560
1557 if (!cs_func(data, src_data, rw, rh, src_stride, dst_stride, ie->flags.alpha, ie->space, cspace)) 1561 if (!cs_func(data, src_data, rw, rh, src_stride, dst_stride,
1562 ie->flags.alpha,
1563 (Efl_Gfx_Colorspace)ie->space,
1564 (Efl_Gfx_Colorspace)cspace))
1558 { 1565 {
1559 ERR("color conversion failed"); 1566 ERR("color conversion failed");
1560 free(data); 1567 free(data);
@@ -1656,19 +1663,25 @@ _image_data_commit(RGBA_Image *im, RGBA_Image_Data_Map *map)
1656 Cspace_Convert_Func cs_func; 1663 Cspace_Convert_Func cs_func;
1657 Eina_Bool can_region; 1664 Eina_Bool can_region;
1658 1665
1659 cs_func = efl_draw_convert_func_get(map->cspace, ie->space, &can_region); 1666 cs_func = efl_draw_convert_func_get((Efl_Gfx_Colorspace)map->cspace,
1667 (Efl_Gfx_Colorspace)ie->space,
1668 &can_region);
1660 EINA_SAFETY_ON_NULL_RETURN(cs_func); 1669 EINA_SAFETY_ON_NULL_RETURN(cs_func);
1661 1670
1662 DBG("unmap commit: convert func (%p)", cs_func); 1671 DBG("unmap commit: convert func (%p)", cs_func);
1663 if (can_region) 1672 if (can_region)
1664 { 1673 {
1665 cs_func(dst, map->slice.mem, map->rw, map->rh, map->stride, dst_stride, 1674 cs_func(dst, map->slice.mem, map->rw, map->rh, map->stride, dst_stride,
1666 ie->flags.alpha, map->cspace, ie->space); 1675 ie->flags.alpha,
1676 (Efl_Gfx_Colorspace)map->cspace,
1677 (Efl_Gfx_Colorspace)ie->space);
1667 } 1678 }
1668 else 1679 else
1669 { 1680 {
1670 cs_func(dst, map->baseptr, ie->w, ie->h, map->stride, dst_stride, 1681 cs_func(dst, map->baseptr, ie->w, ie->h, map->stride, dst_stride,
1671 ie->flags.alpha, map->cspace, ie->space); 1682 ie->flags.alpha,
1683 (Efl_Gfx_Colorspace)map->cspace,
1684 (Efl_Gfx_Colorspace)ie->space);
1672 } 1685 }
1673 } 1686 }
1674} 1687}
@@ -1722,15 +1735,15 @@ eng_image_data_maps_get(void *engdata EINA_UNUSED, const void *image, const Eina
1722} 1735}
1723 1736
1724static inline Eina_Bool 1737static inline Eina_Bool
1725_is_yuv(Efl_Gfx_Colorspace cspace) 1738_is_yuv(Evas_Colorspace cspace)
1726{ 1739{
1727 switch (cspace) 1740 switch (cspace)
1728 { 1741 {
1729 case EFL_GFX_COLORSPACE_YCBCR422P601_PL: 1742 case EVAS_COLORSPACE_YCBCR422P601_PL:
1730 case EFL_GFX_COLORSPACE_YCBCR422P709_PL: 1743 case EVAS_COLORSPACE_YCBCR422P709_PL:
1731 case EFL_GFX_COLORSPACE_YCBCR422601_PL: 1744 case EVAS_COLORSPACE_YCBCR422601_PL:
1732 case EFL_GFX_COLORSPACE_YCBCR420NV12601_PL: 1745 case EVAS_COLORSPACE_YCBCR420NV12601_PL:
1733 case EFL_GFX_COLORSPACE_YCBCR420TM12601_PL: 1746 case EVAS_COLORSPACE_YCBCR420TM12601_PL:
1734 return EINA_TRUE; 1747 return EINA_TRUE;
1735 1748
1736 default: 1749 default:
@@ -3975,58 +3988,60 @@ _smart_merge(Tilebuf *tb, Tilebuf_Rect *rects)
3975 box = region_rects(region); 3988 box = region_rects(region);
3976 n = region_rects_num(region); 3989 n = region_rects_num(region);
3977 merged = calloc(1, n * sizeof(Tilebuf_Rect)); 3990 merged = calloc(1, n * sizeof(Tilebuf_Rect));
3978 j = 0; 3991 if (merged) {
3992 j = 0;
3979#if 1 3993#if 1
3980 // regions sometimes produce box sets like: 3994 // regions sometimes produce box sets like:
3981 // +---+ 3995 // +---+
3982 // | | 3996 // | |
3983 // +---+ +-------+ 3997 // +---+ +-------+
3984 // | | | | 3998 // | | | |
3985 // +---+ +-------+---------+ 3999 // +---+ +-------+---------+
3986 // | | 4000 // | |
3987 // | | 4001 // | |
3988 // +-----------------+ 4002 // +-----------------+
3989 // so the upper-left 2 boxes can be merged into 1 and they have the same 4003 // so the upper-left 2 boxes can be merged into 1 and they have the same
3990 // x coords and are flush-aligned one above the other. that is what 4004 // x coords and are flush-aligned one above the other. that is what
3991 // this does - find these and merge them to have fewer rects 4005 // this does - find these and merge them to have fewer rects
3992 for (i = 0; i < n; i++) 4006 for (i = 0; i < n; i++)
3993 {
3994 // skip empty boxes
3995 if (box[i].x1 == box[i].x2) continue;
3996 // walk all following boxes after this and see if they can be merged
3997 // into box i
3998 for (k = i + 1; k < n; k++)
3999 { 4007 {
4000 // skip empty boxes after i 4008 // skip empty boxes
4001 if (box[k].x1 == box[k].x2) continue; 4009 if (box[i].x1 == box[i].x2) continue;
4002 // match x coords 4010 // walk all following boxes after this and see if they can be merged
4003 if ((box[i].x1 == box[k].x1) && // if aligned vertically 4011 // into box i
4004 (box[i].x2 == box[k].x2)) // exactly above/below 4012 for (k = i + 1; k < n; k++)
4005 { 4013 {
4006 // right below, or right above 4014 // skip empty boxes after i
4007 if (box[i].y2 == box[k].y1) // this box flush below 4015 if (box[k].x1 == box[k].x2) continue;
4008 { 4016 // match x coords
4009 box[i].y2 = box[k].y2; // merge below i 4017 if ((box[i].x1 == box[k].x1) && // if aligned vertically
4010 box[k].x2 = box[k].x1; // empty this box - merged 4018 (box[i].x2 == box[k].x2)) // exactly above/below
4011 }
4012 else if (box[i].y1 == box[k].y2) // this box flush above
4013 { 4019 {
4014 box[i].y2 = box[k].y2; // merge above i 4020 // right below, or right above
4015 box[k].x2 = box[k].x1; // empty this box - merged 4021 if (box[i].y2 == box[k].y1) // this box flush below
4022 {
4023 box[i].y2 = box[k].y2; // merge below i
4024 box[k].x2 = box[k].x1; // empty this box - merged
4025 }
4026 else if (box[i].y1 == box[k].y2) // this box flush above
4027 {
4028 box[i].y2 = box[k].y2; // merge above i
4029 box[k].x2 = box[k].x1; // empty this box - merged
4030 }
4016 } 4031 }
4017 } 4032 }
4033 // i may have expanded but will not be empty. future boxes after
4034 // this may be empty though but handled at top of loop
4035 merged[j].x = box[i].x1;
4036 merged[j].y = box[i].y1;
4037 merged[j].w = box[i].x2 - box[i].x1;
4038 merged[j].h = box[i].y2 - box[i].y1;
4039 mergelist = (Tilebuf_Rect *)eina_inlist_append
4040 (EINA_INLIST_GET(mergelist), EINA_INLIST_GET(&(merged[j])));
4041 j++;
4018 } 4042 }
4019 // i may have expanded but will not be empty. future boxes after
4020 // this may be empty though but handled at top of loop
4021 merged[j].x = box[i].x1;
4022 merged[j].y = box[i].y1;
4023 merged[j].w = box[i].x2 - box[i].x1;
4024 merged[j].h = box[i].y2 - box[i].y1;
4025 mergelist = (Tilebuf_Rect *)eina_inlist_append
4026 (EINA_INLIST_GET(mergelist), EINA_INLIST_GET(&(merged[j])));
4027 j++;
4028 }
4029#endif 4043#endif
4044 }
4030 region_free(region); 4045 region_free(region);
4031 rects = mergelist; 4046 rects = mergelist;
4032 4047
@@ -4389,8 +4404,9 @@ eng_ector_buffer_new(void *data, Evas *evas, int width, int height,
4389 } 4404 }
4390 4405
4391 // alloc buffer 4406 // alloc buffer
4392 ie = evas_cache_image_copied_data(evas_common_image_cache_get(), width, height, 4407 ie = evas_cache_image_copied_data(evas_common_image_cache_get(),
4393 NULL, EINA_TRUE, cspace); 4408 width, height, NULL, EINA_TRUE,
4409 (Evas_Colorspace)cspace);
4394 if (!ie) return NULL; 4410 if (!ie) return NULL;
4395 pixels = ((RGBA_Image *) ie)->image.data; 4411 pixels = ((RGBA_Image *) ie)->image.data;
4396 memset(pixels, 0, width * height * pxs); 4412 memset(pixels, 0, width * height * pxs);
@@ -4645,6 +4661,12 @@ eng_gfx_filter_supports(void *data EINA_UNUSED, Evas_Filter_Command *cmd)
4645 return EVAS_FILTER_SUPPORT_CPU; 4661 return EVAS_FILTER_SUPPORT_CPU;
4646} 4662}
4647 4663
4664static void
4665eng_font_glyphs_gc_collect(void *data EINA_UNUSED, float ratio EINA_UNUSED, int *texture_size EINA_UNUSED, int *atlas_size EINA_UNUSED, Eina_Bool only_when_requested EINA_UNUSED)
4666{
4667 return;
4668}
4669
4648static Eina_Bool 4670static Eina_Bool
4649eng_gfx_filter_process(void *data EINA_UNUSED, Evas_Filter_Command *cmd) 4671eng_gfx_filter_process(void *data EINA_UNUSED, Evas_Filter_Command *cmd)
4650{ 4672{
@@ -4851,6 +4873,7 @@ static Evas_Func func =
4851 eng_gfx_filter_supports, 4873 eng_gfx_filter_supports,
4852 eng_gfx_filter_process, 4874 eng_gfx_filter_process,
4853 /* FUTURE software generic calls go here */ 4875 /* FUTURE software generic calls go here */
4876 eng_font_glyphs_gc_collect,
4854 0 // sizeof (Info) 4877 0 // sizeof (Info)
4855}; 4878};
4856 4879
diff --git a/src/modules/evas/engines/software_x11/meson.build b/src/modules/evas/engines/software_x11/meson.build
index 6ddaeee37b..ed0a3e4b46 100644
--- a/src/modules/evas/engines/software_x11/meson.build
+++ b/src/modules/evas/engines/software_x11/meson.build
@@ -26,7 +26,7 @@ config_h.set('BUILD_ENGINE_SOFTWARE_XLIB', '1')
26 26
27#ecore_x_deps carries all the extensions etc. so we dont have to search them twice 27#ecore_x_deps carries all the extensions etc. so we dont have to search them twice
28#it looks weird but is right, gl_deps is needed for evas_x_egl.c 28#it looks weird but is right, gl_deps is needed for evas_x_egl.c
29engine_deps += [x11, ecore_x, ecore_x_deps, gl_deps] 29engine_deps += [x11, ecore_x, ecore_x_ext_deps, gl_deps]
30 30
31shared_module(mod_full_name, engine_src, 31shared_module(mod_full_name, engine_src,
32 include_directories : config_dir + [engine_include_dir], 32 include_directories : config_dir + [engine_include_dir],
diff --git a/src/modules/evas/engines/wayland_shm/evas_engine.c b/src/modules/evas/engines/wayland_shm/evas_engine.c
index 3a3623a567..041dfa9e54 100644
--- a/src/modules/evas/engines/wayland_shm/evas_engine.c
+++ b/src/modules/evas/engines/wayland_shm/evas_engine.c
@@ -243,6 +243,8 @@ eng_image_native_set(void *engine EINA_UNUSED, void *image, void *native)
243 NULL, 1, 243 NULL, 1,
244 EVAS_COLORSPACE_ARGB8888); 244 EVAS_COLORSPACE_ARGB8888);
245 245
246 EINA_SAFETY_ON_NULL_RETURN_VAL(im2, im);
247
246 if (im->native.data) 248 if (im->native.data)
247 { 249 {
248 if (im->native.func.free) 250 if (im->native.func.free)
diff --git a/src/modules/evas/image_loaders/avif/evas_image_load_avif.c b/src/modules/evas/image_loaders/avif/evas_image_load_avif.c
new file mode 100644
index 0000000000..34b6da9bd3
--- /dev/null
+++ b/src/modules/evas/image_loaders/avif/evas_image_load_avif.c
@@ -0,0 +1,382 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6
7#include <avif/avif.h>
8
9#include "Evas_Loader.h"
10#include "evas_common_private.h"
11
12typedef struct _Evas_Loader_Internal Evas_Loader_Internal;
13struct _Evas_Loader_Internal
14{
15 Eina_File *f;
16 Evas_Image_Load_Opts *opts;
17 Evas_Image_Animated *animated;
18 avifDecoder *decoder;
19 double duration;
20};
21
22static int _evas_loader_avif_log_dom = -1;
23
24#ifdef ERR
25# undef ERR
26#endif
27#define ERR(...) EINA_LOG_DOM_ERR(_evas_loader_avif_log_dom, __VA_ARGS__)
28
29#ifdef WRN
30# undef WRN
31#endif
32#define WRN(...) EINA_LOG_DOM_WARN(_evas_loader_avif_log_dom, __VA_ARGS__)
33
34#ifdef INF
35# undef INF
36#endif
37#define INF(...) EINA_LOG_DOM_INFO(_evas_loader_avif_log_dom, __VA_ARGS__)
38
39static Eina_Bool
40evas_image_load_file_head_avif_internal(Evas_Loader_Internal *loader,
41 Emile_Image_Property *prop,
42 void *map, size_t length,
43 int *error)
44{
45 Evas_Image_Animated *animated;
46 avifROData raw;
47 avifDecoder *decoder;
48 avifResult res;
49 Eina_Bool ret;
50
51 animated = loader->animated;
52
53 ret = EINA_FALSE;
54 prop->w = 0;
55 prop->h = 0;
56 prop->alpha = EINA_FALSE;
57
58 raw.size = length;
59 raw.data = (const uint8_t *)map;
60
61 decoder = avifDecoderCreate();
62 if (!decoder)
63 {
64 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
65 return ret;
66 }
67
68 res = avifDecoderParse(decoder, &raw);
69 if (res != AVIF_RESULT_OK)
70 {
71 ERR("avif file format invalid");
72 *error = EVAS_LOAD_ERROR_GENERIC;
73 goto destroy_decoder;
74 }
75
76 if (decoder->imageCount < 1)
77 {
78 ERR("avif file format invalid");
79 *error = EVAS_LOAD_ERROR_GENERIC;
80 goto destroy_decoder;
81 }
82
83 res = avifDecoderNextImage(decoder);
84 if (res != AVIF_RESULT_OK)
85 {
86 ERR("avif file format invalid");
87 *error = EVAS_LOAD_ERROR_GENERIC;
88 goto destroy_decoder;
89 }
90
91 prop->w = decoder->image->width;
92 prop->h = decoder->image->height;
93
94 /* if size is invalid, we exit */
95 if ((prop->w < 1) || (prop->h < 1) ||
96 (prop->w > IMG_MAX_SIZE) || (prop->h > IMG_MAX_SIZE) ||
97 IMG_TOO_BIG(prop->w, prop->h))
98 {
99 if (IMG_TOO_BIG(prop->w, prop->h))
100 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
101 else
102 *error= EVAS_LOAD_ERROR_GENERIC;
103 goto destroy_decoder;
104 }
105
106 prop->alpha = !!decoder->image->alphaPlane;
107
108 if (decoder->imageCount > 1)
109 {
110 animated->loop_hint = EVAS_IMAGE_ANIMATED_HINT_NONE;
111 animated->frame_count = decoder->imageCount;
112 animated->loop_count = 1;
113 animated->animated = EINA_TRUE;
114 loader->duration = decoder->duration / decoder->imageCount;
115 }
116
117 *error = EVAS_LOAD_ERROR_NONE;
118 ret = EINA_TRUE;
119
120 destroy_decoder:
121 avifDecoderDestroy(decoder);
122
123 return ret;
124}
125
126static Eina_Bool
127evas_image_load_file_data_avif_internal(Evas_Loader_Internal *loader,
128 void *pixels,
129 void *map, size_t length,
130 int *error)
131{
132 avifRGBImage rgb;
133 avifDecoder *decoder;
134 avifResult res;
135 Evas_Image_Animated *animated;
136 Eina_Bool ret;
137
138 ret = EINA_FALSE;
139
140 /* FIXME: create decoder in evas_image_load_file_data_avif instead ? */
141 decoder = loader->decoder;
142 if (!decoder)
143 {
144 avifROData raw;
145 decoder = avifDecoderCreate();
146 if (!decoder)
147 {
148 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
149 return EINA_FALSE;
150 }
151
152 raw.size = length;
153 raw.data = (const uint8_t *)map;
154
155 res = avifDecoderParse(decoder, &raw);
156 if (res != AVIF_RESULT_OK)
157 {
158 *error = EVAS_LOAD_ERROR_GENERIC;
159 goto on_error;
160 }
161
162 loader->decoder = decoder;
163 }
164
165 animated = loader->animated;
166 if (animated->animated)
167 {
168 /* FIXME: next image instead ? */
169 res = avifDecoderNthImage(decoder, animated->cur_frame + 1);
170 if (res != AVIF_RESULT_OK)
171 {
172 *error = EVAS_LOAD_ERROR_GENERIC;
173 goto on_error;
174 }
175 }
176 else
177 {
178 res = avifDecoderNextImage(decoder);
179 if (res != AVIF_RESULT_OK)
180 {
181 *error = EVAS_LOAD_ERROR_GENERIC;
182 goto on_error;
183 }
184 }
185
186 avifRGBImageSetDefaults(&rgb, decoder->image);
187#ifdef WORDS_BIGENDIAN
188 rgb.format = AVIF_RGB_FORMAT_ARGB;
189#else
190 rgb.format = AVIF_RGB_FORMAT_BGRA;
191#endif
192 rgb.depth = 8;
193 rgb.pixels = pixels;
194 rgb.rowBytes = 4 * decoder->image->width;
195
196 avifImageYUVToRGB(decoder->image, &rgb);
197
198 *error = EVAS_LOAD_ERROR_NONE;
199
200 ret = EINA_TRUE;
201
202 on_error:
203
204 return ret;
205}
206
207static void *
208evas_image_load_file_open_avif(Eina_File *f, Eina_Stringshare *key EINA_UNUSED,
209 Evas_Image_Load_Opts *opts,
210 Evas_Image_Animated *animated,
211 int *error)
212{
213 Evas_Loader_Internal *loader;
214
215 loader = calloc(1, sizeof (Evas_Loader_Internal));
216 if (!loader)
217 {
218 *error = EVAS_LOAD_ERROR_RESOURCE_ALLOCATION_FAILED;
219 return NULL;
220 }
221
222 loader->f = f;
223 loader->opts = opts;
224 loader->animated = animated;
225
226 return loader;
227}
228
229static void
230evas_image_load_file_close_avif(void *loader_data)
231{
232 Evas_Loader_Internal *loader;
233
234 loader = loader_data;
235 avifDecoderDestroy(loader->decoder);
236 free(loader_data);
237}
238
239static Eina_Bool
240evas_image_load_file_head_avif(void *loader_data,
241 Evas_Image_Property *prop,
242 int *error)
243{
244 Evas_Loader_Internal *loader = loader_data;
245 Eina_File *f;
246 void *map;
247 Eina_Bool val;
248
249 f = loader->f;
250
251 map = eina_file_map_all(f, EINA_FILE_RANDOM);
252 if (!map)
253 {
254 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
255 return EINA_FALSE;
256 }
257
258 val = evas_image_load_file_head_avif_internal(loader,
259 (Emile_Image_Property *)prop,
260 map, eina_file_size_get(f),
261 error);
262
263 eina_file_map_free(f, map);
264
265 return val;
266}
267
268static Eina_Bool
269evas_image_load_file_data_avif(void *loader_data,
270 Evas_Image_Property *prop EINA_UNUSED,
271 void *pixels,
272 int *error)
273{
274 Evas_Loader_Internal *loader;
275 Eina_File *f;
276 void *map;
277 Eina_Bool val = EINA_FALSE;
278
279 loader = (Evas_Loader_Internal *)loader_data;
280 f = loader->f;
281
282 map = eina_file_map_all(f, EINA_FILE_WILLNEED);
283 if (!map)
284 {
285 *error = EVAS_LOAD_ERROR_DOES_NOT_EXIST;
286 goto on_error;
287 }
288
289 val = evas_image_load_file_data_avif_internal(loader,
290 pixels,
291 map, eina_file_size_get(f),
292 error);
293
294 eina_file_map_free(f, map);
295
296 on_error:
297 return val;
298}
299
300static double
301evas_image_load_frame_duration_avif(void *loader_data,
302 int start_frame,
303 int frame_num)
304{
305 Evas_Loader_Internal *loader;
306 Evas_Image_Animated *animated;
307
308 loader = (Evas_Loader_Internal *)loader_data;
309 animated = loader->animated;
310
311 if (!animated->animated)
312 return -1.0;
313
314 if (frame_num < 0)
315 return -1.0;
316
317 if ((start_frame + frame_num) > animated->frame_count)
318 return -1.0;
319
320 if (frame_num < 1)
321 frame_num = 1;
322
323 return loader->duration;
324}
325
326static Evas_Image_Load_Func evas_image_load_avif_func =
327{
328 EVAS_IMAGE_LOAD_VERSION,
329 evas_image_load_file_open_avif,
330 evas_image_load_file_close_avif,
331 evas_image_load_file_head_avif,
332 NULL,
333 evas_image_load_file_data_avif,
334 evas_image_load_frame_duration_avif,
335 EINA_TRUE,
336 EINA_TRUE
337};
338
339static int
340module_open(Evas_Module *em)
341{
342 if (!em) return 0;
343
344 _evas_loader_avif_log_dom = eina_log_domain_register("evas-avif", EINA_COLOR_BLUE);
345 if (_evas_loader_avif_log_dom < 0)
346 {
347 EINA_LOG_ERR("Can not create a module log domain.");
348 return 0;
349 }
350
351 em->functions = (void *)(&evas_image_load_avif_func);
352
353 return 1;
354}
355
356static void
357module_close(Evas_Module *em EINA_UNUSED)
358{
359 if (_evas_loader_avif_log_dom >= 0)
360 {
361 eina_log_domain_unregister(_evas_loader_avif_log_dom);
362 _evas_loader_avif_log_dom = -1;
363 }
364}
365
366static Evas_Module_Api evas_modapi =
367{
368 EVAS_MODULE_API_VERSION,
369 "avif",
370 "none",
371 {
372 module_open,
373 module_close
374 }
375};
376
377EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_LOADER, image_loader, avif);
378
379#ifndef EVAS_STATIC_BUILD_AVIF
380EVAS_EINA_MODULE_DEFINE(image_loader, avif);
381#endif
382
diff --git a/src/modules/evas/image_loaders/gif/evas_image_load_gif.c b/src/modules/evas/image_loaders/gif/evas_image_load_gif.c
index 5a55035c5a..fec8f4bb09 100644
--- a/src/modules/evas/image_loaders/gif/evas_image_load_gif.c
+++ b/src/modules/evas/image_loaders/gif/evas_image_load_gif.c
@@ -263,7 +263,7 @@ _decode_image(GifFileType *gif, DATA32 *data, int rowpix, int xin, int yin,
263 263
264 if (cmap) 264 if (cmap)
265 { 265 {
266 // fill in local color table of guaranteed 256 entires with cmap & pad 266 // fill in local color table of guaranteed 256 entries with cmap & pad
267 for (cnum = 0; cnum < cmap->ColorCount; cnum++) 267 for (cnum = 0; cnum < cmap->ColorCount; cnum++)
268 colors[cnum] = cmap->Colors[cnum]; 268 colors[cnum] = cmap->Colors[cnum];
269 for (cnum = cmap->ColorCount; cnum < 256; cnum++) 269 for (cnum = cmap->ColorCount; cnum < 256; cnum++)
diff --git a/src/modules/evas/image_loaders/png/evas_image_load_png.c b/src/modules/evas/image_loaders/png/evas_image_load_png.c
index 0558c3e9cf..ce55916b0e 100644
--- a/src/modules/evas/image_loaders/png/evas_image_load_png.c
+++ b/src/modules/evas/image_loaders/png/evas_image_load_png.c
@@ -519,7 +519,7 @@ evas_image_load_file_head_with_data_png(void *loader_data,
519 memcpy(&prop->content, &optional_content, sizeof (Eina_Rectangle)); 519 memcpy(&prop->content, &optional_content, sizeof (Eina_Rectangle));
520 520
521 // Check that the limit of our content zone are correct 521 // Check that the limit of our content zone are correct
522 // This could be handled as an incorrect file completly, 522 // This could be handled as an incorrect file completely,
523 // but let's try to recover 523 // but let's try to recover
524 if (prop->content.x == 0 || prop->content.y == 0) 524 if (prop->content.x == 0 || prop->content.y == 0)
525 { 525 {
diff --git a/src/modules/evas/image_loaders/psd/evas_image_load_psd.c b/src/modules/evas/image_loaders/psd/evas_image_load_psd.c
index 5dcf31039b..58cd961acf 100644
--- a/src/modules/evas/image_loaders/psd/evas_image_load_psd.c
+++ b/src/modules/evas/image_loaders/psd/evas_image_load_psd.c
@@ -61,7 +61,7 @@ static Eina_Bool get_compressed_channels_length(PSD_Header *Head,
61static int 61static int
62read_ushort(const unsigned char *map, size_t length, size_t *position, unsigned short *ret) 62read_ushort(const unsigned char *map, size_t length, size_t *position, unsigned short *ret)
63{ 63{
64 if (*position + 2 > length) return 0; 64 if (((*position) + 2) > length) return 0;
65 // FIXME: need to check order 65 // FIXME: need to check order
66 *ret = (map[(*position) + 0] << 8) | map[(*position) + 1]; 66 *ret = (map[(*position) + 0] << 8) | map[(*position) + 1];
67 *position += 2; 67 *position += 2;
@@ -71,7 +71,7 @@ read_ushort(const unsigned char *map, size_t length, size_t *position, unsigned
71static int 71static int
72read_uint(const unsigned char *map, size_t length, size_t *position, unsigned int *ret) 72read_uint(const unsigned char *map, size_t length, size_t *position, unsigned int *ret)
73{ 73{
74 if (*position + 4 > length) return 0; 74 if (((*position) + 4) > length) return 0;
75 // FIXME: need to check order 75 // FIXME: need to check order
76 *ret = ARGB_JOIN(map[(*position) + 0], map[(*position) + 1], map[(*position) + 2], map[(*position) + 3]); 76 *ret = ARGB_JOIN(map[(*position) + 0], map[(*position) + 1], map[(*position) + 2], map[(*position) + 3]);
77 *position += 4; 77 *position += 4;
@@ -81,14 +81,14 @@ read_uint(const unsigned char *map, size_t length, size_t *position, unsigned in
81static int 81static int
82read_block(const unsigned char *map, size_t length, size_t *position, void *target, size_t size) 82read_block(const unsigned char *map, size_t length, size_t *position, void *target, size_t size)
83{ 83{
84 if (*position + size > length) return 0; 84 if (((*position) + size) > length) return 0;
85 memcpy(target, map + *position, size); 85 memcpy(target, map + *position, size);
86 *position += size; 86 *position += size;
87 return 1; 87 return 1;
88} 88}
89 89
90// Internal function used to get the Psd header from the current file. 90// Internal function used to get the Psd header from the current file.
91Eina_Bool 91static Eina_Bool
92psd_get_header(PSD_Header *header, const unsigned char *map, size_t length, size_t *position) 92psd_get_header(PSD_Header *header, const unsigned char *map, size_t length, size_t *position)
93{ 93{
94 unsigned short tmp; 94 unsigned short tmp;
@@ -114,7 +114,7 @@ psd_get_header(PSD_Header *header, const unsigned char *map, size_t length, size
114 114
115 115
116// Internal function used to check if the HEADER is a valid Psd header. 116// Internal function used to check if the HEADER is a valid Psd header.
117Eina_Bool 117static Eina_Bool
118is_psd(PSD_Header *header) 118is_psd(PSD_Header *header)
119{ 119{
120 if (strncmp((char*)header->signature, "8BPS", 4)) 120 if (strncmp((char*)header->signature, "8BPS", 4))
@@ -238,7 +238,7 @@ read_compressed_channel(const unsigned char *map, size_t length, size_t *positio
238} 238}
239 239
240 240
241Eina_Bool 241static Eina_Bool
242psd_get_data(PSD_Header *head, 242psd_get_data(PSD_Header *head,
243 const unsigned char *map, size_t length, size_t *position, 243 const unsigned char *map, size_t length, size_t *position,
244 unsigned char *buffer, Eina_Bool compressed, 244 unsigned char *buffer, Eina_Bool compressed,
@@ -492,7 +492,7 @@ psd_get_data(PSD_Header *head,
492} 492}
493 493
494 494
495Eina_Bool 495static Eina_Bool
496get_single_channel(PSD_Header *head, 496get_single_channel(PSD_Header *head,
497 const unsigned char *map, size_t length, size_t *position, 497 const unsigned char *map, size_t length, size_t *position,
498 unsigned char *buffer, 498 unsigned char *buffer,
@@ -552,7 +552,7 @@ get_single_channel(PSD_Header *head,
552 return EINA_TRUE; 552 return EINA_TRUE;
553} 553}
554 554
555Eina_Bool 555static Eina_Bool
556read_psd_grey(void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error) 556read_psd_grey(void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error)
557{ 557{
558 unsigned int color_mode, resource_size, misc_info; 558 unsigned int color_mode, resource_size, misc_info;
@@ -566,15 +566,19 @@ read_psd_grey(void *pixels, PSD_Header *head, const unsigned char *map, size_t l
566 CHECK_RET(read_uint(map, length, position, &color_mode)); 566 CHECK_RET(read_uint(map, length, position, &color_mode));
567 // Skip over the 'color mode data section' 567 // Skip over the 'color mode data section'
568 *position += color_mode; 568 *position += color_mode;
569 if ((*position) >= length) return EINA_FALSE;
569 570
570 CHECK_RET(read_uint(map, length, position, &resource_size)); 571 CHECK_RET(read_uint(map, length, position, &resource_size));
571 // Read the 'image resources section' 572 // Read the 'image resources section'
572 *position += resource_size; 573 *position += resource_size;
574 if ((*position) >= length) return EINA_FALSE;
573 575
574 CHECK_RET(read_uint(map, length, position, &misc_info)); 576 CHECK_RET(read_uint(map, length, position, &misc_info));
575 *position += misc_info; 577 *position += misc_info;
578 if ((*position) >= length) return EINA_FALSE;
576 579
577 CHECK_RET(read_ushort(map, length, position, &compressed)); 580 CHECK_RET(read_ushort(map, length, position, &compressed));
581 if (compressed != 0) compressed = EINA_TRUE;
578 582
579 head->channel_num = head->channels; 583 head->channel_num = head->channels;
580 // Temporary to read only one channel...some greyscale .psd files have 2. 584 // Temporary to read only one channel...some greyscale .psd files have 2.
@@ -602,7 +606,7 @@ read_psd_grey(void *pixels, PSD_Header *head, const unsigned char *map, size_t l
602} 606}
603 607
604 608
605Eina_Bool 609static Eina_Bool
606read_psd_indexed(void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error) 610read_psd_indexed(void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error)
607{ 611{
608 unsigned int color_mode, resource_size, misc_info; 612 unsigned int color_mode, resource_size, misc_info;
@@ -624,15 +628,19 @@ read_psd_indexed(void *pixels, PSD_Header *head, const unsigned char *map, size_
624 */ 628 */
625 // Skip over the 'color mode data section' 629 // Skip over the 'color mode data section'
626 *position += color_mode; 630 *position += color_mode;
631 if ((*position) >= length) return EINA_FALSE;
627 632
628 // Read the 'image resources section' 633 // Read the 'image resources section'
629 CHECK_RET(read_uint(map, length, position, &resource_size)); 634 CHECK_RET(read_uint(map, length, position, &resource_size));
630 *position += resource_size; 635 *position += resource_size;
636 if ((*position) >= length) return EINA_FALSE;
631 637
632 CHECK_RET(read_uint(map, length, position, &misc_info)); 638 CHECK_RET(read_uint(map, length, position, &misc_info));
633 *position += misc_info; 639 *position += misc_info;
640 if ((*position) >= length) return EINA_FALSE;
634 641
635 CHECK_RET(read_ushort(map, length, position, &compressed)); 642 CHECK_RET(read_ushort(map, length, position, &compressed));
643 if (compressed != 0) compressed = EINA_TRUE;
636 644
637 if (head->channels != 1 || head->depth != 8) 645 if (head->channels != 1 || head->depth != 8)
638 { 646 {
@@ -648,7 +656,7 @@ read_psd_indexed(void *pixels, PSD_Header *head, const unsigned char *map, size_
648#undef CHECK_RET 656#undef CHECK_RET
649} 657}
650 658
651Eina_Bool 659static Eina_Bool
652read_psd_rgb(void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error) 660read_psd_rgb(void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error)
653{ 661{
654 unsigned int color_mode, resource_size, misc_info; 662 unsigned int color_mode, resource_size, misc_info;
@@ -660,15 +668,19 @@ read_psd_rgb(void *pixels, PSD_Header *head, const unsigned char *map, size_t le
660 CHECK_RET(read_uint(map, length, position, &color_mode)); 668 CHECK_RET(read_uint(map, length, position, &color_mode));
661 // Skip over the 'color mode data section' 669 // Skip over the 'color mode data section'
662 *position += color_mode; 670 *position += color_mode;
671 if ((*position) >= length) return EINA_FALSE;
663 672
664 // Read the 'image resources section' 673 // Read the 'image resources section'
665 CHECK_RET(read_uint(map, length, position, &resource_size)); 674 CHECK_RET(read_uint(map, length, position, &resource_size));
666 *position += resource_size; 675 *position += resource_size;
676 if ((*position) >= length) return EINA_FALSE;
667 677
668 CHECK_RET(read_uint(map, length, position, &misc_info)); 678 CHECK_RET(read_uint(map, length, position, &misc_info));
669 *position += misc_info; 679 *position += misc_info;
680 if ((*position) >= length) return EINA_FALSE;
670 681
671 CHECK_RET(read_ushort(map, length, position, &compressed)); 682 CHECK_RET(read_ushort(map, length, position, &compressed));
683 if (compressed != 0) compressed = EINA_TRUE;
672 684
673 head->channel_num = head->channels; 685 head->channel_num = head->channels;
674 686
@@ -690,7 +702,7 @@ read_psd_rgb(void *pixels, PSD_Header *head, const unsigned char *map, size_t le
690#undef CHECK_RET 702#undef CHECK_RET
691} 703}
692 704
693Eina_Bool 705static Eina_Bool
694read_psd_cmyk(Emile_Image_Property *prop, void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error) 706read_psd_cmyk(Emile_Image_Property *prop, void *pixels, PSD_Header *head, const unsigned char *map, size_t length, size_t *position, int *error)
695{ 707{
696 unsigned int color_mode, resource_size, misc_info, size, j, data_size; 708 unsigned int color_mode, resource_size, misc_info, size, j, data_size;
@@ -707,15 +719,19 @@ read_psd_cmyk(Emile_Image_Property *prop, void *pixels, PSD_Header *head, const
707 CHECK_RET(read_uint(map, length, position, &color_mode)); 719 CHECK_RET(read_uint(map, length, position, &color_mode));
708 // Skip over the 'color mode data section' 720 // Skip over the 'color mode data section'
709 *position += color_mode; 721 *position += color_mode;
722 if ((*position) >= length) return EINA_FALSE;
710 723
711 CHECK_RET(read_uint(map, length, position, &resource_size)); 724 CHECK_RET(read_uint(map, length, position, &resource_size));
712 // Read the 'image resources section' 725 // Read the 'image resources section'
713 *position += resource_size; 726 *position += resource_size;
727 if ((*position) >= length) return EINA_FALSE;
714 728
715 CHECK_RET(read_uint(map, length, position, &misc_info)); 729 CHECK_RET(read_uint(map, length, position, &misc_info));
716 *position += misc_info; 730 *position += misc_info;
731 if ((*position) >= length) return EINA_FALSE;
717 732
718 CHECK_RET(read_ushort(map, length, position, &compressed)); 733 CHECK_RET(read_ushort(map, length, position, &compressed));
734 if (compressed != 0) compressed = EINA_TRUE;
719 735
720 switch (head->channels) 736 switch (head->channels)
721 { 737 {
diff --git a/src/modules/evas/image_savers/avif/evas_image_save_avif.c b/src/modules/evas/image_savers/avif/evas_image_save_avif.c
new file mode 100644
index 0000000000..61fefcefc7
--- /dev/null
+++ b/src/modules/evas/image_savers/avif/evas_image_save_avif.c
@@ -0,0 +1,181 @@
1#ifdef HAVE_CONFIG_H
2# include <config.h>
3#endif
4
5#include <stdio.h>
6
7#include <avif/avif.h>
8
9#include "evas_common_private.h"
10#include "evas_private.h"
11
12
13static int
14save_image_avif(RGBA_Image *im, const char *file, int quality)
15{
16 FILE *f;
17 avifRGBImage rgb;
18 avifRWData output;
19 avifImage *image;
20 avifEncoder * encoder;
21 avifPixelFormat format;
22 avifResult res;
23 size_t size;
24 int threads_count;
25 int quantizer;
26 int color;
27 int transfer;
28 int matrix;
29 int ret = 0;
30
31 if (!im || !im->image.data || !file || !*file)
32 return 0;
33
34 f = fopen(file, "wb");
35 if (!f)
36 return ret;
37
38 if (quality < 60)
39 {
40 format = AVIF_PIXEL_FORMAT_YUV420;
41#if (AVIF_VERSION < 704)
42 matrix = AVIF_NCLX_MATRIX_COEFFICIENTS_BT601;
43 color = AVIF_NCLX_COLOUR_PRIMARIES_BT601;
44#else
45 matrix = AVIF_MATRIX_COEFFICIENTS_BT601;
46 color = AVIF_COLOR_PRIMARIES_BT601;
47#endif
48 }
49 else if (quality >= 90)
50 {
51 format = AVIF_PIXEL_FORMAT_YUV444;
52#if (AVIF_VERSION < 704)
53 matrix = AVIF_NCLX_MATRIX_COEFFICIENTS_BT709;
54 color = AVIF_NCLX_COLOUR_PRIMARIES_BT709;
55#else
56 matrix = AVIF_MATRIX_COEFFICIENTS_BT709;
57 color = AVIF_COLOR_PRIMARIES_BT709;
58#endif
59 }
60 else
61 {
62 format = AVIF_PIXEL_FORMAT_YUV422;
63#if (AVIF_VERSION < 704)
64 matrix = AVIF_NCLX_MATRIX_COEFFICIENTS_BT709;
65 color = AVIF_NCLX_COLOUR_PRIMARIES_BT709;
66#else
67 matrix = AVIF_MATRIX_COEFFICIENTS_BT709;
68 color = AVIF_COLOR_PRIMARIES_BT709;
69#endif
70 }
71
72#if (AVIF_VERSION < 704)
73 transfer = AVIF_NCLX_TRANSFER_CHARACTERISTICS_SRGB;
74#else
75 transfer = AVIF_TRANSFER_CHARACTERISTICS_SRGB;
76#endif
77
78 image = avifImageCreate(im->cache_entry.w, im->cache_entry.h, 8, format);
79 if (!image)
80 goto close_f;
81
82#if (AVIF_VERSION < 704)
83 image->nclx.colourPrimaries = color;
84 image->nclx.transferCharacteristics = transfer;
85 image->nclx.matrixCoefficients = matrix;
86#else
87 image->colorPrimaries = color;
88 image->transferCharacteristics = transfer;
89 image->matrixCoefficients = matrix;
90#endif
91 image->yuvRange = AVIF_RANGE_FULL;
92
93 avifRGBImageSetDefaults(&rgb, image);
94#ifdef WORDS_BIGENDIAN
95 rgb.format = AVIF_RGB_FORMAT_ARGB;
96#else
97 rgb.format = AVIF_RGB_FORMAT_BGRA;
98#endif
99 rgb.depth = 8;
100 rgb.pixels = (uint8_t *)im->image.data;
101 rgb.rowBytes = 4 * im->cache_entry.w;
102 avifImageRGBToYUV(image, &rgb);
103
104 output.data = NULL;
105 output.size = 0;
106 encoder = avifEncoderCreate();
107 if (!encoder)
108 goto destroy_image;
109
110 threads_count = 1;
111 if (eina_cpu_count() > 2)
112 threads_count = eina_cpu_count() - 1;
113
114 quantizer = ((100 - quality) * AVIF_QUANTIZER_WORST_QUALITY) / 100;
115
116 encoder->maxThreads = threads_count;
117 encoder->minQuantizer = quantizer;
118 encoder->maxQuantizer = quantizer;
119 res = avifEncoderWrite(encoder, image, &output);
120
121 if (res != AVIF_RESULT_OK)
122 goto destroy_encoder;
123
124 size = fwrite(output.data, output.size, 1, f);
125 if (size != output.size)
126 goto destroy_encoder;
127
128 ret = 1;
129
130 destroy_encoder:
131 avifEncoderDestroy(encoder);
132 avifRWDataFree(&output);
133 destroy_image:
134 avifImageDestroy(image);
135 close_f:
136 fclose(f);
137
138 return ret;
139}
140
141static int evas_image_save_file_avif(RGBA_Image *im, const char *file, const char *key EINA_UNUSED,
142 int quality, int compress EINA_UNUSED, const char *encoding EINA_UNUSED)
143{
144 return save_image_avif(im, file, quality);
145}
146
147
148static Evas_Image_Save_Func evas_image_save_avif_func =
149{
150 evas_image_save_file_avif
151};
152
153static int
154module_open(Evas_Module *em)
155{
156 if (!em) return 0;
157 em->functions = (void *)(&evas_image_save_avif_func);
158 return 1;
159}
160
161static void
162module_close(Evas_Module *em EINA_UNUSED)
163{
164}
165
166static Evas_Module_Api evas_modapi =
167{
168 EVAS_MODULE_API_VERSION,
169 "avif",
170 "none",
171 {
172 module_open,
173 module_close
174 }
175};
176
177EVAS_MODULE_DEFINE(EVAS_MODULE_TYPE_IMAGE_SAVER, image_saver, avif);
178
179#ifndef EVAS_STATIC_BUILD_AVIF
180EVAS_EINA_MODULE_DEFINE(image_saver, avif);
181#endif
diff --git a/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c b/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c
index cefdc3304f..246e3e2a0e 100644
--- a/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c
+++ b/src/modules/evas/vg_loaders/svg/evas_vg_load_svg.c
@@ -259,8 +259,6 @@ static struct {
259 259
260_PARSE_TAG(Efl_Gfx_Fill_Rule, fill_rule, fill_rule_tags, EFL_GFX_FILL_RULE_WINDING); 260_PARSE_TAG(Efl_Gfx_Fill_Rule, fill_rule, fill_rule_tags, EFL_GFX_FILL_RULE_WINDING);
261 261
262#if 0
263// unused at the moment
264/* parse the dash pattern used during stroking a path. 262/* parse the dash pattern used during stroking a path.
265 * Value: none | <dasharray> | inherit 263 * Value: none | <dasharray> | inherit
266 * Initial: none 264 * Initial: none
@@ -269,7 +267,8 @@ _PARSE_TAG(Efl_Gfx_Fill_Rule, fill_rule, fill_rule_tags, EFL_GFX_FILL_RULE_WINDI
269static inline void 267static inline void
270_parse_dash_array(const char *str, Efl_Gfx_Dash** dash, int *length) 268_parse_dash_array(const char *str, Efl_Gfx_Dash** dash, int *length)
271{ 269{
272 double tmp[30]; 270 // It is assumed that the length of the dasharray string is 255 or less.
271 double tmp[255];
273 char *end = NULL; 272 char *end = NULL;
274 int leni, gapi, count = 0, index = 0; 273 int leni, gapi, count = 0, index = 0;
275 274
@@ -291,20 +290,21 @@ _parse_dash_array(const char *str, Efl_Gfx_Dash** dash, int *length)
291 gapi = (2 * index + 1) % count; 290 gapi = (2 * index + 1) % count;
292 (*dash)[index].length = tmp[leni]; 291 (*dash)[index].length = tmp[leni];
293 (*dash)[index].gap = tmp[gapi]; 292 (*dash)[index].gap = tmp[gapi];
293 index++;
294 } 294 }
295 } 295 }
296 else 296 else
297 { // even case 297 { // even case
298 *length = count/2; 298 *length = count/2;
299 *dash = calloc(*length, sizeof(Efl_Gfx_Dash)); 299 *dash = calloc(*length, sizeof(Efl_Gfx_Dash));
300 while (index < count) 300 while (index < *length)
301 { 301 {
302 (*dash)[index].length = tmp[2 * index]; 302 (*dash)[index].length = tmp[2 * index];
303 (*dash)[index].gap = tmp[2 * index + 1]; 303 (*dash)[index].gap = tmp[2 * index + 1];
304 index++;
304 } 305 }
305 } 306 }
306} 307}
307#endif
308 308
309static Eina_Stringshare * 309static Eina_Stringshare *
310 _id_from_url(const char *url) 310 _id_from_url(const char *url)
@@ -865,6 +865,13 @@ _handle_stroke_opacity_attr(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node* node,
865} 865}
866 866
867static void 867static void
868_handle_stroke_dasharray_attr(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node* node, const char *value)
869{
870 node->style->stroke.flags |= SVG_STROKE_FLAGS_DASH;
871 _parse_dash_array(value, &node->style->stroke.dash, &node->style->stroke.dash_count);
872}
873
874static void
868_handle_stroke_width_attr(Evas_SVG_Loader *loader, Svg_Node* node, const char *value) 875_handle_stroke_width_attr(Evas_SVG_Loader *loader, Svg_Node* node, const char *value)
869{ 876{
870 node->style->stroke.flags |= SVG_STROKE_FLAGS_WIDTH; 877 node->style->stroke.flags |= SVG_STROKE_FLAGS_WIDTH;
@@ -942,6 +949,7 @@ static const struct {
942 STYLE_DEF(stroke-linejoin, stroke_linejoin), 949 STYLE_DEF(stroke-linejoin, stroke_linejoin),
943 STYLE_DEF(stroke-linecap, stroke_linecap), 950 STYLE_DEF(stroke-linecap, stroke_linecap),
944 STYLE_DEF(stroke-opacity, stroke_opacity), 951 STYLE_DEF(stroke-opacity, stroke_opacity),
952 STYLE_DEF(stroke-dasharray, stroke_dasharray),
945 STYLE_DEF(transform, transform), 953 STYLE_DEF(transform, transform),
946 STYLE_DEF(display, display) 954 STYLE_DEF(display, display)
947}; 955};
@@ -1091,6 +1099,24 @@ _create_switch_node(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node *parent EINA_U
1091 return NULL; 1099 return NULL;
1092} 1100}
1093 1101
1102static Svg_Node *
1103_create_mask_node(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node *parent EINA_UNUSED, const char *buf EINA_UNUSED, unsigned buflen EINA_UNUSED)
1104{
1105 Svg_Node *node = _create_node(NULL, SVG_NODE_UNKNOWN);
1106
1107 node->display = EINA_FALSE;
1108 return node;
1109}
1110
1111static Svg_Node *
1112_create_clipPath_node(Evas_SVG_Loader *loader EINA_UNUSED, Svg_Node *parent EINA_UNUSED, const char *buf EINA_UNUSED, unsigned buflen EINA_UNUSED)
1113{
1114 Svg_Node *node = _create_node(NULL, SVG_NODE_UNKNOWN);
1115
1116 node->display = EINA_FALSE;
1117 return node;
1118}
1119
1094static Eina_Bool 1120static Eina_Bool
1095_attr_parse_path_node(void *data, const char *key, const char *value) 1121_attr_parse_path_node(void *data, const char *key, const char *value)
1096{ 1122{
@@ -1381,6 +1407,13 @@ _attr_parse_rect_node(void *data, const char *key, const char *value)
1381 if (rect_tags[i].sz - 1 == sz && !strncmp(rect_tags[i].tag, key, sz)) 1407 if (rect_tags[i].sz - 1 == sz && !strncmp(rect_tags[i].tag, key, sz))
1382 { 1408 {
1383 *((double*) (array + rect_tags[i].offset)) = _to_double(loader->svg_parse, value, rect_tags[i].type); 1409 *((double*) (array + rect_tags[i].offset)) = _to_double(loader->svg_parse, value, rect_tags[i].type);
1410
1411 //Case if only rx or ry is declared
1412 if (!strncmp(rect_tags[i].tag, "rx", sz)) rect->has_rx = EINA_TRUE;
1413 if (!strncmp(rect_tags[i].tag, "ry", sz)) rect->has_ry = EINA_TRUE;
1414
1415 if (!EINA_DBL_EQ(rect->rx, 0) && EINA_DBL_EQ(rect->ry, 0) && rect->has_rx && !rect->has_ry) rect->ry = rect->rx;
1416 if (!EINA_DBL_EQ(rect->ry, 0) && EINA_DBL_EQ(rect->rx, 0) && !rect->has_rx && rect->has_ry) rect->rx = rect->ry;
1384 return EINA_TRUE; 1417 return EINA_TRUE;
1385 } 1418 }
1386 1419
@@ -1397,8 +1430,6 @@ _attr_parse_rect_node(void *data, const char *key, const char *value)
1397 _parse_style_attr(loader, key, value); 1430 _parse_style_attr(loader, key, value);
1398 } 1431 }
1399 1432
1400 if (!EINA_DBL_EQ(rect->rx, 0) && EINA_DBL_EQ(rect->ry, 0)) rect->ry = rect->rx;
1401 if (!EINA_DBL_EQ(rect->ry, 0) && EINA_DBL_EQ(rect->rx, 0)) rect->rx = rect->ry;
1402 1433
1403 return EINA_TRUE; 1434 return EINA_TRUE;
1404} 1435}
@@ -1408,6 +1439,10 @@ _create_rect_node(Evas_SVG_Loader *loader, Svg_Node *parent, const char *buf, un
1408{ 1439{
1409 loader->svg_parse->node = _create_node(parent, SVG_NODE_RECT); 1440 loader->svg_parse->node = _create_node(parent, SVG_NODE_RECT);
1410 1441
1442 if (loader->svg_parse->node) {
1443 loader->svg_parse->node->node.rect.has_rx = loader->svg_parse->node->node.rect.has_ry = EINA_FALSE;
1444 }
1445
1411 eina_simple_xml_attributes_parse(buf, buflen, 1446 eina_simple_xml_attributes_parse(buf, buflen,
1412 _attr_parse_rect_node, loader); 1447 _attr_parse_rect_node, loader);
1413 return loader->svg_parse->node; 1448 return loader->svg_parse->node;
@@ -1601,6 +1636,8 @@ _copy_attribute(Svg_Node *to, Svg_Node *from)
1601 to->node.rect.h = from->node.rect.h; 1636 to->node.rect.h = from->node.rect.h;
1602 to->node.rect.rx = from->node.rect.rx; 1637 to->node.rect.rx = from->node.rect.rx;
1603 to->node.rect.ry = from->node.rect.ry; 1638 to->node.rect.ry = from->node.rect.ry;
1639 to->node.rect.has_rx = from->node.rect.has_rx;
1640 to->node.rect.has_ry = from->node.rect.has_ry;
1604 break; 1641 break;
1605 case SVG_NODE_LINE: 1642 case SVG_NODE_LINE:
1606 to->node.line.x1 = from->node.line.x1; 1643 to->node.line.x1 = from->node.line.x1;
@@ -1703,7 +1740,9 @@ static const struct {
1703 TAG_DEF(defs), 1740 TAG_DEF(defs),
1704 TAG_DEF(g), 1741 TAG_DEF(g),
1705 TAG_DEF(svg), 1742 TAG_DEF(svg),
1706 TAG_DEF(switch) 1743 TAG_DEF(switch),
1744 TAG_DEF(mask),
1745 TAG_DEF(clipPath)
1707}; 1746};
1708 1747
1709#define FIND_FACTORY(Short_Name, Tags_Array) \ 1748#define FIND_FACTORY(Short_Name, Tags_Array) \
@@ -2112,9 +2151,18 @@ _find_gradient_factory(const char *name)
2112 return NULL; 2151 return NULL;
2113} 2152}
2114 2153
2154static Svg_Node*
2155_get_parent_node_from_loader(Evas_SVG_Loader *loader)
2156{
2157 if (eina_array_count(loader->stack) > 0)
2158 return eina_array_data_get(loader->stack, eina_array_count(loader->stack) - 1);
2159 else
2160 return loader->doc;
2161}
2162
2115static void 2163static void
2116_evas_svg_loader_xml_open_parser(Evas_SVG_Loader *loader, 2164_evas_svg_loader_xml_open_parser(Evas_SVG_Loader *loader,
2117 const char *content, unsigned int length) 2165 const char *content, unsigned int length, Eina_Bool empty)
2118{ 2166{
2119 const char *attrs = NULL; 2167 const char *attrs = NULL;
2120 int attrs_length = 0; 2168 int attrs_length = 0;
@@ -2157,20 +2205,21 @@ _evas_svg_loader_xml_open_parser(Evas_SVG_Loader *loader,
2157 } 2205 }
2158 else 2206 else
2159 { 2207 {
2160 parent = eina_array_data_get(loader->stack, eina_array_count(loader->stack) - 1); 2208 parent = _get_parent_node_from_loader(loader);
2161 node = method(loader, parent, attrs, attrs_length); 2209 node = method(loader, parent, attrs, attrs_length);
2162 } 2210 }
2163 eina_array_push(loader->stack, node);
2164 2211
2165 if (node->type == SVG_NODE_DEFS) 2212 if (node->type == SVG_NODE_DEFS)
2166 { 2213 {
2167 loader->doc->node.doc.defs = node; 2214 loader->doc->node.doc.defs = node;
2168 loader->def = node; 2215 loader->def = node;
2169 } 2216 if (!empty) eina_array_push(loader->stack, node);
2217 }
2218 else eina_array_push(loader->stack, node);
2170 } 2219 }
2171 else if ((method = _find_graphics_factory(tag_name))) 2220 else if ((method = _find_graphics_factory(tag_name)))
2172 { 2221 {
2173 parent = eina_array_data_get(loader->stack, eina_array_count(loader->stack) - 1); 2222 parent = _get_parent_node_from_loader(loader);
2174 node = method(loader, parent, attrs, attrs_length); 2223 node = method(loader, parent, attrs, attrs_length);
2175 } 2224 }
2176 else if ((gradient_method = _find_gradient_factory(tag_name))) 2225 else if ((gradient_method = _find_gradient_factory(tag_name)))
@@ -2218,7 +2267,9 @@ static const struct {
2218} pop_array[] = { 2267} pop_array[] = {
2219 POP_TAG(g), 2268 POP_TAG(g),
2220 POP_TAG(svg), 2269 POP_TAG(svg),
2221 POP_TAG(defs) 2270 POP_TAG(defs),
2271 POP_TAG(mask),
2272 POP_TAG(clipPath)
2222}; 2273};
2223 2274
2224static void 2275static void
@@ -2250,10 +2301,10 @@ _evas_svg_loader_parser(void *data, Eina_Simple_XML_Type type,
2250 switch (type) 2301 switch (type)
2251 { 2302 {
2252 case EINA_SIMPLE_XML_OPEN: 2303 case EINA_SIMPLE_XML_OPEN:
2253 _evas_svg_loader_xml_open_parser(loader, content, length); 2304 _evas_svg_loader_xml_open_parser(loader, content, length, EINA_FALSE);
2254 break; 2305 break;
2255 case EINA_SIMPLE_XML_OPEN_EMPTY: 2306 case EINA_SIMPLE_XML_OPEN_EMPTY:
2256 _evas_svg_loader_xml_open_parser(loader, content, length); 2307 _evas_svg_loader_xml_open_parser(loader, content, length, EINA_TRUE);
2257 break; 2308 break;
2258 case EINA_SIMPLE_XML_CLOSE: 2309 case EINA_SIMPLE_XML_CLOSE:
2259 _evas_svg_loader_xml_close_parser(loader, content, length); 2310 _evas_svg_loader_xml_close_parser(loader, content, length);
@@ -2324,6 +2375,22 @@ _inherit_style(Svg_Style_Property *child, Svg_Style_Property *parent)
2324 { 2375 {
2325 child->stroke.join = parent->stroke.join; 2376 child->stroke.join = parent->stroke.join;
2326 } 2377 }
2378 if (!(child->stroke.flags & SVG_STROKE_FLAGS_DASH))
2379 {
2380 int i = 0;
2381 int count = parent->stroke.dash_count;
2382 if (count > 0)
2383 {
2384 if (child->stroke.dash) free(child->stroke.dash);
2385 child->stroke.dash = calloc(count, sizeof(Efl_Gfx_Dash));
2386 child->stroke.dash_count = count;
2387 for (i = 0; i < count; i++)
2388 {
2389 child->stroke.dash[i].length = parent->stroke.dash[i].length;
2390 child->stroke.dash[i].gap = parent->stroke.dash[i].gap;
2391 }
2392 }
2393 }
2327} 2394}
2328 2395
2329void 2396void
@@ -2445,14 +2512,11 @@ evas_vg_load_file_open_svg(Eina_File *file,
2445 defs = loader.doc->node.doc.defs; 2512 defs = loader.doc->node.doc.defs;
2446 if (defs) 2513 if (defs)
2447 _update_gradient(loader.doc, defs->node.defs.gradients); 2514 _update_gradient(loader.doc, defs->node.defs.gradients);
2448 else 2515 if (loader.gradients)
2449 { 2516 {
2450 if (loader.gradients) 2517 Eina_List* gradient_list = loader.gradients;
2451 { 2518 _update_gradient(loader.doc, gradient_list);
2452 Eina_List* gradient_list = loader.gradients; 2519 eina_list_free(gradient_list);
2453 _update_gradient(loader.doc, gradient_list);
2454 eina_list_free(gradient_list);
2455 }
2456 } 2520 }
2457 2521
2458 *error = EVAS_LOAD_ERROR_NONE; 2522 *error = EVAS_LOAD_ERROR_NONE;