forked from enlightenment/efl
Evas filters: Add support for Evas_Object_Image
This adds filter support to Image objects as well. The exact same filters can run on Text and on Images (provided some colorspace limitations are respected). This basically adds: - Support for RGBA input buffer - Eo entry points for Image filter support - Implement basic filter support in Evas_Image
This commit is contained in:
parent
de4969ccb2
commit
59cf013db9
|
@ -1023,6 +1023,46 @@ class Evas_Image (Evas_Object)
|
||||||
Evas_3D_Scene *scene; /*@ 3D scene on an image object. */
|
Evas_3D_Scene *scene; /*@ 3D scene on an image object. */
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
filter_program {
|
||||||
|
set {
|
||||||
|
/*@ Set an Evas filter program on this Text Object.
|
||||||
|
|
||||||
|
If the program fails to compile (syntax error, invalid
|
||||||
|
buffer name, etc...), the standard text effects will be
|
||||||
|
applied instead (SHADOW, etc...). switch back to the
|
||||||
|
standard text effects.
|
||||||
|
|
||||||
|
@since 1.9
|
||||||
|
@note EXPERIMENTAL FEATURE. This is an unstable API,
|
||||||
|
please use only for testing purposes.
|
||||||
|
@see @ref evasfiltersref "Evas filters reference"
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
values {
|
||||||
|
const char* program; /*@ The program code, as defined
|
||||||
|
by the @ref evasfiltersref "Evas filters script language".
|
||||||
|
Pass NULL to remove the former program and switch back
|
||||||
|
to the standard text effect
|
||||||
|
|
||||||
|
@since 1.9
|
||||||
|
@note EXPERIMENTAL FEATURE. This is an unstable API,
|
||||||
|
please use only for testing purposes.
|
||||||
|
@see @ref evasfiltersref "Evas filters reference"
|
||||||
|
*/
|
||||||
|
}
|
||||||
|
}
|
||||||
|
filter_source {
|
||||||
|
set {
|
||||||
|
/*@ Bind an object to use as a mask or texture with Evas Filters.
|
||||||
|
|
||||||
|
This will create automatically a new RGBA buffer containing
|
||||||
|
the source object's pixels (as it is rendered). */
|
||||||
|
}
|
||||||
|
values {
|
||||||
|
const char* name; /*@ Object name as used in the program code */
|
||||||
|
Eo* eobj; /*@ Eo object to use through proxy rendering */
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
methods {
|
methods {
|
||||||
preload_begin {
|
preload_begin {
|
||||||
|
|
|
@ -18,6 +18,7 @@
|
||||||
#include "../common/evas_convert_color.h"
|
#include "../common/evas_convert_color.h"
|
||||||
#include "../common/evas_convert_colorspace.h"
|
#include "../common/evas_convert_colorspace.h"
|
||||||
#include "../common/evas_convert_yuv.h"
|
#include "../common/evas_convert_yuv.h"
|
||||||
|
#include "evas_filter.h"
|
||||||
|
|
||||||
#include <Eo.h>
|
#include <Eo.h>
|
||||||
|
|
||||||
|
@ -91,6 +92,16 @@ struct _Evas_Object_Image_State
|
||||||
|
|
||||||
Evas_Colorspace cspace;
|
Evas_Colorspace cspace;
|
||||||
|
|
||||||
|
struct {
|
||||||
|
Eina_Stringshare *code;
|
||||||
|
Evas_Filter_Program *chain;
|
||||||
|
Eina_Hash *sources; // Evas_Filter_Proxy_Binding
|
||||||
|
int sources_count;
|
||||||
|
void *output;
|
||||||
|
Eina_Bool changed : 1;
|
||||||
|
Eina_Bool invalid : 1; // Code parse failed
|
||||||
|
} filter;
|
||||||
|
|
||||||
Eina_Bool smooth_scale : 1;
|
Eina_Bool smooth_scale : 1;
|
||||||
Eina_Bool has_alpha :1;
|
Eina_Bool has_alpha :1;
|
||||||
Eina_Bool opaque_valid : 1;
|
Eina_Bool opaque_valid : 1;
|
||||||
|
@ -233,6 +244,11 @@ static const Evas_Object_Image_State default_state = {
|
||||||
0, //frame
|
0, //frame
|
||||||
EVAS_TEXTURE_REPEAT,
|
EVAS_TEXTURE_REPEAT,
|
||||||
EVAS_COLORSPACE_ARGB8888,
|
EVAS_COLORSPACE_ARGB8888,
|
||||||
|
|
||||||
|
// filter
|
||||||
|
{ NULL, NULL, NULL, 0, NULL, EINA_FALSE, EINA_FALSE },
|
||||||
|
|
||||||
|
// flags
|
||||||
EINA_TRUE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE
|
EINA_TRUE, EINA_FALSE, EINA_FALSE, EINA_FALSE, EINA_FALSE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
@ -3103,6 +3119,14 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
Evas_Filter_Context *filter = NULL;
|
||||||
|
void * const surface_save = surface;
|
||||||
|
void * const context_save = context;
|
||||||
|
const Eina_Bool do_async_save = do_async;
|
||||||
|
int l = 0, r = 0, t = 0, b = 0;
|
||||||
|
Eina_Bool clear = EINA_FALSE;
|
||||||
|
int W, H, offx, offy;
|
||||||
|
|
||||||
obj->layer->evas->engine.func->image_scale_hint_set(output,
|
obj->layer->evas->engine.func->image_scale_hint_set(output,
|
||||||
pixels,
|
pixels,
|
||||||
o->scale_hint);
|
o->scale_hint);
|
||||||
|
@ -3118,6 +3142,69 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
|
||||||
if (idh < 1) idh = 1;
|
if (idh < 1) idh = 1;
|
||||||
if (idx > 0) idx -= idw;
|
if (idx > 0) idx -= idw;
|
||||||
if (idy > 0) idy -= idh;
|
if (idy > 0) idy -= idh;
|
||||||
|
|
||||||
|
offx = obj->cur->geometry.x + x;
|
||||||
|
offy = obj->cur->geometry.y + y;
|
||||||
|
|
||||||
|
/* Evas Filters on Image Object. Yet another experimental piece of code.
|
||||||
|
* Replace current context, offset and surface by filter-made targets.
|
||||||
|
*/
|
||||||
|
if (!o->cur->filter.invalid && o->cur->filter.code)
|
||||||
|
{
|
||||||
|
Evas_Filter_Program *pgm = o->cur->filter.chain;;
|
||||||
|
Eina_Bool ok;
|
||||||
|
|
||||||
|
evas_filter_program_padding_get(pgm, &l, &r, &t, &b);
|
||||||
|
W = obj->cur->geometry.w + l + r;
|
||||||
|
H = obj->cur->geometry.h + t + b;
|
||||||
|
|
||||||
|
if (!pgm)
|
||||||
|
{
|
||||||
|
pgm = evas_filter_program_new("Image", EINA_FALSE);
|
||||||
|
evas_filter_program_source_set_all(pgm, o->cur->filter.sources);
|
||||||
|
ok = evas_filter_program_parse(pgm, o->cur->filter.code);
|
||||||
|
if (!ok) goto state_write;
|
||||||
|
}
|
||||||
|
|
||||||
|
filter = evas_filter_context_new(obj->layer->evas, do_async);
|
||||||
|
ok = evas_filter_context_program_use(filter, pgm);
|
||||||
|
if (!ok) goto state_write;
|
||||||
|
|
||||||
|
evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
|
||||||
|
ok = evas_filter_context_buffers_allocate_all(filter, W, H);
|
||||||
|
if (!ok) goto state_write;
|
||||||
|
|
||||||
|
if (obj->layer->evas->engine.func->gl_surface_read_pixels)
|
||||||
|
{
|
||||||
|
evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
|
||||||
|
surface = obj->layer->evas->engine.func->image_map_surface_new(output, W, H, EINA_TRUE);
|
||||||
|
}
|
||||||
|
|
||||||
|
state_write:
|
||||||
|
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||||
|
{
|
||||||
|
if (ok)
|
||||||
|
{
|
||||||
|
offx = l;
|
||||||
|
offy = t;
|
||||||
|
context = obj->layer->evas->engine.func->context_new(output);
|
||||||
|
clear = EINA_TRUE;
|
||||||
|
do_async = EINA_FALSE;
|
||||||
|
state_write->filter.chain = pgm;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ERR("Failed to apply this filter");
|
||||||
|
evas_filter_context_destroy(filter);
|
||||||
|
evas_filter_program_del(pgm);
|
||||||
|
state_write->filter.invalid = EINA_TRUE;
|
||||||
|
state_write->filter.chain = NULL;
|
||||||
|
filter = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
|
||||||
|
}
|
||||||
|
|
||||||
while ((int)idx < obj->cur->geometry.w)
|
while ((int)idx < obj->cur->geometry.w)
|
||||||
{
|
{
|
||||||
Evas_Coord ydy;
|
Evas_Coord ydy;
|
||||||
|
@ -3133,6 +3220,16 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
iw = ((int)(idx + idw)) - ix;
|
iw = ((int)(idx + idw)) - ix;
|
||||||
|
|
||||||
|
if (clear)
|
||||||
|
{
|
||||||
|
obj->layer->evas->engine.func->context_color_set(output, context, 0, 0, 0, 0);
|
||||||
|
obj->layer->evas->engine.func->context_render_op_set(output, context, EVAS_RENDER_COPY);
|
||||||
|
obj->layer->evas->engine.func->rectangle_draw(output, context, surface, 0, 0, W, H, EINA_FALSE);
|
||||||
|
obj->layer->evas->engine.func->context_color_set(output, context, 255, 255, 255, 255);
|
||||||
|
obj->layer->evas->engine.func->context_render_op_set(output, context, EVAS_RENDER_BLEND);
|
||||||
|
}
|
||||||
|
|
||||||
while ((int)idy < obj->cur->geometry.h)
|
while ((int)idy < obj->cur->geometry.h)
|
||||||
{
|
{
|
||||||
int dobreak_h = 0;
|
int dobreak_h = 0;
|
||||||
|
@ -3156,8 +3253,8 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
|
||||||
(obj, output, context, surface, pixels,
|
(obj, output, context, surface, pixels,
|
||||||
0, 0,
|
0, 0,
|
||||||
imagew, imageh,
|
imagew, imageh,
|
||||||
obj->cur->geometry.x + ix + x,
|
offx + ix,
|
||||||
obj->cur->geometry.y + iy + y,
|
offy + iy,
|
||||||
iw, ih,
|
iw, ih,
|
||||||
o->cur->smooth_scale,
|
o->cur->smooth_scale,
|
||||||
do_async);
|
do_async);
|
||||||
|
@ -3168,8 +3265,8 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
|
||||||
int bl, br, bt, bb, bsl, bsr, bst, bsb;
|
int bl, br, bt, bb, bsl, bsr, bst, bsb;
|
||||||
int imw, imh, ox, oy;
|
int imw, imh, ox, oy;
|
||||||
|
|
||||||
ox = obj->cur->geometry.x + ix + x;
|
ox = offx + ix;
|
||||||
oy = obj->cur->geometry.y + iy + y;
|
oy = offy + iy;
|
||||||
imw = imagew;
|
imw = imagew;
|
||||||
imh = imageh;
|
imh = imageh;
|
||||||
bl = o->cur->border.l;
|
bl = o->cur->border.l;
|
||||||
|
@ -3327,6 +3424,24 @@ evas_object_image_render(Evas_Object *eo_obj, Evas_Object_Protected_Data *obj, v
|
||||||
idy = ydy;
|
idy = ydy;
|
||||||
if (dobreak_w) break;
|
if (dobreak_w) break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Evas filters wrap-up */
|
||||||
|
if (filter)
|
||||||
|
{
|
||||||
|
//void *outbuf = evas_filter_buffer_backing_steal(filter, EVAS_FILTER_BUFFER_OUTPUT_ID);
|
||||||
|
//EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||||
|
//state_write->filter.output = outbuf;
|
||||||
|
//EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
|
||||||
|
|
||||||
|
evas_filter_image_draw(filter, context, EVAS_FILTER_BUFFER_INPUT_ID, surface, do_async_save);
|
||||||
|
obj->layer->evas->engine.func->context_free(output, context);
|
||||||
|
|
||||||
|
evas_filter_target_set(filter, context_save, surface_save, obj->cur->geometry.x + x, obj->cur->geometry.y + y);
|
||||||
|
evas_filter_context_autodestroy(filter);
|
||||||
|
evas_filter_run(filter);
|
||||||
|
|
||||||
|
obj->layer->evas->engine.func->image_map_surface_free(output, surface);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -4477,6 +4592,176 @@ _evas_object_image_video_overlay_do(Evas_Object *eo_obj)
|
||||||
o->delayed.video_hide = EINA_FALSE;
|
o->delayed.video_hide = EINA_FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Evas Filters functions. Similar to Evas_Text. */
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_evas_image_filter_program_set(Eo *eo_obj, Evas_Image_Data *o, const char *arg)
|
||||||
|
{
|
||||||
|
Evas_Object_Protected_Data *obj;
|
||||||
|
Evas_Filter_Program *pgm = NULL;
|
||||||
|
|
||||||
|
if (!o) return;
|
||||||
|
if (o->cur->filter.code == arg) return;
|
||||||
|
if (o->cur->filter.code && arg && !strcmp(arg, o->cur->filter.code)) return;
|
||||||
|
|
||||||
|
// Parse filter program
|
||||||
|
evas_filter_program_del(o->cur->filter.chain);
|
||||||
|
if (arg)
|
||||||
|
{
|
||||||
|
pgm = evas_filter_program_new("Evas_Text: Filter Program", EINA_FALSE);
|
||||||
|
evas_filter_program_source_set_all(pgm, o->cur->filter.sources);
|
||||||
|
if (!evas_filter_program_parse(pgm, arg))
|
||||||
|
{
|
||||||
|
ERR("Parsing failed!");
|
||||||
|
evas_filter_program_del(pgm);
|
||||||
|
pgm = NULL;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||||
|
{
|
||||||
|
state_write->filter.chain = pgm;
|
||||||
|
state_write->filter.changed = EINA_TRUE;
|
||||||
|
state_write->filter.invalid = (pgm == NULL);
|
||||||
|
eina_stringshare_replace(&state_write->filter.code, arg);
|
||||||
|
}
|
||||||
|
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
|
||||||
|
|
||||||
|
// Update object
|
||||||
|
obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
|
||||||
|
o->changed = EINA_TRUE;
|
||||||
|
o->written = EINA_FALSE;
|
||||||
|
evas_object_change(eo_obj, obj);
|
||||||
|
evas_object_clip_dirty(eo_obj, obj);
|
||||||
|
evas_object_coords_recalc(eo_obj, obj);
|
||||||
|
evas_object_inform_call_resize(eo_obj);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_filter_source_hash_free_cb(void *data)
|
||||||
|
{
|
||||||
|
Evas_Filter_Proxy_Binding *pb = data;
|
||||||
|
Evas_Object_Protected_Data *proxy, *source;
|
||||||
|
Evas_Image_Data *o;
|
||||||
|
|
||||||
|
proxy = eo_data_scope_get(pb->eo_proxy, EVAS_OBJ_CLASS);
|
||||||
|
source = eo_data_scope_get(pb->eo_source, EVAS_OBJ_CLASS);
|
||||||
|
|
||||||
|
if (source)
|
||||||
|
{
|
||||||
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy,
|
||||||
|
Evas_Object_Proxy_Data, source_write)
|
||||||
|
source_write->proxies = eina_list_remove(source_write->proxies, pb->eo_proxy);
|
||||||
|
EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
|
||||||
|
}
|
||||||
|
|
||||||
|
o = eo_data_scope_get(pb->eo_proxy, MY_CLASS);
|
||||||
|
|
||||||
|
if (o && proxy)
|
||||||
|
{
|
||||||
|
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||||
|
state_write->filter.sources_count--;
|
||||||
|
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write)
|
||||||
|
|
||||||
|
if (!o->cur->filter.sources_count)
|
||||||
|
{
|
||||||
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, proxy->proxy,
|
||||||
|
Evas_Object_Proxy_Data, proxy_write)
|
||||||
|
proxy_write->is_proxy = EINA_FALSE;
|
||||||
|
EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, proxy_write)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
eina_stringshare_del(pb->name);
|
||||||
|
free(pb);
|
||||||
|
}
|
||||||
|
|
||||||
|
EOLIAN static void
|
||||||
|
_evas_image_filter_source_set(Eo *eo_obj, Evas_Image_Data *o, const char *name,
|
||||||
|
Evas_Object *eo_source)
|
||||||
|
{
|
||||||
|
|
||||||
|
Evas_Object_Protected_Data *obj;
|
||||||
|
Evas_Filter_Program *pgm = o->cur->filter.chain;
|
||||||
|
Evas_Filter_Proxy_Binding *pb, *pb_old = NULL;
|
||||||
|
Evas_Object_Protected_Data *source = NULL;
|
||||||
|
Eina_Hash *sources = o->cur->filter.sources;
|
||||||
|
int sources_count = o->cur->filter.sources_count;
|
||||||
|
|
||||||
|
obj = eo_data_scope_get(eo_obj, EVAS_OBJ_CLASS);
|
||||||
|
if (eo_source) source = eo_data_scope_get(eo_source, EVAS_OBJ_CLASS);
|
||||||
|
|
||||||
|
if (!name)
|
||||||
|
{
|
||||||
|
if (!eo_source || !o->cur->filter.sources) return;
|
||||||
|
if (eina_hash_del_by_data(o->cur->filter.sources, eo_source))
|
||||||
|
goto update;
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!sources)
|
||||||
|
{
|
||||||
|
if (!source) return;
|
||||||
|
sources = eina_hash_string_small_new
|
||||||
|
(EINA_FREE_CB(_filter_source_hash_free_cb));
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
pb_old = eina_hash_find(sources, name);
|
||||||
|
if (pb_old)
|
||||||
|
{
|
||||||
|
if (pb_old->eo_source == eo_source) goto update;
|
||||||
|
eina_hash_del(sources, name, pb_old);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!source)
|
||||||
|
{
|
||||||
|
pb_old = eina_hash_find(sources, name);
|
||||||
|
if (!pb_old) return;
|
||||||
|
eina_hash_del_by_key(sources, name);
|
||||||
|
goto update;
|
||||||
|
}
|
||||||
|
|
||||||
|
pb = calloc(1, sizeof(*pb));
|
||||||
|
pb->eo_proxy = eo_obj;
|
||||||
|
pb->eo_source = eo_source;
|
||||||
|
pb->name = eina_stringshare_add(name);
|
||||||
|
|
||||||
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy,
|
||||||
|
Evas_Object_Proxy_Data, source_write)
|
||||||
|
if (!eina_list_data_find(source_write->proxies, eo_obj))
|
||||||
|
source_write->proxies = eina_list_append(source_write->proxies, eo_obj);
|
||||||
|
EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
|
||||||
|
|
||||||
|
EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, obj->proxy,
|
||||||
|
Evas_Object_Proxy_Data, proxy_write)
|
||||||
|
proxy_write->is_proxy = EINA_TRUE;
|
||||||
|
EINA_COW_WRITE_END(evas_object_proxy_cow, obj->proxy, proxy_write)
|
||||||
|
|
||||||
|
eina_hash_add(sources, pb->name, pb);
|
||||||
|
sources_count++;
|
||||||
|
|
||||||
|
evas_filter_program_source_set_all(pgm, sources);
|
||||||
|
|
||||||
|
update:
|
||||||
|
EINA_COW_IMAGE_STATE_WRITE_BEGIN(o, state_write)
|
||||||
|
{
|
||||||
|
state_write->filter.changed = EINA_TRUE;
|
||||||
|
state_write->filter.invalid = EINA_FALSE;
|
||||||
|
state_write->filter.sources = sources;
|
||||||
|
state_write->filter.sources_count = sources_count;
|
||||||
|
}
|
||||||
|
EINA_COW_IMAGE_STATE_WRITE_END(o, state_write);
|
||||||
|
|
||||||
|
// Update object
|
||||||
|
o->changed = 1;
|
||||||
|
evas_object_change(eo_obj, obj);
|
||||||
|
evas_object_clip_dirty(eo_obj, obj);
|
||||||
|
evas_object_coords_recalc(eo_obj, obj);
|
||||||
|
evas_object_inform_call_resize(eo_obj);
|
||||||
|
}
|
||||||
|
|
||||||
/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
|
/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
|
||||||
|
|
||||||
#include "canvas/evas_image.eo.c"
|
#include "canvas/evas_image.eo.c"
|
||||||
|
|
|
@ -1740,7 +1740,7 @@ evas_object_text_render(Evas_Object *eo_obj,
|
||||||
if (!o->cur.filter.chain)
|
if (!o->cur.filter.chain)
|
||||||
{
|
{
|
||||||
Evas_Filter_Program *pgm;
|
Evas_Filter_Program *pgm;
|
||||||
pgm = evas_filter_program_new("Evas_Text");
|
pgm = evas_filter_program_new("Evas_Text", EINA_TRUE);
|
||||||
evas_filter_program_source_set_all(pgm, o->cur.filter.sources);
|
evas_filter_program_source_set_all(pgm, o->cur.filter.sources);
|
||||||
if (!evas_filter_program_parse(pgm, o->cur.filter.code))
|
if (!evas_filter_program_parse(pgm, o->cur.filter.code))
|
||||||
{
|
{
|
||||||
|
@ -2315,7 +2315,7 @@ _evas_text_filter_program_set(Eo *eo_obj, Evas_Text_Data *o, const char *arg)
|
||||||
evas_filter_program_del(o->cur.filter.chain);
|
evas_filter_program_del(o->cur.filter.chain);
|
||||||
if (arg)
|
if (arg)
|
||||||
{
|
{
|
||||||
pgm = evas_filter_program_new("Evas_Text: Filter Program");
|
pgm = evas_filter_program_new("Evas_Text: Filter Program", EINA_TRUE);
|
||||||
evas_filter_program_source_set_all(pgm, o->cur.filter.sources);
|
evas_filter_program_source_set_all(pgm, o->cur.filter.sources);
|
||||||
if (!evas_filter_program_parse(pgm, arg))
|
if (!evas_filter_program_parse(pgm, arg))
|
||||||
{
|
{
|
||||||
|
|
|
@ -1753,6 +1753,64 @@ evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/* Image draw: glReadPixels or just use SW buffer */
|
||||||
|
Eina_Bool
|
||||||
|
evas_filter_image_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid,
|
||||||
|
void *image, Eina_Bool do_async)
|
||||||
|
{
|
||||||
|
int w = 0, h = 0;
|
||||||
|
|
||||||
|
ENFN->image_size_get(ENDT, image, &w, &h);
|
||||||
|
if (!w || !h) return EINA_FALSE;
|
||||||
|
|
||||||
|
if (!ctx->gl_engine)
|
||||||
|
{
|
||||||
|
Eina_Bool async_unref;
|
||||||
|
int dw = 0, dh = 0;
|
||||||
|
|
||||||
|
// Copy the image into our input buffer. We could optimize by reusing the buffer.
|
||||||
|
|
||||||
|
void *surface = evas_filter_buffer_backing_get(ctx, bufid);
|
||||||
|
if (!surface) return EINA_FALSE;
|
||||||
|
|
||||||
|
ENFN->image_size_get(ENDT, image, &dw, &dh);
|
||||||
|
if (!dw || !dh) return EINA_FALSE;
|
||||||
|
|
||||||
|
if (w != dw || h != dh)
|
||||||
|
WRN("Target surface size differs from the image to draw");
|
||||||
|
|
||||||
|
async_unref = ENFN->image_draw(ENDT, draw_context, surface, image,
|
||||||
|
0, 0, w, h,
|
||||||
|
0, 0, dw, dh,
|
||||||
|
EINA_TRUE, do_async);
|
||||||
|
if (do_async && async_unref)
|
||||||
|
{
|
||||||
|
#ifdef EVAS_CSERVE2
|
||||||
|
if (evas_cserve2_use_get())
|
||||||
|
evas_cache2_image_ref((Image_Entry *)image);
|
||||||
|
else
|
||||||
|
#endif
|
||||||
|
evas_cache_image_ref((Image_Entry *)image);
|
||||||
|
|
||||||
|
evas_unref_queue_image_put(ctx->evas, image);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
Evas_Filter_Buffer *fb;
|
||||||
|
|
||||||
|
fb = _filter_buffer_get(ctx, bufid);
|
||||||
|
_filter_buffer_backing_free(fb);
|
||||||
|
fb->glimage = image;
|
||||||
|
fb->allocated_gl = EINA_FALSE;
|
||||||
|
_filter_buffer_glimage_pixels_read(fb);
|
||||||
|
fb->glimage = NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/* Clip full input rect (0, 0, sw, sh) to target (dx, dy, dw, dh)
|
/* Clip full input rect (0, 0, sw, sh) to target (dx, dy, dw, dh)
|
||||||
* and get source's clipped sx, sy as well as destination x, y, cols and rows */
|
* and get source's clipped sx, sy as well as destination x, y, cols and rows */
|
||||||
void
|
void
|
||||||
|
|
|
@ -2094,14 +2094,14 @@ evas_filter_program_padding_get(Evas_Filter_Program *pgm,
|
||||||
/** Create an empty filter program for style parsing */
|
/** Create an empty filter program for style parsing */
|
||||||
|
|
||||||
EAPI Evas_Filter_Program *
|
EAPI Evas_Filter_Program *
|
||||||
evas_filter_program_new(const char *name)
|
evas_filter_program_new(const char *name, Eina_Bool input_alpha)
|
||||||
{
|
{
|
||||||
Evas_Filter_Program *pgm;
|
Evas_Filter_Program *pgm;
|
||||||
|
|
||||||
pgm = calloc(1, sizeof(Evas_Filter_Program));
|
pgm = calloc(1, sizeof(Evas_Filter_Program));
|
||||||
if (!pgm) return NULL;
|
if (!pgm) return NULL;
|
||||||
pgm->name = eina_stringshare_add(name);
|
pgm->name = eina_stringshare_add(name);
|
||||||
_buffer_add(pgm, "input", EINA_TRUE, NULL);
|
_buffer_add(pgm, "input", input_alpha, NULL);
|
||||||
_buffer_add(pgm, "output", EINA_FALSE, NULL);
|
_buffer_add(pgm, "output", EINA_FALSE, NULL);
|
||||||
|
|
||||||
return pgm;
|
return pgm;
|
||||||
|
|
|
@ -92,7 +92,7 @@ enum _Evas_Filter_Transform_Flags
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Parser stuff (high level API) */
|
/* Parser stuff (high level API) */
|
||||||
EAPI Evas_Filter_Program *evas_filter_program_new(const char *name);
|
EAPI Evas_Filter_Program *evas_filter_program_new(const char *name, Eina_Bool input_alpha);
|
||||||
EAPI Eina_Bool evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str);
|
EAPI Eina_Bool evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str);
|
||||||
EAPI void evas_filter_program_del(Evas_Filter_Program *pgm);
|
EAPI void evas_filter_program_del(Evas_Filter_Program *pgm);
|
||||||
Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm);
|
Eina_Bool evas_filter_context_program_use(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm);
|
||||||
|
@ -116,6 +116,7 @@ Eina_Bool evas_filter_buffer_backing_release(Evas_Filter_Context
|
||||||
Eina_Bool evas_filter_run(Evas_Filter_Context *ctx);
|
Eina_Bool evas_filter_run(Evas_Filter_Context *ctx);
|
||||||
|
|
||||||
Eina_Bool evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, Evas_Font_Set *font, int x, int y, Evas_Text_Props *text_props, Eina_Bool do_async);
|
Eina_Bool evas_filter_font_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, Evas_Font_Set *font, int x, int y, Evas_Text_Props *text_props, Eina_Bool do_async);
|
||||||
|
Eina_Bool evas_filter_image_draw(Evas_Filter_Context *ctx, void *draw_context, int bufid, void *image, Eina_Bool do_async);
|
||||||
Eina_Bool evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, void *surface, int x, int y);
|
Eina_Bool evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, void *surface, int x, int y);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -71,7 +71,7 @@ START_TEST(evas_filter_parser)
|
||||||
Evas_Filter_Program *pgm;
|
Evas_Filter_Program *pgm;
|
||||||
|
|
||||||
#define CHECK_FILTER(_a, _v) do { \
|
#define CHECK_FILTER(_a, _v) do { \
|
||||||
pgm = evas_filter_program_new("evas_suite"); \
|
pgm = evas_filter_program_new("evas_suite", EINA_TRUE); \
|
||||||
fail_if(evas_filter_program_parse(pgm, _a) != _v); \
|
fail_if(evas_filter_program_parse(pgm, _a) != _v); \
|
||||||
evas_filter_program_del(pgm); \
|
evas_filter_program_del(pgm); \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
Loading…
Reference in New Issue