evas_object_color_set(o, 255, 255, 255, 255);
evas_object_show(o);
- eo_do(o, evas_obj_text_filter_program_set(filter));
+ eo_do(o, efl_gfx_filter_program_set(filter));
ecore_evas_manual_render(wpd.ee);
evas_object_geometry_get(o, NULL, NULL, &w, &h);
lib/efl/interfaces/efl_gfx_gradient_base.eo \
lib/efl/interfaces/efl_gfx_gradient_linear.eo \
lib/efl/interfaces/efl_gfx_gradient_radial.eo \
- lib/efl/interfaces/efl_model_base.eo
+ lib/efl/interfaces/efl_gfx_filter.eo \
+ lib/efl/interfaces/efl_model_base.eo \
+ $(NULL)
efl_eolian_files_h = $(efl_eolian_files:%.eo=%.eo.h)
efl_eolian_files_c = $(efl_eolian_files:%.eo=%.eo.c)
lib/evas/canvas/efl_vg_root_node.eo \
lib/evas/canvas/efl_vg_gradient.eo \
lib/evas/canvas/efl_vg_gradient_radial.eo \
- lib/evas/canvas/efl_vg_gradient_linear.eo
+ lib/evas/canvas/efl_vg_gradient_linear.eo \
+ lib/evas/canvas/evas_filter.eo \
+ $(NULL)
evas_eolian_type_files = \
lib/evas/canvas/evas_types.eot
### Evas filters
-lib_evas_libevas_la_SOURCES += lib/evas/filters/evas_filter.c \
+lib_evas_libevas_la_SOURCES += \
+lib/evas/canvas/evas_filter_mixin.c \
+lib/evas/filters/evas_filter.c \
lib/evas/filters/evas_filter_blend.c \
lib/evas/filters/evas_filter_blur.c \
lib/evas/filters/evas_filter_bump.c \
Edje_Part_Description_Text *chosen_desc,
Edje_Calc_Params *params,
int *minw, int *minh,
- int *maxw, int *maxh, double pos)
+ int *maxw, int *maxh)
#define RECALC_SINGLE_TEXT_USING_APPLY 1
#if RECALC_SINGLE_TEXT_USING_APPLY
/*
free(sfont);
params->type.text.size = size; /* XXX TODO used by further calcs, go inside recalc_apply? */
- _edje_text_recalc_apply(ed, ep, params, chosen_desc, EINA_TRUE, pos);
+ _edje_text_recalc_apply(ed, ep, params, chosen_desc, EINA_TRUE);
if ((!chosen_desc) ||
((!chosen_desc->text.min_x) && (!chosen_desc->text.min_y) &&
static inline const char *
_edje_filter_get(Edje *ed, Edje_Part_Description_Spec_Filter *filter)
{
+ if (!filter->code) return NULL;
if (EINA_UNLIKELY(!filter->checked_data))
{
Edje_String *st;
const char *src1, *src2, *part, *code;
Evas_Object *obj = ep->object;
Eina_List *li1, *li2;
- Eina_Bool im = 0;
/* handle TEXT and IMAGE part types here */
if (ep->part->type == EDJE_PART_TYPE_TEXT)
prev_sources = ep->typedata.text->filter.sources;
filter_sources = edt->text.filter.sources;
}
-#if 0
- // old form
- if (ep->typedata.text->filter.code)
- filter = &ep->typedata.text->filter;
- else
- filter = &chosen_edt->text.filter;
- if (ep->typedata.text->filter.sources != chosen_edt->text.filter.sources)
- {
- prev_sources = ep->typedata.text->filter.sources;
- filter_sources = chosen_edt->text.filter.sources;
- //ep->typedata.text->filter.sources = chosen_edt->text.filter.sources;
- }
-#endif
}
else if (ep->part->type == EDJE_PART_TYPE_IMAGE)
{
prev_sources = edi->image.filter.sources;
filter_sources = chosen_edi->image.filter.sources;
}
- im = 1;
}
else
{
return;
}
- // FIXME: Implement proper EO interface/mixin and remove this ugly thing
-#define efl_gfx_filter_program_set(...) do { \
- if (!im) evas_obj_text_filter_program_set(__VA_ARGS__); \
- else evas_obj_text_filter_program_set(__VA_ARGS__); } while (0)
-#define efl_gfx_filter_source_set(...) do { \
- if (!im) evas_obj_text_filter_source_set(__VA_ARGS__); \
- else evas_obj_image_filter_source_set(__VA_ARGS__); } while (0)
-#define efl_gfx_filter_state_set(...) do { \
- if (!im) evas_obj_text_filter_state_set(__VA_ARGS__); \
- /* else evas_obj_image_filter_state_set(__VA_ARGS__); */ } while (0)
- // End of pure ugliness
-
/* common code below */
code = _edje_filter_get(ed, filter);
if (!code)
_edje_part_recalc_single_textblock(sc, ed, ep, (Edje_Part_Description_Text *)chosen_desc, params, &minw, &minh, &maxw, &maxh);
else if (ep->part->type == EDJE_PART_TYPE_TEXT)
{
- _edje_part_recalc_single_text(sc, ed, ep, (Edje_Part_Description_Text*) desc, (Edje_Part_Description_Text*) chosen_desc, params, &minw, &minh, &maxw, &maxh, pos);
+ _edje_part_recalc_single_text(sc, ed, ep, (Edje_Part_Description_Text*) desc, (Edje_Part_Description_Text*) chosen_desc, params, &minw, &minh, &maxw, &maxh);
_edje_part_recalc_single_filter(ed, ep, desc, chosen_desc, pos);
}
switch (ep->part->type)
{
case EDJE_PART_TYPE_TEXT:
- _edje_text_recalc_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc, EINA_FALSE, pos);
+ _edje_text_recalc_apply(ed, ep, pf, (Edje_Part_Description_Text*) chosen_desc, EINA_FALSE);
break;
case EDJE_PART_TYPE_PROXY:
Edje_Real_Part *ep,
Edje_Calc_Params *params,
Edje_Part_Description_Text *chosen_desc,
- Eina_Bool calc_only, double state_val);
+ Eina_Bool calc_only);
Evas_Font_Size _edje_text_size_calc(Evas_Font_Size size, Edje_Text_Class *tc);
const char * _edje_text_class_font_get(Edje *ed,
Edje_Part_Description_Text *chosen_desc,
_edje_text_recalc_apply(Edje *ed, Edje_Real_Part *ep,
Edje_Calc_Params *params,
Edje_Part_Description_Text *chosen_desc,
- Eina_Bool calc_only, double state_val)
+ Eina_Bool calc_only)
{
const char *text = NULL;
const char *font;
#include "interfaces/efl_gfx_gradient_base.eo.h"
#include "interfaces/efl_gfx_gradient_linear.eo.h"
#include "interfaces/efl_gfx_gradient_radial.eo.h"
+#include "interfaces/efl_gfx_filter.eo.h"
#endif
--- /dev/null
+interface Efl.Gfx.Filter
+{
+ legacy_prefix: null;
+ /* @since 1.15 */
+ methods {
+ @property program {
+ set {
+ [[Set an evas filter program on this object.
+
+ Valid for Text and Image objects at the moment.
+
+ The argument passed to this function is a string
+ containing a valid Lua program based on the filters
+ API as described in the "Evas filters reference"
+ page.
+
+ Set to null to disable filtering.
+ ]]
+ }
+ get {
+ [[Gets the code of the filter program set on this object.
+ May be null.
+ ]]
+ }
+ values {
+ code: const(char)*; [[filter program source code]]
+ }
+ }
+ @property state {
+ set {
+ [[Set the current state of the filter (for use from Edje).]]
+ }
+ values {
+ cur_state: const(char)*;
+ cur_val: double(0.0);
+ next_state: const(char)*;
+ next_val: double(0.0);
+ pos: double(0.0);
+ }
+ }
+ @property padding {
+ get {
+ [[Gets the padding required to apply this filter.]]
+ }
+ values {
+ l: int;
+ r: int;
+ t: int;
+ b: int;
+ }
+ }
+ 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).
+ ]]
+ params {
+ @in name: const(char)*; [[buffer name as used in the program]]
+ @in source: Efl.Gfx.Base*; [[object to use as a proxy source]]
+ }
+ }
+ source_get @const {
+ [[Retrieve which object is attached to this filter given its
+ buffer name.
+ ]]
+ params {
+ @in name: const(char)*; [[buffer name as used in the program]]
+ @out source: Efl.Gfx.Base*; [[object used as a proxy source]]
+ }
+ }
+ }
+}
#include "interfaces/efl_gfx_gradient_linear.eo.c"
#include "interfaces/efl_gfx_gradient_radial.eo.c"
+#include "interfaces/efl_gfx_filter.eo.c"
+
EAPI const Eo_Event_Description _EFL_GFX_CHANGED =
EO_EVENT_DESCRIPTION("Graphics changed", "The visual representation of the object changed");
--- /dev/null
+mixin Evas.Filter (Efl.Gfx.Filter)
+{
+ // Evas internal implementation
+ legacy_prefix: null;
+ methods {
+ @property changed {
+ set {
+ [[Marks this filter as changed.]]
+ }
+ values {
+ val: bool;
+ }
+ }
+ @property invalid {
+ set {
+ [[Marks this filter as invalid.]]
+ }
+ values {
+ val: bool;
+ }
+ }
+ constructor {
+ [[Initialize the Evas.Filter mixin.
+
+ Should be called in a parent's class constructor.
+ ]]
+ }
+ destructor {
+ [[Release all data held by this Evas.Filter.
+
+ This may include image buffers allocated by the Evas engine.
+ This should be called at the beginning of a parent's class destructor.
+ ]]
+ }
+ input_render {
+ [[Called by Evas.Filter when the parent class must render the input.
+ ;
+ ]]
+ params {
+ filter: void*; [[Evas_Filter_Context]]
+ drawctx: void*;
+ l: int;
+ r: int;
+ t: int;
+ b: int;
+ do_async: bool;
+ }
+ }
+ dirty {
+ [[Called when the filter changes must trigger a redraw of the object.
+
+ Virtual, to be implemented in the parent class.
+ ]]
+ }
+ }
+ implements {
+ Efl.Gfx.Filter.program.set;
+ Efl.Gfx.Filter.program.get;
+ Efl.Gfx.Filter.state.set;
+ Efl.Gfx.Filter.padding.get;
+ Efl.Gfx.Filter.source_set;
+ Efl.Gfx.Filter.source_get;
+ @virtual .input_render;
+ @virtual .dirty;
+ }
+}
--- /dev/null
+#include "evas_common_private.h"
+#include "evas_private.h"
+#include "../../lib/efl/interfaces/efl_gfx_filter.eo.h"
+#include "evas_filter.eo.h"
+#include "evas_filter.h"
+
+#define MY_CLASS EVAS_FILTER_MIXIN
+
+#define ENFN obj->layer->evas->engine.func
+#define ENDT obj->layer->evas->engine.data.output
+
+typedef struct _Evas_Filter_Data Evas_Filter_Data;
+struct _Evas_Filter_Data
+{
+ const Evas_Object_Filter_Data *data;
+};
+
+static void
+_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
+{
+ Eo *eo_obj = data;
+
+ // Destroy context as we won't reuse it.
+ evas_filter_context_destroy(ctx);
+
+ // Redraw text with normal styles in case of failure
+ if (!success)
+ {
+ Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
+
+ ERR("Filter failed at runtime!");
+ eo_do(eo_obj,
+ evas_filter_invalid_set(EINA_TRUE);
+ evas_filter_dirty());
+ 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_Filter_Data *pd;
+
+ proxy = eo_data_scope_get(pb->eo_proxy, EVAS_OBJECT_CLASS);
+ source = eo_data_scope_get(pb->eo_source, EVAS_OBJECT_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)
+ }
+
+ pd = eo_data_scope_get(pb->eo_proxy, MY_CLASS);
+
+ if (pd && proxy)
+ {
+ if (!eina_hash_population(pd->data->sources))
+ {
+ 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);
+}
+
+Eina_Bool
+evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj,
+ void *output, void *context, void *surface,
+ int x, int y, Eina_Bool do_async, Eina_Bool alpha)
+{
+ Evas_Filter_Data *pd = eo_data_scope_get(eo_obj, MY_CLASS);
+
+ if (!pd->data->invalid && (pd->data->chain || pd->data->code))
+ {
+ int X, Y, W, H, l = 0, r = 0, t = 0, b = 0;
+ Evas_Filter_Context *filter;
+ void *drawctx;
+ Eina_Bool ok;
+ void *previous = pd->data->output;
+ Evas_Object_Filter_Data *fcow =
+ eina_cow_write(evas_object_filter_cow, (const Eina_Cow_Data**)&(pd->data));
+
+ /* NOTE: Filter rendering is now done ENTIRELY on CPU.
+ * So we rely on cache/cache2 to allocate a real image buffer,
+ * that we can draw to. The OpenGL texture will be created only
+ * after the rendering has been done, as we simply push the output
+ * image to GL.
+ */
+
+ W = obj->cur->geometry.w;
+ H = obj->cur->geometry.h;
+ X = obj->cur->geometry.x;
+ Y = obj->cur->geometry.y;
+
+ // Prepare color multiplier
+ ENFN->context_color_set(output, context,
+ obj->cur->cache.clip.r,
+ obj->cur->cache.clip.g,
+ obj->cur->cache.clip.b,
+ obj->cur->cache.clip.a);
+ if (obj->cur->clipper)
+ ENFN->context_multiplier_set(output, context,
+ obj->cur->clipper->cur->cache.clip.r,
+ obj->cur->clipper->cur->cache.clip.g,
+ obj->cur->clipper->cur->cache.clip.b,
+ obj->cur->clipper->cur->cache.clip.a);
+ else
+ ENFN->context_multiplier_unset(output, context);
+
+ if (!fcow->chain)
+ {
+ Evas_Filter_Program *pgm;
+ pgm = evas_filter_program_new(obj->name ? obj->name : obj->type, alpha);
+ evas_filter_program_source_set_all(pgm, fcow->sources);
+ evas_filter_program_state_set(pgm, eo_obj, obj,
+ fcow->state.cur.name, fcow->state.cur.value,
+ fcow->state.next.name, fcow->state.next.value,
+ fcow->state.pos);
+ if (!evas_filter_program_parse(pgm, fcow->code))
+ {
+ ERR("Filter program parsing failed");
+ evas_filter_program_del(pgm);
+ fcow->invalid = EINA_TRUE;
+
+ eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(pd->data),
+ fcow, EINA_TRUE);
+ return EINA_FALSE;
+ }
+ fcow->chain = pgm;
+ fcow->invalid = EINA_FALSE;
+ }
+ else if (previous && !fcow->changed)
+ {
+ Eina_Bool redraw;
+
+ redraw = evas_filter_program_state_set(fcow->chain, eo_obj, obj,
+ fcow->state.cur.name, fcow->state.cur.value,
+ fcow->state.next.name, fcow->state.next.value,
+ fcow->state.pos);
+ if (redraw)
+ DBG("Filter redraw by state change!");
+
+ // Scan proxies to find if any changed
+ if (!redraw && fcow->sources)
+ {
+ Evas_Filter_Proxy_Binding *pb;
+ Evas_Object_Protected_Data *source;
+ Eina_Iterator *iter;
+
+ iter = eina_hash_iterator_data_new(fcow->sources);
+ EINA_ITERATOR_FOREACH(iter, pb)
+ {
+ source = eo_data_scope_get(pb->eo_source, EVAS_OBJECT_CLASS);
+ if (source->changed)
+ {
+ redraw = EINA_TRUE;
+ break;
+ }
+ }
+ eina_iterator_free(iter);
+ }
+
+ if (!redraw)
+ {
+ // Render this image only
+ ENFN->image_draw(ENDT, context,
+ surface, previous,
+ 0, 0, W, H, // src
+ X + x, Y + y, W, H, // dst
+ EINA_FALSE, // smooth
+ do_async);
+
+ eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(pd->data),
+ fcow, EINA_TRUE);
+ return EINA_TRUE;
+ }
+ }
+ else
+ evas_filter_program_state_set(fcow->chain, eo_obj, obj,
+ fcow->state.cur.name, fcow->state.cur.value,
+ fcow->state.next.name, fcow->state.next.value,
+ fcow->state.pos);
+
+ filter = evas_filter_context_new(obj->layer->evas, do_async);
+
+ // Run script
+ ok = evas_filter_context_program_use(filter, fcow->chain);
+ if (!filter || !ok)
+ {
+ ERR("Parsing failed?");
+ evas_filter_context_destroy(filter);
+
+ eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(pd->data),
+ fcow, EINA_TRUE);
+ return EINA_FALSE;
+ }
+
+ // Proxies
+ evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
+
+ // Draw Context
+ drawctx = ENFN->context_new(ENDT);
+ ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255);
+
+ // Allocate all buffers now
+ evas_filter_context_buffers_allocate_all(filter);
+ evas_filter_target_set(filter, context, surface, X + x, Y + y);
+
+ // Steal output and release previous
+ fcow->output = evas_filter_buffer_backing_steal(filter, EVAS_FILTER_BUFFER_OUTPUT_ID);
+ if (fcow->output != previous)
+ evas_filter_buffer_backing_release(filter, previous);
+
+ evas_filter_program_padding_get(fcow->chain, &l, &r, &t, &b);
+ eo_do(eo_obj, evas_filter_input_render(filter, drawctx, l, r, t, b, do_async));
+#warning TODO: draw text into input buffer
+#if 0
+ // Render text to input buffer
+ EINA_INLIST_FOREACH(EINA_INLIST_GET(pd->items), it)
+ if ((pd->font) && (it->text_props.len > 0))
+ {
+ evas_filter_font_draw(filter, drawctx, EVAS_FILTER_BUFFER_INPUT_ID, pd->font,
+ sl + it->x,
+ st + (int) pd->max_ascent,
+ &it->text_props,
+ do_async);
+ }
+#endif
+
+ ENFN->context_free(ENDT, drawctx);
+
+ // Add post-run callback and run filter
+ evas_filter_context_post_run_callback_set(filter, _filter_cb, eo_obj);
+ ok = evas_filter_run(filter);
+ fcow->changed = EINA_FALSE;
+ if (!ok) fcow->invalid = EINA_TRUE;
+
+ eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data **) &(pd->data), fcow, EINA_TRUE);
+
+ if (ok)
+ {
+ DBG("Effect rendering done.");
+ return EINA_TRUE;
+ }
+ else
+ {
+ ERR("Rendering failed.");
+ return EINA_FALSE;
+ }
+ }
+ return EINA_FALSE;
+}
+
+EOLIAN void
+_evas_filter_efl_gfx_filter_program_set(Eo *eo_obj, Evas_Filter_Data *pd,
+ const char *code)
+{
+ Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
+ Evas_Filter_Program *pgm = NULL;
+
+ if (!pd) return;
+ if (pd->data->code == code) return;
+ if (pd->data->code && code && !strcmp(code, pd->data->code)) return;
+
+ evas_object_async_block(obj);
+ EINA_COW_WRITE_BEGIN(evas_object_filter_cow, pd->data, Evas_Object_Filter_Data, fcow)
+ {
+ // Parse filter program
+ evas_filter_program_del(fcow->chain);
+ if (code)
+ {
+ pgm = evas_filter_program_new("Evas_Text", EINA_TRUE);
+ evas_filter_program_source_set_all(pgm, fcow->sources);
+ evas_filter_program_state_set(pgm, eo_obj, obj,
+ fcow->state.cur.name, fcow->state.cur.value,
+ fcow->state.next.name, fcow->state.next.value,
+ fcow->state.pos);
+ if (!evas_filter_program_parse(pgm, code))
+ {
+ ERR("Parsing failed!");
+ evas_filter_program_del(pgm);
+ pgm = NULL;
+ }
+ }
+ fcow->chain = pgm;
+ fcow->changed = EINA_TRUE;
+ fcow->invalid = (pgm == NULL);
+ eina_stringshare_replace(&fcow->code, code);
+ }
+ EINA_COW_WRITE_END(evas_object_filter_cow, pd->data, fcow);
+
+ // Update object
+ eo_do(eo_obj, evas_filter_dirty());
+ 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);
+}
+
+EOLIAN const char *
+_evas_filter_efl_gfx_filter_program_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd)
+{
+ return pd->data->code;
+}
+
+EOLIAN void
+_evas_filter_efl_gfx_filter_source_set(Eo *eo_obj, Evas_Filter_Data *pd,
+ const char *name, Efl_Gfx_Base *eo_source)
+{
+ Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
+ Evas_Filter_Proxy_Binding *pb, *pb_old = NULL;
+ Evas_Object_Protected_Data *source = NULL;
+ Evas_Object_Filter_Data *fcow = NULL;
+
+ if (eo_source)
+ source = eo_data_scope_get(eo_source, EVAS_OBJECT_CLASS);
+
+ evas_object_async_block(obj);
+ if (!name)
+ {
+ if (!eo_source || !pd->data->sources) return;
+ if (eina_hash_del_by_data(pd->data->sources, eo_source))
+ goto update;
+ return;
+ }
+
+ if (!source && !pd->data->sources)
+ return;
+
+ if (pd->data->sources)
+ {
+ pb_old = eina_hash_find(pd->data->sources, name);
+ if (pb_old && (pb_old->eo_source == eo_source)) return;
+ }
+
+ fcow = eina_cow_write(evas_object_filter_cow, (const Eina_Cow_Data**)&pd->data);
+
+ if (!fcow->sources)
+ fcow->sources = eina_hash_string_small_new(EINA_FREE_CB(_filter_source_hash_free_cb));
+ else if (pb_old)
+ eina_hash_del(fcow->sources, name, pb_old);
+
+ if (!source)
+ {
+ pb_old = eina_hash_find(fcow->sources, name);
+ if (!pb_old)
+ {
+ eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&pd->data, fcow, EINA_TRUE);
+ return;
+ }
+ eina_hash_del_by_key(fcow->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);
+
+ if (!eina_list_data_find(source->proxy->proxies, eo_obj))
+ {
+ EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy, Evas_Object_Proxy_Data, source_write)
+ source_write->proxies = eina_list_append(source_write->proxies, eo_obj);
+ EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
+ }
+
+ if (!obj->proxy->is_proxy)
+ {
+ 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(fcow->sources, pb->name, pb);
+ evas_filter_program_source_set_all(fcow->chain, fcow->sources);
+
+ // Update object
+update:
+ if (fcow)
+ {
+ fcow->changed = EINA_TRUE;
+ fcow->invalid = EINA_FALSE;
+ eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&pd->data, fcow, EINA_TRUE);
+ }
+
+ eo_do(eo_obj, evas_filter_dirty());
+ 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);
+}
+
+EOLIAN void
+_evas_filter_efl_gfx_filter_source_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd,
+ const char *name, Efl_Gfx_Base **source)
+{
+ if (!source) return;
+ *source = eina_hash_find(pd->data->sources, name);
+}
+
+EOLIAN void
+_evas_filter_efl_gfx_filter_state_set(Eo *eo_obj, Evas_Filter_Data *pd,
+ const char *cur_state, double cur_val,
+ const char *next_state, double next_val,
+ double pos)
+{
+ Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
+
+ evas_object_async_block(obj);
+ if ((cur_state != pd->data->state.cur.name) || (cur_val != pd->data->state.cur.value) ||
+ (next_state != pd->data->state.next.name) || (next_val != pd->data->state.next.value) ||
+ (pos != pd->data->state.pos))
+ {
+ EINA_COW_WRITE_BEGIN(evas_object_filter_cow, pd->data, Evas_Object_Filter_Data, fcow)
+ {
+ fcow->changed = 1;
+ fcow->state.cur.name = cur_state;
+ fcow->state.cur.value = cur_val;
+ fcow->state.next.name = next_state;
+ fcow->state.next.value = next_val;
+ fcow->state.pos = pos;
+
+ if (pd->data->chain)
+ {
+ evas_filter_program_state_set(pd->data->chain, eo_obj, obj,
+ fcow->state.cur.name, fcow->state.cur.value,
+ fcow->state.next.name, fcow->state.next.value,
+ fcow->state.pos);
+ }
+ }
+ EINA_COW_WRITE_END(evas_object_filter_cow, pd->data, fcow);
+
+ // Mark as changed
+ eo_do(eo_obj, evas_filter_dirty());
+ 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);
+ }
+}
+
+EOLIAN void
+_evas_filter_efl_gfx_filter_padding_get(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd,
+ int *l, int *r, int *t, int *b)
+{
+ if (!pd->data->chain)
+ {
+ if (l) *l = 0;
+ if (r) *r = 0;
+ if (t) *t = 0;
+ if (b) *b = 0;
+ return;
+ }
+ evas_filter_program_padding_get(pd->data->chain, l, r, t, b);
+}
+
+EOLIAN void
+_evas_filter_changed_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val)
+{
+ if ((evas_object_filter_cow_default != pd->data) && (pd->data->changed != val))
+ {
+ EINA_COW_WRITE_BEGIN(evas_object_filter_cow, pd->data, Evas_Object_Filter_Data, fcow)
+ fcow->changed = val;
+ EINA_COW_WRITE_END(evas_object_filter_cow, pd->data, fcow);
+ }
+}
+
+EOLIAN void
+_evas_filter_invalid_set(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd, Eina_Bool val)
+{
+ if (pd->data->invalid != val)
+ {
+ EINA_COW_WRITE_BEGIN(evas_object_filter_cow, pd->data, Evas_Object_Filter_Data, fcow)
+ fcow->invalid = val;
+ EINA_COW_WRITE_END(evas_object_filter_cow, pd->data, fcow);
+ }
+}
+
+EOLIAN void
+_evas_filter_constructor(Eo *eo_obj EINA_UNUSED, Evas_Filter_Data *pd)
+{
+ pd->data = eina_cow_alloc(evas_object_filter_cow);
+}
+
+EOLIAN void
+_evas_filter_destructor(Eo *eo_obj, Evas_Filter_Data *pd)
+{
+ Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
+
+ if (!pd->data) return;
+ if (evas_object_filter_cow_default == pd->data) return;
+
+ if (pd->data->output)
+ ENFN->image_free(ENDT, pd->data->output);
+ eina_hash_free(pd->data->sources);
+ evas_filter_program_del(pd->data->chain);
+ eina_stringshare_del(pd->data->code);
+ eina_cow_free(evas_object_filter_cow, (const Eina_Cow_Data **) &pd->data);
+}
+
+#include "evas_filter.eo.c"
if (eo_isa(proxy, EVAS_IMAGE_CLASS))
evas_object_image_source_unset(proxy);
else if (eo_isa(proxy, EVAS_TEXT_CLASS))
- eo_do(proxy, evas_obj_text_filter_source_set(NULL, eo_obj));
+ eo_do(proxy, efl_gfx_filter_source_set(NULL, eo_obj));
}
/* Eina_Cow has no way to know if we are going to really change something
#include "evas_common_private.h" /* Includes evas_bidi_utils stuff. */
#include "evas_private.h"
+
+#include "../efl/interfaces/efl_gfx_filter.eo.h"
+#include "evas_filter.eo.h"
#include "evas_filter.h"
#define MY_CLASS EVAS_TEXT_CLASS
Evas_Font_Size size;
Evas_Text_Style_Type style;
-
- const Evas_Object_Filter_Data* filter; // cow
} cur, prev;
struct {
Evas_BiDi_Direction bidi_dir : 2;
char changed : 1;
+ char has_filter : 1;
};
struct _Evas_Object_Text_Item
}
EOLIAN static Eo *
-_evas_text_eo_base_constructor(Eo *eo_obj, Evas_Text_Data *o)
+_evas_text_eo_base_constructor(Eo *eo_obj, Evas_Text_Data *o EINA_UNUSED)
{
eo_obj = eo_do_super_ret(eo_obj, MY_CLASS, eo_obj, eo_constructor());
evas_object_text_init(eo_obj);
- o->cur.filter = eina_cow_alloc(evas_object_filter_cow);
-
return eo_obj;
}
EOLIAN static const char*
_evas_text_efl_text_properties_font_source_get(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o)
{
-
return o->cur.source;
}
-static inline void
-_evas_text_filter_changed_set(Evas_Text_Data *o, Eina_Bool val)
-{
- if ((evas_object_filter_cow_default != o->cur.filter)
- && (o->cur.filter->changed != val))
- {
- EINA_COW_WRITE_BEGIN(evas_object_filter_cow, o->cur.filter, Evas_Object_Filter_Data, fcow)
- fcow->changed = val;
- EINA_COW_WRITE_END(evas_object_filter_cow, o->cur.filter, fcow);
- }
-}
-
EOLIAN static void
_evas_text_efl_text_properties_font_set(Eo *eo_obj, Evas_Text_Data *o, const char *font, Evas_Font_Size size)
{
_evas_object_text_items_clear(o);
_evas_object_text_recalc(eo_obj, o->cur.text);
o->changed = 1;
- _evas_text_filter_changed_set(o, EINA_TRUE);
+ if (o->has_filter)
+ eo_do(eo_obj, evas_filter_changed_set(EINA_TRUE));
evas_object_change(eo_obj, obj);
evas_object_clip_dirty(eo_obj, obj);
evas_object_coords_recalc(eo_obj, obj);
return EINA_TRUE;
}
+static void
+_evas_object_text_pad_get(Evas_Object *eo_obj, Evas_Text_Data *o, int *l, int *r, int *t, int *b)
+{
+ if (l) *l = 0;
+ if (r) *r = 0;
+ if (t) *t = 0;
+ if (b) *b = 0;
+ if (!o->has_filter)
+ evas_text_style_pad_get(o->cur.style, l, r, t, b);
+ else
+ eo_do(eo_obj, efl_gfx_filter_padding_get(l, r, t, b));
+}
+
/**
* @internal
* Populates o->items with the items of the text according to text
}
o->last_computed.advance_without_ellipsis = advance;
- if (!o->cur.filter || !o->cur.filter->chain)
- evas_text_style_pad_get(o->cur.style, &l, &r, NULL, NULL);
- else
- evas_filter_program_padding_get(o->cur.filter->chain, &l, &r, NULL, NULL);
+ _evas_object_text_pad_get(eo_obj, o, &l, &r, NULL, NULL);
/* Handle ellipsis */
if (pos && (o->cur.ellipsis >= 0.0) && (advance + l + r > obj->cur->geometry.w) && (obj->cur->geometry.w > 0))
evas_object_async_block(obj);
o->cur.ellipsis = ellipsis;
o->changed = 1;
- _evas_text_filter_changed_set(o, EINA_TRUE);
+ if (o->has_filter)
+ eo_do(eo_obj, evas_filter_changed_set(EINA_TRUE));
evas_object_change(eo_obj, obj);
evas_object_clip_dirty(eo_obj, obj);
}
if (o->cur.text != text) free(text);
o->changed = 1;
- _evas_text_filter_changed_set(o, EINA_TRUE);
+ if (o->has_filter)
+ eo_do(eo_obj, evas_filter_changed_set(EINA_TRUE));
evas_object_change(eo_obj, obj);
evas_object_clip_dirty(eo_obj, obj);
evas_object_coords_recalc(eo_obj, obj);
Eina_Bool int_ret = _evas_object_text_char_coords_get(eo_obj, o, (size_t) pos,
&x, &y, &w, &h);
- if (!o->cur.filter || !o->cur.filter->chain)
- evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
- else
- evas_filter_program_padding_get(o->cur.filter->chain, &l, &r, &t, &b);
+
+ _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
y += o->max_ascent - t;
x -= l;
if (x < 0)
int int_ret = _evas_object_text_char_at_coords(eo_obj, o, x, y - o->max_ascent,
&rx, &ry, &rw, &rh);
- if (!o->cur.filter || !o->cur.filter->chain)
- evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
- else
- evas_filter_program_padding_get(o->cur.filter->chain, &l, &r, &t, &b);
+ _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
ry += o->max_ascent - t;
rx -= l;
if (rx < 0)
if (o->cur.style == style) return;
evas_object_async_block(obj);
- evas_text_style_pad_get(o->cur.style, &pl, &pr, &pt, &pb);
+ _evas_object_text_pad_get(eo_obj, o, &pl, &pr, &pt, &pb);
+ //evas_text_style_pad_get(o->cur.style, &pl, &pr, &pt, &pb);
o->cur.style = style;
- evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
+ _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
+ //evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
if (o->items) w = obj->cur->geometry.w + (l - pl) + (r - pr);
h = obj->cur->geometry.h + (t - pt) + (b - pb);
}
EOLIAN static void
-_evas_text_style_pad_get(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o, int *l, int *r, int *t, int *b)
+_evas_text_style_pad_get(Eo *eo_obj, Evas_Text_Data *o, int *l, int *r, int *t, int *b)
{
- int sl = 0, sr = 0, st = 0, sb = 0;
- /* use temps to be certain we have initialized values */
- if (!o->cur.filter || !o->cur.filter->chain)
- evas_text_style_pad_get(o->cur.style, &sl, &sr, &st, &sb);
- else
- evas_filter_program_padding_get(o->cur.filter->chain, &sl, &sr, &st, &sb);
- if (l) *l = sl;
- if (r) *r = sr;
- if (t) *t = st;
- if (b) *b = sb;
+ _evas_object_text_pad_get(eo_obj, o, l, r, t, b);
}
EAPI int
#ifdef BIDI_SUPPORT
o->bidi_par_props = evas_bidi_paragraph_props_new();
#endif
+
+ eo_do(eo_obj, evas_filter_constructor());
}
EOLIAN static void
{
Evas_Text_Data *o = eo_data_scope_get(eo_obj, MY_CLASS);
- /* free filter output */
- if (evas_object_filter_cow_default != o->cur.filter)
- {
- EINA_COW_WRITE_BEGIN(evas_object_filter_cow, o->cur.filter, Evas_Object_Filter_Data, fcow)
- if (fcow->output)
- ENFN->image_free(ENDT, fcow->output);
- eina_hash_free(fcow->sources);
- evas_filter_program_del(fcow->chain);
- eina_stringshare_del(fcow->code);
- fcow->output = NULL;
- fcow->chain = NULL;
- fcow->sources = NULL;
- fcow->code = NULL;
- EINA_COW_WRITE_END(evas_object_filter_cow, o->cur.filter, fcow);
- eina_cow_free(evas_object_filter_cow, (const Eina_Cow_Data **) &o->cur.filter);
- }
-
/* free obj */
+ eo_do(eo_obj, evas_filter_destructor());
_evas_object_text_items_clear(o);
if (o->cur.utf8_text) eina_stringshare_del(o->cur.utf8_text);
if (o->cur.font) eina_stringshare_del(o->cur.font);
}
}
-static void
-_filter_cb(Evas_Filter_Context *ctx, void *data, Eina_Bool success)
-{
- Eo *eo_obj = data;
-
- // Destroy context as we won't reuse it.
- evas_filter_context_destroy(ctx);
+/* ugly binding between evas_fitler_mixin.c and this object */
- // Redraw text with normal styles in case of failure
- if (!success)
- {
- Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
- Evas_Text_Data *o = (Evas_Text_Data *) obj->private_data;
+EOLIAN void
+_evas_text_evas_filter_dirty(Eo *eo_obj, Evas_Text_Data *o)
+{
+ _evas_object_text_items_clear(o);
+ o->changed = 1;
+ _evas_object_text_recalc(eo_obj, o->cur.text);
+}
- ERR("Filter failed at runtime!");
- EINA_COW_WRITE_BEGIN(evas_object_filter_cow, o->cur.filter, Evas_Object_Filter_Data, fcow)
- fcow->invalid = EINA_TRUE;
- EINA_COW_WRITE_END(evas_object_filter_cow, o->cur.filter, fcow);
+EOLIAN void
+_evas_text_evas_filter_input_render(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o,
+ void *_filter, void *drawctx,
+ int l, int r, int t, int b, Eina_Bool do_async)
+{
+ Evas_Filter_Context *filter = _filter;
+ Evas_Object_Text_Item *it;
+ (void) r; (void) b;
- // Update object
- _evas_object_text_items_clear(o);
- o->changed = 1;
- _evas_object_text_recalc(eo_obj, o->cur.text);
- 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);
- }
+ EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
+ if ((o->font) && (it->text_props.len > 0))
+ {
+ evas_filter_font_draw(filter, drawctx, EVAS_FILTER_BUFFER_INPUT_ID, o->font,
+ l + it->x,
+ t + (int) o->max_ascent,
+ &it->text_props,
+ do_async);
+ }
}
static void
int shad_dst = 0, shad_sz = 0, dx = 0, dy = 0, haveshad = 0;
/* render object to surface with context, and offxet by x,y */
- if (!o->cur.filter->chain)
- evas_text_style_pad_get(o->cur.style, &sl, NULL, &st, NULL);
- else
- evas_filter_program_padding_get(o->cur.filter->chain, &sl, NULL, &st, NULL);
+ _evas_object_text_pad_get(eo_obj, o, &sl, NULL, &st, NULL);
ENFN->context_multiplier_unset(output, context);
ENFN->context_render_op_set(output, context, obj->cur->render_op);
/* FIXME: This clipping is just until we fix inset handling correctly. */
&it->text_props, \
do_async);
- /* FIXME/WARNING
- * The code below is EXPERIMENTAL, and not to be considered usable or even
- * remotely similar to its final form. You've been warned :)
- */
-
- if (!o->cur.filter->invalid && (o->cur.filter->chain || o->cur.filter->code))
+ if (o->has_filter)
{
- int X, Y, W, H;
- Evas_Filter_Context *filter;
- const int inbuf = 1;
- const int outbuf = 2;
- void *filter_ctx;
- Eina_Bool ok;
- int ox = 0, oy = 0;
- void *previous = o->cur.filter->output;
- Evas_Object_Filter_Data *fcow =
- eina_cow_write(evas_object_filter_cow, (const Eina_Cow_Data**)&(o->cur.filter));
-
- /* NOTE: Font effect rendering is now done ENTIRELY on CPU.
- * So we rely on cache/cache2 to allocate a real image buffer,
- * that we can draw to. The OpenGL texture will be created only
- * after the rendering has been done, as we simply push the output
- * image to GL.
- */
-
- W = obj->cur->geometry.w;
- H = obj->cur->geometry.h;
- X = obj->cur->geometry.x;
- Y = obj->cur->geometry.y;
-
- // Prepare color multiplier
- COLOR_ONLY_SET(obj, cur->cache, clip);
- if (obj->cur->clipper)
- ENFN->context_multiplier_set(output, context,
- obj->cur->clipper->cur->cache.clip.r,
- obj->cur->clipper->cur->cache.clip.g,
- obj->cur->clipper->cur->cache.clip.b,
- obj->cur->clipper->cur->cache.clip.a);
- else
- ENFN->context_multiplier_unset(output, context);
-
- if (!fcow->chain)
- {
- Evas_Filter_Program *pgm;
- pgm = evas_filter_program_new("Evas_Text", EINA_TRUE);
- evas_filter_program_source_set_all(pgm, fcow->sources);
- evas_filter_program_state_set(pgm, eo_obj, obj,
- fcow->state.cur.name, fcow->state.cur.value,
- fcow->state.next.name, fcow->state.next.value,
- fcow->state.pos);
- if (!evas_filter_program_parse(pgm, fcow->code))
- {
- ERR("Filter program parsing failed");
- evas_filter_program_del(pgm);
- fcow->invalid = EINA_TRUE;
-
- eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(o->cur.filter),
- fcow, EINA_TRUE);
- goto normal_render;
- }
- fcow->chain = pgm;
- fcow->invalid = EINA_FALSE;
- }
- else if (previous && !fcow->changed)
- {
- Eina_Bool redraw;
-
- redraw = evas_filter_program_state_set(fcow->chain, eo_obj, obj,
- fcow->state.cur.name, fcow->state.cur.value,
- fcow->state.next.name, fcow->state.next.value,
- fcow->state.pos);
- if (redraw)
- DBG("Filter redraw by state change!");
-
- // Scan proxies to find if any changed
- if (!redraw && fcow->sources)
- {
- Evas_Filter_Proxy_Binding *pb;
- Evas_Object_Protected_Data *source;
- Eina_Iterator *iter;
-
- iter = eina_hash_iterator_data_new(fcow->sources);
- EINA_ITERATOR_FOREACH(iter, pb)
- {
- source = eo_data_scope_get(pb->eo_source, EVAS_OBJECT_CLASS);
- if (source->changed)
- {
- redraw = EINA_TRUE;
- break;
- }
- }
- eina_iterator_free(iter);
- }
-
- if (!redraw)
- {
- // Render this image only
- ENFN->image_draw(ENDT, context,
- surface, previous,
- 0, 0, W, H, // src
- X + x, Y + y, W, H, // dst
- EINA_FALSE, // smooth
- do_async);
-
- eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(o->cur.filter),
- fcow, EINA_TRUE);
- return;
- }
- }
- else
- evas_filter_program_state_set(fcow->chain, eo_obj, obj,
- fcow->state.cur.name, fcow->state.cur.value,
- fcow->state.next.name, fcow->state.next.value,
- fcow->state.pos);
-
- filter = evas_filter_context_new(obj->layer->evas, do_async);
-
- // Run script
- ok = evas_filter_context_program_use(filter, fcow->chain);
- if (!filter || !ok)
- {
- ERR("Parsing failed?");
- evas_filter_context_destroy(filter);
-
- eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(o->cur.filter),
- fcow, EINA_TRUE);
- goto normal_render;
- }
-
- // Proxies
- evas_filter_context_proxy_render_all(filter, eo_obj, EINA_FALSE);
-
- // Draw Context
- filter_ctx = ENFN->context_new(ENDT);
- ENFN->context_color_set(ENDT, filter_ctx, 255, 255, 255, 255);
-
- // Allocate all buffers now
- evas_filter_context_buffers_allocate_all(filter);
- evas_filter_target_set(filter, context, surface, X + x, Y + y);
-
- // Steal output and release previous
- fcow->output = evas_filter_buffer_backing_steal(filter, outbuf);
- if (fcow->output != previous)
- evas_filter_buffer_backing_release(filter, previous);
-
- // Render text to input buffer
- EINA_INLIST_FOREACH(EINA_INLIST_GET(o->items), it)
- if ((o->font) && (it->text_props.len > 0))
- {
- evas_filter_font_draw(filter, filter_ctx, inbuf, o->font,
- sl + ox + it->x,
- st + oy + (int) o->max_ascent,
- &it->text_props,
- do_async);
- }
-
- ENFN->context_free(ENDT, filter_ctx);
-
- // Add post-run callback and run filter
- evas_filter_context_post_run_callback_set(filter, _filter_cb, eo_obj);
- ok = evas_filter_run(filter);
- fcow->changed = EINA_FALSE;
-
- if (!ok) fcow->invalid = EINA_TRUE;
-
- eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&(o->cur.filter),
- fcow, EINA_TRUE);
-
- if (ok)
- {
- DBG("Effect rendering done.");
- return;
- }
- else
- {
- ERR("Rendering failed");
- goto normal_render;
- }
+ if (evas_filter_object_render(eo_obj, obj, output, context, surface, x, y, do_async, EINA_TRUE))
+ return;
}
- /* End of the EXPERIMENTAL code */
-
-normal_render:
-
/* shadows */
switch (o->cur.style & EVAS_TEXT_STYLE_MASK_BASIC)
{
/* DO II */
_evas_object_text_recalc(eo_obj, o->cur.text);
o->changed = 1;
- _evas_text_filter_changed_set(o, EINA_TRUE);
+ if (o->has_filter)
+ eo_do(eo_obj, evas_filter_changed_set(EINA_TRUE));
evas_object_change(eo_obj, obj);
evas_object_clip_dirty(eo_obj, obj);
evas_object_coords_recalc(eo_obj, obj);
w = _evas_object_text_horiz_advance_without_ellipsis_get(o);
h = _evas_object_text_vert_advance_get(eo_obj, o);
- if (!o->cur.filter->chain)
- evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
- else
- evas_filter_program_padding_get(o->cur.filter->chain, &l, &r, &t, &b);
+ _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
if (o->cur.ellipsis >= 0.0)
{
else
{
int t = 0, b = 0, l = 0, r = 0;
-
- if (!o->cur.filter->chain)
- evas_text_style_pad_get(o->cur.style, &l, &r, &t, &b);
- else
- evas_filter_program_padding_get(o->cur.filter->chain, &l, &r, &t, &b);
-
+ _evas_object_text_pad_get(eo_obj, o, &l, &r, &t, &b);
eo_do_super(eo_obj, MY_CLASS,
efl_gfx_size_set(0, o->max_ascent + o->max_descent + t + b));
//// obj->cur->cache.geometry.validity = 0;
o->last_computed.h = obj->cur->geometry.h;
}
-EOLIAN static void
-_evas_text_filter_program_set(Eo *eo_obj, Evas_Text_Data *o, const char *arg)
-{
- Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
- 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;
-
- evas_object_async_block(obj);
- EINA_COW_WRITE_BEGIN(evas_object_filter_cow, o->cur.filter, Evas_Object_Filter_Data, fcow)
- {
- // Parse filter program
- evas_filter_program_del(fcow->chain);
- if (arg)
- {
- pgm = evas_filter_program_new("Evas_Text", EINA_TRUE);
- evas_filter_program_source_set_all(pgm, fcow->sources);
- evas_filter_program_state_set(pgm, eo_obj, obj,
- fcow->state.cur.name, fcow->state.cur.value,
- fcow->state.next.name, fcow->state.next.value,
- fcow->state.pos);
- if (!evas_filter_program_parse(pgm, arg))
- {
- ERR("Parsing failed!");
- evas_filter_program_del(pgm);
- pgm = NULL;
- }
- }
- fcow->chain = pgm;
- fcow->changed = EINA_TRUE;
- fcow->invalid = (pgm == NULL);
- eina_stringshare_replace(&fcow->code, arg);
- }
- EINA_COW_WRITE_END(evas_object_filter_cow, o->cur.filter, fcow);
-
- // Update object
- _evas_object_text_items_clear(o);
- o->changed = 1;
- _evas_object_text_recalc(eo_obj, o->cur.text);
- 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_Text_Data *o;
-
- proxy = eo_data_scope_get(pb->eo_proxy, EVAS_OBJECT_CLASS);
- source = eo_data_scope_get(pb->eo_source, EVAS_OBJECT_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)
- {
- if (!eina_hash_population(o->cur.filter->sources))
- {
- 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_text_filter_source_set(Eo *eo_obj, Evas_Text_Data *o, const char *name, Evas_Object *eo_source)
-{
- Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
- Evas_Filter_Proxy_Binding *pb, *pb_old = NULL;
- Evas_Object_Protected_Data *source = NULL;
- Evas_Object_Filter_Data *fcow = NULL;
-
- if (eo_source) source = eo_data_scope_get(eo_source, EVAS_OBJECT_CLASS);
-
- evas_object_async_block(obj);
- 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 (!source && !o->cur.filter->sources)
- return;
-
- if (o->cur.filter->sources)
- {
- pb_old = eina_hash_find(o->cur.filter->sources, name);
- if (pb_old && (pb_old->eo_source == eo_source)) return;
- }
-
- fcow = eina_cow_write(evas_object_filter_cow, (const Eina_Cow_Data**)&o->cur.filter);
-
- if (!fcow->sources)
- {
- fcow->sources = eina_hash_string_small_new
- (EINA_FREE_CB(_filter_source_hash_free_cb));
- }
- else if (pb_old)
- eina_hash_del(fcow->sources, name, pb_old);
-
- if (!source)
- {
- pb_old = eina_hash_find(fcow->sources, name);
- if (!pb_old)
- {
- eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&o->cur.filter,
- fcow, EINA_TRUE);
- return;
- }
- eina_hash_del_by_key(fcow->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);
-
- if (!eina_list_data_find(source->proxy->proxies, eo_obj))
- {
- EINA_COW_WRITE_BEGIN(evas_object_proxy_cow, source->proxy, Evas_Object_Proxy_Data, source_write)
- source_write->proxies = eina_list_append(source_write->proxies, eo_obj);
- EINA_COW_WRITE_END(evas_object_proxy_cow, source->proxy, source_write)
- }
-
- if (!obj->proxy->is_proxy)
- {
- 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(fcow->sources, pb->name, pb);
- evas_filter_program_source_set_all(fcow->chain, fcow->sources);
-
- // Update object
-update:
- if (fcow)
- {
- fcow->changed = EINA_TRUE;
- fcow->invalid = EINA_FALSE;
- eina_cow_done(evas_object_filter_cow, (const Eina_Cow_Data**)&o->cur.filter,
- fcow, EINA_TRUE);
- }
-
- _evas_object_text_items_clear(o);
- o->changed = 1;
- _evas_object_text_recalc(eo_obj, o->cur.text);
- 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);
-}
-
-EOLIAN static void
-_evas_text_filter_state_set(Eo *eo_obj EINA_UNUSED, Evas_Text_Data *o,
- const char *cur_state, double cur_val,
- const char *next_state, double next_val, double pos)
-{
- Evas_Object_Protected_Data *obj = eo_data_scope_get(eo_obj, EVAS_OBJECT_CLASS);
-
- evas_object_async_block(obj);
- if ((cur_state != o->cur.filter->state.cur.name) || (cur_val != o->cur.filter->state.cur.value) ||
- (next_state != o->cur.filter->state.next.name) || (next_val != o->cur.filter->state.next.value) ||
- (pos != o->cur.filter->state.pos))
- {
- EINA_COW_WRITE_BEGIN(evas_object_filter_cow, o->cur.filter, Evas_Object_Filter_Data, fcow)
- {
- fcow->changed = 1;
- fcow->state.cur.name = cur_state;
- fcow->state.cur.value = cur_val;
- fcow->state.next.name = next_state;
- fcow->state.next.value = next_val;
- fcow->state.pos = pos;
-
- if (o->cur.filter->chain)
- {
- evas_filter_program_state_set(o->cur.filter->chain, eo_obj, obj,
- fcow->state.cur.name, fcow->state.cur.value,
- fcow->state.next.name, fcow->state.next.value,
- fcow->state.pos);
- }
- }
- EINA_COW_WRITE_END(evas_object_filter_cow, o->cur.filter, fcow);
-
- // Mark as changed
- _evas_object_text_items_clear(o);
- o->changed = 1;
- _evas_object_text_recalc(eo_obj, o->cur.text);
- 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);
- }
-}
-
EAPI void
evas_object_text_font_source_set(Eo *obj, const char *font_source)
{
return eo_do_ret((Eo *) obj, ret, efl_text_get());
}
+
+/* urgh. why are those needed? */
+
+EOLIAN void
+_evas_text_efl_gfx_filter_program_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED, const char *code)
+{
+ pd->has_filter = (code != NULL);
+ eo_do_super(obj, MY_CLASS, efl_gfx_filter_program_set(code));
+}
+
+EOLIAN const char *
+_evas_text_efl_gfx_filter_program_get(Eo *obj, Evas_Text_Data *pd EINA_UNUSED)
+{
+ const char *code;
+ return eo_do_super_ret(obj, MY_CLASS, code, efl_gfx_filter_program_get());
+}
+
+EOLIAN void
+_evas_text_efl_gfx_filter_source_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED, const char *name, Efl_Gfx_Base *source)
+{
+ eo_do_super(obj, MY_CLASS, efl_gfx_filter_source_set(name, source));
+}
+
+EOLIAN void
+_evas_text_efl_gfx_filter_source_get(Eo *obj, Evas_Text_Data *pd EINA_UNUSED, const char *name, Efl_Gfx_Base **source)
+{
+ eo_do_super(obj, MY_CLASS, efl_gfx_filter_source_get(name, source));
+}
+
+EOLIAN void
+_evas_text_efl_gfx_filter_state_set(Eo *obj, Evas_Text_Data *pd EINA_UNUSED,
+ const char *cur_state, double cur_val,
+ const char *next_state, double next_val, double pos)
+{
+ eo_do_super(obj, MY_CLASS, efl_gfx_filter_state_set(cur_state, cur_val, next_state, next_val, pos));
+}
+
+
+
#include "canvas/evas_text.eo.c"
-class Evas.Text (Evas.Object, Efl.Text, Efl.Text_Properties)
+class Evas.Text (Evas.Object, Efl.Text, Efl.Text_Properties, Evas.Filter)
{
legacy_prefix: evas_object_text;
eo_prefix: evas_obj_text;
a: int; /*@ The alpha component of the given color. */
}
}
- @property 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"
- */
- legacy: null;
- }
- values {
- program: const(char)*; /*@ 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 */
- }
- }
- @property 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).
-
- @since 1.9
- @note EXPERIMENTAL FEATURE. This is an unstable API,
- please use only for testing purposes.
- @see @ref evasfiltersref "Evas filters reference" */
- legacy: null;
- }
- values {
- name: const(char)*; /*@ Object name as used in the program code */
- eobj: Evas.Object *; /*@ Eo object to use through proxy rendering */
- }
- }
- @property filter_state {
- set {
- /*@ Set the current state of the filter (for use from Edje)
-
- @internal
- @since 1.15
- */
- legacy: null;
- }
- values {
- cur_state: const(char)*;
- cur_val: double(0.0);
- next_state: const(char)*;
- next_val: double(0.0);
- animpos: double(0.0);
- }
- }
@property max_descent {
get {
return: Evas.Coord;
Efl.Text_Properties.font.set;
Efl.Text_Properties.font_source.get;
Efl.Text_Properties.font_source.set;
+ Efl.Gfx.Filter.program.set;
+ Efl.Gfx.Filter.program.get;
+ Efl.Gfx.Filter.source_set;
+ Efl.Gfx.Filter.source_get;
+ Efl.Gfx.Filter.state.set;
+ Evas.Filter.dirty;
+ Evas.Filter.input_render;
}
}
void evas_model_set_from_surface_primitive(Evas_Canvas3D_Mesh *mesh, int frame, Evas_Canvas3D_Surface_Func func, int precision, Evas_Vec2 tex_scale);
void evas_model_set_from_terrain_primitive(Evas_Canvas3D_Mesh *mesh, int frame, int precision, Evas_Vec2 tex_scale);
+/* Filter functions */
+Eina_Bool evas_filter_object_render(Eo *eo_obj, Evas_Object_Protected_Data *obj, void *output, void *context, void *surface, int x, int y, Eina_Bool do_async, Eina_Bool alpha);
+
extern int _evas_alloc_error;
extern int _evas_event_counter;
// Don't test proxy cases here.
if (tc->source) continue;
- eo_do(to, evas_obj_text_filter_program_set(tc->code));
+ eo_do(to, efl_gfx_filter_program_set(tc->code));
evas_object_text_style_pad_get(to, &l, &r, &t, &b);
evas_object_geometry_get(to, NULL, NULL, &W, &H);
//fprintf(stderr, "Case %d: %dx%d for padding %d,%d,%d,%d\n", k, W, H, l, r, t, b);
evas_object_show(o);
eo_do(to,
efl_gfx_color_set(255, 255, 255, 255),
- evas_obj_text_filter_source_set(tc->source, o),
- evas_obj_text_filter_program_set(tc->code));
+ efl_gfx_filter_source_set(tc->source, o),
+ efl_gfx_filter_program_set(tc->code));
}
else
{
eo_do(to,
efl_gfx_color_set(255, 255, 255, 255),
- evas_obj_text_filter_program_set(tc->code));
+ efl_gfx_filter_program_set(tc->code));
}
evas_object_geometry_get(to, NULL, NULL, &w, &h);