Evas filters: Add transform filter

This is the simplest solution I can come up with for "mirror" effects.
Displacement maps are HARD to generate and use properly, since the buffer
size is unknown until runtime.
Even if we align the map to the text itself (using the padding information),
it's still hard to describe properly how to apply the displacement map, and
to generate it... So let's just add a simple flip operation.
This commit is contained in:
Jean-Philippe Andre 2014-01-07 16:44:10 +09:00
parent 388a30950a
commit d9fb0cdc34
5 changed files with 126 additions and 0 deletions

View File

@ -374,6 +374,7 @@ lib/evas/filters/evas_filter_curve.c \
lib/evas/filters/evas_filter_displace.c \
lib/evas/filters/evas_filter_mask.c \
lib/evas/filters/evas_filter_parser.c \
lib/evas/filters/evas_filter_transform.c \
lib/evas/filters/evas_filter_utils.c

View File

@ -1047,6 +1047,39 @@ end:
return cmdid;
}
int
evas_filter_command_transform_add(Evas_Filter_Context *ctx, void *draw_context,
int inbuf, int outbuf,
Evas_Filter_Transform_Flags flags)
{
Evas_Filter_Command *cmd;
Evas_Filter_Buffer *in, *out;
EINA_SAFETY_ON_NULL_RETURN_VAL(ctx, -1);
in = _filter_buffer_get(ctx, inbuf);
out = _filter_buffer_get(ctx, outbuf);
if (!in || !out)
{
ERR("Invalid buffer id: input %d [%p], output %d [%p]",
inbuf, in, outbuf, out);
return -1;
}
if (in->alpha_only != out->alpha_only)
{
CRI("Incompatible buffer formats");
return -1;
}
cmd = _command_new(ctx, EVAS_FILTER_MODE_TRANSFORM, in, NULL, out);
if (!cmd) return -1;
cmd->transform.flags = flags;
return cmd->id;
}
static Eina_Bool
_fill_cpu(Evas_Filter_Command *cmd)
{
@ -1248,6 +1281,9 @@ _filter_command_run(Evas_Filter_Command *cmd)
case EVAS_FILTER_MODE_BUMP:
func = evas_filter_bump_map_cpu_func_get(cmd);
break;
case EVAS_FILTER_MODE_TRANSFORM:
func = evas_filter_transform_cpu_func_get(cmd);
break;
default:
CRI("Invalid filter mode.");
break;

View File

@ -103,6 +103,11 @@ struct _Evas_Filter_Command
Eina_Bool compensate : 1; // Compensate for darkening
//Eina_Bool specular : 1; // Use specular light as well (needs specular_factor > 0)
} bump;
struct
{
Evas_Filter_Transform_Flags flags;
} transform;
};
struct {
@ -158,6 +163,7 @@ 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);
Evas_Filter_Apply_Func evas_filter_transform_cpu_func_get(Evas_Filter_Command *cmd);
/* Utility functions */
void _clip_to_target(int *sx, int *sy, int sw, int sh, int ox, int oy, int dw, int dh, int *dx, int *dy, int *rows, int *cols);

View File

@ -0,0 +1,65 @@
#include "evas_filter_private.h"
static Eina_Bool
_vflip_cpu(Evas_Filter_Command *cmd)
{
size_t datasize, stride;
DATA8 *in, *out, *span;
int w, h, sy, dy;
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->input->backing, EINA_FALSE);
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd->output->backing, EINA_FALSE);
w = cmd->input->w;
h = cmd->input->h;
EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->output->w == w, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->output->h == h, EINA_FALSE);
EINA_SAFETY_ON_FALSE_RETURN_VAL(cmd->output->alpha_only == cmd->input->alpha_only, EINA_FALSE);
in = ((RGBA_Image *) cmd->input->backing)->mask.data;
out = ((RGBA_Image *) cmd->output->backing)->mask.data;
datasize = cmd->input->alpha_only ? sizeof(DATA8) : sizeof(DATA32);
stride = w * datasize;
if (in == out)
{
span = malloc(stride);
if (!span) return EINA_FALSE;
}
for (sy = 0, dy = h - 1; dy >= 0; sy++, dy--)
{
DATA8* src = in + stride * sy;
DATA8* dst = out + stride * dy;
if (in == out)
{
memcpy(span, dst, stride);
memcpy(dst, src, stride);
memcpy(src, span, stride);
if (sy >= (h / 2)) break;
}
else
memcpy(dst, src, stride);
}
return EINA_TRUE;
}
Evas_Filter_Apply_Func
evas_filter_transform_cpu_func_get(Evas_Filter_Command *cmd)
{
EINA_SAFETY_ON_NULL_RETURN_VAL(cmd, NULL);
switch (cmd->transform.flags)
{
case EVAS_FILTER_TRANSFORM_VFLIP:
return _vflip_cpu;
default:
CRI("Unknown transform flag %d", (int) cmd->transform.flags);
return NULL;
}
}

View File

@ -14,6 +14,7 @@ typedef enum _Evas_Filter_Channel Evas_Filter_Channel;
typedef enum _Evas_Filter_Displacement_Flags Evas_Filter_Displacement_Flags;
typedef enum _Evas_Filter_Bump_Flags Evas_Filter_Bump_Flags;
typedef enum _Evas_Filter_Fill_Mode Evas_Filter_Fill_Mode;
typedef enum _Evas_Filter_Transform_Flags Evas_Filter_Transform_Flags;
typedef Eina_Bool (* Evas_Filter_Apply_Func) (Evas_Filter_Command *cmd);
typedef void (* Evas_Filter_Cb) (Evas_Filter_Context *ctx, void *data);
@ -30,6 +31,7 @@ enum _Evas_Filter_Mode
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_TRANSFORM, /**< Apply a simple geometrical transformation */
EVAS_FILTER_MODE_LAST
};
@ -79,6 +81,11 @@ enum _Evas_Filter_Fill_Mode
EVAS_FILTER_FILL_MODE_STRETCH_XY = EVAS_FILTER_FILL_MODE_STRETCH_X | EVAS_FILTER_FILL_MODE_STRETCH_Y
};
enum _Evas_Filter_Transform_Flags
{
EVAS_FILTER_TRANSFORM_VFLIP = 1
};
/* Parser stuff (high level API) */
Evas_Filter_Program *evas_filter_program_new(const char *name);
Eina_Bool evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str);
@ -213,5 +220,16 @@ int evas_filter_command_mask_add(Evas_Filter_Context *ctx,
*/
int evas_filter_command_bump_map_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int bumpbuf, int outbuf, float azimuth, float elevation, float depth, float specular_factor, DATA32 black, DATA32 color, DATA32 white, Evas_Filter_Bump_Flags flags, Evas_Filter_Fill_Mode fillmode);
/**
* @brief Apply a geometrical transformation to the buffer
* @param ctx Current filter chain
* @param draw_context Current Evas draw context (ignored)
* @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)
* @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);
#endif