Evas filters: Add fill command

This will simply clear the target buffer with the specified color.
This commit is contained in:
Jean-Philippe Andre 2013-12-12 17:46:46 +09:00
parent 0a450b3ace
commit 109894bb56
4 changed files with 156 additions and 1 deletions

View File

@ -18,7 +18,13 @@
static void _buffer_free(Evas_Filter_Buffer *fb);
static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd);
#ifdef CLAMP
# undef CLAMP
#endif
#define CLAMP(a,b,c) MIN(MAX((b),(a)),(c))
#define DRAW_COLOR_SET(r, g, b, a) do { cmd->draw.R = r; cmd->draw.G = g; cmd->draw.B = b; cmd->draw.A = a; } while (0)
#define DRAW_CLIP_SET(x, y, w, h) do { cmd->draw.clipx = x; cmd->draw.clipy = y; cmd->draw.clipw = w; cmd->draw.cliph = h; } while (0)
typedef struct _Evas_Filter_Thread_Command Evas_Filter_Thread_Command;
struct _Evas_Filter_Thread_Command
@ -537,6 +543,36 @@ _filter_buffer_unlock_all(Evas_Filter_Context *ctx)
buf->locked = EINA_FALSE;
}
int
evas_filter_command_fill_add(Evas_Filter_Context *ctx, void *draw_context,
int bufid)
{
Evas_Filter_Command *cmd;
Evas_Filter_Buffer *buf = NULL;
int R, G, B, A, cx, cy, cw, ch;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
EINA_SAFETY_ON_NULL_RETURN_VAL(draw_context, -1);
buf = _filter_buffer_get(ctx, bufid);
if (!buf)
{
ERR("Buffer %d does not exist.", bufid);
return -1;
}
cmd = _command_new(ctx, EVAS_FILTER_MODE_FILL, buf, NULL, NULL);
if (!cmd) return -1;
ENFN->context_color_get(ENDT, draw_context, &R, &G, &B, &A);
DRAW_COLOR_SET(R, G, B, A);
ENFN->context_clip_get(ENDT, draw_context, &cx, &cy, &cw, &ch);
DRAW_CLIP_SET(cx, cy, cw, ch);
return cmd->id;
}
int
evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx,
int inbuf, int outbuf, Evas_Filter_Blur_Type type,
@ -551,6 +587,7 @@ evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *drawctx,
int ret = 0, id;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
EINA_SAFETY_ON_NULL_RETURN_VAL(drawctx, -1);
switch (type)
{
@ -1005,6 +1042,61 @@ end:
return cmdid;
}
static Eina_Bool
_fill_cpu(Evas_Filter_Command *cmd)
{
Evas_Filter_Buffer *fb = cmd->input;
int step = fb->alpha_only ? sizeof(DATA8) : sizeof(DATA32);
int x = MAX(0, cmd->draw.clipx);
int y = MAX(0, cmd->draw.clipy);
DATA8 *ptr = ((RGBA_Image *) fb->backing)->mask.data;
int w, h, k, j;
if (cmd->draw.clipw)
w = MIN(cmd->draw.clipw, fb->w);
else
w = fb->w - x;
if (cmd->draw.cliph)
h = MIN(cmd->draw.cliph, fb->h);
else
h = fb->h - y;
ptr += y * step * fb->w;
if ((fb->alpha_only)
|| (!cmd->draw.R && !cmd->draw.G && !cmd->draw.B && !cmd->draw.A)
|| ((cmd->draw.R == 0xff) && (cmd->draw.G == 0xff)
&& (cmd->draw.B == 0xff) && (cmd->draw.A == 0xff)))
{
for (k = 0; k < h; k++)
{
memset(ptr + (x * step), cmd->draw.A, step * w);
ptr += step * fb->w;
}
}
else
{
DATA32 *dst = ((DATA32 *) ptr) + x;
DATA32 color = ARGB_JOIN(cmd->draw.A, cmd->draw.R, cmd->draw.G, cmd->draw.B);
for (k = 0; k < h; k++)
{
for (j = 0; j < w; j++)
*dst++ = color;
dst += fb->w;
}
}
return EINA_TRUE;
}
Evas_Filter_Apply_Func
evas_filter_fill_cpu_func_get(Evas_Filter_Command *cmd)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, NULL);
return _fill_cpu;
}
/* 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 */
void
@ -1130,6 +1222,9 @@ _filter_command_run(Evas_Filter_Command *cmd)
case EVAS_FILTER_MODE_DISPLACE:
func = evas_filter_displace_cpu_func_get(cmd);
break;
case EVAS_FILTER_MODE_FILL:
func = evas_filter_fill_cpu_func_get(cmd);
break;
case EVAS_FILTER_MODE_MASK:
func = evas_filter_mask_cpu_func_get(cmd);
break;

View File

@ -860,6 +860,25 @@ _displace_instruction_prepare(Evas_Filter_Instruction *instr)
return EINA_TRUE;
}
static Eina_Bool
_fill_instruction_prepare(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, "fill"), EINA_FALSE);
/*
* fill [dst=]BUFFER [color=COLOR]
* Works with both Alpha and RGBA.
*/
instr->type = EVAS_FILTER_MODE_BUFFER;
_instruction_param_seq_add(instr, "dst", VT_BUFFER, NULL);
_instruction_param_seq_add(instr, "color", VT_COLOR, 0x0);
return EINA_TRUE;
}
static void
_grow_padding_update(Evas_Filter_Instruction *instr,
int *l, int *r, int *t, int *b)
@ -941,6 +960,8 @@ _instruction_create(const char *name)
prepare = _curve_instruction_prepare;
else if (!strcasecmp(name, "displace"))
prepare = _displace_instruction_prepare;
else if (!strcasecmp(name, "fill"))
prepare = _fill_instruction_prepare;
else if (!strcasecmp(name, "grow"))
prepare = _grow_instruction_prepare;
else if (!strcasecmp(name, "mask"))
@ -1318,6 +1339,30 @@ _instr2cmd_displace(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
return cmdid;
}
static int
_instr2cmd_fill(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
Evas_Filter_Instruction *instr, void *dc)
{
const char *bufname;
Buffer *buf;
int R, G, B, A;
DATA32 color;
int cmdid;
bufname = _instruction_param_gets(instr, "dst", NULL);
color = _instruction_param_getc(instr, "color", NULL);
// TODO/FIXME: Add clip info
buf = _buffer_get(pgm, bufname);
ENFN->context_color_get(ENDT, dc, &R, &G, &B, &A);
ENFN->context_color_set(ENDT, dc, R_VAL(&color), G_VAL(&color), B_VAL(&color), A_VAL(&color));
cmdid = evas_filter_command_fill_add(ctx, dc, buf->cid);
ENFN->context_color_set(ENDT, dc, R, G, B, A);
return cmdid;
}
static int
_instr2cmd_grow(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
Evas_Filter_Instruction *instr, void *dc)
@ -1389,6 +1434,9 @@ _command_from_instruction(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
case EVAS_FILTER_MODE_DISPLACE:
instr2cmd = _instr2cmd_displace;
break;
case EVAS_FILTER_MODE_FILL:
instr2cmd = _instr2cmd_fill;
break;
case EVAS_FILTER_MODE_GROW:
instr2cmd = _instr2cmd_grow;
break;

View File

@ -130,6 +130,7 @@ Evas_Filter_Apply_Func evas_filter_blur_cpu_func_get(Evas_Filter_Command *cmd)
Evas_Filter_Apply_Func evas_filter_bump_map_cpu_func_get(Evas_Filter_Command *cmd);
Evas_Filter_Apply_Func evas_filter_curve_cpu_func_get(Evas_Filter_Command *cmd);
Evas_Filter_Apply_Func evas_filter_displace_cpu_func_get(Evas_Filter_Command *cmd);
Evas_Filter_Apply_Func evas_filter_fill_cpu_func_get(Evas_Filter_Command *cmd);
Evas_Filter_Apply_Func evas_filter_mask_cpu_func_get(Evas_Filter_Command *cmd);
/* Utility functions */

View File

@ -26,6 +26,7 @@ enum _Evas_Filter_Mode
EVAS_FILTER_MODE_BLUR, /**< @see Evas_Filter_Blur_Type */
EVAS_FILTER_MODE_CURVE, /**< Apply color curve */
EVAS_FILTER_MODE_DISPLACE, /**< Apply XY displacement based on RG mask */
EVAS_FILTER_MODE_FILL, /**< Fill a buffer with a solid color */
EVAS_FILTER_MODE_MASK, /**< Apply Alpha or RGBA texture on image */
EVAS_FILTER_MODE_BUMP, /**< Apply bump mapping (light effect) */
EVAS_FILTER_MODE_LAST
@ -125,6 +126,17 @@ int evas_filter_command_blend_add(Evas_Filter_Context *ctx,
*/
int evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, Evas_Filter_Blur_Type type, int dx, int dy, int ox, int oy);
/**
* @brief Fill a buffer with the current color
* @param ctx Current filter chain
* @param draw_context Current Evas draw context. Current color is used when buf is RGBA, and clip is used to specify the fill area.
* @param buf Buffer: ALPHA or RGBA
* @return Filter command ID or -1 in case of error
* @note The current draw context's render operation is ignored (always uses COPY mode).
*/
int evas_filter_command_fill_add(Evas_Filter_Context *ctx, void *draw_context, int buf);
int evas_filter_command_curve_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, DATA8 *curve /* 256 elements */, Evas_Filter_Channel channel);
/**
* @brief Grow/Shrink an image, as defined in image processing (this is not a scale algorithm!)
* @param ctx Current filter chain
@ -136,7 +148,6 @@ int evas_filter_command_blur_add(Evas_Filter_Context *ctx,
* @return Filter command ID or -1 in case of error
*/
int evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int radius, Eina_Bool smooth);
int evas_filter_command_curve_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, DATA8 *curve /* 256 elements */, Evas_Filter_Channel channel);
/**
* @brief Apply a displacement map to a buffer. This will move pixels from the source to the destination based on pixel per pixel offset, as defined in the displacement map