📄 qregion_qws.cpp
字号:
} curStart = pRegEnd - pReg->rects.data(); pRegEnd = pReg->rects.data() + pReg->numRects; } if ((curNumRects == prevNumRects) && (curNumRects != 0)) { pCurBox -= curNumRects; /* * The bands may only be coalesced if the bottom of the previous * matches the top scanline of the current. */ if (pPrevBox->bottom() == pCurBox->top() - 1) { /* * Make sure the bands have boxes in the same places. This * assumes that boxes have been added in such a way that they * cover the most area possible. I.e. two boxes in a band must * have some horizontal space between them. */ do { if ((pPrevBox->left() != pCurBox->left()) || (pPrevBox->right() != pCurBox->right())) { /* * The bands don't line up so they can't be coalesced. */ return (curStart); } pPrevBox++; pCurBox++; prevNumRects -= 1; } while (prevNumRects != 0); pReg->numRects -= curNumRects; pCurBox -= curNumRects; pPrevBox -= curNumRects; /* * The bands may be merged, so set the bottom y of each box * in the previous band to that of the corresponding box in * the current band. */ do { pPrevBox->setBottom( pCurBox->bottom() ); pPrevBox++; pCurBox++; curNumRects -= 1; } while (curNumRects != 0); /* * If only one band was added to the region, we have to backup * curStart to the start of the previous band. * * If more than one band was added to the region, copy the * other bands down. The assumption here is that the other bands * came from the same region as the current one and no further * coalescing can be done on them since it's all been done * already... curStart is already in the right place. */ if (pCurBox == pRegEnd) { curStart = prevStart; } else { do { *pPrevBox++ = *pCurBox++; } while (pCurBox != pRegEnd); } } } return (curStart);}/*- *----------------------------------------------------------------------- * miRegionOp -- * Apply an operation to two regions. Called by miUnion, miInverse, * miSubtract, miIntersect... * * Results: * None. * * Side Effects: * The new region is overwritten. * * Notes: * The idea behind this function is to view the two regions as sets. * Together they cover a rectangle of area that this function divides * into horizontal bands where points are covered only by one region * or by both. For the first case, the nonOverlapFunc is called with * each the band and the band's upper and lower extents. For the * second, the overlapFunc is called to process the entire band. It * is responsible for clipping the rectangles in the band, though * this function provides the boundaries. * At the end of each band, the new region is coalesced, if possible, * to reduce the number of rectangles in the region. * *----------------------------------------------------------------------- *//* static void*/static voidmiRegionOp(register Region newReg, Region reg1, Region reg2, void (*overlapFunc)(...), void (*nonOverlap1Func)(...), void (*nonOverlap2Func)(...)) //register Region newReg; /* Place to store result */ //Region reg1; /* First region in operation */ //Region reg2; /* 2d region in operation */ //void (*overlapFunc)(); /* Function to call for over- //* lapping bands */ //void (*nonOverlap1Func)(); /* Function to call for non- //* overlapping bands in region //* 1 */ //void (*nonOverlap2Func)(); /* Function to call for non- //* overlapping bands in region //* 2 */{ register QRect *r1; /* Pointer into first region */ register QRect *r2; /* Pointer into 2d region */ QRect *r1End; /* End of 1st region */ QRect *r2End; /* End of 2d region */ register int ybot; /* Bottom of intersection */ register int ytop; /* Top of intersection */ int prevBand; /* Index of start of * previous band in newReg */ int curBand; /* Index of start of current * band in newReg */ register QRect *r1BandEnd; /* End of current band in r1 */ register QRect *r2BandEnd; /* End of current band in r2 */ int top; /* Top of non-overlapping * band */ int bot; /* Bottom of non-overlapping * band */ /* * Initialization: * set r1, r2, r1End and r2End appropriately, preserve the important * parts of the destination region until the end in case it's one of * the two source regions, then mark the "new" region empty, allocating * another array of rectangles for it to use. */ r1 = reg1->rects.data(); r2 = reg2->rects.data(); r1End = r1 + reg1->numRects; r2End = r2 + reg2->numRects; QArray<QRect> oldRects = newReg->rects; newReg->rects.detach(); EMPTY_REGION(newReg); /* * Allocate a reasonable number of rectangles for the new region. The idea * is to allocate enough so the individual functions don't need to * reallocate and copy the array, which is time consuming, yet we don't * have to worry about using too much memory. I hope to be able to * nuke the Xrealloc() at the end of this function eventually. */ newReg->rects.resize( QMAX(reg1->numRects,reg2->numRects) * 2 ); /* * Initialize ybot and ytop. * In the upcoming loop, ybot and ytop serve different functions depending * on whether the band being handled is an overlapping or non-overlapping * band. * In the case of a non-overlapping band (only one of the regions * has points in the band), ybot is the bottom of the most recent * intersection and thus clips the top of the rectangles in that band. * ytop is the top of the next intersection between the two regions and * serves to clip the bottom of the rectangles in the current band. * For an overlapping band (where the two regions intersect), ytop clips * the top of the rectangles of both regions and ybot clips the bottoms. */ if (reg1->extents.top() < reg2->extents.top()) ybot = reg1->extents.top() - 1; else ybot = reg2->extents.top() - 1; /* * prevBand serves to mark the start of the previous band so rectangles * can be coalesced into larger rectangles. qv. miCoalesce, above. * In the beginning, there is no previous band, so prevBand == curBand * (curBand is set later on, of course, but the first band will always * start at index 0). prevBand and curBand must be indices because of * the possible expansion, and resultant moving, of the new region's * array of rectangles. */ prevBand = 0; do { curBand = newReg->numRects; /* * This algorithm proceeds one source-band (as opposed to a * destination band, which is determined by where the two regions * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the * rectangle after the last one in the current band for their * respective regions. */ r1BandEnd = r1; while ((r1BandEnd != r1End) && (r1BandEnd->top() == r1->top())) { r1BandEnd++; } r2BandEnd = r2; while ((r2BandEnd != r2End) && (r2BandEnd->top() == r2->top())) { r2BandEnd++; } /* * First handle the band that doesn't intersect, if any. * * Note that attention is restricted to one band in the * non-intersecting region at once, so if a region has n * bands between the current position and the next place it overlaps * the other, this entire loop will be passed through n times. */ if (r1->top() < r2->top()) { top = QMAX(r1->top(),ybot+1); bot = QMIN(r1->bottom(),r2->top()-1); if ((nonOverlap1Func != (voidProcp)NULL) && bot >= top) { (* nonOverlap1Func) (newReg, r1, r1BandEnd, top, bot); } ytop = r2->top(); } else if (r2->top() < r1->top()) { top = QMAX(r2->top(),ybot+1); bot = QMIN(r2->bottom(),r1->top()-1); if ((nonOverlap2Func != (voidProcp)NULL) && bot >= top) { (* nonOverlap2Func) (newReg, r2, r2BandEnd, top, bot); } ytop = r1->top(); } else { ytop = r1->top(); } /* * If any rectangles got added to the region, try and coalesce them * with rectangles from the previous band. Note we could just do * this test in miCoalesce, but some machines incur a not * inconsiderable cost for function calls, so... */ if (newReg->numRects != curBand) { prevBand = miCoalesce (newReg, prevBand, curBand); } /* * Now see if we've hit an intersecting band. The two bands only * intersect if ybot >= ytop */ ybot = QMIN(r1->bottom(), r2->bottom()); curBand = newReg->numRects; if (ybot >= ytop) { (* overlapFunc) (newReg, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot); } if (newReg->numRects != curBand) { prevBand = miCoalesce (newReg, prevBand, curBand); } /* * If we've finished with a band (y2 == ybot) we skip forward * in the region to the next band. */ if (r1->bottom() == ybot) { r1 = r1BandEnd; } if (r2->bottom() == ybot) { r2 = r2BandEnd; } } while ((r1 != r1End) && (r2 != r2End)); /* * Deal with whichever region still has rectangles left. */ curBand = newReg->numRects; if (r1 != r1End) { if (nonOverlap1Func != (voidProcp)NULL) { do { r1BandEnd = r1; while ((r1BandEnd < r1End) && (r1BandEnd->top() == r1->top())) { r1BandEnd++; } (* nonOverlap1Func) (newReg, r1, r1BandEnd, QMAX(r1->top(),ybot+1), r1->bottom()); r1 = r1BandEnd; } while (r1 != r1End); } } else if ((r2 != r2End) && (nonOverlap2Func != (voidProcp)NULL)) { do { r2BandEnd = r2; while ((r2BandEnd < r2End) && (r2BandEnd->top() == r2->top())) { r2BandEnd++; } (* nonOverlap2Func) (newReg, r2, r2BandEnd, QMAX(r2->top(),ybot+1), r2->bottom()); r2 = r2BandEnd; } while (r2 != r2End); } if (newReg->numRects != curBand) { (void) miCoalesce (newReg, prevBand, curBand); } /* * A bit of cleanup. To keep regions from growing without bound, * we shrink the array of rectangles to match the new number of * rectangles in the region. This never goes to 0, however... * * Only do this stuff if the number of rectangles allocated is more than * twice the number of rectangles in the region (a simple optimization...). */ if (newReg->numRects < (int)(newReg->rects.size() >> 1)) { if (REGION_NOT_EMPTY(newReg)) { newReg->rects.resize(newReg->numRects); } else { /* * No point in doing the extra work involved in an Xrealloc if * the region is empty */ newReg->rects.resize(1); } } return;}/*====================================================================== * Region Union *====================================================================*//*- *----------------------------------------------------------------------- * miUnionNonO -- * Handle a non-overlapping band for the union operation. Just * Adds the rectangles into the region. Doesn't have to check for * subsumption or anything. * * Results: * None. * * Side Effects: * pReg->numRects is incremented and the final rectangles overwritten * with the rectangles we're passed. * *----------------------------------------------------------------------- *//* static void*/staticintmiUnionNonO (register Region pReg, register QRect * r, QRect * rEnd, register int y1, register int y2){ register QRect * pNextRect; pNextRect = pReg->rects.data() + pReg->numRects; ASSERT(y1 <= y2); while (r != rEnd) { ASSERT(r->left() <= r->right()); MEMCHECK(pReg, pNextRect, pReg->rects) pNextRect->setCoords( r->left(), y1, r->right(), y2 ); pReg->numRects++; pNextRect++; r++; } return 0; /* lint */}/*- *----------------------------------------------------------------------- * miUnionO -- * Handle an overlapping band for the union operation. Picks the * left-most rectangle each time and merges it into the region. * * Results: * None. * * Side Effects: * Rectangles are overwritten in pReg->rects and pReg->numRects will * be changed. * *----------------------------------------------------------------------- *//* static void*/staticintmiUnionO (register Region pReg, register QRect *r1, QRect *r1End, register QRect *r2, QRect *r2End, register int y1, register int y2){ register QRect *pNextRect; pNextRect = pReg->rects.data() + pReg->numRects;#define MERGERECT(r) \
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -