#include <region.h>
Collaboration diagram for Wt::Region:
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 Rect & | boundingRect () const |
const RectArray & | rects () 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 |
Region & | operator|= (const Region &r) |
Region & | operator+= (const Region &r) |
Region & | operator &= (const Region &r) |
Region & | operator-= (const Region &r) |
Region & | operator^= (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 |
pixels outside the region are always ignored
Definition at line 19 of file region.h.
typedef boost::shared_ptr<RectArray> Wt::Region::RectArrayPtr [private] |
Wt::Region::Region | ( | ) |
Wt::Region::Region | ( | const Rect & | rect | ) |
Wt::Region::Region | ( | const Point & | p | ) |
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:
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 }
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 }
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
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 }
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 }
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:
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:
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:
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:
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:
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:
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:
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:
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:
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:
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 }
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:
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:
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:
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().
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.