Evas filters: Implement fill with padding

Add parameters l, r, t, b to clip the fill area.
While l=x and t=y, the width and height of the clip are determined
at filter run-time, since we don't know the buffer size before.
This commit is contained in:
Jean-Philippe Andre 2014-01-02 18:44:01 +09:00
parent b5b6f6ef3c
commit 2da17927da
4 changed files with 66 additions and 21 deletions

View File

@ -24,7 +24,7 @@ static void _command_del(Evas_Filter_Context *ctx, Evas_Filter_Command *cmd);
#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)
#define DRAW_CLIP_SET(_x, _y, _w, _h) do { cmd->draw.clip.x = _x; cmd->draw.clip.y = _y; cmd->draw.clip.w = _w; cmd->draw.clip.h = _h; } while (0)
#define DRAW_FILL_SET(fmode) do { cmd->draw.fillmode = fmode; } while (0)
typedef struct _Evas_Filter_Thread_Command Evas_Filter_Thread_Command;
@ -791,8 +791,8 @@ evas_filter_command_blend_add(Evas_Filter_Context *ctx, void *drawctx,
cmd->draw.ox = ox;
cmd->draw.oy = oy;
cmd->draw.render_op = ENFN->context_render_op_get(ENDT, drawctx);
ENFN->context_clip_get(ENDT, drawctx, &cmd->draw.clipx, &cmd->draw.clipy,
&cmd->draw.clipw, &cmd->draw.cliph);
ENFN->context_clip_get(ENDT, drawctx, &cmd->draw.clip.x, &cmd->draw.clip.y,
&cmd->draw.clip.w, &cmd->draw.clip.h);
return cmd->id;
}
@ -1057,19 +1057,29 @@ _fill_cpu(Evas_Filter_Command *cmd)
{
Evas_Filter_Buffer *fb = cmd->output;
int step = fb->alpha_only ? sizeof(DATA8) : sizeof(DATA32);
int x = MAX(0, cmd->draw.clipx);
int y = MAX(0, cmd->draw.clipy);
int x = MAX(0, cmd->draw.clip.x);
int y = MAX(0, cmd->draw.clip.y);
DATA8 *ptr = ((RGBA_Image *) fb->backing)->mask.data;
int w, h, k, j;
if (cmd->draw.clipw)
w = MIN(cmd->draw.clipw, fb->w);
if (!cmd->draw.clip_mode_lrtb)
{
if (cmd->draw.clip.w)
w = MIN(cmd->draw.clip.w, fb->w - x);
else
w = fb->w - x;
if (cmd->draw.clip.h)
h = MIN(cmd->draw.clip.h, fb->h - y);
else
h = fb->h - y;
}
else
w = fb->w - x;
if (cmd->draw.cliph)
h = MIN(cmd->draw.cliph, fb->h);
else
h = fb->h - y;
{
x = MAX(0, cmd->draw.clip.l);
y = MAX(0, cmd->draw.clip.t);
w = CLAMP(0, fb->w - x - cmd->draw.clip.r, fb->w - x);
h = CLAMP(0, fb->h - y - cmd->draw.clip.b, fb->h - y);
}
ptr += y * step * fb->w;
if ((fb->alpha_only)
@ -1091,7 +1101,7 @@ _fill_cpu(Evas_Filter_Command *cmd)
{
for (j = 0; j < w; j++)
*dst++ = color;
dst += fb->w;
dst += fb->w - w;
}
}
@ -1187,7 +1197,8 @@ _filter_command_run(Evas_Filter_Command *cmd)
cmd->id, _filter_name_get(cmd->mode),
cmd->input->id, cmd->mask ? cmd->mask->id : 0, cmd->output->id);
if (!cmd->input->w && !cmd->input->h)
if (!cmd->input->w && !cmd->input->h
&& (cmd->mode != EVAS_FILTER_MODE_FILL))
{
DBG("Skipping processing of empty input buffer (size 0x0)");
return EINA_TRUE;

View File

@ -92,8 +92,8 @@ _filter_blend_cpu_rgba(Evas_Filter_Command *cmd)
cmd->ENFN->context_color_set(cmd->ENDT, drawctx, cmd->draw.R, cmd->draw.G,
cmd->draw.B, cmd->draw.A);
cmd->ENFN->context_render_op_set(cmd->ENDT, drawctx, cmd->draw.render_op);
cmd->ENFN->context_clip_set(cmd->ENDT, drawctx, cmd->draw.clipx,
cmd->draw.clipy, cmd->draw.clipw, cmd->draw.cliph);
cmd->ENFN->context_clip_set(cmd->ENDT, drawctx, cmd->draw.clip.x,
cmd->draw.clip.y, cmd->draw.clip.w, cmd->draw.clip.h);
cmd->ENFN->image_draw(cmd->ENDT, drawctx, out, in,
0, 0, w, h, // src

View File

@ -926,13 +926,22 @@ _fill_instruction_prepare(Evas_Filter_Instruction *instr)
EINA_SAFETY_ON_FALSE_RETURN_VAL(!strcasecmp(instr->name, "fill"), EINA_FALSE);
/*
* fill [dst=]BUFFER [color=COLOR]
* fill [dst=BUFFER] [color=COLOR] (l=INT) (r=INT) (t=INT) (b=INT)
*
* Works with both Alpha and RGBA.
*
* The geometry is defined by l, r, t, b, offsets from the edges of the buffer
* These offsets always go INWARDS, which means b > 0 goes UP, while t > 0
* goes DOWN.
*/
instr->type = EVAS_FILTER_MODE_FILL;
_instruction_param_seq_add(instr, "dst", VT_BUFFER, NULL);
_instruction_param_seq_add(instr, "dst", VT_BUFFER, "output");
_instruction_param_seq_add(instr, "color", VT_COLOR, 0x0);
_instruction_param_seq_add(instr, "l", VT_INT, 0);
_instruction_param_seq_add(instr, "r", VT_INT, 0);
_instruction_param_seq_add(instr, "t", VT_INT, 0);
_instruction_param_seq_add(instr, "b", VT_INT, 0);
return EINA_TRUE;
}
@ -1308,6 +1317,12 @@ evas_filter_program_proxy_source_get(Evas_Filter_Program *pgm, const char *name)
#define SETCOLOR(c) do { ENFN->context_color_get(ENDT, dc, &R, &G, &B, &A); \
ENFN->context_color_set(ENDT, dc, CR(c), CG(c), CB(c), CA(c)); } while (0)
#define RESETCOLOR() do { ENFN->context_color_set(ENDT, dc, R, G, B, A); } while (0)
#define SETCLIP(l, r, t, b) int _l = 0, _r = 0, _t = 0, _b = 0; \
do { ENFN->context_clip_get(ENDT, dc, &_l, &_r, &_t, &_b); \
ENFN->context_clip_set(ENDT, dc, l, r, t, b); } while (0)
#define RESETCLIP() do { ENFN->context_clip_set(ENDT, dc, _l, _r, _t, _b); } while (0)
int A, R, G, B;
static Evas_Filter_Fill_Mode
@ -1473,13 +1488,17 @@ _instr2cmd_fill(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
{
const char *bufname;
Buffer *buf;
int R, G, B, A;
int R, G, B, A, l, r, t, b;
Evas_Filter_Command *cmd;
DATA32 color;
int cmdid;
bufname = _instruction_param_gets(instr, "dst", NULL);
color = _instruction_param_getc(instr, "color", NULL);
// TODO/FIXME: Add clip info
l = _instruction_param_geti(instr, "l", NULL);
r = _instruction_param_geti(instr, "r", NULL);
t = _instruction_param_geti(instr, "t", NULL);
b = _instruction_param_geti(instr, "b", NULL);
buf = _buffer_get(pgm, bufname);
@ -1487,6 +1506,13 @@ _instr2cmd_fill(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
cmdid = evas_filter_command_fill_add(ctx, dc, buf->cid);
RESETCOLOR();
cmd = EINA_INLIST_CONTAINER_GET(eina_inlist_last(ctx->commands), Evas_Filter_Command);
cmd->draw.clip.l = l;
cmd->draw.clip.r = r;
cmd->draw.clip.t = t;
cmd->draw.clip.b = b;
cmd->draw.clip_mode_lrtb = EINA_TRUE;
return cmdid;
}

View File

@ -106,8 +106,16 @@ struct _Evas_Filter_Command
int render_op;
int R, G, B, A;
int ox, oy;
int clipx, clipy, clipw, cliph;
union {
struct {
int x, y, w, h;
};
struct {
int l, r, t, b;
};
} clip;
Evas_Filter_Fill_Mode fillmode;
Eina_Bool clip_mode_lrtb : 1;
} draw;
};