kimcinoo pushed a commit to branch master.

http://git.enlightenment.org/core/efl.git/commit/?id=51169ac325c59912417412b9138eeacbbb6a93bc

commit 51169ac325c59912417412b9138eeacbbb6a93bc
Author: Shinwoo Kim <cinoo....@samsung.com>
Date:   Tue Nov 5 10:44:58 2019 +0900

    evas filter: Implement inverse color filter
    
    Summary: This is the first version of inverse color filter both GL and SW.
    
    Test Plan:
    1. Create filter_example with following .
    efl_gfx_filter_program_set(image, "inverse_color ()", "inverse color");
    
    2. Run.
    ./filter_example (Use ELM_ACCEL=gl for GL engine)
    
    Reviewers: Hermet, jsuya
    
    Reviewed By: Hermet
    
    Subscribers: cedric, #reviewers, #committers
    
    Tags: #efl
    
    Differential Revision: https://phab.enlightenment.org/D10335
---
 src/lib/evas/filters/evas_filter.c                 | 22 +++++
 src/lib/evas/filters/evas_filter_parser.c          | 39 +++++++++
 src/lib/evas/include/evas_filter.h                 | 12 +++
 src/lib/evas/software_generic/filters/meson.build  |  1 +
 .../evas/engines/gl_common/evas_gl_common.h        |  4 +-
 .../evas/engines/gl_common/evas_gl_context.c       | 93 ++++++++++++++++++++++
 .../evas/engines/gl_common/evas_gl_shader.c        |  7 +-
 .../engines/gl_common/shader/evas_gl_shaders.x     |  3 +
 .../evas/engines/gl_common/shader/fragment.glsl    |  4 +
 src/modules/evas/engines/gl_generic/evas_engine.c  |  1 +
 .../engines/gl_generic/filters/gl_engine_filter.h  |  1 +
 .../gl_generic/filters/gl_filter_inverse_color.c   | 53 ++++++++++++
 src/modules/evas/engines/gl_generic/meson.build    |  1 +
 .../evas/engines/software_generic/evas_engine.c    |  1 +
 .../software_generic/filters/evas_engine_filter.h  |  1 +
 .../filters/evas_filter_inverse_color.c            | 57 +++++++++++++
 16 files changed, 298 insertions(+), 2 deletions(-)

diff --git a/src/lib/evas/filters/evas_filter.c 
b/src/lib/evas/filters/evas_filter.c
index 36c9c5d2b1..c9d8005e26 100644
--- a/src/lib/evas/filters/evas_filter.c
+++ b/src/lib/evas/filters/evas_filter.c
@@ -1619,6 +1619,28 @@ evas_filter_command_grayscale_add(Evas_Filter_Context 
*ctx,
    return cmd;
 }
 
+Evas_Filter_Command *
+evas_filter_command_inverse_color_add(Evas_Filter_Context *ctx,
+                                     void *draw_context EINA_UNUSED,
+                                     int inbuf, int outbuf)
+{
+   Evas_Filter_Command *cmd;
+   Evas_Filter_Buffer *in, *out;
+
+   EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, NULL);
+
+   in = _filter_buffer_get(ctx, inbuf);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(in, NULL);
+
+   out = _filter_buffer_get(ctx, outbuf);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL);
+
+   cmd = _command_new(ctx, EVAS_FILTER_MODE_INVERSE_COLOR, in, NULL, out);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(out, NULL);
+
+   return cmd;
+}
+
 void
 evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, 
Eina_Rectangle rect)
 {
diff --git a/src/lib/evas/filters/evas_filter_parser.c 
b/src/lib/evas/filters/evas_filter_parser.c
index 6d89a3518f..6654841061 100644
--- a/src/lib/evas/filters/evas_filter_parser.c
+++ b/src/lib/evas/filters/evas_filter_parser.c
@@ -1809,6 +1809,26 @@ _grayscale_instruction_prepare(Evas_Filter_Program *pgm, 
Evas_Filter_Instruction
    return EINA_TRUE;
 }
 
+/**
+  @page evasfiltersref
+  Apply inverse color
+  TODO: write down more information
+ */
+
+static Eina_Bool
+_inverse_color_instruction_prepare(Evas_Filter_Program *pgm, 
Evas_Filter_Instruction *instr)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(instr, EINA_FALSE);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(instr->name, EINA_FALSE);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(!strcasecmp(instr->name, "inverse_color"), 
EINA_FALSE);
+
+   instr->type = EVAS_FILTER_MODE_INVERSE_COLOR;
+   _instruction_param_seq_add(instr, "src", VT_BUFFER, _buffer_get(pgm, 
"input"));
+   _instruction_param_seq_add(instr, "dst", VT_BUFFER, _buffer_get(pgm, 
"output"));
+
+   return EINA_TRUE;
+}
+
 static int
 _padding_set_padding_update(Evas_Filter_Program *pgm,
                             Evas_Filter_Instruction *instr,
@@ -2270,6 +2290,7 @@ LUA_GENERIC_FUNCTION(mask)
 LUA_GENERIC_FUNCTION(padding_set)
 LUA_GENERIC_FUNCTION(transform)
 LUA_GENERIC_FUNCTION(grayscale)
+LUA_GENERIC_FUNCTION(inverse_color)
 
 static const luaL_Reg _lua_buffer_metamethods[] = {
    { "__call", _lua_buffer_new },
@@ -2507,6 +2528,7 @@ _lua_state_create(Evas_Filter_Program *pgm)
    PUSH_LUA_FUNCTION(padding_set)
    PUSH_LUA_FUNCTION(transform)
    PUSH_LUA_FUNCTION(grayscale)
+   PUSH_LUA_FUNCTION(inverse_color)
 
    for (unsigned k = 0; k < (sizeof(fill_modes) / sizeof(fill_modes[0])); k++)
      {
@@ -3439,6 +3461,20 @@ _instr2cmd_grayscale(Evas_Filter_Context *ctx,
    return evas_filter_command_grayscale_add(ctx, dc, src->cid, dst->cid);
 }
 
+static Evas_Filter_Command *
+_instr2cmd_inverse_color(Evas_Filter_Context *ctx,
+                         Evas_Filter_Instruction *instr, void *dc)
+{
+   Buffer *src, *dst;
+
+   src = _instruction_param_getbuf(instr, "src", NULL);
+   dst = _instruction_param_getbuf(instr, "dst", NULL);
+   INSTR_PARAM_CHECK(src);
+   INSTR_PARAM_CHECK(dst);
+
+   return evas_filter_command_inverse_color_add(ctx, dc, src->cid, dst->cid);
+}
+
 static Eina_Bool
 _command_from_instruction(Evas_Filter_Context *ctx,
                           Evas_Filter_Instruction *instr, void *dc)
@@ -3478,6 +3514,9 @@ _command_from_instruction(Evas_Filter_Context *ctx,
       case EVAS_FILTER_MODE_GRAYSCALE:
         instr2cmd = _instr2cmd_grayscale;
         break;
+      case EVAS_FILTER_MODE_INVERSE_COLOR:
+        instr2cmd = _instr2cmd_inverse_color;
+        break;
       case EVAS_FILTER_MODE_PADDING_SET:
       case EVAS_FILTER_MODE_BUFFER:
         return EINA_TRUE;
diff --git a/src/lib/evas/include/evas_filter.h 
b/src/lib/evas/include/evas_filter.h
index 8dab0a9a34..5a22c2b6ae 100644
--- a/src/lib/evas/include/evas_filter.h
+++ b/src/lib/evas/include/evas_filter.h
@@ -70,6 +70,7 @@ enum _Evas_Filter_Mode
    EVAS_FILTER_MODE_TRANSFORM,    /**< Apply a simple geometrical 
transformation */
    EVAS_FILTER_MODE_PADDING_SET,  /**< Special padding_set instruction to 
force a specific padding value */
    EVAS_FILTER_MODE_GRAYSCALE,    /**< Leave only grayscale information */
+   EVAS_FILTER_MODE_INVERSE_COLOR,/**< Apply inverse color */
    EVAS_FILTER_MODE_LAST
 };
 
@@ -318,6 +319,17 @@ Evas_Filter_Command     
*evas_filter_command_transform_add(Evas_Filter_Context *
  */
 Evas_Filter_Command     *evas_filter_command_grayscale_add(Evas_Filter_Context 
*ctx, void *draw_context, int inbuf, int outbuf);
 
+/**
+ * @brief Apply inverse color of the buffer
+ * @param ctx            Current filter chain
+ * @param draw_context   Current Evas draw context (ignored)
+ * @param inbuf          Input buffer (Alpha or RGBA)
+ * @param outbuf         Output buffer (Alpha or RGBA), same size as inbuf
+ * @return               Filter command or NULL in case of error
+ * @internal
+ */
+Evas_Filter_Command     
*evas_filter_command_inverse_color_add(Evas_Filter_Context *ctx, void 
*draw_context, int inbuf, int outbuf);
+
 /* Simple binding between a filter object and its sources */
 struct _Evas_Filter_Proxy_Binding
 {
diff --git a/src/lib/evas/software_generic/filters/meson.build 
b/src/lib/evas/software_generic/filters/meson.build
index 17c7bce8c2..abe0594c99 100644
--- a/src/lib/evas/software_generic/filters/meson.build
+++ b/src/lib/evas/software_generic/filters/meson.build
@@ -11,6 +11,7 @@ raw_evas_src = [
   'evas_filter_mask.c',
   'evas_filter_transform.c',
   'evas_filter_grayscale.c',
+  'evas_filter_inverse_color.c',
 ]
 
 foreach file : raw_evas_src
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 b2cf74bee5..0cc7f30573 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_common.h
+++ b/src/modules/evas/engines/gl_common/evas_gl_common.h
@@ -266,7 +266,8 @@ enum _Shader_Type {
    SHD_FILTER_CURVE,
    SHD_FILTER_BLUR_X,
    SHD_FILTER_BLUR_Y,
-   SHD_FILTER_GRAYSCALE
+   SHD_FILTER_GRAYSCALE,
+   SHD_FILTER_INVERSE_COLOR
 };
 
 #define ARRAY_BUFFER_USE 500
@@ -682,6 +683,7 @@ void              
evas_gl_common_filter_blur_push(Evas_Engine_GL_Context *gc, Ev
                                                   double dx, double dy, double 
dw, double dh, const double * const values, const double * const offsets, int 
count, double radius,
                                                   Eina_Bool horiz, Eina_Bool 
alphaonly);
 void              evas_gl_common_filter_grayscale_push(Evas_Engine_GL_Context 
*gc, Evas_GL_Texture *tex, int x, int y, int w, int h);
+void              
evas_gl_common_filter_inverse_color_push(Evas_Engine_GL_Context *gc, 
Evas_GL_Texture *tex, int x, int y, int w, int h);
 
 int               evas_gl_common_shader_program_init(Evas_GL_Shared *shared);
 void              evas_gl_common_shader_program_shutdown(Evas_GL_Shared 
*shared);
diff --git a/src/modules/evas/engines/gl_common/evas_gl_context.c 
b/src/modules/evas/engines/gl_common/evas_gl_context.c
index 9178d3f6b8..6637a839df 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_context.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_context.c
@@ -3771,6 +3771,99 @@ 
evas_gl_common_filter_grayscale_push(Evas_Engine_GL_Context *gc,
    if (!nomul)
      PUSH_6_COLORS(pn, r, g, b, a);
 }
+
+void
+evas_gl_common_filter_inverse_color_push(Evas_Engine_GL_Context *gc,
+                                         Evas_GL_Texture *tex,
+                                         int x, int y, int w, int h)
+{
+   double ox1, oy1, ox2, oy2, ox3, oy3, ox4, oy4, pw, ph;
+   GLfloat tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4;
+   GLfloat offsetx, offsety;
+   int r, g, b, a, nomul = 0, pn;
+   Evas_GL_Program *prog;
+   Eina_Bool blend = EINA_TRUE;
+   Eina_Bool smooth = EINA_TRUE;
+   Shader_Type type = SHD_FILTER_INVERSE_COLOR;
+
+   r = R_VAL(&gc->dc->mul.col);
+   g = G_VAL(&gc->dc->mul.col);
+   b = B_VAL(&gc->dc->mul.col);
+   a = A_VAL(&gc->dc->mul.col);
+   if (gc->dc->render_op == EVAS_RENDER_COPY)
+     blend = EINA_FALSE;
+
+   prog = evas_gl_common_shader_program_get(gc, type, NULL, 0, r, g, b, a,
+                                            w, h, w, h, smooth, tex, 
EINA_FALSE,
+                                            NULL, EINA_FALSE, EINA_FALSE, 0, 0,
+                                            EINA_FALSE, NULL, &nomul, NULL);
+
+   _filter_data_flush(gc, prog);
+   EINA_SAFETY_ON_NULL_RETURN(prog);
+
+   pn = _evas_gl_common_context_push(type, gc, tex, NULL, prog,
+                                     x, y, w, h, blend, smooth,
+                                     0, 0, 0, 0, 0, EINA_FALSE);
+
+   gc->pipe[pn].region.type = type;
+   gc->pipe[pn].shader.prog = prog;
+   gc->pipe[pn].shader.cur_tex = tex->pt->texture;
+   gc->pipe[pn].shader.cur_texm = 0;
+   gc->pipe[pn].shader.tex_target = GL_TEXTURE_2D;
+   gc->pipe[pn].shader.smooth = smooth;
+   gc->pipe[pn].shader.mask_smooth = 0;
+   gc->pipe[pn].shader.blend = blend;
+   gc->pipe[pn].shader.render_op = gc->dc->render_op;
+   gc->pipe[pn].shader.clip = 0;
+   gc->pipe[pn].shader.cx = 0;
+   gc->pipe[pn].shader.cy = 0;
+   gc->pipe[pn].shader.cw = 0;
+   gc->pipe[pn].shader.ch = 0;
+   gc->pipe[pn].array.line = 0;
+   gc->pipe[pn].array.use_vertex = 1;
+   gc->pipe[pn].array.use_color = !nomul;
+   gc->pipe[pn].array.use_texuv = 1;
+   gc->pipe[pn].array.use_texuv2 = 0;
+   gc->pipe[pn].array.use_texuv3 = 0;
+   gc->pipe[pn].array.use_texsam = 0;
+   gc->pipe[pn].array.use_mask = 0;
+   gc->pipe[pn].array.use_masksam = 0;
+
+   pipe_region_expand(gc, pn, x, y, w, h);
+   PIPE_GROW(gc, pn, 6);
+
+   _filter_data_alloc(gc, pn, 0);
+
+   pw = tex->pt->w;
+   ph = tex->pt->h;
+
+   ox1 = x;
+   oy1 = y;
+   ox2 = x + w;
+   oy2 = y;
+   ox3 = x + w;
+   oy3 = y + h;
+   ox4 = x;
+   oy4 = y + h;
+
+   offsetx = tex->x;
+   offsety = tex->y;
+
+   tx1 = ((double)(offsetx) + ox1) / pw;
+   ty1 = ((double)(offsety) + oy1) / ph;
+   tx2 = ((double)(offsetx) + ox2) / pw;
+   ty2 = ((double)(offsety) + oy2) / ph;
+   tx3 = ((double)(offsetx) + ox3) / pw;
+   ty3 = ((double)(offsety) + oy3) / ph;
+   tx4 = ((double)(offsetx) + ox4) / pw;
+   ty4 = ((double)(offsety) + oy4) / ph;
+
+   PUSH_6_VERTICES(pn, x, y, w, h);
+   PUSH_6_QUAD(pn, tx1, ty1, tx2, ty2, tx3, ty3, tx4, ty4);
+
+   if (!nomul)
+     PUSH_6_COLORS(pn, r, g, b, a);
+}
 // ----------------------------------------------------------------------------
 
 EAPI void
diff --git a/src/modules/evas/engines/gl_common/evas_gl_shader.c 
b/src/modules/evas/engines/gl_common/evas_gl_shader.c
index 7c338674ec..5702ce49c3 100644
--- a/src/modules/evas/engines/gl_common/evas_gl_shader.c
+++ b/src/modules/evas/engines/gl_common/evas_gl_shader.c
@@ -46,8 +46,9 @@ typedef enum {
    SHADER_FLAG_FILTER_DIR_Y      = (1 << 24),
    SHADER_FLAG_FILTER_ALPHA_ONLY = (1 << 25),
    SHADER_FLAG_FILTER_GRAYSCALE  = (1 << 26),
+   SHADER_FLAG_FILTER_INVERSE_COLOR  = (1 << 27),
 } Shader_Flag;
-#define SHADER_FLAG_COUNT 27
+#define SHADER_FLAG_COUNT 28
 
 static const char *_shader_flags[SHADER_FLAG_COUNT] = {
    "TEX",
@@ -77,6 +78,7 @@ static const char *_shader_flags[SHADER_FLAG_COUNT] = {
    "FILTER_DIR_Y",
    "ALPHA_ONLY",
    "FILTER_GRAYSCALE",
+   "FILTER_INVERSE_COLOR",
 };
 
 static Eina_Bool compiler_released = EINA_FALSE;
@@ -829,6 +831,9 @@ evas_gl_common_shader_flags_get(Evas_GL_Shared *shared, 
Shader_Type type,
       case SHD_FILTER_GRAYSCALE:
         flags |= SHADER_FLAG_FILTER_GRAYSCALE;
         break;
+      case SHD_FILTER_INVERSE_COLOR:
+        flags |= SHADER_FLAG_FILTER_INVERSE_COLOR;
+        break;
       default:
         CRI("Impossible shader type.");
         return 0;
diff --git a/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x 
b/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x
index 73ca4bef11..e5c16b5b75 100644
--- a/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x
+++ b/src/modules/evas/engines/gl_common/shader/evas_gl_shaders.x
@@ -217,6 +217,9 @@ static const char fragment_glsl[] =
    "#ifdef SHD_FILTER_GRAYSCALE\n"
    "   c.rgb = 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;\n"
    "#endif\n"
+   "#ifdef SHD_FILTER_INVERSE_COLOR\n"
+   "   c.rgb = c.a - c.rgb;\n"
+   "#endif\n"
    "#ifndef SHD_FILTER_BLUR\n"
    "   gl_FragColor =\n"
    "       c\n"
diff --git a/src/modules/evas/engines/gl_common/shader/fragment.glsl 
b/src/modules/evas/engines/gl_common/shader/fragment.glsl
index 39fccf1119..b51bbb4d38 100644
--- a/src/modules/evas/engines/gl_common/shader/fragment.glsl
+++ b/src/modules/evas/engines/gl_common/shader/fragment.glsl
@@ -234,6 +234,10 @@ vec4 fetch_pixel(float ox, float oy)
    c.rgb = 0.3 * c.r + 0.59 * c.g + 0.11 * c.b;
 #endif
 
+#ifdef SHD_FILTER_INVERSE_COLOR
+   c.rgb = c.a - c.rgba;
+#endif
+
 #ifndef SHD_FILTER_BLUR
 
    gl_FragColor =
diff --git a/src/modules/evas/engines/gl_generic/evas_engine.c 
b/src/modules/evas/engines/gl_generic/evas_engine.c
index 3428cf5620..2ca2d5b634 100644
--- a/src/modules/evas/engines/gl_generic/evas_engine.c
+++ b/src/modules/evas/engines/gl_generic/evas_engine.c
@@ -3128,6 +3128,7 @@ _gfx_filter_func_get(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd)
       case EVAS_FILTER_MODE_MASK: funcptr = gl_filter_mask_func_get(re, cmd); 
break;
       //case EVAS_FILTER_MODE_TRANSFORM: funcptr = 
gl_filter_transform_func_get(re, cmd); break;
       case EVAS_FILTER_MODE_GRAYSCALE: funcptr = 
gl_filter_grayscale_func_get(re, cmd); break;
+      case EVAS_FILTER_MODE_INVERSE_COLOR: funcptr = 
gl_filter_inverse_color_func_get(re, cmd); break;
       default: return NULL;
      }
 
diff --git a/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h 
b/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h
index b1045d019e..5b5d67799c 100644
--- a/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h
+++ b/src/modules/evas/engines/gl_generic/filters/gl_engine_filter.h
@@ -18,6 +18,7 @@ GL_Filter_Apply_Func 
gl_filter_fill_func_get(Render_Engine_GL_Generic *re, Evas_
 GL_Filter_Apply_Func gl_filter_mask_func_get(Render_Engine_GL_Generic *re, 
Evas_Filter_Command *cmd);
 //GL_Filter_Apply_Func gl_filter_transform_func_get(Evas_Filter_Command *cmd);
 GL_Filter_Apply_Func gl_filter_grayscale_func_get(Render_Engine_GL_Generic 
*re, Evas_Filter_Command *cmd);
+GL_Filter_Apply_Func gl_filter_inverse_color_func_get(Render_Engine_GL_Generic 
*re, Evas_Filter_Command *cmd);
 
 #undef DBG
 #undef INF
diff --git 
a/src/modules/evas/engines/gl_generic/filters/gl_filter_inverse_color.c 
b/src/modules/evas/engines/gl_generic/filters/gl_filter_inverse_color.c
new file mode 100644
index 0000000000..8319db69b0
--- /dev/null
+++ b/src/modules/evas/engines/gl_generic/filters/gl_filter_inverse_color.c
@@ -0,0 +1,53 @@
+#include "gl_engine_filter.h"
+
+static Eina_Bool
+_gl_filter_inverse_color(Render_Engine_GL_Generic *re, Evas_Filter_Command 
*cmd)
+{
+   Evas_Engine_GL_Context *gc;
+   Evas_GL_Image *image, *surface;
+   RGBA_Draw_Context *dc_save;
+   int w, h;
+
+   w = cmd->input->w;
+   h = cmd->input->h;
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(w == cmd->output->w, EINA_FALSE);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL(h == cmd->output->h, EINA_FALSE);
+
+   image = evas_ector_buffer_drawable_image_get(cmd->input->buffer);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(image, EINA_FALSE);
+
+   surface = evas_ector_buffer_render_image_get(cmd->output->buffer);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(surface, EINA_FALSE);
+
+   gc = gl_generic_context_find(re, 1);
+   evas_gl_common_context_target_surface_set(gc, surface);
+
+   dc_save = gc->dc;
+   gc->dc = evas_common_draw_context_new();
+   evas_common_draw_context_set_multiplier(gc->dc, cmd->draw.R, cmd->draw.G, 
cmd->draw.B, cmd->draw.A);
+
+   if (cmd->input == cmd->output)
+     gc->dc->render_op = EVAS_RENDER_COPY;
+   else
+     gc->dc->render_op = _gfx_to_evas_render_op(cmd->draw.rop);
+
+   evas_gl_common_filter_inverse_color_push(gc, image->tex, 0, 0, w, h);
+
+   evas_common_draw_context_free(gc->dc);
+   gc->dc = dc_save;
+
+   evas_ector_buffer_engine_image_release(cmd->input->buffer, image);
+   evas_ector_buffer_engine_image_release(cmd->output->buffer, surface);
+
+   return EINA_TRUE;
+}
+
+GL_Filter_Apply_Func
+gl_filter_inverse_color_func_get(Render_Engine_GL_Generic *re EINA_UNUSED, 
Evas_Filter_Command *cmd)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
+
+   return _gl_filter_inverse_color;
+}
diff --git a/src/modules/evas/engines/gl_generic/meson.build 
b/src/modules/evas/engines/gl_generic/meson.build
index d137eb26ef..6f7e9dc259 100644
--- a/src/modules/evas/engines/gl_generic/meson.build
+++ b/src/modules/evas/engines/gl_generic/meson.build
@@ -13,6 +13,7 @@ engine_src = files([
   join_paths('filters','gl_filter_fill.c'),
   join_paths('filters','gl_filter_mask.c'),
   join_paths('filters','gl_filter_grayscale.c'),
+  join_paths('filters','gl_filter_inverse_color.c'),
 ])
 common_engine_src = [
   'evas_gl_private.h',
diff --git a/src/modules/evas/engines/software_generic/evas_engine.c 
b/src/modules/evas/engines/software_generic/evas_engine.c
index 085f053b1d..404370db29 100644
--- a/src/modules/evas/engines/software_generic/evas_engine.c
+++ b/src/modules/evas/engines/software_generic/evas_engine.c
@@ -4545,6 +4545,7 @@ _gfx_filter_func_get(Evas_Filter_Command *cmd)
       case EVAS_FILTER_MODE_MASK: func = eng_filter_mask_func_get(cmd); break;
       case EVAS_FILTER_MODE_TRANSFORM: func = 
eng_filter_transform_func_get(cmd); break;
       case EVAS_FILTER_MODE_GRAYSCALE: func = 
eng_filter_grayscale_func_get(cmd); break;
+      case EVAS_FILTER_MODE_INVERSE_COLOR: func = 
eng_filter_inverse_color_func_get(cmd); break;
       default: return NULL;
      }
 
diff --git 
a/src/modules/evas/engines/software_generic/filters/evas_engine_filter.h 
b/src/modules/evas/engines/software_generic/filters/evas_engine_filter.h
index 33998f9344..bc6bbbdadc 100644
--- a/src/modules/evas/engines/software_generic/filters/evas_engine_filter.h
+++ b/src/modules/evas/engines/software_generic/filters/evas_engine_filter.h
@@ -14,5 +14,6 @@ Software_Filter_Func 
eng_filter_fill_func_get(Evas_Filter_Command *cmd);
 Software_Filter_Func eng_filter_mask_func_get(Evas_Filter_Command *cmd);
 Software_Filter_Func eng_filter_transform_func_get(Evas_Filter_Command *cmd);
 Software_Filter_Func eng_filter_grayscale_func_get(Evas_Filter_Command *cmd);
+Software_Filter_Func eng_filter_inverse_color_func_get(Evas_Filter_Command 
*cmd);
 
 #endif // EVAS_ENGINE_FILTER_H
diff --git 
a/src/modules/evas/engines/software_generic/filters/evas_filter_inverse_color.c 
b/src/modules/evas/engines/software_generic/filters/evas_filter_inverse_color.c
new file mode 100644
index 0000000000..8079e3adb5
--- /dev/null
+++ 
b/src/modules/evas/engines/software_generic/filters/evas_filter_inverse_color.c
@@ -0,0 +1,57 @@
+#include "evas_engine_filter.h"
+
+static Eina_Bool
+_evas_filter_inverse_color(Evas_Filter_Command *cmd)
+{
+   int sw, sh, dw, dh, x, y, slen, dlen;
+   unsigned int src_len, src_stride, dst_len, dst_stride;
+   Eina_Bool ret = EINA_FALSE;
+   DATA32 *ts, *td, *src = NULL, *dst = NULL;
+
+   ector_buffer_size_get(cmd->input->buffer, &sw, &sh);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL((sw > 0) && (sh > 0), ret);
+
+   ector_buffer_size_get(cmd->output->buffer, &dw, &dh);
+   EINA_SAFETY_ON_FALSE_RETURN_VAL((dw > 0) && (dh > 0), ret);
+
+   src = _buffer_map_all(cmd->input->buffer, &src_len, E_READ, E_ARGB, 
&src_stride);
+   EINA_SAFETY_ON_FALSE_GOTO(src, end);
+
+   dst = _buffer_map_all(cmd->output->buffer, &dst_len, E_WRITE, E_ARGB, 
&dst_stride);
+   EINA_SAFETY_ON_FALSE_GOTO(dst, end);
+
+   slen = src_stride / sizeof(*src);
+   dlen = dst_stride / sizeof(*dst);
+
+   ts = src;
+   td = dst;
+   for (y = 0; y < sh ; y++)
+     {
+        for (x = 0; x < sw; x++)
+          {
+             A_VAL(td + x) = A_VAL(ts + x);
+             R_VAL(td + x) = A_VAL(ts + x) - R_VAL(ts + x);
+             G_VAL(td + x) = A_VAL(ts + x) - G_VAL(ts + x);
+             B_VAL(td + x) = A_VAL(ts + x) - B_VAL(ts + x);
+          }
+          ts += slen;
+          td += dlen;
+     }
+
+   ret = EINA_TRUE;
+
+end:
+   if (src) ector_buffer_unmap(cmd->input->buffer, src, src_len);
+   if (dst) ector_buffer_unmap(cmd->output->buffer, dst, dst_len);
+   return ret;
+}
+
+Software_Filter_Func
+eng_filter_inverse_color_func_get(Evas_Filter_Command *cmd)
+{
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, NULL);
+   EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
+
+   return _evas_filter_inverse_color;
+}

-- 


Reply via email to