Wt::Region Class Reference

Region specifies a 'working area' of the screen. More...

#include <region.h>

Collaboration diagram for Wt::Region:

Collaboration graph
[legend]
List of all members.

Public Member Functions

bool isEmpty () const
 true if region empty
bool contains (const Point &p) const
 check if a region contains a point
bool contains (const Rect &r) const
 Check if a region contains/overlaps a rectangle.
void translate (int dx, int dy)
 Move a region by dx, dy.
Region unite (const Region &r) const
Region intersect (const Region &r) const
Region subtract (const Region &r) const
Region eor (const Region &r) const
const RectboundingRect () const
const RectArrayrects () const
 returns the array of rectangles composing the region
Region operator| (const Region &r) const
Region operator+ (const Region &r) const
Region operator & (const Region &r) const
Region operator- (const Region &r) const
Region operator^ (const Region &r) const
Regionoperator|= (const Region &r)
Regionoperator+= (const Region &r)
Regionoperator &= (const Region &r)
Regionoperator-= (const Region &r)
Regionoperator^= (const Region &r)
bool operator== (const Region &r) const
 compare two regions
bool operator!= (const Region &r) const
 compare two regions
Contructors
 Region ()
 Create a new empty region.
 Region (const Rect &rect)
 Region from rectangle.
 Region (const Point &p)
 Region from point.

Protected Member Functions

void detach ()

Private Types

typedef boost::shared_ptr<
RectArray
RectArrayPtr
typedef void(Region::*) overlapFunc (const RectArray &ra1, int start1, int end1, const RectArray &ra2, int start2, int end2, int y1, int y2)
typedef void(Region::*) nonOverlapFunc (const RectArray &ra, int start, int end, int y1, int y2)

Private Member Functions

void merge_rect (const RectArray &ra, int index, int y1, int y2)
void calc_extents ()
int coalesce (int prevStart, int curStart)
void regionOp (const Region &other, overlapFunc overlapFn, nonOverlapFunc nonOverlap1Fn, nonOverlapFunc nonOverlap2Fn)
void unionNonO (const RectArray &ra, int start, int end, int y1, int y2)
void unionO (const RectArray &ra1, int start1, int end1, const RectArray &ra2, int start2, int end2, int y1, int y2)
void intersectO (const RectArray &ra1, int start1, int end1, const RectArray &ra2, int start2, int end2, int y1, int y2)
void subtractNonO (const RectArray &ra, int start, int end, int y1, int y2)
void subtractO (const RectArray &ra1, int start1, int end1, const RectArray &ra2, int start2, int end2, int y1, int y2)

Private Attributes

RectArrayPtr rects_
Rect extents

Detailed Description

Region specifies a 'working area' of the screen.

pixels outside the region are always ignored

Definition at line 19 of file region.h.


Member Typedef Documentation

typedef void(Region::*) Wt::Region::nonOverlapFunc(const RectArray &ra, int start, int end, int y1, int y2) [private]

Definition at line 97 of file region.h.

typedef void(Region::*) Wt::Region::overlapFunc(const RectArray &ra1, int start1, int end1, const RectArray &ra2, int start2, int end2, int y1, int y2) [private]

Definition at line 94 of file region.h.

typedef boost::shared_ptr<RectArray> Wt::Region::RectArrayPtr [private]

Definition at line 89 of file region.h.


Constructor & Destructor Documentation

Wt::Region::Region (  ) 

Create a new empty region.

Definition at line 80 of file region.cpp.

00081         : rects_(new RectArray),
00082 extents(0, 0, 0, 0) {}

Wt::Region::Region ( const Rect rect  ) 

Region from rectangle.

Definition at line 84 of file region.cpp.

00085         : rects_(new RectArray(1, rect)),
00086 extents(rect) {}

Wt::Region::Region ( const Point p  ) 

Region from point.

Definition at line 88 of file region.cpp.

00089         : rects_(new RectArray(1, Rect(p.x(), p.y(), 1, 1))),
00090 extents(rects()[0]) {}


Member Function Documentation

const Rect& Wt::Region::boundingRect (  )  const [inline]

Definition at line 57 of file region.h.

References extents.

Referenced by Wt::Widget::mapToGlobal(), Wt::Widget::mapToParent(), and Wt::operator<<().

00057                                      {
00058         return extents;
00059     }

void Wt::Region::calc_extents (  )  [private]

Definition at line 375 of file region.cpp.

References Wt::SDLRect::bottom(), extents, Wt::Rect::isValid(), Wt::SDLRect::left(), rects(), Wt::SDLRect::right(), Wt::Rect::setCoords(), Wt::SDLRect::setRect(), and Wt::SDLRect::top().

Referenced by intersect(), and subtract().

00375                           {
00376     const int n = rects().size();
00377 
00378     if (!n) {
00379         extents.setRect(0, 0, 0, 0);
00380         return;
00381     }
00382 
00383     const RectArray& ra = rects();
00384     /*
00385      * Since pBox is the first rectangle in the region, it must have the
00386      * smallest y1 and since pBoxEnd is the last rectangle in the region,
00387      * it must have the largest y2, because of banding. Initialize x1 and
00388      * x2 from  pBox and pBoxEnd, resp., as good things to initialize them
00389      * to...
00390      */
00391     extents.setCoords(ra[0].x(), ra[0].y(), ra[0].right(), ra[n - 1].bottom());
00392 
00393     assert(extents.isValid());
00394     for (int i = 1; i < n; i++) {
00395         extents.setCoords(std::min(ra[i].left(), extents.left()), extents.top(),
00396                           std::max(ra[i].right(), extents.right()), extents.bottom());
00397     }
00398     assert(extents.isValid());
00399 }

Here is the call graph for this function:

int Wt::Region::coalesce ( int  prevStart,
int  curStart 
) [private]

Definition at line 423 of file region.cpp.

References rects_.

Referenced by regionOp().

00426 {
00427     int curNumRects = 0; /* Number of rectangles in current band */
00428     int prevNumRects = curStart - prevStart;
00429 
00430     RectArray& ra = *rects_;
00431     const int n = ra.size();
00432     int numRects = n;
00433 
00434     int bandY1 = ra[curStart].top(); /* Y1 coordinate for current band */
00435     int current;
00436     int current_prev = prevStart;
00437     int current_end = n;
00438 
00439     /*
00440      * Figure out how many rectangles are in the current band. Have to do
00441      * this because multiple bands could have been added in miRegionOp
00442      * at the end when one region has been exhausted.
00443      */
00444     for (current = curStart; current < n
00445             && ra[current].top() == bandY1; current++) {
00446         curNumRects++;
00447     }
00448 
00449     if (current != current_end) {
00450         /*
00451          * If more than one band was added, we have to find the start
00452          * of the last band added so the next coalescing job can start
00453          * at the right place... (given when multiple bands are added,
00454          * this may be pointless -- see above).
00455          */
00456         current_end--;
00457         while (ra[current_end - 1].top() == ra[current_end].top()) {
00458             current_end--;
00459         }
00460         curStart = current_end;
00461         current_end = n;
00462     }
00463 
00464     if ((curNumRects == prevNumRects) && (curNumRects != 0)) {
00465         current -= curNumRects;
00466 
00467         /*
00468          * The bands may only be coalesced if the bottom of the previous
00469          * matches the top scanline of the current.
00470          */
00471         if (ra[current_prev].bottom() == ra[current].top() - 1) {
00472             //if (pPrevBox->bottom() == pCurBox->top() - 1) {
00473             /*
00474              * Make sure the bands have boxes in the same places. This
00475              * assumes that boxes have been added in such a way that they
00476              * cover the most area possible. I.e. two boxes in a band must
00477              * have some horizontal space between them.
00478              */
00479 
00480             do {
00481                 if ((ra[current_prev].left() != ra[current].left()) ||
00482                         (ra[current_prev].right() != ra[current].right())) {
00483                     /*
00484                      * The bands don't line up so they can't be coalesced.
00485                      */
00486                     return curStart;
00487                 }
00488                 current_prev++;
00489                 current++;
00490                 prevNumRects -= 1;
00491             } while (prevNumRects != 0);
00492 
00493             numRects -= curNumRects;
00494             rects_->resize(numRects);
00495             current -= curNumRects;
00496             current_prev -= curNumRects;
00497 
00498             /*
00499              * The bands may be merged, so set the bottom y of each box
00500              * in the previous band to that of the corresponding box in
00501              * the current band.
00502              */
00503 
00504             do {
00505                 ra[current_prev].setBottom(ra[current].bottom());
00506                 current_prev++;
00507                 current++;
00508                 curNumRects--;
00509             } while (curNumRects != 0);
00510 
00511             /*
00512              * If only one band was added to the region, we have to backup
00513              * curStart to the start of the previous band.
00514              *
00515              * If more than one band was added to the region, copy the
00516              * other bands down. The assumption here is that the other bands
00517              * came from the same region as the current one and no further
00518              * coalescing can be done on them since it's all been done
00519              * already... curStart is already in the right place.
00520              */
00521             if (current == current_end) {
00522                 curStart = prevStart;
00523             } else {
00524                 do {
00525                     ra[current_prev] = ra[current];
00526                     current_prev++;
00527                     current++;
00528                 } while (current != current_end);
00529             }
00530         }
00531     }
00532     return curStart;
00533 }

bool Wt::Region::contains ( const Rect r  )  const

Check if a region contains/overlaps a rectangle.

Definition at line 107 of file region.cpp.

References Wt::SDLRect::bottom(), extents, Wt::SDLRect::intersects(), Wt::SDLRect::left(), rects(), Wt::SDLRect::right(), Wt::SDLRect::x(), and Wt::SDLRect::y().

00107                                             {
00108     const int n = rects().size();
00109 
00110     /* this is (just) a useful optimization */
00111     if (!n || !extents.intersects(rect))
00112         return false;
00113 
00114     bool partIn = false;
00115     bool partOut = false;
00116     int rx = rect.x();
00117     int ry = rect.y();
00118     const RectArray& ra = rects();
00119 
00120     /* can stop when both partOut and partIn are TRUE, or we reach prect->y2 */
00121     for (int i = 0; i < n; i++) {
00122         const Rect& pbox = ra[i];
00123 
00124         if (pbox.bottom() < ry)
00125             continue;   /* getting up to speed or skipping remainder of band */
00126 
00127         if (pbox.top() > ry) {
00128             partOut = true; /* missed part of rectangle above */
00129             if (partIn || (pbox.top() > rect.bottom()))
00130                 break;
00131             ry = pbox.top();    /* x guaranteed to be == prect->x1 */
00132         }
00133 
00134         if (pbox.right() < rx)
00135             continue;       /* not far enough over yet */
00136 
00137         if (pbox.left() > rx) {
00138             partOut = true; /* missed part of rectangle to left */
00139             if (partIn)
00140                 break;
00141         }
00142 
00143         if (pbox.left() <= rect.right()) {
00144             partIn = true;  /* definitely overlap */
00145             if (partOut)
00146                 break;
00147         }
00148 
00149         if (pbox.right() >= rect.right()) {
00150             ry = pbox.bottom() + 1; /* finished with this band */
00151             if (ry > rect.bottom())
00152                 break;
00153             rx = rect.left();   /* reset x out to left again */
00154         } else {
00155             /*
00156              * Because boxes in a band are maximal width, if the first box
00157              * to overlap the rectangle doesn't completely cover it in that
00158              * band, the rectangle must be partially out, since some of it
00159              * will be uncovered in that band. partIn will have been set true
00160              * by now...
00161              */
00162             break;
00163         }
00164     }
00165 
00166     return (partIn ? ((ry <= rect.bottom()) ? false: true) : false);
00167 }

Here is the call graph for this function:

bool Wt::Region::contains ( const Point p  )  const

check if a region contains a point

Definition at line 92 of file region.cpp.

References Wt::Rect::contains(), extents, and rects().

00092                                           {
00093     const int n = rects().size();
00094     if (!n)
00095         return false;
00096     if (!extents.contains(p))
00097         return false;
00098 
00099     const RectArray& ra = rects();
00100     for (int i=0; i < n; i++) {
00101         if (ra[i].contains(p))
00102             return true;
00103     }
00104     return false;
00105 }

Here is the call graph for this function:

void Wt::Region::detach (  )  [protected]

Definition at line 353 of file region.cpp.

References rects_.

Referenced by intersect(), operator &=(), operator+=(), operator-=(), operator^=(), operator|=(), subtract(), translate(), and unite().

00353                     {
00354     //avoid detaching if we are the only client for this surface
00355     if (!rects_.unique()) {
00356         rects_.reset(new RectArray(*rects_));
00357     }
00358 }

Region Wt::Region::eor ( const Region r  )  const

Definition at line 274 of file region.cpp.

Referenced by operator^().

00274                                         {
00275     Region r1(*this);
00276     Region temp(r - r1);
00277 
00278     r1 -= r;
00279 
00280     return r1 |= temp;
00281 }

Region Wt::Region::intersect ( const Region r  )  const

Definition at line 227 of file region.cpp.

References calc_extents(), detach(), extents, intersectO(), Wt::SDLRect::intersects(), rects(), rects_, and regionOp().

Referenced by operator &().

00227                                               {
00228     const int n = rects().size();
00229     const int rn = r.rects().size();
00230     Region r1(*this);
00231     r1.detach();
00232 
00233     /* check for trivial reject */
00234     if (!n || !rn || !r1.extents.intersects(r.extents))
00235         r1.rects_->clear();
00236     else
00237         r1.regionOp(r, &Region::intersectO, 0, 0);
00238 
00239     /*
00240      * Can't alter region's extents before miRegionOp depends on the
00241      * extents of the regions being unchanged. Besides, this way there's
00242      * no checking against rectangles that will be nuked due to
00243      * coalescing, so we have to examine fewer rectangles.
00244      */
00245     r1.calc_extents();
00246 
00247     return r1;
00248 }

Here is the call graph for this function:

void Wt::Region::intersectO ( const RectArray ra1,
int  start1,
int  end1,
const RectArray ra2,
int  start2,
int  end2,
int  y1,
int  y2 
) [private]

Definition at line 847 of file region.cpp.

References rects_.

Referenced by intersect().

00849                                         {
00850     while ((i1 != end1) && (i2 != end2)) {
00851         int x1 = std::max (ra1[i1].left(), ra2[i2].left());
00852         int x2 = std::min (ra1[i1].right(), ra2[i2].right());
00853 
00854         /*
00855          * If there's any overlap between the two rectangles, add that
00856          * overlap to the new region.
00857          * There's no need to check for subsumption because the only way
00858          * such a need could arise is if some region has two rectangles
00859          * right next to each other. Since that should never happen...
00860          */
00861         if (x1 <= x2) {
00862             assert (y1 <= y2);
00863             rects_->push_back(Rect(x1, y1, x2 - x1 + 1, y2 - y1 + 1));
00864         }
00865 
00866         /*
00867          * Need to advance the pointers. Shift the one that extends
00868          * to the right the least, since the other still has a chance to
00869          * overlap with that region's next rectangle, if you see what I mean.
00870          */
00871         if (ra1[i1].right() < ra2[i2].right()) {
00872             i1++;
00873         } else if (ra2[i2].right() < ra1[i1].right()) {
00874             i2++;
00875         } else {
00876             i1++;
00877             i2++;
00878         }
00879     }
00880 }

bool Wt::Region::isEmpty (  )  const [inline]

true if region empty

Note:
the defauly copy constructor, assignment operator and destructor should be ok

Definition at line 38 of file region.h.

References rects_.

Referenced by Wt::RootWindow::blit_region_ex(), and Wt::Application::postEvent().

00038                          {
00039         return rects_->size() == 0;
00040     }

void Wt::Region::merge_rect ( const RectArray ra,
int  index,
int  y1,
int  y2 
) [private]

Definition at line 774 of file region.cpp.

References rects_.

Referenced by unionO().

00774                                                                   {
00775     RectArray& lra = *rects_;
00776     const int total = lra.size();
00777 
00778     if ((total != 0) &&
00779             (lra[total - 1].top() == y1) &&
00780             (lra[total - 1].bottom() == y2) &&
00781             (lra[total - 1].right() + 1 >= ra[i].left())) {
00782 
00783         lra[total - 1].setRight(std::max(lra[total - 1].right(), ra[i].right()));
00784         assert(lra[total - 1].left() <= lra[total - 1].right());
00785     } else {
00786         lra.push_back(Rect(ra[i].left(), y1,
00787                            ra[i].width(), y2 - y1 + 1));
00788     }
00789 }

Region Wt::Region::operator & ( const Region r  )  const

Definition at line 291 of file region.cpp.

References intersect().

00291                                               {
00292     return this->intersect(r);
00293 }

Here is the call graph for this function:

Region & Wt::Region::operator &= ( const Region r  ) 

Definition at line 315 of file region.cpp.

References detach().

00315                                           {
00316     detach();
00317     *this = *this & r;
00318     return *this;
00319 }

Here is the call graph for this function:

bool Wt::Region::operator!= ( const Region r  )  const [inline]

compare two regions

Definition at line 81 of file region.h.

References operator==().

00081                                            {
00082         return !operator==(r);
00083     }

Here is the call graph for this function:

Region Wt::Region::operator+ ( const Region r  )  const

Definition at line 287 of file region.cpp.

References unite().

00287                                               {
00288     return this->unite(r);
00289 }

Here is the call graph for this function:

Region & Wt::Region::operator+= ( const Region r  ) 

Definition at line 309 of file region.cpp.

References detach().

00309                                           {
00310     detach();
00311     *this = *this + r;
00312     return *this;
00313 }

Here is the call graph for this function:

Region Wt::Region::operator- ( const Region r  )  const

Definition at line 295 of file region.cpp.

References subtract().

00295                                               {
00296     return this->subtract(r);
00297 }

Here is the call graph for this function:

Region & Wt::Region::operator-= ( const Region r  ) 

Definition at line 321 of file region.cpp.

References detach().

00321                                           {
00322     detach();
00323     *this = *this - r;
00324     return *this;
00325 }

Here is the call graph for this function:

bool Wt::Region::operator== ( const Region r  )  const

compare two regions

Definition at line 333 of file region.cpp.

References extents, and rects().

Referenced by operator!=().

00333                                                  {
00334     const int n = rects().size();
00335     const int other_n = other.rects().size();
00336     if (n!= other_n)
00337         return false;
00338     else if (!n)
00339         return true;
00340     else if (extents != other.extents)
00341         return false;
00342     else {
00343         const RectArray& ra = rects();
00344         const RectArray& other_ra = other.rects();
00345         for (int i = 0; i < n; i++) {
00346             if (ra[i] != other_ra[i])
00347                 return false;
00348         }
00349     }
00350     return true;
00351 }

Here is the call graph for this function:

Region Wt::Region::operator^ ( const Region r  )  const

Definition at line 299 of file region.cpp.

References eor().

00299                                               {
00300     return this->eor(r);
00301 }

Here is the call graph for this function:

Region & Wt::Region::operator^= ( const Region r  ) 

Definition at line 327 of file region.cpp.

References detach().

00327                                           {
00328     detach();
00329     *this = *this ^ r;
00330     return *this;
00331 }

Here is the call graph for this function:

Region Wt::Region::operator| ( const Region r  )  const

Definition at line 283 of file region.cpp.

References unite().

00283                                               {
00284     return this->unite(r);
00285 }

Here is the call graph for this function:

Region & Wt::Region::operator|= ( const Region r  ) 

Definition at line 303 of file region.cpp.

References detach().

00303                                           {
00304     detach();
00305     *this = *this | r;
00306     return *this;
00307 }

Here is the call graph for this function:

const RectArray& Wt::Region::rects (  )  const [inline]

returns the array of rectangles composing the region

Definition at line 62 of file region.h.

References rects_.

Referenced by Wt::PixmapOf< Wt::SDLSurface >::blend(), calc_extents(), contains(), Wt::Widget::erase(), Wt::PixmapOf< Wt::SDLSurface >::fill(), intersect(), Wt::operator<<(), operator==(), regionOp(), subtract(), unite(), and Wt::Display::update().

00062                                    {
00063         return *rects_;
00064     }

void Wt::Region::regionOp ( const Region other,
overlapFunc  overlapFn,
nonOverlapFunc  nonOverlap1Fn,
nonOverlapFunc  nonOverlap2Fn 
) [private]

Definition at line 561 of file region.cpp.

References coalesce(), extents, rects(), rects_, and Wt::SDLRect::top().

Referenced by intersect(), subtract(), and unite().

00566 {
00567     int ybot;           /* Bottom of intersection */
00568     int ytop;           /* Top of intersection */
00569     unsigned int prevBand;  /* Index of start of previous band in newReg */
00570     unsigned int curBand;   /* Index of start of current band in newReg */
00571     int top;            /* Top of non-overlapping band */
00572     int bot;            /* Bottom of non-overlapping band */
00573 
00574     /*
00575      * Initialization:
00576      *  set r1, r2, r1End and r2End appropriately, preserve the important
00577      * parts of the destination region until the end in case it's one of
00578      * the two source regions, then mark the "new" region empty, allocating
00579      * another array of rectangles for it to use.
00580      */
00581     const RectArray& ra1 = rects();
00582     const int n1 = ra1.size();
00583     int i1 = 0;
00584     const RectArray& ra2 = other.rects();
00585     const int n2 = ra2.size();
00586     int i2 = 0;
00587     // keep one copy
00588     RectArrayPtr old_rects_ = rects_;
00589     int band_1_end;
00590     int band_2_end;
00591 
00592     /*
00593      * Allocate a reasonable number of rectangles for the new region. The idea
00594      * is to allocate enough so the individual functions don't need to
00595      * reallocate and copy the array, which is time consuming, yet we don't
00596      * have to worry about using too much memory. I hope to be able to
00597      * nuke the Xrealloc() at the end of this function eventually.
00598      */
00599     rects_.reset(new RectArray);
00600     rects_->reserve(std::max(n1, n2) * 2);
00601 
00602     /*
00603      * Initialize ybot and ytop.
00604      * In the upcoming loop, ybot and ytop serve different functions depending
00605      * on whether the band being handled is an overlapping or non-overlapping
00606      * band.
00607      *  In the case of a non-overlapping band (only one of the regions
00608      * has points in the band), ybot is the bottom of the most recent
00609      * intersection and thus clips the top of the rectangles in that band.
00610      * ytop is the top of the next intersection between the two regions and
00611      * serves to clip the bottom of the rectangles in the current band.
00612      *  For an overlapping band (where the two regions intersect), ytop clips
00613      * the top of the rectangles of both regions and ybot clips the bottoms.
00614      */
00615     //ybot = std::min(reg1->extents.top(), reg2->extents.top()) - 1;
00616     ybot = std::min(extents.top(), other.extents.top()) - 1;
00617 
00618     /*
00619      * prevBand serves to mark the start of the previous band so rectangles
00620      * can be coalesced into larger rectangles. qv. miCoalesce, above.
00621      * In the beginning, there is no previous band, so prevBand == curBand
00622      * (curBand is set later on, of course, but the first band will always
00623      * start at index 0). prevBand and curBand must be indices because of
00624      * the possible expansion, and resultant moving, of the new region's
00625      * array of rectangles.
00626      */
00627     prevBand = 0;
00628 
00629     do {
00630         curBand = rects().size();
00631 
00632         /*
00633          * This algorithm proceeds one source-band (as opposed to a
00634          * destination band, which is determined by where the two regions
00635          * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
00636          * rectangle after the last one in the current band for their
00637          * respective regions.
00638          */
00639         for (band_1_end = i1; band_1_end < n1 &&
00640             ra1[band_1_end].top() == ra1[i1].top(); band_1_end++) {}
00641 
00642         for (band_2_end = i2; band_2_end < n2 &&
00643             ra2[band_2_end].top() == ra2[i2].top(); band_2_end++) {}
00644 
00645         /*
00646          * First handle the band that doesn't intersect, if any.
00647          *
00648          * Note that attention is restricted to one band in the
00649          * non-intersecting region at once, so if a region has n
00650          * bands between the current position and the next place it overlaps
00651          * the other, this entire loop will be passed through n times.
00652          */
00653         if (ra1[i1].top() < ra2[i2].top()) {
00654             top = std::max (ra1[i1].top(), ybot + 1);
00655             bot = std::min (ra1[i1].bottom(), ra2[i2].top() - 1);
00656 
00657             if ((top != bot + 1) && (nonOverlap1Fn != 0)) {
00658                 (this->*nonOverlap1Fn)(ra1, i1, band_1_end, top, bot);
00659             }
00660 
00661             ytop = ra2[i2].top();
00662         } else if (ra2[i2].top() < ra1[i1].top()) {
00663             top = std::max (ra2[i2].top(), ybot + 1);
00664             bot = std::min (ra2[i2].bottom(), ra1[i1].top() - 1);
00665 
00666             if ((top != bot + 1) && (nonOverlap2Fn != 0)) {
00667                 (this->*nonOverlap2Fn)(ra2, i2, band_2_end, top, bot);
00668             }
00669 
00670             ytop = ra1[i1].top();
00671         } else {
00672             ytop = ra1[i1].top();
00673         }
00674 
00675         /*
00676          * If any rectangles got added to the region, try and coalesce them
00677          * with rectangles from the previous band. Note we could just do
00678          * this test in miCoalesce, but some machines incur a not
00679          * inconsiderable cost for function calls, so...
00680          */
00681         if (rects().size() != curBand) {
00682             prevBand = coalesce(prevBand, curBand);
00683         }
00684 
00685         /*
00686          * Now see if we've hit an intersecting band. The two bands only
00687          * intersect if ybot > ytop
00688          */
00689         ybot = std::min(ra1[i1].bottom(), ra2[i2].bottom());
00690         curBand = rects().size();
00691         if (ybot >= ytop) {
00692             (this->*overlapFn)(ra1, i1, band_1_end, ra2,
00693                                i2, band_2_end, ytop, ybot);
00694         }
00695 
00696         if (rects().size() != curBand) {
00697             prevBand = coalesce(prevBand, curBand);
00698         }
00699 
00700         /*
00701          * If we've finished with a band (y2 == ybot) we skip forward
00702          * in the region to the next band.
00703          */
00704         if (ra1[i1].bottom() == ybot) {
00705             i1 = band_1_end;
00706         }
00707         if (ra2[i2].bottom() == ybot) {
00708             i2 = band_2_end;
00709         }
00710     } while ((i1 != n1) && (i2 != n2));
00711 
00712     /*
00713      * Deal with whichever region still has rectangles left.
00714      */
00715     curBand = rects().size();
00716     if (i1 != n1 && nonOverlap1Fn) {
00717         do {
00718             for (band_1_end = i1; band_1_end < n1 &&
00719                 ra1[band_1_end].top() == ra1[i1].top(); band_1_end++) {}
00720 
00721             (this->*nonOverlap1Fn)(ra1, i1, band_1_end,
00722                                    std::max(ra1[i1].top(), ybot + 1),
00723                                    ra1[i1].bottom());
00724             i1 = band_1_end;
00725         } while (i1 != n1);
00726     } else if (i2 != n2 && nonOverlap2Fn) {
00727         do {
00728             for (band_2_end = i2; band_2_end < n2 &&
00729                 ra2[band_2_end].top() == ra2[i2].top(); band_2_end++) {}
00730 
00731             (this->*nonOverlap2Fn)(ra2, i2, band_2_end,
00732                                    std::max(ra2[i2].top(), ybot + 1),
00733                                    ra2[i2].bottom());
00734             i2 = band_2_end;
00735         } while (i2 != n2);
00736     }
00737 
00738     if (rects().size() != curBand) {
00739         coalesce(prevBand, curBand);
00740     }
00741 }

Here is the call graph for this function:

Region Wt::Region::subtract ( const Region r  )  const

Definition at line 250 of file region.cpp.

References calc_extents(), detach(), extents, Wt::SDLRect::intersects(), rects(), regionOp(), subtractNonO(), and subtractO().

Referenced by operator-().

00250                                              {
00251     const int n = rects().size();
00252     const int rn = r.rects().size();
00253 
00254     /* check for trivial reject */
00255     if (!n || !rn || !extents.intersects(r.extents))
00256         return *this;
00257 
00258     Region r1(*this);
00259     r1.detach();
00260 
00261     r1.regionOp(r, &Region::subtractO, &Region::subtractNonO, 0);
00262 
00263     /*
00264      * Can't alter region's extents before we call miRegionOp because miRegionOp
00265      * depends on the extents of those regions being the unaltered. Besides, this
00266      * way there's no checking against rectangles that will be nuked
00267      * due to coalescing, so we have to examine fewer rectangles.
00268      */
00269     r1.calc_extents ();
00270 
00271     return r1;
00272 }

Here is the call graph for this function:

void Wt::Region::subtractNonO ( const RectArray ra,
int  start,
int  end,
int  y1,
int  y2 
) [private]

Definition at line 898 of file region.cpp.

References rects_.

Referenced by subtract().

00899                                                          {
00900     assert(y1 <= y2);
00901 
00902     for (int i = start; i < end; i++) {
00903         assert(ra[i].left() <= ra[i].right());
00904         rects_->push_back(Rect(ra[i].left(), y1,
00905                                ra[i].width(), y2 - y1 + 1));
00906     }
00907 }

void Wt::Region::subtractO ( const RectArray ra1,
int  start1,
int  end1,
const RectArray ra2,
int  start2,
int  end2,
int  y1,
int  y2 
) [private]

Definition at line 923 of file region.cpp.

References rects_.

Referenced by subtract().

00925                                        {
00926     int x1 = ra1[i1].left();
00927 
00928     assert(y1 <= y2);
00929 
00930     while ((i1 != end1) && (i2 != end2)) {
00931         if (ra2[i2].right() < x1) {
00932             /*
00933              * Subtrahend missed the boat: go to next subtrahend.
00934              */
00935             i2++;
00936         } else if (ra2[i2].left() <= x1) {
00937             /*
00938              * Subtrahend preceeds minuend: nuke left edge of minuend.
00939              */
00940             x1 = ra2[i2].right() + 1;
00941             if (x1 > ra1[i1].right()) {
00942                 /*
00943                  * Minuend completely covered: advance to next minuend and
00944                  * reset left fence to edge of new minuend.
00945                  */
00946                 i1++;
00947                 if (i1 != end1)
00948                     x1 = ra1[i1].left();
00949             } else {
00950                 /*
00951                  * Subtrahend now used up since it doesn't extend beyond
00952                  * minuend
00953                  */
00954                 i2++;
00955             }
00956         } else if (ra2[i2].left() <= ra1[i1].right()) {
00957             /*
00958              * Left part of subtrahend covers part of minuend: add uncovered
00959              * part of minuend to region and skip to next subtrahend.
00960              */
00961             assert(x1 < ra2[i2].left());
00962             rects_->push_back(Rect(x1, y1, ra2[i2].left() - x1, y2 - y1 + 1));
00963 
00964             x1 = ra2[i2].right() + 1;
00965             if (x1 > ra1[i1].right()) {
00966                 /*
00967                  * Minuend used up: advance to new...
00968                  */
00969                 i1++;
00970                 if (i1 != end1)
00971                     x1 = ra1[i1].left();
00972             } else {
00973                 /*
00974                  * Subtrahend used up
00975                  */
00976                 i2++;
00977             }
00978         } else {
00979             /*
00980              * Minuend used up: add any remaining piece before advancing.
00981              */
00982             if (ra1[i1].right() >= x1) {
00983                 rects_->push_back(Rect(x1, y1,
00984                                        ra1[i1].right() - x1 + 1, y2 - y1 + 1));
00985             }
00986             i1++;
00987             if (i1 != end1)
00988                 x1 = ra1[i1].left();
00989         }
00990     }
00991 
00992     /*
00993        * Add remaining minuend rectangles to region.
00994        */
00995     while(i1 != end1) {
00996         assert(x1 <= ra1[i1].right());
00997         rects_->push_back(Rect(x1, y1,
00998                                ra1[i1].right() - x1 + 1, y2 - y1 + 1));
00999 
01000         i1++;
01001         if (i1 != end1)
01002             x1 = ra1[i1].left();
01003     }
01004 }

void Wt::Region::translate ( int  dx,
int  dy 
)

Move a region by dx, dy.

Definition at line 173 of file region.cpp.

References detach(), extents, Wt::SDLRect::moveBy(), and rects_.

Referenced by Wt::Widget::mapToGlobal(), and Wt::Widget::mapToParent().

00173                                      {
00174     const int n = rects_->size();
00175     if (!n)
00176         return;
00177 
00178     detach();
00179     RectArray& ra = *rects_;
00180     for (int i = 0; i < n; i++) {
00181         ra[i].moveBy(dx, dy);
00182     }
00183 
00184     extents.moveBy(dx, dy);
00185 }

Here is the call graph for this function:

void Wt::Region::unionNonO ( const RectArray ra,
int  start,
int  end,
int  y1,
int  y2 
) [private]

Definition at line 763 of file region.cpp.

References rects_.

Referenced by unite().

00764                                                            {
00765     assert(y1 <= y2);
00766 
00767     for (int i = start; i < end; i++) {
00768         assert(ra[i].left() <= ra[i].right());
00769         rects_->push_back(Rect(ra[i].left(), y1,
00770                                ra[i].width(), y2 - y1 + 1));
00771     }
00772 }

void Wt::Region::unionO ( const RectArray ra1,
int  start1,
int  end1,
const RectArray ra2,
int  start2,
int  end2,
int  y1,
int  y2 
) [private]

Definition at line 807 of file region.cpp.

References merge_rect().

Referenced by unite().

00809                                     {
00810     assert (y1 <= y2);
00811     while ((i1 != end1) && (i2 != end2)) {
00812         if (ra1[i1].left() < ra2[i2].left()) {
00813             merge_rect(ra1, i1, y1, y2);
00814             i1++;
00815         } else {
00816             merge_rect(ra2, i2, y1, y2);
00817             i2++;
00818         }
00819     }
00820 
00821     while (i1 != end1) {
00822         merge_rect(ra1, i1, y1, y2);
00823         i1++;
00824     }
00825     while (i2 != end2) {
00826         merge_rect(ra2, i2, y1, y2);
00827         i2++;
00828     }
00829 }

Here is the call graph for this function:

Region Wt::Region::unite ( const Region r  )  const

unite

Definition at line 188 of file region.cpp.

References Wt::SDLRect::bottom(), Wt::Rect::contains(), detach(), extents, Wt::SDLRect::left(), rects(), regionOp(), Wt::SDLRect::right(), Wt::Rect::setCoords(), Wt::SDLRect::top(), unionNonO(), and unionO().

Referenced by operator+(), and operator|().

00188                                           {
00189     const int n = rects().size();
00190     /*  checks all the simple cases */
00191 
00192     /*
00193      * region is empty
00194      */
00195     if (!n) {
00196         return r;
00197     }
00198 
00199     const int rn = r.rects().size();
00200     /*
00201      * region and other are the same or other is empty
00202      */
00203     if ( (this == &r) || !rn )
00204         return *this;
00205 
00206     // region completely subsumes other
00207     if ((n == 1) && extents.contains(r.extents))
00208         return *this;
00209 
00210     // other completely subsumes region
00211     if ((rn == 1) && r.extents.contains(extents))
00212         return r;
00213 
00214     Region r1(*this);
00215     r1.detach();
00216 
00217     r1.regionOp(r, &Region::unionO,
00218                 &Region::unionNonO, &Region::unionNonO);
00219     r1.extents.setCoords(std::min(extents.left(), r.extents.left()),
00220                          std::min(extents.top(), r.extents.top()),
00221                          std::max(extents.right(), r.extents.right()),
00222                          std::max(extents.bottom(), r.extents.bottom()));
00223 
00224     return r1;
00225 }

Here is the call graph for this function:


Member Data Documentation

Rect Wt::Region::extents [private]

Definition at line 91 of file region.h.

Referenced by boundingRect(), calc_extents(), contains(), intersect(), operator==(), regionOp(), subtract(), translate(), and unite().

RectArrayPtr Wt::Region::rects_ [private]

Definition at line 90 of file region.h.

Referenced by coalesce(), detach(), intersect(), intersectO(), isEmpty(), merge_rect(), rects(), regionOp(), subtractNonO(), subtractO(), translate(), and unionNonO().


The documentation for this class was generated from the following files:

Generated Fri Jul 28 19:31:34 2006.
Copyright © 1998-2003 by the respective authors.

This document is licensed under the terms of the GNU Free Documentation License and may be freely distributed under the conditions given by this license.