Add slightly changed copy of miComputeCompositeRegion() to pixman-pict.c
authorSøren Sandmann <sandmann@redhat.com>
Mon, 21 May 2007 14:00:05 +0000 (10:00 -0400)
committerSøren Sandmann <sandmann@redhat.com>
Mon, 21 May 2007 14:00:05 +0000 (10:00 -0400)
TODO
pixman/pixman-pict.c
pixman/pixman.h

diff --git a/TODO b/TODO
index 4bc4895..69feef7 100644 (file)
--- a/TODO
+++ b/TODO
         IC_SHIFT to 5 for all machines.
 
 - Consider whether calling regions region16 is really such a great idea
+
+- Right now we _always_ have a clip region, which is empty by default.
+  Why does this work at all? It probably doesn't. The server
+  distinguishes two cases, one where nothing is clipped (CT_NONE), and
+  one where there is a clip region (CT_REGION).
+
+- The rectangles in a region probably shouldn't be returned const as
+  the X server will be changing them.
index 5c4fe7a..ad1b762 100644 (file)
@@ -991,23 +991,147 @@ fbCompositeSrcSrc_nxn  (pixman_op_t         op,
 #endif
 }
 
-static pixman_bool_t
-compute_composite_region (pixman_region16_t *region,
-                         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)
+#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)
 {
-    /* FIXME */
-    pixman_region_init (region);
+    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;
 }
                          
index 60ecae0..7c7968c 100644 (file)
@@ -460,6 +460,18 @@ void               pixman_image_set_indexed             (pixman_image_t               *image,
                                                      const pixman_indexed_t       *indexed);
 
 /* Composite */
+void           pixman_image_composite               (pixman_op_t                   op,
+                                                     pixman_image_t               *src,
+                                                     pixman_image_t               *mask,
+                                                     pixman_image_t               *dest,
+                                                     int16_t                       src_x,
+                                                     int16_t                       src_y,
+                                                     int16_t                       mask_x,
+                                                     int16_t                       mask_y,
+                                                     int16_t                       dest_x,
+                                                     int16_t                       dest_y,
+                                                     uint16_t                      width,
+                                                     uint16_t                      height);
 void            pixman_image_composite_rect          (pixman_op_t                   op,
                                                      pixman_image_t               *src,
                                                      pixman_image_t               *mask,