* 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"
-
-#ifdef DEBUG
-#include <stdio.h>
-#define assert(expr) {if (!(expr)) fprintf(stderr,\
-"Assertion failed file %s, line %d: expr\n", __FILE__, __LINE__); }
-#else
-#define assert(expr)
-#endif
-
-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,
- GdkRegion *rgn);
-static void miRegionOp (GdkRegion *newReg,
- GdkRegion *reg1,
- GdkRegion *reg2,
- overlapFunc overlapFn,
- nonOverlapFunc nonOverlap1Fn,
- nonOverlapFunc nonOverlap2Fn);
-
-/* Create a new empty region */
-
+#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:
+ *
+ * Creates a new empty #GdkRegion.
+ *
+ * Returns: a new empty #GdkRegion
+ */
GdkRegion *
-gdk_region_new ()
+gdk_region_new (void)
{
GdkRegion *temp;
- temp = g_new (GdkRegion, 1);
- temp->rects = g_new (GdkRegionBox, 1);
+ temp = g_slice_new (GdkRegion);
temp->numRects = 0;
+ temp->rects = &temp->extents;
temp->extents.x1 = 0;
temp->extents.y1 = 0;
temp->extents.x2 = 0;
}
GdkRegion *
-gdk_region_rectangle (GdkRectangle *rectangle)
+_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;
+}
+
+
+/**
+ * gdk_region_rectangle:
+ * @rectangle: a #GdkRectangle
+ *
+ * Creates a new region containing the area @rectangle.
+ *
+ * Return value: a new region
+ **/
+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_new (GdkRegion, 1);
- temp->rects = g_new (GdkRegionBox, 1);
+ temp = g_slice_new (GdkRegion);
temp->numRects = 1;
- temp->extents.x1 = temp->rects[0].x1 = rectangle->x;
- temp->extents.y1 = temp->rects[0].y1 = rectangle->y;
- temp->extents.x2 = temp->rects[0].x2 = rectangle->x + rectangle->width;
- temp->extents.y2 = temp->rects[0].y2 = rectangle->y + rectangle->height;
+ 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;
}
+/**
+ * gdk_region_copy:
+ * @region: a #GdkRegion
+ *
+ * Copies @region, creating an identical new region.
+ *
+ * Return value: a new region identical to @region
+ **/
GdkRegion *
-gdk_region_copy (GdkRegion *region)
+gdk_region_copy (const GdkRegion *region)
{
GdkRegion *temp;
- temp = g_new (GdkRegion, 1);
- temp->rects = g_new (GdkRegionBox, region->numRects);
+ g_return_val_if_fail (region != NULL, NULL);
- temp->numRects = region->numRects;
- temp->extents = region->extents;
- temp->size = region->numRects;
-
- memcpy (temp->rects, region->rects, region->numRects * sizeof (GdkRegionBox));
+ temp = gdk_region_new ();
+
+ miRegionCopy (temp, region);
return temp;
}
+/**
+ * gdk_region_get_clipbox:
+ * @region: a #GdkRegion
+ * @rectangle: return location for the clipbox
+ *
+ * Obtains the smallest rectangle which includes the entire #GdkRegion.
+ *
+ */
+void
+gdk_region_get_clipbox (const GdkRegion *region,
+ GdkRectangle *rectangle)
+{
+ 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;
+}
+
+
+/**
+ * gdk_region_get_rectangles:
+ * @region: a #GdkRegion
+ * @rectangles: return location for an array of rectangles
+ * @n_rectangles: length of returned array
+ *
+ * Obtains the area covered by the region as a list of rectangles.
+ * The array returned in @rectangles must be freed with g_free().
+ **/
void
-gdk_region_get_clipbox (GdkRegion *r, GdkRectangle *rect)
+gdk_region_get_rectangles (const GdkRegion *region,
+ GdkRectangle **rectangles,
+ gint *n_rectangles)
{
- rect->x = r->extents.x1;
- rect->y = r->extents.y1;
- rect->width = r->extents.x2 - r->extents.x1;
- rect->height = r->extents.y2 - r->extents.y1;
+ gint i;
+
+ 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);
+
+ for (i = 0; i < region->numRects; 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;
+ }
}
+/**
+ * gdk_region_union_with_rect:
+ * @region: a #GdkRegion.
+ * @rect: a #GdkRectangle.
+ *
+ * Sets the area of @region to the union of the areas of @region and
+ * @rect. The resulting area is the set of pixels contained in
+ * either @region or @rect.
+ **/
void
-gdk_region_union_with_rect (GdkRegion *region,
- GdkRectangle *rect)
+gdk_region_union_with_rect (GdkRegion *region,
+ const GdkRectangle *rect)
{
GdkRegion tmp_region;
- if (!rect->width || !rect->height)
+ 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;
pReg->extents.y2 = 0;
return;
}
-
+
pExtents = &pReg->extents;
pBox = pReg->rects;
pBoxEnd = &pBox[pReg->numRects - 1];
pExtents->x2 = pBoxEnd->x2;
pExtents->y2 = pBoxEnd->y2;
- assert(pExtents->y1 < pExtents->y2);
+ g_assert(pExtents->y1 < pExtents->y2);
while (pBox <= pBoxEnd)
{
if (pBox->x1 < pExtents->x1)
}
pBox++;
}
- assert(pExtents->x1 < pExtents->x2);
+ g_assert(pExtents->x1 < pExtents->x2);
}
+/**
+ * gdk_region_destroy:
+ * @region: a #GdkRegion
+ *
+ * Destroys a #GdkRegion.
+ */
void
-gdk_region_destroy (GdkRegion *r)
+gdk_region_destroy (GdkRegion *region)
{
- g_free (r->rects);
- g_free (r);
-}
+ g_return_if_fail (region != NULL);
+ if (region->rects != ®ion->extents)
+ g_free (region->rects);
+ g_slice_free (GdkRegion, region);
+}
-/* TranslateRegion(pRegion, x, y)
- translates in place
- added by raymond
-*/
+/**
+ * gdk_region_offset:
+ * @region: a #GdkRegion
+ * @dx: the distance to move the region horizontally
+ * @dy: the distance to move the region vertically
+ *
+ * Moves a region the specified distance.
+ */
void
gdk_region_offset (GdkRegion *region,
gint x,
int nbox;
GdkRegionBox *pbox;
+ g_return_if_fail (region != NULL);
+
pbox = region->rects;
nbox = region->numRects;
pbox->y2 += y;
pbox++;
}
- region->extents.x1 += x;
- region->extents.x2 += x;
- region->extents.y1 += y;
- region->extents.y2 += y;
+ if (region->rects != ®ion->extents)
+ {
+ region->extents.x1 += x;
+ region->extents.x2 += x;
+ region->extents.y1 += y;
+ region->extents.y2 += y;
+ }
}
/*
#undef ZShiftRegion
#undef ZCopyRegion
+/**
+ * gdk_region_shrink:
+ * @region: a #GdkRegion
+ * @dx: the number of pixels to shrink the region horizontally
+ * @dy: the number of pixels to shrink the region vertically
+ *
+ * Resizes a region by the specified amount.
+ * Positive values shrink the region. Negative values expand it.
+ */
void
-gdk_region_shrink (GdkRegion *r,
+gdk_region_shrink (GdkRegion *region,
int dx,
int dy)
{
GdkRegion *s, *t;
int grow;
+ g_return_if_fail (region != NULL);
+
if (!dx && !dy)
return;
if (grow)
dx = -dx;
if (dx)
- Compress(r, s, t, (unsigned) 2*dx, TRUE, grow);
+ Compress(region, s, t, (unsigned) 2*dx, TRUE, grow);
grow = (dy < 0);
if (grow)
dy = -dy;
if (dy)
- Compress(r, s, t, (unsigned) 2*dy, FALSE, grow);
+ Compress(region, s, t, (unsigned) 2*dy, FALSE, grow);
- gdk_region_offset (r, dx, dy);
+ gdk_region_offset (region, dx, dy);
gdk_region_destroy (s);
gdk_region_destroy (t);
}
*/
if (x1 < x2)
{
- assert (y1<y2);
+ g_assert (y1<y2);
MEMCHECK (pReg, pNextRect, pReg->rects);
pNextRect->x1 = x1;
pNextRect->y2 = y2;
pReg->numRects += 1;
pNextRect++;
- assert (pReg->numRects <= pReg->size);
+ g_assert (pReg->numRects <= pReg->size);
}
/*
}
}
+/**
+ * gdk_region_intersect:
+ * @source1: a #GdkRegion
+ * @source2: another #GdkRegion
+ *
+ * Sets the area of @source1 to the intersection of the areas of @source1
+ * and @source2. The resulting area is the set of pixels contained in
+ * both @source1 and @source2.
+ **/
void
-gdk_region_intersect (GdkRegion *region,
- GdkRegion *other)
+gdk_region_intersect (GdkRegion *source1,
+ const GdkRegion *source2)
{
+ g_return_if_fail (source1 != NULL);
+ g_return_if_fail (source2 != NULL);
+
/* check for trivial reject */
- if ((!(region->numRects)) || (!(other->numRects)) ||
- (!EXTENTCHECK(®ion->extents, &other->extents)))
- region->numRects = 0;
+ if ((!(source1->numRects)) || (!(source2->numRects)) ||
+ (!EXTENTCHECK(&source1->extents, &source2->extents)))
+ source1->numRects = 0;
else
- miRegionOp (region, region, other,
+ miRegionOp (source1, source1, source2,
miIntersectO, (nonOverlapFunc) NULL, (nonOverlapFunc) NULL);
/*
- * Can't alter region's extents before miRegionOp depends on the
+ * 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(region);
+ miSetExtents(source1);
}
static void
-miRegionCopy(GdkRegion *dstrgn, GdkRegion *rgn)
+miRegionCopy (GdkRegion *dstrgn,
+ const GdkRegion *rgn)
{
if (dstrgn != rgn) /* don't want to copy to itself */
{
if (dstrgn->size < rgn->numRects)
{
- dstrgn->rects = g_renew (GdkRegionBox, dstrgn->rects, 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.x1 = rgn->extents.x1;
- dstrgn->extents.y1 = rgn->extents.y1;
- dstrgn->extents.x2 = rgn->extents.x2;
- dstrgn->extents.y2 = rgn->extents.y2;
+ dstrgn->extents = rgn->extents;
memcpy (dstrgn->rects, rgn->rects, rgn->numRects * sizeof (GdkRegionBox));
}
*/
/* static void*/
static void
-miRegionOp(GdkRegion *newReg,
- GdkRegion *reg1,
- GdkRegion *reg2,
- overlapFunc overlapFn, /* Function to call for over-
+miRegionOp(GdkRegion *newReg,
+ GdkRegion *reg1,
+ const GdkRegion *reg2,
+ overlapFunc overlapFn, /* Function to call for over-
* lapping bands */
- nonOverlapFunc nonOverlap1Fn, /* Function to call for non-
+ nonOverlapFunc nonOverlap1Fn, /* Function to call for non-
* overlapping bands in region
* 1 */
- nonOverlapFunc nonOverlap2Fn) /* Function to call for non-
+ nonOverlapFunc nonOverlap2Fn) /* Function to call for non-
* overlapping bands in region
* 2 */
{
*/
newReg->size = 1;
g_free (newReg->rects);
- newReg->rects = g_new (GdkRegionBox, 1);
+ newReg->rects = &newReg->extents;
}
}
- g_free (oldRects);
+
+ if (oldRects != &newReg->extents)
+ g_free (oldRects);
}
\f
pNextRect = &pReg->rects[pReg->numRects];
- assert(y1 < y2);
+ g_assert(y1 < y2);
while (r != rEnd)
{
- assert(r->x1 < r->x2);
+ g_assert(r->x1 < r->x2);
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->x1 = r->x1;
pNextRect->y1 = y1;
pReg->numRects += 1;
pNextRect++;
- assert(pReg->numRects<=pReg->size);
+ g_assert(pReg->numRects<=pReg->size);
r++;
}
}
if (pNextRect[-1].x2 < r->x2) \
{ \
pNextRect[-1].x2 = r->x2; \
- assert(pNextRect[-1].x1<pNextRect[-1].x2); \
+ g_assert(pNextRect[-1].x1<pNextRect[-1].x2); \
} \
} \
else \
pReg->numRects += 1; \
pNextRect += 1; \
} \
- assert(pReg->numRects<=pReg->size); \
+ g_assert(pReg->numRects<=pReg->size); \
r++;
- assert (y1<y2);
+ g_assert (y1<y2);
while ((r1 != r1End) && (r2 != r2End))
{
if (r1->x1 < r2->x1)
}
}
+/**
+ * gdk_region_union:
+ * @source1: a #GdkRegion
+ * @source2: a #GdkRegion
+ *
+ * Sets the area of @source1 to the union of the areas of @source1 and
+ * @source2. The resulting area is the set of pixels contained in
+ * either @source1 or @source2.
+ **/
void
-gdk_region_union (GdkRegion *region,
- GdkRegion *other)
+gdk_region_union (GdkRegion *source1,
+ const GdkRegion *source2)
{
+ g_return_if_fail (source1 != NULL);
+ g_return_if_fail (source2 != NULL);
+
/* checks all the simple cases */
- /*
- * region and other are the same or other is empty
- */
- if ((region == other) || (!(other->numRects)))
+ /*
+ * source1 and source2 are the same or source2 is empty
+ */
+ if ((source1 == source2) || (!(source2->numRects)))
return;
- /*
- * region is empty
- */
- if (!(region->numRects))
+ /*
+ * source1 is empty
+ */
+ if (!(source1->numRects))
{
- miRegionCopy (region, other);
+ miRegionCopy (source1, source2);
return;
}
-
+
/*
- * region completely subsumes otehr
- */
- if ((region->numRects == 1) &&
- (region->extents.x1 <= other->extents.x1) &&
- (region->extents.y1 <= other->extents.y1) &&
- (region->extents.x2 >= other->extents.x2) &&
- (region->extents.y2 >= other->extents.y2))
+ * 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;
/*
- * other completely subsumes region
- */
- if ((other->numRects == 1) &&
- (other->extents.x1 <= region->extents.x1) &&
- (other->extents.y1 <= region->extents.y1) &&
- (other->extents.x2 >= region->extents.x2) &&
- (other->extents.y2 >= region->extents.y2))
+ * 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(region, other);
+ miRegionCopy(source1, source2);
return;
}
- miRegionOp (region, region, other, miUnionO,
+ miRegionOp (source1, source1, source2, miUnionO,
miUnionNonO, miUnionNonO);
- region->extents.x1 = MIN (region->extents.x1, other->extents.x1);
- region->extents.y1 = MIN (region->extents.y1, other->extents.y1);
- region->extents.x2 = MAX (region->extents.x2, other->extents.x2);
- region->extents.y2 = MAX (region->extents.y2, other->extents.y2);
+ 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
pNextRect = &pReg->rects[pReg->numRects];
- assert(y1<y2);
+ g_assert(y1<y2);
while (r != rEnd)
{
- assert (r->x1<r->x2);
+ g_assert (r->x1<r->x2);
MEMCHECK (pReg, pNextRect, pReg->rects);
pNextRect->x1 = r->x1;
pNextRect->y1 = y1;
pReg->numRects += 1;
pNextRect++;
- assert (pReg->numRects <= pReg->size);
+ g_assert (pReg->numRects <= pReg->size);
r++;
}
x1 = r1->x1;
- assert(y1<y2);
+ g_assert(y1<y2);
pNextRect = &pReg->rects[pReg->numRects];
while ((r1 != r1End) && (r2 != r2End))
* Left part of subtrahend covers part of minuend: add uncovered
* part of minuend to region and skip to next subtrahend.
*/
- assert(x1<r2->x1);
+ g_assert(x1<r2->x1);
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->x1 = x1;
pNextRect->y1 = y1;
pReg->numRects += 1;
pNextRect++;
- assert(pReg->numRects<=pReg->size);
+ g_assert(pReg->numRects<=pReg->size);
x1 = r2->x2;
if (x1 >= r1->x2)
pNextRect->y2 = y2;
pReg->numRects += 1;
pNextRect++;
- assert(pReg->numRects<=pReg->size);
+ g_assert(pReg->numRects<=pReg->size);
}
r1++;
- x1 = r1->x1;
+ if (r1 != r1End)
+ x1 = r1->x1;
}
}
*/
while (r1 != r1End)
{
- assert(x1<r1->x2);
+ g_assert(x1<r1->x2);
MEMCHECK(pReg, pNextRect, pReg->rects);
pNextRect->x1 = x1;
pNextRect->y1 = y1;
pReg->numRects += 1;
pNextRect++;
- assert(pReg->numRects<=pReg->size);
+ g_assert(pReg->numRects<=pReg->size);
r1++;
if (r1 != r1End)
}
}
}
-
-/*-
- *-----------------------------------------------------------------------
- * gdk_region_subtract --
- * Subtract other from region and leave the result in region.
- *
- * Results:
- * TRUE.
- *
- * Side Effects:
- * region is overwritten.
- *
- *-----------------------------------------------------------------------
- */
+/**
+ * gdk_region_subtract:
+ * @source1: a #GdkRegion
+ * @source2: another #GdkRegion
+ *
+ * Subtracts the area of @source2 from the area @source1. The resulting
+ * area is the set of pixels contained in @source1 but not in @source2.
+ **/
void
-gdk_region_subtract (GdkRegion *region,
- GdkRegion *other)
+gdk_region_subtract (GdkRegion *source1,
+ const GdkRegion *source2)
{
+ g_return_if_fail (source1 != NULL);
+ g_return_if_fail (source2 != NULL);
+
/* check for trivial reject */
- if ((!(region->numRects)) || (!(other->numRects)) ||
- (!EXTENTCHECK(®ion->extents, &other->extents)))
+ if ((!(source1->numRects)) || (!(source2->numRects)) ||
+ (!EXTENTCHECK(&source1->extents, &source2->extents)))
return;
- miRegionOp (region, region, other, miSubtractO,
+ miRegionOp (source1, source1, source2, miSubtractO,
miSubtractNonO1, (nonOverlapFunc) NULL);
/*
- * Can't alter region's extents before we call miRegionOp because miRegionOp
+ * 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 (region);
+ miSetExtents (source1);
}
+/**
+ * gdk_region_xor:
+ * @source1: a #GdkRegion
+ * @source2: another #GdkRegion
+ *
+ * Sets the area of @source1 to the exclusive-OR of the areas of @source1
+ * and @source2. The resulting area is the set of pixels contained in one
+ * or the other of the two sources but not in both.
+ **/
void
-gdk_region_xor (GdkRegion *sra,
- GdkRegion *srb)
+gdk_region_xor (GdkRegion *source1,
+ const GdkRegion *source2)
{
GdkRegion *trb;
- trb = gdk_region_copy (srb);
+ g_return_if_fail (source1 != NULL);
+ g_return_if_fail (source2 != NULL);
+
+ trb = gdk_region_copy (source2);
- gdk_region_subtract (trb, sra);
- gdk_region_subtract (sra, srb);
+ gdk_region_subtract (trb, source1);
+ gdk_region_subtract (source1, source2);
- gdk_region_union (sra,trb);
+ gdk_region_union (source1, trb);
gdk_region_destroy (trb);
}
-/*
- * Check to see if the region is empty. Assumes a region is passed
- * as a parameter
+/**
+ * gdk_region_empty:
+ * @region: a #GdkRegion
+ *
+ * Finds out if the #GdkRegion is empty.
+ *
+ * Returns: %TRUE if @region is empty.
*/
gboolean
-gdk_region_empty (GdkRegion *r)
+gdk_region_empty (const GdkRegion *region)
{
- if (r->numRects == 0)
+ g_return_val_if_fail (region != NULL, FALSE);
+
+ if (region->numRects == 0)
return TRUE;
else
return FALSE;
}
-/*
- * Check to see if two regions are equal
+/**
+ * gdk_region_equal:
+ * @region1: a #GdkRegion
+ * @region2: a #GdkRegion
+ *
+ * Finds out if the two regions are the same.
+ *
+ * Returns: %TRUE if @region1 and @region2 are equal.
*/
gboolean
-gdk_region_equal (GdkRegion *r1,
- GdkRegion *r2)
+gdk_region_equal (const GdkRegion *region1,
+ const GdkRegion *region2)
{
int i;
- if (r1->numRects != r2->numRects) return FALSE;
- else if (r1->numRects == 0) return TRUE;
- else if (r1->extents.x1 != r2->extents.x1) return FALSE;
- else if (r1->extents.x2 != r2->extents.x2) return FALSE;
- else if (r1->extents.y1 != r2->extents.y1) return FALSE;
- else if (r1->extents.y2 != r2->extents.y2) return FALSE;
+ 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 < r1->numRects; i++ )
+ for(i = 0; i < region1->numRects; i++ )
{
- if (r1->rects[i].x1 != r2->rects[i].x1) return FALSE;
- else if (r1->rects[i].x2 != r2->rects[i].x2) return FALSE;
- else if (r1->rects[i].y1 != r2->rects[i].y1) return FALSE;
- else if (r1->rects[i].y2 != r2->rects[i].y2) return FALSE;
+ 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;
}
+/**
+ * gdk_region_rect_equal:
+ * @region: a #GdkRegion
+ * @rectangle: a #GdkRectangle
+ *
+ * Finds out if a regions is the same as a rectangle.
+ *
+ * Returns: %TRUE if @region and @rectangle are equal.
+ *
+ * Since: 2.18
+ */
gboolean
-gdk_region_point_in (GdkRegion *region,
- int x,
- int y)
+gdk_region_rect_equal (const GdkRegion *region,
+ const GdkRectangle *rectangle)
+{
+ 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;
+ return TRUE;
+}
+
+/**
+ * gdk_region_point_in:
+ * @region: a #GdkRegion
+ * @x: the x coordinate of a point
+ * @y: the y coordinate of a point
+ *
+ * Finds out if a point is in a region.
+ *
+ * Returns: %TRUE if the point is in @region.
+ */
+gboolean
+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++)
+ for (i = 0; i < region->numRects; i++)
{
if (INBOX (region->rects[i], x, y))
return TRUE;
return FALSE;
}
+/**
+ * gdk_region_rect_in:
+ * @region: a #GdkRegion.
+ * @rectangle: a #GdkRectangle.
+ *
+ * Tests whether a rectangle is within a region.
+ *
+ * Returns: %GDK_OVERLAP_RECTANGLE_IN, %GDK_OVERLAP_RECTANGLE_OUT, or
+ * %GDK_OVERLAP_RECTANGLE_PART, depending on whether the rectangle is inside,
+ * outside, or partly inside the #GdkRegion, respectively.
+ */
GdkOverlapType
-gdk_region_rect_in (GdkRegion *region,
- GdkRectangle *rectangle)
+gdk_region_rect_in (const GdkRegion *region,
+ const GdkRectangle *rectangle)
{
GdkRegionBox *pbox;
GdkRegionBox *pboxEnd;
GdkRegionBox rect;
GdkRegionBox *prect = ▭
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);
- gint rx = rectangle->x;
- gint ry = rectangle->y;
+ rx = rectangle->x;
+ ry = rectangle->y;
prect->x1 = rx;
prect->y1 = ry;
GDK_OVERLAP_RECTANGLE_PART : GDK_OVERLAP_RECTANGLE_IN) :
GDK_OVERLAP_RECTANGLE_OUT);
}
+
+
+static void
+gdk_region_unsorted_spans_intersect_foreach (GdkRegion *region,
+ const GdkSpan *spans,
+ int n_spans,
+ GdkSpanFunc function,
+ gpointer data)
+{
+ gint i, left, right, y;
+ gint clipped_left, clipped_right;
+ GdkRegionBox *pbox;
+ GdkRegionBox *pboxEnd;
+
+ if (!region->numRects)
+ return;
+
+ 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)) )
+ continue;
+
+ /* can stop when we passed y */
+ for (pbox = region->rects, pboxEnd = pbox + region->numRects;
+ pbox < pboxEnd;
+ pbox++)
+ {
+ if (pbox->y2 <= y)
+ continue; /* Not quite there yet */
+
+ if (pbox->y1 > y)
+ break; /* passed the spanline */
+
+ if ((right > pbox->x1) && (left < pbox->x2))
+ {
+ GdkSpan out_span;
+
+ clipped_left = MAX (left, pbox->x1);
+ clipped_right = MIN (right, pbox->x2);
+
+ out_span.y = y;
+ out_span.x = clipped_left;
+ out_span.width = clipped_right - clipped_left;
+ (*function) (&out_span, data);
+ }
+ }
+ }
+}
+
+/**
+ * gdk_region_spans_intersect_foreach:
+ * @region: a #GdkRegion
+ * @spans: an array of #GdkSpans
+ * @n_spans: the length of @spans
+ * @sorted: %TRUE if @spans is sorted wrt. the y coordinate
+ * @function: function to call on each span in the intersection
+ * @data: data to pass to @function
+ *
+ * Calls a function on each span in the intersection of @region and @spans.
+ */
+void
+gdk_region_spans_intersect_foreach (GdkRegion *region,
+ const GdkSpan *spans,
+ int n_spans,
+ gboolean sorted,
+ GdkSpanFunc function,
+ gpointer data)
+{
+ gint left, right, y;
+ gint clipped_left, clipped_right;
+ GdkRegionBox *pbox;
+ GdkRegionBox *pboxEnd;
+ const GdkSpan *span, *tmpspan;
+ const GdkSpan *end_span;
+
+ g_return_if_fail (region != NULL);
+ g_return_if_fail (spans != NULL);
+
+ if (!sorted)
+ {
+ gdk_region_unsorted_spans_intersect_foreach (region,
+ spans,
+ n_spans,
+ function,
+ data);
+ return;
+ }
+
+ if ((!region->numRects) || (n_spans == 0))
+ return;
+
+ /* The main method here is to step along the
+ * sorted rectangles and spans in lock step, and
+ * clipping the spans that are in the current
+ * rectangle before going on to the next rectangle.
+ */
+
+ span = spans;
+ end_span = spans + n_spans;
+ pbox = region->rects;
+ pboxEnd = pbox + region->numRects;
+ while (pbox < pboxEnd)
+ {
+ while ((pbox->y2 < span->y) || (span->y < pbox->y1))
+ {
+ /* Skip any rectangles that are above the current span */
+ if (pbox->y2 < span->y)
+ {
+ pbox++;
+ if (pbox == pboxEnd)
+ return;
+ }
+ /* Skip any spans that are above the current rectangle */
+ if (span->y < pbox->y1)
+ {
+ span++;
+ if (span == end_span)
+ return;
+ }
+ }
+
+ /* Ok, we got at least one span that might intersect this rectangle. */
+ tmpspan = span;
+ while ((tmpspan < end_span) &&
+ (tmpspan->y < pbox->y2))
+ {
+ y = tmpspan->y;
+ left = tmpspan->x;
+ right = left + tmpspan->width; /* right is not in the span! */
+
+ if ((right > pbox->x1) && (left < pbox->x2))
+ {
+ GdkSpan out_span;
+
+ clipped_left = MAX (left, pbox->x1);
+ clipped_right = MIN (right, pbox->x2);
+
+ out_span.y = y;
+ out_span.x = clipped_left;
+ out_span.width = clipped_right - clipped_left;
+ (*function) (&out_span, data);
+ }
+
+ tmpspan++;
+ }
+
+ /* Finished this rectangle.
+ * The spans could still intersect the next one
+ */
+ pbox++;
+ }
+}
+
+#define __GDK_REGION_GENERIC_C__
+#include "gdkaliasdef.c"