Add a version of miComputeCompositeRegion; call it from
authorSøren Sandmann Pedersen <sandmann@redhat.com>
Mon, 11 Jun 2007 04:22:19 +0000 (00:22 -0400)
committerSøren Sandmann Pedersen <sandmann@redhat.com>
Mon, 11 Jun 2007 04:22:19 +0000 (00:22 -0400)
pixman_image_composite(). Remove const from return value of
pixman_region_rectangles().

pixman/Makefile.am
pixman/pixman-compute-region.c [new file with mode: 0644]
pixman/pixman-image.c
pixman/pixman-pict.c
pixman/pixman-private.h
pixman/pixman-region.c
pixman/pixman.h

index 71b70a9..f08ec23 100644 (file)
@@ -12,8 +12,8 @@ libpixman_la_SOURCES =                \
        pixman-utils.c          \
        pixman-edge.c           \
        pixman-edge-imp.h       \
-       pixman-trap.c
-
+       pixman-trap.c           \
+       pixman-compute-region.c
 
 if USE_MMX
 noinst_LTLIBRARIES = libpixman-mmx.la
diff --git a/pixman/pixman-compute-region.c b/pixman/pixman-compute-region.c
new file mode 100644 (file)
index 0000000..d4e0ed6
--- /dev/null
@@ -0,0 +1,206 @@
+/*
+ *
+ * Copyright © 1999 Keith Packard
+ *
+ * Permission to use, copy, modify, distribute, and sell this software and its
+ * documentation for any purpose is hereby granted without fee, provided that
+ * the above copyright notice appear in all copies and that both that
+ * copyright notice and this permission notice appear in supporting
+ * documentation, and that the name of Keith Packard not be used in
+ * advertising or publicity pertaining to distribution of the software without
+ * specific, written prior permission.  Keith Packard makes no
+ * representations about the suitability of this software for any purpose.  It
+ * is provided "as is" without express or implied warranty.
+ *
+ * KEITH PACKARD DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE,
+ * INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO
+ * EVENT SHALL KEITH PACKARD BE LIABLE FOR ANY SPECIAL, INDIRECT OR
+ * CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE,
+ * DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER
+ * TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+ * PERFORMANCE OF THIS SOFTWARE.
+ */
+
+#include <config.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include "pixman-private.h"
+
+#define BOUND(v)       (int16_t) ((v) < INT16_MIN ? INT16_MIN : (v) > INT16_MAX ? INT16_MAX : (v))
+
+static inline pixman_bool_t
+miClipPictureReg (pixman_region16_t *  pRegion,
+                 pixman_region16_t *   pClip,
+                 int           dx,
+                 int           dy)
+{
+    if (pixman_region_n_rects(pRegion) == 1 &&
+       pixman_region_n_rects(pClip) == 1)
+    {
+       pixman_box16_t *  pRbox = pixman_region_rectangles(pRegion, NULL);
+       pixman_box16_t *  pCbox = pixman_region_rectangles(pClip, NULL);
+       int     v;
+       
+       if (pRbox->x1 < (v = pCbox->x1 + dx))
+           pRbox->x1 = BOUND(v);
+       if (pRbox->x2 > (v = pCbox->x2 + dx))
+           pRbox->x2 = BOUND(v);
+       if (pRbox->y1 < (v = pCbox->y1 + dy))
+           pRbox->y1 = BOUND(v);
+       if (pRbox->y2 > (v = pCbox->y2 + dy))
+           pRbox->y2 = BOUND(v);
+       if (pRbox->x1 >= pRbox->x2 ||
+           pRbox->y1 >= pRbox->y2)
+       {
+           pixman_region_init (pRegion);
+       }
+    }
+    else if (!pixman_region_not_empty (pClip))
+       return FALSE;
+    else
+    {
+       if (dx || dy)
+           pixman_region_translate (pRegion, -dx, -dy);
+       if (!pixman_region_intersect (pRegion, pRegion, pClip))
+           return FALSE;
+       if (dx || dy)
+           pixman_region_translate(pRegion, dx, dy);
+    }
+    return pixman_region_not_empty(pRegion);
+}
+
+
+static inline pixman_bool_t
+miClipPictureSrc (pixman_region16_t *  pRegion,
+                 pixman_image_t *      pPicture,
+                 int           dx,
+                 int           dy)
+{
+    /* XXX what to do with clipping from transformed pictures? */
+    if (pPicture->common.transform || pPicture->type != BITS)
+       return TRUE;
+
+    if (pPicture->common.repeat)
+    {
+       /* If the clip region was set by a client, then it should be intersected
+        * with the composite region since it's interpreted as happening
+        * after the repeat algorithm.
+        *
+        * If the clip region was not set by a client, then it was imposed by
+        * boundaries of the pixmap, or by sibling or child windows, which means
+        * it should in theory be repeated along. FIXME: we ignore that case.
+        * It is only relevant for windows that are (a) clipped by siblings/children
+        * and (b) used as source. However this case is not useful anyway due
+        * to lack of GraphicsExpose events.
+        */
+       if (pPicture->common.has_client_clip)
+       {
+           pixman_region_translate ( pRegion, dx, dy);
+           
+           if (!pixman_region_intersect (pRegion, pRegion, 
+                                         (pixman_region16_t *) &pPicture->common.clip_region))
+               return FALSE;
+           
+           pixman_region_translate ( pRegion, -dx, -dy);
+       }
+           
+       return TRUE;
+    }
+    else
+    {
+       return miClipPictureReg (pRegion,
+                                &pPicture->common.clip_region,
+                                dx,
+                                dy);
+    }
+}
+
+/*
+ * returns FALSE if the final region is empty.  Indistinguishable from
+ * an allocation failure, but rendering ignores those anyways.
+ */
+
+pixman_bool_t
+pixman_compute_composite_region (pixman_region16_t *   pRegion,
+                                pixman_image_t *       pSrc,
+                                pixman_image_t *       pMask,
+                                pixman_image_t *       pDst,
+                                int16_t                xSrc,
+                                int16_t                ySrc,
+                                int16_t                xMask,
+                                int16_t                yMask,
+                                int16_t                xDst,
+                                int16_t                yDst,
+                                uint16_t       width,
+                                uint16_t       height)
+{
+    int                v;
+    
+    pRegion->extents.x1 = xDst;
+    v = xDst + width;
+    pRegion->extents.x2 = BOUND(v);
+    pRegion->extents.y1 = yDst;
+    v = yDst + height;
+    pRegion->extents.y2 = BOUND(v);
+    pRegion->data = 0;
+    /* Check for empty operation */
+    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
+       pRegion->extents.y1 >= pRegion->extents.y2)
+    {
+       pixman_region_init (pRegion);
+       return FALSE;
+    }
+    /* clip against dst */
+    if (!miClipPictureReg (pRegion, &pDst->common.clip_region, 0, 0))
+    {
+       pixman_region_fini (pRegion);
+       return FALSE;
+    }
+    if (pDst->common.alpha_map)
+    {
+       if (!miClipPictureReg (pRegion, &pDst->common.alpha_map->common.clip_region,
+                              -pDst->common.alpha_origin.x,
+                              -pDst->common.alpha_origin.y))
+       {
+           pixman_region_fini (pRegion);
+           return FALSE;
+       }
+    }
+    /* clip against src */
+    if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
+    {
+       pixman_region_fini (pRegion);
+       return FALSE;
+    }
+    if (pSrc->common.alpha_map)
+    {
+       if (!miClipPictureSrc (pRegion, (pixman_image_t *)pSrc->common.alpha_map,
+                              xDst - (xSrc + pSrc->common.alpha_origin.x),
+                              yDst - (ySrc + pSrc->common.alpha_origin.y)))
+       {
+           pixman_region_fini (pRegion);
+           return FALSE;
+       }
+    }
+    /* clip against mask */
+    if (pMask)
+    {
+       if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
+       {
+           pixman_region_fini (pRegion);
+           return FALSE;
+       }       
+       if (pMask->common.alpha_map)
+       {
+           if (!miClipPictureSrc (pRegion, (pixman_image_t *)pMask->common.alpha_map,
+                                  xDst - (xMask + pMask->common.alpha_origin.x),
+                                  yDst - (yMask + pMask->common.alpha_origin.y)))
+           {
+               pixman_region_fini (pRegion);
+               return FALSE;
+           }
+       }
+    }
+    
+    return TRUE;
+}
index e7e5d24..1cc28b2 100644 (file)
@@ -85,6 +85,7 @@ allocate_image (void)
        image_common_t *common = &image->common;
        
        pixman_region_init (&common->clip_region);
+       common->has_client_clip = FALSE;
        common->transform = NULL;
        common->repeat = PIXMAN_REPEAT_NONE;
        common->filter = PIXMAN_FILTER_NEAREST;
@@ -310,6 +311,15 @@ pixman_image_set_clip_region (pixman_image_t    *image,
     }
 }
 
+/* Sets whether the clip region includes a clip region set by the client
+ */
+void
+pixman_image_set_has_client_clip (pixman_image_t *image,
+                                 pixman_bool_t   client_clip)
+{
+    image->common.has_client_clip = client_clip;
+}
+
 void
 pixman_image_set_transform (pixman_image_t           *image,
                            const pixman_transform_t *transform)
index cff88e7..76793b1 100644 (file)
@@ -942,150 +942,6 @@ fbCompositeSrcSrc_nxn  (pixman_op_t          op,
 #endif
 }
 
-#define BOUND(v)        (int16_t) ((v) < INT16_MIN ? INT16_MIN : (v) > INT16_MAX ? INT16_MAX : (v))
-
-static __inline pixman_bool_t
-miClipPictureReg (pixman_region16_t *  pRegion,
-                 pixman_region16_t *   pClip,
-                 int                   dx,
-                 int                   dy)
-{
-    if (pixman_region_n_rects(pRegion) == 1 &&
-       pixman_region_n_rects(pClip) == 1)
-    {
-       pixman_box16_t *  pRbox = pixman_region_rectangles(pRegion, NULL);
-       pixman_box16_t *  pCbox = pixman_region_rectangles(pClip, NULL);
-       int     v;
-
-       if (pRbox->x1 < (v = pCbox->x1 + dx))
-           pRbox->x1 = BOUND(v);
-       if (pRbox->x2 > (v = pCbox->x2 + dx))
-           pRbox->x2 = BOUND(v);
-       if (pRbox->y1 < (v = pCbox->y1 + dy))
-           pRbox->y1 = BOUND(v);
-       if (pRbox->y2 > (v = pCbox->y2 + dy))
-           pRbox->y2 = BOUND(v);
-       if (pRbox->x1 >= pRbox->x2 ||
-           pRbox->y1 >= pRbox->y2)
-       {
-           pixman_region_init (pRegion);
-       }
-    }
-    else if (!pixman_region_not_empty (pClip))
-       return FALSE;
-    else
-    {
-       if (dx || dy)
-           pixman_region_translate (pRegion, -dx, -dy);
-       if (!pixman_region_intersect (pRegion, pRegion, pClip))
-           return FALSE;
-       if (dx || dy)
-           pixman_region_translate(pRegion, dx, dy);
-    }
-    return pixman_region_not_empty (pRegion);
-}
-                 
-static __inline pixman_bool_t
-miClipPictureSrc (pixman_region16_t *  pRegion,
-                 pixman_image_t *      pPicture,
-                 int           dx,
-                 int           dy)
-{
-    /* XXX what to do with clipping from transformed pictures? */
-    if (pPicture->common.transform || pPicture->type != BITS)
-       return TRUE;
-    
-    return miClipPictureReg (pRegion,
-                            &pPicture->common.clip_region,
-                            dx,
-                            dy);
-}
-
-static pixman_bool_t
-compute_composite_region (pixman_region16_t *  pRegion,
-                         pixman_image_t *      pSrc,
-                         pixman_image_t *      pMask,
-                         pixman_image_t *      pDst,
-                         int16_t               xSrc,
-                         int16_t               ySrc,
-                         int16_t               xMask,
-                         int16_t               yMask,
-                         int16_t               xDst,
-                         int16_t               yDst,
-                         uint16_t      width,
-                         uint16_t      height)
-{
-    int                v;
-
-    pRegion->extents.x1 = xDst;
-    v = xDst + width;
-    pRegion->extents.x2 = BOUND(v);
-    pRegion->extents.y1 = yDst;
-    v = yDst + height;
-    pRegion->extents.y2 = BOUND(v);
-    pRegion->data = 0;
-    /* Check for empty operation */
-    if (pRegion->extents.x1 >= pRegion->extents.x2 ||
-       pRegion->extents.y1 >= pRegion->extents.y2)
-    {
-       pixman_region_init (pRegion);
-       return FALSE;
-    }
-    /* clip against dst */
-    if (!miClipPictureReg (pRegion, &pDst->common.clip_region, 0, 0))
-    {
-       pixman_region_fini (pRegion);
-       return FALSE;
-    }
-    if (pDst->common.alpha_map)
-    {
-       if (!miClipPictureReg (pRegion, &pDst->common.alpha_map->common.clip_region,
-                              -pDst->common.alpha_origin.x,
-                              -pDst->common.alpha_origin.y))
-       {
-           pixman_region_fini (pRegion);
-           return FALSE;
-       }
-    }
-    /* clip against src */
-    if (!miClipPictureSrc (pRegion, pSrc, xDst - xSrc, yDst - ySrc))
-    {
-       pixman_region_fini (pRegion);
-       return FALSE;
-    }
-    if (pSrc->common.alpha_map)
-    {
-       if (!miClipPictureSrc (pRegion, (pixman_image_t *)pSrc->common.alpha_map,
-                              xDst - (xSrc + pSrc->common.alpha_origin.x),
-                              yDst - (ySrc + pSrc->common.alpha_origin.y)))
-       {
-           pixman_region_fini (pRegion);
-           return FALSE;
-       }
-    }
-    /* clip against mask */
-    if (pMask)
-    {
-       if (!miClipPictureSrc (pRegion, pMask, xDst - xMask, yDst - yMask))
-       {
-           pixman_region_fini (pRegion);
-           return FALSE;
-       }       
-       if (pMask->common.alpha_map)
-       {
-           if (!miClipPictureSrc (pRegion, (pixman_image_t *)pMask->common.alpha_map,
-                                  xDst - (xMask + pMask->common.alpha_origin.x),
-                                  yDst - (yMask + pMask->common.alpha_origin.y)))
-           {
-               pixman_region_fini (pRegion);
-               return FALSE;
-           }
-       }
-    }
-    
-    return TRUE;
-}
-                         
 static void
 pixman_walk_composite_region (pixman_op_t op,
                              pixman_image_t * pSrc,
@@ -1101,25 +957,23 @@ pixman_walk_composite_region (pixman_op_t op,
                              uint16_t height,
                              pixman_bool_t srcRepeat,
                              pixman_bool_t maskRepeat,
-                             CompositeFunc compositeRect,
-                             pixman_region16_t *region)
+                             CompositeFunc compositeRect)
 {
-#if 0
-    pixman_region16_t region;
-#endif
     int                    n;
     const pixman_box16_t *pbox;
     int                    w, h, w_this, h_this;
     int                    x_msk, y_msk, x_src, y_src, x_dst, y_dst;
-    
-#if 0
-    if (!compute_composite_region (&region, pSrc, pMask, pDst, xSrc, ySrc,
-                                  xMask, yMask, xDst, yDst, width, height))
+    pixman_region16_t reg;
+    pixman_region16_t *region;
+
+    pixman_region_init (&reg);
+    if (!pixman_compute_composite_region (&reg, pSrc, pMask, pDst,
+                                         xSrc, ySrc, xMask, yMask, xDst, yDst, width, height))
     {
-       fprinf ("blah\n");
-        return;
+       return;
     }
-#endif
+
+    region = &reg;
     
     pbox = pixman_region_rectangles (region, &n);
     while (n--)
@@ -1177,9 +1031,7 @@ pixman_walk_composite_region (pixman_op_t op,
        }
        pbox++;
     }
-#if 0
-    pixman_region_fini (&region);
-#endif
+    pixman_region_fini (&reg);
 }
 
 static pixman_bool_t
@@ -1223,8 +1075,7 @@ pixman_image_composite (pixman_op_t      op,
                        int16_t      xDst,
                        int16_t      yDst,
                        uint16_t     width,
-                       uint16_t     height,
-                       pixman_region16_t *region)
+                       uint16_t     height)
 {
     pixman_bool_t          srcRepeat = pSrc->type == BITS && pSrc->common.repeat == PIXMAN_REPEAT_NORMAL;
     pixman_bool_t          maskRepeat = FALSE;
@@ -1234,7 +1085,7 @@ pixman_image_composite (pixman_op_t      op,
     pixman_bool_t      maskAlphaMap = FALSE;
     pixman_bool_t      dstAlphaMap = pDst->common.alpha_map != NULL;
     CompositeFunc   func = NULL;
-
+    
 #ifdef USE_MMX
     static pixman_bool_t mmx_setup = FALSE;
     if (!mmx_setup)
@@ -1821,7 +1672,7 @@ pixman_image_composite (pixman_op_t      op,
 
     pixman_walk_composite_region (op, pSrc, pMask, pDst, xSrc, ySrc,
                                  xMask, yMask, xDst, yDst, width, height,
-                                 srcRepeat, maskRepeat, func, region);
+                                 srcRepeat, maskRepeat, func);
 }
 
 
index 06d641c..09969fb 100644 (file)
@@ -148,6 +148,7 @@ struct image_common
     image_type_t               type;
     int32_t                    ref_count;
     pixman_region16_t          clip_region;
+    pixman_bool_t               has_client_clip;
     pixman_transform_t        *transform;
     pixman_repeat_t            repeat;
     pixman_filter_t            filter;
index f5d2f45..7a0f9da 100644 (file)
@@ -49,6 +49,7 @@ SOFTWARE.
 #include <stdlib.h>
 #include <limits.h>
 #include <string.h>
+#include <stdio.h>
 
 #include "pixman-private.h"
 #include "pixman.h"
@@ -256,8 +257,7 @@ pixman_region_equal(reg1, reg2)
     return TRUE;
 }
 
-#ifdef DEBUG_PIXREGION
-static int
+int
 pixman_region16_print(rgn)
     pixman_region16_t * rgn;
 {
@@ -268,17 +268,16 @@ pixman_region16_print(rgn)
     num = PIXREGION_NUM_RECTS(rgn);
     size = PIXREGION_SIZE(rgn);
     rects = PIXREGION_RECTS(rgn);
-    ErrorF("num: %d size: %d\n", num, size);
-    ErrorF("extents: %d %d %d %d\n",
+    fprintf(stderr, "num: %d size: %d\n", num, size);
+    fprintf(stderr, "extents: %d %d %d %d\n",
           rgn->extents.x1, rgn->extents.y1, rgn->extents.x2, rgn->extents.y2);
     for (i = 0; i < num; i++)
-      ErrorF("%d %d %d %d \n",
-            rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
-    ErrorF("\n");
+       fprintf(stderr, "%d %d %d %d \n",
+               rects[i].x1, rects[i].y1, rects[i].x2, rects[i].y2);
+    fprintf(stderr, "\n");
     return(num);
 }
 
-#endif /* DEBUG_PIXREGION */
 
 void
 pixman_region_init (pixman_region16_t *region)
@@ -324,7 +323,7 @@ pixman_region_rects (pixman_region16_t *region)
     return PIXREGION_RECTS (region);
 }
 
-const pixman_box16_t *
+pixman_box16_t *
 pixman_region_rectangles (pixman_region16_t *region,
                          int               *n_rects)
 {
index b6d3a95..7f33273 100644 (file)
@@ -282,7 +282,7 @@ pixman_region_overlap_t pixman_region_contains_rectangle (pixman_region16_t *pix
 pixman_bool_t           pixman_region_not_empty (pixman_region16_t *region);
 pixman_box16_t *        pixman_region_extents (pixman_region16_t *region);
 int                     pixman_region_n_rects (pixman_region16_t *region);
-const pixman_box16_t *  pixman_region_rectangles (pixman_region16_t *region,
+pixman_box16_t *        pixman_region_rectangles (pixman_region16_t *region,
                                                  int               *n_rects);
 pixman_bool_t          pixman_region_equal (pixman_region16_t *region1,
                                             pixman_region16_t *region2);
@@ -436,6 +436,8 @@ void            pixman_image_unref                   (pixman_image_t
 /* Set properties */
 void            pixman_image_set_clip_region         (pixman_image_t               *image,
                                                      pixman_region16_t            *region);
+void           pixman_image_set_has_client_clip     (pixman_image_t               *image,
+                                                     pixman_bool_t                 clien_clip);
 void            pixman_image_set_transform           (pixman_image_t               *image,
                                                      const pixman_transform_t     *transform);
 void            pixman_image_set_repeat              (pixman_image_t               *image,
@@ -460,6 +462,18 @@ void               pixman_image_set_indexed             (pixman_image_t               *image,
                                                      const pixman_indexed_t       *indexed);
 
 /* Composite */
+pixman_bool_t   pixman_compute_composite_region (pixman_region16_t *   pRegion,
+                                                pixman_image_t *       pSrc,
+                                                pixman_image_t *       pMask,
+                                                pixman_image_t *       pDst,
+                                                int16_t                xSrc,
+                                                int16_t                ySrc,
+                                                int16_t                xMask,
+                                                int16_t                yMask,
+                                                int16_t                xDst,
+                                                int16_t                yDst,
+                                                uint16_t               width,
+                                                uint16_t               height);
 void           pixman_image_composite               (pixman_op_t                   op,
                                                      pixman_image_t               *src,
                                                      pixman_image_t               *mask,
@@ -471,8 +485,7 @@ void                pixman_image_composite               (pixman_op_t                   op,
                                                      int16_t                       dest_x,
                                                      int16_t                       dest_y,
                                                      uint16_t                      width,
-                                                     uint16_t                      height,
-                                                     pixman_region16_t            *composite_region);
+                                                     uint16_t                      height);
 void            pixman_image_composite_rect          (pixman_op_t                   op,
                                                      pixman_image_t               *src,
                                                      pixman_image_t               *mask,