Support for Proxy Objects (and others)
authornash <nash@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sun, 6 Feb 2011 23:52:17 +0000 (23:52 +0000)
committernash <nash@7cbeb6ba-43b4-40fd-8cce-4c39aea84d33>
Sun, 6 Feb 2011 23:52:17 +0000 (23:52 +0000)
Proxy objects allow you to use another image as the source of an image.
Essentially allowing the same object to be rendered multiple times.  One
object (the source) is the original, each additional 'copy' is an image with
evas_object_image_source_set.

This is complete.

Also add partially working arbitrary maps, and arbitrary clipping.
Unfortunately both have some issues yet to be resolved (waiting on the next
feature to get merged together).

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

19 files changed:
.gitignore
src/lib/Evas.h
src/lib/canvas/evas_map.c
src/lib/canvas/evas_object_image.c
src/lib/canvas/evas_object_proxy.c
src/lib/canvas/evas_render.c
src/lib/engines/common/evas_convert_colorspace.c
src/lib/engines/common/evas_map_image.c
src/lib/engines/common/evas_map_image.h
src/lib/engines/common/evas_pipe.h
src/lib/include/evas_common.h
src/lib/include/evas_private.h
src/modules/engines/gl_common/shader/.gitignore [new file with mode: 0644]
src/modules/engines/gl_common/shader/img_mask_frag.h [new file with mode: 0644]
src/modules/engines/gl_common/shader/img_mask_frag.shd [new file with mode: 0644]
src/modules/engines/gl_common/shader/img_mask_vert.h [new file with mode: 0644]
src/modules/engines/gl_common/shader/img_mask_vert.shd [new file with mode: 0644]
src/modules/engines/gl_x11/evas_engine.c
src/modules/engines/software_generic/evas_engine.c

index 0024e2d..638192c 100644 (file)
@@ -7,6 +7,7 @@
 Makefile
 Makefile.in
 *.so
+.*.sw[po]
 /README
 /aclocal.m4
 /autom4te.cache/
@@ -25,3 +26,5 @@ Makefile.in
 /ltmain.sh
 /missing
 /stamp-h1
+tags
+cscope.out
index a0701f2..e8bccc9 100644 (file)
@@ -164,7 +164,7 @@ typedef enum _Evas_Colorspace
    EVAS_COLORSPACE_YCBCR422P601_PL, /**< YCbCr 4:2:2 Planar, ITU.BT-601 specifications. The data poitned to is just an array of row pointer, pointing to the Y rows, then the Cb, then Cr rows */
    EVAS_COLORSPACE_YCBCR422P709_PL,/**< YCbCr 4:2:2 Planar, ITU.BT-709 specifications. The data poitned to is just an array of row pointer, pointing to the Y rows, then the Cb, then Cr rows */
    EVAS_COLORSPACE_RGB565_A5P, /**< 16bit rgb565 + Alpha plane at end - 5 bits of the 8 being used per alpha byte */
-   EVAS_COLORSPACE_GRY8 /**< 8bit grayscale */
+   EVAS_COLORSPACE_GRY8, /**< 8bit grayscale */
 } Evas_Colorspace; /**< Colorspaces for pixel data supported by Evas */
 
 /**
@@ -331,7 +331,7 @@ typedef enum _Evas_Pixel_Import_Pixel_Format
 {
    EVAS_PIXEL_FORMAT_NONE = 0, /**< No pixel format */
    EVAS_PIXEL_FORMAT_ARGB32 = 1, /**< ARGB 32bit pixel format with A in the high byte per 32bit pixel word */
-   EVAS_PIXEL_FORMAT_YUV420P_601 = 2 /**< YUV 420 Planar format with CCIR 601 color encoding wuth contiguous planes in the order Y, U and V */
+   EVAS_PIXEL_FORMAT_YUV420P_601 = 2, /**< YUV 420 Planar format with CCIR 601 color encoding wuth contiguous planes in the order Y, U and V */
 } Evas_Pixel_Import_Pixel_Format; /**< Pixel format for import call. See evas_object_image_pixels_import() */
 
 struct _Evas_Pixel_Import_Source
@@ -995,6 +995,7 @@ typedef void      (*Evas_Async_Events_Put_Cb)(void *target, Evas_Callback_Type t
    EAPI Eina_Bool         evas_map_alpha_get                (const Evas_Map *m);
    EAPI Evas_Map         *evas_map_dup                      (const Evas_Map *m);
    EAPI void              evas_map_free                     (Evas_Map *m);
+   EAPI int               evas_map_count_get               (const Evas_Map *m) EINA_CONST;
    EAPI void              evas_map_point_coord_set          (Evas_Map *m, int idx, Evas_Coord x, Evas_Coord y, Evas_Coord z);
    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);
@@ -1229,6 +1230,11 @@ typedef void (*Evas_Object_Intercept_Clip_Unset_Cb) (void *data, Evas_Object *ob
  *
  * R = (r * a) / 32; G = (g * a) / 32; B = (b * a) / 32;
  *
+ * EVAS_COLORSPACE_A8:
+ *
+ * The image is just a alpha mask (8 bit's per pixel).  This is used for alpha
+ * masking.
+ *
  * @ingroup Evas_Object_Specific
  */
 typedef void (*Evas_Object_Image_Pixels_Get_Cb) (void *data, Evas_Object *o);
@@ -1287,6 +1293,8 @@ typedef void (*Evas_Object_Image_Pixels_Get_Cb) (void *data, Evas_Object *o);
    EAPI void                     evas_object_image_content_hint_set       (Evas_Object *obj, Evas_Image_Content_Hint hint) EINA_ARG_NONNULL(1);
    EAPI Evas_Image_Content_Hint  evas_object_image_content_hint_get       (const Evas_Object *obj) EINA_WARN_UNUSED_RESULT EINA_ARG_NONNULL(1) EINA_PURE;
 
+   EAPI void                     evas_object_image_alpha_mask_set         (Evas_Object *, Eina_Bool) EINA_ARG_NONNULL(1);
+
 /**
  * @defgroup Evas_Object_Text Text Object Functions
  *
@@ -2091,7 +2099,13 @@ struct _Evas_Smart_Cb_Description
 /**
  * @defgroup Evas_Proxy Evas Proxy Objects
  *
- * Provides a way of applying effects to complete objects.
+ * @brief Provides a way of applying effects to complete objects.
+ *
+ * A proxy object is a visible copy of another object.  Generally a map or
+ * similar effect will be applied to the proxy to apply some sort of rendering
+ * effect to.
+ * 
+ * Proxies are generally used for special effects.
  */
    EAPI Evas_Object                         *evas_object_proxy_add            (Evas *e) EINA_MALLOC;
    EAPI Eina_Bool                            evas_object_proxy_source_set     (Evas_Object *o, Evas_Object *source);
index 42974ef..63f957d 100644 (file)
@@ -96,7 +96,15 @@ static inline Evas_Map *
 _evas_map_new(int count)
 {
    int i;
-   Evas_Map *m = calloc(1, sizeof(Evas_Map) + (count * sizeof(Evas_Map_Point)));
+   int alloc;
+   Evas_Map *m;
+
+   /* Adjust allocation such that: at least 4 points, and always an even
+    * number: this allows the software engine to work efficiently */
+   alloc = (count < 4) ? 4 : count;
+   if (alloc & 0x1) alloc ++;
+
+   m = calloc(1, sizeof(Evas_Map) + (alloc * sizeof(Evas_Map_Point)));
    if (!m) return NULL;
    m->count = count;
    m->persp.foc = 0;
@@ -155,24 +163,24 @@ Eina_Bool
 evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
                     Evas_Coord *mx, Evas_Coord *my, int grab)
 {
-   int i, j, edges, edge[4][2], douv;
+   int i, j, edges, edge[m->count][2], douv;
    Evas_Coord xe[2];
    double u[2] = { 0.0, 0.0 };
    double v[2] = { 0.0, 0.0 };
 
-   if (m->count != 4) return 0;
+   if (m->count < 4) return 0;
    // FIXME need to handle grab mode and extrapolte coords outside
    // map
    if (grab)
      {
         Evas_Coord ymin, ymax;
-        
+
         ymin = m->points[0].y;
         ymax = m->points[0].y;
         for (i = 1; i < m->count; i++)
           {
-             if (m->points[i].y < ymin) ymin = m->points[i].y; 
-             else if (m->points[i].y > ymax) ymax = m->points[i].y; 
+             if (m->points[i].y < ymin) ymin = m->points[i].y;
+             else if (m->points[i].y > ymax) ymax = m->points[i].y;
           }
         if (y <= ymin) y = ymin + 1;
         if (y >= ymax) y = ymax - 1;
@@ -250,12 +258,12 @@ evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
         if (xe[0] > xe[1])
           {
              int ti;
-             
+
              ti = xe[0]; xe[0] = xe[1]; xe[1] = ti;
              if (douv)
                {
                   double td;
-                  
+
                   td = u[0]; u[0] = u[1]; u[1] = td;
                   td = v[0]; v[0] = v[1]; v[1] = td;
                }
@@ -264,11 +272,11 @@ evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
           {
              if (douv)
                {
-                  if (mx) 
-                    *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) / 
+                  if (mx)
+                    *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
                                   (xe[1] - xe[0]));
                  if (my)
-                    *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) / 
+                    *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
                                   (xe[1] - xe[0]));
                }
              return 1;
@@ -277,11 +285,11 @@ evas_map_coords_get(const Evas_Map *m, Evas_Coord x, Evas_Coord y,
           {
              if (douv)
                {
-                  if (mx) 
-                    *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) / 
+                  if (mx)
+                    *mx = u[0] + (((x - xe[0]) * (u[1] - u[0])) /
                                   (xe[1] - xe[0]));
                   if (my)
-                    *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) / 
+                    *my = v[0] + (((x - xe[0]) * (v[1] - v[0])) /
                                   (xe[1] - xe[0]));
                }
              return 1;
@@ -471,21 +479,23 @@ evas_object_map_set(Evas_Object *obj, const Evas_Map *map)
           }
         return;
      }
-   if (!obj->cur.map)
-     {
-        obj->cur.map = _evas_map_dup(map);
-        if (obj->cur.usemap)
-           evas_object_mapped_clip_across_mark(obj);
-     }
-   else
+
+   if (obj->cur.map && obj->cur.map->count == map->count)
      {
         Evas_Map *omap = obj->cur.map;
-        obj->cur.map = _evas_map_new(4);
-        memcpy(obj->cur.map, omap, sizeof(Evas_Map) + (4 * sizeof(Evas_Map_Point)));
+        obj->cur.map = _evas_map_new(map->count);
+        memcpy(obj->cur.map, omap, sizeof(Evas_Map) + (map->count * sizeof(Evas_Map_Point)));
         _evas_map_copy(obj->cur.map, map);
         if (obj->prev.map == omap) obj->prev.map = NULL;
         free(omap);
      }
+   else
+     {
+       if (obj->cur.map) evas_map_free(obj->cur.map);
+        obj->cur.map = _evas_map_dup(map);
+        if (obj->cur.usemap)
+           evas_object_mapped_clip_across_mark(obj);
+     }
    _evas_map_calc_map_geometry(obj);
 }
 
@@ -543,9 +553,9 @@ evas_object_map_get(const Evas_Object *obj)
 EAPI Evas_Map *
 evas_map_new(int count)
 {
-   if (count != 4)
+   if (count < 4)
      {
-       ERR("num (%i) != 4 is unsupported!", count);
+       ERR("num (%i) < 4 is unsupported!", count);
        return NULL;
      }
    return _evas_map_new(count);
@@ -645,6 +655,21 @@ evas_map_free(Evas_Map *m)
 }
 
 /**
+ * Get a maps size.
+ *
+ * Returns the number of points in a map.  Should be at least 4.
+ *
+ * @param m map to get size.
+ * @return -1 on error, points otherwise.
+ */
+EAPI int
+evas_map_count_get(const Evas_Map *m)
+{
+   if (!m) return -1;
+   return m->count;
+}
+
+/**
  * Change the map point's coordinate.
  * 
  * This sets the fixen point's coordinate in the map. Note that points
@@ -1216,10 +1241,11 @@ evas_map_util_3d_lighting(Evas_Map *m,
         x = m->points[i].x;
         y = m->points[i].y;
         z = m->points[i].z;
-        
+printf("Normal %d\n",i);
         // calc normal
-        h = (i + m->count - 1) % m->count; // prev point
-        j = (i + 1) % m->count; // next point
+        h = (i - 1 + 4) % 4 + (i & ~0x3); // prev point
+        j = (i + 1)     % 4 + (i & ~0x3); // next point
+printf("\tNext/Prev: %2d/%2d\n",h,j);
 
         x1 = m->points[h].x - x;
         y1 = m->points[h].y - y;
@@ -1228,13 +1254,16 @@ evas_map_util_3d_lighting(Evas_Map *m,
         x2 = m->points[j].x - x;
         y2 = m->points[j].y - y;
         z2 = m->points[j].z - z;
-        
+printf("\tX:   %3.2lf,%3.2lf,%3.2lf\n",x,y,z);
+printf("\tX1:  %3.2lf,%3.2lf,%3.2lf\n",x1,y1,z1);
+printf("\tX2:  %3.2lf,%3.2lf,%3.2lf\n",x2,y2,z2);
         nx = (y1 * z2) - (z1 * y2);
         ny = (z1 * x2) - (x1 * z2);
         nz = (x1 * y2) - (y1 * x2);
         
         ln = (nx * nx) + (ny * ny) + (nz * nz);
         ln = sqrt(ln);
+printf("\tLength: %3.2lf\n",ln);
         
         if (ln != 0.0)
           {
@@ -1242,7 +1271,8 @@ evas_map_util_3d_lighting(Evas_Map *m,
              ny /= ln;
              nz /= ln;
           }
-        
+printf("\tpoint %2d: %3.2lf,%3.2lf,%3.2lf normal: %3.2lf %3.2lf %3.2lf\n",i,x,y,z,nx,ny,nz);
+
         // calc point -> light vector
         x = lx - x;
         y = ly - y;
@@ -1265,9 +1295,11 @@ evas_map_util_3d_lighting(Evas_Map *m,
         mr = ar + ((lr - ar) * br);
         mg = ag + ((lg - ag) * br);
         mb = ab + ((lb - ab) * br);
-        mr = (mr * m->points[i].a) / 255;
-        mg = (mg * m->points[i].a) / 255;
-        mb = (mb * m->points[i].a) / 255;
+       if (m->points[i].a != 255){
+               mr = (mr * m->points[i].a) / 255;
+               mg = (mg * m->points[i].a) / 255;
+               mb = (mb * m->points[i].a) / 255;
+       }
         m->points[i].r = (m->points[i].r * mr) / 255;
         m->points[i].g = (m->points[i].g * mg) / 255;
         m->points[i].b = (m->points[i].b * mb) / 255;
index e66f83b..ce05deb 100644 (file)
@@ -2050,6 +2050,39 @@ evas_object_image_content_hint_set(Evas_Object *obj, Evas_Image_Content_Hint hin
 }
 
 /**
+ * Enable an image to be used as an alpha mask.
+ *
+ * This will set any flags, and discard any excess image data not used as an
+ * alpha mask.
+ *
+ * Note there is little point in using a image as alpha mask unless it has an
+ * alpha channel.
+ *
+ * @param obj Object to use as an alpha mask.
+ * @param ismask Use image as alphamask, must be true.
+ */
+EAPI void
+evas_object_image_alpha_mask_set(Evas_Object *obj, Eina_Bool ismask)
+{
+   Evas_Object_Image *o;
+
+   if (!ismask) return;
+
+   MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
+   return;
+   MAGIC_CHECK_END();
+   o = (Evas_Object_Image *)(obj->object_data);
+   MAGIC_CHECK(o, Evas_Object_Image, MAGIC_OBJ_IMAGE);
+   return;
+   MAGIC_CHECK_END();
+
+   /* Convert to A8 if not already */
+
+   /* done */
+
+}
+
+/**
  * Get the content hint of a given image of the canvas.
  *
  * @param obj The given canvas pointer.
@@ -2453,13 +2486,13 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
               }
             o->dirty_pixels = 0;
          }
-        if ((obj->cur.map) && (obj->cur.map->count == 4) && (obj->cur.usemap))
+        if ((obj->cur.map) && (obj->cur.map->count > 3) && (obj->cur.usemap))
           {
             const Evas_Map_Point *p, *p_end;
-             RGBA_Map_Point pts[4], *pt;
+             RGBA_Map_Point pts[obj->cur.map->count], *pt;
 
             p = obj->cur.map->points;
-            p_end = p + 4;
+            p_end = p + obj->cur.map->count;
             pt = pts;
              
              pts[0].px = obj->cur.map->persp.px << FP;
@@ -2483,9 +2516,14 @@ evas_object_image_render(Evas_Object *obj, void *output, void *context, void *su
                   else if (pt->v > (o->cur.image.h * FP1)) pt->v = (o->cur.image.h * FP1);
                   pt->col = ARGB_JOIN(p->a, p->r, p->g, 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);
+            if (obj->cur.map->count & 0x1)
+              {
+                 pts[obj->cur.map->count] = pts[obj->cur.map->count -1];
+              }
+
+             obj->layer->evas->engine.func->image_map_draw
+               (output, context, surface, o->engine_data, obj->cur.map->count,
+               pts, o->cur.smooth_scale | obj->cur.map->smooth, 0);
           }
         else
           {
@@ -3256,3 +3294,5 @@ evas_object_image_filled_resize_listener(void *data __UNUSED__, Evas *e __UNUSED
    evas_object_geometry_get(obj, NULL, NULL, &w, &h);
    evas_object_image_fill_set(obj, 0, 0, w, h);
 }
+
+/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
index 58dadda..8471bf8 100644 (file)
@@ -21,6 +21,7 @@ typedef struct _Evas_Object_Proxy
 
    Evas_Map *defmap;
    Eina_Bool mapupdate;
+   Eina_Bool rendering;
 } Evas_Object_Proxy;
 
 
@@ -98,6 +99,14 @@ static const Evas_Object_Func object_func =
 };
 
 
+/**
+ * Add a new proxy object.
+ *
+ * The proxy object must have a source set before it is useful.
+ *
+ * @param e Evas canvas to add proxy too.
+ * @return New proxy object.
+ */
 EAPI Evas_Object *
 evas_object_proxy_add(Evas *e)
 {
@@ -119,32 +128,33 @@ evas_object_proxy_add(Evas *e)
    return obj;
 }
 
+/**
+ * Set the source object on a proxy object.
+ *
+ * Any existing source object will be removed.  Setting the src to NULL clears
+ * the proxy object.
+ *
+ * You cannot set a proxy on a proxy.
+ *
+ * @param obj Proxy object.
+ * @param src Source of the proxy.
+ * @return EINA_TRUE on success, EINA_FALSE on error.
+ */
 EAPI Eina_Bool
 evas_object_proxy_source_set(Evas_Object *obj, Evas_Object *src)
 {
-   Evas_Object_Proxy *o,*so;
+   Evas_Object_Proxy *o;
 
    MAGIC_CHECK(obj, Evas_Object, MAGIC_OBJ);
-   return false;
+   return EINA_FALSE;
    MAGIC_CHECK_END();
    o = obj->object_data;
    MAGIC_CHECK(o, Evas_Object_Proxy, MAGIC_OBJ_PROXY);
-   return false;
+   return EINA_FALSE;
    MAGIC_CHECK_END();
 
-   if (o->source == src) return true;
-
-   if (src)
-     {
-        MAGIC_CHECK(src, Evas_Object, MAGIC_OBJ);
-        return false;
-        MAGIC_CHECK_END();
-        so = src->object_data;
-        /* Stop the loop _now_ */
-        /* FIXME: Should I check for smarts that contain proxies too? */
-        if (so->magic == MAGIC_OBJ_PROXY)
-           return false;
-     }
+   if (src == obj) return EINA_FALSE;
+   if (o->source == src) return EINA_TRUE;
 
    if (o->source)
      {
@@ -156,9 +166,15 @@ evas_object_proxy_source_set(Evas_Object *obj, Evas_Object *src)
         _proxy_set(obj, src);
      }
 
-   return true;
+   return EINA_TRUE;
 }
 
+/**
+ * Get the current source object of a proxy.
+ *
+ * @param obj Proxy object
+ * @return Source object, or NULL on error.
+ */
 EAPI Evas_Object *
 evas_object_proxy_source_get(Evas_Object *obj)
 {
@@ -175,15 +191,23 @@ evas_object_proxy_source_get(Evas_Object *obj)
    return o->source;
 }
 
+/**
+ * Clear the source on a proxy.
+ *
+ * This is equivalent to calling evas_object_proxy_source_set with a NULL
+ * source.
+ *
+ * @param obj Proxy object to clear source of.
+ * @return EINA_TRUE on success, EINA_FALSE on error.
+ */
 EAPI Eina_Bool
-evas_object_proxy_source_unset(Evas_Object *o)
+evas_object_proxy_source_unset(Evas_Object *obj)
 {
-   return evas_object_proxy_source_set(o, NULL);
+   return evas_object_proxy_source_set(obj, NULL);
 }
 
 
 
-
 /* Internal helpers */
 static void
 evas_object_proxy_init(Evas_Object *obj)
@@ -313,6 +337,30 @@ _proxy_render(Evas_Object *obj, void *output, void *context,
 
    o = obj->object_data;
 
+   if (o->rendering)
+     {
+        int r = rand() % 255;
+        int g = rand() % 255;
+        int b = rand() % 255;
+        printf("Ahh: Recursive proxies: Go away!\n");
+        obj->layer->evas->engine.func->context_color_set(output,
+                                                         context,
+                                                         r,g,b,255);
+        obj->layer->evas->engine.func->context_multiplier_unset(output,
+                                                                context);
+        obj->layer->evas->engine.func->context_render_op_set(output, context,
+                                                             obj->cur.render_op);
+        obj->layer->evas->engine.func->rectangle_draw(output,
+                                                      context,
+                                                      surface,
+                                                      obj->cur.geometry.x + x,
+                                                      obj->cur.geometry.y + y,
+                                                      obj->cur.geometry.w,
+                                                      obj->cur.geometry.h);
+        return;
+     }
+
+
    if (!o->source) return;
 
 //   ENFN->context_multiplier_unset(output, context);
@@ -331,8 +379,10 @@ _proxy_render(Evas_Object *obj, void *output, void *context,
      }
    else
      {
+         o->rendering = true;
          _proxy_subrender(obj->layer->evas, o->source);
          pixels = o->source->proxy.surface;
+         o->rendering = false;
      }
 
    if (o->mapupdate) _proxy_map_update(obj);
@@ -383,8 +433,9 @@ _proxy_render(Evas_Object *obj, void *output, void *context,
              pt->v = p->v * FP1;
              pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
           }
-        obj->layer->evas->engine.func->image_map4_draw
-           (output, context, surface, pixels, pts, map->smooth, 0);
+        obj->layer->evas->engine.func->image_map_draw
+           (output, context, surface, pixels, map->count, pts,
+            map->smooth, 0);
      }
    else
      {
index 25b8789..26a4b13 100644 (file)
@@ -703,7 +703,10 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
 
    // set render_pre - for child objs that may not have gotten it.
    obj->pre_render_done = 1;
-
+   RD("          Hasmap: %p (%d) %p %d -> %d\n",obj->func->can_map,
+                  obj->func->can_map ? obj->func->can_map(obj): -1,
+                  obj->cur.map, obj->cur.usemap,
+                  _evas_render_has_map(obj));
    if (_evas_render_has_map(obj))
      {
         const Evas_Map_Point *p, *p_end;
@@ -730,7 +733,7 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
         pts[0].z0 = obj->cur.map->persp.z0 << FP;
         
         p = obj->cur.map->points;
-        p_end = p + 4;
+        p_end = p + obj->cur.map->count;
         pt = pts;
         for (; p < p_end; p++, pt++)
           {
@@ -748,6 +751,12 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
              else if (pt->v > (sh * FP1)) pt->v = (sh * FP1);
              pt->col = ARGB_JOIN(p->a, p->r, p->g, p->b);
           }
+        /* Copy last for software engine */
+        if (obj->cur.map->count & 0x1)
+          {
+            pts[obj->cur.map->count] = pts[obj->cur.map->count - 1];
+          }
+
 
         if (obj->cur.map->surface)
           {
@@ -937,9 +946,10 @@ evas_render_mapped(Evas *e, Evas_Object *obj, void *context, void *surface,
                }
           }
         if (obj->cur.cache.clip.visible)
-           obj->layer->evas->engine.func->image_map4_draw
+           obj->layer->evas->engine.func->image_map_draw
            (e->engine.data.output, e->engine.data.context, surface,
-            obj->cur.map->surface, pts, obj->cur.map->smooth, 0);
+            obj->cur.map->surface, obj->cur.map->count, pts,
+            obj->cur.map->smooth, 0);
         // FIXME: needs to cache these maps and
         // keep them only rendering updates
 //        obj->layer->evas->engine.func->image_map_surface_free
index 75711bb..c0918ee 100644 (file)
@@ -9,6 +9,9 @@
 #define CONVERT_A5P_TO_A8(s) \
        ((((s) << 3) & 0xf8) | (((s) >> 2) & 0x7))
 
+#define CONVERT_ARGB_8888_TO_A_8(s)    ((s) >> 24)
+
+
 static inline void *
 evas_common_convert_argb8888_to_rgb565_a5p(void *data __UNUSED__, int w __UNUSED__, int h __UNUSED__, int stride __UNUSED__, Eina_Bool has_alpha __UNUSED__)
 {
@@ -43,6 +46,28 @@ evas_common_convert_rgb565_a5p_to_argb8888(void *data, int w, int h, int stride,
    return ret;
 }
 
+static inline void *
+evas_common_convert_argb8888_to_a8(void *data, int w, int h, int stride, Eina_Bool has_alpha)
+{
+   uint32_t *src, *end;
+   uint8_t *ret, *dst;
+
+   src = data;
+   end = src + (stride * h);
+   ret = malloc(w * h);
+
+   if (!has_alpha)
+     {
+        return memset(ret,0xff, w * h);
+     }
+
+   for ( ; src < end ; src ++, dst ++)
+      *dst = CONVERT_ARGB_8888_TO_A_8(*src);
+   return ret;
+}
+
+
+
 EAPI void *
 evas_common_convert_argb8888_to(void *data, int w, int h, int stride, Eina_Bool has_alpha, Evas_Colorspace cspace)
 {
@@ -50,6 +75,8 @@ evas_common_convert_argb8888_to(void *data, int w, int h, int stride, Eina_Bool
      {
        case EVAS_COLORSPACE_RGB565_A5P:
          return evas_common_convert_argb8888_to_rgb565_a5p(data, w, h, stride, has_alpha);
+        case EVAS_COLORSPACE_A8:
+          return evas_common_convert_argb8888_to_a8(data, w, h, stride, has_alpha);
        default:
          break;
      }
@@ -68,3 +95,6 @@ evas_common_convert_rgb565_a5p_to(void *data, int w, int h, int stride, Eina_Boo
      }
    return NULL;
 }
+
+
+/* vim:set ts=8 sw=3 sts=3 expandtab cino=>5n-2f0^-2{2(0W1st0 :*/
index 41b71a1..7330910 100644 (file)
@@ -325,23 +325,23 @@ _calc_spans(RGBA_Map_Point *p, Line *spans, int ystart, int yend, int cx, int cy
 #ifdef BUILD_SCALE_SMOOTH
 # ifdef BUILD_MMX
 #  undef FUNC_NAME
-#  define FUNC_NAME evas_common_map4_rgba_internal_mmx
+#  define FUNC_NAME evas_common_map_rgba_internal_mmx
 #  undef SCALE_USING_MMX
 #  define SCALE_USING_MMX
 #  include "evas_map_image_internal.c"
 # endif
 # ifdef BUILD_C
 #  undef FUNC_NAME
-#  define FUNC_NAME evas_common_map4_rgba_internal
+#  define FUNC_NAME evas_common_map_rgba_internal
 #  undef SCALE_USING_MMX
 #  include "evas_map_image_internal.c"
 # endif
 #endif
 
 EAPI void
-evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
+evas_common_map_rgba(RGBA_Image *src, RGBA_Image *dst,
                       RGBA_Draw_Context *dc,
-                      RGBA_Map_Point *p, 
+                      int npoints, RGBA_Map_Point *p,
                       int smooth, int level)
 {
 #ifdef BUILD_MMX
@@ -363,11 +363,11 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
      {
 #ifdef BUILD_MMX
         if (mmx)
-          evas_common_map4_rgba_internal_mmx(src, dst, dc, p, smooth, level);
+          evas_common_map_rgba_internal_mmx(src, dst, dc, p, smooth, level);
         else
 #endif
 #ifdef BUILD_C
-          evas_common_map4_rgba_internal(src, dst, dc, p, smooth, level);
+          evas_common_map_rgba_internal(src, dst, dc, p, smooth, level);
 #endif
         return;
      }
@@ -387,11 +387,11 @@ evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
         evas_common_draw_context_set_clip(dc, r->x, r->y, r->w, r->h);
 #ifdef BUILD_MMX
         if (mmx)
-          evas_common_map4_rgba_internal_mmx(src, dst, dc, p, smooth, level);
+          evas_common_map_rgba_internal_mmx(src, dst, dc, p, smooth, level);
         else
 #endif
 #ifdef BUILD_C
-          evas_common_map4_rgba_internal(src, dst, dc, p, smooth, level);
+          evas_common_map_rgba_internal(src, dst, dc, p, smooth, level);
 #endif        
      }
    evas_common_draw_context_apply_clear_cutouts(rects);
index 883b278..a7cb8cf 100644 (file)
@@ -2,9 +2,9 @@
 #define _EVAS_MAP_H
 
 EAPI void
-evas_common_map4_rgba(RGBA_Image *src, RGBA_Image *dst,
+evas_common_map_rgba(RGBA_Image *src, RGBA_Image *dst,
                       RGBA_Draw_Context *dc,
-                      RGBA_Map_Point *points,
+                      int npoints, RGBA_Map_Point *points,
                       int smooth, int level);
 
 #endif /* _EVAS_MAP_H */
index 73213b6..a6662c9 100644 (file)
@@ -95,8 +95,8 @@ EAPI void evas_common_pipe_poly_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGB
 EAPI void evas_common_pipe_text_draw(RGBA_Image *dst, RGBA_Draw_Context *dc, RGBA_Font *fn, int x, int y, const Eina_Unicode *text, const Evas_Text_Props *intl_props);
 EAPI void evas_common_pipe_image_load(RGBA_Image *im);
 EAPI void evas_common_pipe_image_draw(RGBA_Image *src, RGBA_Image *dst, RGBA_Draw_Context *dc, int smooth, 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);
-EAPI void evas_common_pipe_map4_begin(RGBA_Image *root);
-EAPI void evas_common_pipe_map4_draw(RGBA_Image *src, RGBA_Image *dst,
+EAPI void evas_common_pipe_map_begin(RGBA_Image *root);
+EAPI void evas_common_pipe_map_draw(RGBA_Image *src, RGBA_Image *dst,
                                     RGBA_Draw_Context *dc, RGBA_Map_Point *p,
                                     int smooth, int level);
 EAPI void evas_common_pipe_flush(RGBA_Image *im);
index b43f937..5d6ee93 100644 (file)
@@ -664,6 +664,7 @@ struct _RGBA_Draw_Context
       DATA32 col;
    } col;
    struct RGBA_Draw_Context_clip {
+      DATA8  *mask;
       int    x, y, w, h;
       Eina_Bool use : 1;
    } clip;
index 23d1fc0..26b1b62 100644 (file)
@@ -672,7 +672,7 @@ struct _Evas_Func
    int  (*image_scale_hint_get)            (void *data, void *image);
    int  (*font_last_up_to_pos)             (void *data, void *font, const Eina_Unicode *text, const Evas_Text_Props *intl_props, int x, int y);
 
-   void (*image_map4_draw)                 (void *data, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level);
+   void (*image_map_draw)                  (void *data, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level);
    void *(*image_map_surface_new)          (void *data, int w, int h, int alpha);
    void (*image_map_surface_free)          (void *data, void *surface);
 
diff --git a/src/modules/engines/gl_common/shader/.gitignore b/src/modules/engines/gl_common/shader/.gitignore
new file mode 100644 (file)
index 0000000..a01ee28
--- /dev/null
@@ -0,0 +1 @@
+.*.swp
diff --git a/src/modules/engines/gl_common/shader/img_mask_frag.h b/src/modules/engines/gl_common/shader/img_mask_frag.h
new file mode 100644 (file)
index 0000000..0571c72
--- /dev/null
@@ -0,0 +1,11 @@
+"#ifdef GL_ES\n"
+"precision mediump float;\n"
+"#endif\n"
+"uniform sampler2D tex, texm;\n"
+"varying vec4 col;\n"
+"varying vec2 tex_c, tex_cm;\n"
+"void main()\n"
+"{\n"
+"   gl_FragColor = texture2D(texm, tex_cm.xy).aaaa * texture2D(tex, tex_c.xy).rgba * col;\n"
+"}\n"
+"\n"
diff --git a/src/modules/engines/gl_common/shader/img_mask_frag.shd b/src/modules/engines/gl_common/shader/img_mask_frag.shd
new file mode 100644 (file)
index 0000000..87aa2b7
--- /dev/null
@@ -0,0 +1,11 @@
+#ifdef GL_ES
+precision mediump float;
+#endif
+uniform sampler2D tex, texm;
+varying vec4 col;
+varying vec2 tex_c, tex_cm;
+void main()
+{
+   gl_FragColor = texture2D(texm, tex_cm.xy).aaaa * texture2D(tex, tex_c.xy).rgba * col;
+}
+
diff --git a/src/modules/engines/gl_common/shader/img_mask_vert.h b/src/modules/engines/gl_common/shader/img_mask_vert.h
new file mode 100644 (file)
index 0000000..5b52e41
--- /dev/null
@@ -0,0 +1,16 @@
+"#ifdef GL_ES\n"
+"precision mediump float;\n"
+"#endif\n"
+"attribute vec4 vertex;\n"
+"attribute vec4 color;\n"
+"attribute vec2 tex_coord, tex_coordm;\n"
+"uniform mat4 mvp;\n"
+"varying vec4 col;\n"
+"varying vec2 tex_c, tex_cm;\n"
+"void main()\n"
+"{\n"
+"   gl_Position = mvp * vertex;\n"
+"   col = color;\n"
+"   tex_c = tex_coord;\n"
+"   tex_cm = tex_coordm;\n"
+"}\n"
diff --git a/src/modules/engines/gl_common/shader/img_mask_vert.shd b/src/modules/engines/gl_common/shader/img_mask_vert.shd
new file mode 100644 (file)
index 0000000..f91b545
--- /dev/null
@@ -0,0 +1,16 @@
+#ifdef GL_ES
+precision mediump float;
+#endif
+attribute vec4 vertex;
+attribute vec4 color;
+attribute vec2 tex_coord, tex_coordm;
+uniform mat4 mvp;
+varying vec4 col;
+varying vec2 tex_c, tex_cm;
+void main()
+{
+   gl_Position = mvp * vertex;
+   col = color;
+   tex_c = tex_coord;
+   tex_cm = tex_coordm;
+}
index ccf3f9a..851cfc7 100644 (file)
@@ -1738,7 +1738,7 @@ eng_image_scale_hint_get(void *data __UNUSED__, void *image)
 }
 
 static void
-eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level)
+eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level)
 {
    Evas_GL_Image *gim = image;
    Render_Engine *re;
@@ -1942,7 +1942,7 @@ module_open(Evas_Module *em)
    ORD(image_scale_hint_get);
    ORD(image_stride_get);
    
-   ORD(image_map4_draw);
+   ORD(image_map_draw);
    ORD(image_map_surface_new);
    ORD(image_map_surface_free);
    
index 84628e5..fe4486f 100644 (file)
@@ -506,12 +506,14 @@ eng_image_draw(void *data __UNUSED__, void *context, void *surface, void *image,
 }
 
 static void
-eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *image, RGBA_Map_Point *p, int smooth, int level)
+eng_image_map_draw(void *data __UNUSED__, void *context, void *surface, void *image, int npoints, RGBA_Map_Point *p, int smooth, int level)
 {
    RGBA_Image *im;
 
    if (!image) return;
+   if (npoints < 3) return;
    im = image;
+
    if ((p[0].x == p[3].x) &&
        (p[1].x == p[2].x) &&
        (p[0].y == p[1].y) &&
@@ -550,12 +552,18 @@ eng_image_map4_draw(void *data __UNUSED__, void *context, void *surface, void *i
        && evas_common_frameq_enabled()
 # endif
         )
-          evas_common_pipe_map4_draw(im, surface, context, p, smooth, level);
+          evas_common_pipe_map_draw(im, surface, context, npoints, p, smooth, level);
         else
 #endif
-          evas_common_map4_rgba(im, surface, context, p, smooth, level);
+          evas_common_map_rgba(im, surface, context, npoints, p, smooth, level);
      }
    evas_common_cpu_end_opt();
+
+   if (npoints > 4)
+     {
+        eng_image_map_draw(data, context, surface, image, npoints - 2, p + 2,
+                       smooth, level);
+     }
 }
 
 static void *
@@ -907,7 +915,7 @@ static Evas_Func func =
      /* more font draw functions */
      eng_font_last_up_to_pos,
      /* FUTURE software generic calls go here (done) */
-     eng_image_map4_draw,
+     eng_image_map_draw,
      eng_image_map_surface_new,
      eng_image_map_surface_free,
      NULL, // eng_image_content_hint_set - software doesn't use it