⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 qregion_unix.cpp

📁 qt-x11-opensource-src-4.1.4.tar.gz源码
💻 CPP
📖 第 1 页 / 共 5 页
字号:
{    register int x1;    register int x2;    register QRect *pNextRect;    pNextRect = dest.rects.data() + dest.numRects;    while (r1 != r1End && r2 != r2End) {        x1 = qMax(r1->left(), r2->left());        x2 = qMin(r1->right(), r2->right());        /*         * If there's any overlap between the two rectangles, add that         * overlap to the new region.         * There's no need to check for subsumption because the only way         * such a need could arise is if some region has two rectangles         * right next to each other. Since that should never happen...         */        if (x1 <= x2) {            Q_ASSERT(y1 <= y2);            MEMCHECK(dest, pNextRect, dest.rects)            pNextRect->setCoords(x1, y1, x2, y2);            ++dest.numRects;            ++pNextRect;        }        /*         * Need to advance the pointers. Shift the one that extends         * to the right the least, since the other still has a chance to         * overlap with that region's next rectangle, if you see what I mean.         */        if (r1->right() < r2->right()) {            ++r1;        } else if (r2->right() < r1->right()) {            ++r2;        } else {            ++r1;            ++r2;        }    }}/*====================================================================== *          Generic Region Operator *====================================================================*//*- *----------------------------------------------------------------------- * miCoalesce -- *      Attempt to merge the boxes in the current band with those in the *      previous one. Used only by miRegionOp. * * Results: *      The new index for the previous band. * * Side Effects: *      If coalescing takes place: *          - rectangles in the previous band will have their y2 fields *            altered. *          - dest.numRects will be decreased. * *----------------------------------------------------------------------- */static int miCoalesce(register QRegionPrivate &dest, int prevStart, int curStart){    register QRect *pPrevBox;   /* Current box in previous band */    register QRect *pCurBox;    /* Current box in current band */    register QRect *pRegEnd;    /* End of region */    int curNumRects;    /* Number of rectangles in current band */    int prevNumRects;   /* Number of rectangles in previous band */    int bandY1;         /* Y1 coordinate for current band */    QRect *rData = dest.rects.data();    pRegEnd = rData + dest.numRects;    pPrevBox = rData + prevStart;    prevNumRects = curStart - prevStart;    /*     * Figure out how many rectangles are in the current band. Have to do     * this because multiple bands could have been added in miRegionOp     * at the end when one region has been exhausted.     */    pCurBox = rData + curStart;    bandY1 = pCurBox->top();    for (curNumRects = 0; pCurBox != pRegEnd && pCurBox->top() == bandY1; ++curNumRects) {        ++pCurBox;    }    if (pCurBox != pRegEnd) {        /*         * If more than one band was added, we have to find the start         * of the last band added so the next coalescing job can start         * at the right place... (given when multiple bands are added,         * this may be pointless -- see above).         */        --pRegEnd;        while ((pRegEnd - 1)->top() == pRegEnd->top())            --pRegEnd;        curStart = pRegEnd - rData;        pRegEnd = rData + dest.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;            } while (prevNumRects != 0);            dest.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 miRegionOp(register QRegionPrivate &dest, const QRegionPrivate *reg1, const QRegionPrivate *reg2,                       OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func,                       NonOverlapFunc nonOverlap2Func){    register const QRect *r1;         // Pointer into first region    register const QRect *r2;         // Pointer into 2d region    const QRect *r1End;               // End of 1st region    const 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 dest    int curBand;                // Index of start of current band in dest    register const QRect *r1BandEnd;  // End of current band in r1    register const 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;    QVector<QRect> oldRects = dest.rects;    dest.numRects = 0;    /*     * 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 realloc() at the end of this function eventually.     */    dest.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 = dest.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 != 0 && bot >= top)                (*nonOverlap1Func)(dest, 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 != 0 && bot >= top)                (*nonOverlap2Func)(dest, 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 (dest.numRects != curBand)            prevBand = miCoalesce(dest, 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 = dest.numRects;        if (ybot >= ytop)            (*overlapFunc)(dest, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);        if (dest.numRects != curBand)            prevBand = miCoalesce(dest, 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 = dest.numRects;    if (r1 != r1End) {        if (nonOverlap1Func != 0) {            do {                r1BandEnd = r1;                while (r1BandEnd < r1End && r1BandEnd->top() == r1->top())                    ++r1BandEnd;                (*nonOverlap1Func)(dest, r1, r1BandEnd, qMax(r1->top(), ybot + 1), r1->bottom());                r1 = r1BandEnd;            } while (r1 != r1End);        }    } else if ((r2 != r2End) && (nonOverlap2Func != 0)) {        do {            r2BandEnd = r2;            while (r2BandEnd < r2End && r2BandEnd->top() == r2->top())                 ++r2BandEnd;            (*nonOverlap2Func)(dest, r2, r2BandEnd, qMax(r2->top(), ybot + 1), r2->bottom());            r2 = r2BandEnd;        } while (r2 != r2End);    }    if (dest.numRects != curBand)        (void)miCoalesce(dest, 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.     *     * 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 (dest.numRects < (dest.rects.size() >> 1))        dest.rects.resize(dest.numRects);}/*====================================================================== *          Region Union *====================================================================*//*- *----------------------------------------------------------------------- * miUnionNonO -- *      Handle a non-overlapping band for the union operation. Just

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -