efl/src/lib/evas/filters/evas_filter_utils.c

155 lines
4.1 KiB
C

/* Utility functions for the filters. */
#include "evas_filter_private.h"
Evas_Filter_Buffer *
evas_filter_buffer_scaled_get(Evas_Filter_Context *ctx,
Evas_Filter_Buffer *src,
unsigned w, unsigned h)
{
Evas_Filter_Buffer *fb;
Image_Entry *dstdata = NULL;
Image_Entry *srcdata;
void *drawctx;
srcdata = evas_filter_buffer_backing_get(ctx, src->id);
EINA_SAFETY_ON_NULL_RETURN_VAL(srcdata, NULL);
if (src->alpha_only)
{
// There is no supporting function in Evas for alpha scaling...
// but guess what? There is also no use case in the filters :)
CRI("Alpha buffer scaling is not supported");
return NULL;
}
fb = evas_filter_temporary_buffer_get(ctx, w, h, src->alpha_only);
if (!fb) return NULL;
dstdata = evas_filter_buffer_backing_get(ctx, fb->id);
if (!dstdata)
{
CRI("No backing found for buffer %d", fb->id);
return NULL;
}
if ((dstdata->w != w) || (dstdata->h != h))
{
CRI("Buffer size mismatch: got %dx%d requested %dx%d",
dstdata->w, dstdata->h, w, h);
return NULL;
}
if (ctx->gl_engine)
{
RGBA_Image *s = (RGBA_Image *) srcdata;
RGBA_Image *d = (RGBA_Image *) dstdata;
EINA_SAFETY_ON_NULL_RETURN_VAL(s->image.data, NULL);
EINA_SAFETY_ON_NULL_RETURN_VAL(d->image.data, NULL);
if (src->w == (int) w && src->h == (int) h)
memcpy(d->image.data, s->image.data, w * h * 4);
else
{
Eina_Bool ok;
RGBA_Draw_Context dc;
memset(&dc, 0, sizeof(dc));
dc.sli.h = 1;
dc.render_op = EVAS_RENDER_COPY;
ok = evas_common_scale_rgba_in_to_out_clip_sample
(s, d, &dc, 0, 0, src->w, src->h, 0, 0, w, h);
if (!ok)
{
ERR("RGBA Image scaling failed.");
return NULL;
}
}
}
else
{
drawctx = ENFN->context_new(ENDT);
ENFN->context_color_set(ENDT, drawctx, 255, 255, 255, 255);
ENFN->context_render_op_set(ENDT, drawctx, EVAS_RENDER_COPY);
ENFN->image_draw(ENDT, drawctx, dstdata, srcdata,
0, 0, src->w, src->h, // src
0, 0, w, h, // dst
EINA_TRUE, // smooth
EINA_FALSE); // Not async
ENFN->context_free(ENDT, drawctx);
}
return fb;
}
static Eina_Bool
_interpolate_none(DATA8 *output, DATA8 *points, int point_count)
{
int j, k, val, x1, x2;
for (j = 0; j < point_count; j++)
{
x1 = points[j * 2];
val = points[j * 2 + 1];
if (j < (point_count - 1))
x2 = points[(j + 1) * 2];
else
x2 = 256;
if (x2 < x1) return EINA_FALSE;
for (k = x1; k < x2; k++)
output[k] = val;
}
return EINA_TRUE;
}
static Eina_Bool
_interpolate_linear(DATA8 *output, DATA8 *points, int point_count)
{
int j, k, val1, val2, x1, x2;
for (j = 0; j < point_count; j++)
{
x1 = points[j * 2];
val1 = points[j * 2 + 1];
if (j < (point_count - 1))
{
x2 = points[(j + 1) * 2];
val2 = points[(j + 1) * 2 + 1];
}
else
{
x2 = 256;
val2 = val1;
}
if (x2 < x1) return EINA_FALSE;
for (k = x1; k < x2; k++)
output[k] = val1 + ((val2 - val1) * (k - x1)) / (x2 - x1);
}
return EINA_TRUE;
}
Eina_Bool
evas_filter_interpolate(DATA8 *output, DATA8 *points, int point_count,
Evas_Filter_Interpolation_Mode mode)
{
switch (mode)
{
case EVAS_FILTER_INTERPOLATION_MODE_NONE:
return _interpolate_none(output, points, point_count);
case EVAS_FILTER_INTERPOLATION_MODE_LINEAR:
default:
return _interpolate_linear(output, points, point_count);
}
}
int
evas_filter_smallest_pow2_larger_than(int val)
{
int n;
for (n = 0; n < 32; n++)
if (val <= (1 << n)) return n;
ERR("Value %d is too damn high!", val);
return 32;
}