add color to the vertexes in map. this allows for fading/shading of

reflections, goraud shading for smooth 3d surfaces, mor realistic lighting
etc. etc. it comes at a small cost, but worth it.



SVN revision: 43384
This commit is contained in:
Carsten Haitzler 2009-11-01 01:32:23 +00:00
parent e014cd7d72
commit 069de70853
11 changed files with 492 additions and 215 deletions

View File

@ -104,8 +104,7 @@ typedef enum _Evas_Object_Table_Homogeneous_Mode
typedef struct _Evas_Transform Evas_Transform; /**< An Evas projective or affine transform */
typedef struct _Evas_Coord_Rectangle Evas_Coord_Rectangle; /**< A generic rectangle handle */
typedef struct _Evas_Smart_Class Evas_Smart_Class; /**< A smart object base class */
typedef struct _Evas_Map_Point Evas_Map_Point; /**< A point with attributes for x, y, z texture u & v etc. */
typedef struct _Evas_Map Evas_Map; /**< An array of map points */
typedef struct _Evas_Map Evas_Map; /**< An array of map points */
typedef struct _Evas Evas; /**< An Evas canvas handle */
typedef struct _Evas_Object Evas_Object; /**< An Evas Object handle */
@ -868,7 +867,9 @@ extern "C" {
EAPI void evas_map_point_coord_get (const Evas_Map *m, int idx, Evas_Coord *x, Evas_Coord *y, Evas_Coord *z);
EAPI void evas_map_point_image_uv_set (Evas_Map *m, int idx, double u, double v);
EAPI void evas_map_point_image_uv_get (const Evas_Map *m, int idx, double *u, double *v);
EAPI void evas_map_point_color_set (Evas_Map *m, int idx, int r, int g, int b, int a);
EAPI void evas_map_point_color_get (const Evas_Map *m, int idx, int *r, int *g, int *b, int *a);
/* smart objects */
EINA_DEPRECATED EAPI Evas_Smart *evas_smart_new (const char *name, void (*func_add) (Evas_Object *obj), void (*func_del) (Evas_Object *obj), void (*func_layer_set) (Evas_Object *obj, int l), void (*func_raise) (Evas_Object *obj), void (*func_lower) (Evas_Object *obj), void (*func_stack_above) (Evas_Object *obj, Evas_Object *above), void (*func_stack_below) (Evas_Object *obj, Evas_Object *below), void (*func_move) (Evas_Object *obj, Evas_Coord x, Evas_Coord y), void (*func_resize) (Evas_Object *obj, Evas_Coord w, Evas_Coord h), void (*func_show) (Evas_Object *obj), void (*func_hide) (Evas_Object *obj), void (*func_color_set) (Evas_Object *obj, int r, int g, int b, int a), void (*func_clip_set) (Evas_Object *obj, Evas_Object *clip), void (*func_clip_unset) (Evas_Object *obj), const void *data) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_MALLOC;
EAPI void evas_smart_free (Evas_Smart *s) EINA_ARG_NONNULL(1);

View File

@ -63,23 +63,23 @@ _evas_map_calc_map_geometry(Evas_Object *obj)
static inline Evas_Map *
_evas_map_new(int count)
{
int i;
Evas_Map *m = calloc(1, sizeof(Evas_Map) + count * sizeof(Evas_Map_Point));
if (!m) return NULL;
m->count = count;
m->alpha = 1;
m->smooth = 1;
for (i = 0; i < count; i++)
{
m->points[i].r = 255;
m->points[i].g = 255;
m->points[i].b = 255;
m->points[i].a = 255;
}
return m;
}
static inline Evas_Map *
_evas_map_dup(const Evas_Map *orig)
{
Evas_Map *copy = _evas_map_new(orig->count);
if (!copy) return NULL;
memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
return copy;
}
static inline Eina_Bool
_evas_map_copy(Evas_Map *dst, const Evas_Map *src)
{
@ -94,6 +94,17 @@ _evas_map_copy(Evas_Map *dst, const Evas_Map *src)
return EINA_TRUE;
}
static inline Evas_Map *
_evas_map_dup(const Evas_Map *orig)
{
Evas_Map *copy = _evas_map_new(orig->count);
if (!copy) return NULL;
memcpy(copy->points, orig->points, orig->count * sizeof(Evas_Map_Point));
copy->smooth = orig->smooth;
copy->alpha = orig->alpha;
return copy;
}
static inline void
_evas_map_free(Evas_Map *m)
{
@ -516,6 +527,67 @@ evas_map_point_image_uv_get(const Evas_Map *m, int idx, double *u, double *v)
if (v) *v = 0.0;
}
/**
* Set the color of a vertex in the map
*
* This sets the color of the vertex in the map. Colors will be linearly
* interpolated between vertex points through the map. Color will multiply
* the "texture" pixels (like GL_MODULATE in OpenGL). The default color of
* a vertex in a map is white solid (255, 255, 255, 255) which means it will
* have no affect on modifying the texture pixels.
*
* @param m map to change the color of.
* @param idx index of point to change. Must be smaller than map size.
* @param r red (0 - 255)
* @param g green (0 - 255)
* @param b blue (0 - 255)
* @param a alpha (0 - 255)
*
* @see evas_map_point_coord_set()
* @see evas_object_map_set()
*/
EAPI void
evas_map_point_color_set(Evas_Map *m, int idx, int r, int g, int b, int a)
{
Evas_Map_Point *p;
if (!m) return;
if (idx >= m->count) return;
p = m->points + idx;
p->r = r;
p->g = g;
p->b = b;
p->a = a;
}
/**
* Get the color set on a vertex in the map
*
* This gets the color set by evas_map_point_color_set() on the given vertex
* of the map.
*
* @param m map to get the color of the vertex from.
* @param idx index of point get. Must be smaller than map size.
* @param r pointer to red return
* @param g pointer to green return
* @param b pointer to blue return
* @param a pointer to alpha return (0 - 255)
*
* @see evas_map_point_coord_set()
* @see evas_object_map_set()
*/
EAPI void
evas_map_point_color_get(const Evas_Map *m, int idx, int *r, int *g, int *b, int *a)
{
Evas_Map_Point *p;
if (!m) return;
if (idx >= m->count) return;
p = m->points + idx;
if (r) *r = p->r;
if (g) *g = p->g;
if (b) *b = p->b;
if (a) *a = p->a;
}
/****************************************************************************/
/* util functions for manipulating maps, so you don't need to know the math */
/****************************************************************************/

View File

@ -2346,7 +2346,10 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
pt->z = (p->z) << FP;
pt->u = p->u * FP1;
pt->v = p->v * FP1;
}
pt->col =
(((DATA32)p->a) << 24) | (((DATA32)p->r) << 16) |
(((DATA32)p->g) << 8) | (((DATA32)p->b));
}
obj->layer->evas->engine.func->image_map4_draw
(output, context, surface, o->engine_data, pts,
o->cur.smooth_scale | obj->cur.map->smooth, 0);

View File

@ -383,7 +383,7 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, int
{
const Evas_Map_Point *p, *p_end;
RGBA_Map_Point pts[4], *pt;
void *ctx, *ctx2;
void *ctx;
int sw, sh;
int changed = 0;
@ -401,6 +401,9 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, int
pt->z = (p->z) << FP;
pt->u = p->u * FP1;
pt->v = p->v * FP1;
pt->col =
(((DATA32)p->a) << 24) | (((DATA32)p->r) << 16) |
(((DATA32)p->g) << 8) | (((DATA32)p->b));
}
if (obj->cur.map->surface)
@ -448,21 +451,22 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface, int
// clear surface before re-render
if ((changed) && (obj->cur.map->surface))
{
ctx2 = e->engine.func->context_new(e->engine.data.output);
e->engine.func->context_color_set
(e->engine.data.output, ctx2, 0, 0, 0, 0);
e->engine.func->context_render_op_set
(e->engine.data.output, ctx2, EVAS_RENDER_COPY);
e->engine.func->rectangle_draw(e->engine.data.output,
ctx2,
obj->cur.map->surface,
0, 0,
obj->cur.map->surface_w,
obj->cur.map->surface_h);
e->engine.func->context_free(e->engine.data.output, ctx2);
if (obj->cur.map->alpha)
{
ctx = e->engine.func->context_new(e->engine.data.output);
e->engine.func->context_color_set
(e->engine.data.output, ctx, 0, 0, 0, 0);
e->engine.func->context_render_op_set
(e->engine.data.output, ctx, EVAS_RENDER_COPY);
e->engine.func->rectangle_draw(e->engine.data.output,
ctx,
obj->cur.map->surface,
0, 0,
obj->cur.map->surface_w,
obj->cur.map->surface_h);
e->engine.func->context_free(e->engine.data.output, ctx);
}
ctx = e->engine.func->context_new(e->engine.data.output);
// FIXME: only re-render if obj changed or smart children or size changed etc.
if (obj->smart.smart)
{

View File

@ -109,7 +109,9 @@ evas_scale_smooth_scaler_up.c \
evas_scale_span.h \
evas_pipe.h \
evas_intl_utils.h \
evas_map_image_internal.c
evas_map_image_internal.c \
evas_map_image_core.c \
evas_map_image_loop.c
libevas_engine_common_la_DEPENDENCIES = \
$(top_builddir)/config.h

View File

@ -26,6 +26,7 @@ struct _Span
int x1, x2;
FPc o1, o2;
FPc u[2], v[2];
DATA32 col[2];
};
struct _Line
@ -45,13 +46,26 @@ _interp(int x1, int x2, int p, FPc u1, FPc u2)
return u1 + u;
}
static DATA32
_interp_col(int x1, int x2, int p, DATA32 col1, DATA32 col2)
{
DATA32 col;
x2 -= x1;
p -= x1;
p = (p << 8) / (x2 + 1);
return INTERP_256(p, col2, col1);
}
static void
_limit(Span *s, int c1, int c2)
_limit(Span *s, int c1, int c2, int nocol)
{
if (s->x1 < c1)
{
s->u[0] = _interp(s->x1, s->x2, c1, s->u[0], s->u[1]);
s->v[0] = _interp(s->x1, s->x2, c1, s->v[0], s->v[1]);
if (!nocol)
s->col[0] = _interp_col(s->x1, s->x2, c1, s->col[0], s->col[1]);
s->x1 = c1;
s->o1 = c1 << FP;
}
@ -59,6 +73,8 @@ _limit(Span *s, int c1, int c2)
{
s->u[1] = _interp(s->x1, s->x2, c2, s->u[0], s->u[1]);
s->v[1] = _interp(s->x1, s->x2, c2, s->v[0], s->v[1]);
if (!nocol)
s->col[1] = _interp_col(s->x1, s->x2, c2, s->col[0], s->col[1]);
s->x2 = c2;
s->o2 = c2 << FP;
}
@ -72,6 +88,7 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
int py[4];
int edge[4][4], edge_num, swapped, order[4];
FPc uv[4][2], u, v, x, h, t;
DATA32 col[4];
#if 1 // maybe faster on x86?
for (i = 0; i < 4; i++) py[i] = p[i].y >> FP;
@ -83,12 +100,14 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
if ((PY(0) == PY(1)) && (PY(0) == PY(2)) && (PY(0) == PY(3)))
{
int leftp, rightp;
int nocol = 1;
leftp = rightp = 0;
for (i = 1; i < 4; i++)
{
if (p[i].x < p[leftp].x) leftp = i;
if (p[i].x > p[rightp].x) rightp = i;
if (p[i].col != 0xffffffff) nocol = 0;
}
for (y = ystart; y <= yend; y++)
{
@ -100,16 +119,18 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
spans[yp].span[i].o1 = p[leftp].x;
spans[yp].span[i].u[0] = p[leftp].u;
spans[yp].span[i].v[0] = p[leftp].v;
spans[yp].span[i].col[0] = p[leftp].col;
spans[yp].span[i].x2 = p[rightp].x >> FP;
spans[yp].span[i].o2 = p[rightp].x;
spans[yp].span[i].u[1] = p[rightp].u;
spans[yp].span[i].v[1] = p[rightp].v;
spans[yp].span[i].col[1] = p[rightp].col;
if ((spans[yp].span[i].x1 >= (cx + cw)) ||
(spans[yp].span[i].x2 < cx))
spans[yp].span[i].x1 = -1;
else
{
_limit(&(spans[yp].span[i]), cx, cx + cw);
_limit(&(spans[yp].span[i]), cx, cx + cw, nocol);
i++;
spans[yp].span[i].x1 = -1;
}
@ -122,6 +143,8 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
for (y = ystart; y <= yend; y++)
{
int nocol = 1;
yp = y - ystart;
edge_num = 0;
for (i = 0; i < 4; i++)
@ -138,12 +161,14 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
edge[edge_num][1] = i;
edge_num++;
}
if (p[i].col != 0xffffffff) nocol = 0;
}
// calculate line x points for each edge
for (i = 0; i < edge_num; i++)
{
int e1 = edge[i][0];
int e2 = edge[i][1];
FPc t256;
h = (p[e2].y - p[e1].y) >> FP; // height of edge
t = (((y << FP) + (FP1 - 1)) - p[e1].y) >> FP;
@ -156,6 +181,9 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
v = p[e2].v - p[e1].v;
v = p[e1].v + ((v * t) / h);
t256 = (t << 8) / h; // maybe * 255?
col[i] = INTERP_256(t256, p[e2].col, p[e1].col);
uv[i][1] = v;
uv[i][0] = u;
edge[i][2] = x >> FP;
@ -186,16 +214,19 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
spans[yp].span[i].o1 = edge[order[0]][3];
spans[yp].span[i].u[0] = uv[order[0]][0];
spans[yp].span[i].v[0] = uv[order[0]][1];
spans[yp].span[i].col[0] = col[order[0]];
spans[yp].span[i].x2 = edge[order[1]][2];
spans[yp].span[i].o2 = edge[order[1]][3];
spans[yp].span[i].u[1] = uv[order[1]][0];
spans[yp].span[i].v[1] = uv[order[1]][1];
spans[yp].span[i].col[1] = col[order[1]];
if ((spans[yp].span[i].x1 >= (cx + cw)) ||
(spans[yp].span[i].x2 < cx))
spans[yp].span[i].x1 = -1;
else
{
_limit(&(spans[yp].span[i]), cx, cx + cw);
_limit(&(spans[yp].span[i]), cx, cx + cw, nocol);
i++;
spans[yp].span[i].x1 = -1;
}
@ -206,23 +237,29 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
spans[yp].span[i].x1 = edge[order[0]][2];
spans[yp].span[i].u[0] = uv[order[0]][0];
spans[yp].span[i].v[0] = uv[order[0]][1];
spans[yp].span[i].col[0] = col[order[0]];
spans[yp].span[i].x2 = edge[order[1]][2];
spans[yp].span[i].u[1] = uv[order[1]][0];
spans[yp].span[i].v[1] = uv[order[1]][1];
spans[yp].span[i].col[1] = col[order[1]];
if ((spans[yp].span[i].x1 >= (cx + cw)) ||
(spans[yp].span[i].x2 < cx))
spans[yp].span[i].x1 = -1;
else
{
_limit(&(spans[yp].span[i]), cx, cx + cw);
_limit(&(spans[yp].span[i]), cx, cx + cw, nocol);
i++;
}
spans[yp].span[i].x1 = edge[order[2]][2];
spans[yp].span[i].u[0] = uv[order[2]][0];
spans[yp].span[i].v[0] = uv[order[2]][1];
spans[yp].span[i].col[0] = col[order[2]];
spans[yp].span[i].x2 = edge[order[3]][2];
spans[yp].span[i].u[1] = uv[order[3]][0];
spans[yp].span[i].v[1] = uv[order[3]][1];
spans[yp].span[i].col[1] = col[order[3]];
if ((spans[yp].span[i].x1 >= (cx + cw)) ||
(spans[yp].span[i].x2 < cx))
spans[yp].span[i].x1 = -1;
@ -231,7 +268,7 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
int l = cx;
if (i > 0) l = spans[yp].span[i - 1].x2;
_limit(&(spans[yp].span[i]), l, cx + cw);
_limit(&(spans[yp].span[i]), l, cx + cw, nocol);
}
}
else

View File

@ -22,6 +22,7 @@ struct _RGBA_Map_Point
FPc x, y; // x, y screenspace
FPc z; // z in world space. optional
FPc u, v; // u, v in tex coords
DATA32 col; // color at this point
};
EAPI void

View File

@ -0,0 +1,198 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#undef SCALE_USING_MMX
{
if (smooth)
{
for (y = ystart; y <= yend; y++)
{
int x, w, ww;
FPc u, v, ud, vd, dv;
DATA32 *d, *s, *so[4], val1, val2;
#ifdef COLMUL
FPc cv, cd, cc; // col
DATA32 c1, c2; // col
#endif
Line *line;
#ifdef SCALE_USING_MMX
pxor_r2r(mm0, mm0);
MOV_A2R(ALPHA_255, mm5)
#endif
line = &(spans[y - ystart]);
for (i = 0; i < 2; i++)
{
Span *span;
span = &(line->span[i]);
if (span->x1 >= 0)
{
long long tl;
x = span->x1;
w = (span->x2 - x);
if (w <= 0) continue;
dv = (span->o2 - span->o1);
if (dv <= 0) continue;
ww = w;
u = span->u[0] << FPI;
v = span->v[0] << FPI;
ud = ((span->u[1] << FPI) - u) / w;
vd = ((span->v[1] << FPI) - v) / w;
tl = (long long)ud * (w << FP);
tl = tl / dv;
ud = tl;
u -= (ud * (span->o1 - (span->x1 << FP))) / FP1;
tl = (long long)vd * (w << FP);
tl = tl / dv;
vd = tl;
v -= (vd * (span->o1 - (span->x1 << FP))) / FP1;
if (ud < 0) u -= 1;
if (vd < 0) v -= 1;
if (direct)
d = dst->image.data + (y * dst->cache_entry.w) + x;
else
d = buf;
#define SMOOTH 1
#ifdef COLMUL
c1 = span->col[0]; // col
c2 = span->col[1]; // col
cv = 0; // col
cd = (255 << 16) / w; // col
if (c1 == c2)
{
if (c1 == 0xffffffff)
{
#endif
#include "evas_map_image_loop.c"
#ifdef COLMUL
}
else if ((c1 == 0x0000ff) && (!src->cache_entry.flags.alpha))
{
// all black line
# define COLBLACK 1
# include "evas_map_image_loop.c"
# undef COLBLACK
}
else if (c1 == 0x000000)
{
// skip span
}
else
{
// generic loop
# include "evas_map_image_loop.c"
}
}
else
{
# include "evas_map_image_loop.c"
}
#endif
if (!direct)
{
d = dst->image.data;
d += (y * dst->cache_entry.w) + x;
func(buf, NULL, dc->mul.col, d, w);
}
}
else break;
}
}
}
else
{
for (y = ystart; y <= yend; y++)
{
int x, w, ww;
FPc u, v, ud, vd;
DATA32 *d, *s;
#ifdef COLMUL
FPc cv, cd, cc; // col
DATA32 c1, c2; // col
#endif
Line *line;
line = &(spans[y - ystart]);
for (i = 0; i < 2; i++)
{
Span *span;
span = &(line->span[i]);
if (span->x1 >= 0)
{
x = span->x1;
w = (span->x2 - x);
if (w <= 0) continue;
ww = w;
u = span->u[0] << FPI;
v = span->v[0] << FPI;
ud = ((span->u[1] << FPI) - u) / w;
vd = ((span->v[1] << FPI) - v) / w;
if (ud < 0) u -= 1;
if (vd < 0) v -= 1;
if (direct)
d = dst->image.data + (y * dst->cache_entry.w) + x;
else
d = buf;
#undef SMOOTH
#ifdef COLMUL
c1 = span->col[0]; // col
c2 = span->col[1]; // col
cv = 0; // col
cd = (255 << 16) / w; // col
if (c1 == c2)
{
if (c1 == 0xffffffff)
{
#endif
#include "evas_map_image_loop.c"
#ifdef COLMUL
}
else if ((c1 == 0x0000ff) && (!src->cache_entry.flags.alpha))
{
// all black line
# define COLBLACK 1
# include "evas_map_image_loop.c"
# undef COLBLACK
}
else if (c1 == 0x000000)
{
// skip span
}
else
{
// generic loop
# include "evas_map_image_loop.c"
}
}
else
{
// generic loop
# include "evas_map_image_loop.c"
}
#endif
if (!direct)
{
d = dst->image.data;
d += (y * dst->cache_entry.w) + x;
func(buf, NULL, dc->mul.col, d, w);
}
}
else break;
}
}
}
}

View File

@ -14,6 +14,8 @@ FUNC_NAME(RGBA_Image *src, RGBA_Image *dst,
Line *spans;
DATA32 *buf, *sp;
RGBA_Gfx_Func func;
int havea = 0;
int havecol = 4;
// get the clip
c = dc->clip.use; cx = dc->clip.x; cy = dc->clip.y; cw = dc->clip.w; ch = dc->clip.h;
@ -27,10 +29,15 @@ FUNC_NAME(RGBA_Image *src, RGBA_Image *dst,
// find y yop line and y bottom line
ytop = p[0].y;
if ((p[0].col >> 24) < 0xff) havea = 1;
if (p[0].col == 0xffffffff) havecol--;
for (i = 1; i < 4; i++)
{
if (p[i].y < ytop) ytop = p[i].y;
if ((p[i].col >> 24) < 0xff) havea = 1;
if (p[i].col == 0xffffffff) havecol--;
}
ybottom = p[0].y;
for (i = 1; i < 4; i++)
{
@ -81,198 +88,33 @@ FUNC_NAME(RGBA_Image *src, RGBA_Image *dst,
// if operation is solid, bypass buf and draw func and draw direct to dst
direct = 0;
if ((!src->cache_entry.flags.alpha) && (!dst->cache_entry.flags.alpha) &&
(!dc->mul.use))
direct = 1;
(!dc->mul.use) && (!havea))
{
direct = 1;
}
else
{
int pa;
buf = alloca(cw * sizeof(DATA32));
if (!buf) return;
pa = src->cache_entry.flags.alpha;
if (havea) src->cache_entry.flags.alpha = 1;
if (dc->mul.use)
func = evas_common_gfx_func_composite_pixel_color_span_get(src, dc->mul.col, dst, cw, dc->render_op);
else
func = evas_common_gfx_func_composite_pixel_span_get(src, dst, cw, dc->render_op);
src->cache_entry.flags.alpha = pa;
}
if (smooth)
if (!havecol)
{
for (y = ystart; y <= yend; y++)
{
int x, w, ww;
FPc u, v, ud, vd, dv;
DATA32 *d, *s, *so[4], val1, val2;
Line *line;
#ifdef SCALE_USING_MMX
pxor_r2r(mm0, mm0);
MOV_A2R(ALPHA_255, mm5)
#endif
line = &(spans[y - ystart]);
for (i = 0; i < 2; i++)
{
Span *span;
span = &(line->span[i]);
if (span->x1 >= 0)
{
long long tl;
x = span->x1;
w = (span->x2 - x);
if (w <= 0) continue;
dv = (span->o2 - span->o1);
if (dv <= 0) continue;
ww = w;
u = span->u[0] << FPI;
v = span->v[0] << FPI;
ud = ((span->u[1] << FPI) - u) / w;
vd = ((span->v[1] << FPI) - v) / w;
tl = (long long)ud * (w << FP);
tl = tl / dv;
ud = tl;
u -= (ud * (span->o1 - (span->x1 << FP))) / FP1;
tl = (long long)vd * (w << FP);
tl = tl / dv;
vd = tl;
v -= (vd * (span->o1 - (span->x1 << FP))) / FP1;
if (ud < 0) u -= 1;
if (vd < 0) v -= 1;
if (direct)
d = dst->image.data + (y * dst->cache_entry.w) + x;
else
d = buf;
while (ww > 0)
{
FPc u1, v1, u2, v2;
FPc rv, ru;
DATA32 val1, val2, val3, val4;
u1 = u;
if (u1 < 0) u1 = 0;
else if (u1 >= swp) u1 = swp - 1;
v1 = v;
if (v1 < 0) v1 = 0;
else if (v1 >= shp) v1 = shp - 1;
u2 = u1 + FPFPI1;
if (u2 >= swp) u2 = swp - 1;
v2 = v1 + FPFPI1;
if (v2 >= shp) v2 = shp - 1;
ru = (u >> (FP + FPI - 8)) & 0xff;
rv = (v >> (FP + FPI - 8)) & 0xff;
s = sp + ((v1 >> (FP + FPI)) * sw) +
(u1 >> (FP + FPI));
val1 = *s;
s = sp + ((v1 >> (FP + FPI)) * sw) +
(u2 >> (FP + FPI));
val2 = *s;
s = sp + ((v2 >> (FP + FPI)) * sw) +
(u1 >> (FP + FPI));
val3 = *s;
s = sp + ((v2 >> (FP + FPI)) * sw) +
(u2 >> (FP + FPI));
val4 = *s;
#ifdef SCALE_USING_MMX
MOV_A2R(rv, mm4);
MOV_A2R(ru, mm6);
MOV_P2R(val1, mm1, mm0);
if (val1 | val2)
{
MOV_P2R(val2, mm2, mm0);
INTERP_256_R2R(mm6, mm2, mm1, mm5);
}
MOV_P2R(val3, mm2, mm0);
if (val3 | val4)
{
MOV_P2R(val4, mm3, mm0);
INTERP_256_R2R(mm6, mm3, mm2, mm5);
}
INTERP_256_R2R(mm4, mm2, mm1, mm5);
MOV_R2P(mm1, *d, mm0);
d++;
#else
val1 = INTERP_256(ru, val2, val1);
val3 = INTERP_256(ru, val4, val3);
*d++ = INTERP_256(rv, val3, val1);
#endif
u += ud;
v += vd;
ww--;
}
if (!direct)
{
d = dst->image.data;
d += (y * dst->cache_entry.w) + x;
func(buf, NULL, dc->mul.col, d, w);
}
}
else break;
}
}
#undef COLMUL
#include "evas_map_image_core.c"
}
else
{
for (y = ystart; y <= yend; y++)
{
int x, w, ww;
FPc u, v, ud, vd;
DATA32 *d, *s;
Line *line;
line = &(spans[y - ystart]);
for (i = 0; i < 2; i++)
{
Span *span;
span = &(line->span[i]);
if (span->x1 >= 0)
{
x = span->x1;
w = (span->x2 - x);
if (w <= 0) continue;
ww = w;
u = span->u[0] << FPI;
v = span->v[0] << FPI;
ud = ((span->u[1] << FPI) - u) / w;
vd = ((span->v[1] << FPI) - v) / w;
if (ud < 0) u -= 1;
if (vd < 0) v -= 1;
if (direct)
d = dst->image.data + (y * dst->cache_entry.w) + x;
else
d = buf;
while (ww > 0)
{
s = sp + ((v >> (FP + FPI)) * sw) +
(u >> (FP + FPI));
*d++ = *s;
u += ud;
v += vd;
ww--;
}
if (!direct)
{
d = dst->image.data;
d += (y * dst->cache_entry.w) + x;
func(buf, NULL, dc->mul.col, d, w);
}
}
else break;
}
}
#define COLMUL 1
#include "evas_map_image_core.c"
}
}

View File

@ -0,0 +1,116 @@
/*
* vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2
*/
#ifdef SMOOTH
{
while (ww > 0)
{
# ifdef COLBLACK
*d = 0xff000000; // col
# else
FPc u1, v1, u2, v2;
FPc rv, ru;
DATA32 val1, val2, val3, val4;
u1 = u;
if (u1 < 0) u1 = 0;
else if (u1 >= swp) u1 = swp - 1;
v1 = v;
if (v1 < 0) v1 = 0;
else if (v1 >= shp) v1 = shp - 1;
u2 = u1 + FPFPI1;
if (u2 >= swp) u2 = swp - 1;
v2 = v1 + FPFPI1;
if (v2 >= shp) v2 = shp - 1;
ru = (u >> (FP + FPI - 8)) & 0xff;
rv = (v >> (FP + FPI - 8)) & 0xff;
s = sp + ((v1 >> (FP + FPI)) * sw) +
(u1 >> (FP + FPI));
val1 = *s;
s = sp + ((v1 >> (FP + FPI)) * sw) +
(u2 >> (FP + FPI));
val2 = *s;
s = sp + ((v2 >> (FP + FPI)) * sw) +
(u1 >> (FP + FPI));
val3 = *s;
s = sp + ((v2 >> (FP + FPI)) * sw) +
(u2 >> (FP + FPI));
val4 = *s;
# ifdef SCALE_USING_MMX
MOV_A2R(rv, mm4);
MOV_A2R(ru, mm6);
MOV_P2R(val1, mm1, mm0);
if (val1 | val2)
{
MOV_P2R(val2, mm2, mm0);
INTERP_256_R2R(mm6, mm2, mm1, mm5);
}
MOV_P2R(val3, mm2, mm0);
if (val3 | val4)
{
MOV_P2R(val4, mm3, mm0);
INTERP_256_R2R(mm6, mm3, mm2, mm5);
}
INTERP_256_R2R(mm4, mm2, mm1, mm5);
# ifdef COLMUL
cc = cv >> 16; // col
MOV_A2R(cc, mm2); // col
MOV_A2R(c1, mm3); // col
MOV_A2R(c2, mm4); // col
INTERP_256_R2R(mm2, mm4, mm3, mm5); // col
MUL4_256_R2R(mm3, mm1);
# endif
MOV_R2P(mm1, *d, mm0);
# else
val1 = INTERP_256(ru, val2, val1);
val3 = INTERP_256(ru, val4, val3);
val1 = INTERP_256(rv, val3, val1); // col
# ifdef COLMUL
val2 = INTERP_256((cv >> 16), c2, c1); // col
*d = MUL4_SYM(val2, val1); // col
cv += cd; // col
# else
*d = INTERP_256(rv, val3, val1);
# endif
# endif
u += ud;
v += vd;
# endif
d++;
ww--;
}
}
#else
{
while (ww > 0)
{
# ifdef COLMUL
DATA32 val1, cval; // col
# endif
# ifdef COLBLACK
*d = 0xff000000; // col
# else
s = sp + ((v >> (FP + FPI)) * sw) +
(u >> (FP + FPI));
# ifdef COLMUL
val1 = *s; // col
cval = INTERP_256((cv >> 16), c2, c1); // col
*d = MUL4_SYM(cval, val1);
cv += cd; // col
# else
*d = *s;
# endif
u += ud;
v += vd;
# endif
d++;
ww--;
}
}
#endif

View File

@ -48,6 +48,7 @@ typedef struct _Evas_Intercept_Func_Color Evas_Intercept_Func_Color;
typedef struct _Evas_Key_Grab Evas_Key_Grab;
typedef struct _Evas_Callbacks Evas_Callbacks;
typedef struct _Evas_Format Evas_Format;
typedef struct _Evas_Map_Point Evas_Map_Point;
#define MAGIC_EVAS 0x70777770
#define MAGIC_OBJ 0x71777770
@ -361,7 +362,7 @@ struct _Evas_Map_Point
{
Evas_Coord x, y, z;
double u, v;
// FIXME: add color?
unsigned char r, g, b, a;
};
struct _Evas_Map