From 209a7077a0f9b3c8367213e78cef8604db8169e2 Mon Sep 17 00:00:00 2001 From: Jean-Philippe Andre Date: Tue, 7 Jan 2014 18:38:22 +0900 Subject: [PATCH] Evas filters: Add offset parameter to vflip It is not possible to logically handle padding and offset at the same time for a proper mirror effect, unless this is handled directly at the transformation level. Also, add support for blend() operation padding computation. --- src/lib/evas/filters/evas_filter.c | 8 +- src/lib/evas/filters/evas_filter_parser.c | 122 +++++++++++++++++++++++++++ src/lib/evas/filters/evas_filter_transform.c | 27 +++++- src/lib/evas/include/evas_filter.h | 4 +- 4 files changed, 155 insertions(+), 6 deletions(-) diff --git a/src/lib/evas/filters/evas_filter.c b/src/lib/evas/filters/evas_filter.c index c4ec46b..0f86852 100644 --- a/src/lib/evas/filters/evas_filter.c +++ b/src/lib/evas/filters/evas_filter.c @@ -1048,9 +1048,11 @@ end: } int -evas_filter_command_transform_add(Evas_Filter_Context *ctx, void *draw_context, +evas_filter_command_transform_add(Evas_Filter_Context *ctx, + void *draw_context EINA_UNUSED, int inbuf, int outbuf, - Evas_Filter_Transform_Flags flags) + Evas_Filter_Transform_Flags flags, + int ox, int oy) { Evas_Filter_Command *cmd; Evas_Filter_Buffer *in, *out; @@ -1076,6 +1078,8 @@ evas_filter_command_transform_add(Evas_Filter_Context *ctx, void *draw_context, if (!cmd) return -1; cmd->transform.flags = flags; + cmd->draw.ox = ox; + cmd->draw.oy = oy; return cmd->id; } diff --git a/src/lib/evas/filters/evas_filter_parser.c b/src/lib/evas/filters/evas_filter_parser.c index d1546e6..d936abe 100644 --- a/src/lib/evas/filters/evas_filter_parser.c +++ b/src/lib/evas/filters/evas_filter_parser.c @@ -684,6 +684,38 @@ _buffer_del(Buffer *buf) /* Instruction definitions */ +static void +_blend_padding_update(Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr, + int *padl, int *padr, int *padt, int *padb) +{ + const char *outbuf; + Buffer *out; + int ox, oy, l = 0, r = 0, t = 0, b = 0; + + ox = _instruction_param_geti(instr, "ox", NULL); + oy = _instruction_param_geti(instr, "oy", NULL); + + outbuf = _instruction_param_gets(instr, "dst", NULL); + out = _buffer_get(pgm, outbuf); + EINA_SAFETY_ON_NULL_RETURN(out); + + if (ox < 0) l = (-ox); + else r = ox; + + if (oy < 0) t = (-oy); + else b = oy; + + if (out->pad.l < l) out->pad.l = l; + if (out->pad.r < r) out->pad.r = r; + if (out->pad.t < t) out->pad.t = t; + if (out->pad.b < b) out->pad.b = b; + + if (padl) *padl = l; + if (padr) *padr = r; + if (padt) *padt = t; + if (padb) *padb = b; +} + static Eina_Bool _blend_instruction_prepare(Evas_Filter_Instruction *instr) { @@ -696,6 +728,7 @@ _blend_instruction_prepare(Evas_Filter_Instruction *instr) */ instr->type = EVAS_FILTER_MODE_BLEND; + instr->pad.update = _blend_padding_update; _instruction_param_seq_add(instr, "src", VT_BUFFER, "input"); _instruction_param_seq_add(instr, "dst", VT_BUFFER, "output"); _instruction_param_seq_add(instr, "ox", VT_INT, 0); @@ -1024,6 +1057,62 @@ _mask_instruction_prepare(Evas_Filter_Instruction *instr) return EINA_TRUE; } +static void +_transform_padding_update(Evas_Filter_Program *pgm, + Evas_Filter_Instruction *instr, + int *padl, int *padr, int *padt, int *padb) +{ + const char *outbuf; + Buffer *out; + int ox, oy, l = 0, r = 0, t = 0, b = 0; + + //ox = _instruction_param_geti(instr, "ox", NULL); + ox = 0; + oy = _instruction_param_geti(instr, "oy", NULL); + + outbuf = _instruction_param_gets(instr, "dst", NULL); + out = _buffer_get(pgm, outbuf); + EINA_SAFETY_ON_NULL_RETURN(out); + + if (ox < 0) l = (-ox) * 2; + else r = ox * 2; + + if (oy < 0) t = (-oy) * 2; + else b = oy * 2; + + if (out->pad.l < l) out->pad.l = l; + if (out->pad.r < r) out->pad.r = r; + if (out->pad.t < t) out->pad.t = t; + if (out->pad.b < b) out->pad.b = b; + + if (padl) *padl = l; + if (padr) *padr = r; + if (padt) *padt = t; + if (padb) *padb = b; +} + +static Eina_Bool +_transform_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, "transform"), EINA_FALSE); + + /* + * mask [op=]STRING [input=BUFFER] [output=BUFFER] (oy=INT) + */ + + instr->type = EVAS_FILTER_MODE_TRANSFORM; + instr->pad.update = _transform_padding_update; + _instruction_param_seq_add(instr, "op", VT_STRING, "vflip"); + _instruction_param_seq_add(instr, "src", VT_BUFFER, "input"); + _instruction_param_seq_add(instr, "dst", VT_BUFFER, "output"); + //_instruction_param_name_add(instr, "ox", VT_INT, 0); + _instruction_param_name_add(instr, "oy", VT_INT, 0); + + return EINA_TRUE; +} + static Evas_Filter_Instruction * _instruction_create(const char *name) { @@ -1048,6 +1137,8 @@ _instruction_create(const char *name) prepare = _grow_instruction_prepare; else if (!strcasecmp(name, "mask")) prepare = _mask_instruction_prepare; + else if (!strcasecmp(name, "transform")) + prepare = _transform_instruction_prepare; if (!prepare) { @@ -1648,6 +1739,34 @@ interpolated: } static int +_instr2cmd_transform(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, + Evas_Filter_Instruction *instr, void *dc) +{ + Evas_Filter_Transform_Flags flags; + const char *src, *dst, *op; + Buffer *in, *out; + int ox = 0, oy; + + op = _instruction_param_gets(instr, "op", NULL); + src = _instruction_param_gets(instr, "src", NULL); + dst = _instruction_param_gets(instr, "dst", NULL); + // ox = _instruction_param_geti(instr, "ox", NULL); + oy = _instruction_param_geti(instr, "oy", NULL); + + if (!strcasecmp(op, "vflip")) + flags = EVAS_FILTER_TRANSFORM_VFLIP; + else + { + ERR("Invalid transform '%s'", op); + return -1; + } + + in = _buffer_get(pgm, src); + out = _buffer_get(pgm, dst); + return evas_filter_command_transform_add(ctx, dc, in->cid, out->cid, flags, ox, oy); +} + +static int _command_from_instruction(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Evas_Filter_Instruction *instr, void *dc) { @@ -1680,6 +1799,9 @@ _command_from_instruction(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, case EVAS_FILTER_MODE_CURVE: instr2cmd = _instr2cmd_curve; break; + case EVAS_FILTER_MODE_TRANSFORM: + instr2cmd = _instr2cmd_transform; + break; default: CRI("Invalid instruction type: %d", instr->type); return -1; diff --git a/src/lib/evas/filters/evas_filter_transform.c b/src/lib/evas/filters/evas_filter_transform.c index 7ae81d6..bc9f65d 100644 --- a/src/lib/evas/filters/evas_filter_transform.c +++ b/src/lib/evas/filters/evas_filter_transform.c @@ -5,7 +5,8 @@ _vflip_cpu(Evas_Filter_Command *cmd) { size_t datasize, stride; DATA8 *in, *out, *span; - int w, h, sy, dy; + int w, h, sy, dy, oy, center, t, b, objh; + int s0, s1, d0, d1; EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE); EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, EINA_FALSE); @@ -24,23 +25,43 @@ _vflip_cpu(Evas_Filter_Command *cmd) datasize = cmd->input->alpha_only ? sizeof(DATA8) : sizeof(DATA32); stride = w * datasize; + oy = cmd->draw.oy; + t = cmd->ctx->padt; + b = cmd->ctx->padb; + objh = h - t - b; + center = t + objh / 2 + oy; + + s0 = t; + s1 = h - b - 1; + if (oy >= 0) + { + d0 = center + (objh / 2) + oy; + d1 = center - (objh / 2) - oy; + } + else + { + d0 = center + (objh / 2) - oy; + d1 = center - (objh / 2) + oy; + } + if (in == out) { span = malloc(stride); if (!span) return EINA_FALSE; } - for (sy = 0, dy = h - 1; dy >= 0; sy++, dy--) + for (sy = s0, dy = d0; (dy >= d1) && (sy <= s1); sy++, dy--) { DATA8* src = in + stride * sy; DATA8* dst = out + stride * dy; if (in == out) { + if (src == dst) break; memcpy(span, dst, stride); memcpy(dst, src, stride); memcpy(src, span, stride); - if (sy >= (h / 2)) break; + if (sy >= center) break; } else memcpy(dst, src, stride); diff --git a/src/lib/evas/include/evas_filter.h b/src/lib/evas/include/evas_filter.h index 1d1a171..28623ee 100644 --- a/src/lib/evas/include/evas_filter.h +++ b/src/lib/evas/include/evas_filter.h @@ -227,9 +227,11 @@ int evas_filter_command_bump_map_add(Evas_Filter_Context *c * @param inbuf Input buffer (Alpha or RGBA) * @param outbuf Output buffer (Alpha or RGBA), same size as inbuf * @param flags Specifies the operation to apply (eg. vflip) + * @param ox X offset + * @param oy Y offset * @return Filter command ID or -1 in case of error */ -int evas_filter_command_transform_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, Evas_Filter_Transform_Flags flags); +int evas_filter_command_transform_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, Evas_Filter_Transform_Flags flags, int ox, int oy); #endif -- 2.7.4