29typedef enum { OGDK_EVEN_ODD_RULE, OGDK_WINDING_RULE } OGdkFillRule;
32 OGDK_OVERLAP_RECTANGLE_IN,
33 OGDK_OVERLAP_RECTANGLE_OUT,
34 OGDK_OVERLAP_RECTANGLE_PART
37#define EMPTY_REGION(pReg) pReg->numRects = 0
38#define REGION_NOT_EMPTY(pReg) pReg->numRects
78#define NUMPTSTOBUFFER 200
89#define INBOX(r, x, y) \
90 ((((r).x2 > x)) && (((r).x1 <= x)) && (((r).y2 > y)) && (((r).y1 <= y)))
96#define EXTENTCHECK(r1, r2) \
97 ((r1)->x2 > (r2)->x1 && (r1)->x1 < (r2)->x2 && (r1)->y2 > (r2)->y1 && \
111#define OGROWREGION(reg, nRects) \
113 if ((nRects) == 0) { \
114 if ((reg)->rects != &(reg)->extents) { \
115 free((reg)->rects); \
116 (reg)->rects = &(reg)->extents; \
118 } else if ((reg)->rects == &(reg)->extents) { \
119 (reg)->rects = (OGdkRegionBox *)malloc(nRects * sizeof(OGdkRegionBox)); \
120 (reg)->rects[0] = (reg)->extents; \
122 (reg)->rects = (OGdkRegionBox *)realloc((reg)->rects, \
123 sizeof(OGdkRegionBox) * nRects); \
124 (reg)->size = (nRects); \
130#define OMEMCHECK(reg, rect, firstrect) \
132 if ((reg)->numRects >= ((reg)->size - 1)) { \
133 OGROWREGION(reg, 2 * (reg)->size); \
134 (rect) = &(firstrect)[(reg)->numRects]; \
139#define MIN(a, b) wxMin(a, b)
143#define MAX(a, b) wxMax(a, b)
165#define OBRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2) \
175 dx = (x2) - xStart; \
179 incr1 = -2 * dx + 2 * (dy) * m1; \
180 incr2 = -2 * dx + 2 * (dy) * m; \
181 d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
185 incr1 = 2 * dx - 2 * (dy) * m1; \
186 incr2 = 2 * dx - 2 * (dy) * m; \
187 d = -2 * m * (dy) + 2 * dx; \
192#define OBRESINCRPGON(d, minval, m, m1, incr1, incr2) \
227#define OBRESINITPGONSTRUCT(dmaj, min1, min2, bres) \
228 OBRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, bres.m, bres.m1, \
229 bres.incr1, bres.incr2)
231#define OBRESINCRPGONSTRUCT(bres) \
232 OBRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, \
239#define COUNTERCLOCKWISE -1
267#define SLLSPERBLOCK 25
287#define OEVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET) \
289 if (pAET->ymax == y) { \
290 pPrevAET->next = pAET->next; \
291 pAET = pPrevAET->next; \
293 if (pAET) pAET->back = pPrevAET; \
295 OBRESINCRPGONSTRUCT(pAET->bres); \
308#define OEVALUATEEDGEEVENODD(pAET, pPrevAET, y) \
310 if (pAET->ymax == y) { \
311 pPrevAET->next = pAET->next; \
312 pAET = pPrevAET->next; \
313 if (pAET) pAET->back = pPrevAET; \
315 OBRESINCRPGONSTRUCT(pAET->bres); \
325bool gdk_region_point_in(
const OGdkRegion *region,
int x,
int y);
326OGdkOverlapType gdk_region_rect_in(
const OGdkRegion *region,
328void gdk_region_offset(
OGdkRegion *region,
int dx,
int dy);
333 OGdkFillRule fill_rule);
337bool gdk_region_empty(
const OGdkRegion *region);
339void gdk_region_get_rectangles(
const OGdkRegion *region,
352 m_region = gdk_region_copy(refData.m_region);
356 if (m_region) gdk_region_destroy(m_region);
367#define M_REGIONDATA ((OCPNRegionRefData *)m_refData)
368#define M_REGIONDATA_OF(rgn) ((OCPNRegionRefData *)(rgn.m_refData))
374#define M_REGIONDATA ((OCPNRegionRefData *)m_refData)
376#ifndef USE_NEW_REGION
378OCPNRegion::OCPNRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h)
379 : wxRegion(x, y, w, h)
383OCPNRegion::OCPNRegion(
const wxPoint &topLeft,
const wxPoint &bottomRight)
384 : wxRegion(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
385 bottomRight.y - topLeft.y) {}
387OCPNRegion::OCPNRegion(
const wxRect &rect)
388 : wxRegion(rect.x, rect.y, rect.width, rect.height) {}
390OCPNRegion::OCPNRegion(
const wxRegion ®ion) : wxRegion(region) {}
392OCPNRegion::OCPNRegion(
size_t n,
const wxPoint *points,
int fillStyle)
393 : wxRegion(n, points,
394#if wxCHECK_VERSION(2, 9, 0)
400wxRegion *OCPNRegion::GetNew_wxRegion()
const {
return new wxRegion(
this); }
406OCPNRegion::OCPNRegion(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
407 InitRect(x, y, w, h);
410OCPNRegion::OCPNRegion(
const wxPoint &topLeft,
const wxPoint &bottomRight) {
411 InitRect(topLeft.x, topLeft.y, bottomRight.x - topLeft.x,
412 bottomRight.y - topLeft.y);
415OCPNRegion::OCPNRegion(
const wxRect &rect) {
416 InitRect(rect.x, rect.y, rect.width, rect.height);
419OCPNRegion::OCPNRegion(
const wxRegion ®ion) {
420 wxRegionIterator ri(region);
421 if (!ri.HaveRects())
return;
423 wxRect rect = ri.GetRect();
424 InitRect(rect.x, rect.y, rect.width, rect.height);
427 while (ri.HaveRects()) {
433OCPNRegion::~OCPNRegion() {}
435void OCPNRegion::InitRect(wxCoord x, wxCoord y, wxCoord w, wxCoord h) {
444 M_REGIONDATA->m_region = gdk_region_rectangle(&rect);
453OCPNRegion::OCPNRegion(
size_t n,
const wxPoint *points,
int fillStyle) {
455 for (
size_t i = 0; i < n; i++) {
456 gdkpoints[i].x = points[i].x;
457 gdkpoints[i].y = points[i].y;
464 fillStyle == wxWINDING_RULE ? OGDK_WINDING_RULE : OGDK_EVEN_ODD_RULE);
466 M_REGIONDATA->m_region = reg;
476wxObjectRefData *OCPNRegion::CreateRefData()
const {
480wxObjectRefData *OCPNRegion::CloneRefData(
const wxObjectRefData *data)
const {
488bool OCPNRegion::ODoIsEqual(
const OCPNRegion ®ion)
const {
489 if (!region.m_refData)
return false;
491 return ogdk_region_equal(M_REGIONDATA->m_region,
492 M_REGIONDATA_OF(region)->m_region);
499void OCPNRegion::Clear() { UnRef(); }
501bool OCPNRegion::ODoUnionWithRect(
const wxRect &r) {
505 if (r.IsEmpty())
return true;
508 InitRect(r.x, r.y, r.width, r.height);
515 rect.width = r.width;
516 rect.height = r.height;
518 gdk_region_union_with_rect(M_REGIONDATA->m_region, &rect);
524bool OCPNRegion::ODoUnionWithRegion(
const OCPNRegion ®ion) {
525 wxCHECK_MSG(region.Ok(),
false,
"invalid region");
529 M_REGIONDATA->m_region = gdk_region_new();
534 gdk_region_union(M_REGIONDATA->m_region, (
OGdkRegion *)region.GetRegion());
539bool OCPNRegion::ODoIntersect(
const OCPNRegion ®ion) {
540 wxCHECK_MSG(region.Ok(),
false,
"invalid region");
549 gdk_region_intersect(M_REGIONDATA->m_region,
555bool OCPNRegion::ODoSubtract(
const OCPNRegion ®ion) {
556 wxCHECK_MSG(region.Ok(),
false,
"invalid region");
564 gdk_region_subtract(M_REGIONDATA->m_region, (
OGdkRegion *)region.GetRegion());
570bool OCPNRegion::DoXor(
const OCPNRegion& region )
572 wxCHECK_MSG( region.Ok(),
false,
"invalid region" );
587bool OCPNRegion::ODoOffset(wxCoord x, wxCoord y) {
588 if (!m_refData)
return false;
592 gdk_region_offset(M_REGIONDATA->m_region, x, y);
601bool OCPNRegion::ODoGetBox(wxCoord &x, wxCoord &y, wxCoord &w,
605 gdk_region_get_clipbox(M_REGIONDATA->m_region, &rect);
622bool OCPNRegion::IsEmpty()
const {
623 if (!m_refData)
return true;
625 return gdk_region_empty(M_REGIONDATA->m_region);
628wxRegionContain OCPNRegion::ODoContainsPoint(wxCoord x, wxCoord y)
const {
629 if (!m_refData)
return wxOutRegion;
631 if (gdk_region_point_in(M_REGIONDATA->m_region, x, y))
637wxRegionContain OCPNRegion::ODoContainsRect(
const wxRect &r)
const {
638 if (!m_refData)
return wxOutRegion;
643 rect.width = r.width;
644 rect.height = r.height;
645 OGdkOverlapType res = gdk_region_rect_in(M_REGIONDATA->m_region, &rect);
647 case OGDK_OVERLAP_RECTANGLE_IN:
649 case OGDK_OVERLAP_RECTANGLE_OUT:
651 case OGDK_OVERLAP_RECTANGLE_PART:
658void *OCPNRegion::GetRegion()
const {
659 if (!m_refData)
return NULL;
661 return M_REGIONDATA->m_region;
664wxRegion *OCPNRegion::GetNew_wxRegion()
const {
665 wxRegion *r =
new wxRegion;
670 gdk_region_get_rectangles((
OGdkRegion *)GetRegion(), &gdkrects, &numRects);
673 for (
int i = 0; i < numRects; ++i) {
680 wr.height = gr.height;
695#ifndef USE_NEW_REGION
697OCPNRegionIterator::OCPNRegionIterator(
const OCPNRegion ®ion) {
698 m_ri =
new wxRegionIterator(region);
701OCPNRegionIterator::~OCPNRegionIterator() {
delete m_ri; }
703void OCPNRegionIterator::Reset() { m_ri->Reset(); }
705void OCPNRegionIterator::Reset(
const OCPNRegion ®ion) {
709wxRect OCPNRegionIterator::GetRect()
const {
return m_ri->GetRect(); }
711bool OCPNRegionIterator::HaveRects()
const {
return m_ri->HaveRects(); }
713void OCPNRegionIterator::NextRect() { ++(*m_ri); }
719OCPNRegionIterator::OCPNRegionIterator() {
724OCPNRegionIterator::OCPNRegionIterator(
const OCPNRegion ®ion) {
729void OCPNRegionIterator::Init() {
734OCPNRegionIterator::~OCPNRegionIterator() { wxDELETEA(m_rects); }
736void OCPNRegionIterator::Reset() { m_current = 0u; }
738void OCPNRegionIterator::NextRect() {
739 if (HaveRects()) ++m_current;
742void OCPNRegionIterator::CreateRects(
const OCPNRegion ®ion) {
747 if (!gdkregion)
return;
751 gdk_region_get_rectangles(gdkregion, &gdkrects, &numRects);
753 m_numRects = numRects;
755 m_rects =
new wxRect[m_numRects];
756 for (
size_t i = 0; i < m_numRects; ++i) {
758 wxRect &wr = m_rects[i];
762 wr.height = gr.height;
768void OCPNRegionIterator::Reset(
const OCPNRegion ®ion) {
774bool OCPNRegionIterator::HaveRects()
const {
return m_current < m_numRects; }
776wxRect OCPNRegionIterator::GetRect()
const {
778 if (HaveRects()) r = m_rects[m_current];
873 const OGdkRegion *reg2, overlapFunc overlapFn,
874 nonOverlapFunc nonOverlap1Fn,
875 nonOverlapFunc nonOverlap2Fn);
890 temp->rects = &temp->extents;
891 temp->extents.x1 = 0;
892 temp->extents.y1 = 0;
893 temp->extents.x2 = 0;
894 temp->extents.y2 = 0;
913 if (rectangle->width <= 0 || rectangle->height <= 0)
return gdk_region_new();
915 temp = gdk_region_new();
918 temp->rects = &temp->extents;
919 temp->extents.x1 = rectangle->x;
920 temp->extents.y1 = rectangle->y;
921 temp->extents.x2 = rectangle->x + rectangle->width;
922 temp->extents.y2 = rectangle->y + rectangle->height;
941 temp = gdk_region_new();
943 miRegionCopy(temp, region);
956void gdk_region_get_clipbox(
const OGdkRegion *region,
961 rectangle->x = region->extents.x1;
962 rectangle->y = region->extents.y1;
963 rectangle->width = region->extents.x2 - region->extents.x1;
964 rectangle->height = region->extents.y2 - region->extents.y1;
976void gdk_region_get_rectangles(
const OGdkRegion *region,
984 *n_rectangles = region->numRects;
988 for (i = 0; i < region->numRects; i++) {
990 rect = region->rects[i];
991 (*rectangles)[i].x = rect.x1;
992 (*rectangles)[i].y = rect.y1;
993 (*rectangles)[i].width = rect.x2 - rect.x1;
994 (*rectangles)[i].height = rect.y2 - rect.y1;
1013 if (rect->width <= 0 || rect->height <= 0)
return;
1015 tmp_region.rects = &tmp_region.extents;
1016 tmp_region.numRects = 1;
1017 tmp_region.extents.x1 = rect->x;
1018 tmp_region.extents.y1 = rect->y;
1019 tmp_region.extents.x2 = rect->x + rect->width;
1020 tmp_region.extents.y2 = rect->y + rect->height;
1021 tmp_region.size = 1;
1023 gdk_region_union(region, &tmp_region);
1044 if (pReg->numRects == 0) {
1045 pReg->extents.x1 = 0;
1046 pReg->extents.y1 = 0;
1047 pReg->extents.x2 = 0;
1048 pReg->extents.y2 = 0;
1052 pExtents = &pReg->extents;
1054 pBoxEnd = &pBox[pReg->numRects - 1];
1063 pExtents->x1 = pBox->x1;
1064 pExtents->y1 = pBox->y1;
1065 pExtents->x2 = pBoxEnd->x2;
1066 pExtents->y2 = pBoxEnd->y2;
1069 while (pBox <= pBoxEnd) {
1070 if (pBox->x1 < pExtents->x1) {
1071 pExtents->x1 = pBox->x1;
1073 if (pBox->x2 > pExtents->x2) {
1074 pExtents->x2 = pBox->x2;
1090 if (region->rects != ®ion->extents) free(region->rects);
1102void gdk_region_offset(
OGdkRegion *region,
int x,
int y) {
1108 pbox = region->rects;
1109 nbox = region->numRects;
1118 if (region->rects != ®ion->extents) {
1119 region->extents.x1 += x;
1120 region->extents.x2 += x;
1121 region->extents.y1 += y;
1122 region->extents.y2 += y;
1146#define ZOpRegion(a, b) \
1148 gdk_region_union(a, b); \
1150 gdk_region_intersect(a, b)
1151#define ZShiftRegion(a, b) \
1153 gdk_region_offset(a, b, 0); \
1155 gdk_region_offset(a, 0, b)
1158 unsigned int dx,
int xdir,
int grow) {
1159 unsigned int shift = 1;
1164 ZShiftRegion(r, -(
int)shift);
1170 ZShiftRegion(s, -(
int)shift);
1189void gdk_region_shrink(
OGdkRegion *region,
int dx,
int dy) {
1195 if (!dx && !dy)
return;
1197 s = gdk_region_new();
1198 t = gdk_region_new();
1202 if (dx) Compress(region, s, t, (
unsigned)2 * dx, TRUE, grow);
1206 if (dy) Compress(region, s, t, (
unsigned)2 * dy, FALSE, grow);
1208 gdk_region_offset(region, dx, dy);
1209 gdk_region_destroy(s);
1210 gdk_region_destroy(t);
1237 pNextRect = &pReg->rects[pReg->numRects];
1239 while ((r1 != r1End) && (r2 != r2End)) {
1240 x1 = MAX(r1->x1, r2->x1);
1241 x2 = MIN(r1->x2, r2->x2);
1253 OMEMCHECK(pReg, pNextRect, pReg->rects);
1258 pReg->numRects += 1;
1268 if (r1->x2 < r2->x2) {
1270 }
else if (r2->x2 < r1->x2) {
1293 if ((!(source1->numRects)) || (!(source2->numRects)) ||
1294 (!EXTENTCHECK(&source1->extents, &source2->extents)))
1295 source1->numRects = 0;
1297 miRegionOp(source1, source1, source2, miIntersectO, (nonOverlapFunc)NULL,
1298 (nonOverlapFunc)NULL);
1306 miSetExtents(source1);
1312 if (dstrgn->size < rgn->numRects) {
1313 if (dstrgn->rects != &dstrgn->extents) free(dstrgn->rects);
1317 dstrgn->size = rgn->numRects;
1320 dstrgn->numRects = rgn->numRects;
1321 dstrgn->extents = rgn->extents;
1323 memcpy(dstrgn->rects, rgn->rects, rgn->numRects *
sizeof(
OGdkRegionBox));
1362 pRegEnd = &pReg->rects[pReg->numRects];
1364 pPrevBox = &pReg->rects[prevStart];
1365 prevNumRects = curStart - prevStart;
1372 pCurBox = &pReg->rects[curStart];
1373 bandY1 = pCurBox->y1;
1374 for (curNumRects = 0; (pCurBox != pRegEnd) && (pCurBox->y1 == bandY1);
1379 if (pCurBox != pRegEnd) {
1387 while (pRegEnd[-1].y1 == pRegEnd->y1) {
1390 curStart = pRegEnd - pReg->rects;
1391 pRegEnd = pReg->rects + pReg->numRects;
1394 if ((curNumRects == prevNumRects) && (curNumRects != 0)) {
1395 pCurBox -= curNumRects;
1400 if (pPrevBox->y2 == pCurBox->y1) {
1408 if ((pPrevBox->x1 != pCurBox->x1) || (pPrevBox->x2 != pCurBox->x2)) {
1417 }
while (prevNumRects != 0);
1419 pReg->numRects -= curNumRects;
1420 pCurBox -= curNumRects;
1421 pPrevBox -= curNumRects;
1429 pPrevBox->y2 = pCurBox->y2;
1433 }
while (curNumRects != 0);
1445 if (pCurBox == pRegEnd) {
1446 curStart = prevStart;
1449 *pPrevBox++ = *pCurBox++;
1450 }
while (pCurBox != pRegEnd);
1484static void miRegionOp(
1486 overlapFunc overlapFn,
1488 nonOverlapFunc nonOverlap1Fn,
1491 nonOverlapFunc nonOverlap2Fn)
1522 r1End = r1 + reg1->numRects;
1523 r2End = r2 + reg2->numRects;
1525 oldRects = newReg->rects;
1527 EMPTY_REGION(newReg);
1536 newReg->size = MAX(reg1->numRects, reg2->numRects) * 2;
1552 if (reg1->extents.y1 < reg2->extents.y1)
1553 ybot = reg1->extents.y1;
1555 ybot = reg2->extents.y1;
1569 curBand = newReg->numRects;
1579 while ((r1BandEnd != r1End) && (r1BandEnd->y1 == r1->y1)) {
1584 while ((r2BandEnd != r2End) && (r2BandEnd->y1 == r2->y1)) {
1596 if (r1->y1 < r2->y1) {
1597 top = MAX(r1->y1, ybot);
1598 bot = MIN(r1->y2, r2->y1);
1603 (*nonOverlap1Fn)(newReg, r1, r1BandEnd, top, bot);
1607 }
else if (r2->y1 < r1->y1) {
1608 top = MAX(r2->y1, ybot);
1609 bot = MIN(r2->y2, r1->y1);
1614 (*nonOverlap2Fn)(newReg, r2, r2BandEnd, top, bot);
1628 if (newReg->numRects != curBand) {
1629 prevBand = miCoalesce(newReg, prevBand, curBand);
1636 ybot = MIN(r1->y2, r2->y2);
1637 curBand = newReg->numRects;
1639 (*overlapFn)(newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
1642 if (newReg->numRects != curBand) {
1643 prevBand = miCoalesce(newReg, prevBand, curBand);
1650 if (r1->y2 == ybot) {
1653 if (r2->y2 == ybot) {
1656 }
while ((r1 != r1End) && (r2 != r2End));
1661 curBand = newReg->numRects;
1663 if (nonOverlap1Fn != (nonOverlapFunc)NULL) {
1666 while ((r1BandEnd < r1End) && (r1BandEnd->y1 == r1->y1)) {
1669 (*nonOverlap1Fn)(newReg, r1, r1BandEnd, MAX(r1->y1, ybot), r1->y2);
1671 }
while (r1 != r1End);
1673 }
else if ((r2 != r2End) && (nonOverlap2Fn != (nonOverlapFunc)NULL)) {
1676 while ((r2BandEnd < r2End) && (r2BandEnd->y1 == r2->y1)) {
1679 (*nonOverlap2Fn)(newReg, r2, r2BandEnd, MAX(r2->y1, ybot), r2->y2);
1681 }
while (r2 != r2End);
1684 if (newReg->numRects != curBand) {
1685 (void)miCoalesce(newReg, prevBand, curBand);
1696 if (newReg->numRects < (newReg->size >> 1)) {
1697 if (REGION_NOT_EMPTY(newReg)) {
1698 newReg->size = newReg->numRects;
1709 free(newReg->rects);
1710 newReg->rects = &newReg->extents;
1714 if (oldRects != &newReg->extents) free(oldRects);
1741 pNextRect = &pReg->rects[pReg->numRects];
1747 OMEMCHECK(pReg, pNextRect, pReg->rects);
1748 pNextRect->x1 = r->x1;
1750 pNextRect->x2 = r->x2;
1752 pReg->numRects += 1;
1781 pNextRect = &pReg->rects[pReg->numRects];
1783#define MERGERECT(r) \
1784 if ((pReg->numRects != 0) && (pNextRect[-1].y1 == y1) && \
1785 (pNextRect[-1].y2 == y2) && (pNextRect[-1].x2 >= r->x1)) { \
1786 if (pNextRect[-1].x2 < r->x2) { \
1787 pNextRect[-1].x2 = r->x2; \
1791 OMEMCHECK(pReg, pNextRect, pReg->rects); \
1792 pNextRect->y1 = y1; \
1793 pNextRect->y2 = y2; \
1794 pNextRect->x1 = r->x1; \
1795 pNextRect->x2 = r->x2; \
1796 pReg->numRects += 1; \
1803 while ((r1 != r1End) && (r2 != r2End)) {
1804 if (r1->x1 < r2->x1) {
1814 }
while (r1 != r1End);
1816 while (r2 != r2End) {
1839 if ((source1 == source2) || (!(source2->numRects)))
return;
1844 if (!(source1->numRects)) {
1845 miRegionCopy(source1, source2);
1852 if ((source1->numRects == 1) &&
1853 (source1->extents.x1 <= source2->extents.x1) &&
1854 (source1->extents.y1 <= source2->extents.y1) &&
1855 (source1->extents.x2 >= source2->extents.x2) &&
1856 (source1->extents.y2 >= source2->extents.y2))
1862 if ((source2->numRects == 1) &&
1863 (source2->extents.x1 <= source1->extents.x1) &&
1864 (source2->extents.y1 <= source1->extents.y1) &&
1865 (source2->extents.x2 >= source1->extents.x2) &&
1866 (source2->extents.y2 >= source1->extents.y2)) {
1867 miRegionCopy(source1, source2);
1871 miRegionOp(source1, source1, source2, miUnionO, miUnionNonO, miUnionNonO);
1873 source1->extents.x1 = MIN(source1->extents.x1, source2->extents.x1);
1874 source1->extents.y1 = MIN(source1->extents.y1, source2->extents.y1);
1875 source1->extents.x2 = MAX(source1->extents.x2, source2->extents.x2);
1876 source1->extents.y2 = MAX(source1->extents.y2, source2->extents.y2);
1902 pNextRect = &pReg->rects[pReg->numRects];
1908 OMEMCHECK(pReg, pNextRect, pReg->rects);
1909 pNextRect->x1 = r->x1;
1911 pNextRect->x2 = r->x2;
1913 pReg->numRects += 1;
1946 pNextRect = &pReg->rects[pReg->numRects];
1948 while ((r1 != r1End) && (r2 != r2End)) {
1954 }
else if (r2->x1 <= x1) {
1965 if (r1 != r1End) x1 = r1->x1;
1973 }
else if (r2->x1 < r1->x2) {
1979 OMEMCHECK(pReg, pNextRect, pReg->rects);
1982 pNextRect->x2 = r2->x1;
1984 pReg->numRects += 1;
1995 if (r1 != r1End) x1 = r1->x1;
2007 OMEMCHECK(pReg, pNextRect, pReg->rects);
2010 pNextRect->x2 = r1->x2;
2012 pReg->numRects += 1;
2017 if (r1 != r1End) x1 = r1->x1;
2024 while (r1 != r1End) {
2026 OMEMCHECK(pReg, pNextRect, pReg->rects);
2029 pNextRect->x2 = r1->x2;
2031 pReg->numRects += 1;
2056 if ((!(source1->numRects)) || (!(source2->numRects)) ||
2057 (!EXTENTCHECK(&source1->extents, &source2->extents)))
2060 miRegionOp(source1, source1, source2, miSubtractO, miSubtractNonO1,
2061 (nonOverlapFunc)NULL);
2069 miSetExtents(source1);
2087 trb = gdk_region_copy(source2);
2089 gdk_region_subtract(trb, source1);
2090 gdk_region_subtract(source1, source2);
2092 gdk_region_union(source1, trb);
2094 gdk_region_destroy(trb);
2105bool gdk_region_empty(
const OGdkRegion *region) {
2108 if (region->numRects == 0)
2129 if (region1->numRects != region2->numRects)
return FALSE;
2130 if (region1->numRects == 0)
return TRUE;
2131 if (region1->extents.x1 != region2->extents.x1)
return FALSE;
2132 if (region1->extents.x2 != region2->extents.x2)
return FALSE;
2133 if (region1->extents.y1 != region2->extents.y1)
return FALSE;
2134 if (region1->extents.y2 != region2->extents.y2)
return FALSE;
2135 for (i = 0; i < region1->numRects; i++) {
2136 if (region1->rects[i].x1 != region2->rects[i].x1)
return FALSE;
2137 if (region1->rects[i].x2 != region2->rects[i].x2)
return FALSE;
2138 if (region1->rects[i].y1 != region2->rects[i].y1)
return FALSE;
2139 if (region1->rects[i].y2 != region2->rects[i].y2)
return FALSE;
2154bool gdk_region_point_in(
const OGdkRegion *region,
int x,
int y) {
2159 if (region->numRects == 0)
return FALSE;
2160 if (!INBOX(region->extents, x, y))
return FALSE;
2161 for (i = 0; i < region->numRects; i++) {
2162 if (INBOX(region->rects[i], x, y))
return TRUE;
2178OGdkOverlapType gdk_region_rect_in(
const OGdkRegion *region,
2184 bool partIn, partOut;
2196 prect->x2 = rx + rectangle->width;
2197 prect->y2 = ry + rectangle->height;
2200 if ((region->numRects == 0) || !EXTENTCHECK(®ion->extents, prect))
2201 return OGDK_OVERLAP_RECTANGLE_OUT;
2207 for (pbox = region->rects, pboxEnd = pbox + region->numRects; pbox < pboxEnd;
2212 if (pbox->y1 > ry) {
2214 if (partIn || (pbox->y1 >= prect->y2))
break;
2218 if (pbox->x2 <= rx)
continue;
2220 if (pbox->x1 > rx) {
2225 if (pbox->x1 < prect->x2) {
2230 if (pbox->x2 >= prect->x2) {
2232 if (ry >= prect->y2)
break;
2246 return (partIn ? ((ry < prect->y2) ? OGDK_OVERLAP_RECTANGLE_PART
2247 : OGDK_OVERLAP_RECTANGLE_IN)
2248 : OGDK_OVERLAP_RECTANGLE_OUT);
2253 gdk_region_unsorted_spans_intersect_foreach (GdkRegion *region,
2254 const GdkSpan *spans,
2256 GdkSpanFunc function,
2259 gint i, left, right, y;
2260 gint clipped_left, clipped_right;
2262 GdkRegionBox *pboxEnd;
2264 if (!region->numRects)
2267 for (i=0;i<n_spans;i++)
2271 right = left + spans[i].width;
2273 if (! ((region->extents.y1 <= y) &&
2274 (region->extents.y2 > y) &&
2275 (region->extents.x1 < right) &&
2276 (region->extents.x2 > left)) )
2280 for (pbox = region->rects, pboxEnd = pbox + region->numRects;
2290 if ((right > pbox->x1) && (left < pbox->x2))
2294 clipped_left = MAX (left, pbox->x1);
2295 clipped_right = MIN (right, pbox->x2);
2298 out_span.x = clipped_left;
2299 out_span.width = clipped_right - clipped_left;
2300 (*function) (&out_span, data);
2320 gdk_region_spans_intersect_foreach (GdkRegion *region,
2321 const GdkSpan *spans,
2324 GdkSpanFunc function,
2327 gint left, right, y;
2328 gint clipped_left, clipped_right;
2330 GdkRegionBox *pboxEnd;
2331 const GdkSpan *span, *tmpspan;
2332 const GdkSpan *end_span;
2334 g_return_if_fail (region != NULL);
2335 g_return_if_fail (spans != NULL);
2339 gdk_region_unsorted_spans_intersect_foreach (region,
2347 if ((!region->numRects) || (n_spans == 0))
2357 end_span = spans + n_spans;
2358 pbox = region->rects;
2359 pboxEnd = pbox + region->numRects;
2360 while (pbox < pboxEnd)
2362 while ((pbox->y2 < span->y) || (span->y < pbox->y1))
2365 if (pbox->y2 < span->y)
2368 if (pbox == pboxEnd)
2372 if (span->y < pbox->y1)
2375 if (span == end_span)
2382 while ((tmpspan < end_span) &&
2383 (tmpspan->y < pbox->y2))
2387 right = left + tmpspan->width;
2389 if ((right > pbox->x1) && (left < pbox->x2))
2393 clipped_left = MAX (left, pbox->x1);
2394 clipped_right = MIN (right, pbox->x2);
2397 out_span.x = clipped_left;
2398 out_span.width = clipped_right - clipped_left;
2399 (*function) (&out_span, data);
2458#define LARGE_COORDINATE 1000000
2459#define SMALL_COORDINATE -LARGE_COORDINATE
2485 pPrevSLL = &ET->scanlines;
2486 pSLL = pPrevSLL->next;
2487 while (pSLL && (pSLL->scanline < scanline)) {
2495 if ((!pSLL) || (pSLL->scanline > scanline)) {
2496 if (*iSLLBlock > SLLSPERBLOCK - 1) {
2498 (*SLLBlock)->next = tmpSLLBlock;
2500 *SLLBlock = tmpSLLBlock;
2503 pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
2505 pSLL->next = pPrevSLL->next;
2507 pPrevSLL->next = pSLL;
2509 pSLL->scanline = scanline;
2515 start = pSLL->edgelist;
2516 while (start && (start->bres.minor_axis < ETE->bres.minor_axis)) {
2518 start = start->next;
2525 pSLL->edgelist = ETE;
2561 if (count < 2)
return;
2569 AET->bres.minor_axis = SMALL_COORDINATE;
2575 ET->ymax = SMALL_COORDINATE;
2576 ET->ymin = LARGE_COORDINATE;
2579 PrevPt = &pts[count - 1];
2592 if (PrevPt->y > CurrPt->y) {
2593 bottom = PrevPt, top = CurrPt;
2594 pETEs->ClockWise = 0;
2596 bottom = CurrPt, top = PrevPt;
2597 pETEs->ClockWise = 1;
2603 if (bottom->y != top->y) {
2604 pETEs->ymax = bottom->y - 1;
2609 dy = bottom->y - top->y;
2610 OBRESINITPGONSTRUCT(dy, top->x, bottom->x, pETEs->bres);
2612 InsertEdgeInET(ET, pETEs, top->y, &pSLLBlock, &iSLLBlock);
2614 if (PrevPt->y > ET->ymax) ET->ymax = PrevPt->y;
2615 if (PrevPt->y < ET->ymin) ET->ymin = PrevPt->y;
2639 while (AET && (AET->bres.minor_axis < ETEs->bres.minor_axis)) {
2645 if (AET) AET->back = ETEs;
2646 ETEs->back = pPrevAET;
2647 pPrevAET->next = ETEs;
2688 if ((!inside && !isInside) || (inside && isInside)) {
2689 pWETE->nextWETE = AET;
2717 while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
2718 pETEchase = pETEchase->back;
2721 if (pETEchase != pETEinsert) {
2722 pETEchaseBackTMP = pETEchase->back;
2723 pETEinsert->back->next = AET;
2724 if (AET) AET->back = pETEinsert->back;
2725 pETEinsert->next = pETEchase;
2726 pETEchase->back->next = pETEinsert;
2727 pETEchase->back = pETEinsert;
2728 pETEinsert->back = pETEchaseBackTMP;
2742 tmpSLLBlock = pSLLBlock->next;
2744 pSLLBlock = tmpSLLBlock;
2756static int PtsToRegion(
int numFullPtBlocks,
int iCurPtBlock,
2765 extents = ®->extents;
2767 numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
2769 OGROWREGION(reg, numRects);
2771 CurPtBlock = FirstPtBlock;
2772 rects = reg->rects - 1;
2774 extents->x1 = 1000000 , extents->x2 = -1000000 ;
2776 for (; numFullPtBlocks >= 0; numFullPtBlocks--) {
2778 i = NUMPTSTOBUFFER >> 1;
2779 if (!numFullPtBlocks) i = iCurPtBlock >> 1;
2780 for (pts = CurPtBlock->pts; i--; pts += 2) {
2781 if (pts->x == pts[1].x)
continue;
2782 if (numRects && pts->x == rects->x1 && pts->y == rects->y2 &&
2783 pts[1].x == rects->x2 &&
2784 (numRects == 1 || rects[-1].y1 != rects->y1) &&
2785 (i && pts[2].y > pts[1].y)) {
2786 rects->y2 = pts[1].y + 1;
2793 rects->x2 = pts[1].x;
2794 rects->y2 = pts[1].y + 1;
2795 if (rects->x1 < extents->x1) extents->x1 = rects->x1;
2796 if (rects->x2 > extents->x2) extents->x2 = rects->x2;
2798 CurPtBlock = CurPtBlock->next;
2802 extents->y1 = reg->rects->y1;
2803 extents->y2 = rects->y2;
2810 reg->numRects = numRects;
2828 OGdkFillRule fill_rule) {
2845 int fixWAET = FALSE;
2848 int numFullPtBlocks = 0;
2850 region = gdk_region_new();
2853 if (((n_points == 4) || ((n_points == 5) && (points[4].x == points[0].x) &&
2854 (points[4].y == points[0].y))) &&
2855 (((points[0].y == points[1].y) && (points[1].x == points[2].x) &&
2856 (points[2].y == points[3].y) && (points[3].x == points[0].x)) ||
2857 ((points[0].x == points[1].x) && (points[1].y == points[2].y) &&
2858 (points[2].x == points[3].x) && (points[3].y == points[0].y)))) {
2859 region->extents.x1 = MIN(points[0].x, points[2].x);
2860 region->extents.y1 = MIN(points[0].y, points[2].y);
2861 region->extents.x2 = MAX(points[0].x, points[2].x);
2862 region->extents.y2 = MAX(points[0].y, points[2].y);
2863 if ((region->extents.x1 != region->extents.x2) &&
2864 (region->extents.y1 != region->extents.y2)) {
2865 region->numRects = 1;
2866 *(region->rects) = region->extents;
2873 pts = FirstPtBlock.pts;
2874 CreateETandAET(n_points, points, &ET, &AET, pETEs, &SLLBlock);
2875 pSLL = ET.scanlines.next;
2876 curPtBlock = &FirstPtBlock;
2878 if (fill_rule == OGDK_EVEN_ODD_RULE) {
2882 for (y = ET.ymin; y < ET.ymax; y++) {
2887 if (pSLL != NULL && y == pSLL->scanline) {
2888 loadAET(&AET, pSLL->edgelist);
2898 pts->x = pAET->bres.minor_axis, pts->y = y;
2904 if (iPts == NUMPTSTOBUFFER) {
2906 tmpPtBlock->next = NULL;
2907 curPtBlock->next = tmpPtBlock;
2908 curPtBlock = tmpPtBlock;
2909 pts = curPtBlock->pts;
2913 OEVALUATEEDGEEVENODD(pAET, pPrevAET, y);
2915 (void)InsertionSort(&AET);
2921 for (y = ET.ymin; y < ET.ymax; y++) {
2926 if (pSLL != NULL && y == pSLL->scanline) {
2927 loadAET(&AET, pSLL->edgelist);
2943 if (pWETE == pAET) {
2944 pts->x = pAET->bres.minor_axis, pts->y = y;
2950 if (iPts == NUMPTSTOBUFFER) {
2952 tmpPtBlock->next = NULL;
2953 curPtBlock->next = tmpPtBlock;
2954 curPtBlock = tmpPtBlock;
2955 pts = curPtBlock->pts;
2959 pWETE = pWETE->nextWETE;
2961 OEVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET);
2968 if (InsertionSort(&AET) || fixWAET) {
2974 FreeStorage(SLLBlock.next);
2975 (void)PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
2976 for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
2977 tmpPtBlock = curPtBlock->next;
2979 curPtBlock = tmpPtBlock;
A wrapper class for wxRegion with additional functionality.