Blame gdk/gdkregion-generic.c

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