From 2da17927da41ebbdc285886300da88d3c72a46e5 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Thu, 2 Jan 2014 18:44:01 +0900 Subject: [PATCH] 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. --- src/lib/evas/filters/evas_filter.c | 39 ++++++++++++++-------- src/lib/evas/filters/evas_filter_blend.c | 4 +-- src/lib/evas/filters/evas_filter_parser.c | 34 ++++++++++++++++--- src/lib/evas/filters/evas_filter_private.h | 10 +++++- 4 files changed, 66 insertions(+), 21 deletions(-) diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index daecc7363a..2142962c0c 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -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); - else - w = fb->w - x; - if (cmd->draw.cliph) - h = MIN(cmd->draw.cliph, fb->h); + 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 - 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; diff --git a/src/lib/evas/filters/evas_filter_blend.c b/src/lib/evas/filters/evas_filter_blend.c index 6781376e70..ec988439c6 100644 --- a/src/lib/evas/filters/evas_filter_blend.c +++ b/src/lib/evas/filters/evas_filter_blend.c @@ -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 diff --git a/src/lib/evas/filters/evas_filter_parser.c b/src/lib/evas/filters/evas_filter_parser.c index cb9f2d9ba7..0b64b77028 100644 --- a/src/lib/evas/filters/evas_filter_parser.c +++ b/src/lib/evas/filters/evas_filter_parser.c @@ -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; } diff --git a/src/lib/evas/filters/evas_filter_private.h b/src/lib/evas/filters/evas_filter_private.h index 0a0c85e3c4..1357a3f786 100644 --- a/src/lib/evas/filters/evas_filter_private.h +++ b/src/lib/evas/filters/evas_filter_private.h @@ -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; }; -- 2.34.1