efl/legacy/evas/src/lib/engines/common/evas_scale_sample.c

410 lines
12 KiB
C

#include "evas_common.h"
void scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int src_region_x, int src_region_y, int src_region_w, int src_region_h, int dst_region_x, int dst_region_y, int dst_region_w, int dst_region_h);
#ifndef BUILD_SCALE_SMOOTH
#ifdef BUILD_SCALE_SAMPLE
void
evas_common_scale_rgba_in_to_out_clip_smooth(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
int src_region_x, int src_region_y,
int src_region_w, int src_region_h,
int dst_region_x, int dst_region_y,
int dst_region_w, int dst_region_h)
{
evas_common_scale_rgba_in_to_out_clip_sample(src, dst, dc,
src_region_x, src_region_y,
src_region_w, src_region_h,
dst_region_x, dst_region_y,
dst_region_w, dst_region_h);
}
#endif
#endif
#ifdef BUILD_SCALE_SAMPLE
void
evas_common_scale_rgba_in_to_out_clip_sample(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
int src_region_x, int src_region_y,
int src_region_w, int src_region_h,
int dst_region_x, int dst_region_y,
int dst_region_w, int dst_region_h)
{
int c, cx, cy, cw, ch;
Cutout_Rect *rects, *r;
Evas_Object_List *l;
/* handle cutouts here! */
if ((dst_region_w <= 0) || (dst_region_h <= 0)) return;
if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->image->w, dst->image->h)))
return;
/* no cutouts - cut right to the chase */
if (!dc->cutout.rects)
{
scale_rgba_in_to_out_clip_sample_internal(src, dst, dc,
src_region_x, src_region_y,
src_region_w, src_region_h,
dst_region_x, dst_region_y,
dst_region_w, dst_region_h);
return;
}
/* save out clip info */
c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
evas_common_draw_context_clip_clip(dc, 0, 0, dst->image->w, dst->image->h);
evas_common_draw_context_clip_clip(dc, dst_region_x, dst_region_y, dst_region_w, dst_region_h);
/* our clip is 0 size.. abort */
if ((dc->clip.w <= 0) || (dc->clip.h <= 0))
{
dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
return;
}
rects = evas_common_draw_context_apply_cutouts(dc);
for (l = (Evas_Object_List *)rects; l; l = l->next)
{
r = (Cutout_Rect *)l;
evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
scale_rgba_in_to_out_clip_sample_internal(src, dst, dc,
src_region_x, src_region_y,
src_region_w, src_region_h,
dst_region_x, dst_region_y,
dst_region_w, dst_region_h);
}
evas_common_draw_context_apply_free_cutouts(rects);
/* restore clip info */
dc->clip.use = c; dc->clip.x = cx; dc->clip.y = cy; dc->clip.w = cw; dc->clip.h = ch;
}
void
scale_rgba_in_to_out_clip_sample_internal(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
int src_region_x, int src_region_y,
int src_region_w, int src_region_h,
int dst_region_x, int dst_region_y,
int dst_region_w, int dst_region_h)
{
int x, y;
int *lin_ptr;
DATA32 *buf, *dptr;
DATA32 **row_ptr;
DATA32 *ptr, *dst_ptr, *src_data, *dst_data;
int dst_jump;
int dst_clip_x, dst_clip_y, dst_clip_w, dst_clip_h;
int src_w, src_h, dst_w, dst_h;
if (!(RECTS_INTERSECT(dst_region_x, dst_region_y, dst_region_w, dst_region_h, 0, 0, dst->image->w, dst->image->h)))
return;
if (!(RECTS_INTERSECT(src_region_x, src_region_y, src_region_w, src_region_h, 0, 0, src->image->w, src->image->h)))
return;
src_w = src->image->w;
src_h = src->image->h;
dst_w = dst->image->w;
dst_h = dst->image->h;
src_data = src->image->data;
dst_data = dst->image->data;
if (dc->clip.use)
{
dst_clip_x = dc->clip.x;
dst_clip_y = dc->clip.y;
dst_clip_w = dc->clip.w;
dst_clip_h = dc->clip.h;
if (dst_clip_x < 0)
{
dst_clip_w += dst_clip_x;
dst_clip_x = 0;
}
if (dst_clip_y < 0)
{
dst_clip_h += dst_clip_y;
dst_clip_y = 0;
}
if ((dst_clip_x + dst_clip_w) > dst_w)
dst_clip_w = dst_w - dst_clip_x;
if ((dst_clip_y + dst_clip_h) > dst_h)
dst_clip_h = dst_h - dst_clip_y;
}
else
{
dst_clip_x = 0;
dst_clip_y = 0;
dst_clip_w = dst_w;
dst_clip_h = dst_h;
}
if (dst_clip_x < dst_region_x)
{
dst_clip_w += dst_clip_x - dst_region_x;
dst_clip_x = dst_region_x;
}
if ((dst_clip_x + dst_clip_w) > (dst_region_x + dst_region_w))
dst_clip_w = dst_region_x + dst_region_w - dst_clip_x;
if (dst_clip_y < dst_region_y)
{
dst_clip_h += dst_clip_y - dst_region_y;
dst_clip_y = dst_region_y;
}
if ((dst_clip_y + dst_clip_h) > (dst_region_y + dst_region_h))
dst_clip_h = dst_region_y + dst_region_h - dst_clip_y;
if ((src_region_w <= 0) || (src_region_h <= 0) ||
(dst_region_w <= 0) || (dst_region_h <= 0) ||
(dst_clip_w <= 0) || (dst_clip_h <= 0))
return;
/* sanitise x */
if (src_region_x < 0)
{
dst_region_x -= (src_region_x * dst_region_w) / src_region_w;
dst_region_w += (src_region_x * dst_region_w) / src_region_w;
src_region_w += src_region_x;
src_region_x = 0;
}
if (src_region_x >= src_w) return;
if ((src_region_x + src_region_w) > src_w)
{
dst_region_w = (dst_region_w * (src_w - src_region_x)) / (src_region_w);
src_region_w = src_w - src_region_x;
}
if (dst_region_w <= 0) return;
if (src_region_w <= 0) return;
if (dst_clip_x < 0)
{
dst_clip_w += dst_clip_x;
dst_clip_x = 0;
}
if (dst_clip_w <= 0) return;
if (dst_clip_x >= dst_w) return;
if (dst_clip_x < dst_region_x)
{
dst_clip_w += (dst_clip_x - dst_region_x);
dst_clip_x = dst_region_x;
}
if ((dst_clip_x + dst_clip_w) > dst_w)
{
dst_clip_w = dst_w - dst_clip_x;
}
if (dst_clip_w <= 0) return;
/* sanitise y */
if (src_region_y < 0)
{
dst_region_y -= (src_region_y * dst_region_h) / src_region_h;
dst_region_h += (src_region_y * dst_region_h) / src_region_h;
src_region_h += src_region_y;
src_region_y = 0;
}
if (src_region_y >= src_h) return;
if ((src_region_y + src_region_h) > src_h)
{
dst_region_h = (dst_region_h * (src_h - src_region_y)) / (src_region_h);
src_region_h = src_h - src_region_y;
}
if (dst_region_h <= 0) return;
if (src_region_h <= 0) return;
if (dst_clip_y < 0)
{
dst_clip_h += dst_clip_y;
dst_clip_y = 0;
}
if (dst_clip_h <= 0) return;
if (dst_clip_y >= dst_h) return;
if (dst_clip_y < dst_region_y)
{
dst_clip_h += (dst_clip_y - dst_region_y);
dst_clip_y = dst_region_y;
}
if ((dst_clip_y + dst_clip_h) > dst_h)
{
dst_clip_h = dst_h - dst_clip_y;
}
if (dst_clip_h <= 0) return;
/* allocate scale lookup tables */
lin_ptr = malloc(dst_clip_w * sizeof(int));
if (!lin_ptr) goto no_lin_ptr;
row_ptr = malloc(dst_clip_h * sizeof(DATA32 *));
if (!row_ptr) goto no_row_ptr;
/* figure out dst jump */
dst_jump = dst_w - dst_clip_w;
/* figure out dest start ptr */
dst_ptr = dst_data + dst_clip_x + (dst_clip_y * dst_w);
if (dc->mod.use)
{
Gfx_Func_Blend_Src_Cmod_Dst func;
func = evas_common_draw_func_blend_cmod_get(src, dst, dst_clip_w);
/* if 1:1 scale */
if ((dst_region_w == src_region_w) &&
(dst_region_h == src_region_h))
{
ptr = src_data + ((dst_clip_y - dst_region_y + src_region_y) * src_w) + (dst_clip_x - dst_region_x) + src_region_x;
for (y = 0; y < dst_clip_h; y++)
{
/* * blend here [clip_w *] ptr -> dst_ptr * */
func(ptr, dst_ptr, dst_clip_w, dc->mod.r, dc->mod.g, dc->mod.b, dc->mod.a);
ptr += src_w;
dst_ptr += dst_w;
}
}
else
{
/* a scanline buffer */
buf = malloc(dst_clip_w * sizeof(DATA32));
if (!buf) goto no_buf;
/* fill scale tables */
for (x = 0; x < dst_clip_w; x++)
lin_ptr[x] = (((x + dst_clip_x - dst_region_x) * src_region_w) / dst_region_w) + src_region_x;
for (y = 0; y < dst_clip_h; y++)
row_ptr[y] = src_data + (((((y + dst_clip_y - dst_region_y) * src_region_h) / dst_region_h)
+ src_region_y) * src_w);
/* scale to dst */
dptr = dst_ptr;
for (y = 0; y < dst_clip_h; y++)
{
dst_ptr = buf;
for (x = 0; x < dst_clip_w; x++)
{
ptr = row_ptr[y] + lin_ptr[x];
*dst_ptr = *ptr;
dst_ptr++;
}
/* * blend here [clip_w *] buf -> dptr * */
func(buf, dptr, dst_clip_w, dc->mod.r, dc->mod.g, dc->mod.b, dc->mod.a);
dptr += dst_w;
}
free(buf);
}
}
else if (dc->mul.use)
{
Gfx_Func_Blend_Src_Mul_Dst func;
func = evas_common_draw_func_blend_mul_get(src, dc->mul.col, dst, dst_clip_w);
/* if 1:1 scale */
if ((dst_region_w == src_region_w) &&
(dst_region_h == src_region_h))
{
ptr = src_data + ((dst_clip_y - dst_region_y + src_region_y) * src_w) + (dst_clip_x - dst_region_x) + src_region_x;
for (y = 0; y < dst_clip_h; y++)
{
/* * blend here [clip_w *] ptr -> dst_ptr * */
func(ptr, dst_ptr, dst_clip_w, dc->mul.col);
ptr += src_w;
dst_ptr += dst_w;
}
}
else
{
/* a scanline buffer */
buf = malloc(dst_clip_w * sizeof(DATA32));
if (!buf) goto no_buf;
/* fill scale tables */
for (x = 0; x < dst_clip_w; x++)
lin_ptr[x] = (((x + dst_clip_x - dst_region_x) * src_region_w) / dst_region_w) + src_region_x;
for (y = 0; y < dst_clip_h; y++)
row_ptr[y] = src_data + (((((y + dst_clip_y - dst_region_y) * src_region_h) / dst_region_h)
+ src_region_y) * src_w);
/* scale to dst */
dptr = dst_ptr;
for (y = 0; y < dst_clip_h; y++)
{
dst_ptr = buf;
for (x = 0; x < dst_clip_w; x++)
{
ptr = row_ptr[y] + lin_ptr[x];
*dst_ptr = *ptr;
dst_ptr++;
}
/* * blend here [clip_w *] buf -> dptr * */
func(buf, dptr, dst_clip_w, dc->mul.col);
dptr += dst_w;
}
free(buf);
}
}
else
{
Gfx_Func_Blend_Src_Dst func;
func = evas_common_draw_func_blend_get(src, dst, dst_clip_w);
/* if 1:1 scale */
if ((dst_region_w == src_region_w) &&
(dst_region_h == src_region_h))
{
ptr = src_data + ((dst_clip_y - dst_region_y + src_region_y) * src_w) + (dst_clip_x - dst_region_x) + src_region_x;
for (y = 0; y < dst_clip_h; y++)
{
/* * blend here [clip_w *] ptr -> dst_ptr * */
func(ptr, dst_ptr, dst_clip_w);
ptr += src_w;
dst_ptr += dst_w;
}
}
else
{
/* a scanline buffer */
buf = malloc(dst_clip_w * sizeof(DATA32));
if (!buf) goto no_buf;
/* fill scale tables */
for (x = 0; x < dst_clip_w; x++)
lin_ptr[x] = (((x + dst_clip_x - dst_region_x) * src_region_w) / dst_region_w) + src_region_x;
for (y = 0; y < dst_clip_h; y++)
row_ptr[y] = src_data + (((((y + dst_clip_y - dst_region_y) * src_region_h) / dst_region_h)
+ src_region_y) * src_w);
/* scale to dst */
dptr = dst_ptr;
for (y = 0; y < dst_clip_h; y++)
{
dst_ptr = buf;
for (x = 0; x < dst_clip_w; x++)
{
ptr = row_ptr[y] + lin_ptr[x];
*dst_ptr = *ptr;
dst_ptr++;
}
/* * blend here [clip_w *] buf -> dptr * */
func(buf, dptr, dst_clip_w);
dptr += dst_w;
}
free(buf);
}
}
no_buf:
/* free scale tables */
free(row_ptr);
no_row_ptr:
free(lin_ptr);
//_WIN32_WCE
no_lin_ptr: ;
}
#else
#ifdef BUILD_SCALE_SMOOTH
void
evas_common_scale_rgba_in_to_out_clip_sample(RGBA_Image *src, RGBA_Image *dst,
RGBA_Draw_Context *dc,
int src_region_x, int src_region_y,
int src_region_w, int src_region_h,
int dst_region_x, int dst_region_y,
int dst_region_w, int dst_region_h)
{
evas_common_scale_rgba_in_to_out_clip_smooth(src, dst, dc,
src_region_x, src_region_y,
src_region_w, src_region_h,
dst_region_x, dst_region_y,
dst_region_w, dst_region_h);
}
#endif
#endif