Evas filters: Add new instruction padding_set
This will allow forcing a specific value for the filter padding, instead of relying on auto calculation. Two advantages: - Auto calculation can't be perfect, since it will add as much padding as required for the full blur effect - This prepares the path for animations with effects, where the object size does not change over time
This commit is contained in:
parent
c7616dd738
commit
91a471b4dc
|
@ -316,7 +316,12 @@ struct _Evas_Filter_Program
|
||||||
Eina_Hash /* const char * : Evas_Filter_Proxy_Binding */ *proxies;
|
Eina_Hash /* const char * : Evas_Filter_Proxy_Binding */ *proxies;
|
||||||
Eina_Inlist /* Evas_Filter_Instruction */ *instructions;
|
Eina_Inlist /* Evas_Filter_Instruction */ *instructions;
|
||||||
Eina_Inlist /* Buffer */ *buffers;
|
Eina_Inlist /* Buffer */ *buffers;
|
||||||
|
struct {
|
||||||
|
int l, r, t, b;
|
||||||
|
} pad;
|
||||||
Eina_Bool valid : 1;
|
Eina_Bool valid : 1;
|
||||||
|
Eina_Bool padding_calc : 1; // Padding has been calculated
|
||||||
|
Eina_Bool padding_set : 1; // Padding has been forced
|
||||||
};
|
};
|
||||||
|
|
||||||
/* Instructions */
|
/* Instructions */
|
||||||
|
@ -1635,6 +1640,85 @@ _transform_instruction_prepare(Evas_Filter_Instruction *instr)
|
||||||
return EINA_TRUE;
|
return EINA_TRUE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void
|
||||||
|
_padding_set_padding_update(Evas_Filter_Program *pgm,
|
||||||
|
Evas_Filter_Instruction *instr,
|
||||||
|
int *padl, int *padr, int *padt, int *padb)
|
||||||
|
{
|
||||||
|
int l = 0, r = 0, t = 0, b = 0;
|
||||||
|
Eina_Bool lset = EINA_FALSE;
|
||||||
|
Eina_Bool rset = EINA_FALSE;
|
||||||
|
Eina_Bool tset = EINA_FALSE;
|
||||||
|
Eina_Bool bset = EINA_FALSE;
|
||||||
|
|
||||||
|
l = _instruction_param_geti(instr, "l", &lset);
|
||||||
|
r = _instruction_param_geti(instr, "r", &rset);
|
||||||
|
t = _instruction_param_geti(instr, "t", &tset);
|
||||||
|
b = _instruction_param_geti(instr, "b", &bset);
|
||||||
|
|
||||||
|
if (!lset && !rset && !bset && !tset)
|
||||||
|
DBG("padding_set() called without specifying any of l,r,t,b resets to 0");
|
||||||
|
|
||||||
|
if (l < 0 || r < 0 || t < 0 || b < 0)
|
||||||
|
{
|
||||||
|
WRN("invalid padding values in padding_set(%d, %d, %d, %d), resets to 0", l, r, t, b);
|
||||||
|
l = r = t = b = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!rset) r = l;
|
||||||
|
if (!tset) t = r;
|
||||||
|
if (!bset) b = t;
|
||||||
|
|
||||||
|
if (padl) *padl = l;
|
||||||
|
if (padr) *padr = r;
|
||||||
|
if (padt) *padt = t;
|
||||||
|
if (padb) *padb = b;
|
||||||
|
pgm->padding_set = EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
@page evasfiltersref
|
||||||
|
|
||||||
|
@subsection sec_commands_padding_set Padding_Set
|
||||||
|
|
||||||
|
Forcily set a specific padding for this filter.
|
||||||
|
|
||||||
|
@code
|
||||||
|
padding_set (l, r = [l], t = [r], b = [t]);
|
||||||
|
@endcode
|
||||||
|
|
||||||
|
@param l Padding on the left side in pixels.
|
||||||
|
@param r Padding on the right side in pixels. If unset, defaults to @a l.
|
||||||
|
@param t Padding on the top in pixels. If unset, defaults to @a r.
|
||||||
|
@param b Padding on the bottom in pixels. If unset, defaults to @a t.
|
||||||
|
|
||||||
|
All values must be >= 0. When filtering 'filled' images, some values may be too high
|
||||||
|
and would result in completely hiding the image.
|
||||||
|
|
||||||
|
It is not possible to set only one of those without forcing the others as well.
|
||||||
|
A common use case will be when changing a blur size during an animation, or
|
||||||
|
when applying a mask that will hide most of the (blurred) text.
|
||||||
|
|
||||||
|
@since 1.10
|
||||||
|
*/
|
||||||
|
|
||||||
|
static Eina_Bool
|
||||||
|
_padding_set_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, "padding_set"), EINA_FALSE);
|
||||||
|
|
||||||
|
instr->type = EVAS_FILTER_MODE_PADDING_SET;
|
||||||
|
instr->pad.update = _padding_set_padding_update;
|
||||||
|
_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;
|
||||||
|
}
|
||||||
|
|
||||||
static Evas_Filter_Instruction *
|
static Evas_Filter_Instruction *
|
||||||
_instruction_create(const char *name)
|
_instruction_create(const char *name)
|
||||||
{
|
{
|
||||||
|
@ -1661,6 +1745,8 @@ _instruction_create(const char *name)
|
||||||
prepare = _mask_instruction_prepare;
|
prepare = _mask_instruction_prepare;
|
||||||
else if (!strcasecmp(name, "transform"))
|
else if (!strcasecmp(name, "transform"))
|
||||||
prepare = _transform_instruction_prepare;
|
prepare = _transform_instruction_prepare;
|
||||||
|
else if (!strcasecmp(name, "padding_set"))
|
||||||
|
prepare = _padding_set_instruction_prepare;
|
||||||
|
|
||||||
if (!prepare)
|
if (!prepare)
|
||||||
{
|
{
|
||||||
|
@ -1825,6 +1911,7 @@ evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str)
|
||||||
|
|
||||||
// Add to the queue
|
// Add to the queue
|
||||||
pgm->instructions = eina_inlist_append(pgm->instructions, EINA_INLIST_GET(instr));
|
pgm->instructions = eina_inlist_append(pgm->instructions, EINA_INLIST_GET(instr));
|
||||||
|
pgm->padding_calc = EINA_FALSE;
|
||||||
instr = NULL;
|
instr = NULL;
|
||||||
count++;
|
count++;
|
||||||
}
|
}
|
||||||
|
@ -1859,20 +1946,42 @@ evas_filter_program_padding_get(Evas_Filter_Program *pgm,
|
||||||
|
|
||||||
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
|
EINA_SAFETY_ON_NULL_RETURN_VAL(pgm, EINA_FALSE);
|
||||||
|
|
||||||
|
if (pgm->padding_calc || pgm->padding_set)
|
||||||
|
{
|
||||||
|
if (l) *l = pgm->pad.l;
|
||||||
|
if (r) *r = pgm->pad.r;
|
||||||
|
if (t) *t = pgm->pad.t;
|
||||||
|
if (b) *b = pgm->pad.b;
|
||||||
|
return EINA_TRUE;
|
||||||
|
}
|
||||||
|
|
||||||
// Reset all paddings
|
// Reset all paddings
|
||||||
EINA_INLIST_FOREACH(pgm->buffers, buf)
|
EINA_INLIST_FOREACH(pgm->buffers, buf)
|
||||||
buf->pad.l = buf->pad.r = buf->pad.t = buf->pad.b = 0;
|
buf->pad.l = buf->pad.r = buf->pad.t = buf->pad.b = 0;
|
||||||
|
|
||||||
// Accumulate paddings
|
// Accumulate paddings
|
||||||
EINA_INLIST_FOREACH(pgm->instructions, instr)
|
EINA_INLIST_FOREACH(pgm->instructions, instr)
|
||||||
if (instr->pad.update)
|
{
|
||||||
{
|
if (instr->type == EVAS_FILTER_MODE_PADDING_SET)
|
||||||
instr->pad.update(pgm, instr, &pl, &pr, &pt, &pb);
|
{
|
||||||
if (pl > maxl) maxl = pl;
|
instr->pad.update(pgm, instr, &maxl, &maxr, &maxt, &maxb);
|
||||||
if (pr > maxr) maxr = pr;
|
break;
|
||||||
if (pt > maxt) maxt = pt;
|
}
|
||||||
if (pb > maxb) maxb = pb;
|
else if (instr->pad.update)
|
||||||
}
|
{
|
||||||
|
instr->pad.update(pgm, instr, &pl, &pr, &pt, &pb);
|
||||||
|
if (pl > maxl) maxl = pl;
|
||||||
|
if (pr > maxr) maxr = pr;
|
||||||
|
if (pt > maxt) maxt = pt;
|
||||||
|
if (pb > maxb) maxb = pb;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pgm->pad.l = maxl;
|
||||||
|
pgm->pad.r = maxr;
|
||||||
|
pgm->pad.t = maxt;
|
||||||
|
pgm->pad.b = maxb;
|
||||||
|
pgm->padding_calc = EINA_TRUE;
|
||||||
|
|
||||||
if (l) *l = maxl;
|
if (l) *l = maxl;
|
||||||
if (r) *r = maxr;
|
if (r) *r = maxr;
|
||||||
|
@ -2350,6 +2459,8 @@ _command_from_instruction(Evas_Filter_Context *ctx, Evas_Filter_Program *pgm,
|
||||||
case EVAS_FILTER_MODE_TRANSFORM:
|
case EVAS_FILTER_MODE_TRANSFORM:
|
||||||
instr2cmd = _instr2cmd_transform;
|
instr2cmd = _instr2cmd_transform;
|
||||||
break;
|
break;
|
||||||
|
case EVAS_FILTER_MODE_PADDING_SET:
|
||||||
|
return EINA_TRUE;
|
||||||
default:
|
default:
|
||||||
CRI("Invalid instruction type: %d", instr->type);
|
CRI("Invalid instruction type: %d", instr->type);
|
||||||
return -1;
|
return -1;
|
||||||
|
|
|
@ -37,6 +37,7 @@ enum _Evas_Filter_Mode
|
||||||
EVAS_FILTER_MODE_MASK, /**< Apply Alpha or RGBA texture on image */
|
EVAS_FILTER_MODE_MASK, /**< Apply Alpha or RGBA texture on image */
|
||||||
EVAS_FILTER_MODE_BUMP, /**< Apply bump mapping (light effect) */
|
EVAS_FILTER_MODE_BUMP, /**< Apply bump mapping (light effect) */
|
||||||
EVAS_FILTER_MODE_TRANSFORM, /**< Apply a simple geometrical transformation */
|
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_LAST
|
EVAS_FILTER_MODE_LAST
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue