|
Packit Service |
2781ba |
/* $TOG: Region.c /main/31 1998/02/06 17:50:22 kaleb $ */
|
|
Packit Service |
2781ba |
/************************************************************************
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
Copyright 1987, 1988, 1998 The Open Group
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
All Rights Reserved.
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
The above copyright notice and this permission notice shall be included in
|
|
Packit Service |
2781ba |
all copies or substantial portions of the Software.
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
Packit Service |
2781ba |
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
Packit Service |
2781ba |
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
Packit Service |
2781ba |
OPEN GROUP BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN
|
|
Packit Service |
2781ba |
AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
|
|
Packit Service |
2781ba |
CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
Except as contained in this notice, the name of The Open Group shall not be
|
|
Packit Service |
2781ba |
used in advertising or otherwise to promote the sale, use or other dealings
|
|
Packit Service |
2781ba |
in this Software without prior written authorization from The Open Group.
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
Copyright 1987, 1988 by Digital Equipment Corporation, Maynard, Massachusetts.
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
All Rights Reserved
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
Permission to use, copy, modify, and distribute this software and its
|
|
Packit Service |
2781ba |
documentation for any purpose and without fee is hereby granted,
|
|
Packit Service |
2781ba |
provided that the above copyright notice appear in all copies and that
|
|
Packit Service |
2781ba |
both that copyright notice and this permission notice appear in
|
|
Packit Service |
2781ba |
supporting documentation, and that the name of Digital not be
|
|
Packit Service |
2781ba |
used in advertising or publicity pertaining to distribution of the
|
|
Packit Service |
2781ba |
software without specific, written prior permission.
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
|
|
Packit Service |
2781ba |
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
|
|
Packit Service |
2781ba |
DIGITAL BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR
|
|
Packit Service |
2781ba |
ANY DAMAGES WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS,
|
|
Packit Service |
2781ba |
WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION,
|
|
Packit Service |
2781ba |
ARISING OUT OF OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS
|
|
Packit Service |
2781ba |
SOFTWARE.
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
************************************************************************/
|
|
Packit Service |
2781ba |
/* $XFree86: xc/lib/X11/Region.c,v 1.5 1999/05/09 10:50:01 dawes Exp $ */
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* The functions in this file implement the Region abstraction, similar to one
|
|
Packit Service |
2781ba |
* used in the X11 sample server. A Region is simply an area, as the name
|
|
Packit Service |
2781ba |
* implies, and is implemented as a "y-x-banded" array of rectangles. To
|
|
Packit Service |
2781ba |
* explain: Each Region is made up of a certain number of rectangles sorted
|
|
Packit Service |
2781ba |
* by y coordinate first, and then by x coordinate.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Furthermore, the rectangles are banded such that every rectangle with a
|
|
Packit Service |
2781ba |
* given upper-left y coordinate (y1) will have the same lower-right y
|
|
Packit Service |
2781ba |
* coordinate (y2) and vice versa. If a rectangle has scanlines in a band, it
|
|
Packit Service |
2781ba |
* will span the entire vertical distance of the band. This means that some
|
|
Packit Service |
2781ba |
* areas that could be merged into a taller rectangle will be represented as
|
|
Packit Service |
2781ba |
* several shorter rectangles to account for shorter rectangles to its left
|
|
Packit Service |
2781ba |
* or right but within its "vertical scope".
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* An added constraint on the rectangles is that they must cover as much
|
|
Packit Service |
2781ba |
* horizontal area as possible. E.g. no two rectangles in a band are allowed
|
|
Packit Service |
2781ba |
* to touch.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Whenever possible, bands will be merged together to cover a greater vertical
|
|
Packit Service |
2781ba |
* distance (and thus reduce the number of rectangles). Two bands can be merged
|
|
Packit Service |
2781ba |
* only if the bottom of one touches the top of the other and they have
|
|
Packit Service |
2781ba |
* rectangles in the same places (of the same width, of course). This maintains
|
|
Packit Service |
2781ba |
* the y-x-banding that's so nice to have...
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include <config.h>
|
|
Packit Service |
2781ba |
#include <stdlib.h>
|
|
Packit Service |
2781ba |
#include <string.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include <glib.h>
|
|
Packit Service |
2781ba |
#include <glib-object.h>
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#include "gegl.h"
|
|
Packit Service |
2781ba |
#include "gegl-region.h"
|
|
Packit Service |
2781ba |
#include "gegl-region-generic.h"
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
typedef void (* overlapFunc) (GeglRegion *pReg,
|
|
Packit Service |
2781ba |
GeglRegionBox *r1,
|
|
Packit Service |
2781ba |
GeglRegionBox *r1End,
|
|
Packit Service |
2781ba |
GeglRegionBox *r2,
|
|
Packit Service |
2781ba |
GeglRegionBox *r2End,
|
|
Packit Service |
2781ba |
gint y1,
|
|
Packit Service |
2781ba |
gint y2);
|
|
Packit Service |
2781ba |
typedef void (* nonOverlapFunc) (GeglRegion *pReg,
|
|
Packit Service |
2781ba |
GeglRegionBox *r,
|
|
Packit Service |
2781ba |
GeglRegionBox *rEnd,
|
|
Packit Service |
2781ba |
gint y1,
|
|
Packit Service |
2781ba |
gint y2);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void miRegionCopy (GeglRegion *dstrgn,
|
|
Packit Service |
2781ba |
const GeglRegion *rgn);
|
|
Packit Service |
2781ba |
static void miRegionOp (GeglRegion *newReg,
|
|
Packit Service |
2781ba |
GeglRegion *reg1,
|
|
Packit Service |
2781ba |
const GeglRegion *reg2,
|
|
Packit Service |
2781ba |
overlapFunc overlapFn,
|
|
Packit Service |
2781ba |
nonOverlapFunc nonOverlap1Fn,
|
|
Packit Service |
2781ba |
nonOverlapFunc nonOverlap2Fn);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_new:
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Creates a new empty #GeglRegion.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Returns: a new empty #GeglRegion
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
GeglRegion *
|
|
Packit Service |
2781ba |
gegl_region_new (void)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegion *temp;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
temp = g_slice_new (GeglRegion);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
temp->numRects = 0;
|
|
Packit Service |
2781ba |
temp->rects = &temp->extents;
|
|
Packit Service |
2781ba |
temp->extents.x1 = 0;
|
|
Packit Service |
2781ba |
temp->extents.y1 = 0;
|
|
Packit Service |
2781ba |
temp->extents.x2 = 0;
|
|
Packit Service |
2781ba |
temp->extents.y2 = 0;
|
|
Packit Service |
2781ba |
temp->size = 1;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
return temp;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_rectangle:
|
|
Packit Service |
2781ba |
* @rectangle: a #GeglRectangle
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Creates a new region containing the area @rectangle.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Return value: a new region
|
|
Packit Service |
2781ba |
**/
|
|
Packit Service |
2781ba |
GeglRegion *
|
|
Packit Service |
2781ba |
gegl_region_rectangle (const GeglRectangle *rectangle)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegion *temp;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_val_if_fail (rectangle != NULL, NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (rectangle->width <= 0 || rectangle->height <= 0)
|
|
Packit Service |
2781ba |
return gegl_region_new ();
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
temp = g_slice_new (GeglRegion);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
temp->numRects = 1;
|
|
Packit Service |
2781ba |
temp->rects = &temp->extents;
|
|
Packit Service |
2781ba |
temp->extents.x1 = rectangle->x;
|
|
Packit Service |
2781ba |
temp->extents.y1 = rectangle->y;
|
|
Packit Service |
2781ba |
temp->extents.x2 = rectangle->x + rectangle->width;
|
|
Packit Service |
2781ba |
temp->extents.y2 = rectangle->y + rectangle->height;
|
|
Packit Service |
2781ba |
temp->size = 1;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
return temp;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_copy:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Copies @region, creating an identical new region.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Return value: a new region identical to @region
|
|
Packit Service |
2781ba |
**/
|
|
Packit Service |
2781ba |
GeglRegion *
|
|
Packit Service |
2781ba |
gegl_region_copy (const GeglRegion *region)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegion *temp;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_val_if_fail (region != NULL, NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
temp = gegl_region_new ();
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
miRegionCopy (temp, region);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
return temp;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_get_clipbox:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion
|
|
Packit Service |
2781ba |
* @rectangle: return location for the clipbox
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Obtains the smallest rectangle which includes the entire #GeglRegion.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_get_clipbox (GeglRegion *region,
|
|
Packit Service |
2781ba |
GeglRectangle *rectangle)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_return_if_fail (region != NULL);
|
|
Packit Service |
2781ba |
g_return_if_fail (rectangle != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
rectangle->x = region->extents.x1;
|
|
Packit Service |
2781ba |
rectangle->y = region->extents.y1;
|
|
Packit Service |
2781ba |
rectangle->width = region->extents.x2 - region->extents.x1;
|
|
Packit Service |
2781ba |
rectangle->height = region->extents.y2 - region->extents.y1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_get_rectangles:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion
|
|
Packit Service |
2781ba |
* @rectangles: return location for an array of rectangles
|
|
Packit Service |
2781ba |
* @n_rectangles: length of returned array
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Obtains the area covered by the region as a list of rectangles.
|
|
Packit Service |
2781ba |
* The array returned in @rectangles must be freed with g_free().
|
|
Packit Service |
2781ba |
**/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_get_rectangles (GeglRegion *region,
|
|
Packit Service |
2781ba |
GeglRectangle **rectangles,
|
|
Packit Service |
2781ba |
gint *n_rectangles)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gint i;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_if_fail (region != NULL);
|
|
Packit Service |
2781ba |
g_return_if_fail (rectangles != NULL);
|
|
Packit Service |
2781ba |
g_return_if_fail (n_rectangles != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
*n_rectangles = region->numRects;
|
|
Packit Service |
2781ba |
*rectangles = g_new (GeglRectangle, region->numRects);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (i = 0; i < region->numRects; i++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegionBox rect;
|
|
Packit Service |
2781ba |
rect = region->rects[i];
|
|
Packit Service |
2781ba |
(*rectangles)[i].x = rect.x1;
|
|
Packit Service |
2781ba |
(*rectangles)[i].y = rect.y1;
|
|
Packit Service |
2781ba |
(*rectangles)[i].width = rect.x2 - rect.x1;
|
|
Packit Service |
2781ba |
(*rectangles)[i].height = rect.y2 - rect.y1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_union_with_rect:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion.
|
|
Packit Service |
2781ba |
* @rect: a #GeglRectangle.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Sets the area of @region to the union of the areas of @region and
|
|
Packit Service |
2781ba |
* @rect. The resulting area is the set of pixels contained in
|
|
Packit Service |
2781ba |
* either @region or @rect.
|
|
Packit Service |
2781ba |
**/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_union_with_rect (GeglRegion *region,
|
|
Packit Service |
2781ba |
const GeglRectangle *rect)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegion tmp_region;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_if_fail (region != NULL);
|
|
Packit Service |
2781ba |
g_return_if_fail (rect != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (rect->width <= 0 || rect->height <= 0)
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
tmp_region.rects = &tmp_region.extents;
|
|
Packit Service |
2781ba |
tmp_region.numRects = 1;
|
|
Packit Service |
2781ba |
tmp_region.extents.x1 = rect->x;
|
|
Packit Service |
2781ba |
tmp_region.extents.y1 = rect->y;
|
|
Packit Service |
2781ba |
tmp_region.extents.x2 = rect->x + rect->width;
|
|
Packit Service |
2781ba |
tmp_region.extents.y2 = rect->y + rect->height;
|
|
Packit Service |
2781ba |
tmp_region.size = 1;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_region_union (region, &tmp_region);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*-
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
* miSetExtents --
|
|
Packit Service |
2781ba |
* Reset the extents of a region to what they should be. Called by
|
|
Packit Service |
2781ba |
* miSubtract and miIntersect b/c they can't figure it out along the
|
|
Packit Service |
2781ba |
* way or do so easily, as miUnion can.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Results:
|
|
Packit Service |
2781ba |
* None.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Side Effects:
|
|
Packit Service |
2781ba |
* The region's 'extents' structure is overwritten.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
miSetExtents (GeglRegion *pReg)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegionBox *pBox, *pBoxEnd, *pExtents;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (pReg->numRects == 0)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
pReg->extents.x1 = 0;
|
|
Packit Service |
2781ba |
pReg->extents.y1 = 0;
|
|
Packit Service |
2781ba |
pReg->extents.x2 = 0;
|
|
Packit Service |
2781ba |
pReg->extents.y2 = 0;
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
pExtents = &pReg->extents;
|
|
Packit Service |
2781ba |
pBox = pReg->rects;
|
|
Packit Service |
2781ba |
pBoxEnd = &pBox[pReg->numRects - 1];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Since pBox is the first rectangle in the region, it must have the
|
|
Packit Service |
2781ba |
* smallest y1 and since pBoxEnd is the last rectangle in the region,
|
|
Packit Service |
2781ba |
* it must have the largest y2, because of banding. Initialize x1 and
|
|
Packit Service |
2781ba |
* x2 from pBox and pBoxEnd, resp., as good things to initialize them
|
|
Packit Service |
2781ba |
* to...
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
pExtents->x1 = pBox->x1;
|
|
Packit Service |
2781ba |
pExtents->y1 = pBox->y1;
|
|
Packit Service |
2781ba |
pExtents->x2 = pBoxEnd->x2;
|
|
Packit Service |
2781ba |
pExtents->y2 = pBoxEnd->y2;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (pExtents->y1 < pExtents->y2);
|
|
Packit Service |
2781ba |
while (pBox <= pBoxEnd)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (pBox->x1 < pExtents->x1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
pExtents->x1 = pBox->x1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
if (pBox->x2 > pExtents->x2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
pExtents->x2 = pBox->x2;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
pBox++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
g_assert (pExtents->x1 < pExtents->x2);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_destroy:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Destroys a #GeglRegion.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_destroy (GeglRegion *region)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_return_if_fail (region != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (region->rects != ®ion->extents)
|
|
Packit Service |
2781ba |
g_free (region->rects);
|
|
Packit Service |
2781ba |
g_slice_free (GeglRegion, region);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_offset:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion
|
|
Packit Service |
2781ba |
* @dx: the distance to move the region horizontally
|
|
Packit Service |
2781ba |
* @dy: the distance to move the region vertically
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Moves a region the specified distance.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_offset (GeglRegion *region,
|
|
Packit Service |
2781ba |
gint x,
|
|
Packit Service |
2781ba |
gint y)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
int nbox;
|
|
Packit Service |
2781ba |
GeglRegionBox *pbox;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_if_fail (region != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
pbox = region->rects;
|
|
Packit Service |
2781ba |
nbox = region->numRects;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
while (nbox--)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
pbox->x1 += x;
|
|
Packit Service |
2781ba |
pbox->x2 += x;
|
|
Packit Service |
2781ba |
pbox->y1 += y;
|
|
Packit Service |
2781ba |
pbox->y2 += y;
|
|
Packit Service |
2781ba |
pbox++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
if (region->rects != ®ion->extents)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
region->extents.x1 += x;
|
|
Packit Service |
2781ba |
region->extents.x2 += x;
|
|
Packit Service |
2781ba |
region->extents.y1 += y;
|
|
Packit Service |
2781ba |
region->extents.y2 += y;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
Utility procedure Compress:
|
|
Packit Service |
2781ba |
Replace r by the region r', where
|
|
Packit Service |
2781ba |
p in r' iff (Quantifer m <= dx) (p + m in r), and
|
|
Packit Service |
2781ba |
Quantifier is Exists if grow is TRUE, For all if grow is FALSE, and
|
|
Packit Service |
2781ba |
(x,y) + m = (x+m,y) if xdir is TRUE; (x,y+m) if xdir is FALSE.
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
Thus, if xdir is TRUE and grow is FALSE, r is replaced by the region
|
|
Packit Service |
2781ba |
of all points p such that p and the next dx points on the same
|
|
Packit Service |
2781ba |
horizontal scan line are all in r. We do this using by noting
|
|
Packit Service |
2781ba |
that p is the head of a run of length 2^i + k iff p is the head
|
|
Packit Service |
2781ba |
of a run of length 2^i and p+2^i is the head of a run of length
|
|
Packit Service |
2781ba |
k. Thus, the loop invariant: s contains the region corresponding
|
|
Packit Service |
2781ba |
to the runs of length shift. r contains the region corresponding
|
|
Packit Service |
2781ba |
to the runs of length 1 + dxo & (shift-1), where dxo is the original
|
|
Packit Service |
2781ba |
value of dx. dx = dxo & ~(shift-1). As parameters, s and t are
|
|
Packit Service |
2781ba |
scratch regions, so that we don't have to allocate them on every
|
|
Packit Service |
2781ba |
call.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#define ZOpRegion(a, b) if (grow) gegl_region_union (a, b);\
|
|
Packit Service |
2781ba |
else gegl_region_intersect (a, b)
|
|
Packit Service |
2781ba |
#define ZShiftRegion(a, b) if (xdir) gegl_region_offset (a, b, 0);\
|
|
Packit Service |
2781ba |
else gegl_region_offset (a, 0, b)
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
Compress (GeglRegion *r,
|
|
Packit Service |
2781ba |
GeglRegion *s,
|
|
Packit Service |
2781ba |
GeglRegion *t,
|
|
Packit Service |
2781ba |
guint dx,
|
|
Packit Service |
2781ba |
int xdir,
|
|
Packit Service |
2781ba |
int grow)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
guint shift = 1;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
miRegionCopy (s, r);
|
|
Packit Service |
2781ba |
while (dx)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (dx & shift)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
ZShiftRegion (r, -(int) shift);
|
|
Packit Service |
2781ba |
ZOpRegion (r, s);
|
|
Packit Service |
2781ba |
dx -= shift;
|
|
Packit Service |
2781ba |
if (!dx) break;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
miRegionCopy (t, s);
|
|
Packit Service |
2781ba |
ZShiftRegion (s, -(int) shift);
|
|
Packit Service |
2781ba |
ZOpRegion (s, t);
|
|
Packit Service |
2781ba |
shift <<= 1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#undef ZOpRegion
|
|
Packit Service |
2781ba |
#undef ZShiftRegion
|
|
Packit Service |
2781ba |
#undef ZCopyRegion
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_shrink:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion
|
|
Packit Service |
2781ba |
* @dx: the number of pixels to shrink the region horizontally
|
|
Packit Service |
2781ba |
* @dy: the number of pixels to shrink the region vertically
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Resizes a region by the specified amount.
|
|
Packit Service |
2781ba |
* Positive values shrink the region. Negative values expand it.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_shrink (GeglRegion *region,
|
|
Packit Service |
2781ba |
int dx,
|
|
Packit Service |
2781ba |
int dy)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegion *s, *t;
|
|
Packit Service |
2781ba |
int grow;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_if_fail (region != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (!dx && !dy)
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
s = gegl_region_new ();
|
|
Packit Service |
2781ba |
t = gegl_region_new ();
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
grow = (dx < 0);
|
|
Packit Service |
2781ba |
if (grow)
|
|
Packit Service |
2781ba |
dx = -dx;
|
|
Packit Service |
2781ba |
if (dx)
|
|
Packit Service |
2781ba |
Compress (region, s, t, (unsigned) 2 * dx, TRUE, grow);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
grow = (dy < 0);
|
|
Packit Service |
2781ba |
if (grow)
|
|
Packit Service |
2781ba |
dy = -dy;
|
|
Packit Service |
2781ba |
if (dy)
|
|
Packit Service |
2781ba |
Compress (region, s, t, (unsigned) 2 * dy, FALSE, grow);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_region_offset (region, dx, dy);
|
|
Packit Service |
2781ba |
gegl_region_destroy (s);
|
|
Packit Service |
2781ba |
gegl_region_destroy (t);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*======================================================================
|
|
Packit Service |
2781ba |
* Region Intersection
|
|
Packit Service |
2781ba |
*====================================================================*/
|
|
Packit Service |
2781ba |
/*-
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
* miIntersectO --
|
|
Packit Service |
2781ba |
* Handle an overlapping band for miIntersect.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Results:
|
|
Packit Service |
2781ba |
* None.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Side Effects:
|
|
Packit Service |
2781ba |
* Rectangles may be added to the region.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
/* static void*/
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
miIntersectO (GeglRegion *pReg,
|
|
Packit Service |
2781ba |
GeglRegionBox *r1,
|
|
Packit Service |
2781ba |
GeglRegionBox *r1End,
|
|
Packit Service |
2781ba |
GeglRegionBox *r2,
|
|
Packit Service |
2781ba |
GeglRegionBox *r2End,
|
|
Packit Service |
2781ba |
gint y1,
|
|
Packit Service |
2781ba |
gint y2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
int x1;
|
|
Packit Service |
2781ba |
int x2;
|
|
Packit Service |
2781ba |
GeglRegionBox *pNextRect;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
pNextRect = &pReg->rects[pReg->numRects];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
while ((r1 != r1End) && (r2 != r2End))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
x1 = MAX (r1->x1, r2->x1);
|
|
Packit Service |
2781ba |
x2 = MIN (r1->x2, r2->x2);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* If there's any overlap between the two rectangles, add that
|
|
Packit Service |
2781ba |
* overlap to the new region.
|
|
Packit Service |
2781ba |
* There's no need to check for subsumption because the only way
|
|
Packit Service |
2781ba |
* such a need could arise is if some region has two rectangles
|
|
Packit Service |
2781ba |
* right next to each other. Since that should never happen...
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (x1 < x2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_assert (y1 < y2);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
MEMCHECK (pReg, pNextRect, pReg->rects);
|
|
Packit Service |
2781ba |
pNextRect->x1 = x1;
|
|
Packit Service |
2781ba |
pNextRect->y1 = y1;
|
|
Packit Service |
2781ba |
pNextRect->x2 = x2;
|
|
Packit Service |
2781ba |
pNextRect->y2 = y2;
|
|
Packit Service |
2781ba |
pReg->numRects += 1;
|
|
Packit Service |
2781ba |
pNextRect++;
|
|
Packit Service |
2781ba |
g_assert (pReg->numRects <= pReg->size);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Need to advance the pointers. Shift the one that extends
|
|
Packit Service |
2781ba |
* to the right the least, since the other still has a chance to
|
|
Packit Service |
2781ba |
* overlap with that region's next rectangle, if you see what I mean.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (r1->x2 < r2->x2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r1++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else if (r2->x2 < r1->x2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r2++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r1++;
|
|
Packit Service |
2781ba |
r2++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_intersect:
|
|
Packit Service |
2781ba |
* @source1: a #GeglRegion
|
|
Packit Service |
2781ba |
* @source2: another #GeglRegion
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Sets the area of @source1 to the intersection of the areas of @source1
|
|
Packit Service |
2781ba |
* and @source2. The resulting area is the set of pixels contained in
|
|
Packit Service |
2781ba |
* both @source1 and @source2.
|
|
Packit Service |
2781ba |
**/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_intersect (GeglRegion *source1,
|
|
Packit Service |
2781ba |
const GeglRegion *source2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_return_if_fail (source1 != NULL);
|
|
Packit Service |
2781ba |
g_return_if_fail (source2 != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* check for trivial reject */
|
|
Packit Service |
2781ba |
if ((!(source1->numRects)) || (!(source2->numRects)) ||
|
|
Packit Service |
2781ba |
(!EXTENTCHECK (&source1->extents, &source2->extents)))
|
|
Packit Service |
2781ba |
source1->numRects = 0;
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
miRegionOp (source1, source1, source2,
|
|
Packit Service |
2781ba |
miIntersectO, (nonOverlapFunc) NULL, (nonOverlapFunc) NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Can't alter source1's extents before miRegionOp depends on the
|
|
Packit Service |
2781ba |
* extents of the regions being unchanged. Besides, this way there's
|
|
Packit Service |
2781ba |
* no checking against rectangles that will be nuked due to
|
|
Packit Service |
2781ba |
* coalescing, so we have to examine fewer rectangles.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
miSetExtents (source1);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
miRegionCopy (GeglRegion *dstrgn,
|
|
Packit Service |
2781ba |
const GeglRegion *rgn)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (dstrgn != rgn) /* don't want to copy to itself */
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (dstrgn->size < rgn->numRects)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (dstrgn->rects != &dstrgn->extents)
|
|
Packit Service |
2781ba |
g_free (dstrgn->rects);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
dstrgn->rects = g_new (GeglRegionBox, rgn->numRects);
|
|
Packit Service |
2781ba |
dstrgn->size = rgn->numRects;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
dstrgn->numRects = rgn->numRects;
|
|
Packit Service |
2781ba |
dstrgn->extents = rgn->extents;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
memcpy (dstrgn->rects, rgn->rects, rgn->numRects * sizeof (GeglRegionBox));
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*======================================================================
|
|
Packit Service |
2781ba |
* Generic Region Operator
|
|
Packit Service |
2781ba |
*====================================================================*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*-
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
* miCoalesce --
|
|
Packit Service |
2781ba |
* Attempt to merge the boxes in the current band with those in the
|
|
Packit Service |
2781ba |
* previous one. Used only by miRegionOp.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Results:
|
|
Packit Service |
2781ba |
* The new index for the previous band.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Side Effects:
|
|
Packit Service |
2781ba |
* If coalescing takes place:
|
|
Packit Service |
2781ba |
* - rectangles in the previous band will have their y2 fields
|
|
Packit Service |
2781ba |
* altered.
|
|
Packit Service |
2781ba |
* - pReg->numRects will be decreased.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
/* static int*/
|
|
Packit Service |
2781ba |
static int
|
|
Packit Service |
2781ba |
miCoalesce (GeglRegion *pReg, /* Region to coalesce */
|
|
Packit Service |
2781ba |
gint prevStart, /* Index of start of previous band */
|
|
Packit Service |
2781ba |
gint curStart) /* Index of start of current band */
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegionBox *pPrevBox; /* Current box in previous band */
|
|
Packit Service |
2781ba |
GeglRegionBox *pCurBox; /* Current box in current band */
|
|
Packit Service |
2781ba |
GeglRegionBox *pRegEnd; /* End of region */
|
|
Packit Service |
2781ba |
int curNumRects; /* Number of rectangles in current
|
|
Packit Service |
2781ba |
* band */
|
|
Packit Service |
2781ba |
int prevNumRects; /* Number of rectangles in previous
|
|
Packit Service |
2781ba |
* band */
|
|
Packit Service |
2781ba |
int bandY1; /* Y1 coordinate for current band */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
pRegEnd = &pReg->rects[pReg->numRects];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
pPrevBox = &pReg->rects[prevStart];
|
|
Packit Service |
2781ba |
prevNumRects = curStart - prevStart;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Figure out how many rectangles are in the current band. Have to do
|
|
Packit Service |
2781ba |
* this because multiple bands could have been added in miRegionOp
|
|
Packit Service |
2781ba |
* at the end when one region has been exhausted.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
pCurBox = &pReg->rects[curStart];
|
|
Packit Service |
2781ba |
bandY1 = pCurBox->y1;
|
|
Packit Service |
2781ba |
for (curNumRects = 0;
|
|
Packit Service |
2781ba |
(pCurBox != pRegEnd) && (pCurBox->y1 == bandY1);
|
|
Packit Service |
2781ba |
curNumRects++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
pCurBox++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (pCurBox != pRegEnd)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* If more than one band was added, we have to find the start
|
|
Packit Service |
2781ba |
* of the last band added so the next coalescing job can start
|
|
Packit Service |
2781ba |
* at the right place... (given when multiple bands are added,
|
|
Packit Service |
2781ba |
* this may be pointless -- see above).
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
pRegEnd--;
|
|
Packit Service |
2781ba |
while (pRegEnd[-1].y1 == pRegEnd->y1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
pRegEnd--;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
curStart = pRegEnd - pReg->rects;
|
|
Packit Service |
2781ba |
pRegEnd = pReg->rects + pReg->numRects;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if ((curNumRects == prevNumRects) && (curNumRects != 0))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
pCurBox -= curNumRects;
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* The bands may only be coalesced if the bottom of the previous
|
|
Packit Service |
2781ba |
* matches the top scanline of the current.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (pPrevBox->y2 == pCurBox->y1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Make sure the bands have boxes in the same places. This
|
|
Packit Service |
2781ba |
* assumes that boxes have been added in such a way that they
|
|
Packit Service |
2781ba |
* cover the most area possible. I.e. two boxes in a band must
|
|
Packit Service |
2781ba |
* have some horizontal space between them.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
do
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if ((pPrevBox->x1 != pCurBox->x1) ||
|
|
Packit Service |
2781ba |
(pPrevBox->x2 != pCurBox->x2))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* The bands don't line up so they can't be coalesced.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
return (curStart);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
pPrevBox++;
|
|
Packit Service |
2781ba |
pCurBox++;
|
|
Packit Service |
2781ba |
prevNumRects -= 1;
|
|
Packit Service |
2781ba |
} while (prevNumRects != 0);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
pReg->numRects -= curNumRects;
|
|
Packit Service |
2781ba |
pCurBox -= curNumRects;
|
|
Packit Service |
2781ba |
pPrevBox -= curNumRects;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* The bands may be merged, so set the bottom y of each box
|
|
Packit Service |
2781ba |
* in the previous band to that of the corresponding box in
|
|
Packit Service |
2781ba |
* the current band.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
do
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
pPrevBox->y2 = pCurBox->y2;
|
|
Packit Service |
2781ba |
pPrevBox++;
|
|
Packit Service |
2781ba |
pCurBox++;
|
|
Packit Service |
2781ba |
curNumRects -= 1;
|
|
Packit Service |
2781ba |
} while (curNumRects != 0);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* If only one band was added to the region, we have to backup
|
|
Packit Service |
2781ba |
* curStart to the start of the previous band.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* If more than one band was added to the region, copy the
|
|
Packit Service |
2781ba |
* other bands down. The assumption here is that the other bands
|
|
Packit Service |
2781ba |
* came from the same region as the current one and no further
|
|
Packit Service |
2781ba |
* coalescing can be done on them since it's all been done
|
|
Packit Service |
2781ba |
* already... curStart is already in the right place.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (pCurBox == pRegEnd)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
curStart = prevStart;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
do
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
*pPrevBox++ = *pCurBox++;
|
|
Packit Service |
2781ba |
} while (pCurBox != pRegEnd);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
return curStart;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*-
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
* miRegionOp --
|
|
Packit Service |
2781ba |
* Apply an operation to two regions. Called by miUnion, miInverse,
|
|
Packit Service |
2781ba |
* miSubtract, miIntersect...
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Results:
|
|
Packit Service |
2781ba |
* None.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Side Effects:
|
|
Packit Service |
2781ba |
* The new region is overwritten.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Notes:
|
|
Packit Service |
2781ba |
* The idea behind this function is to view the two regions as sets.
|
|
Packit Service |
2781ba |
* Together they cover a rectangle of area that this function divides
|
|
Packit Service |
2781ba |
* into horizontal bands where points are covered only by one region
|
|
Packit Service |
2781ba |
* or by both. For the first case, the nonOverlapFunc is called with
|
|
Packit Service |
2781ba |
* each the band and the band's upper and lower extents. For the
|
|
Packit Service |
2781ba |
* second, the overlapFunc is called to process the entire band. It
|
|
Packit Service |
2781ba |
* is responsible for clipping the rectangles in the band, though
|
|
Packit Service |
2781ba |
* this function provides the boundaries.
|
|
Packit Service |
2781ba |
* At the end of each band, the new region is coalesced, if possible,
|
|
Packit Service |
2781ba |
* to reduce the number of rectangles in the region.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
/* static void*/
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
miRegionOp (GeglRegion *newReg,
|
|
Packit Service |
2781ba |
GeglRegion *reg1,
|
|
Packit Service |
2781ba |
const GeglRegion *reg2,
|
|
Packit Service |
2781ba |
overlapFunc overlapFn, /* Function to call for over-
|
|
Packit Service |
2781ba |
* lapping bands */
|
|
Packit Service |
2781ba |
nonOverlapFunc nonOverlap1Fn, /* Function to call for non-
|
|
Packit Service |
2781ba |
* overlapping bands in region
|
|
Packit Service |
2781ba |
* 1 */
|
|
Packit Service |
2781ba |
nonOverlapFunc nonOverlap2Fn) /* Function to call for non-
|
|
Packit Service |
2781ba |
* overlapping bands in region
|
|
Packit Service |
2781ba |
* 2 */
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegionBox *r1; /* Pointer into first region */
|
|
Packit Service |
2781ba |
GeglRegionBox *r2; /* Pointer into 2d region */
|
|
Packit Service |
2781ba |
GeglRegionBox *r1End; /* End of 1st region */
|
|
Packit Service |
2781ba |
GeglRegionBox *r2End; /* End of 2d region */
|
|
Packit Service |
2781ba |
int ybot; /* Bottom of intersection */
|
|
Packit Service |
2781ba |
int ytop; /* Top of intersection */
|
|
Packit Service |
2781ba |
GeglRegionBox *oldRects; /* Old rects for newReg */
|
|
Packit Service |
2781ba |
int prevBand; /* Index of start of
|
|
Packit Service |
2781ba |
* previous band in newReg */
|
|
Packit Service |
2781ba |
int curBand; /* Index of start of current
|
|
Packit Service |
2781ba |
* band in newReg */
|
|
Packit Service |
2781ba |
GeglRegionBox *r1BandEnd; /* End of current band in r1 */
|
|
Packit Service |
2781ba |
GeglRegionBox *r2BandEnd; /* End of current band in r2 */
|
|
Packit Service |
2781ba |
int top; /* Top of non-overlapping
|
|
Packit Service |
2781ba |
* band */
|
|
Packit Service |
2781ba |
int bot; /* Bottom of non-overlapping
|
|
Packit Service |
2781ba |
* band */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Initialization:
|
|
Packit Service |
2781ba |
* set r1, r2, r1End and r2End appropriately, preserve the important
|
|
Packit Service |
2781ba |
* parts of the destination region until the end in case it's one of
|
|
Packit Service |
2781ba |
* the two source regions, then mark the "new" region empty, allocating
|
|
Packit Service |
2781ba |
* another array of rectangles for it to use.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
r1 = reg1->rects;
|
|
Packit Service |
2781ba |
r2 = reg2->rects;
|
|
Packit Service |
2781ba |
r1End = r1 + reg1->numRects;
|
|
Packit Service |
2781ba |
r2End = r2 + reg2->numRects;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
oldRects = newReg->rects;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
EMPTY_REGION (newReg);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Allocate a reasonable number of rectangles for the new region. The idea
|
|
Packit Service |
2781ba |
* is to allocate enough so the individual functions don't need to
|
|
Packit Service |
2781ba |
* reallocate and copy the array, which is time consuming, yet we don't
|
|
Packit Service |
2781ba |
* have to worry about using too much memory. I hope to be able to
|
|
Packit Service |
2781ba |
* nuke the Xrealloc() at the end of this function eventually.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
newReg->size = MAX (reg1->numRects, reg2->numRects) * 2;
|
|
Packit Service |
2781ba |
newReg->rects = g_new (GeglRegionBox, newReg->size);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Initialize ybot and ytop.
|
|
Packit Service |
2781ba |
* In the upcoming loop, ybot and ytop serve different functions depending
|
|
Packit Service |
2781ba |
* on whether the band being handled is an overlapping or non-overlapping
|
|
Packit Service |
2781ba |
* band.
|
|
Packit Service |
2781ba |
* In the case of a non-overlapping band (only one of the regions
|
|
Packit Service |
2781ba |
* has points in the band), ybot is the bottom of the most recent
|
|
Packit Service |
2781ba |
* intersection and thus clips the top of the rectangles in that band.
|
|
Packit Service |
2781ba |
* ytop is the top of the next intersection between the two regions and
|
|
Packit Service |
2781ba |
* serves to clip the bottom of the rectangles in the current band.
|
|
Packit Service |
2781ba |
* For an overlapping band (where the two regions intersect), ytop clips
|
|
Packit Service |
2781ba |
* the top of the rectangles of both regions and ybot clips the bottoms.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (reg1->extents.y1 < reg2->extents.y1)
|
|
Packit Service |
2781ba |
ybot = reg1->extents.y1;
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
ybot = reg2->extents.y1;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* prevBand serves to mark the start of the previous band so rectangles
|
|
Packit Service |
2781ba |
* can be coalesced into larger rectangles. qv. miCoalesce, above.
|
|
Packit Service |
2781ba |
* In the beginning, there is no previous band, so prevBand == curBand
|
|
Packit Service |
2781ba |
* (curBand is set later on, of course, but the first band will always
|
|
Packit Service |
2781ba |
* start at index 0). prevBand and curBand must be indices because of
|
|
Packit Service |
2781ba |
* the possible expansion, and resultant moving, of the new region's
|
|
Packit Service |
2781ba |
* array of rectangles.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
prevBand = 0;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
do
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
curBand = newReg->numRects;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* This algorithm proceeds one source-band (as opposed to a
|
|
Packit Service |
2781ba |
* destination band, which is determined by where the two regions
|
|
Packit Service |
2781ba |
* intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
|
|
Packit Service |
2781ba |
* rectangle after the last one in the current band for their
|
|
Packit Service |
2781ba |
* respective regions.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
r1BandEnd = r1;
|
|
Packit Service |
2781ba |
while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r1BandEnd++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
r2BandEnd = r2;
|
|
Packit Service |
2781ba |
while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r2BandEnd++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* First handle the band that doesn't intersect, if any.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Note that attention is restricted to one band in the
|
|
Packit Service |
2781ba |
* non-intersecting region at once, so if a region has n
|
|
Packit Service |
2781ba |
* bands between the current position and the next place it overlaps
|
|
Packit Service |
2781ba |
* the other, this entire loop will be passed through n times.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (r1->y1 < r2->y1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
top = MAX (r1->y1, ybot);
|
|
Packit Service |
2781ba |
bot = MIN (r1->y2, r2->y1);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if ((top != bot) && (nonOverlap1Fn != (void (*)())NULL))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
(*nonOverlap1Fn)(newReg, r1, r1BandEnd, top, bot);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
ytop = r2->y1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else if (r2->y1 < r1->y1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
top = MAX (r2->y1, ybot);
|
|
Packit Service |
2781ba |
bot = MIN (r2->y2, r1->y1);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if ((top != bot) && (nonOverlap2Fn != (void (*)())NULL))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
(*nonOverlap2Fn)(newReg, r2, r2BandEnd, top, bot);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
ytop = r1->y1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
ytop = r1->y1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* If any rectangles got added to the region, try and coalesce them
|
|
Packit Service |
2781ba |
* with rectangles from the previous band. Note we could just do
|
|
Packit Service |
2781ba |
* this test in miCoalesce, but some machines incur a not
|
|
Packit Service |
2781ba |
* inconsiderable cost for function calls, so...
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (newReg->numRects != curBand)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
prevBand = miCoalesce (newReg, prevBand, curBand);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Now see if we've hit an intersecting band. The two bands only
|
|
Packit Service |
2781ba |
* intersect if ybot > ytop
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
ybot = MIN (r1->y2, r2->y2);
|
|
Packit Service |
2781ba |
curBand = newReg->numRects;
|
|
Packit Service |
2781ba |
if (ybot > ytop)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
(*overlapFn)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (newReg->numRects != curBand)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
prevBand = miCoalesce (newReg, prevBand, curBand);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* If we've finished with a band (y2 == ybot) we skip forward
|
|
Packit Service |
2781ba |
* in the region to the next band.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (r1->y2 == ybot)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r1 = r1BandEnd;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
if (r2->y2 == ybot)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r2 = r2BandEnd;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
} while ((r1 != r1End) && (r2 != r2End));
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Deal with whichever region still has rectangles left.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
curBand = newReg->numRects;
|
|
Packit Service |
2781ba |
if (r1 != r1End)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (nonOverlap1Fn != (nonOverlapFunc) NULL)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
do
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r1BandEnd = r1;
|
|
Packit Service |
2781ba |
while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r1BandEnd++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
(*nonOverlap1Fn)(newReg, r1, r1BandEnd,
|
|
Packit Service |
2781ba |
MAX (r1->y1, ybot), r1->y2);
|
|
Packit Service |
2781ba |
r1 = r1BandEnd;
|
|
Packit Service |
2781ba |
} while (r1 != r1End);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else if ((r2 != r2End) && (nonOverlap2Fn != (nonOverlapFunc) NULL))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
do
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r2BandEnd = r2;
|
|
Packit Service |
2781ba |
while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
r2BandEnd++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
(*nonOverlap2Fn)(newReg, r2, r2BandEnd,
|
|
Packit Service |
2781ba |
MAX (r2->y1, ybot), r2->y2);
|
|
Packit Service |
2781ba |
r2 = r2BandEnd;
|
|
Packit Service |
2781ba |
} while (r2 != r2End);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (newReg->numRects != curBand)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
(void) miCoalesce (newReg, prevBand, curBand);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* A bit of cleanup. To keep regions from growing without bound,
|
|
Packit Service |
2781ba |
* we shrink the array of rectangles to match the new number of
|
|
Packit Service |
2781ba |
* rectangles in the region. This never goes to 0, however...
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Only do this stuff if the number of rectangles allocated is more than
|
|
Packit Service |
2781ba |
* twice the number of rectangles in the region (a simple optimization...).
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (newReg->numRects < (newReg->size >> 1))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (REGION_NOT_EMPTY (newReg))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
newReg->size = newReg->numRects;
|
|
Packit Service |
2781ba |
newReg->rects = g_renew (GeglRegionBox, newReg->rects, newReg->size);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* No point in doing the extra work involved in an Xrealloc if
|
|
Packit Service |
2781ba |
* the region is empty
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
newReg->size = 1;
|
|
Packit Service |
2781ba |
g_free (newReg->rects);
|
|
Packit Service |
2781ba |
newReg->rects = &newReg->extents;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (oldRects != &newReg->extents)
|
|
Packit Service |
2781ba |
g_free (oldRects);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*======================================================================
|
|
Packit Service |
2781ba |
* Region Union
|
|
Packit Service |
2781ba |
*====================================================================*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*-
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
* miUnionNonO --
|
|
Packit Service |
2781ba |
* Handle a non-overlapping band for the union operation. Just
|
|
Packit Service |
2781ba |
* Adds the rectangles into the region. Doesn't have to check for
|
|
Packit Service |
2781ba |
* subsumption or anything.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Results:
|
|
Packit Service |
2781ba |
* None.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Side Effects:
|
|
Packit Service |
2781ba |
* pReg->numRects is incremented and the final rectangles overwritten
|
|
Packit Service |
2781ba |
* with the rectangles we're passed.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
miUnionNonO (GeglRegion *pReg,
|
|
Packit Service |
2781ba |
GeglRegionBox *r,
|
|
Packit Service |
2781ba |
GeglRegionBox *rEnd,
|
|
Packit Service |
2781ba |
gint y1,
|
|
Packit Service |
2781ba |
gint y2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegionBox *pNextRect;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
pNextRect = &pReg->rects[pReg->numRects];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (y1 < y2);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
while (r != rEnd)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_assert (r->x1 < r->x2);
|
|
Packit Service |
2781ba |
MEMCHECK (pReg, pNextRect, pReg->rects);
|
|
Packit Service |
2781ba |
pNextRect->x1 = r->x1;
|
|
Packit Service |
2781ba |
pNextRect->y1 = y1;
|
|
Packit Service |
2781ba |
pNextRect->x2 = r->x2;
|
|
Packit Service |
2781ba |
pNextRect->y2 = y2;
|
|
Packit Service |
2781ba |
pReg->numRects += 1;
|
|
Packit Service |
2781ba |
pNextRect++;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (pReg->numRects <= pReg->size);
|
|
Packit Service |
2781ba |
r++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*-
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
* miUnionO --
|
|
Packit Service |
2781ba |
* Handle an overlapping band for the union operation. Picks the
|
|
Packit Service |
2781ba |
* left-most rectangle each time and merges it into the region.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Results:
|
|
Packit Service |
2781ba |
* None.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Side Effects:
|
|
Packit Service |
2781ba |
* Rectangles are overwritten in pReg->rects and pReg->numRects will
|
|
Packit Service |
2781ba |
* be changed.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* static void*/
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
miUnionO (GeglRegion *pReg,
|
|
Packit Service |
2781ba |
GeglRegionBox *r1,
|
|
Packit Service |
2781ba |
GeglRegionBox *r1End,
|
|
Packit Service |
2781ba |
GeglRegionBox *r2,
|
|
Packit Service |
2781ba |
GeglRegionBox *r2End,
|
|
Packit Service |
2781ba |
gint y1,
|
|
Packit Service |
2781ba |
gint y2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegionBox *pNextRect;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
pNextRect = &pReg->rects[pReg->numRects];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#define MERGERECT(r) \
|
|
Packit Service |
2781ba |
if ((pReg->numRects != 0) && \
|
|
Packit Service |
2781ba |
(pNextRect[-1].y1 == y1) && \
|
|
Packit Service |
2781ba |
(pNextRect[-1].y2 == y2) && \
|
|
Packit Service |
2781ba |
(pNextRect[-1].x2 >= r->x1)) \
|
|
Packit Service |
2781ba |
{ \
|
|
Packit Service |
2781ba |
if (pNextRect[-1].x2 < r->x2) \
|
|
Packit Service |
2781ba |
{ \
|
|
Packit Service |
2781ba |
pNextRect[-1].x2 = r->x2; \
|
|
Packit Service |
2781ba |
g_assert (pNextRect[-1].x1 < pNextRect[-1].x2); \
|
|
Packit Service |
2781ba |
} \
|
|
Packit Service |
2781ba |
} \
|
|
Packit Service |
2781ba |
else \
|
|
Packit Service |
2781ba |
{ \
|
|
Packit Service |
2781ba |
MEMCHECK (pReg, pNextRect, pReg->rects); \
|
|
Packit Service |
2781ba |
pNextRect->y1 = y1; \
|
|
Packit Service |
2781ba |
pNextRect->y2 = y2; \
|
|
Packit Service |
2781ba |
pNextRect->x1 = r->x1; \
|
|
Packit Service |
2781ba |
pNextRect->x2 = r->x2; \
|
|
Packit Service |
2781ba |
pReg->numRects += 1; \
|
|
Packit Service |
2781ba |
pNextRect += 1; \
|
|
Packit Service |
2781ba |
} \
|
|
Packit Service |
2781ba |
g_assert (pReg->numRects <= pReg->size); \
|
|
Packit Service |
2781ba |
r++;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (y1 < y2);
|
|
Packit Service |
2781ba |
while ((r1 != r1End) && (r2 != r2End))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (r1->x1 < r2->x1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
MERGERECT (r1);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
MERGERECT (r2);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (r1 != r1End)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
do
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
MERGERECT (r1);
|
|
Packit Service |
2781ba |
} while (r1 != r1End);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else while (r2 != r2End)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
MERGERECT (r2);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_union:
|
|
Packit Service |
2781ba |
* @source1: a #GeglRegion
|
|
Packit Service |
2781ba |
* @source2: a #GeglRegion
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Sets the area of @source1 to the union of the areas of @source1 and
|
|
Packit Service |
2781ba |
* @source2. The resulting area is the set of pixels contained in
|
|
Packit Service |
2781ba |
* either @source1 or @source2.
|
|
Packit Service |
2781ba |
**/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_union (GeglRegion *source1,
|
|
Packit Service |
2781ba |
const GeglRegion *source2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_return_if_fail (source1 != NULL);
|
|
Packit Service |
2781ba |
g_return_if_fail (source2 != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* checks all the simple cases */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* source1 and source2 are the same or source2 is empty
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if ((source1 == source2) || (!(source2->numRects)))
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* source1 is empty
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (!(source1->numRects))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
miRegionCopy (source1, source2);
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* source1 completely subsumes source2
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if ((source1->numRects == 1) &&
|
|
Packit Service |
2781ba |
(source1->extents.x1 <= source2->extents.x1) &&
|
|
Packit Service |
2781ba |
(source1->extents.y1 <= source2->extents.y1) &&
|
|
Packit Service |
2781ba |
(source1->extents.x2 >= source2->extents.x2) &&
|
|
Packit Service |
2781ba |
(source1->extents.y2 >= source2->extents.y2))
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* source2 completely subsumes source1
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if ((source2->numRects == 1) &&
|
|
Packit Service |
2781ba |
(source2->extents.x1 <= source1->extents.x1) &&
|
|
Packit Service |
2781ba |
(source2->extents.y1 <= source1->extents.y1) &&
|
|
Packit Service |
2781ba |
(source2->extents.x2 >= source1->extents.x2) &&
|
|
Packit Service |
2781ba |
(source2->extents.y2 >= source1->extents.y2))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
miRegionCopy (source1, source2);
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
miRegionOp (source1, source1, source2, miUnionO,
|
|
Packit Service |
2781ba |
miUnionNonO, miUnionNonO);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
source1->extents.x1 = MIN (source1->extents.x1, source2->extents.x1);
|
|
Packit Service |
2781ba |
source1->extents.y1 = MIN (source1->extents.y1, source2->extents.y1);
|
|
Packit Service |
2781ba |
source1->extents.x2 = MAX (source1->extents.x2, source2->extents.x2);
|
|
Packit Service |
2781ba |
source1->extents.y2 = MAX (source1->extents.y2, source2->extents.y2);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*======================================================================
|
|
Packit Service |
2781ba |
* Region Subtraction
|
|
Packit Service |
2781ba |
*====================================================================*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*-
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
* miSubtractNonO --
|
|
Packit Service |
2781ba |
* Deal with non-overlapping band for subtraction. Any parts from
|
|
Packit Service |
2781ba |
* region 2 we discard. Anything from region 1 we add to the region.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Results:
|
|
Packit Service |
2781ba |
* None.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Side Effects:
|
|
Packit Service |
2781ba |
* pReg may be affected.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
/* static void*/
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
miSubtractNonO1 (GeglRegion *pReg,
|
|
Packit Service |
2781ba |
GeglRegionBox *r,
|
|
Packit Service |
2781ba |
GeglRegionBox *rEnd,
|
|
Packit Service |
2781ba |
gint y1,
|
|
Packit Service |
2781ba |
gint y2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegionBox *pNextRect;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
pNextRect = &pReg->rects[pReg->numRects];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (y1 < y2);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
while (r != rEnd)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_assert (r->x1 < r->x2);
|
|
Packit Service |
2781ba |
MEMCHECK (pReg, pNextRect, pReg->rects);
|
|
Packit Service |
2781ba |
pNextRect->x1 = r->x1;
|
|
Packit Service |
2781ba |
pNextRect->y1 = y1;
|
|
Packit Service |
2781ba |
pNextRect->x2 = r->x2;
|
|
Packit Service |
2781ba |
pNextRect->y2 = y2;
|
|
Packit Service |
2781ba |
pReg->numRects += 1;
|
|
Packit Service |
2781ba |
pNextRect++;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (pReg->numRects <= pReg->size);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
r++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*-
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
* miSubtractO --
|
|
Packit Service |
2781ba |
* Overlapping band subtraction. x1 is the left-most point not yet
|
|
Packit Service |
2781ba |
* checked.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Results:
|
|
Packit Service |
2781ba |
* None.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Side Effects:
|
|
Packit Service |
2781ba |
* pReg may have rectangles added to it.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
*-----------------------------------------------------------------------
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
/* static void*/
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
miSubtractO (GeglRegion *pReg,
|
|
Packit Service |
2781ba |
GeglRegionBox *r1,
|
|
Packit Service |
2781ba |
GeglRegionBox *r1End,
|
|
Packit Service |
2781ba |
GeglRegionBox *r2,
|
|
Packit Service |
2781ba |
GeglRegionBox *r2End,
|
|
Packit Service |
2781ba |
gint y1,
|
|
Packit Service |
2781ba |
gint y2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegionBox *pNextRect;
|
|
Packit Service |
2781ba |
int x1;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
x1 = r1->x1;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (y1 < y2);
|
|
Packit Service |
2781ba |
pNextRect = &pReg->rects[pReg->numRects];
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
while ((r1 != r1End) && (r2 != r2End))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (r2->x2 <= x1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Subtrahend missed the boat: go to next subtrahend.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
r2++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else if (r2->x1 <= x1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Subtrahend preceeds minuend: nuke left edge of minuend.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
x1 = r2->x2;
|
|
Packit Service |
2781ba |
if (x1 >= r1->x2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Minuend completely covered: advance to next minuend and
|
|
Packit Service |
2781ba |
* reset left fence to edge of new minuend.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
r1++;
|
|
Packit Service |
2781ba |
if (r1 != r1End)
|
|
Packit Service |
2781ba |
x1 = r1->x1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Subtrahend now used up since it doesn't extend beyond
|
|
Packit Service |
2781ba |
* minuend
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
r2++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else if (r2->x1 < r1->x2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Left part of subtrahend covers part of minuend: add uncovered
|
|
Packit Service |
2781ba |
* part of minuend to region and skip to next subtrahend.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
g_assert (x1 < r2->x1);
|
|
Packit Service |
2781ba |
MEMCHECK (pReg, pNextRect, pReg->rects);
|
|
Packit Service |
2781ba |
pNextRect->x1 = x1;
|
|
Packit Service |
2781ba |
pNextRect->y1 = y1;
|
|
Packit Service |
2781ba |
pNextRect->x2 = r2->x1;
|
|
Packit Service |
2781ba |
pNextRect->y2 = y2;
|
|
Packit Service |
2781ba |
pReg->numRects += 1;
|
|
Packit Service |
2781ba |
pNextRect++;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (pReg->numRects <= pReg->size);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
x1 = r2->x2;
|
|
Packit Service |
2781ba |
if (x1 >= r1->x2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Minuend used up: advance to new...
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
r1++;
|
|
Packit Service |
2781ba |
if (r1 != r1End)
|
|
Packit Service |
2781ba |
x1 = r1->x1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Subtrahend used up
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
r2++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Minuend used up: add any remaining piece before advancing.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
if (r1->x2 > x1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
MEMCHECK (pReg, pNextRect, pReg->rects);
|
|
Packit Service |
2781ba |
pNextRect->x1 = x1;
|
|
Packit Service |
2781ba |
pNextRect->y1 = y1;
|
|
Packit Service |
2781ba |
pNextRect->x2 = r1->x2;
|
|
Packit Service |
2781ba |
pNextRect->y2 = y2;
|
|
Packit Service |
2781ba |
pReg->numRects += 1;
|
|
Packit Service |
2781ba |
pNextRect++;
|
|
Packit Service |
2781ba |
g_assert (pReg->numRects <= pReg->size);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
r1++;
|
|
Packit Service |
2781ba |
if (r1 != r1End)
|
|
Packit Service |
2781ba |
x1 = r1->x1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Add remaining minuend rectangles to region.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
while (r1 != r1End)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_assert (x1 < r1->x2);
|
|
Packit Service |
2781ba |
MEMCHECK (pReg, pNextRect, pReg->rects);
|
|
Packit Service |
2781ba |
pNextRect->x1 = x1;
|
|
Packit Service |
2781ba |
pNextRect->y1 = y1;
|
|
Packit Service |
2781ba |
pNextRect->x2 = r1->x2;
|
|
Packit Service |
2781ba |
pNextRect->y2 = y2;
|
|
Packit Service |
2781ba |
pReg->numRects += 1;
|
|
Packit Service |
2781ba |
pNextRect++;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_assert (pReg->numRects <= pReg->size);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
r1++;
|
|
Packit Service |
2781ba |
if (r1 != r1End)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
x1 = r1->x1;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_subtract:
|
|
Packit Service |
2781ba |
* @source1: a #GeglRegion
|
|
Packit Service |
2781ba |
* @source2: another #GeglRegion
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Subtracts the area of @source2 from the area @source1. The resulting
|
|
Packit Service |
2781ba |
* area is the set of pixels contained in @source1 but not in @source2.
|
|
Packit Service |
2781ba |
**/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_subtract (GeglRegion *source1,
|
|
Packit Service |
2781ba |
const GeglRegion *source2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_return_if_fail (source1 != NULL);
|
|
Packit Service |
2781ba |
g_return_if_fail (source2 != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* check for trivial reject */
|
|
Packit Service |
2781ba |
if ((!(source1->numRects)) || (!(source2->numRects)) ||
|
|
Packit Service |
2781ba |
(!EXTENTCHECK (&source1->extents, &source2->extents)))
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
miRegionOp (source1, source1, source2, miSubtractO,
|
|
Packit Service |
2781ba |
miSubtractNonO1, (nonOverlapFunc) NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Can't alter source1's extents before we call miRegionOp because miRegionOp
|
|
Packit Service |
2781ba |
* depends on the extents of those regions being the unaltered. Besides, this
|
|
Packit Service |
2781ba |
* way there's no checking against rectangles that will be nuked
|
|
Packit Service |
2781ba |
* due to coalescing, so we have to examine fewer rectangles.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
miSetExtents (source1);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_xor:
|
|
Packit Service |
2781ba |
* @source1: a #GeglRegion
|
|
Packit Service |
2781ba |
* @source2: another #GeglRegion
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Sets the area of @source1 to the exclusive-OR of the areas of @source1
|
|
Packit Service |
2781ba |
* and @source2. The resulting area is the set of pixels contained in one
|
|
Packit Service |
2781ba |
* or the other of the two sources but not in both.
|
|
Packit Service |
2781ba |
**/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_xor (GeglRegion *source1,
|
|
Packit Service |
2781ba |
const GeglRegion *source2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegion *trb;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_if_fail (source1 != NULL);
|
|
Packit Service |
2781ba |
g_return_if_fail (source2 != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
trb = gegl_region_copy (source2);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_region_subtract (trb, source1);
|
|
Packit Service |
2781ba |
gegl_region_subtract (source1, source2);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_region_union (source1, trb);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_region_destroy (trb);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_empty:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Finds out if the #GeglRegion is empty.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Returns: %TRUE if @region is empty.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
gboolean
|
|
Packit Service |
2781ba |
gegl_region_empty (const GeglRegion *region)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
g_return_val_if_fail (region != NULL, FALSE);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (region->numRects == 0)
|
|
Packit Service |
2781ba |
return TRUE;
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
return FALSE;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_equal:
|
|
Packit Service |
2781ba |
* @region1: a #GeglRegion
|
|
Packit Service |
2781ba |
* @region2: a #GeglRegion
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Finds out if the two regions are the same.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Returns: %TRUE if @region1 and @region2 are equal.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
gboolean
|
|
Packit Service |
2781ba |
gegl_region_equal (const GeglRegion *region1,
|
|
Packit Service |
2781ba |
const GeglRegion *region2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
int i;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_val_if_fail (region1 != NULL, FALSE);
|
|
Packit Service |
2781ba |
g_return_val_if_fail (region2 != NULL, FALSE);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (region1->numRects != region2->numRects) return FALSE;
|
|
Packit Service |
2781ba |
else if (region1->numRects == 0) return TRUE;
|
|
Packit Service |
2781ba |
else if (region1->extents.x1 != region2->extents.x1) return FALSE;
|
|
Packit Service |
2781ba |
else if (region1->extents.x2 != region2->extents.x2) return FALSE;
|
|
Packit Service |
2781ba |
else if (region1->extents.y1 != region2->extents.y1) return FALSE;
|
|
Packit Service |
2781ba |
else if (region1->extents.y2 != region2->extents.y2) return FALSE;
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
for (i = 0; i < region1->numRects; i++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (region1->rects[i].x1 != region2->rects[i].x1) return FALSE;
|
|
Packit Service |
2781ba |
else if (region1->rects[i].x2 != region2->rects[i].x2) return FALSE;
|
|
Packit Service |
2781ba |
else if (region1->rects[i].y1 != region2->rects[i].y1) return FALSE;
|
|
Packit Service |
2781ba |
else if (region1->rects[i].y2 != region2->rects[i].y2) return FALSE;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
return TRUE;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_point_in:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion
|
|
Packit Service |
2781ba |
* @x: the x coordinate of a point
|
|
Packit Service |
2781ba |
* @y: the y coordinate of a point
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Finds out if a point is in a region.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Returns: %TRUE if the point is in @region.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
gboolean
|
|
Packit Service |
2781ba |
gegl_region_point_in (const GeglRegion *region,
|
|
Packit Service |
2781ba |
gint x,
|
|
Packit Service |
2781ba |
gint y)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
int i;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_val_if_fail (region != NULL, FALSE);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (region->numRects == 0)
|
|
Packit Service |
2781ba |
return FALSE;
|
|
Packit Service |
2781ba |
if (!INBOX (region->extents, x, y))
|
|
Packit Service |
2781ba |
return FALSE;
|
|
Packit Service |
2781ba |
for (i = 0; i < region->numRects; i++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (INBOX (region->rects[i], x, y))
|
|
Packit Service |
2781ba |
return TRUE;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
return FALSE;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_rect_in:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion.
|
|
Packit Service |
2781ba |
* @rectangle: a #GeglRectangle.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Tests whether a rectangle is within a region.
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Returns: %GEGL_OVERLAP_RECTANGLE_IN, %GEGL_OVERLAP_RECTANGLE_OUT, or
|
|
Packit Service |
2781ba |
* %GEGL_OVERLAP_RECTANGLE_PART, depending on whether the rectangle is inside,
|
|
Packit Service |
2781ba |
* outside, or partly inside the #GeglRegion, respectively.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
GeglOverlapType
|
|
Packit Service |
2781ba |
gegl_region_rect_in (const GeglRegion *region,
|
|
Packit Service |
2781ba |
const GeglRectangle *rectangle)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRegionBox *pbox;
|
|
Packit Service |
2781ba |
GeglRegionBox *pboxEnd;
|
|
Packit Service |
2781ba |
GeglRegionBox rect;
|
|
Packit Service |
2781ba |
GeglRegionBox *prect = ▭
|
|
Packit Service |
2781ba |
gboolean partIn, partOut;
|
|
Packit Service |
2781ba |
gint rx, ry;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_val_if_fail (region != NULL, GEGL_OVERLAP_RECTANGLE_OUT);
|
|
Packit Service |
2781ba |
g_return_val_if_fail (rectangle != NULL, GEGL_OVERLAP_RECTANGLE_OUT);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
rx = rectangle->x;
|
|
Packit Service |
2781ba |
ry = rectangle->y;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
prect->x1 = rx;
|
|
Packit Service |
2781ba |
prect->y1 = ry;
|
|
Packit Service |
2781ba |
prect->x2 = rx + rectangle->width;
|
|
Packit Service |
2781ba |
prect->y2 = ry + rectangle->height;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* this is (just) a useful optimization */
|
|
Packit Service |
2781ba |
if ((region->numRects == 0) || !EXTENTCHECK (®ion->extents, prect))
|
|
Packit Service |
2781ba |
return GEGL_OVERLAP_RECTANGLE_OUT;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
partOut = FALSE;
|
|
Packit Service |
2781ba |
partIn = FALSE;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */
|
|
Packit Service |
2781ba |
for (pbox = region->rects, pboxEnd = pbox + region->numRects;
|
|
Packit Service |
2781ba |
pbox < pboxEnd;
|
|
Packit Service |
2781ba |
pbox++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (pbox->y2 <= ry)
|
|
Packit Service |
2781ba |
continue;/* getting up to speed or skipping remainder of band */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (pbox->y1 > ry)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
partOut = TRUE; /* missed part of rectangle above */
|
|
Packit Service |
2781ba |
if (partIn || (pbox->y1 >= prect->y2))
|
|
Packit Service |
2781ba |
break;
|
|
Packit Service |
2781ba |
ry = pbox->y1; /* x guaranteed to be == prect->x1 */
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (pbox->x2 <= rx)
|
|
Packit Service |
2781ba |
continue;/* not far enough over yet */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (pbox->x1 > rx)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
partOut = TRUE; /* missed part of rectangle to left */
|
|
Packit Service |
2781ba |
if (partIn)
|
|
Packit Service |
2781ba |
break;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (pbox->x1 < prect->x2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
partIn = TRUE; /* definitely overlap */
|
|
Packit Service |
2781ba |
if (partOut)
|
|
Packit Service |
2781ba |
break;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (pbox->x2 >= prect->x2)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
ry = pbox->y2; /* finished with this band */
|
|
Packit Service |
2781ba |
if (ry >= prect->y2)
|
|
Packit Service |
2781ba |
break;
|
|
Packit Service |
2781ba |
rx = prect->x1; /* reset x out to left again */
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
else
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/*
|
|
Packit Service |
2781ba |
* Because boxes in a band are maximal width, if the first box
|
|
Packit Service |
2781ba |
* to overlap the rectangle doesn't completely cover it in that
|
|
Packit Service |
2781ba |
* band, the rectangle must be partially out, since some of it
|
|
Packit Service |
2781ba |
* will be uncovered in that band. partIn will have been set true
|
|
Packit Service |
2781ba |
* by now...
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
break;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
return (partIn ?
|
|
Packit Service |
2781ba |
((ry < prect->y2) ?
|
|
Packit Service |
2781ba |
GEGL_OVERLAP_RECTANGLE_PART : GEGL_OVERLAP_RECTANGLE_IN) :
|
|
Packit Service |
2781ba |
GEGL_OVERLAP_RECTANGLE_OUT);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
static void
|
|
Packit Service |
2781ba |
gegl_region_unsorted_spans_intersect_foreach (GeglRegion *region,
|
|
Packit Service |
2781ba |
GeglSpan *spans,
|
|
Packit Service |
2781ba |
int n_spans,
|
|
Packit Service |
2781ba |
GeglSpanFunc function,
|
|
Packit Service |
2781ba |
gpointer data)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gint i, left, right, y;
|
|
Packit Service |
2781ba |
gint clipped_left, clipped_right;
|
|
Packit Service |
2781ba |
GeglRegionBox *pbox;
|
|
Packit Service |
2781ba |
GeglRegionBox *pboxEnd;
|
|
Packit Service |
2781ba |
GeglSpan out_span;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (!region->numRects)
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
for (i = 0; i < n_spans; i++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
y = spans[i].y;
|
|
Packit Service |
2781ba |
left = spans[i].x;
|
|
Packit Service |
2781ba |
right = left + spans[i].width; /* right is not in the span! */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (!((region->extents.y1 <= y) &&
|
|
Packit Service |
2781ba |
(region->extents.y2 > y) &&
|
|
Packit Service |
2781ba |
(region->extents.x1 < right) &&
|
|
Packit Service |
2781ba |
(region->extents.x2 > left)))
|
|
Packit Service |
2781ba |
continue;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* can stop when we passed y */
|
|
Packit Service |
2781ba |
for (pbox = region->rects, pboxEnd = pbox + region->numRects;
|
|
Packit Service |
2781ba |
pbox < pboxEnd;
|
|
Packit Service |
2781ba |
pbox++)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
if (pbox->y2 <= y)
|
|
Packit Service |
2781ba |
continue;/* Not quite there yet */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (pbox->y1 > y)
|
|
Packit Service |
2781ba |
break;/* passed the spanline */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if ((right > pbox->x1) && (left < pbox->x2))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
clipped_left = MAX (left, pbox->x1);
|
|
Packit Service |
2781ba |
clipped_right = MIN (right, pbox->x2);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
out_span.y = y;
|
|
Packit Service |
2781ba |
out_span.x = clipped_left;
|
|
Packit Service |
2781ba |
out_span.width = clipped_right - clipped_left;
|
|
Packit Service |
2781ba |
(*function)(&out_span, data);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/**
|
|
Packit Service |
2781ba |
* gegl_region_spans_intersect_foreach:
|
|
Packit Service |
2781ba |
* @region: a #GeglRegion
|
|
Packit Service |
2781ba |
* @spans: an array of #GeglSpans
|
|
Packit Service |
2781ba |
* @n_spans: the length of @spans
|
|
Packit Service |
2781ba |
* @sorted: %TRUE if @spans is sorted wrt. the y coordinate
|
|
Packit Service |
2781ba |
* @function: function to call on each span in the intersection
|
|
Packit Service |
2781ba |
* @data: data to pass to @function
|
|
Packit Service |
2781ba |
*
|
|
Packit Service |
2781ba |
* Calls a function on each span in the intersection of @region and @spans.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_spans_intersect_foreach (GeglRegion *region,
|
|
Packit Service |
2781ba |
GeglSpan *spans,
|
|
Packit Service |
2781ba |
int n_spans,
|
|
Packit Service |
2781ba |
gboolean sorted,
|
|
Packit Service |
2781ba |
GeglSpanFunc function,
|
|
Packit Service |
2781ba |
gpointer data)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gint left, right, y;
|
|
Packit Service |
2781ba |
gint clipped_left, clipped_right;
|
|
Packit Service |
2781ba |
GeglRegionBox *pbox;
|
|
Packit Service |
2781ba |
GeglRegionBox *pboxEnd;
|
|
Packit Service |
2781ba |
GeglSpan *span, *tmpspan;
|
|
Packit Service |
2781ba |
GeglSpan *end_span;
|
|
Packit Service |
2781ba |
GeglSpan out_span;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_return_if_fail (region != NULL);
|
|
Packit Service |
2781ba |
g_return_if_fail (spans != NULL);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if (!sorted)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
gegl_region_unsorted_spans_intersect_foreach (region,
|
|
Packit Service |
2781ba |
spans,
|
|
Packit Service |
2781ba |
n_spans,
|
|
Packit Service |
2781ba |
function,
|
|
Packit Service |
2781ba |
data);
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if ((!region->numRects) || (n_spans == 0))
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* The main method here is to step along the
|
|
Packit Service |
2781ba |
* sorted rectangles and spans in lock step, and
|
|
Packit Service |
2781ba |
* clipping the spans that are in the current
|
|
Packit Service |
2781ba |
* rectangle before going on to the next rectangle.
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
span = spans;
|
|
Packit Service |
2781ba |
end_span = spans + n_spans;
|
|
Packit Service |
2781ba |
pbox = region->rects;
|
|
Packit Service |
2781ba |
pboxEnd = pbox + region->numRects;
|
|
Packit Service |
2781ba |
while (pbox < pboxEnd)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
while ((pbox->y2 < span->y) || (span->y < pbox->y1))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
/* Skip any rectangles that are above the current span */
|
|
Packit Service |
2781ba |
if (pbox->y2 < span->y)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
pbox++;
|
|
Packit Service |
2781ba |
if (pbox == pboxEnd)
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
/* Skip any spans that are above the current rectangle */
|
|
Packit Service |
2781ba |
if (span->y < pbox->y1)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
span++;
|
|
Packit Service |
2781ba |
if (span == end_span)
|
|
Packit Service |
2781ba |
return;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* Ok, we got at least one span that might intersect this rectangle. */
|
|
Packit Service |
2781ba |
tmpspan = span;
|
|
Packit Service |
2781ba |
while ((tmpspan < end_span) &&
|
|
Packit Service |
2781ba |
(tmpspan->y < pbox->y2))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
y = tmpspan->y;
|
|
Packit Service |
2781ba |
left = tmpspan->x;
|
|
Packit Service |
2781ba |
right = left + tmpspan->width; /* right is not in the span! */
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
if ((right > pbox->x1) && (left < pbox->x2))
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
clipped_left = MAX (left, pbox->x1);
|
|
Packit Service |
2781ba |
clipped_right = MIN (right, pbox->x2);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
out_span.y = y;
|
|
Packit Service |
2781ba |
out_span.x = clipped_left;
|
|
Packit Service |
2781ba |
out_span.width = clipped_right - clipped_left;
|
|
Packit Service |
2781ba |
(*function)(&out_span, data);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
tmpspan++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
/* Finished this rectangle.
|
|
Packit Service |
2781ba |
* The spans could still intersect the next one
|
|
Packit Service |
2781ba |
*/
|
|
Packit Service |
2781ba |
pbox++;
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
void
|
|
Packit Service |
2781ba |
gegl_region_dump (GeglRegion *region)
|
|
Packit Service |
2781ba |
{
|
|
Packit Service |
2781ba |
GeglRectangle *rectangles = NULL;
|
|
Packit Service |
2781ba |
gint n_rectangles = 0;
|
|
Packit Service |
2781ba |
gint i;
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
gegl_region_get_rectangles (region, &rectangles, &n_rectangles);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_print ("GeglRegion %p:\n", region);
|
|
Packit Service |
2781ba |
for (i = 0; i < n_rectangles; i++)
|
|
Packit Service |
2781ba |
g_print (" { %d, %d, %dx%d },\n",
|
|
Packit Service |
2781ba |
rectangles[i].x,
|
|
Packit Service |
2781ba |
rectangles[i].y,
|
|
Packit Service |
2781ba |
rectangles[i].width,
|
|
Packit Service |
2781ba |
rectangles[i].height);
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
g_free (rectangles);
|
|
Packit Service |
2781ba |
}
|
|
Packit Service |
2781ba |
|
|
Packit Service |
2781ba |
#define __GEGL_REGION_GENERIC_C__
|