/////////////////////////////////////////////////////////////////////////////
-// Name: generic/region.cpp
+// Name: src/generic/region.cpp
// Purpose: generic wxRegion class
// Author: David Elliott
// Modified by:
// Created: 2004/04/12
// RCS-ID: $Id$
// Copyright: (c) 2004 David Elliott
-// Licence: wxWindows licence
+// Licence: wxWindows licence
/////////////////////////////////////////////////////////////////////////////
-#include "wx/generic/region.h"
-#include "wx/utils.h"
+
+// For compilers that support precompilation, includes "wx.h".
+#include "wx/wxprec.h"
+
+#ifdef __BORLANDC__
+ #pragma hdrstop
+#endif
+
+#include "wx/region.h"
+
+#ifndef WX_PRECOMP
+ #include "wx/utils.h"
+#endif
// ========================================================================
// Classes to interface with X.org code
public:
// Default constructor initializes nothing
REGION() {}
+
REGION(const wxRect& rect)
{
rects = &extents;
extents.y2 = rect.y + rect.height;
size = 1;
}
- BoxPtr GetBox(int i) { if(i<numRects) return rects+i; else return NULL; }
+
+ BoxPtr GetBox(int i)
+ {
+ return i < numRects ? rects + i : NULL;
+ }
// X.org methods
static bool XClipBox(
register int x,
register int y);
static bool XIntersectRegion(
- Region reg1,
- Region reg2, /* source regions */
- register Region newReg); /* destination Region */
+ Region reg1,
+ Region reg2, /* source regions */
+ register Region newReg); /* destination Region */
static bool XUnionRegion(
- Region reg1,
- Region reg2, /* source regions */
- Region newReg); /* destination Region */
+ Region reg1,
+ Region reg2, /* source regions */
+ Region newReg); /* destination Region */
static bool XSubtractRegion(
- Region regM,
- Region regS,
- register Region regD);
+ Region regM,
+ Region regS,
+ register Region regD);
static bool XXorRegion(Region sra, Region srb, Region dr);
static bool XEmptyRegion(
Region r);
Region pRegion,
int x, int y);
static wxRegionContain XRectInRegion(
- register Region region,
+ register Region region,
int rx, int ry,
unsigned int rwidth, unsigned int rheight);
protected:
static Region XCreateRegion(void);
static void miSetExtents (
- Region pReg);
+ Region pReg);
static bool XDestroyRegion(Region r);
static int miIntersectO (
- register Region pReg,
- register BoxPtr r1,
- BoxPtr r1End,
- register BoxPtr r2,
- BoxPtr r2End,
- wxCoord y1,
- wxCoord y2);
+ register Region pReg,
+ register BoxPtr r1,
+ BoxPtr r1End,
+ register BoxPtr r2,
+ BoxPtr r2End,
+ wxCoord y1,
+ wxCoord y2);
static void miRegionCopy(
register Region dstrgn,
register Region rgn);
static int miCoalesce(
- register Region pReg, /* Region to coalesce */
- int prevStart, /* Index of start of previous band */
- int curStart); /* Index of start of current band */
+ register Region pReg, /* Region to coalesce */
+ int prevStart, /* Index of start of previous band */
+ int curStart); /* Index of start of current band */
static void miRegionOp(
- register Region newReg, /* Place to store result */
- Region reg1, /* First region in operation */
- Region reg2, /* 2d region in operation */
- int (*overlapFunc)(
+ register Region newReg, /* Place to store result */
+ Region reg1, /* First region in operation */
+ Region reg2, /* 2d region in operation */
+ int (*overlapFunc)(
register Region pReg,
register BoxPtr r1,
BoxPtr r1End,
register BoxPtr r2,
BoxPtr r2End,
- wxCoord y1,
- wxCoord y2), /* Function to call for over-
- * lapping bands */
- int (*nonOverlap1Func)(
+ wxCoord y1,
+ wxCoord y2), /* Function to call for over-
+ * lapping bands */
+ int (*nonOverlap1Func)(
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
- register wxCoord y1,
- register wxCoord y2), /* Function to call for non-
- * overlapping bands in region
- * 1 */
- int (*nonOverlap2Func)(
+ register wxCoord y1,
+ register wxCoord y2), /* Function to call for non-
+ * overlapping bands in region
+ * 1 */
+ int (*nonOverlap2Func)(
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
- register wxCoord y1,
- register wxCoord y2)); /* Function to call for non-
- * overlapping bands in region
- * 2 */
+ register wxCoord y1,
+ register wxCoord y2)); /* Function to call for non-
+ * overlapping bands in region
+ * 2 */
static int miUnionNonO (
- register Region pReg,
- register BoxPtr r,
- BoxPtr rEnd,
- register wxCoord y1,
- register wxCoord y2);
+ register Region pReg,
+ register BoxPtr r,
+ BoxPtr rEnd,
+ register wxCoord y1,
+ register wxCoord y2);
static int miUnionO (
- register Region pReg,
- register BoxPtr r1,
- BoxPtr r1End,
- register BoxPtr r2,
- BoxPtr r2End,
- register wxCoord y1,
- register wxCoord y2);
+ register Region pReg,
+ register BoxPtr r1,
+ BoxPtr r1End,
+ register BoxPtr r2,
+ BoxPtr r2End,
+ register wxCoord y1,
+ register wxCoord y2);
static int miSubtractNonO1 (
- register Region pReg,
- register BoxPtr r,
- BoxPtr rEnd,
- register wxCoord y1,
- register wxCoord y2);
+ register Region pReg,
+ register BoxPtr r,
+ BoxPtr rEnd,
+ register wxCoord y1,
+ register wxCoord y2);
static int miSubtractO (
- register Region pReg,
- register BoxPtr r1,
- BoxPtr r1End,
- register BoxPtr r2,
- BoxPtr r2End,
- register wxCoord y1,
- register wxCoord y2);
+ register Region pReg,
+ register BoxPtr r1,
+ BoxPtr r1End,
+ register BoxPtr r2,
+ BoxPtr r2End,
+ register wxCoord y1,
+ register wxCoord y2);
protected:
long size;
long numRects;
// ========================================================================
// wxRegionRefData
// ========================================================================
-class wxRegionRefData : public wxObjectRefData, public REGION
+
+class wxRegionRefData : public wxGDIRefData,
+ public REGION
{
public:
wxRegionRefData()
- /* XCreateRegion */
- { size = 1;
+ : wxGDIRefData(),
+ REGION()
+ {
+ size = 1;
numRects = 0;
- rects = NULL;
+ rects = ( BOX * )malloc( (unsigned) sizeof( BOX ));
extents.x1 = 0;
extents.x2 = 0;
extents.y1 = 0;
extents.y2 = 0;
}
+
wxRegionRefData(const wxPoint& topLeft, const wxPoint& bottomRight)
- : wxObjectRefData()
- , REGION()
- { rects = (BOX*)malloc(sizeof(BOX));
+ : wxGDIRefData(),
+ REGION()
+ {
+ rects = (BOX*)malloc(sizeof(BOX));
size = 1;
numRects = 1;
extents.x1 = topLeft.x;
extents.y2 = bottomRight.y;
*rects = extents;
}
+
wxRegionRefData(const wxRect& rect)
- : wxObjectRefData()
- , REGION(rect)
- { rects = (BOX*)malloc(sizeof(BOX));
+ : wxGDIRefData(),
+ REGION(rect)
+ {
+ rects = (BOX*)malloc(sizeof(BOX));
*rects = extents;
}
+
wxRegionRefData(const wxRegionRefData& refData)
- : wxObjectRefData()
- , REGION()
+ : wxGDIRefData(),
+ REGION()
{
size = refData.size;
numRects = refData.numRects;
rects = (Box*)malloc(numRects*sizeof(Box));
+ memcpy(rects, refData.rects, numRects*sizeof(Box));
extents = refData.extents;
}
- ~wxRegionRefData()
+
+ virtual ~wxRegionRefData()
{
free(rects);
}
+
private:
// Don't allow this
wxRegionRefData(const REGION&);
// ========================================================================
// wxRegionGeneric
// ========================================================================
-//IMPLEMENT_DYNAMIC_CLASS(wxRegionGeneric, wxGDIObject);
+//IMPLEMENT_DYNAMIC_CLASS(wxRegionGeneric, wxGDIObject)
#define M_REGIONDATA ((wxRegionRefData *)m_refData)
#define M_REGIONDATA_OF(rgn) ((wxRegionRefData *)(rgn.m_refData))
void wxRegionGeneric::Clear()
{
UnRef();
+ if (!m_refData)
+ m_refData = new wxRegionRefData(wxRect(0,0,0,0));
}
-wxObjectRefData *wxRegionGeneric::CreateRefData() const
+wxGDIRefData *wxRegionGeneric::CreateGDIRefData() const
{
return new wxRegionRefData;
}
-wxObjectRefData *wxRegionGeneric::CloneRefData(const wxObjectRefData *data) const
+wxGDIRefData *wxRegionGeneric::CloneGDIRefData(const wxGDIRefData *data) const
{
return new wxRegionRefData(*(wxRegionRefData *)data);
}
-bool wxRegionGeneric::operator== (const wxRegionGeneric& region)
+bool wxRegionGeneric::DoIsEqual(const wxRegion& region) const
{
- wxASSERT(m_refData && region.m_refData);
return REGION::XEqualRegion(M_REGIONDATA,M_REGIONDATA_OF(region));
}
-wxRect wxRegionGeneric::GetBox() const
+bool wxRegionGeneric::DoGetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
{
- wxASSERT(m_refData);
- wxRect rect;
- REGION::XClipBox(M_REGIONDATA,&rect);
- return rect;
-}
+ if ( !m_refData )
+ return false;
-void wxRegionGeneric::GetBox(wxCoord& x, wxCoord& y, wxCoord&w, wxCoord &h) const
-{
- wxASSERT(m_refData);
wxRect rect;
REGION::XClipBox(M_REGIONDATA,&rect);
x = rect.x;
y = rect.y;
w = rect.width;
h = rect.height;
+ return true;
}
// ----------------------------------------------------------------------------
// wxRegionGeneric operations
// ----------------------------------------------------------------------------
-bool wxRegionGeneric::Union(const wxRect& rect)
-/* XUnionRectWithRegion */
+bool wxRegionGeneric::DoUnionWithRect(const wxRect& rect)
{
- if (!rect.width || !rect.height)
- return false;
+ if ( rect.IsEmpty() )
+ {
+ // nothing to do
+ return true;
+ }
AllocExclusive();
REGION region(rect);
return REGION::XUnionRegion(®ion,M_REGIONDATA,M_REGIONDATA);
}
-bool wxRegionGeneric::Union(const wxRegionGeneric& region)
+bool wxRegionGeneric::DoUnionWithRegion(const wxRegion& region)
{
AllocExclusive();
return REGION::XUnionRegion(M_REGIONDATA_OF(region),M_REGIONDATA,M_REGIONDATA);
}
-bool wxRegionGeneric::Intersect(const wxRect& rect)
-{
- if (!rect.width || !rect.height)
- return false;
- AllocExclusive();
- REGION region(rect);
-
- return REGION::XIntersectRegion(®ion,M_REGIONDATA,M_REGIONDATA);
-}
-
-bool wxRegionGeneric::Intersect(const wxRegionGeneric& region)
+bool wxRegionGeneric::DoIntersect(const wxRegion& region)
{
AllocExclusive();
return REGION::XIntersectRegion(M_REGIONDATA_OF(region),M_REGIONDATA,M_REGIONDATA);
}
-bool wxRegionGeneric::Subtract(const wxRect& rect)
+bool wxRegionGeneric::DoSubtract(const wxRegion& region)
{
- if (!rect.width || !rect.height)
- return false;
- AllocExclusive();
- REGION region(rect);
-
- return REGION::XSubtractRegion(®ion,M_REGIONDATA,M_REGIONDATA);
-}
+ if ( region.IsEmpty() )
+ {
+ // nothing to do
+ return true;
+ }
-bool wxRegionGeneric::Subtract(const wxRegionGeneric& region)
-{
return REGION::XSubtractRegion(M_REGIONDATA_OF(region),M_REGIONDATA,M_REGIONDATA);
}
-bool wxRegionGeneric::Xor(const wxRect& rect)
-{
- if (!rect.width || !rect.height)
- return false;
- AllocExclusive();
- REGION region(rect);
-
- return REGION::XXorRegion(®ion,M_REGIONDATA,M_REGIONDATA);
-}
-
-bool wxRegionGeneric::Xor(const wxRegionGeneric& region)
+bool wxRegionGeneric::DoXor(const wxRegion& region)
{
AllocExclusive();
return REGION::XXorRegion(M_REGIONDATA_OF(region),M_REGIONDATA,M_REGIONDATA);
}
-bool wxRegionGeneric::Offset(wxCoord x, wxCoord y)
+bool wxRegionGeneric::DoOffset(wxCoord x, wxCoord y)
{
AllocExclusive();
return REGION::XOffsetRegion(M_REGIONDATA, x, y);
// wxRegionGeneric comparison
// ----------------------------------------------------------------------------
-bool wxRegionGeneric::Empty() const
+bool wxRegionGeneric::IsEmpty() const
{
wxASSERT(m_refData);
return REGION::XEmptyRegion(M_REGIONDATA);
}
// Does the region contain the point (x,y)?
-wxRegionContain wxRegionGeneric::Contains(long x, long y) const
+wxRegionContain wxRegionGeneric::DoContainsPoint(wxCoord x, wxCoord y) const
{
wxASSERT(m_refData);
- return REGION::XPointInRegion(M_REGIONDATA,x,y)?wxInRegion:wxOutRegion;
+ return REGION::XPointInRegion(M_REGIONDATA,x,y) ? wxInRegion : wxOutRegion;
}
-
-// Does the region contain the point pt?
-wxRegionContain wxRegionGeneric::Contains(const wxPoint& pt) const
-{
- wxASSERT(m_refData);
- return REGION::XPointInRegion(M_REGIONDATA,pt.x,pt.y)?wxInRegion:wxOutRegion;
-}
-
-// Does the region contain the rectangle (x, y, w, h)?
-wxRegionContain wxRegionGeneric::Contains(long x, long y, long w, long h) const
-{
- wxASSERT(m_refData);
- return REGION::XRectInRegion(M_REGIONDATA,x,y,w,h);
-}
-
+
// Does the region contain the rectangle rect?
-wxRegionContain wxRegionGeneric::Contains(const wxRect& rect) const
+wxRegionContain wxRegionGeneric::DoContainsRect(const wxRect& rect) const
{
wxASSERT(m_refData);
return REGION::XRectInRegion(M_REGIONDATA,rect.x,rect.y,rect.width,rect.height);
}
-
+
// ========================================================================
// wxRegionIteratorGeneric
// ========================================================================
-//IMPLEMENT_DYNAMIC_CLASS(wxRegionIteratorGeneric,wxObject);
+//IMPLEMENT_DYNAMIC_CLASS(wxRegionIteratorGeneric,wxObject)
wxRegionIteratorGeneric::wxRegionIteratorGeneric()
{
wxRect wxRegionIteratorGeneric::GetRect() const
{
- wxASSERT(m_refData);
+ wxASSERT(m_region.m_refData);
const Box *box = M_REGIONDATA_OF(m_region)->GetBox(m_current);
wxASSERT(box);
return wxRect
long wxRegionIteratorGeneric::GetX() const
{
- wxASSERT(m_refData);
+ wxASSERT(m_region.m_refData);
const Box *box = M_REGIONDATA_OF(m_region)->GetBox(m_current);
wxASSERT(box);
return box->x1;
long wxRegionIteratorGeneric::GetY() const
{
- wxASSERT(m_refData);
+ wxASSERT(m_region.m_refData);
const Box *box = M_REGIONDATA_OF(m_region)->GetBox(m_current);
wxASSERT(box);
return box->y1;
long wxRegionIteratorGeneric::GetW() const
{
- wxASSERT(m_refData);
+ wxASSERT(m_region.m_refData);
const Box *box = M_REGIONDATA_OF(m_region)->GetBox(m_current);
wxASSERT(box);
return box->x2 - box->x1;
long wxRegionIteratorGeneric::GetH() const
{
- wxASSERT(m_refData);
+ wxASSERT(m_region.m_refData);
const Box *box = M_REGIONDATA_OF(m_region)->GetBox(m_current);
wxASSERT(box);
return box->y2 - box->y1;
All Rights Reserved
-Permission to use, copy, modify, and distribute this software and its
-documentation for any purpose and without fee is hereby granted,
+Permission to use, copy, modify, and distribute this software and its
+documentation for any purpose and without fee is hereby granted,
provided that the above copyright notice appear in all copies and that
-both that copyright notice and this permission notice appear in
+both that copyright notice and this permission notice appear in
supporting documentation, and that the name of Digital not be
used in advertising or publicity pertaining to distribution of the
-software without specific, written prior permission.
+software without specific, written prior permission.
DIGITAL DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING
ALL IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL
/* 1 if two BOXs overlap.
* 0 if two BOXs do not overlap.
- * Remember, x2 and y2 are not in the region
+ * Remember, x2 and y2 are not in the region
*/
#define EXTENTCHECK(r1, r2) \
- ((r1)->x2 > (r2)->x1 && \
- (r1)->x1 < (r2)->x2 && \
- (r1)->y2 > (r2)->y1 && \
- (r1)->y1 < (r2)->y2)
+ ((r1)->x2 > (r2)->x1 && \
+ (r1)->x1 < (r2)->x2 && \
+ (r1)->y2 > (r2)->y1 && \
+ (r1)->y1 < (r2)->y2)
/*
* Check to see if there is enough memory in the present region.
* the y-x-banding that's so nice to have...
*/
-/* Create a new empty region */
-Region REGION::
-XCreateRegion(void)
+/* Create a new empty region */
+Region REGION::XCreateRegion(void)
{
- Region temp;
+ Region temp = new REGION;
+
+ if (!temp)
+ return (Region) NULL;
+
+ temp->rects = ( BOX * )malloc( (unsigned) sizeof( BOX ));
- if (! (temp = new REGION))
- return (Region) NULL;
- if (! (temp->rects = ( BOX * )malloc( (unsigned) sizeof( BOX )))) {
- free((char *) temp);
- return (Region) NULL;
+ if (!temp->rects)
+ {
+ free((char *) temp);
+ return (Region) NULL;
}
temp->numRects = 0;
temp->extents.x1 = 0;
return( temp );
}
-bool REGION::
-XClipBox(
- Region r,
- wxRect *rect)
+bool REGION::XClipBox(Region r, wxRect *rect)
{
rect->x = r->extents.x1;
rect->y = r->extents.y1;
/*-
*-----------------------------------------------------------------------
* miSetExtents --
- * Reset the extents of a region to what they should be. Called by
- * miSubtract and miIntersect b/c they can't figure it out along the
- * way or do so easily, as miUnion can.
+ * Reset the extents of a region to what they should be. Called by
+ * miSubtract and miIntersect b/c they can't figure it out along the
+ * way or do so easily, as miUnion can.
*
* Results:
- * None.
+ * None.
*
* Side Effects:
- * The region's 'extents' structure is overwritten.
+ * The region's 'extents' structure is overwritten.
*
*-----------------------------------------------------------------------
*/
void REGION::
-miSetExtents (
- Region pReg)
+miSetExtents (Region pReg)
{
- register BoxPtr pBox,
- pBoxEnd,
- pExtents;
+ register BoxPtr pBox,
+ pBoxEnd,
+ pExtents;
if (pReg->numRects == 0)
{
- pReg->extents.x1 = 0;
- pReg->extents.y1 = 0;
- pReg->extents.x2 = 0;
- pReg->extents.y2 = 0;
- return;
+ pReg->extents.x1 = 0;
+ pReg->extents.y1 = 0;
+ pReg->extents.x2 = 0;
+ pReg->extents.y2 = 0;
+ return;
}
pExtents = &pReg->extents;
assert(pExtents->y1 < pExtents->y2);
while (pBox <= pBoxEnd)
{
- if (pBox->x1 < pExtents->x1)
- {
- pExtents->x1 = pBox->x1;
- }
- if (pBox->x2 > pExtents->x2)
- {
- pExtents->x2 = pBox->x2;
- }
- pBox++;
+ if (pBox->x1 < pExtents->x1)
+ {
+ pExtents->x1 = pBox->x1;
+ }
+ if (pBox->x2 > pExtents->x2)
+ {
+ pExtents->x2 = pBox->x2;
+ }
+ pBox++;
}
assert(pExtents->x1 < pExtents->x2);
}
while(nbox--)
{
- pbox->x1 += x;
- pbox->x2 += x;
- pbox->y1 += y;
- pbox->y2 += y;
- pbox++;
+ pbox->x1 += x;
+ pbox->x2 += x;
+ pbox->y1 += y;
+ pbox->y2 += y;
+ pbox++;
}
pRegion->extents.x1 += x;
pRegion->extents.x2 += x;
}
/*======================================================================
- * Region Intersection
+ * Region Intersection
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* miIntersectO --
- * Handle an overlapping band for miIntersect.
+ * Handle an overlapping band for miIntersect.
*
* Results:
- * None.
+ * None.
*
* Side Effects:
- * Rectangles may be added to the region.
+ * Rectangles may be added to the region.
*
*-----------------------------------------------------------------------
*/
/* static void*/
int REGION::
miIntersectO (
- register Region pReg,
- register BoxPtr r1,
- BoxPtr r1End,
- register BoxPtr r2,
- BoxPtr r2End,
- wxCoord y1,
- wxCoord y2)
+ register Region pReg,
+ register BoxPtr r1,
+ BoxPtr r1End,
+ register BoxPtr r2,
+ BoxPtr r2End,
+ wxCoord y1,
+ wxCoord y2)
{
- register wxCoord x1;
- register wxCoord x2;
- register BoxPtr pNextRect;
+ register wxCoord x1;
+ register wxCoord x2;
+ register BoxPtr pNextRect;
pNextRect = &pReg->rects[pReg->numRects];
while ((r1 != r1End) && (r2 != r2End))
{
- x1 = wxMax(r1->x1,r2->x1);
- x2 = wxMin(r1->x2,r2->x2);
-
- /*
- * If there's any overlap between the two rectangles, add that
- * overlap to the new region.
- * There's no need to check for subsumption because the only way
- * such a need could arise is if some region has two rectangles
- * right next to each other. Since that should never happen...
- */
- if (x1 < x2)
- {
- assert(y1<y2);
-
- MEMCHECK(pReg, pNextRect, pReg->rects);
- pNextRect->x1 = x1;
- pNextRect->y1 = y1;
- pNextRect->x2 = x2;
- pNextRect->y2 = y2;
- pReg->numRects += 1;
- pNextRect++;
- assert(pReg->numRects <= pReg->size);
- }
-
- /*
- * Need to advance the pointers. Shift the one that extends
- * to the right the least, since the other still has a chance to
- * overlap with that region's next rectangle, if you see what I mean.
- */
- if (r1->x2 < r2->x2)
- {
- r1++;
- }
- else if (r2->x2 < r1->x2)
- {
- r2++;
- }
- else
- {
- r1++;
- r2++;
- }
+ x1 = wxMax(r1->x1,r2->x1);
+ x2 = wxMin(r1->x2,r2->x2);
+
+ /*
+ * If there's any overlap between the two rectangles, add that
+ * overlap to the new region.
+ * There's no need to check for subsumption because the only way
+ * such a need could arise is if some region has two rectangles
+ * right next to each other. Since that should never happen...
+ */
+ if (x1 < x2)
+ {
+ assert(y1<y2);
+
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->x1 = x1;
+ pNextRect->y1 = y1;
+ pNextRect->x2 = x2;
+ pNextRect->y2 = y2;
+ pReg->numRects += 1;
+ pNextRect++;
+ assert(pReg->numRects <= pReg->size);
+ }
+
+ /*
+ * Need to advance the pointers. Shift the one that extends
+ * to the right the least, since the other still has a chance to
+ * overlap with that region's next rectangle, if you see what I mean.
+ */
+ if (r1->x2 < r2->x2)
+ {
+ r1++;
+ }
+ else if (r2->x2 < r1->x2)
+ {
+ r2++;
+ }
+ else
+ {
+ r1++;
+ r2++;
+ }
}
- return 0; /* lint */
+ return 0; /* lint */
}
bool REGION::
XIntersectRegion(
- Region reg1,
- Region reg2, /* source regions */
- register Region newReg) /* destination Region */
+ Region reg1,
+ Region reg2, /* source regions */
+ register Region newReg) /* destination Region */
{
/* check for trivial reject */
if ( (!(reg1->numRects)) || (!(reg2->numRects)) ||
- (!EXTENTCHECK(®1->extents, ®2->extents)))
+ (!EXTENTCHECK(®1->extents, ®2->extents)))
newReg->numRects = 0;
else
- miRegionOp (newReg, reg1, reg2,
- miIntersectO, NULL, NULL);
-
+ miRegionOp (newReg, reg1, reg2,
+ miIntersectO, NULL, NULL);
+
/*
* Can't alter newReg's extents before we call miRegionOp because
* it might be one of the source regions and miRegionOp depends
{
if (dstrgn != rgn) /* don't want to copy to itself */
- {
+ {
if (dstrgn->size < rgn->numRects)
{
if (dstrgn->rects)
{
- BOX *prevRects = dstrgn->rects;
-
- if (! (dstrgn->rects = (BOX *)
- realloc((char *) dstrgn->rects,
- (unsigned) rgn->numRects * (sizeof(BOX))))) {
- free(prevRects);
- return;
- }
+ BOX *prevRects = dstrgn->rects;
+
+ dstrgn->rects = (BOX *)
+ realloc((char *) dstrgn->rects,
+ (unsigned) rgn->numRects * (sizeof(BOX)));
+ if (!dstrgn->rects)
+ {
+ free(prevRects);
+ return;
+ }
}
dstrgn->size = rgn->numRects;
- }
+ }
dstrgn->numRects = rgn->numRects;
dstrgn->extents.x1 = rgn->extents.x1;
dstrgn->extents.y1 = rgn->extents.y1;
dstrgn->extents.x2 = rgn->extents.x2;
dstrgn->extents.y2 = rgn->extents.y2;
- memcpy((char *) dstrgn->rects, (char *) rgn->rects,
- (int) (rgn->numRects * sizeof(BOX)));
+ memcpy((char *) dstrgn->rects, (char *) rgn->rects,
+ (int) (rgn->numRects * sizeof(BOX)));
}
}
/*======================================================================
- * Generic Region Operator
+ * Generic Region Operator
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* miCoalesce --
- * Attempt to merge the boxes in the current band with those in the
- * previous one. Used only by miRegionOp.
+ * Attempt to merge the boxes in the current band with those in the
+ * previous one. Used only by miRegionOp.
*
* Results:
- * The new index for the previous band.
+ * The new index for the previous band.
*
* Side Effects:
- * If coalescing takes place:
- * - rectangles in the previous band will have their y2 fields
- * altered.
- * - pReg->numRects will be decreased.
+ * If coalescing takes place:
+ * - rectangles in the previous band will have their y2 fields
+ * altered.
+ * - pReg->numRects will be decreased.
*
*-----------------------------------------------------------------------
*/
/* static int*/
int REGION::
miCoalesce(
- register Region pReg, /* Region to coalesce */
- int prevStart, /* Index of start of previous band */
- int curStart) /* Index of start of current band */
+ register Region pReg, /* Region to coalesce */
+ int prevStart, /* Index of start of previous band */
+ int curStart) /* Index of start of current band */
{
- register BoxPtr pPrevBox; /* Current box in previous band */
- register BoxPtr pCurBox; /* Current box in current band */
- register BoxPtr pRegEnd; /* End of region */
- int curNumRects; /* Number of rectangles in current
- * band */
- int prevNumRects; /* Number of rectangles in previous
- * band */
- int bandY1; /* Y1 coordinate for current band */
+ register BoxPtr pPrevBox; /* Current box in previous band */
+ register BoxPtr pCurBox; /* Current box in current band */
+ register BoxPtr pRegEnd; /* End of region */
+ int curNumRects; /* Number of rectangles in current
+ * band */
+ int prevNumRects; /* Number of rectangles in previous
+ * band */
+ int bandY1; /* Y1 coordinate for current band */
pRegEnd = &pReg->rects[pReg->numRects];
pCurBox = &pReg->rects[curStart];
bandY1 = pCurBox->y1;
for (curNumRects = 0;
- (pCurBox != pRegEnd) && (pCurBox->y1 == bandY1);
- curNumRects++)
+ (pCurBox != pRegEnd) && (pCurBox->y1 == bandY1);
+ curNumRects++)
{
- pCurBox++;
+ pCurBox++;
}
-
+
if (pCurBox != pRegEnd)
{
- /*
- * If more than one band was added, we have to find the start
- * of the last band added so the next coalescing job can start
- * at the right place... (given when multiple bands are added,
- * this may be pointless -- see above).
- */
- pRegEnd--;
- while (pRegEnd[-1].y1 == pRegEnd->y1)
- {
- pRegEnd--;
- }
- curStart = pRegEnd - pReg->rects;
- pRegEnd = pReg->rects + pReg->numRects;
+ /*
+ * If more than one band was added, we have to find the start
+ * of the last band added so the next coalescing job can start
+ * at the right place... (given when multiple bands are added,
+ * this may be pointless -- see above).
+ */
+ pRegEnd--;
+ while (pRegEnd[-1].y1 == pRegEnd->y1)
+ {
+ pRegEnd--;
+ }
+ curStart = pRegEnd - pReg->rects;
+ pRegEnd = pReg->rects + pReg->numRects;
}
-
- if ((curNumRects == prevNumRects) && (curNumRects != 0)) {
- pCurBox -= curNumRects;
- /*
- * The bands may only be coalesced if the bottom of the previous
- * matches the top scanline of the current.
- */
- if (pPrevBox->y2 == pCurBox->y1)
- {
- /*
- * Make sure the bands have boxes in the same places. This
- * assumes that boxes have been added in such a way that they
- * cover the most area possible. I.e. two boxes in a band must
- * have some horizontal space between them.
- */
- do
- {
- if ((pPrevBox->x1 != pCurBox->x1) ||
- (pPrevBox->x2 != pCurBox->x2))
- {
- /*
- * The bands don't line up so they can't be coalesced.
- */
- return (curStart);
- }
- pPrevBox++;
- pCurBox++;
- prevNumRects -= 1;
- } while (prevNumRects != 0);
-
- pReg->numRects -= curNumRects;
- pCurBox -= curNumRects;
- pPrevBox -= curNumRects;
-
- /*
- * The bands may be merged, so set the bottom y of each box
- * in the previous band to that of the corresponding box in
- * the current band.
- */
- do
- {
- pPrevBox->y2 = pCurBox->y2;
- pPrevBox++;
- pCurBox++;
- curNumRects -= 1;
- } while (curNumRects != 0);
-
- /*
- * If only one band was added to the region, we have to backup
- * curStart to the start of the previous band.
- *
- * If more than one band was added to the region, copy the
- * other bands down. The assumption here is that the other bands
- * came from the same region as the current one and no further
- * coalescing can be done on them since it's all been done
- * already... curStart is already in the right place.
- */
- if (pCurBox == pRegEnd)
- {
- curStart = prevStart;
- }
- else
- {
- do
- {
- *pPrevBox++ = *pCurBox++;
- } while (pCurBox != pRegEnd);
- }
-
- }
+
+ if ((curNumRects == prevNumRects) && (curNumRects != 0))
+ {
+ pCurBox -= curNumRects;
+ /*
+ * The bands may only be coalesced if the bottom of the previous
+ * matches the top scanline of the current.
+ */
+ if (pPrevBox->y2 == pCurBox->y1)
+ {
+ /*
+ * Make sure the bands have boxes in the same places. This
+ * assumes that boxes have been added in such a way that they
+ * cover the most area possible. I.e. two boxes in a band must
+ * have some horizontal space between them.
+ */
+ do
+ {
+ if ((pPrevBox->x1 != pCurBox->x1) ||
+ (pPrevBox->x2 != pCurBox->x2))
+ {
+ /*
+ * The bands don't line up so they can't be coalesced.
+ */
+ return (curStart);
+ }
+ pPrevBox++;
+ pCurBox++;
+ prevNumRects -= 1;
+ } while (prevNumRects != 0);
+
+ pReg->numRects -= curNumRects;
+ pCurBox -= curNumRects;
+ pPrevBox -= curNumRects;
+
+ /*
+ * The bands may be merged, so set the bottom y of each box
+ * in the previous band to that of the corresponding box in
+ * the current band.
+ */
+ do
+ {
+ pPrevBox->y2 = pCurBox->y2;
+ pPrevBox++;
+ pCurBox++;
+ curNumRects -= 1;
+ } while (curNumRects != 0);
+
+ /*
+ * If only one band was added to the region, we have to backup
+ * curStart to the start of the previous band.
+ *
+ * If more than one band was added to the region, copy the
+ * other bands down. The assumption here is that the other bands
+ * came from the same region as the current one and no further
+ * coalescing can be done on them since it's all been done
+ * already... curStart is already in the right place.
+ */
+ if (pCurBox == pRegEnd)
+ {
+ curStart = prevStart;
+ }
+ else
+ {
+ do
+ {
+ *pPrevBox++ = *pCurBox++;
+ } while (pCurBox != pRegEnd);
+ }
+
+ }
}
return (curStart);
}
/*-
*-----------------------------------------------------------------------
* miRegionOp --
- * Apply an operation to two regions. Called by miUnion, miInverse,
- * miSubtract, miIntersect...
+ * Apply an operation to two regions. Called by miUnion, miInverse,
+ * miSubtract, miIntersect...
*
* Results:
- * None.
+ * None.
*
* Side Effects:
- * The new region is overwritten.
+ * The new region is overwritten.
*
* Notes:
- * The idea behind this function is to view the two regions as sets.
- * Together they cover a rectangle of area that this function divides
- * into horizontal bands where points are covered only by one region
- * or by both. For the first case, the nonOverlapFunc is called with
- * each the band and the band's upper and lower extents. For the
- * second, the overlapFunc is called to process the entire band. It
- * is responsible for clipping the rectangles in the band, though
- * this function provides the boundaries.
- * At the end of each band, the new region is coalesced, if possible,
- * to reduce the number of rectangles in the region.
+ * The idea behind this function is to view the two regions as sets.
+ * Together they cover a rectangle of area that this function divides
+ * into horizontal bands where points are covered only by one region
+ * or by both. For the first case, the nonOverlapFunc is called with
+ * each the band and the band's upper and lower extents. For the
+ * second, the overlapFunc is called to process the entire band. It
+ * is responsible for clipping the rectangles in the band, though
+ * this function provides the boundaries.
+ * At the end of each band, the new region is coalesced, if possible,
+ * to reduce the number of rectangles in the region.
*
*-----------------------------------------------------------------------
*/
/* static void*/
void REGION::
miRegionOp(
- register Region newReg, /* Place to store result */
- Region reg1, /* First region in operation */
- Region reg2, /* 2d region in operation */
- int (*overlapFunc)(
+ register Region newReg, /* Place to store result */
+ Region reg1, /* First region in operation */
+ Region reg2, /* 2d region in operation */
+ int (*overlapFunc)(
register Region pReg,
register BoxPtr r1,
BoxPtr r1End,
register BoxPtr r2,
BoxPtr r2End,
wxCoord y1,
- wxCoord y2), /* Function to call for over-
- * lapping bands */
- int (*nonOverlap1Func)(
+ wxCoord y2), /* Function to call for over-
+ * lapping bands */
+ int (*nonOverlap1Func)(
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
register wxCoord y1,
- register wxCoord y2), /* Function to call for non-
- * overlapping bands in region
- * 1 */
- int (*nonOverlap2Func)(
+ register wxCoord y2), /* Function to call for non-
+ * overlapping bands in region
+ * 1 */
+ int (*nonOverlap2Func)(
register Region pReg,
register BoxPtr r,
BoxPtr rEnd,
register wxCoord y1,
- register wxCoord y2)) /* Function to call for non-
- * overlapping bands in region
- * 2 */
+ register wxCoord y2)) /* Function to call for non-
+ * overlapping bands in region
+ * 2 */
{
- register BoxPtr r1; /* Pointer into first region */
- register BoxPtr r2; /* Pointer into 2d region */
- BoxPtr r1End; /* End of 1st region */
- BoxPtr r2End; /* End of 2d region */
- register wxCoord ybot; /* Bottom of intersection */
- register wxCoord ytop; /* Top of intersection */
- BoxPtr oldRects; /* Old rects for newReg */
- int prevBand; /* Index of start of
- * previous band in newReg */
- int curBand; /* Index of start of current
- * band in newReg */
- register BoxPtr r1BandEnd; /* End of current band in r1 */
- register BoxPtr r2BandEnd; /* End of current band in r2 */
- wxCoord top; /* Top of non-overlapping
- * band */
- wxCoord bot; /* Bottom of non-overlapping
- * band */
-
+ register BoxPtr r1; /* Pointer into first region */
+ register BoxPtr r2; /* Pointer into 2d region */
+ BoxPtr r1End; /* End of 1st region */
+ BoxPtr r2End; /* End of 2d region */
+ register wxCoord ybot; /* Bottom of intersection */
+ register wxCoord ytop; /* Top of intersection */
+ BoxPtr oldRects; /* Old rects for newReg */
+ int prevBand; /* Index of start of
+ * previous band in newReg */
+ int curBand; /* Index of start of current
+ * band in newReg */
+ register BoxPtr r1BandEnd; /* End of current band in r1 */
+ register BoxPtr r2BandEnd; /* End of current band in r2 */
+ wxCoord top; /* Top of non-overlapping
+ * band */
+ wxCoord bot; /* Bottom of non-overlapping
+ * band */
+
/*
* Initialization:
- * set r1, r2, r1End and r2End appropriately, preserve the important
+ * set r1, r2, r1End and r2End appropriately, preserve the important
* parts of the destination region until the end in case it's one of
* the two source regions, then mark the "new" region empty, allocating
* another array of rectangles for it to use.
r2 = reg2->rects;
r1End = r1 + reg1->numRects;
r2End = r2 + reg2->numRects;
-
+
oldRects = newReg->rects;
-
+
EMPTY_REGION(newReg);
/*
*/
newReg->size = wxMax(reg1->numRects,reg2->numRects) * 2;
- if (! (newReg->rects = (BoxPtr)
- malloc ((unsigned) (sizeof(BoxRec) * newReg->size)))) {
- newReg->size = 0;
- return;
+ newReg->rects = (BoxPtr)malloc((unsigned) (sizeof(BoxRec) * newReg->size));
+
+ if (!newReg->rects)
+ {
+ newReg->size = 0;
+ return;
}
-
+
/*
* Initialize ybot and ytop.
* In the upcoming loop, ybot and ytop serve different functions depending
* on whether the band being handled is an overlapping or non-overlapping
* band.
- * In the case of a non-overlapping band (only one of the regions
+ * In the case of a non-overlapping band (only one of the regions
* has points in the band), ybot is the bottom of the most recent
* intersection and thus clips the top of the rectangles in that band.
* ytop is the top of the next intersection between the two regions and
* serves to clip the bottom of the rectangles in the current band.
- * For an overlapping band (where the two regions intersect), ytop clips
+ * For an overlapping band (where the two regions intersect), ytop clips
* the top of the rectangles of both regions and ybot clips the bottoms.
*/
if (reg1->extents.y1 < reg2->extents.y1)
- ybot = reg1->extents.y1;
+ ybot = reg1->extents.y1;
else
- ybot = reg2->extents.y1;
-
+ ybot = reg2->extents.y1;
+
/*
* prevBand serves to mark the start of the previous band so rectangles
* can be coalesced into larger rectangles. qv. miCoalesce, above.
* array of rectangles.
*/
prevBand = 0;
-
+
do
{
- curBand = newReg->numRects;
-
- /*
- * This algorithm proceeds one source-band (as opposed to a
- * destination band, which is determined by where the two regions
- * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
- * rectangle after the last one in the current band for their
- * respective regions.
- */
- r1BandEnd = r1;
- while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1))
- {
- r1BandEnd++;
- }
-
- r2BandEnd = r2;
- while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1))
- {
- r2BandEnd++;
- }
-
- /*
- * First handle the band that doesn't intersect, if any.
- *
- * Note that attention is restricted to one band in the
- * non-intersecting region at once, so if a region has n
- * bands between the current position and the next place it overlaps
- * the other, this entire loop will be passed through n times.
- */
- if (r1->y1 < r2->y1)
- {
- top = wxMax(r1->y1,ybot);
- bot = wxMin(r1->y2,r2->y1);
-
- if ((top != bot) && (nonOverlap1Func != NULL))
- {
- (* nonOverlap1Func) (newReg, r1, r1BandEnd, top, bot);
- }
-
- ytop = r2->y1;
- }
- else if (r2->y1 < r1->y1)
- {
- top = wxMax(r2->y1,ybot);
- bot = wxMin(r2->y2,r1->y1);
-
- if ((top != bot) && (nonOverlap2Func != NULL))
- {
- (* nonOverlap2Func) (newReg, r2, r2BandEnd, top, bot);
- }
-
- ytop = r1->y1;
- }
- else
- {
- ytop = r1->y1;
- }
-
- /*
- * If any rectangles got added to the region, try and coalesce them
- * with rectangles from the previous band. Note we could just do
- * this test in miCoalesce, but some machines incur a not
- * inconsiderable cost for function calls, so...
- */
- if (newReg->numRects != curBand)
- {
- prevBand = miCoalesce (newReg, prevBand, curBand);
- }
-
- /*
- * Now see if we've hit an intersecting band. The two bands only
- * intersect if ybot > ytop
- */
- ybot = wxMin(r1->y2, r2->y2);
- curBand = newReg->numRects;
- if (ybot > ytop)
- {
- (* overlapFunc) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
-
- }
-
- if (newReg->numRects != curBand)
- {
- prevBand = miCoalesce (newReg, prevBand, curBand);
- }
-
- /*
- * If we've finished with a band (y2 == ybot) we skip forward
- * in the region to the next band.
- */
- if (r1->y2 == ybot)
- {
- r1 = r1BandEnd;
- }
- if (r2->y2 == ybot)
- {
- r2 = r2BandEnd;
- }
+ curBand = newReg->numRects;
+
+ /*
+ * This algorithm proceeds one source-band (as opposed to a
+ * destination band, which is determined by where the two regions
+ * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
+ * rectangle after the last one in the current band for their
+ * respective regions.
+ */
+ r1BandEnd = r1;
+ while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1))
+ {
+ r1BandEnd++;
+ }
+
+ r2BandEnd = r2;
+ while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1))
+ {
+ r2BandEnd++;
+ }
+
+ /*
+ * First handle the band that doesn't intersect, if any.
+ *
+ * Note that attention is restricted to one band in the
+ * non-intersecting region at once, so if a region has n
+ * bands between the current position and the next place it overlaps
+ * the other, this entire loop will be passed through n times.
+ */
+ if (r1->y1 < r2->y1)
+ {
+ top = wxMax(r1->y1,ybot);
+ bot = wxMin(r1->y2,r2->y1);
+
+ if ((top != bot) && (nonOverlap1Func != NULL))
+ {
+ (* nonOverlap1Func) (newReg, r1, r1BandEnd, top, bot);
+ }
+
+ ytop = r2->y1;
+ }
+ else if (r2->y1 < r1->y1)
+ {
+ top = wxMax(r2->y1,ybot);
+ bot = wxMin(r2->y2,r1->y1);
+
+ if ((top != bot) && (nonOverlap2Func != NULL))
+ {
+ (* nonOverlap2Func) (newReg, r2, r2BandEnd, top, bot);
+ }
+
+ ytop = r1->y1;
+ }
+ else
+ {
+ ytop = r1->y1;
+ }
+
+ /*
+ * If any rectangles got added to the region, try and coalesce them
+ * with rectangles from the previous band. Note we could just do
+ * this test in miCoalesce, but some machines incur a not
+ * inconsiderable cost for function calls, so...
+ */
+ if (newReg->numRects != curBand)
+ {
+ prevBand = miCoalesce (newReg, prevBand, curBand);
+ }
+
+ /*
+ * Now see if we've hit an intersecting band. The two bands only
+ * intersect if ybot > ytop
+ */
+ ybot = wxMin(r1->y2, r2->y2);
+ curBand = newReg->numRects;
+ if (ybot > ytop)
+ {
+ (* overlapFunc) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
+
+ }
+
+ if (newReg->numRects != curBand)
+ {
+ prevBand = miCoalesce (newReg, prevBand, curBand);
+ }
+
+ /*
+ * If we've finished with a band (y2 == ybot) we skip forward
+ * in the region to the next band.
+ */
+ if (r1->y2 == ybot)
+ {
+ r1 = r1BandEnd;
+ }
+ if (r2->y2 == ybot)
+ {
+ r2 = r2BandEnd;
+ }
} while ((r1 != r1End) && (r2 != r2End));
/*
curBand = newReg->numRects;
if (r1 != r1End)
{
- if (nonOverlap1Func != NULL)
- {
- do
- {
- r1BandEnd = r1;
- while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1))
- {
- r1BandEnd++;
- }
- (* nonOverlap1Func) (newReg, r1, r1BandEnd,
- wxMax(r1->y1,ybot), r1->y2);
- r1 = r1BandEnd;
- } while (r1 != r1End);
- }
+ if (nonOverlap1Func != NULL)
+ {
+ do
+ {
+ r1BandEnd = r1;
+ while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1))
+ {
+ r1BandEnd++;
+ }
+ (* nonOverlap1Func) (newReg, r1, r1BandEnd,
+ wxMax(r1->y1,ybot), r1->y2);
+ r1 = r1BandEnd;
+ } while (r1 != r1End);
+ }
}
else if ((r2 != r2End) && (nonOverlap2Func != NULL))
{
- do
- {
- r2BandEnd = r2;
- while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1))
- {
- r2BandEnd++;
- }
- (* nonOverlap2Func) (newReg, r2, r2BandEnd,
- wxMax(r2->y1,ybot), r2->y2);
- r2 = r2BandEnd;
- } while (r2 != r2End);
+ do
+ {
+ r2BandEnd = r2;
+ while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1))
+ {
+ r2BandEnd++;
+ }
+ (* nonOverlap2Func) (newReg, r2, r2BandEnd,
+ wxMax(r2->y1,ybot), r2->y2);
+ r2 = r2BandEnd;
+ } while (r2 != r2End);
}
if (newReg->numRects != curBand)
{
- (void) miCoalesce (newReg, prevBand, curBand);
+ (void) miCoalesce (newReg, prevBand, curBand);
}
/*
*/
if (newReg->numRects < (newReg->size >> 1))
{
- if (REGION_NOT_EMPTY(newReg))
- {
- BoxPtr prev_rects = newReg->rects;
- newReg->size = newReg->numRects;
- newReg->rects = (BoxPtr) realloc ((char *) newReg->rects,
- (unsigned) (sizeof(BoxRec) * newReg->size));
- if (! newReg->rects)
- newReg->rects = prev_rects;
- }
- else
- {
- /*
- * No point in doing the extra work involved in an realloc if
- * the region is empty
- */
- newReg->size = 1;
- free((char *) newReg->rects);
- newReg->rects = (BoxPtr) malloc(sizeof(BoxRec));
- }
+ if (REGION_NOT_EMPTY(newReg))
+ {
+ BoxPtr prev_rects = newReg->rects;
+ newReg->size = newReg->numRects;
+ newReg->rects = (BoxPtr) realloc ((char *) newReg->rects,
+ (unsigned) (sizeof(BoxRec) * newReg->size));
+ if (! newReg->rects)
+ newReg->rects = prev_rects;
+ }
+ else
+ {
+ /*
+ * No point in doing the extra work involved in an realloc if
+ * the region is empty
+ */
+ newReg->size = 1;
+ free((char *) newReg->rects);
+ newReg->rects = (BoxPtr) malloc(sizeof(BoxRec));
+ }
}
free ((char *) oldRects);
return;
}
/*======================================================================
- * Region Union
+ * Region Union
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* miUnionNonO --
- * Handle a non-overlapping band for the union operation. Just
- * Adds the rectangles into the region. Doesn't have to check for
- * subsumption or anything.
+ * Handle a non-overlapping band for the union operation. Just
+ * Adds the rectangles into the region. Doesn't have to check for
+ * subsumption or anything.
*
* Results:
- * None.
+ * None.
*
* Side Effects:
- * pReg->numRects is incremented and the final rectangles overwritten
- * with the rectangles we're passed.
+ * pReg->numRects is incremented and the final rectangles overwritten
+ * with the rectangles we're passed.
*
*-----------------------------------------------------------------------
*/
/* static void*/
int REGION::
miUnionNonO (
- register Region pReg,
- register BoxPtr r,
- BoxPtr rEnd,
- register wxCoord y1,
- register wxCoord y2)
+ register Region pReg,
+ register BoxPtr r,
+ BoxPtr rEnd,
+ register wxCoord y1,
+ register wxCoord y2)
{
- register BoxPtr pNextRect;
+ register BoxPtr pNextRect;
pNextRect = &pReg->rects[pReg->numRects];
while (r != rEnd)
{
- assert(r->x1 < r->x2);
- MEMCHECK(pReg, pNextRect, pReg->rects);
- pNextRect->x1 = r->x1;
- pNextRect->y1 = y1;
- pNextRect->x2 = r->x2;
- pNextRect->y2 = y2;
- pReg->numRects += 1;
- pNextRect++;
-
- assert(pReg->numRects<=pReg->size);
- r++;
+ assert(r->x1 < r->x2);
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->x1 = r->x1;
+ pNextRect->y1 = y1;
+ pNextRect->x2 = r->x2;
+ pNextRect->y2 = y2;
+ pReg->numRects += 1;
+ pNextRect++;
+
+ assert(pReg->numRects<=pReg->size);
+ r++;
}
- return 0; /* lint */
+ return 0; /* lint */
}
/*-
*-----------------------------------------------------------------------
* miUnionO --
- * Handle an overlapping band for the union operation. Picks the
- * left-most rectangle each time and merges it into the region.
+ * Handle an overlapping band for the union operation. Picks the
+ * left-most rectangle each time and merges it into the region.
*
* Results:
- * None.
+ * None.
*
* Side Effects:
- * Rectangles are overwritten in pReg->rects and pReg->numRects will
- * be changed.
+ * Rectangles are overwritten in pReg->rects and pReg->numRects will
+ * be changed.
*
*-----------------------------------------------------------------------
*/
/* static void*/
int REGION::
miUnionO (
- register Region pReg,
- register BoxPtr r1,
- BoxPtr r1End,
- register BoxPtr r2,
- BoxPtr r2End,
- register wxCoord y1,
- register wxCoord y2)
+ register Region pReg,
+ register BoxPtr r1,
+ BoxPtr r1End,
+ register BoxPtr r2,
+ BoxPtr r2End,
+ register wxCoord y1,
+ register wxCoord y2)
{
- register BoxPtr pNextRect;
-
+ register BoxPtr pNextRect;
+
pNextRect = &pReg->rects[pReg->numRects];
#define MERGERECT(r) \
if ((pReg->numRects != 0) && \
- (pNextRect[-1].y1 == y1) && \
- (pNextRect[-1].y2 == y2) && \
- (pNextRect[-1].x2 >= r->x1)) \
+ (pNextRect[-1].y1 == y1) && \
+ (pNextRect[-1].y2 == y2) && \
+ (pNextRect[-1].x2 >= r->x1)) \
{ \
- if (pNextRect[-1].x2 < r->x2) \
- { \
- pNextRect[-1].x2 = r->x2; \
- assert(pNextRect[-1].x1<pNextRect[-1].x2); \
- } \
+ if (pNextRect[-1].x2 < r->x2) \
+ { \
+ pNextRect[-1].x2 = r->x2; \
+ assert(pNextRect[-1].x1<pNextRect[-1].x2); \
+ } \
} \
else \
{ \
- MEMCHECK(pReg, pNextRect, pReg->rects); \
- pNextRect->y1 = y1; \
- pNextRect->y2 = y2; \
- pNextRect->x1 = r->x1; \
- pNextRect->x2 = r->x2; \
- pReg->numRects += 1; \
+ MEMCHECK(pReg, pNextRect, pReg->rects); \
+ pNextRect->y1 = y1; \
+ pNextRect->y2 = y2; \
+ pNextRect->x1 = r->x1; \
+ pNextRect->x2 = r->x2; \
+ pReg->numRects += 1; \
pNextRect += 1; \
} \
assert(pReg->numRects<=pReg->size);\
r++;
-
+
assert (y1<y2);
while ((r1 != r1End) && (r2 != r2End))
{
- if (r1->x1 < r2->x1)
- {
- MERGERECT(r1);
- }
- else
- {
- MERGERECT(r2);
- }
+ if (r1->x1 < r2->x1)
+ {
+ MERGERECT(r1);
+ }
+ else
+ {
+ MERGERECT(r2);
+ }
}
-
+
if (r1 != r1End)
{
- do
- {
- MERGERECT(r1);
- } while (r1 != r1End);
+ do
+ {
+ MERGERECT(r1);
+ } while (r1 != r1End);
}
else while (r2 != r2End)
{
- MERGERECT(r2);
+ MERGERECT(r2);
}
- return 0; /* lint */
+ return 0; /* lint */
}
bool REGION::
XUnionRegion(
- Region reg1,
- Region reg2, /* source regions */
- Region newReg) /* destination Region */
+ Region reg1,
+ Region reg2, /* source regions */
+ Region newReg) /* destination Region */
{
/* checks all the simple cases */
/*
* Region 1 completely subsumes region 2
*/
- if ((reg1->numRects == 1) &&
- (reg1->extents.x1 <= reg2->extents.x1) &&
- (reg1->extents.y1 <= reg2->extents.y1) &&
- (reg1->extents.x2 >= reg2->extents.x2) &&
- (reg1->extents.y2 >= reg2->extents.y2))
+ if ((reg1->numRects == 1) &&
+ (reg1->extents.x1 <= reg2->extents.x1) &&
+ (reg1->extents.y1 <= reg2->extents.y1) &&
+ (reg1->extents.x2 >= reg2->extents.x2) &&
+ (reg1->extents.y2 >= reg2->extents.y2))
{
if (newReg != reg1)
miRegionCopy(newReg, reg1);
/*
* Region 2 completely subsumes region 1
*/
- if ((reg2->numRects == 1) &&
- (reg2->extents.x1 <= reg1->extents.x1) &&
- (reg2->extents.y1 <= reg1->extents.y1) &&
- (reg2->extents.x2 >= reg1->extents.x2) &&
- (reg2->extents.y2 >= reg1->extents.y2))
+ if ((reg2->numRects == 1) &&
+ (reg2->extents.x1 <= reg1->extents.x1) &&
+ (reg2->extents.y1 <= reg1->extents.y1) &&
+ (reg2->extents.x2 >= reg1->extents.x2) &&
+ (reg2->extents.y2 >= reg1->extents.y2))
{
if (newReg != reg2)
miRegionCopy(newReg, reg2);
return 1;
}
- miRegionOp (newReg, reg1, reg2, miUnionO,
- miUnionNonO, miUnionNonO);
+ miRegionOp (newReg, reg1, reg2, miUnionO,
+ miUnionNonO, miUnionNonO);
newReg->extents.x1 = wxMin(reg1->extents.x1, reg2->extents.x1);
newReg->extents.y1 = wxMin(reg1->extents.y1, reg2->extents.y1);
}
/*======================================================================
- * Region Subtraction
+ * Region Subtraction
*====================================================================*/
/*-
*-----------------------------------------------------------------------
* miSubtractNonO --
- * Deal with non-overlapping band for subtraction. Any parts from
- * region 2 we discard. Anything from region 1 we add to the region.
+ * Deal with non-overlapping band for subtraction. Any parts from
+ * region 2 we discard. Anything from region 1 we add to the region.
*
* Results:
- * None.
+ * None.
*
* Side Effects:
- * pReg may be affected.
+ * pReg may be affected.
*
*-----------------------------------------------------------------------
*/
/* static void*/
int REGION::
miSubtractNonO1 (
- register Region pReg,
- register BoxPtr r,
- BoxPtr rEnd,
- register wxCoord y1,
- register wxCoord y2)
+ register Region pReg,
+ register BoxPtr r,
+ BoxPtr rEnd,
+ register wxCoord y1,
+ register wxCoord y2)
{
- register BoxPtr pNextRect;
-
+ register BoxPtr pNextRect;
+
pNextRect = &pReg->rects[pReg->numRects];
-
+
assert(y1<y2);
while (r != rEnd)
{
- assert(r->x1<r->x2);
- MEMCHECK(pReg, pNextRect, pReg->rects);
- pNextRect->x1 = r->x1;
- pNextRect->y1 = y1;
- pNextRect->x2 = r->x2;
- pNextRect->y2 = y2;
- pReg->numRects += 1;
- pNextRect++;
-
- assert(pReg->numRects <= pReg->size);
-
- r++;
+ assert(r->x1<r->x2);
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->x1 = r->x1;
+ pNextRect->y1 = y1;
+ pNextRect->x2 = r->x2;
+ pNextRect->y2 = y2;
+ pReg->numRects += 1;
+ pNextRect++;
+
+ assert(pReg->numRects <= pReg->size);
+
+ r++;
}
- return 0; /* lint */
+ return 0; /* lint */
}
/*-
*-----------------------------------------------------------------------
* miSubtractO --
- * Overlapping band subtraction. x1 is the left-most point not yet
- * checked.
+ * Overlapping band subtraction. x1 is the left-most point not yet
+ * checked.
*
* Results:
- * None.
+ * None.
*
* Side Effects:
- * pReg may have rectangles added to it.
+ * pReg may have rectangles added to it.
*
*-----------------------------------------------------------------------
*/
/* static void*/
int REGION::
miSubtractO (
- register Region pReg,
- register BoxPtr r1,
- BoxPtr r1End,
- register BoxPtr r2,
- BoxPtr r2End,
- register wxCoord y1,
- register wxCoord y2)
+ register Region pReg,
+ register BoxPtr r1,
+ BoxPtr r1End,
+ register BoxPtr r2,
+ BoxPtr r2End,
+ register wxCoord y1,
+ register wxCoord y2)
{
- register BoxPtr pNextRect;
- register int x1;
-
+ register BoxPtr pNextRect;
+ register int x1;
+
x1 = r1->x1;
-
+
assert(y1<y2);
pNextRect = &pReg->rects[pReg->numRects];
while ((r1 != r1End) && (r2 != r2End))
{
- if (r2->x2 <= x1)
- {
- /*
- * Subtrahend missed the boat: go to next subtrahend.
- */
- r2++;
- }
- else if (r2->x1 <= x1)
- {
- /*
- * Subtrahend preceeds minuend: nuke left edge of minuend.
- */
- x1 = r2->x2;
- if (x1 >= r1->x2)
- {
- /*
- * Minuend completely covered: advance to next minuend and
- * reset left fence to edge of new minuend.
- */
- r1++;
- if (r1 != r1End)
- x1 = r1->x1;
- }
- else
- {
- /*
- * Subtrahend now used up since it doesn't extend beyond
- * minuend
- */
- r2++;
- }
- }
- else if (r2->x1 < r1->x2)
- {
- /*
- * Left part of subtrahend covers part of minuend: add uncovered
- * part of minuend to region and skip to next subtrahend.
- */
- assert(x1<r2->x1);
- MEMCHECK(pReg, pNextRect, pReg->rects);
- pNextRect->x1 = x1;
- pNextRect->y1 = y1;
- pNextRect->x2 = r2->x1;
- pNextRect->y2 = y2;
- pReg->numRects += 1;
- pNextRect++;
-
- assert(pReg->numRects<=pReg->size);
-
- x1 = r2->x2;
- if (x1 >= r1->x2)
- {
- /*
- * Minuend used up: advance to new...
- */
- r1++;
- if (r1 != r1End)
- x1 = r1->x1;
- }
- else
- {
- /*
- * Subtrahend used up
- */
- r2++;
- }
- }
- else
- {
- /*
- * Minuend used up: add any remaining piece before advancing.
- */
- if (r1->x2 > x1)
- {
- MEMCHECK(pReg, pNextRect, pReg->rects);
- pNextRect->x1 = x1;
- pNextRect->y1 = y1;
- pNextRect->x2 = r1->x2;
- pNextRect->y2 = y2;
- pReg->numRects += 1;
- pNextRect++;
- assert(pReg->numRects<=pReg->size);
- }
- r1++;
- if (r1 != r1End)
- x1 = r1->x1;
- }
+ if (r2->x2 <= x1)
+ {
+ /*
+ * Subtrahend missed the boat: go to next subtrahend.
+ */
+ r2++;
+ }
+ else if (r2->x1 <= x1)
+ {
+ /*
+ * Subtrahend preceeds minuend: nuke left edge of minuend.
+ */
+ x1 = r2->x2;
+ if (x1 >= r1->x2)
+ {
+ /*
+ * Minuend completely covered: advance to next minuend and
+ * reset left fence to edge of new minuend.
+ */
+ r1++;
+ if (r1 != r1End)
+ x1 = r1->x1;
+ }
+ else
+ {
+ /*
+ * Subtrahend now used up since it doesn't extend beyond
+ * minuend
+ */
+ r2++;
+ }
+ }
+ else if (r2->x1 < r1->x2)
+ {
+ /*
+ * Left part of subtrahend covers part of minuend: add uncovered
+ * part of minuend to region and skip to next subtrahend.
+ */
+ assert(x1<r2->x1);
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->x1 = x1;
+ pNextRect->y1 = y1;
+ pNextRect->x2 = r2->x1;
+ pNextRect->y2 = y2;
+ pReg->numRects += 1;
+ pNextRect++;
+
+ assert(pReg->numRects<=pReg->size);
+
+ x1 = r2->x2;
+ if (x1 >= r1->x2)
+ {
+ /*
+ * Minuend used up: advance to new...
+ */
+ r1++;
+ if (r1 != r1End)
+ x1 = r1->x1;
+ }
+ else
+ {
+ /*
+ * Subtrahend used up
+ */
+ r2++;
+ }
+ }
+ else
+ {
+ /*
+ * Minuend used up: add any remaining piece before advancing.
+ */
+ if (r1->x2 > x1)
+ {
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->x1 = x1;
+ pNextRect->y1 = y1;
+ pNextRect->x2 = r1->x2;
+ pNextRect->y2 = y2;
+ pReg->numRects += 1;
+ pNextRect++;
+ assert(pReg->numRects<=pReg->size);
+ }
+ r1++;
+ if (r1 != r1End)
+ x1 = r1->x1;
+ }
}
/*
*/
while (r1 != r1End)
{
- assert(x1<r1->x2);
- MEMCHECK(pReg, pNextRect, pReg->rects);
- pNextRect->x1 = x1;
- pNextRect->y1 = y1;
- pNextRect->x2 = r1->x2;
- pNextRect->y2 = y2;
- pReg->numRects += 1;
- pNextRect++;
-
- assert(pReg->numRects<=pReg->size);
-
- r1++;
- if (r1 != r1End)
- {
- x1 = r1->x1;
- }
+ assert(x1<r1->x2);
+ MEMCHECK(pReg, pNextRect, pReg->rects);
+ pNextRect->x1 = x1;
+ pNextRect->y1 = y1;
+ pNextRect->x2 = r1->x2;
+ pNextRect->y2 = y2;
+ pReg->numRects += 1;
+ pNextRect++;
+
+ assert(pReg->numRects<=pReg->size);
+
+ r1++;
+ if (r1 != r1End)
+ {
+ x1 = r1->x1;
+ }
}
- return 0; /* lint */
+ return 0; /* lint */
}
-
+
/*-
*-----------------------------------------------------------------------
* miSubtract --
- * Subtract regS from regM and leave the result in regD.
- * S stands for subtrahend, M for minuend and D for difference.
+ * Subtract regS from regM and leave the result in regD.
+ * S stands for subtrahend, M for minuend and D for difference.
*
* Results:
- * true.
+ * true.
*
* Side Effects:
- * regD is overwritten.
+ * regD is overwritten.
*
*-----------------------------------------------------------------------
*/
-bool REGION::
-XSubtractRegion(
- Region regM,
- Region regS,
- register Region regD)
+bool REGION::XSubtractRegion(Region regM, Region regS, register Region regD)
{
/* check for trivial reject */
if ( (!(regM->numRects)) || (!(regS->numRects)) ||
- (!EXTENTCHECK(®M->extents, ®S->extents)) )
+ (!EXTENTCHECK(®M->extents, ®S->extents)) )
{
- miRegionCopy(regD, regM);
+ miRegionCopy(regD, regM);
return true;
}
-
- miRegionOp (regD, regM, regS, miSubtractO,
- miSubtractNonO1, NULL);
+
+ miRegionOp (regD, regM, regS, miSubtractO,
+ miSubtractNonO1, NULL);
/*
* Can't alter newReg's extents before we call miRegionOp because
return true;
}
-bool REGION::
-XXorRegion(Region sra, Region srb, Region dr)
+bool REGION::XXorRegion(Region sra, Region srb, Region dr)
{
- Region tra, trb;
+ Region tra = XCreateRegion();
+
+ wxCHECK_MSG( tra, false, wxT("region not created") );
+
+ Region trb = XCreateRegion();
+
+ wxCHECK_MSG( trb, false, wxT("region not created") );
- if ((! (tra = XCreateRegion())) || (! (trb = XCreateRegion())))
- return 0;
(void) XSubtractRegion(sra,srb,tra);
(void) XSubtractRegion(srb,sra,trb);
(void) XUnionRegion(tra,trb,dr);
}
/*
- * Check to see if the region is empty. Assumes a region is passed
+ * Check to see if the region is empty. Assumes a region is passed
* as a parameter
*/
-bool REGION::
-XEmptyRegion(
- Region r)
+bool REGION::XEmptyRegion(Region r)
{
if( r->numRects == 0 ) return true;
else return false;
}
/*
- * Check to see if two regions are equal
+ * Check to see if two regions are equal
*/
-bool REGION::
-XEqualRegion(Region r1, Region r2)
+bool REGION::XEqualRegion(Region r1, Region r2)
{
int i;
else if ( r1->extents.y1 != r2->extents.y1 ) return false;
else if ( r1->extents.y2 != r2->extents.y2 ) return false;
else for( i=0; i < r1->numRects; i++ ) {
- if ( r1->rects[i].x1 != r2->rects[i].x1 ) return false;
- else if ( r1->rects[i].x2 != r2->rects[i].x2 ) return false;
- else if ( r1->rects[i].y1 != r2->rects[i].y1 ) return false;
- else if ( r1->rects[i].y2 != r2->rects[i].y2 ) return false;
+ if ( r1->rects[i].x1 != r2->rects[i].x1 ) return false;
+ else if ( r1->rects[i].x2 != r2->rects[i].x2 ) return false;
+ else if ( r1->rects[i].y1 != r2->rects[i].y1 ) return false;
+ else if ( r1->rects[i].y2 != r2->rects[i].y2 ) return false;
}
return true;
}
-bool REGION::
-XPointInRegion(
- Region pRegion,
- int x, int y)
+bool REGION::XPointInRegion(Region pRegion, int x, int y)
{
int i;
for (i=0; i<pRegion->numRects; i++)
{
if (INBOX (pRegion->rects[i], x, y))
- return true;
+ return true;
}
return false;
}
-wxRegionContain REGION::
-XRectInRegion(
- register Region region,
- int rx, int ry,
- unsigned int rwidth, unsigned int rheight)
+wxRegionContain REGION::XRectInRegion(register Region region,
+ int rx, int ry,
+ unsigned int rwidth,
+ unsigned int rheight)
{
register BoxPtr pbox;
register BoxPtr pboxEnd;
prect->y1 = ry;
prect->x2 = rwidth + rx;
prect->y2 = rheight + ry;
-
+
/* this is (just) a useful optimization */
if ((region->numRects == 0) || !EXTENTCHECK(®ion->extents, prect))
return(wxOutRegion);
- partOut = FALSE;
- partIn = FALSE;
+ partOut = false;
+ partIn = false;
- /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */
+ /* can stop when both partOut and partIn are true, or we reach prect->y2 */
for (pbox = region->rects, pboxEnd = pbox + region->numRects;
- pbox < pboxEnd;
- pbox++)
+ pbox < pboxEnd;
+ pbox++)
{
- if (pbox->y2 <= ry)
- continue; /* getting up to speed or skipping remainder of band */
-
- if (pbox->y1 > ry)
- {
- partOut = TRUE; /* missed part of rectangle above */
- if (partIn || (pbox->y1 >= prect->y2))
- break;
- ry = pbox->y1; /* x guaranteed to be == prect->x1 */
- }
-
- if (pbox->x2 <= rx)
- continue; /* not far enough over yet */
-
- if (pbox->x1 > rx)
- {
- partOut = TRUE; /* missed part of rectangle to left */
- if (partIn)
- break;
- }
-
- if (pbox->x1 < prect->x2)
- {
- partIn = TRUE; /* definitely overlap */
- if (partOut)
- break;
- }
-
- if (pbox->x2 >= prect->x2)
- {
- ry = pbox->y2; /* finished with this band */
- if (ry >= prect->y2)
- break;
- rx = prect->x1; /* reset x out to left again */
- } else
- {
- /*
- * Because boxes in a band are maximal width, if the first box
- * to overlap the rectangle doesn't completely cover it in that
- * band, the rectangle must be partially out, since some of it
- * will be uncovered in that band. partIn will have been set true
- * by now...
- */
- break;
- }
+ if (pbox->y2 <= ry)
+ continue; /* getting up to speed or skipping remainder of band */
+
+ if (pbox->y1 > ry)
+ {
+ partOut = true; /* missed part of rectangle above */
+ if (partIn || (pbox->y1 >= prect->y2))
+ break;
+ ry = pbox->y1; /* x guaranteed to be == prect->x1 */
+ }
+
+ if (pbox->x2 <= rx)
+ continue; /* not far enough over yet */
+
+ if (pbox->x1 > rx)
+ {
+ partOut = true; /* missed part of rectangle to left */
+ if (partIn)
+ break;
+ }
+
+ if (pbox->x1 < prect->x2)
+ {
+ partIn = true; /* definitely overlap */
+ if (partOut)
+ break;
+ }
+
+ if (pbox->x2 >= prect->x2)
+ {
+ ry = pbox->y2; /* finished with this band */
+ if (ry >= prect->y2)
+ break;
+ rx = prect->x1; /* reset x out to left again */
+ } else
+ {
+ /*
+ * Because boxes in a band are maximal width, if the first box
+ * to overlap the rectangle doesn't completely cover it in that
+ * band, the rectangle must be partially out, since some of it
+ * will be uncovered in that band. partIn will have been set true
+ * by now...
+ */
+ break;
+ }
}
- return(partIn ? ((ry < prect->y2) ? wxPartRegion : wxInRegion) :
- wxOutRegion);
+ return(partIn ? ((ry < prect->y2) ? wxPartRegion : wxInRegion) :
+ wxOutRegion);
}
-