]> Pileus Git - ~andy/gtk/commitdiff
Implement GdkRegion in terms of cairo_region_t
authorBenjamin Otte <otte@redhat.com>
Mon, 28 Jun 2010 12:27:55 +0000 (14:27 +0200)
committerBenjamin Otte <otte@redhat.com>
Tue, 29 Jun 2010 14:06:38 +0000 (16:06 +0200)
Only changes in headers: GdkRegion and GdkRectangle are typedeffed to
cairo_region_t and cairo_rectangle_int_t respectively. The region type
was opaque anyway so it doesn't matter and the rectangle types are
identical.

https://bugzilla.gnome.org/show_bug.cgi?id=613284

gdk/gdkcairo.c
gdk/gdkpolyreg-generic.c
gdk/gdkregion-generic.c
gdk/gdktypes.h
gdk/x11/gdkdrawable-x11.c
gdk/x11/gdkgc-x11.c
gdk/x11/gdkmain-x11.c

index ef8ec25627553eefd8994c63e93f0aa9ae8ef9c2..868be8eb42bcbc2974bed97007a731b9fbfed0fe 100644 (file)
@@ -20,7 +20,6 @@
 #include "gdkcairo.h"
 #include "gdkdrawable.h"
 #include "gdkinternals.h"
-#include "gdkregion-generic.h"
 #include "gdkalias.h"
 
 /**
@@ -143,21 +142,19 @@ void
 gdk_cairo_region (cairo_t         *cr,
                  const GdkRegion *region)
 {
-  GdkRegionBox *boxes;
+  cairo_rectangle_int_t box;
   gint n_boxes, i;
 
   g_return_if_fail (cr != NULL);
   g_return_if_fail (region != NULL);
 
-  boxes = region->rects;
-  n_boxes = region->numRects;
+  n_boxes = cairo_region_num_rectangles (region);
 
   for (i = 0; i < n_boxes; i++)
-    cairo_rectangle (cr,
-                    boxes[i].x1,
-                    boxes[i].y1,
-                    boxes[i].x2 - boxes[i].x1,
-                    boxes[i].y2 - boxes[i].y1);
+    {
+      cairo_region_get_rectangle (region, i, &box);
+      cairo_rectangle (cr, box.x, box.y, box.width, box.height);
+    }
 }
 
 /**
index 95433383a2428a0f7d99ec35d4e6dbdaf0c6fb84..f344b54948ee1d1f09c3325198f86501a46a13a1 100644 (file)
@@ -382,29 +382,25 @@ FreeStorage (ScanLineListBlock *pSLLBlock)
  *     stack by the calling procedure.
  *
  */
-static int
+static cairo_region_t *
 PtsToRegion (int         numFullPtBlocks,
              int         iCurPtBlock,
-             POINTBLOCK *FirstPtBlock,
-             GdkRegion  *reg)
+             POINTBLOCK *FirstPtBlock)
 {
-    GdkRegionBox *rects;
+    GdkRectangle *rects, *allRects;
     GdkPoint *pts;
     POINTBLOCK *CurPtBlock;
     int i;
-    GdkRegionBox *extents;
     int numRects;
+    cairo_region_t *region;
 
-    extents = &reg->extents;
     numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
  
-    GROWREGION(reg, numRects);
+    allRects = g_new (GdkRectangle, numRects);
 
     CurPtBlock = FirstPtBlock;
-    rects = reg->rects - 1;
+    rects = allRects - 1;
     numRects = 0;
-    extents->x1 = G_MAXSHORT,  extents->x2 = G_MINSHORT;
  
     for ( ; numFullPtBlocks >= 0; numFullPtBlocks--) {
        /* the loop uses 2 points per iteration */
@@ -414,37 +410,24 @@ PtsToRegion (int         numFullPtBlocks,
        for (pts = CurPtBlock->pts; i--; pts += 2) {
            if (pts->x == pts[1].x)
                continue;
-           if (numRects && pts->x == rects->x1 && pts->y == rects->y2 &&
-               pts[1].x == rects->x2 &&
-               (numRects == 1 || rects[-1].y1 != rects->y1) &&
+           if (numRects && pts->x == rects->x && pts->y == rects->y + rects->height &&
+               pts[1].x == rects->x + rects->width &&
+               (numRects == 1 || rects[-1].y != rects->y) &&
                (i && pts[2].y > pts[1].y)) {
-               rects->y2 = pts[1].y + 1;
+               rects->height = pts[1].y + 1 - rects->y;
                continue;
            }
            numRects++;
            rects++;
-           rects->x1 = pts->x;  rects->y1 = pts->y;
-           rects->x2 = pts[1].x;  rects->y2 = pts[1].y + 1;
-           if (rects->x1 < extents->x1)
-               extents->x1 = rects->x1;
-           if (rects->x2 > extents->x2)
-               extents->x2 = rects->x2;
+           rects->x = pts->x;  rects->y = pts->y;
+           rects->width = pts[1].x - rects->x;  rects->height = pts[1].y + 1 - rects->y;
         }
        CurPtBlock = CurPtBlock->next;
     }
 
-    if (numRects) {
-       extents->y1 = reg->rects->y1;
-       extents->y2 = rects->y2;
-    } else {
-       extents->x1 = 0;
-       extents->y1 = 0;
-       extents->x2 = 0;
-       extents->y2 = 0;
-    }
-    reg->numRects = numRects;
-    return(TRUE);
+    region = cairo_region_create_rectangles (allRects, numRects);
+    g_free (allRects);
+    return region;
 }
 
 /**
@@ -481,8 +464,6 @@ gdk_region_polygon (const GdkPoint *points,
     POINTBLOCK *tmpPtBlock;
     int numFullPtBlocks = 0;
  
-    region = gdk_region_new ();
-
     /* special case a rectangle */
     if (((n_points == 4) ||
         ((n_points == 5) && (points[4].x == points[0].x) && (points[4].y == points[0].y))) &&
@@ -494,16 +475,13 @@ gdk_region_polygon (const GdkPoint *points,
          (points[1].y == points[2].y) &&
          (points[2].x == points[3].x) &&
          (points[3].y == points[0].y)))) {
-       region->extents.x1 = MIN(points[0].x, points[2].x);
-       region->extents.y1 = MIN(points[0].y, points[2].y);
-       region->extents.x2 = MAX(points[0].x, points[2].x);
-       region->extents.y2 = MAX(points[0].y, points[2].y);
-       if ((region->extents.x1 != region->extents.x2) &&
-           (region->extents.y1 != region->extents.y2)) {
-           region->numRects = 1;
-           *(region->rects) = region->extents;
-       }
-       return(region);
+        GdkRectangle extents;
+
+       extents.x = MIN(points[0].x, points[2].x);
+       extents.y = MIN(points[0].y, points[2].y);
+       extents.width = MAX(points[0].x, points[2].x) - extents.x;
+       extents.height = MAX(points[0].y, points[2].y) - extents.y;
+       return gdk_region_rectangle (&extents);
     }
 
     pETEs = g_new (EdgeTableEntry, n_points);
@@ -610,7 +588,7 @@ gdk_region_polygon (const GdkPoint *points,
         }
     }
     FreeStorage(SLLBlock.next);        
-    (void) PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
+    region = PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock);
     for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
        tmpPtBlock = curPtBlock->next;
        g_free (curPtBlock);
index 0801b1ebfd9d53658609779623728ff57b983314..7b74222b19f234d349affab81134d0c32a7b7a40 100644 (file)
@@ -1,103 +1,9 @@
-/* $TOG: Region.c /main/31 1998/02/06 17:50:22 kaleb $ */
-/************************************************************************
-
-Copyright 1987, 1988, 1998  The Open Group
-
-All Rights Reserved.
-
-The above copyright notice and this permission notice shall be included in
-all copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL THE
-OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
-AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
-CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
-
-Except as contained in this notice, the name of The Open Group shall not be
-used in advertising or otherwise to promote the sale, use or other dealings
-in this Software without prior written authorization from The Open Group.
-
-
-Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
-
-                        All Rights Reserved
-
-Permission to use, copy, modify, and distribute this software and its 
-documentation for any purpose and without fee is hereby granted, 
-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 Digital not be
-used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.  
-
-DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
-ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
-DIGITAL 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.
-
-************************************************************************/
-/* $XFree86: xc/lib/X11/Region.c,v 1.5 1999/05/09 10:50:01 dawes Exp $ */
-/*
- * The functions in this file implement the Region abstraction, similar to one
- * used in the X11 sample server. A Region is simply an area, as the name
- * implies, and is implemented as a "y-x-banded" array of rectangles. To
- * explain: Each Region is made up of a certain number of rectangles sorted
- * by y coordinate first, and then by x coordinate.
- *
- * Furthermore, the rectangles are banded such that every rectangle with a
- * given upper-left y coordinate (y1) will have the same lower-right y
- * coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it
- * will span the entire vertical distance of the band. This means that some
- * areas that could be merged into a taller rectangle will be represented as
- * several shorter rectangles to account for shorter rectangles to its left
- * or right but within its "vertical scope".
- *
- * An added constraint on the rectangles is that they must cover as much
- * horizontal area as possible. E.g. no two rectangles in a band are allowed
- * to touch.
- *
- * Whenever possible, bands will be merged together to cover a greater vertical
- * distance (and thus reduce the number of rectangles). Two bands can be merged
- * only if the bottom of one touches the top of the other and they have
- * rectangles in the same places (of the same width, of course). This maintains
- * the y-x-banding that's so nice to have...
- */
-
 #include "config.h"
 #include <stdlib.h>
 #include <string.h>
 #include <gdkregion.h>
-#include "gdkregion-generic.h"
 #include "gdkalias.h"
 
-typedef void (* overlapFunc)    (GdkRegion    *pReg,
-                                 GdkRegionBox *r1,
-                                 GdkRegionBox *r1End,
-                                 GdkRegionBox *r2,
-                                 GdkRegionBox *r2End,
-                                 gint          y1,
-                                 gint          y2);
-typedef void (* nonOverlapFunc) (GdkRegion    *pReg,
-                                 GdkRegionBox *r,
-                                 GdkRegionBox *rEnd,
-                                 gint          y1,
-                                 gint          y2);
-
-static void miRegionCopy (GdkRegion       *dstrgn,
-                         const GdkRegion *rgn);
-static void miRegionOp   (GdkRegion       *newReg,
-                         GdkRegion       *reg1,
-                         const GdkRegion *reg2,
-                         overlapFunc      overlapFn,
-                         nonOverlapFunc   nonOverlap1Fn,
-                         nonOverlapFunc   nonOverlap2Fn);
-static void miSetExtents (GdkRegion       *pReg);
-
 /**
  * gdk_region_new:
  *
@@ -108,43 +14,14 @@ static void miSetExtents (GdkRegion       *pReg);
 GdkRegion *
 gdk_region_new (void)
 {
-  GdkRegion *temp;
-
-  temp = g_slice_new (GdkRegion);
-
-  temp->numRects = 0;
-  temp->rects = &temp->extents;
-  temp->extents.x1 = 0;
-  temp->extents.y1 = 0;
-  temp->extents.x2 = 0;
-  temp->extents.y2 = 0;
-  temp->size = 1;
-  
-  return temp;
+  return cairo_region_create ();
 }
 
 GdkRegion *
 _gdk_region_new_from_yxbanded_rects (GdkRectangle *rects,
                                     int num_rects)
 {
-  GdkRegion *temp;
-  int i;
-
-  temp = g_slice_new (GdkRegion);
-
-  temp->rects = g_new (GdkRegionBox, num_rects);
-  temp->size = num_rects;
-  temp->numRects = num_rects;
-  for (i = 0; i < num_rects; i++)
-    {
-      temp->rects[i].x1 = rects[i].x;
-      temp->rects[i].y1 = rects[i].y;
-      temp->rects[i].x2 = rects[i].x + rects[i].width;
-      temp->rects[i].y2 = rects[i].y + rects[i].height;
-    }
-  miSetExtents (temp);  
-  
-  return temp;
+  return cairo_region_create_rectangles (rects, num_rects);
 }
 
 
@@ -159,24 +36,12 @@ _gdk_region_new_from_yxbanded_rects (GdkRectangle *rects,
 GdkRegion *
 gdk_region_rectangle (const GdkRectangle *rectangle)
 {
-  GdkRegion *temp;
-
   g_return_val_if_fail (rectangle != NULL, NULL);
 
   if (rectangle->width <= 0 || rectangle->height <= 0)
     return gdk_region_new();
 
-  temp = g_slice_new (GdkRegion);
-
-  temp->numRects = 1;
-  temp->rects = &temp->extents;
-  temp->extents.x1 = rectangle->x;
-  temp->extents.y1 = rectangle->y;
-  temp->extents.x2 = rectangle->x + rectangle->width;
-  temp->extents.y2 = rectangle->y + rectangle->height;
-  temp->size = 1;
-  
-  return temp;
+  return cairo_region_create_rectangle (rectangle);
 }
 
 /**
@@ -190,15 +55,7 @@ gdk_region_rectangle (const GdkRectangle *rectangle)
 GdkRegion *
 gdk_region_copy (const GdkRegion *region)
 {
-  GdkRegion *temp;
-
-  g_return_val_if_fail (region != NULL, NULL);
-
-  temp = gdk_region_new ();
-
-  miRegionCopy (temp, region);
-
-  return temp;
+  return cairo_region_copy (region);
 }
 
 /**
@@ -216,10 +73,7 @@ gdk_region_get_clipbox (const GdkRegion *region,
   g_return_if_fail (region != NULL);
   g_return_if_fail (rectangle != NULL);
   
-  rectangle->x = region->extents.x1;
-  rectangle->y = region->extents.y1;
-  rectangle->width = region->extents.x2 - region->extents.x1;
-  rectangle->height = region->extents.y2 - region->extents.y1;
+  cairo_region_get_extents (region, rectangle);
 }
 
 
@@ -237,24 +91,23 @@ gdk_region_get_rectangles (const GdkRegion  *region,
                            GdkRectangle    **rectangles,
                            gint             *n_rectangles)
 {
-  gint i;
+  gint i, n;
+  GdkRectangle *rects;
   
   g_return_if_fail (region != NULL);
   g_return_if_fail (rectangles != NULL);
   g_return_if_fail (n_rectangles != NULL);
   
-  *n_rectangles = region->numRects;
-  *rectangles = g_new (GdkRectangle, region->numRects);
+  n = cairo_region_num_rectangles (region);
+  rects = g_new (GdkRectangle, n);
 
-  for (i = 0; i < region->numRects; i++)
+  for (i = 0; i < n; i++)
     {
-      GdkRegionBox rect;
-      rect = region->rects[i];
-      (*rectangles)[i].x = rect.x1;
-      (*rectangles)[i].y = rect.y1;
-      (*rectangles)[i].width = rect.x2 - rect.x1;
-      (*rectangles)[i].height = rect.y2 - rect.y1;
+      cairo_region_get_rectangle (region, i, &rects[i]);
     }
+
+  *n_rectangles = n;
+  *rectangles = rects;
 }
 
 /**
@@ -270,84 +123,13 @@ void
 gdk_region_union_with_rect (GdkRegion          *region,
                            const GdkRectangle *rect)
 {
-  GdkRegion tmp_region;
-
   g_return_if_fail (region != NULL);
   g_return_if_fail (rect != NULL);
 
   if (rect->width <= 0 || rect->height <= 0)
     return;
     
-  tmp_region.rects = &tmp_region.extents;
-  tmp_region.numRects = 1;
-  tmp_region.extents.x1 = rect->x;
-  tmp_region.extents.y1 = rect->y;
-  tmp_region.extents.x2 = rect->x + rect->width;
-  tmp_region.extents.y2 = rect->y + rect->height;
-  tmp_region.size = 1;
-
-  gdk_region_union (region, &tmp_region);
-}
-
-/*-
- *-----------------------------------------------------------------------
- * miSetExtents --
- *     Reset the extents of a region to what they should be. Called by
- *     miSubtract and miIntersect b/c they can't figure it out along the
- *     way or do so easily, as miUnion can.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     The region's 'extents' structure is overwritten.
- *
- *-----------------------------------------------------------------------
- */
-static void
-miSetExtents (GdkRegion *pReg)
-{
-  GdkRegionBox *pBox, *pBoxEnd, *pExtents;
-
-  if (pReg->numRects == 0)
-    {
-      pReg->extents.x1 = 0;
-      pReg->extents.y1 = 0;
-      pReg->extents.x2 = 0;
-      pReg->extents.y2 = 0;
-      return;
-    }
-  
-  pExtents = &pReg->extents;
-  pBox = pReg->rects;
-  pBoxEnd = &pBox[pReg->numRects - 1];
-
-    /*
-     * Since pBox is the first rectangle in the region, it must have the
-     * smallest y1 and since pBoxEnd is the last rectangle in the region,
-     * it must have the largest y2, because of banding. Initialize x1 and
-     * x2 from  pBox and pBoxEnd, resp., as good things to initialize them
-     * to...
-     */
-  pExtents->x1 = pBox->x1;
-  pExtents->y1 = pBox->y1;
-  pExtents->x2 = pBoxEnd->x2;
-  pExtents->y2 = pBoxEnd->y2;
-
-  g_assert(pExtents->y1 < pExtents->y2);
-  while (pBox <= pBoxEnd)
-    {
-      if (pBox->x1 < pExtents->x1)
-       {
-         pExtents->x1 = pBox->x1;
-       }
-      if (pBox->x2 > pExtents->x2)
-       {
-         pExtents->x2 = pBox->x2;
-       }
-      pBox++;
-    }
-  g_assert(pExtents->x1 < pExtents->x2);
+  cairo_region_union_rectangle (region, rect);
 }
 
 /**
@@ -361,9 +143,7 @@ gdk_region_destroy (GdkRegion *region)
 {
   g_return_if_fail (region != NULL);
 
-  if (region->rects != &region->extents)
-    g_free (region->rects);
-  g_slice_free (GdkRegion, region);
+  cairo_region_destroy (region);
 }
 
 
@@ -380,87 +160,9 @@ gdk_region_offset (GdkRegion *region,
                   gint       x,
                   gint       y)
 {
-  int nbox;
-  GdkRegionBox *pbox;
-
-  g_return_if_fail (region != NULL);
-
-  pbox = region->rects;
-  nbox = region->numRects;
-
-  while(nbox--)
-    {
-      pbox->x1 += x;
-      pbox->x2 += x;
-      pbox->y1 += y;
-      pbox->y2 += y;
-      pbox++;
-    }
-  if (region->rects != &region->extents)
-    {
-      region->extents.x1 += x;
-      region->extents.x2 += x;
-      region->extents.y1 += y;
-      region->extents.y2 += y;
-    }
+  cairo_region_translate (region, x, y);
 }
 
-/* 
-   Utility procedure Compress:
-   Replace r by the region r', where 
-     p in r' iff (Quantifer m <= dx) (p + m in r), and
-     Quantifier is Exists if grow is TRUE, For all if grow is FALSE, and
-     (x,y) + m = (x+m,y) if xdir is TRUE; (x,y+m) if xdir is FALSE.
-
-   Thus, if xdir is TRUE and grow is FALSE, r is replaced by the region
-   of all points p such that p and the next dx points on the same
-   horizontal scan line are all in r.  We do this using by noting
-   that p is the head of a run of length 2^i + k iff p is the head
-   of a run of length 2^i and p+2^i is the head of a run of length
-   k. Thus, the loop invariant: s contains the region corresponding
-   to the runs of length shift.  r contains the region corresponding
-   to the runs of length 1 + dxo & (shift-1), where dxo is the original
-   value of dx.  dx = dxo & ~(shift-1).  As parameters, s and t are
-   scratch regions, so that we don't have to allocate them on every
-   call.
-*/
-
-#define ZOpRegion(a,b) if (grow) gdk_region_union (a, b); \
-                        else gdk_region_intersect (a,b)
-#define ZShiftRegion(a,b) if (xdir) gdk_region_offset (a,b,0); \
-                         else gdk_region_offset (a,0,b)
-
-static void
-Compress(GdkRegion *r,
-        GdkRegion *s,
-        GdkRegion *t,
-        guint      dx,
-        int        xdir,
-        int        grow)
-{
-  guint shift = 1;
-
-  miRegionCopy (s, r);
-  while (dx)
-    {
-      if (dx & shift)
-       {
-         ZShiftRegion(r, -(int)shift);
-         ZOpRegion(r, s);
-         dx -= shift;
-         if (!dx) break;
-        }
-      miRegionCopy (t, s);
-      ZShiftRegion(s, -(int)shift);
-      ZOpRegion(s, t);
-      shift <<= 1;
-    }
-}
-
-#undef ZOpRegion
-#undef ZShiftRegion
-#undef ZCopyRegion
-
 /**
  * gdk_region_shrink:
  * @region: a #GdkRegion
@@ -475,111 +177,24 @@ gdk_region_shrink (GdkRegion *region,
                   int        dx,
                   int        dy)
 {
-  GdkRegion *s, *t;
-  int grow;
-
-  g_return_if_fail (region != NULL);
-
-  if (!dx && !dy)
-    return;
-
-  s = gdk_region_new ();
-  t = gdk_region_new ();
-
-  grow = (dx < 0);
-  if (grow)
-    dx = -dx;
-  if (dx)
-     Compress(region, s, t, (unsigned) 2*dx, TRUE, grow);
-     
-  grow = (dy < 0);
-  if (grow)
-    dy = -dy;
-  if (dy)
-     Compress(region, s, t, (unsigned) 2*dy, FALSE, grow);
-  
-  gdk_region_offset (region, dx, dy);
-  gdk_region_destroy (s);
-  gdk_region_destroy (t);
-}
-
-\f
-/*======================================================================
- *         Region Intersection
- *====================================================================*/
-/*-
- *-----------------------------------------------------------------------
- * miIntersectO --
- *     Handle an overlapping band for miIntersect.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     Rectangles may be added to the region.
- *
- *-----------------------------------------------------------------------
- */
-/* static void*/
-static void
-miIntersectO (GdkRegion    *pReg,
-             GdkRegionBox *r1,
-             GdkRegionBox *r1End,
-             GdkRegionBox *r2,
-             GdkRegionBox *r2End,
-             gint          y1,
-             gint          y2)
-{
-  int          x1;
-  int          x2;
-  GdkRegionBox *pNextRect;
+  GdkRectangle *rects;
+  int i, n_rects;
 
-  pNextRect = &pReg->rects[pReg->numRects];
+  gdk_region_get_rectangles (region, &rects, &n_rects);
+  /* clear region */
+  gdk_region_subtract (region, region);
 
-  while ((r1 != r1End) && (r2 != r2End))
+  for (i = 0; i < n_rects; i++)
     {
-      x1 = MAX (r1->x1,r2->x1);
-      x2 = MIN (r1->x2,r2->x2);
-
-      /*
-       * If there's any overlap between the two rectangles, add that
-       * overlap to the new region.
-       * There's no need to check for subsumption because the only way
-       * such a need could arise is if some region has two rectangles
-       * right next to each other. Since that should never happen...
-       */
-      if (x1 < x2)
-       {
-         g_assert (y1<y2);
-
-         MEMCHECK (pReg, pNextRect, pReg->rects);
-         pNextRect->x1 = x1;
-         pNextRect->y1 = y1;
-         pNextRect->x2 = x2;
-         pNextRect->y2 = y2;
-         pReg->numRects += 1;
-         pNextRect++;
-         g_assert (pReg->numRects <= pReg->size);
-       }
-
-      /*
-       * Need to advance the pointers. Shift the one that extends
-       * to the right the least, since the other still has a chance to
-       * overlap with that region's next rectangle, if you see what I mean.
-       */
-      if (r1->x2 < r2->x2)
-       {
-         r1++;
-       }
-      else if (r2->x2 < r1->x2)
-       {
-         r2++;
-       }
-      else
-       {
-         r1++;
-         r2++;
-       }
+      if (rects[i].width <= 2 * dx ||
+          rects[i].height <= 2 * dy)
+        continue;
+
+      rects[i].x += dx;
+      rects[i].y += dy;
+      rects[i].width -= 2 * dx;
+      rects[i].height -= 2 * dy;
+      cairo_region_union_rectangle (region, &rects[i]);
     }
 }
 
@@ -599,610 +214,7 @@ gdk_region_intersect (GdkRegion       *source1,
   g_return_if_fail (source1 != NULL);
   g_return_if_fail (source2 != NULL);
   
-  /* check for trivial reject */
-  if ((!(source1->numRects)) || (!(source2->numRects))  ||
-      (!EXTENTCHECK(&source1->extents, &source2->extents)))
-    source1->numRects = 0;
-  else
-    miRegionOp (source1, source1, source2,
-               miIntersectO, (nonOverlapFunc) NULL, (nonOverlapFunc) NULL);
-    
-  /*
-   * Can't alter source1's extents before miRegionOp depends on the
-   * extents of the regions being unchanged. Besides, this way there's
-   * no checking against rectangles that will be nuked due to
-   * coalescing, so we have to examine fewer rectangles.
-   */
-  miSetExtents(source1);
-}
-
-static void
-miRegionCopy (GdkRegion       *dstrgn,
-             const GdkRegion *rgn)
-{
-  if (dstrgn != rgn) /*  don't want to copy to itself */
-    {  
-      if (dstrgn->size < rgn->numRects)
-        {
-         if (dstrgn->rects != &dstrgn->extents)
-           g_free (dstrgn->rects);
-
-         dstrgn->rects = g_new (GdkRegionBox, rgn->numRects);
-         dstrgn->size = rgn->numRects;
-       }
-
-      dstrgn->numRects = rgn->numRects;
-      dstrgn->extents = rgn->extents;
-
-      memcpy (dstrgn->rects, rgn->rects, rgn->numRects * sizeof (GdkRegionBox));
-    }
-}
-
-
-/*======================================================================
- *         Generic Region Operator
- *====================================================================*/
-
-/*-
- *-----------------------------------------------------------------------
- * miCoalesce --
- *     Attempt to merge the boxes in the current band with those in the
- *     previous one. Used only by miRegionOp.
- *
- * Results:
- *     The new index for the previous band.
- *
- * Side Effects:
- *     If coalescing takes place:
- *         - rectangles in the previous band will have their y2 fields
- *           altered.
- *         - pReg->numRects will be decreased.
- *
- *-----------------------------------------------------------------------
- */
-/* static int*/
-static int
-miCoalesce (GdkRegion *pReg,         /* Region to coalesce */
-           gint       prevStart,    /* Index of start of previous band */
-           gint       curStart)     /* Index of start of current band */
-{
-  GdkRegionBox *pPrevBox;      /* Current box in previous band */
-  GdkRegionBox *pCurBox;       /* Current box in current band */
-  GdkRegionBox *pRegEnd;       /* End of region */
-  int          curNumRects;    /* Number of rectangles in current
-                                * band */
-  int          prevNumRects;   /* Number of rectangles in previous
-                                * band */
-  int          bandY1;         /* Y1 coordinate for current band */
-
-  pRegEnd = &pReg->rects[pReg->numRects];
-
-  pPrevBox = &pReg->rects[prevStart];
-  prevNumRects = curStart - prevStart;
-
-    /*
-     * Figure out how many rectangles are in the current band. Have to do
-     * this because multiple bands could have been added in miRegionOp
-     * at the end when one region has been exhausted.
-     */
-  pCurBox = &pReg->rects[curStart];
-  bandY1 = pCurBox->y1;
-  for (curNumRects = 0;
-       (pCurBox != pRegEnd) && (pCurBox->y1 == bandY1);
-       curNumRects++)
-    {
-      pCurBox++;
-    }
-    
-  if (pCurBox != pRegEnd)
-    {
-      /*
-       * If more than one band was added, we have to find the start
-       * of the last band added so the next coalescing job can start
-       * at the right place... (given when multiple bands are added,
-       * this may be pointless -- see above).
-       */
-      pRegEnd--;
-      while (pRegEnd[-1].y1 == pRegEnd->y1)
-       {
-         pRegEnd--;
-       }
-      curStart = pRegEnd - pReg->rects;
-      pRegEnd = pReg->rects + pReg->numRects;
-    }
-       
-  if ((curNumRects == prevNumRects) && (curNumRects != 0)) {
-    pCurBox -= curNumRects;
-    /*
-     * The bands may only be coalesced if the bottom of the previous
-     * matches the top scanline of the current.
-     */
-    if (pPrevBox->y2 == pCurBox->y1)
-      {
-       /*
-        * Make sure the bands have boxes in the same places. This
-        * assumes that boxes have been added in such a way that they
-        * cover the most area possible. I.e. two boxes in a band must
-        * have some horizontal space between them.
-        */
-       do
-         {
-           if ((pPrevBox->x1 != pCurBox->x1) ||
-               (pPrevBox->x2 != pCurBox->x2))
-             {
-               /*
-                * The bands don't line up so they can't be coalesced.
-                */
-               return (curStart);
-             }
-           pPrevBox++;
-           pCurBox++;
-           prevNumRects -= 1;
-         } while (prevNumRects != 0);
-
-       pReg->numRects -= curNumRects;
-       pCurBox -= curNumRects;
-       pPrevBox -= curNumRects;
-
-       /*
-        * The bands may be merged, so set the bottom y of each box
-        * in the previous band to that of the corresponding box in
-        * the current band.
-        */
-       do
-         {
-           pPrevBox->y2 = pCurBox->y2;
-           pPrevBox++;
-           pCurBox++;
-           curNumRects -= 1;
-         }
-       while (curNumRects != 0);
-
-       /*
-        * If only one band was added to the region, we have to backup
-        * curStart to the start of the previous band.
-        *
-        * If more than one band was added to the region, copy the
-        * other bands down. The assumption here is that the other bands
-        * came from the same region as the current one and no further
-        * coalescing can be done on them since it's all been done
-        * already... curStart is already in the right place.
-        */
-       if (pCurBox == pRegEnd)
-         {
-           curStart = prevStart;
-         }
-       else
-         {
-           do
-             {
-               *pPrevBox++ = *pCurBox++;
-             }
-           while (pCurBox != pRegEnd);
-         }
-           
-      }
-  }
-  return curStart;
-}
-
-/*-
- *-----------------------------------------------------------------------
- * miRegionOp --
- *     Apply an operation to two regions. Called by miUnion, miInverse,
- *     miSubtract, miIntersect...
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     The new region is overwritten.
- *
- * Notes:
- *     The idea behind this function is to view the two regions as sets.
- *     Together they cover a rectangle of area that this function divides
- *     into horizontal bands where points are covered only by one region
- *     or by both. For the first case, the nonOverlapFunc is called with
- *     each the band and the band's upper and lower extents. For the
- *     second, the overlapFunc is called to process the entire band. It
- *     is responsible for clipping the rectangles in the band, though
- *     this function provides the boundaries.
- *     At the end of each band, the new region is coalesced, if possible,
- *     to reduce the number of rectangles in the region.
- *
- *-----------------------------------------------------------------------
- */
-/* static void*/
-static void
-miRegionOp(GdkRegion       *newReg,
-          GdkRegion       *reg1,
-          const GdkRegion *reg2,
-          overlapFunc      overlapFn,          /* Function to call for over-
-                                                * lapping bands */
-          nonOverlapFunc   nonOverlap1Fn,      /* Function to call for non-
-                                                * overlapping bands in region
-                                                * 1 */
-          nonOverlapFunc   nonOverlap2Fn)      /* Function to call for non-
-                                                * overlapping bands in region
-                                                * 2 */
-{
-    GdkRegionBox *r1;                  /* Pointer into first region */
-    GdkRegionBox *r2;                  /* Pointer into 2d region */
-    GdkRegionBox *r1End;               /* End of 1st region */
-    GdkRegionBox *r2End;               /* End of 2d region */
-    int          ybot;                 /* Bottom of intersection */
-    int          ytop;                 /* Top of intersection */
-    GdkRegionBox *oldRects;            /* Old rects for newReg */
-    int                  prevBand;             /* Index of start of
-                                        * previous band in newReg */
-    int                  curBand;              /* Index of start of current
-                                        * band in newReg */
-    GdkRegionBox *r1BandEnd;           /* End of current band in r1 */
-    GdkRegionBox *r2BandEnd;           /* End of current band in r2 */
-    int          top;                  /* Top of non-overlapping
-                                        * band */
-    int          bot;                  /* Bottom of non-overlapping
-                                        * band */
-    
-    /*
-     * Initialization:
-     * set r1, r2, r1End and r2End appropriately, preserve the important
-     * parts of the destination region until the end in case it's one of
-     * the two source regions, then mark the "new" region empty, allocating
-     * another array of rectangles for it to use.
-     */
-    r1 = reg1->rects;
-    r2 = reg2->rects;
-    r1End = r1 + reg1->numRects;
-    r2End = r2 + reg2->numRects;
-    
-    oldRects = newReg->rects;
-    
-    EMPTY_REGION(newReg);
-
-    /*
-     * Allocate a reasonable number of rectangles for the new region. The idea
-     * is to allocate enough so the individual functions don't need to
-     * reallocate and copy the array, which is time consuming, yet we don't
-     * have to worry about using too much memory. I hope to be able to
-     * nuke the Xrealloc() at the end of this function eventually.
-     */
-    newReg->size = MAX (reg1->numRects, reg2->numRects) * 2;
-    newReg->rects = g_new (GdkRegionBox, newReg->size);
-    
-    /*
-     * Initialize ybot and ytop.
-     * In the upcoming loop, ybot and ytop serve different functions depending
-     * on whether the band being handled is an overlapping or non-overlapping
-     * band.
-     *         In the case of a non-overlapping band (only one of the regions
-     * has points in the band), ybot is the bottom of the most recent
-     * intersection and thus clips the top of the rectangles in that band.
-     * ytop is the top of the next intersection between the two regions and
-     * serves to clip the bottom of the rectangles in the current band.
-     * For an overlapping band (where the two regions intersect), ytop clips
-     * the top of the rectangles of both regions and ybot clips the bottoms.
-     */
-    if (reg1->extents.y1 < reg2->extents.y1)
-      ybot = reg1->extents.y1;
-    else
-      ybot = reg2->extents.y1;
-    
-    /*
-     * prevBand serves to mark the start of the previous band so rectangles
-     * can be coalesced into larger rectangles. qv. miCoalesce, above.
-     * In the beginning, there is no previous band, so prevBand == curBand
-     * (curBand is set later on, of course, but the first band will always
-     * start at index 0). prevBand and curBand must be indices because of
-     * the possible expansion, and resultant moving, of the new region's
-     * array of rectangles.
-     */
-    prevBand = 0;
-    
-    do
-      {
-       curBand = newReg->numRects;
-
-       /*
-        * This algorithm proceeds one source-band (as opposed to a
-        * destination band, which is determined by where the two regions
-        * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
-        * rectangle after the last one in the current band for their
-        * respective regions.
-        */
-       r1BandEnd = r1;
-       while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1))
-         {
-           r1BandEnd++;
-         }
-       
-       r2BandEnd = r2;
-       while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1))
-         {
-           r2BandEnd++;
-         }
-       
-       /*
-        * First handle the band that doesn't intersect, if any.
-        *
-        * Note that attention is restricted to one band in the
-        * non-intersecting region at once, so if a region has n
-        * bands between the current position and the next place it overlaps
-        * the other, this entire loop will be passed through n times.
-        */
-       if (r1->y1 < r2->y1)
-         {
-           top = MAX (r1->y1,ybot);
-           bot = MIN (r1->y2,r2->y1);
-
-           if ((top != bot) && (nonOverlap1Fn != (void (*)())NULL))
-             {
-               (* nonOverlap1Fn) (newReg, r1, r1BandEnd, top, bot);
-             }
-
-           ytop = r2->y1;
-         }
-       else if (r2->y1 < r1->y1)
-         {
-           top = MAX (r2->y1,ybot);
-           bot = MIN (r2->y2,r1->y1);
-
-           if ((top != bot) && (nonOverlap2Fn != (void (*)())NULL))
-             {
-               (* nonOverlap2Fn) (newReg, r2, r2BandEnd, top, bot);
-             }
-
-           ytop = r1->y1;
-         }
-       else
-         {
-           ytop = r1->y1;
-         }
-
-       /*
-        * If any rectangles got added to the region, try and coalesce them
-        * with rectangles from the previous band. Note we could just do
-        * this test in miCoalesce, but some machines incur a not
-        * inconsiderable cost for function calls, so...
-        */
-       if (newReg->numRects != curBand)
-         {
-           prevBand = miCoalesce (newReg, prevBand, curBand);
-         }
-
-       /*
-        * Now see if we've hit an intersecting band. The two bands only
-        * intersect if ybot > ytop
-        */
-       ybot = MIN (r1->y2, r2->y2);
-       curBand = newReg->numRects;
-       if (ybot > ytop)
-         {
-           (* overlapFn) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
-
-         }
-       
-       if (newReg->numRects != curBand)
-         {
-           prevBand = miCoalesce (newReg, prevBand, curBand);
-         }
-
-       /*
-        * If we've finished with a band (y2 == ybot) we skip forward
-        * in the region to the next band.
-        */
-       if (r1->y2 == ybot)
-         {
-           r1 = r1BandEnd;
-         }
-       if (r2->y2 == ybot)
-         {
-           r2 = r2BandEnd;
-         }
-      } while ((r1 != r1End) && (r2 != r2End));
-
-    /*
-     * Deal with whichever region still has rectangles left.
-     */
-    curBand = newReg->numRects;
-    if (r1 != r1End)
-      {
-       if (nonOverlap1Fn != (nonOverlapFunc )NULL)
-         {
-           do
-             {
-               r1BandEnd = r1;
-               while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1))
-                 {
-                   r1BandEnd++;
-                 }
-               (* nonOverlap1Fn) (newReg, r1, r1BandEnd,
-                                    MAX (r1->y1,ybot), r1->y2);
-               r1 = r1BandEnd;
-             } while (r1 != r1End);
-         }
-      }
-    else if ((r2 != r2End) && (nonOverlap2Fn != (nonOverlapFunc) NULL))
-      {
-       do
-         {
-           r2BandEnd = r2;
-           while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1))
-             {
-               r2BandEnd++;
-             }
-           (* nonOverlap2Fn) (newReg, r2, r2BandEnd,
-                              MAX (r2->y1,ybot), r2->y2);
-           r2 = r2BandEnd;
-         } while (r2 != r2End);
-      }
-
-    if (newReg->numRects != curBand)
-    {
-      (void) miCoalesce (newReg, prevBand, curBand);
-    }
-
-    /*
-     * A bit of cleanup. To keep regions from growing without bound,
-     * we shrink the array of rectangles to match the new number of
-     * rectangles in the region. This never goes to 0, however...
-     *
-     * Only do this stuff if the number of rectangles allocated is more than
-     * twice the number of rectangles in the region (a simple optimization...).
-     */
-    if (newReg->numRects < (newReg->size >> 1))
-      {
-       if (REGION_NOT_EMPTY (newReg))
-         {
-           newReg->size = newReg->numRects;
-           newReg->rects = g_renew (GdkRegionBox, newReg->rects, newReg->size);
-         }
-       else
-         {
-           /*
-            * No point in doing the extra work involved in an Xrealloc if
-            * the region is empty
-            */
-           newReg->size = 1;
-           g_free (newReg->rects);
-           newReg->rects = &newReg->extents;
-         }
-      }
-
-    if (oldRects != &newReg->extents)
-      g_free (oldRects);
-}
-
-\f
-/*======================================================================
- *         Region Union
- *====================================================================*/
-
-/*-
- *-----------------------------------------------------------------------
- * miUnionNonO --
- *     Handle a non-overlapping band for the union operation. Just
- *     Adds the rectangles into the region. Doesn't have to check for
- *     subsumption or anything.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     pReg->numRects is incremented and the final rectangles overwritten
- *     with the rectangles we're passed.
- *
- *-----------------------------------------------------------------------
- */
-static void
-miUnionNonO (GdkRegion    *pReg,
-            GdkRegionBox *r,
-            GdkRegionBox *rEnd,
-            gint          y1,
-            gint          y2)
-{
-  GdkRegionBox *pNextRect;
-
-  pNextRect = &pReg->rects[pReg->numRects];
-
-  g_assert(y1 < y2);
-
-  while (r != rEnd)
-    {
-      g_assert(r->x1 < r->x2);
-      MEMCHECK(pReg, pNextRect, pReg->rects);
-      pNextRect->x1 = r->x1;
-      pNextRect->y1 = y1;
-      pNextRect->x2 = r->x2;
-      pNextRect->y2 = y2;
-      pReg->numRects += 1;
-      pNextRect++;
-
-      g_assert(pReg->numRects<=pReg->size);
-      r++;
-    }
-}
-
-
-/*-
- *-----------------------------------------------------------------------
- * miUnionO --
- *     Handle an overlapping band for the union operation. Picks the
- *     left-most rectangle each time and merges it into the region.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     Rectangles are overwritten in pReg->rects and pReg->numRects will
- *     be changed.
- *
- *-----------------------------------------------------------------------
- */
-
-/* static void*/
-static void
-miUnionO (GdkRegion *pReg,
-         GdkRegionBox *r1,
-         GdkRegionBox *r1End,
-         GdkRegionBox *r2,
-         GdkRegionBox *r2End,
-         gint          y1,
-         gint          y2)
-{
-  GdkRegionBox *       pNextRect;
-    
-  pNextRect = &pReg->rects[pReg->numRects];
-
-#define MERGERECT(r)                                   \
-    if ((pReg->numRects != 0) &&                       \
-       (pNextRect[-1].y1 == y1) &&                     \
-       (pNextRect[-1].y2 == y2) &&                     \
-       (pNextRect[-1].x2 >= r->x1))                    \
-      {                                                \
-       if (pNextRect[-1].x2 < r->x2)                   \
-         {                                             \
-           pNextRect[-1].x2 = r->x2;                   \
-           g_assert(pNextRect[-1].x1<pNextRect[-1].x2);        \
-         }                                             \
-      }                                                \
-    else                                               \
-      {                                                \
-       MEMCHECK(pReg, pNextRect, pReg->rects);         \
-       pNextRect->y1 = y1;                             \
-       pNextRect->y2 = y2;                             \
-       pNextRect->x1 = r->x1;                          \
-       pNextRect->x2 = r->x2;                          \
-       pReg->numRects += 1;                            \
-        pNextRect += 1;                                \
-      }                                                \
-    g_assert(pReg->numRects<=pReg->size);                      \
-    r++;
-    
-    g_assert (y1<y2);
-    while ((r1 != r1End) && (r2 != r2End))
-    {
-       if (r1->x1 < r2->x1)
-       {
-           MERGERECT(r1);
-       }
-       else
-       {
-           MERGERECT(r2);
-       }
-    }
-    
-    if (r1 != r1End)
-    {
-       do
-       {
-           MERGERECT(r1);
-       } while (r1 != r1End);
-    }
-    else while (r2 != r2End)
-    {
-       MERGERECT(r2);
-    }
+  cairo_region_intersect (source1, (cairo_region_t *) source2);
 }
 
 /**
@@ -1221,250 +233,7 @@ gdk_region_union (GdkRegion       *source1,
   g_return_if_fail (source1 != NULL);
   g_return_if_fail (source2 != NULL);
   
-  /*  checks all the simple cases */
-
-  /*
-   * source1 and source2 are the same or source2 is empty
-   */
-  if ((source1 == source2) || (!(source2->numRects)))
-    return;
-
-  /* 
-   * source1 is empty
-   */
-  if (!(source1->numRects))
-    {
-      miRegionCopy (source1, source2);
-      return;
-    }
-  
-  /*
-   * source1 completely subsumes source2
-   */
-  if ((source1->numRects == 1) && 
-      (source1->extents.x1 <= source2->extents.x1) &&
-      (source1->extents.y1 <= source2->extents.y1) &&
-      (source1->extents.x2 >= source2->extents.x2) &&
-      (source1->extents.y2 >= source2->extents.y2))
-    return;
-
-  /*
-   * source2 completely subsumes source1
-   */
-  if ((source2->numRects == 1) && 
-      (source2->extents.x1 <= source1->extents.x1) &&
-      (source2->extents.y1 <= source1->extents.y1) &&
-      (source2->extents.x2 >= source1->extents.x2) &&
-      (source2->extents.y2 >= source1->extents.y2))
-    {
-      miRegionCopy(source1, source2);
-      return;
-    }
-
-  miRegionOp (source1, source1, source2, miUnionO, 
-             miUnionNonO, miUnionNonO);
-
-  source1->extents.x1 = MIN (source1->extents.x1, source2->extents.x1);
-  source1->extents.y1 = MIN (source1->extents.y1, source2->extents.y1);
-  source1->extents.x2 = MAX (source1->extents.x2, source2->extents.x2);
-  source1->extents.y2 = MAX (source1->extents.y2, source2->extents.y2);
-}
-
-\f
-/*======================================================================
- *               Region Subtraction
- *====================================================================*/
-
-/*-
- *-----------------------------------------------------------------------
- * miSubtractNonO --
- *     Deal with non-overlapping band for subtraction. Any parts from
- *     region 2 we discard. Anything from region 1 we add to the region.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     pReg may be affected.
- *
- *-----------------------------------------------------------------------
- */
-/* static void*/
-static void
-miSubtractNonO1 (GdkRegion    *pReg,
-                GdkRegionBox *r,
-                GdkRegionBox *rEnd,
-                gint          y1,
-                gint          y2)
-{
-  GdkRegionBox *       pNextRect;
-       
-  pNextRect = &pReg->rects[pReg->numRects];
-       
-  g_assert(y1<y2);
-
-  while (r != rEnd)
-    {
-      g_assert (r->x1<r->x2);
-      MEMCHECK (pReg, pNextRect, pReg->rects);
-      pNextRect->x1 = r->x1;
-      pNextRect->y1 = y1;
-      pNextRect->x2 = r->x2;
-      pNextRect->y2 = y2;
-      pReg->numRects += 1;
-      pNextRect++;
-
-      g_assert (pReg->numRects <= pReg->size);
-
-      r++;
-    }
-}
-
-/*-
- *-----------------------------------------------------------------------
- * miSubtractO --
- *     Overlapping band subtraction. x1 is the left-most point not yet
- *     checked.
- *
- * Results:
- *     None.
- *
- * Side Effects:
- *     pReg may have rectangles added to it.
- *
- *-----------------------------------------------------------------------
- */
-/* static void*/
-static void
-miSubtractO (GdkRegion    *pReg,
-            GdkRegionBox *r1,
-            GdkRegionBox *r1End,
-            GdkRegionBox *r2,
-            GdkRegionBox *r2End,
-            gint          y1,
-            gint          y2)
-{
-  GdkRegionBox *       pNextRect;
-  int          x1;
-    
-  x1 = r1->x1;
-    
-  g_assert(y1<y2);
-  pNextRect = &pReg->rects[pReg->numRects];
-
-  while ((r1 != r1End) && (r2 != r2End))
-    {
-      if (r2->x2 <= x1)
-       {
-         /*
-          * Subtrahend missed the boat: go to next subtrahend.
-          */
-         r2++;
-       }
-      else if (r2->x1 <= x1)
-       {
-         /*
-          * Subtrahend preceeds minuend: nuke left edge of minuend.
-          */
-         x1 = r2->x2;
-         if (x1 >= r1->x2)
-           {
-             /*
-              * Minuend completely covered: advance to next minuend and
-              * reset left fence to edge of new minuend.
-              */
-             r1++;
-             if (r1 != r1End)
-               x1 = r1->x1;
-           }
-         else
-           {
-             /*
-              * Subtrahend now used up since it doesn't extend beyond
-              * minuend
-              */
-             r2++;
-           }
-       }
-      else if (r2->x1 < r1->x2)
-       {
-         /*
-          * Left part of subtrahend covers part of minuend: add uncovered
-          * part of minuend to region and skip to next subtrahend.
-          */
-         g_assert(x1<r2->x1);
-         MEMCHECK(pReg, pNextRect, pReg->rects);
-         pNextRect->x1 = x1;
-         pNextRect->y1 = y1;
-         pNextRect->x2 = r2->x1;
-         pNextRect->y2 = y2;
-         pReg->numRects += 1;
-         pNextRect++;
-
-         g_assert(pReg->numRects<=pReg->size);
-
-         x1 = r2->x2;
-         if (x1 >= r1->x2)
-           {
-             /*
-              * Minuend used up: advance to new...
-              */
-             r1++;
-             if (r1 != r1End)
-               x1 = r1->x1;
-           }
-         else
-           {
-             /*
-              * Subtrahend used up
-              */
-             r2++;
-           }
-       }
-      else
-       {
-         /*
-          * Minuend used up: add any remaining piece before advancing.
-          */
-         if (r1->x2 > x1)
-           {
-             MEMCHECK(pReg, pNextRect, pReg->rects);
-             pNextRect->x1 = x1;
-             pNextRect->y1 = y1;
-             pNextRect->x2 = r1->x2;
-             pNextRect->y2 = y2;
-             pReg->numRects += 1;
-             pNextRect++;
-             g_assert(pReg->numRects<=pReg->size);
-           }
-         r1++;
-         if (r1 != r1End)
-           x1 = r1->x1;
-       }
-    }
-
-  /*
-     * Add remaining minuend rectangles to region.
-     */
-  while (r1 != r1End)
-    {
-      g_assert(x1<r1->x2);
-      MEMCHECK(pReg, pNextRect, pReg->rects);
-      pNextRect->x1 = x1;
-      pNextRect->y1 = y1;
-      pNextRect->x2 = r1->x2;
-      pNextRect->y2 = y2;
-      pReg->numRects += 1;
-      pNextRect++;
-
-      g_assert(pReg->numRects<=pReg->size);
-
-      r1++;
-      if (r1 != r1End)
-       {
-         x1 = r1->x1;
-       }
-    }
+  cairo_region_union (source1, (cairo_region_t *) source2);
 }
 
 /**
@@ -1482,21 +251,7 @@ gdk_region_subtract (GdkRegion       *source1,
   g_return_if_fail (source1 != NULL);
   g_return_if_fail (source2 != NULL);
   
-  /* check for trivial reject */
-  if ((!(source1->numRects)) || (!(source2->numRects)) ||
-      (!EXTENTCHECK(&source1->extents, &source2->extents)))
-    return;
-  miRegionOp (source1, source1, source2, miSubtractO,
-             miSubtractNonO1, (nonOverlapFunc) NULL);
-
-  /*
-   * Can't alter source1's extents before we call miRegionOp because miRegionOp
-   * depends on the extents of those regions being the unaltered. Besides, this
-   * way there's no checking against rectangles that will be nuked
-   * due to coalescing, so we have to examine fewer rectangles.
-   */
-  miSetExtents (source1);
+  cairo_region_subtract (source1, source2);
 }
 
 /**
@@ -1540,10 +295,7 @@ gdk_region_empty (const GdkRegion *region)
 {
   g_return_val_if_fail (region != NULL, FALSE);
   
-  if (region->numRects == 0)
-    return TRUE;
-  else
-    return FALSE;
+  return cairo_region_is_empty (region);
 }
 
 /**
@@ -1559,26 +311,10 @@ gboolean
 gdk_region_equal (const GdkRegion *region1,
                  const GdkRegion *region2)
 {
-  int i;
-
   g_return_val_if_fail (region1 != NULL, FALSE);
   g_return_val_if_fail (region2 != NULL, FALSE);
 
-  if (region1->numRects != region2->numRects) return FALSE;
-  else if (region1->numRects == 0) return TRUE;
-  else if (region1->extents.x1 != region2->extents.x1) return FALSE;
-  else if (region1->extents.x2 != region2->extents.x2) return FALSE;
-  else if (region1->extents.y1 != region2->extents.y1) return FALSE;
-  else if (region1->extents.y2 != region2->extents.y2) return FALSE;
-  else
-    for(i = 0; i < region1->numRects; i++ )
-      {
-       if (region1->rects[i].x1 != region2->rects[i].x1) return FALSE;
-       else if (region1->rects[i].x2 != region2->rects[i].x2) return FALSE;
-       else if (region1->rects[i].y1 != region2->rects[i].y1) return FALSE;
-       else if (region1->rects[i].y2 != region2->rects[i].y2) return FALSE;
-      }
-  return TRUE;
+  return cairo_region_equal (region1, region2);
 }
 
 /**
@@ -1596,14 +332,17 @@ gboolean
 gdk_region_rect_equal (const GdkRegion    *region,
                       const GdkRectangle *rectangle)
 {
+  cairo_rectangle_int_t extents;
+
   g_return_val_if_fail (region != NULL, FALSE);
   g_return_val_if_fail (rectangle != NULL, FALSE);
 
-  if (region->numRects != 1) return FALSE;
-  else if (region->extents.x1 != rectangle->x) return FALSE;
-  else if (region->extents.y1 != rectangle->y) return FALSE;
-  else if (region->extents.x2 != rectangle->x + rectangle->width) return FALSE;
-  else if (region->extents.y2 != rectangle->y + rectangle->height) return FALSE;
+  if (cairo_region_num_rectangles (region) != 1) return FALSE;
+  cairo_region_get_extents (region, &extents);
+  if (extents.x != rectangle->x) return FALSE;
+  else if (extents.y != rectangle->y) return FALSE;
+  else if (extents.width != rectangle->width) return FALSE;
+  else if (extents.height != rectangle->height) return FALSE;
   return TRUE;
 }
 
@@ -1622,20 +361,9 @@ gdk_region_point_in (const GdkRegion *region,
                     int              x,
                     int              y)
 {
-  int i;
-
   g_return_val_if_fail (region != NULL, FALSE);
 
-  if (region->numRects == 0)
-    return FALSE;
-  if (!INBOX(region->extents, x, y))
-    return FALSE;
-  for (i = 0; i < region->numRects; i++)
-    {
-      if (INBOX (region->rects[i], x, y))
-       return TRUE;
-    }
-  return FALSE;
+  return cairo_region_contains_point (region, x, y);
 }
 
 /**
@@ -1653,90 +381,10 @@ GdkOverlapType
 gdk_region_rect_in (const GdkRegion    *region,
                    const GdkRectangle *rectangle)
 {
-  GdkRegionBox *pbox;
-  GdkRegionBox *pboxEnd;
-  GdkRegionBox  rect;
-  GdkRegionBox *prect = &rect;
-  gboolean      partIn, partOut;
-  gint rx, ry;
-
   g_return_val_if_fail (region != NULL, GDK_OVERLAP_RECTANGLE_OUT);
   g_return_val_if_fail (rectangle != NULL, GDK_OVERLAP_RECTANGLE_OUT);
 
-  rx = rectangle->x;
-  ry = rectangle->y;
-  
-  prect->x1 = rx;
-  prect->y1 = ry;
-  prect->x2 = rx + rectangle->width;
-  prect->y2 = ry + rectangle->height;
-    
-    /* this is (just) a useful optimization */
-  if ((region->numRects == 0) || !EXTENTCHECK (&region->extents, prect))
-    return GDK_OVERLAP_RECTANGLE_OUT;
-
-  partOut = FALSE;
-  partIn = FALSE;
-
-    /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */
-  for (pbox = region->rects, pboxEnd = pbox + region->numRects;
-       pbox < pboxEnd;
-       pbox++)
-    {
-
-      if (pbox->y2 <= ry)
-       continue;       /* getting up to speed or skipping remainder of band */
-
-      if (pbox->y1 > ry)
-       {
-         partOut = TRUE;       /* missed part of rectangle above */
-         if (partIn || (pbox->y1 >= prect->y2))
-           break;
-         ry = pbox->y1;        /* x guaranteed to be == prect->x1 */
-       }
-
-      if (pbox->x2 <= rx)
-       continue;               /* not far enough over yet */
-
-      if (pbox->x1 > rx)
-       {
-         partOut = TRUE;       /* missed part of rectangle to left */
-         if (partIn)
-           break;
-       }
-
-      if (pbox->x1 < prect->x2)
-       {
-         partIn = TRUE;        /* definitely overlap */
-         if (partOut)
-           break;
-       }
-
-      if (pbox->x2 >= prect->x2)
-       {
-         ry = pbox->y2;        /* finished with this band */
-         if (ry >= prect->y2)
-           break;
-         rx = prect->x1;       /* reset x out to left again */
-       }
-      else
-       {
-         /*
-          * Because boxes in a band are maximal width, if the first box
-          * to overlap the rectangle doesn't completely cover it in that
-          * band, the rectangle must be partially out, since some of it
-          * will be uncovered in that band. partIn will have been set true
-          * by now...
-          */
-         break;
-       }
-
-    }
-
-  return (partIn ?
-            ((ry < prect->y2) ?
-             GDK_OVERLAP_RECTANGLE_PART : GDK_OVERLAP_RECTANGLE_IN) : 
-         GDK_OVERLAP_RECTANGLE_OUT);
+  return cairo_region_contains_rectangle (region, rectangle);
 }
 
 
@@ -1747,43 +395,44 @@ gdk_region_unsorted_spans_intersect_foreach (GdkRegion     *region,
                                             GdkSpanFunc    function,
                                             gpointer       data)
 {
-  gint i, left, right, y;
+  gint i, j, left, right, y, n_rects;
   gint clipped_left, clipped_right;
-  GdkRegionBox *pbox;
-  GdkRegionBox *pboxEnd;
+  cairo_rectangle_int_t pbox, extents;
 
-  if (!region->numRects)
+  n_rects = cairo_region_num_rectangles (region);
+  if (!n_rects)
     return;
 
+  cairo_region_get_extents (region, &extents);
   for (i=0;i<n_spans;i++)
     {
       y = spans[i].y;
       left = spans[i].x;
       right = left + spans[i].width; /* right is not in the span! */
     
-      if (! ((region->extents.y1 <= y) &&
-            (region->extents.y2 > y) &&
-            (region->extents.x1 < right) &&
-            (region->extents.x2 > left)) ) 
+      if (! ((extents.y <= y) &&
+            (extents.y + extents.height > y) &&
+            (extents.x < right) &&
+            (extents.x + extents.width > left)) ) 
        continue;
 
       /* can stop when we passed y */
-      for (pbox = region->rects, pboxEnd = pbox + region->numRects;
-          pbox < pboxEnd;
-          pbox++)
+      for (j = 0; j < n_rects; j++)
        {
-         if (pbox->y2 <= y)
+          cairo_region_get_rectangle (region, j, &pbox);
+
+         if (pbox.y + pbox.height <= y)
            continue; /* Not quite there yet */
          
-         if (pbox->y1 > y)
+         if (pbox.y > y)
            break; /* passed the spanline */
          
-         if ((right > pbox->x1) && (left < pbox->x2)) 
+         if ((right > pbox.x) && (left < pbox.x + pbox.width)) 
            {
               GdkSpan out_span;
 
-             clipped_left = MAX (left, pbox->x1);
-             clipped_right = MIN (right, pbox->x2);
+             clipped_left = MAX (left, pbox.x);
+             clipped_right = MIN (right, pbox.x + pbox.width);
              
              out_span.y = y;
              out_span.x = clipped_left;
@@ -1813,10 +462,9 @@ gdk_region_spans_intersect_foreach (GdkRegion     *region,
                                    GdkSpanFunc    function,
                                    gpointer       data)
 {
-  gint left, right, y;
+  gint i, left, right, y, n_rects;
   gint clipped_left, clipped_right;
-  GdkRegionBox *pbox;
-  GdkRegionBox *pboxEnd;
+  GdkRectangle pbox;
   const GdkSpan *span, *tmpspan;
   const GdkSpan *end_span;
 
@@ -1833,7 +481,8 @@ gdk_region_spans_intersect_foreach (GdkRegion     *region,
       return;
     }
   
-  if ((!region->numRects) || (n_spans == 0))
+  n_rects = cairo_region_num_rectangles (region);
+  if (n_rects == 0 || n_spans == 0)
     return;
 
   /* The main method here is to step along the
@@ -1844,21 +493,22 @@ gdk_region_spans_intersect_foreach (GdkRegion     *region,
 
   span = spans;
   end_span = spans + n_spans;
-  pbox = region->rects;
-  pboxEnd = pbox + region->numRects;
-  while (pbox < pboxEnd)
+  for (i = 0; i < n_rects; i++)
     {
-      while ((pbox->y2 < span->y) || (span->y < pbox->y1))
+      cairo_region_get_rectangle (region, i, &pbox);
+
+      while ((pbox.y + pbox.height < span->y) || (span->y < pbox.y))
        {
          /* Skip any rectangles that are above the current span */
-         if (pbox->y2 < span->y)
+         if (pbox.y + pbox.height < span->y)
            {
-             pbox++;
-             if (pbox == pboxEnd)
+             i++;
+             if (i == n_rects)
                return;
+              cairo_region_get_rectangle (region, i, &pbox);
            }
          /* Skip any spans that are above the current rectangle */
-         if (span->y < pbox->y1)
+         if (span->y < pbox.y)
            {
              span++;
              if (span == end_span)
@@ -1869,18 +519,18 @@ gdk_region_spans_intersect_foreach (GdkRegion     *region,
       /* Ok, we got at least one span that might intersect this rectangle. */
       tmpspan = span;
       while ((tmpspan < end_span) &&
-            (tmpspan->y < pbox->y2))
+            (tmpspan->y < pbox.y + pbox.height))
        {
          y = tmpspan->y;
          left = tmpspan->x;
          right = left + tmpspan->width; /* right is not in the span! */
          
-         if ((right > pbox->x1) && (left < pbox->x2))
+         if ((right > pbox.x) && (left < pbox.x + pbox.width))
            {
               GdkSpan out_span;
 
-             clipped_left = MAX (left, pbox->x1);
-             clipped_right = MIN (right, pbox->x2);
+             clipped_left = MAX (left, pbox.x);
+             clipped_right = MIN (right, pbox.x + pbox.width);
              
              out_span.y = y;
              out_span.x = clipped_left;
@@ -1890,11 +540,6 @@ gdk_region_spans_intersect_foreach (GdkRegion     *region,
          
          tmpspan++;
        }
-
-      /* Finished this rectangle.
-       * The spans could still intersect the next one
-       */
-      pbox++;
     }
 }
 
index d33e6e74acd3a93310a071fb08c67968bd9d0fb3..a35dca28d8793610fafe0d3cfb062d55ce964dd9 100644 (file)
@@ -36,6 +36,7 @@
 #include <glib.h>
 #include <pango/pango.h>
 #include <glib-object.h>
+#include <cairo.h>
 
 #ifdef G_OS_WIN32
 #  ifdef GDK_COMPILATION
@@ -73,7 +74,7 @@ G_BEGIN_DECLS
 /* Type definitions for the basic structures.
  */
 typedef struct _GdkPoint             GdkPoint;
-typedef struct _GdkRectangle         GdkRectangle;
+typedef cairo_rectangle_int_t        GdkRectangle;
 typedef struct _GdkSegment           GdkSegment;
 typedef struct _GdkSpan                      GdkSpan;
 
@@ -104,7 +105,7 @@ typedef struct _GdkColormap       GdkColormap;
 typedef struct _GdkCursor            GdkCursor;
 typedef struct _GdkGC                 GdkGC;
 typedef struct _GdkImage              GdkImage;
-typedef struct _GdkRegion             GdkRegion;
+typedef cairo_region_t                GdkRegion;
 typedef struct _GdkVisual             GdkVisual;
 
 typedef struct _GdkDrawable           GdkDrawable;
index 42073d38ede1aa1d2d78fc80ab8d359eab3cf965..c85ac413be25ed966dc7c8f49ead119899cb4050 100644 (file)
@@ -27,7 +27,6 @@
 #include "config.h"
 
 #include "gdkx.h"
-#include "gdkregion-generic.h"
 
 #include <cairo-xlib.h>
 
@@ -351,22 +350,16 @@ gdk_x11_drawable_update_picture_clip (GdkDrawable *drawable,
 
   if (clip_region)
     {
-      GdkRegionBox *boxes = clip_region->rects;
-      gint n_boxes = clip_region->numRects;
-      XRectangle *rects = g_new (XRectangle, n_boxes);
-      int i;
-
-      for (i=0; i < n_boxes; i++)
-       {
-         rects[i].x = CLAMP (boxes[i].x1 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT);
-         rects[i].y = CLAMP (boxes[i].y1 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT);
-         rects[i].width = CLAMP (boxes[i].x2 + gc->clip_x_origin, G_MINSHORT, G_MAXSHORT) - rects[i].x;
-         rects[i].height = CLAMP (boxes[i].y2 + gc->clip_y_origin, G_MINSHORT, G_MAXSHORT) - rects[i].y;
-       }
-      
+      XRectangle *rects;
+      int n_rects;
+
+      _gdk_region_get_xrectangles (clip_region, 
+                                   gc->clip_x_origin,
+                                   gc->clip_y_origin,
+                                   &rects,
+                                   &n_rects);
       XRenderSetPictureClipRectangles (xdisplay, picture,
-                                      0, 0, rects, n_boxes);
-      
+                                      0, 0, rects, n_rects);
       g_free (rects);
     }
   else
index 3cac64fd4f51a40203e2094039487367d7b2b1ce..b0d25782db9417ebb9fbda2999f728b2f68b3a12 100644 (file)
@@ -28,7 +28,6 @@
 
 #include "gdkgc.h"
 #include "gdkprivate-x11.h"
-#include "gdkregion-generic.h"
 #include "gdkx.h"
 #include "gdkalias.h"
 
index d876fd4db750d49bd386025551fdb7dca7d31c37..9c71105beb35126805a815a7aebf5b1df78cc1b0 100644 (file)
@@ -49,7 +49,6 @@
 #include "gdkinternals.h"
 #include "gdkprivate-x11.h"
 #include "gdkintl.h"
-#include "gdkregion-generic.h"
 #include "gdkalias.h"
 
 #include <gdk/gdkdeviceprivate.h>
@@ -524,20 +523,24 @@ _gdk_region_get_xrectangles (const GdkRegion *region,
                              XRectangle     **rects,
                              gint            *n_rects)
 {
-  XRectangle *rectangles = g_new (XRectangle, region->numRects);
-  GdkRegionBox *boxes = region->rects;
-  gint i;
+  XRectangle *rectangles;
+  cairo_rectangle_int_t box;
+  gint i, n;
   
-  for (i = 0; i < region->numRects; i++)
+  n = cairo_region_num_rectangles (region);
+  rectangles = g_new (XRectangle, n);
+
+  for (i = 0; i < n; i++)
     {
-      rectangles[i].x = CLAMP (boxes[i].x1 + x_offset, G_MINSHORT, G_MAXSHORT);
-      rectangles[i].y = CLAMP (boxes[i].y1 + y_offset, G_MINSHORT, G_MAXSHORT);
-      rectangles[i].width = CLAMP (boxes[i].x2 + x_offset, G_MINSHORT, G_MAXSHORT) - rectangles[i].x;
-      rectangles[i].height = CLAMP (boxes[i].y2 + y_offset, G_MINSHORT, G_MAXSHORT) - rectangles[i].y;
+      cairo_region_get_rectangle (region, i, &box);
+      rectangles[i].x = CLAMP (box.x + x_offset, G_MINSHORT, G_MAXSHORT);
+      rectangles[i].y = CLAMP (box.y + y_offset, G_MINSHORT, G_MAXSHORT);
+      rectangles[i].width = CLAMP (box.width, G_MINSHORT, G_MAXSHORT);
+      rectangles[i].height = CLAMP (box.height, G_MINSHORT, G_MAXSHORT);
     }
 
+  *n_rects = n;
   *rects = rectangles;
-  *n_rects = region->numRects;
 }
 
 /**