add color to the vertexes in map. this allows for fading/shading of
authorraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sun, 1 Nov 2009 01:32:23 +0000 (01:32 +0000)
committerraster <raster@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sun, 1 Nov 2009 01:32:23 +0000 (01:32 +0000)
reflections, goraud shading for smooth 3d surfaces, mor realistic lighting
etc. etc. it comes at a small cost, but worth it.

git-svn-id: svn+ssh://svn.enlightenment.org/var/svn/e/trunk/evas@43384 7cbeb6ba-43b4-40fd-8cce-4c39aea84d33

src/lib/Evas.h
src/lib/canvas/evas_map.c
src/lib/canvas/evas_object_image.c
src/lib/canvas/evas_render.c
src/lib/engines/common/Makefile.am
src/lib/engines/common/evas_map_image.c
src/lib/engines/common/evas_map_image.h
src/lib/engines/common/evas_map_image_core.c [new file with mode: 0644]
src/lib/engines/common/evas_map_image_internal.c
src/lib/engines/common/evas_map_image_loop.c [new file with mode: 0644]
src/lib/include/evas_private.h

index 9c3f17e..e0f737b 100644 (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);
index 0d31e1b..bc3f484 100644 (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 */
 /****************************************************************************/
index 1754068..ef65bf1 100644 (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);
index 77b4b09..b095dd1 100644 (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)
                {
index 02e804f..f8669ae 100644 (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
index 53327ae..5042f4c 100644 (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
index b774745..24209db 100644 (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
diff --git a/src/lib/engines/common/evas_map_image_core.c b/src/lib/engines/common/evas_map_image_core.c
new file mode 100644 (file)
index 0000000..54bc064
--- /dev/null
@@ -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;
+               }
+          }
+     }
+}
index da49755..37a306a 100644 (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"
      }
 }
diff --git a/src/lib/engines/common/evas_map_image_loop.c b/src/lib/engines/common/evas_map_image_loop.c
new file mode 100644 (file)
index 0000000..3a158b1
--- /dev/null
@@ -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
index 2ff66fe..933b9e5 100644 (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