pixman_image_set_alpha_map(): Disallow alpha map cycles
authorSøren Sandmann Pedersen <ssp@redhat.com>
Wed, 4 Aug 2010 21:51:49 +0000 (17:51 -0400)
committerSøren Sandmann Pedersen <ssp@redhat.com>
Mon, 16 Aug 2010 02:08:16 +0000 (22:08 -0400)
If someone tries to set an alpha map that itself has an alpha map,
simply return. Also, if someone tries to add an alpha map to an image
that is being _used_ as an alpha map, simply return.

This ensures that an alpha map can never have an alpha map.

pixman/pixman-image.c
pixman/pixman-private.h

index 269c3c1..cdc9c40 100644 (file)
@@ -101,6 +101,7 @@ _pixman_image_allocate (void)
 
        pixman_region32_init (&common->clip_region);
 
+       common->alpha_count = 0;
        common->have_clip_region = FALSE;
        common->clip_sources = FALSE;
        common->transform = NULL;
@@ -668,15 +669,41 @@ pixman_image_set_alpha_map (pixman_image_t *image,
 
     return_if_fail (!alpha_map || alpha_map->type == BITS);
 
+    if (alpha_map && common->alpha_count > 0)
+    {
+       /* If this image is being used as an alpha map itself,
+        * then you can't give it an alpha map of its own.
+        */
+       return;
+    }
+
+    if (alpha_map && alpha_map->common.alpha_map)
+    {
+       /* If the image has an alpha map of its own,
+        * then it can't be used as an alpha map itself
+        */
+       return;
+    }
+
     if (common->alpha_map != (bits_image_t *)alpha_map)
     {
        if (common->alpha_map)
+       {
+           common->alpha_map->common.alpha_count--;
+
            pixman_image_unref ((pixman_image_t *)common->alpha_map);
+       }
 
        if (alpha_map)
+       {
            common->alpha_map = (bits_image_t *)pixman_image_ref (alpha_map);
+
+           common->alpha_map->common.alpha_count++;
+       }
        else
+       {
            common->alpha_map = NULL;
+       }
     }
 
     common->alpha_origin_x = x;
index 0629c42..c4e6bb8 100644 (file)
@@ -80,6 +80,7 @@ struct image_common
     image_type_t                type;
     int32_t                     ref_count;
     pixman_region32_t           clip_region;
+    int32_t                    alpha_count;        /* How many times this image is being used as an alpha map */
     pixman_bool_t               have_clip_region;   /* FALSE if there is no clip */
     pixman_bool_t               client_clip;        /* Whether the source clip was
                                                       set by a client */