summaryrefslogtreecommitdiff
path: root/src/lib/evas/include/evas_filter.h
blob: dd779812f9e4122a1486d8a4e304b93f8d2bafc4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
#ifndef _EVAS_FILTER_H
#define _EVAS_FILTER_H

#include "evas_common_private.h"
#include "evas_private.h"


#ifdef EAPI
# undef EAPI
#endif

#ifdef _WIN32
# ifdef EFL_BUILD
#  ifdef DLL_EXPORT
#   define EAPI __declspec(dllexport)
#  else
#   define EAPI
#  endif
# else
#  define EAPI __declspec(dllimport)
# endif
#else
# ifdef __GNUC__
#  if __GNUC__ >= 4
#   define EAPI __attribute__ ((visibility("default")))
#  else
#   define EAPI
#  endif
# else
#  define EAPI
# endif
#endif

#include "efl_canvas_filter_internal.eo.h"

#ifdef DEBUG
# define FILTERS_DEBUG
#endif

typedef struct _Evas_Filter_Instruction Evas_Filter_Instruction;
typedef struct _Evas_Filter_Buffer Evas_Filter_Buffer;
typedef struct _Evas_Filter_Proxy_Binding Evas_Filter_Proxy_Binding;
typedef struct _Evas_Filter_Padding Evas_Filter_Padding;
typedef enum _Evas_Filter_Mode Evas_Filter_Mode;
typedef enum _Evas_Filter_Blur_Type Evas_Filter_Blur_Type;
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 void (* Evas_Filter_Cb) (Evas_Filter_Context *ctx, void *data, Eina_Bool success);

#define EVAS_FILTER_BUFFER_RGBA  EINA_FALSE
#define EVAS_FILTER_BUFFER_ALPHA EINA_TRUE

#define EVAS_FILTER_BUFFER_INPUT_ID  1
#define EVAS_FILTER_BUFFER_OUTPUT_ID 2

/** @internal */
enum _Evas_Filter_Mode
{
   EVAS_FILTER_MODE_SKIP,         /**< No operation */
   EVAS_FILTER_MODE_BLEND,        /**< Blend with current context render_op */
   EVAS_FILTER_MODE_BLUR,         /**< @see Evas_Filter_Blur_Type */
   EVAS_FILTER_MODE_CURVE,        /**< Apply color curve */
   EVAS_FILTER_MODE_DISPLACE,     /**< Apply XY displacement based on RG mask */
   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_PADDING_SET,  /**< Special padding_set instruction to force a specific padding value */
   EVAS_FILTER_MODE_GRAYSCALE,    /**< Leave only grayscale information */
   EVAS_FILTER_MODE_INVERSE_COLOR,/**< Apply inverse color */
   EVAS_FILTER_MODE_LAST
};

/** @internal */
enum _Evas_Filter_Blur_Type
{
   EVAS_FILTER_BLUR_DEFAULT  = 0x0, // Default blur (GAUSSIAN or series of BOX)
   EVAS_FILTER_BLUR_BOX      = 0x1, // Optimizable on CPU. But, UGLY. O(n)
   EVAS_FILTER_BLUR_GAUSSIAN = 0x2, // Gaussian blur (using sine curve)
   EVAS_FILTER_BLUR_LAST,
};

/** @internal */
enum _Evas_Filter_Channel
{
   EVAS_FILTER_CHANNEL_ALPHA = 0,
   EVAS_FILTER_CHANNEL_RED   = 1,
   EVAS_FILTER_CHANNEL_GREEN = 2,
   EVAS_FILTER_CHANNEL_BLUE  = 3,
   EVAS_FILTER_CHANNEL_RGB   = 4
};

/** @internal */
enum _Evas_Filter_Displacement_Flags
{
   EVAS_FILTER_DISPLACE_NEAREST  = 0x0,   /**< Interpolate between pixels (linear interpolation) */
   EVAS_FILTER_DISPLACE_LINEAR   = 0x1,   /**< Interpolate between pixels (linear interpolation) */
   EVAS_FILTER_DISPLACE_BLACK    = 0x0,   /**< Use black (or transparent) when going out of bounds) */
   EVAS_FILTER_DISPLACE_STRETCH  = 0x2,   /**< Stretch border pixels when going out of bounds */
   EVAS_FILTER_DISPLACE_BITMASK  = 0x3
};

/** @internal */
enum _Evas_Filter_Bump_Flags
{
   EVAS_FILTER_BUMP_NORMAL       = 0x0,
   EVAS_FILTER_BUMP_COMPENSATE   = 0x1    /**< Compensate for darkening (diffuse light) or brightening (specular light) of zero gradient surfaces */
};

/** @internal */
enum _Evas_Filter_Fill_Mode
{
   EVAS_FILTER_FILL_MODE_NONE               = 0x0,
   EVAS_FILTER_FILL_MODE_STRETCH_X          = 0x1,
   EVAS_FILTER_FILL_MODE_STRETCH_Y          = 0x2,
   EVAS_FILTER_FILL_MODE_REPEAT_X           = 0x4,
   EVAS_FILTER_FILL_MODE_REPEAT_Y           = 0x8,
   EVAS_FILTER_FILL_MODE_REPEAT_X_STRETCH_Y = EVAS_FILTER_FILL_MODE_REPEAT_X | EVAS_FILTER_FILL_MODE_STRETCH_Y,
   EVAS_FILTER_FILL_MODE_REPEAT_Y_STRETCH_X = EVAS_FILTER_FILL_MODE_REPEAT_Y | EVAS_FILTER_FILL_MODE_STRETCH_X,
   EVAS_FILTER_FILL_MODE_REPEAT_XY          = EVAS_FILTER_FILL_MODE_REPEAT_X | EVAS_FILTER_FILL_MODE_REPEAT_Y,
   EVAS_FILTER_FILL_MODE_STRETCH_XY         = EVAS_FILTER_FILL_MODE_STRETCH_X | EVAS_FILTER_FILL_MODE_STRETCH_Y
};

/** @internal */
enum _Evas_Filter_Transform_Flags
{
   EVAS_FILTER_TRANSFORM_VFLIP = 1
};

/** @internal */
struct _Evas_Filter_Padding
{
   int l, r, t, b;
};

#define EFL_CANVAS_FILTER_STATE_DEFAULT { {}, { 255, 255, 255, 255 }, { "default", 0.0 }, {}, 0, 0, 1.0, 0.0 }

/* Parser stuff (high level API) */
EAPI Evas_Filter_Program *evas_filter_program_new(const char *name, Eina_Bool input_alpha);
EAPI Eina_Bool           evas_filter_program_state_set(Evas_Filter_Program *pgm, const Efl_Canvas_Filter_State *state);
EAPI Eina_Bool           evas_filter_program_parse(Evas_Filter_Program *pgm, const char *str);
EAPI void                evas_filter_program_del(Evas_Filter_Program *pgm);
EAPI Eina_Bool           evas_filter_program_padding_get(Evas_Filter_Program *pgm, Evas_Filter_Padding *final, Evas_Filter_Padding *calc);
EAPI void                evas_filter_program_source_set_all(Evas_Filter_Program *pgm, Eina_Hash *sources);
void                     evas_filter_program_data_set_all(Evas_Filter_Program *pgm, Eina_Inlist *data);

/* Filter context (low level) */
Evas_Filter_Context     *evas_filter_context_new(Evas_Public_Data *evas, Eina_Bool async, void *user_data);
void                    *evas_filter_context_data_get(Evas_Filter_Context *ctx);
Eina_Bool                evas_filter_context_async_get(Evas_Filter_Context *ctx);
void                     evas_filter_context_size_get(Evas_Filter_Context *ctx, int *w, int *H);
int                      evas_filter_context_ref(Evas_Filter_Context *ctx);
void                     evas_filter_context_unref(Evas_Filter_Context *ctx);
Eina_Bool                evas_filter_context_program_use(void *engine, void *output, Evas_Filter_Context *ctx, Evas_Filter_Program *pgm, Eina_Bool reuse, int object_x, int object_y);
void                     evas_filter_context_proxy_render_all(Evas_Filter_Context *ctx, Eo *eo_obj, void *output, Eina_Bool do_async);
void                     evas_filter_context_post_run_callback_set(Evas_Filter_Context *ctx, Evas_Filter_Cb cb, void *data);
Eina_Bool                evas_filter_context_buffers_allocate_all(Evas_Filter_Context *ctx);
void                     evas_filter_context_obscured_region_set(Evas_Filter_Context *ctx, Eina_Rectangle rect);

int                      evas_filter_buffer_empty_new(Evas_Filter_Context *ctx, int w, int h, Eina_Bool alpha_only);
int                      evas_filter_buffer_proxy_new(Evas_Filter_Context *ctx, Evas_Filter_Proxy_Binding *pb, int *w, int *h);
void                    *evas_filter_buffer_backing_get(Evas_Filter_Context *ctx, int bufid, Eina_Bool render);
Eina_Bool                evas_filter_buffer_backing_set(Evas_Filter_Context *ctx, int bufid, void *engine_buffer);

Eina_Bool                evas_filter_context_run(void *engine, void *output, Evas_Filter_Context *ctx);

Eina_Bool                evas_filter_font_draw(Evas_Filter_Context *ctx, void *engine, void *output, void *draw_context, int bufid, Evas_Font_Set *font, int x, int y, Evas_Text_Props *text_props, Eina_Bool do_async);
Eina_Bool                evas_filter_target_set(Evas_Filter_Context *ctx, void *draw_context, void *surface, int x, int y, const RGBA_Map *map);

// utility function
void                     _evas_filter_source_hash_free_cb(void *data);

/**
 * @brief Blend a source buffer into a destination buffer, allowing X,Y offsets, Alpha to RGBA conversion with color
 * @param ctx            Current filter chain
 * @param draw_context   Current Evas draw context. Current color is used when inbuf is ALPHA and outbuf is RGBA.
 * @param inbuf          Source buffer: ALPHA or RGBA
 * @param outbuf         Destination buffer: ALPHA or RGBA (note: must be RGBA if inbuf is RGBA)
 * @param ox             X offset in the destination buffer
 * @param oy             Y offset in the destination buffer
 * @param fillmode       Specifies whether to repeat or stretch the input onto its destination, and on which axes
 * @param alphaonly      If true, discard RGB during RGBA -> Alpha conversions.
 * @return               Filter command ID or -1 in case of error
 * @internal
 */
Evas_Filter_Command     *evas_filter_command_blend_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int ox, int oy, Evas_Filter_Fill_Mode fillmode, Eina_Bool alphaonly);

/**
 * @brief Apply a blur effect on a buffer
 * @param ctx            Current filter chain
 * @param draw_context   Current Evas draw context. Current color is used when inbuf is ALPHA and outbuf is RGBA.
 * @param inbuf          Source buffer: ALPHA or RGBA
 * @param outbuf         Destination buffer: ALPHA or RGBA (note: must be RGBA if inbuf is RGBA)
 * @param type           Type of blur: BOX, GAUSSIAN or MOTION
 * @param dx             X radius of blur. Can be negative ONLY for MOTION blur
 * @param dy             Y radius of blur. Can be negative ONLY for MOTION blur
 * @param ox             X offset in the destination buffer
 * @param oy             Y offset in the destination buffer
 * @param count          Number of times to repeat the operation (used for smooth fast blurs with box blur)
 * @param alphaonly      If true, discard RGB during RGBA -> Alpha conversions.
 * @return               Filter command ID or -1 in case of error
 * @internal
 */
Evas_Filter_Command     *evas_filter_command_blur_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, Evas_Filter_Blur_Type type, int dx, int dy, int ox, int oy, int count, Eina_Bool alphaonly);

/**
 * @brief Fill a buffer with the current color
 * @param ctx            Current filter chain
 * @param draw_context   Current Evas draw context. Current color is used when buf is RGBA, and clip is used to specify the fill area.
 * @param buf            Buffer: ALPHA or RGBA
 * @return               Filter command ID or -1 in case of error
 * @note The current draw context's render operation is ignored (always uses COPY mode).
 * @internal
 */
Evas_Filter_Command     *evas_filter_command_fill_add(Evas_Filter_Context *ctx, void *draw_context, int buf);

/**
 * @brief evas_filter_command_curve_add
 * @param ctx            Current filter chain
 * @param draw_context   Current Evas draw context. Current color is used when buf is RGBA, and clip is used to specify the fill area.
 * @param inbuf          Input buffer, ALPHA or RGBA.
 * @param outbuf         Output buffer, must have same colorspace as inbuf.
 * @param curve          The data points to use, must contain 256 values.
 * @param channel        Which channel to apply the curve (red, green, blue, alpha or RGB)
 * @return               Filter command ID or -1 in case of error
 * @internal
 */
Evas_Filter_Command     *evas_filter_command_curve_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, DATA8 *curve /* 256 elements */, Evas_Filter_Channel channel);

/**
 * @brief Grow/Shrink an image, as defined in image processing (this is not a scale algorithm!)
 * @param ctx            Current filter chain
 * @param draw_context   Current Evas draw context. Current color is used when inbuf is ALPHA and outbuf is RGBA.
 * @param inbuf          Source buffer: ALPHA or RGBA
 * @param outbuf         Destination buffer: ALPHA or RGBA (note: must be RGBA if inbuf is RGBA)
 * @param radius         Number of pixels to grow by. If negative, shrink instead of grow
 * @param smooth         Use smooth blur and curve for grow (default: true)
 * @param alphaonly      If true, discard RGB during RGBA -> Alpha conversions.
 * @return               Filter command ID or -1 in case of error
 * @internal
 */
Evas_Filter_Command     *evas_filter_command_grow_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int radius, Eina_Bool smooth, Eina_Bool alphaonly);

/**
 * @brief Apply a displacement map to a buffer. This will move pixels from the source to the destination based on pixel per pixel offset, as defined in the displacement map
 * @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 dispbuf        Displacement map. Should be an RGBA buffer, where the Red and Green channels are the displacement maps for X and Y. Can be also ALPHA buffer, in which case only one dimension can be specified (X or Y).
 * @param flags          Alters how the map is interpreted, @see Evas_Filter_Displacement_Flags
 * @param intensity      Maximum offset possible, if the map's value is maximal at this point (ie. 0 or 255)
 * @param fillmode       Specifies how to repeat and stretch the map to fit the target size
 * @return               Filter command ID or -1 in case of error
 * @internal
 */
Evas_Filter_Command     *evas_filter_command_displacement_map_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf, int dispbuf, Evas_Filter_Displacement_Flags flags, int intensity, Evas_Filter_Fill_Mode fillmode);

/**
 * @brief Apply a texture to a buffer
 * @param ctx            Current filter chain
 * @param draw_context   Current Evas draw context (ignored)
 * @param inbuf          Input buffer (Alpha or RGBA)
 * @param maskbuf        Texture buffer (Alpha or RGBA)
 * @param outbuf         Output buffer (Alpha or RGBA)
 * @param fillmode       Specifies how to repeat and stretch the mask to fit the target size
 * @return               Filter command ID or -1 in case of error
 * @note For the moment, inbuf can only be ALPHA, and output must be RGBA if mask is RGBA as well
 * @internal
 */
Evas_Filter_Command     *evas_filter_command_mask_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int maskbuf, int outbuf, Evas_Filter_Fill_Mode fillmode);

/**
 * @brief Apply a relief effect based on a bump map (Z map)
 * @param ctx              Current filter chain
 * @param draw_context     Current Evas draw context (ignored)
 * @param inbuf            Input buffer (Alpha or RGBA)
 * @param bumpbuf          Bump map (Alpha only), same size as inbuf. By definition, lows are black (alpha 0) and highs are white (alpha 255).
 * @param outbuf           Output buffer (Alpha or RGBA), same size as inbuf
 * @param azimuth          CCW angle in degrees from the X axis of the light direction. 0 is light from the right, 90 from the top, 180 from the left, 270 from the bottom. All values are valid.
 * @param elevation        Angle in degrees between the XY plane and the light. Only values from 0 (light is perfectly horizontal) to 90 (light comes from the viewer herself) are acceptable.
 * @param depth            Max depth in the bump map. Default value is 10.
 * @param specular_factor  Factor for the specular light effect (shininess). Ranges from 1.0 to 1000+ with logarithmic effects
 * @param black            Darkest color, defines the ambiant light
 * @param color            Light's normal color
 * @param white            Brightest color, used in the shininess effect
 * @param flags            Optional flags: compensation for darkening
 * @param fillmode         Specifies how to repeat and stretch the map to fit the target size
 * @return                 Filter command ID or -1 in case of error
 * @internal
 */
Evas_Filter_Command     *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)
 * @param ox             X offset
 * @param oy             Y offset
 * @return               Filter command ID or -1 in case of error
 * @internal
 */
Evas_Filter_Command     *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);

/**
 * @brief Remove color information from 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
 * @return               Filter command or NULL in case of error
 * @internal
 */
Evas_Filter_Command     *evas_filter_command_grayscale_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf);

/**
 * @brief Apply inverse color of 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
 * @return               Filter command or NULL in case of error
 * @internal
 */
Evas_Filter_Command     *evas_filter_command_inverse_color_add(Evas_Filter_Context *ctx, void *draw_context, int inbuf, int outbuf);

/* Simple binding between a filter object and its sources */
struct _Evas_Filter_Proxy_Binding
{
   Evas_Object *eo_proxy;
   Evas_Object *eo_source;
   Eina_Stringshare *name;
};

struct _Evas_Filter_Data_Binding
{
   EINA_INLIST;
   Eina_Stringshare *name;
   Eina_Stringshare *value;
   Eina_Bool execute : 1;
};

#undef EAPI
#define EAPI

#endif