src/gui/painting/qregion_unix.cpp File Reference

#include "qregion.h"
#include "qpainterpath.h"
#include "qpolygon.h"
#include "qbuffer.h"
#include "qimage.h"
#include <qdebug.h>
#include "qbitmap.h"
#include <stdlib.h>
#include "qregion_x11.cpp"
#include <limits.h>

Include dependency graph for qregion_unix.cpp:

Go to the source code of this file.

Classes

struct  QRegionPrivate
struct  _POINTBLOCK
struct  BRESINFO
struct  _EdgeTableEntry
struct  _ScanLineList
struct  EdgeTable
struct  _ScanLineListBlock

Defines

#define RectangleOut   0
#define RectangleIn   1
#define RectanglePart   2
#define EvenOddRule   0
#define WindingRule   1
#define EXTENTCHECK(r1, r2)
#define EXTENTS(r, idRect)
#define MEMCHECK(dest, rect, firstrect)
#define NUMPTSTOBUFFER   200
#define MERGERECT(r)
#define BRESINITPGON(dy, x1, x2, xStart, d, m, m1, incr1, incr2)
#define BRESINCRPGON(d, minval, m, m1, incr1, incr2)
#define BRESINITPGONSTRUCT(dmaj, min1, min2, bres)
#define BRESINCRPGONSTRUCT(bres)   BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)
#define CLOCKWISE   1
#define COUNTERCLOCKWISE   -1
#define SLLSPERBLOCK   25
#define EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
#define EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
#define LARGE_COORDINATE   1000000
#define SMALL_COORDINATE   -LARGE_COORDINATE
#define AddSpan

Typedefs

typedef void(*) OverlapFunc (register QRegionPrivate &dest, register const QRect *r1, const QRect *r1End, register const QRect *r2, const QRect *r2End, register int y1, register int y2)
typedef void(*) NonOverlapFunc (register QRegionPrivate &dest, register const QRect *r, const QRect *rEnd, register int y1, register int y2)
typedef _POINTBLOCK POINTBLOCK
typedef _EdgeTableEntry EdgeTableEntry
typedef _ScanLineList ScanLineList
typedef _ScanLineListBlock ScanLineListBlock

Functions

static bool isEmpty (const QRegionPrivate *preg)
static bool EqualRegion (const QRegionPrivate *r1, const QRegionPrivate *r2)
static void UnionRegion (const QRegionPrivate *reg1, const QRegionPrivate *reg2, QRegionPrivate &dest)
static void miRegionOp (register QRegionPrivate &dest, const QRegionPrivate *reg1, const QRegionPrivate *reg2, OverlapFunc overlapFunc, NonOverlapFunc nonOverlap1Func, NonOverlapFunc nonOverlap2Func)
static void UnionRectWithRegion (register const QRect *rect, const QRegionPrivate *source, QRegionPrivate &dest)
static void miSetExtents (QRegionPrivate &dest)
static void OffsetRegion (register QRegionPrivate &region, register int x, register int y)
static void miIntersectO (register QRegionPrivate &dest, register const QRect *r1, const QRect *r1End, register const QRect *r2, const QRect *r2End, int y1, int y2)
static int miCoalesce (register QRegionPrivate &dest, int prevStart, int curStart)
static void miUnionNonO (register QRegionPrivate &dest, register const QRect *r, const QRect *rEnd, register int y1, register int y2)
static void miUnionO (register QRegionPrivate &dest, register const QRect *r1, const QRect *r1End, register const QRect *r2, const QRect *r2End, register int y1, register int y2)
static void miSubtractNonO1 (register QRegionPrivate &dest, register const QRect *r, const QRect *rEnd, register int y1, register int y2)
static void miSubtractO (register QRegionPrivate &dest, register const QRect *r1, const QRect *r1End, register const QRect *r2, const QRect *r2End, register int y1, register int y2)
static void SubtractRegion (QRegionPrivate *regM, QRegionPrivate *regS, register QRegionPrivate &dest)
static void XorRegion (QRegionPrivate *sra, QRegionPrivate *srb, QRegionPrivate &dest)
static bool PointInRegion (QRegionPrivate *pRegion, int x, int y)
static bool RectInRegion (register QRegionPrivate *region, int rx, int ry, uint rwidth, uint rheight)
static void InsertEdgeInET (EdgeTable *ET, EdgeTableEntry *ETE, int scanline, ScanLineListBlock **SLLBlock, int *iSLLBlock)
static void CreateETandAET (register int count, register const QPoint *pts, EdgeTable *ET, EdgeTableEntry *AET, register EdgeTableEntry *pETEs, ScanLineListBlock *pSLLBlock)
static void loadAET (register EdgeTableEntry *AET, register EdgeTableEntry *ETEs)
static void computeWAET (register EdgeTableEntry *AET)
static int InsertionSort (register EdgeTableEntry *AET)
static void FreeStorage (register ScanLineListBlock *pSLLBlock)
static void PtsToRegion (register int numFullPtBlocks, register int iCurPtBlock, POINTBLOCK *FirstPtBlock, QRegionPrivate *reg)
static QRegionPrivatePolygonRegion (const QPoint *Pts, int Count, int rule)
QRegionPrivateqt_bitmapToRegion (const QBitmap &bitmap)


Define Documentation

#define AddSpan

Value:

{ \
            xr.setCoords(prev1, y, x-1, y); \
            UnionRectWithRegion(&xr, region, *region); \
        }

#define BRESINCRPGON ( d,
minval,
m,
m1,
incr1,
incr2   ) 

Value:

{ \
    if (m1 > 0) { \
        if (d > 0) { \
            minval += m1; \
            d += incr1; \
        } \
        else { \
            minval += m; \
            d += incr2; \
        } \
    } else {\
        if (d >= 0) { \
            minval += m1; \
            d += incr1; \
        } \
        else { \
            minval += m; \
            d += incr2; \
        } \
    } \
}

Definition at line 1528 of file qregion_unix.cpp.

#define BRESINCRPGONSTRUCT ( bres   )     BRESINCRPGON(bres.d, bres.minor_axis, bres.m, bres.m1, bres.incr1, bres.incr2)

Definition at line 1570 of file qregion_unix.cpp.

#define BRESINITPGON ( dy,
x1,
x2,
xStart,
d,
m,
m1,
incr1,
incr2   ) 

Value:

{ \
    int dx;      /* local storage */ \
\
    /* \
     *  if the edge is horizontal, then it is ignored \
     *  and assumed not to be processed.  Otherwise, do this stuff. \
     */ \
    if ((dy) != 0) { \
        xStart = (x1); \
        dx = (x2) - xStart; \
        if (dx < 0) { \
            m = dx / (dy); \
            m1 = m - 1; \
            incr1 = -2 * dx + 2 * (dy) * m1; \
            incr2 = -2 * dx + 2 * (dy) * m; \
            d = 2 * m * (dy) - 2 * dx - 2 * (dy); \
        } else { \
            m = dx / (dy); \
            m1 = m + 1; \
            incr1 = 2 * dx - 2 * (dy) * m1; \
            incr2 = 2 * dx - 2 * (dy) * m; \
            d = -2 * m * (dy) + 2 * dx; \
        } \
    } \
}

Definition at line 1505 of file qregion_unix.cpp.

#define BRESINITPGONSTRUCT ( dmaj,
min1,
min2,
bres   ) 

Value:

BRESINITPGON(dmaj, min1, min2, bres.minor_axis, bres.d, \
                     bres.m, bres.m1, bres.incr1, bres.incr2)

Definition at line 1566 of file qregion_unix.cpp.

Referenced by CreateETandAET().

#define CLOCKWISE   1

Definition at line 1624 of file qregion_unix.cpp.

#define COUNTERCLOCKWISE   -1

Definition at line 1625 of file qregion_unix.cpp.

#define EVALUATEEDGEEVENODD ( pAET,
pPrevAET,
 ) 

Value:

{ \
   if (pAET->ymax == y) {          /* leaving this edge */ \
      pPrevAET->next = pAET->next; \
      pAET = pPrevAET->next; \
      if (pAET) \
         pAET->back = pPrevAET; \
   } \
   else { \
      BRESINCRPGONSTRUCT(pAET->bres) \
      pPrevAET = pAET; \
      pAET = pAET->next; \
   } \
}

Definition at line 1701 of file qregion_unix.cpp.

Referenced by PolygonRegion().

#define EVALUATEEDGEWINDING ( pAET,
pPrevAET,
y,
fixWAET   ) 

Value:

{ \
   if (pAET->ymax == y) {          /* leaving this edge */ \
      pPrevAET->next = pAET->next; \
      pAET = pPrevAET->next; \
      fixWAET = 1; \
      if (pAET) \
         pAET->back = pPrevAET; \
   } \
   else { \
      BRESINCRPGONSTRUCT(pAET->bres) \
      pPrevAET = pAET; \
      pAET = pAET->next; \
   } \
}

Definition at line 1678 of file qregion_unix.cpp.

Referenced by PolygonRegion().

#define EvenOddRule   0

Definition at line 193 of file qregion_unix.cpp.

Referenced by QX11PaintEnginePrivate::fillPolygon_dev(), and PolygonRegion().

#define EXTENTCHECK ( r1,
r2   ) 

Value:

((r1)->right() >= (r2)->left() && \
         (r1)->left() <= (r2)->right() && \
         (r1)->bottom() >= (r2)->top() && \
         (r1)->top() <= (r2)->bottom())

Definition at line 255 of file qregion_unix.cpp.

Referenced by RectInRegion(), and SubtractRegion().

#define EXTENTS ( r,
idRect   ) 

Value:

{\
            if((r)->left() < (idRect)->extents.left())\
              (idRect)->extents.setLeft((r)->left());\
            if((r)->top() < (idRect)->extents.top())\
              (idRect)->extents.setTop((r)->top());\
            if((r)->right() > (idRect)->extents.right())\
              (idRect)->extents.setRight((r)->right());\
            if((r)->bottom() > (idRect)->extents.bottom())\
              (idRect)->extents.setBottom((r)->bottom());\
        }

Definition at line 264 of file qregion_unix.cpp.

#define LARGE_COORDINATE   1000000

Definition at line 1766 of file qregion_unix.cpp.

Referenced by CreateETandAET().

#define MEMCHECK ( dest,
rect,
firstrect   ) 

Value:

{\
        if ((dest).numRects >= ((dest).rects.size()-1)){\
          firstrect.resize(firstrect.size() * 2); \
          (rect) = (firstrect).data() + (dest).numRects;\
        }\
      }

Definition at line 278 of file qregion_unix.cpp.

Referenced by miIntersectO(), miSubtractNonO1(), miSubtractO(), and miUnionNonO().

#define MERGERECT (  ) 

Value:

if ((dest.numRects != 0) &&  \
        (pNextRect[-1].top() == y1) &&  \
        (pNextRect[-1].bottom() == y2) &&  \
        (pNextRect[-1].right() >= r->left()-1)) { \
        if (pNextRect[-1].right() < r->right()) { \
            pNextRect[-1].setRight(r->right());  \
            Q_ASSERT(pNextRect[-1].left() <= pNextRect[-1].right()); \
        }  \
    } else { \
        MEMCHECK(dest, pNextRect, dest.rects)  \
        pNextRect->setCoords(r->left(), y1, r->right(), y2); \
        dest.numRects++;  \
        pNextRect++;  \
    }  \
    r++;

Referenced by miUnionO().

#define NUMPTSTOBUFFER   200

Definition at line 290 of file qregion_unix.cpp.

Referenced by PolygonRegion(), and PtsToRegion().

#define RectangleIn   1

Definition at line 191 of file qregion_unix.cpp.

Referenced by RectInRegion().

#define RectangleOut   0

Definition at line 190 of file qregion_unix.cpp.

Referenced by RectInRegion().

#define RectanglePart   2

Definition at line 192 of file qregion_unix.cpp.

Referenced by RectInRegion().

#define SLLSPERBLOCK   25

Definition at line 1656 of file qregion_unix.cpp.

Referenced by InsertEdgeInET(), and miInsertEdgeInET().

#define SMALL_COORDINATE   -LARGE_COORDINATE

Definition at line 1767 of file qregion_unix.cpp.

Referenced by CreateETandAET().

#define WindingRule   1

Definition at line 194 of file qregion_unix.cpp.

Referenced by QX11PaintEnginePrivate::fillPolygon_dev().


Typedef Documentation

typedef struct _EdgeTableEntry EdgeTableEntry

typedef void(*) NonOverlapFunc(register QRegionPrivate &dest, register const QRect *r, const QRect *rEnd, register int y1, register int y2)

Definition at line 181 of file qregion_unix.cpp.

typedef void(*) OverlapFunc(register QRegionPrivate &dest, register const QRect *r1, const QRect *r1End, register const QRect *r2, const QRect *r2End, register int y1, register int y2)

Definition at line 179 of file qregion_unix.cpp.

typedef struct _POINTBLOCK POINTBLOCK

typedef struct _ScanLineList ScanLineList

typedef struct _ScanLineListBlock ScanLineListBlock


Function Documentation

static void computeWAET ( register EdgeTableEntry AET  )  [static]

Definition at line 1989 of file qregion_unix.cpp.

References _EdgeTableEntry::next, and _EdgeTableEntry::nextWETE.

Referenced by PolygonRegion().

01993 {
01994     register EdgeTableEntry *pWETE;
01995     register int inside = 1;
01996     register int isInside = 0;
01997 
01998     AET->nextWETE = 0;
01999     pWETE = AET;
02000     AET = AET->next;
02001     while (AET) {
02002         if (AET->ClockWise)
02003             ++isInside;
02004         else
02005             --isInside;
02006 
02007         if (!inside && !isInside || inside && isInside) {
02008             pWETE->nextWETE = AET;
02009             pWETE = AET;
02010             inside = !inside;
02011         }
02012         AET = AET->next;

static void CreateETandAET ( register int  count,
register const QPoint pts,
EdgeTable ET,
EdgeTableEntry AET,
register EdgeTableEntry pETEs,
ScanLineListBlock pSLLBlock 
) [static]

Definition at line 1858 of file qregion_unix.cpp.

References _EdgeTableEntry::back, _EdgeTableEntry::bres, BRESINITPGONSTRUCT, InsertEdgeInET(), LARGE_COORDINATE, BRESINFO::minor_axis, _ScanLineListBlock::next, _ScanLineList::next, _EdgeTableEntry::next, _EdgeTableEntry::nextWETE, EdgeTable::scanlines, SMALL_COORDINATE, QPoint::x(), QPoint::y(), EdgeTable::ymax, and EdgeTable::ymin.

Referenced by PolygonRegion().

01864 {
01865     register const QPoint *top,
01866                           *bottom,
01867                           *PrevPt,
01868                           *CurrPt;
01869     int iSLLBlock = 0;
01870     int dy;
01871 
01872     if (count < 2)
01873         return;
01874 
01875     /*
01876      *  initialize the Active Edge Table
01877      */
01878     AET->next = 0;
01879     AET->back = 0;
01880     AET->nextWETE = 0;
01881     AET->bres.minor_axis = SMALL_COORDINATE;
01882 
01883     /*
01884      *  initialize the Edge Table.
01885      */
01886     ET->scanlines.next = 0;
01887     ET->ymax = SMALL_COORDINATE;
01888     ET->ymin = LARGE_COORDINATE;
01889     pSLLBlock->next = 0;
01890 
01891     PrevPt = &pts[count - 1];
01892 
01893     /*
01894      *  for each vertex in the array of points.
01895      *  In this loop we are dealing with two vertices at
01896      *  a time -- these make up one edge of the polygon.
01897      */
01898     while (count--) {
01899         CurrPt = pts++;
01900 
01901         /*
01902          *  find out which point is above and which is below.
01903          */
01904         if (PrevPt->y() > CurrPt->y()) {
01905             bottom = PrevPt;
01906             top = CurrPt;
01907             pETEs->ClockWise = 0;
01908         } else {
01909             bottom = CurrPt;
01910             top = PrevPt;
01911             pETEs->ClockWise = 1;
01912         }
01913 
01914         /*
01915          * don't add horizontal edges to the Edge table.
01916          */
01917         if (bottom->y() != top->y()) {
01918             pETEs->ymax = bottom->y() - 1;  /* -1 so we don't get last scanline */
01919 
01920             /*
01921              *  initialize integer edge algorithm
01922              */
01923             dy = bottom->y() - top->y();
01924             BRESINITPGONSTRUCT(dy, top->x(), bottom->x(), pETEs->bres)
01925 
01926             InsertEdgeInET(ET, pETEs, top->y(), &pSLLBlock, &iSLLBlock);
01927 
01928             if (PrevPt->y() > ET->ymax)
01929                 ET->ymax = PrevPt->y();
01930             if (PrevPt->y() < ET->ymin)
01931                 ET->ymin = PrevPt->y();
01932             ++pETEs;
01933         }
01934 

Here is the call graph for this function:

static bool EqualRegion ( const QRegionPrivate r1,
const QRegionPrivate r2 
) [static]

Definition at line 1320 of file qregion_unix.cpp.

References QVector< T >::constData(), QRegionPrivate::extents, i, QRegionPrivate::numRects, and QRegionPrivate::rects.

Referenced by SubtractRegion(), and UnionRegion().

01321 {
01322     if (r1->numRects != r2->numRects) {
01323         return false;
01324     } else if (r1->numRects == 0) {
01325         return true;
01326     } else if (r1->extents != r2->extents) {
01327         return false;
01328     } else {
01329         const QRect *rr1 = r1->rects.constData();
01330         const QRect *rr2 = r2->rects.constData();
01331         for (int i = 0; i < r1->numRects; ++i, ++rr1, ++rr2) {
01332             if (*rr1 != *rr2)
01333                 return false;
01334         }
01335     }
01336 
01337     return true;
01338 }

Here is the call graph for this function:

static void FreeStorage ( register ScanLineListBlock pSLLBlock  )  [static]

Definition at line 2056 of file qregion_unix.cpp.

References _ScanLineListBlock::next.

Referenced by PolygonRegion().

02060 {
02061     register ScanLineListBlock *tmpSLLBlock;
02062 
02063     while (pSLLBlock) {
02064         tmpSLLBlock = pSLLBlock->next;
02065         free(pSLLBlock);

static void InsertEdgeInET ( EdgeTable ET,
EdgeTableEntry ETE,
int  scanline,
ScanLineListBlock **  SLLBlock,
int *  iSLLBlock 
) [static]

Definition at line 1778 of file qregion_unix.cpp.

References _EdgeTableEntry::bres, _ScanLineList::edgelist, BRESINFO::minor_axis, _ScanLineListBlock::next, _ScanLineList::next, _EdgeTableEntry::next, NULL, _ScanLineList::scanline, EdgeTable::scanlines, SLLSPERBLOCK, and start.

Referenced by CreateETandAET().

01783 {
01784     register EdgeTableEntry *start, *prev;
01785     register ScanLineList *pSLL, *pPrevSLL;
01786     ScanLineListBlock *tmpSLLBlock;
01787 
01788     /*
01789      * find the right bucket to put the edge into
01790      */
01791     pPrevSLL = &ET->scanlines;
01792     pSLL = pPrevSLL->next;
01793     while (pSLL && (pSLL->scanline < scanline)) {
01794         pPrevSLL = pSLL;
01795         pSLL = pSLL->next;
01796     }
01797 
01798     /*
01799      * reassign pSLL (pointer to ScanLineList) if necessary
01800      */
01801     if ((!pSLL) || (pSLL->scanline > scanline)) {
01802         if (*iSLLBlock > SLLSPERBLOCK-1)
01803         {
01804             tmpSLLBlock =
01805                   (ScanLineListBlock *)malloc(sizeof(ScanLineListBlock));
01806             (*SLLBlock)->next = tmpSLLBlock;
01807             tmpSLLBlock->next = (ScanLineListBlock *)NULL;
01808             *SLLBlock = tmpSLLBlock;
01809             *iSLLBlock = 0;
01810         }
01811         pSLL = &((*SLLBlock)->SLLs[(*iSLLBlock)++]);
01812 
01813         pSLL->next = pPrevSLL->next;
01814         pSLL->edgelist = (EdgeTableEntry *)NULL;
01815         pPrevSLL->next = pSLL;
01816     }
01817     pSLL->scanline = scanline;
01818 
01819     /*
01820      * now insert the edge in the right bucket
01821      */
01822     prev = 0;
01823     start = pSLL->edgelist;
01824     while (start && (start->bres.minor_axis < ETE->bres.minor_axis)) {
01825         prev = start;
01826         start = start->next;
01827     }
01828     ETE->next = start;
01829 
01830     if (prev)
01831         prev->next = ETE;

static int InsertionSort ( register EdgeTableEntry AET  )  [static]

Definition at line 2023 of file qregion_unix.cpp.

References _EdgeTableEntry::back, _EdgeTableEntry::bres, BRESINFO::minor_axis, and _EdgeTableEntry::next.

Referenced by PolygonRegion().

02027 {
02028     register EdgeTableEntry *pETEchase;
02029     register EdgeTableEntry *pETEinsert;
02030     register EdgeTableEntry *pETEchaseBackTMP;
02031     register int changed = 0;
02032 
02033     AET = AET->next;
02034     while (AET) {
02035         pETEinsert = AET;
02036         pETEchase = AET;
02037         while (pETEchase->back->bres.minor_axis > AET->bres.minor_axis)
02038             pETEchase = pETEchase->back;
02039 
02040         AET = AET->next;
02041         if (pETEchase != pETEinsert) {
02042             pETEchaseBackTMP = pETEchase->back;
02043             pETEinsert->back->next = AET;
02044             if (AET)
02045                 AET->back = pETEinsert->back;
02046             pETEinsert->next = pETEchase;
02047             pETEchase->back->next = pETEinsert;
02048             pETEchase->back = pETEinsert;
02049             pETEinsert->back = pETEchaseBackTMP;
02050             changed = 1;
02051         }

static bool isEmpty ( const QRegionPrivate preg  )  [inline, static]

Definition at line 173 of file qregion_unix.cpp.

References QRegionPrivate::numRects.

Referenced by qdesigner_internal::FormWindow::absoluteDir(), qdesigner_internal::FindIconDialog::accept(), qdesigner_internal::QrcView::acceptDrop(), QSvgStructureNode::addChild(), Q3Url::addPath(), Q3ActionGroup::addTo(), qdesigner_internal::FormWindowWidgetStack::addTool(), QSvgNode::appendStyleProperty(), Browser::Browser(), Q3Action::clearStatusText(), ConnectionManager::clientId(), TextEdit::clipboardDataChanged(), collision_double_dispatch(), SourceTextEdit::contextMenuEvent(), QApplicationPrivate::createEventDispatcher(), QCoreApplicationPrivate::createEventDispatcher(), QThreadPrivate::createEventDispatcher(), Ui3Reader::createFormImpl(), DocuParser::createParser(), createReadHandler(), Q3Url::dirPath(), Q3TextDocument::draw(), QObject::dumpObjectInfo(), QSet< Feature * >::empty(), QMap< int, QFrameInfo >::empty(), TextEdit::filePrintPdf(), QDropData::formats_sys(), QRingBuffer::getChar(), QDockWidgetLayout::getGrid(), getLprPrinters(), Q3ListBoxPixmap::height(), qdesigner_internal::WidgetDataBase::indexOfObject(), isNull(), Q3PointArray::isNull(), QTextEdit::keyPressEvent(), QDialogButtonBoxPrivate::layoutButtons(), main(), merge(), QUrlPrivate::mergePaths(), Q3Ftp::operationListChildren(), Q3Ftp::operationRemove(), Q3Ftp::operationRename(), Q3TextEdit::optimSelectedText(), Q3TextEdit::optimText(), Q3ListBoxPixmap::paint(), Mouse::paint(), Q3TextEdit::paragraphLength(), QXmlSimpleReaderPrivate::parseContent(), Semantic::parseDeclaration(), Semantic::parseNamespace(), PointInRegion(), ProjectPorter::portProFile(), QXmlSimpleReaderPrivate::processReference(), QCss::Selector::pseudoState(), qDBusGenerateMetaObjectXml(), QSessionManager::QSessionManager(), QXmlSimpleReaderPrivate::reportEndEntities(), qdesigner_internal::WidgetBoxTreeView::save(), MetaTranslator::save(), QSqlRelationalTableModel::selectStatement(), QDockWidgetLayout::separatorRect(), Q3Url::setFileName(), QDockWidgetLayout::setGrid(), qdesigner_internal::FindIconDialog::setPaths(), QAccessible::setRootObject(), QApplication::setStyle(), TextEdit::setupEditActions(), QUiLoaderPrivate::setupWidgetMap(), QSvgHandler::startElement(), SubtractRegion(), QAccessibleWidget::text(), Feature::toHtml(), UnionRegion(), QAccessible::updateAccessibility(), qdesigner_internal::NewActionDialog::updateButtons(), LocationDialog::updateLocationsTable(), QWorkspaceChild::updateMask(), qdesigner_internal::SignalSlotConnection::updateVisibility(), QTestAccessibility::verifyEvent(), Q3ListBoxPixmap::width(), and FeatureTreeModel::~FeatureTreeModel().

00174 {
00175     return !preg || preg->numRects == 0;
00176 }

static void loadAET ( register EdgeTableEntry AET,
register EdgeTableEntry ETEs 
) [static]

Definition at line 1945 of file qregion_unix.cpp.

References _EdgeTableEntry::back, and _EdgeTableEntry::next.

Referenced by PolygonRegion().

01949 {
01950     register EdgeTableEntry *pPrevAET;
01951     register EdgeTableEntry *tmp;
01952 
01953     pPrevAET = AET;
01954     AET = AET->next;
01955     while (ETEs) {
01956         while (AET && AET->bres.minor_axis < ETEs->bres.minor_axis) {
01957             pPrevAET = AET;
01958             AET = AET->next;
01959         }
01960         tmp = ETEs->next;
01961         ETEs->next = AET;
01962         if (AET)
01963             AET->back = ETEs;
01964         ETEs->back = pPrevAET;
01965         pPrevAET->next = ETEs;
01966         pPrevAET = ETEs;
01967 

static int miCoalesce ( register QRegionPrivate dest,
int  prevStart,
int  curStart 
) [static]

Definition at line 564 of file qregion_unix.cpp.

References QRect::bottom(), QRect::left(), QRect::right(), QRect::setBottom(), and QRect::top().

Referenced by miRegionOp().

00565 {
00566     register QRect *pPrevBox;   /* Current box in previous band */
00567     register QRect *pCurBox;    /* Current box in current band */
00568     register QRect *pRegEnd;    /* End of region */
00569     int curNumRects;    /* Number of rectangles in current band */
00570     int prevNumRects;   /* Number of rectangles in previous band */
00571     int bandY1;         /* Y1 coordinate for current band */
00572     QRect *rData = dest.rects.data();
00573 
00574     pRegEnd = rData + dest.numRects;
00575 
00576     pPrevBox = rData + prevStart;
00577     prevNumRects = curStart - prevStart;
00578 
00579     /*
00580      * Figure out how many rectangles are in the current band. Have to do
00581      * this because multiple bands could have been added in miRegionOp
00582      * at the end when one region has been exhausted.
00583      */
00584     pCurBox = rData + curStart;
00585     bandY1 = pCurBox->top();
00586     for (curNumRects = 0; pCurBox != pRegEnd && pCurBox->top() == bandY1; ++curNumRects) {
00587         ++pCurBox;
00588     }
00589 
00590     if (pCurBox != pRegEnd) {
00591         /*
00592          * If more than one band was added, we have to find the start
00593          * of the last band added so the next coalescing job can start
00594          * at the right place... (given when multiple bands are added,
00595          * this may be pointless -- see above).
00596          */
00597         --pRegEnd;
00598         while ((pRegEnd - 1)->top() == pRegEnd->top())
00599             --pRegEnd;
00600         curStart = pRegEnd - rData;
00601         pRegEnd = rData + dest.numRects;
00602     }
00603 
00604     if (curNumRects == prevNumRects && curNumRects != 0) {
00605         pCurBox -= curNumRects;
00606         /*
00607          * The bands may only be coalesced if the bottom of the previous
00608          * matches the top scanline of the current.
00609          */
00610         if (pPrevBox->bottom() == pCurBox->top() - 1) {
00611             /*
00612              * Make sure the bands have boxes in the same places. This
00613              * assumes that boxes have been added in such a way that they
00614              * cover the most area possible. I.e. two boxes in a band must
00615              * have some horizontal space between them.
00616              */
00617             do {
00618                 if (pPrevBox->left() != pCurBox->left() || pPrevBox->right() != pCurBox->right()) {
00619                      // The bands don't line up so they can't be coalesced.
00620                     return curStart;
00621                 }
00622                 ++pPrevBox;
00623                 ++pCurBox;
00624                 --prevNumRects;
00625             } while (prevNumRects != 0);
00626 
00627             dest.numRects -= curNumRects;
00628             pCurBox -= curNumRects;
00629             pPrevBox -= curNumRects;
00630 
00631             /*
00632              * The bands may be merged, so set the bottom y of each box
00633              * in the previous band to that of the corresponding box in
00634              * the current band.
00635              */
00636             do {
00637                 pPrevBox->setBottom(pCurBox->bottom());
00638 #ifdef QT_EXPERIMENTAL_REGIONS
00639                 dest.updateInnerRect(*pPrevBox);
00640 #endif
00641                 ++pPrevBox;
00642                 ++pCurBox;
00643                 curNumRects -= 1;
00644             } while (curNumRects != 0);
00645 
00646             /*
00647              * If only one band was added to the region, we have to backup
00648              * curStart to the start of the previous band.
00649              *
00650              * If more than one band was added to the region, copy the
00651              * other bands down. The assumption here is that the other bands
00652              * came from the same region as the current one and no further
00653              * coalescing can be done on them since it's all been done
00654              * already... curStart is already in the right place.
00655              */
00656             if (pCurBox == pRegEnd) {
00657                 curStart = prevStart;
00658             } else {
00659                 do {
00660                     *pPrevBox++ = *pCurBox++;
00661 #ifdef QT_EXPERIMENTAL_REGIONS
00662                     dest.updateInnerRect(*pPrevBox);
00663 #endif
00664                 } while (pCurBox != pRegEnd);
00665             }
00666         }
00667     }
00668     return curStart;
00669 }

Here is the call graph for this function:

static void miIntersectO ( register QRegionPrivate dest,
register const QRect r1,
const QRect r1End,
register const QRect r2,
const QRect r2End,
int  y1,
int  y2 
) [static]

Definition at line 499 of file qregion_unix.cpp.

References MEMCHECK, qMax(), qMin(), and QRect::setCoords().

00501 {
00502     register int x1;
00503     register int x2;
00504     register QRect *pNextRect;
00505 
00506     pNextRect = dest.rects.data() + dest.numRects;
00507 
00508     while (r1 != r1End && r2 != r2End) {
00509         x1 = qMax(r1->left(), r2->left());
00510         x2 = qMin(r1->right(), r2->right());
00511 
00512         /*
00513          * If there's any overlap between the two rectangles, add that
00514          * overlap to the new region.
00515          * There's no need to check for subsumption because the only way
00516          * such a need could arise is if some region has two rectangles
00517          * right next to each other. Since that should never happen...
00518          */
00519         if (x1 <= x2) {
00520             Q_ASSERT(y1 <= y2);
00521             MEMCHECK(dest, pNextRect, dest.rects)
00522             pNextRect->setCoords(x1, y1, x2, y2);
00523             ++dest.numRects;
00524             ++pNextRect;
00525         }
00526 
00527         /*
00528          * Need to advance the pointers. Shift the one that extends
00529          * to the right the least, since the other still has a chance to
00530          * overlap with that region's next rectangle, if you see what I mean.
00531          */
00532         if (r1->right() < r2->right()) {
00533             ++r1;
00534         } else if (r2->right() < r1->right()) {
00535             ++r2;
00536         } else {
00537             ++r1;
00538             ++r2;
00539         }
00540     }
00541 }

Here is the call graph for this function:

static void miRegionOp ( register QRegionPrivate dest,
const QRegionPrivate reg1,
const QRegionPrivate reg2,
OverlapFunc  overlapFunc,
NonOverlapFunc  nonOverlap1Func,
NonOverlapFunc  nonOverlap2Func 
) [static]

Definition at line 697 of file qregion_unix.cpp.

References QRect::bottom(), QVector< T >::data(), QRegionPrivate::extents, miCoalesce(), QRegionPrivate::numRects, qMax(), qMin(), QRegionPrivate::rects, and QRect::top().

Referenced by SubtractRegion(), and UnionRegion().

00700 {
00701     register const QRect *r1;         // Pointer into first region
00702     register const QRect *r2;         // Pointer into 2d region
00703     const QRect *r1End;               // End of 1st region
00704     const QRect *r2End;               // End of 2d region
00705     register int ybot;          // Bottom of intersection
00706     register int ytop;          // Top of intersection
00707     int prevBand;               // Index of start of previous band in dest
00708     int curBand;                // Index of start of current band in dest
00709     register const QRect *r1BandEnd;  // End of current band in r1
00710     register const QRect *r2BandEnd;  // End of current band in r2
00711     int top;                    // Top of non-overlapping band
00712     int bot;                    // Bottom of non-overlapping band
00713 
00714     /*
00715      * Initialization:
00716      *  set r1, r2, r1End and r2End appropriately, preserve the important
00717      * parts of the destination region until the end in case it's one of
00718      * the two source regions, then mark the "new" region empty, allocating
00719      * another array of rectangles for it to use.
00720      */
00721     r1 = reg1->rects.data();
00722     r2 = reg2->rects.data();
00723     r1End = r1 + reg1->numRects;
00724     r2End = r2 + reg2->numRects;
00725 
00726     QVector<QRect> oldRects = dest.rects;
00727 
00728     dest.numRects = 0;
00729 
00730     /*
00731      * Allocate a reasonable number of rectangles for the new region. The idea
00732      * is to allocate enough so the individual functions don't need to
00733      * reallocate and copy the array, which is time consuming, yet we don't
00734      * have to worry about using too much memory. I hope to be able to
00735      * nuke the realloc() at the end of this function eventually.
00736      */
00737     dest.rects.resize(qMax(reg1->numRects,reg2->numRects) * 2);
00738 
00739     /*
00740      * Initialize ybot and ytop.
00741      * In the upcoming loop, ybot and ytop serve different functions depending
00742      * on whether the band being handled is an overlapping or non-overlapping
00743      * band.
00744      *  In the case of a non-overlapping band (only one of the regions
00745      * has points in the band), ybot is the bottom of the most recent
00746      * intersection and thus clips the top of the rectangles in that band.
00747      * ytop is the top of the next intersection between the two regions and
00748      * serves to clip the bottom of the rectangles in the current band.
00749      *  For an overlapping band (where the two regions intersect), ytop clips
00750      * the top of the rectangles of both regions and ybot clips the bottoms.
00751      */
00752     if (reg1->extents.top() < reg2->extents.top())
00753         ybot = reg1->extents.top() - 1;
00754     else
00755         ybot = reg2->extents.top() - 1;
00756 
00757     /*
00758      * prevBand serves to mark the start of the previous band so rectangles
00759      * can be coalesced into larger rectangles. qv. miCoalesce, above.
00760      * In the beginning, there is no previous band, so prevBand == curBand
00761      * (curBand is set later on, of course, but the first band will always
00762      * start at index 0). prevBand and curBand must be indices because of
00763      * the possible expansion, and resultant moving, of the new region's
00764      * array of rectangles.
00765      */
00766     prevBand = 0;
00767 
00768     do {
00769         curBand = dest.numRects;
00770 
00771         /*
00772          * This algorithm proceeds one source-band (as opposed to a
00773          * destination band, which is determined by where the two regions
00774          * intersect) at a time. r1BandEnd and r2BandEnd serve to mark the
00775          * rectangle after the last one in the current band for their
00776          * respective regions.
00777          */
00778         r1BandEnd = r1;
00779         while (r1BandEnd != r1End && r1BandEnd->top() == r1->top())
00780             ++r1BandEnd;
00781 
00782         r2BandEnd = r2;
00783         while (r2BandEnd != r2End && r2BandEnd->top() == r2->top())
00784             ++r2BandEnd;
00785 
00786         /*
00787          * First handle the band that doesn't intersect, if any.
00788          *
00789          * Note that attention is restricted to one band in the
00790          * non-intersecting region at once, so if a region has n
00791          * bands between the current position and the next place it overlaps
00792          * the other, this entire loop will be passed through n times.
00793          */
00794         if (r1->top() < r2->top()) {
00795             top = qMax(r1->top(), ybot + 1);
00796             bot = qMin(r1->bottom(), r2->top() - 1);
00797 
00798             if (nonOverlap1Func != 0 && bot >= top)
00799                 (*nonOverlap1Func)(dest, r1, r1BandEnd, top, bot);
00800             ytop = r2->top();
00801         } else if (r2->top() < r1->top()) {
00802             top = qMax(r2->top(), ybot + 1);
00803             bot = qMin(r2->bottom(), r1->top() - 1);
00804 
00805             if (nonOverlap2Func != 0 && bot >= top)
00806                 (*nonOverlap2Func)(dest, r2, r2BandEnd, top, bot);
00807             ytop = r1->top();
00808         } else {
00809             ytop = r1->top();
00810         }
00811 
00812         /*
00813          * If any rectangles got added to the region, try and coalesce them
00814          * with rectangles from the previous band. Note we could just do
00815          * this test in miCoalesce, but some machines incur a not
00816          * inconsiderable cost for function calls, so...
00817          */
00818         if (dest.numRects != curBand)
00819             prevBand = miCoalesce(dest, prevBand, curBand);
00820 
00821         /*
00822          * Now see if we've hit an intersecting band. The two bands only
00823          * intersect if ybot >= ytop
00824          */
00825         ybot = qMin(r1->bottom(), r2->bottom());
00826         curBand = dest.numRects;
00827         if (ybot >= ytop)
00828             (*overlapFunc)(dest, r1, r1BandEnd, r2, r2BandEnd, ytop, ybot);
00829 
00830         if (dest.numRects != curBand)
00831             prevBand = miCoalesce(dest, prevBand, curBand);
00832 
00833         /*
00834          * If we've finished with a band (y2 == ybot) we skip forward
00835          * in the region to the next band.
00836          */
00837         if (r1->bottom() == ybot)
00838             r1 = r1BandEnd;
00839         if (r2->bottom() == ybot)
00840             r2 = r2BandEnd;
00841     } while (r1 != r1End && r2 != r2End);
00842 
00843     /*
00844      * Deal with whichever region still has rectangles left.
00845      */
00846     curBand = dest.numRects;
00847     if (r1 != r1End) {
00848         if (nonOverlap1Func != 0) {
00849             do {
00850                 r1BandEnd = r1;
00851                 while (r1BandEnd < r1End && r1BandEnd->top() == r1->top())
00852                     ++r1BandEnd;
00853                 (*nonOverlap1Func)(dest, r1, r1BandEnd, qMax(r1->top(), ybot + 1), r1->bottom());
00854                 r1 = r1BandEnd;
00855             } while (r1 != r1End);
00856         }
00857     } else if ((r2 != r2End) && (nonOverlap2Func != 0)) {
00858         do {
00859             r2BandEnd = r2;
00860             while (r2BandEnd < r2End && r2BandEnd->top() == r2->top())
00861                  ++r2BandEnd;
00862             (*nonOverlap2Func)(dest, r2, r2BandEnd, qMax(r2->top(), ybot + 1), r2->bottom());
00863             r2 = r2BandEnd;
00864         } while (r2 != r2End);
00865     }
00866 
00867     if (dest.numRects != curBand)
00868         (void)miCoalesce(dest, prevBand, curBand);
00869 
00870     /*
00871      * A bit of cleanup. To keep regions from growing without bound,
00872      * we shrink the array of rectangles to match the new number of
00873      * rectangles in the region.
00874      *
00875      * Only do this stuff if the number of rectangles allocated is more than
00876      * twice the number of rectangles in the region (a simple optimization).
00877      */
00878 #ifdef QT_EXPERIMENTAL_REGIONS
00879     if (qMax(4, dest.numRects) < (dest.rects.size() >> 1))
00880 #else
00881     if (dest.numRects < (dest.rects.size() >> 1))
00882 #endif
00883         dest.rects.resize(dest.numRects);
00884 }

Here is the call graph for this function:

static void miSetExtents ( QRegionPrivate dest  )  [static]

Definition at line 415 of file qregion_unix.cpp.

References QRect::bottom(), QVector< T >::constData(), QRegionPrivate::extents, QRect::left(), QRegionPrivate::numRects, QRegionPrivate::rects, QRect::right(), QRect::setBottom(), QRect::setCoords(), QRect::setLeft(), QRect::setRight(), QRect::setTop(), and QRect::top().

Referenced by SubtractRegion().

00416 {
00417     register const QRect *pBox,
00418                          *pBoxEnd;
00419     register QRect *pExtents;
00420 
00421 #ifdef QT_EXPERIMENTAL_REGIONS
00422     dest.innerRect.setCoords(0, 0, -1, -1);
00423     dest.innerArea = -1;
00424 #endif
00425     if (dest.numRects == 0) {
00426         dest.extents.setCoords(0, 0, 0, 0);
00427         return;
00428     }
00429 
00430     pExtents = &dest.extents;
00431     pBox = dest.rects.constData();
00432     pBoxEnd = &pBox[dest.numRects - 1];
00433 
00434     /*
00435      * Since pBox is the first rectangle in the region, it must have the
00436      * smallest y1 and since pBoxEnd is the last rectangle in the region,
00437      * it must have the largest y2, because of banding. Initialize x1 and
00438      * x2 from  pBox and pBoxEnd, resp., as good things to initialize them
00439      * to...
00440      */
00441     pExtents->setLeft(pBox->left());
00442     pExtents->setTop(pBox->top());
00443     pExtents->setRight(pBoxEnd->right());
00444     pExtents->setBottom(pBoxEnd->bottom());
00445 
00446     Q_ASSERT(pExtents->top() <= pExtents->bottom());
00447     while (pBox <= pBoxEnd) {
00448         if (pBox->left() < pExtents->left())
00449             pExtents->setLeft(pBox->left());
00450         if (pBox->right() > pExtents->right())
00451             pExtents->setRight(pBox->right());
00452 #ifdef QT_EXPERIMENTAL_REGIONS
00453         dest.updateInnerRect(*pBox);
00454 #endif
00455         ++pBox;
00456     }
00457     Q_ASSERT(pExtents->left() <= pExtents->right());
00458 }

Here is the call graph for this function:

static void miSubtractNonO1 ( register QRegionPrivate dest,
register const QRect r,
const QRect rEnd,
register int  y1,
register int  y2 
) [static]

Definition at line 1137 of file qregion_unix.cpp.

References MEMCHECK, and QRect::setCoords().

Referenced by SubtractRegion().

01139 {
01140     register QRect *pNextRect;
01141 
01142     pNextRect = dest.rects.data() + dest.numRects;
01143 
01144     Q_ASSERT(y1<=y2);
01145 
01146     while (r != rEnd) {
01147         Q_ASSERT(r->left() <= r->right());
01148         MEMCHECK(dest, pNextRect, dest.rects)
01149         pNextRect->setCoords(r->left(), y1, r->right(), y2);
01150         ++dest.numRects;
01151         ++pNextRect;
01152         ++r;
01153     }
01154 }

Here is the call graph for this function:

static void miSubtractO ( register QRegionPrivate dest,
register const QRect r1,
const QRect r1End,
register const QRect r2,
const QRect r2End,
register int  y1,
register int  y2 
) [static]

Definition at line 1171 of file qregion_unix.cpp.

References QTextStream::left(), QRect::left(), MEMCHECK, QTextStream::right(), QRect::right(), and QRect::setCoords().

Referenced by SubtractRegion().

01173 {
01174     register QRect *pNextRect;
01175     register int x1;
01176 
01177     x1 = r1->left();
01178 
01179     Q_ASSERT(y1 <= y2);
01180     pNextRect = dest.rects.data() + dest.numRects;
01181 
01182     while (r1 != r1End && r2 != r2End) {
01183         if (r2->right() < x1) {
01184             /*
01185              * Subtrahend missed the boat: go to next subtrahend.
01186              */
01187             ++r2;
01188         } else if (r2->left() <= x1) {
01189             /*
01190              * Subtrahend precedes minuend: nuke left edge of minuend.
01191              */
01192             x1 = r2->right() + 1;
01193             if (x1 > r1->right()) {
01194                 /*
01195                  * Minuend completely covered: advance to next minuend and
01196                  * reset left fence to edge of new minuend.
01197                  */
01198                 ++r1;
01199                 if (r1 != r1End)
01200                     x1 = r1->left();
01201             } else {
01202                 // Subtrahend now used up since it doesn't extend beyond minuend
01203                 ++r2;
01204             }
01205         } else if (r2->left() <= r1->right()) {
01206             /*
01207              * Left part of subtrahend covers part of minuend: add uncovered
01208              * part of minuend to region and skip to next subtrahend.
01209              */
01210             Q_ASSERT(x1 < r2->left());
01211             MEMCHECK(dest, pNextRect, dest.rects)
01212             pNextRect->setCoords(x1, y1, r2->left() - 1, y2);
01213             ++dest.numRects;
01214             ++pNextRect;
01215 
01216             x1 = r2->right() + 1;
01217             if (x1 > r1->right()) {
01218                 /*
01219                  * Minuend used up: advance to new...
01220                  */
01221                 ++r1;
01222                 if (r1 != r1End)
01223                     x1 = r1->left();
01224             } else {
01225                 // Subtrahend used up
01226                 ++r2;
01227             }
01228         } else {
01229             /*
01230              * Minuend used up: add any remaining piece before advancing.
01231              */
01232             if (r1->right() >= x1) {
01233                 MEMCHECK(dest, pNextRect, dest.rects)
01234                 pNextRect->setCoords(x1, y1, r1->right(), y2);
01235                 ++dest.numRects;
01236                 ++pNextRect;
01237             }
01238             ++r1;
01239             if (r1 != r1End)
01240                 x1 = r1->left();
01241         }
01242     }
01243 
01244     /*
01245      * Add remaining minuend rectangles to region.
01246      */
01247     while (r1 != r1End) {
01248         Q_ASSERT(x1 <= r1->right());
01249         MEMCHECK(dest, pNextRect, dest.rects)
01250         pNextRect->setCoords(x1, y1, r1->right(), y2);
01251         ++dest.numRects;
01252         ++pNextRect;
01253 
01254         ++r1;
01255         if (r1 != r1End)
01256             x1 = r1->left();
01257     }
01258 }

Here is the call graph for this function:

static void miUnionNonO ( register QRegionPrivate dest,
register const QRect r,
const QRect rEnd,
register int  y1,
register int  y2 
) [static]

Definition at line 907 of file qregion_unix.cpp.

References MEMCHECK, and QRect::setCoords().

Referenced by UnionRegion().

00909 {
00910     register QRect *pNextRect;
00911 
00912     pNextRect = dest.rects.data() + dest.numRects;
00913 
00914     Q_ASSERT(y1 <= y2);
00915 
00916     while (r != rEnd) {
00917         Q_ASSERT(r->left() <= r->right());
00918         MEMCHECK(dest, pNextRect, dest.rects)
00919         pNextRect->setCoords(r->left(), y1, r->right(), y2);
00920         dest.numRects++;
00921         ++pNextRect;
00922         ++r;
00923     }
00924 }

Here is the call graph for this function:

static void miUnionO ( register QRegionPrivate dest,
register const QRect r1,
const QRect r1End,
register const QRect r2,
const QRect r2End,
register int  y1,
register int  y2 
) [static]

Definition at line 943 of file qregion_unix.cpp.

References MERGERECT.

Referenced by UnionRegion().

00945 {
00946     register QRect *pNextRect;
00947 
00948     pNextRect = dest.rects.data() + dest.numRects;
00949 
00950 #ifndef QT_EXPERIMENTAL_REGIONS
00951 #define MERGERECT(r)             \
00952     if ((dest.numRects != 0) &&  \
00953         (pNextRect[-1].top() == y1) &&  \
00954         (pNextRect[-1].bottom() == y2) &&  \
00955         (pNextRect[-1].right() >= r->left()-1)) { \
00956         if (pNextRect[-1].right() < r->right()) { \
00957             pNextRect[-1].setRight(r->right());  \
00958             Q_ASSERT(pNextRect[-1].left() <= pNextRect[-1].right()); \
00959         }  \
00960     } else { \
00961         MEMCHECK(dest, pNextRect, dest.rects)  \
00962         pNextRect->setCoords(r->left(), y1, r->right(), y2); \
00963         dest.numRects++;  \
00964         pNextRect++;  \
00965     }  \
00966     r++;
00967 #else
00968 #define MERGERECT(r)             \
00969     if ((dest.numRects != 0) &&  \
00970         (pNextRect[-1].top() == y1) &&  \
00971         (pNextRect[-1].bottom() == y2) &&  \
00972         (pNextRect[-1].right() >= r->left()-1)) { \
00973         if (pNextRect[-1].right() < r->right()) { \
00974             pNextRect[-1].setRight(r->right());  \
00975             dest.updateInnerRect(pNextRect[-1]); \
00976             Q_ASSERT(pNextRect[-1].left() <= pNextRect[-1].right()); \
00977         }  \
00978     } else { \
00979         MEMCHECK(dest, pNextRect, dest.rects)  \
00980         pNextRect->setCoords(r->left(), y1, r->right(), y2); \
00981         dest.updateInnerRect(*pNextRect); \
00982         dest.numRects++;  \
00983         pNextRect++;  \
00984     }  \
00985     r++;
00986 #endif
00987 
00988     Q_ASSERT(y1 <= y2);
00989     while (r1 != r1End && r2 != r2End) {
00990         if (r1->left() < r2->left()) {
00991             MERGERECT(r1)
00992         } else {
00993             MERGERECT(r2)
00994         }
00995     }
00996 
00997     if (r1 != r1End) {
00998         do {
00999             MERGERECT(r1)
01000         } while (r1 != r1End);
01001     } else {
01002         while (r2 != r2End) {
01003             MERGERECT(r2)
01004         }
01005     }
01006 }

static void OffsetRegion ( register QRegionPrivate region,
register int  x,
register int  y 
) [static]

Definition at line 465 of file qregion_unix.cpp.

References QRect::translate().

00466 {
00467     register int nbox;
00468     register QRect *pbox;
00469 
00470     pbox = region.rects.data();
00471     nbox = region.numRects;
00472 
00473     while (nbox--) {
00474         pbox->translate(x, y);
00475         ++pbox;
00476     }
00477     region.extents.translate(x, y);
00478 #ifdef QT_EXPERIMENTAL_REGIONS
00479     region.innerRect.translate(x, y);
00480 #endif
00481 }

Here is the call graph for this function:

static bool PointInRegion ( QRegionPrivate pRegion,
int  x,
int  y 
) [static]

Definition at line 1340 of file qregion_unix.cpp.

References QRect::contains(), QVector< T >::contains(), QRegionPrivate::extents, i, isEmpty(), QRegionPrivate::numRects, and QRegionPrivate::rects.

01341 {
01342     int i;
01343 
01344     if (isEmpty(pRegion))
01345         return false;
01346     if (!pRegion->extents.contains(x, y))
01347         return false;
01348 #ifdef QT_EXPERIMENTAL_REGIONS
01349     if (pRegion->innerRect.contains(x, y))
01350         return true;
01351 #endif
01352     for (i = 0; i < pRegion->numRects; ++i) {
01353         if (pRegion->rects[i].contains(x, y))
01354             return true;
01355     }
01356     return false;
01357 }

Here is the call graph for this function:

static QRegionPrivate* PolygonRegion ( const QPoint Pts,
int  Count,
int  rule 
) [static]

Definition at line 2148 of file qregion_unix.cpp.

References QRect::bottom(), _EdgeTableEntry::bres, computeWAET(), CreateETandAET(), _ScanLineList::edgelist, EVALUATEEDGEEVENODD, EVALUATEEDGEWINDING, EvenOddRule, QRegionPrivate::extents, FreeStorage(), InsertionSort(), QRect::left(), loadAET(), BRESINFO::minor_axis, _ScanLineListBlock::next, _ScanLineList::next, _EdgeTableEntry::next, _POINTBLOCK::next, _EdgeTableEntry::nextWETE, NUMPTSTOBUFFER, QRegionPrivate::numRects, _POINTBLOCK::pts, PtsToRegion(), qMax(), qMin(), QRegionPrivate::rects, QVector< T >::resize(), QRect::right(), _ScanLineList::scanline, EdgeTable::scanlines, QRect::setHeight(), QRect::setLeft(), QRect::setTop(), QRect::setWidth(), QPoint::setX(), QPoint::setY(), QRect::top(), x, y, EdgeTable::ymax, and EdgeTable::ymin.

02155 {
02156     QRegionPrivate *region;
02157     register EdgeTableEntry *pAET;   /* Active Edge Table       */
02158     register int y;                  /* current scanline        */
02159     register int iPts = 0;           /* number of pts in buffer */
02160     register EdgeTableEntry *pWETE;  /* Winding Edge Table Entry*/
02161     register ScanLineList *pSLL;     /* current scanLineList    */
02162     register QPoint *pts;             /* output buffer           */
02163     EdgeTableEntry *pPrevAET;        /* ptr to previous AET     */
02164     EdgeTable ET;                    /* header node for ET      */
02165     EdgeTableEntry AET;              /* header node for AET     */
02166     EdgeTableEntry *pETEs;           /* EdgeTableEntries pool   */
02167     ScanLineListBlock SLLBlock;      /* header for scanlinelist */
02168     int fixWAET = false;
02169     POINTBLOCK FirstPtBlock, *curPtBlock; /* PtBlock buffers    */
02170     POINTBLOCK *tmpPtBlock;
02171     int numFullPtBlocks = 0;
02172 
02173     if (!(region = new QRegionPrivate))
02174         return 0;
02175 
02176     /* special case a rectangle */
02177     if (((Count == 4) ||
02178          ((Count == 5) && (Pts[4].x() == Pts[0].x()) && (Pts[4].y() == Pts[0].y())))
02179          && (((Pts[0].y() == Pts[1].y()) && (Pts[1].x() == Pts[2].x()) && (Pts[2].y() == Pts[3].y())
02180                && (Pts[3].x() == Pts[0].x())) || ((Pts[0].x() == Pts[1].x())
02181                && (Pts[1].y() == Pts[2].y()) && (Pts[2].x() == Pts[3].x())
02182                && (Pts[3].y() == Pts[0].y())))) {
02183         int x = qMin(Pts[0].x(), Pts[2].x());
02184         region->extents.setLeft(x);
02185         int y = qMin(Pts[0].y(), Pts[2].y());
02186         region->extents.setTop(y);
02187         region->extents.setWidth(qMax(Pts[0].x(), Pts[2].x()) - x);
02188         region->extents.setHeight(qMax(Pts[0].y(), Pts[2].y()) - y);
02189         if ((region->extents.left() <= region->extents.right()) &&
02190             (region->extents.top() <= region->extents.bottom())) {
02191             region->numRects = 1;
02192             region->rects.resize(1);
02193             region->rects[0] = region->extents;
02194 #ifdef QT_EXPERIMENTAL_REGIONS
02195             region->innerRect = region->extents;
02196             region->innerArea = region->innerRect.width() * region->innerRect.height();
02197 #endif
02198         }
02199         return region;
02200     }
02201 
02202     if (!(pETEs = static_cast<EdgeTableEntry *>(malloc(sizeof(EdgeTableEntry) * Count))))
02203         return 0;
02204 
02205     pts = FirstPtBlock.pts;
02206     CreateETandAET(Count, Pts, &ET, &AET, pETEs, &SLLBlock);
02207     pSLL = ET.scanlines.next;
02208     curPtBlock = &FirstPtBlock;
02209 
02210     if (rule == EvenOddRule) {
02211         /*
02212          *  for each scanline
02213          */
02214         for (y = ET.ymin; y < ET.ymax; ++y) {
02215             /*
02216              *  Add a new edge to the active edge table when we
02217              *  get to the next edge.
02218              */
02219             if (pSLL && y == pSLL->scanline) {
02220                 loadAET(&AET, pSLL->edgelist);
02221                 pSLL = pSLL->next;
02222             }
02223             pPrevAET = &AET;
02224             pAET = AET.next;
02225 
02226             /*
02227              *  for each active edge
02228              */
02229             while (pAET) {
02230                 pts->setX(pAET->bres.minor_axis);
02231                 pts->setY(y);
02232                 ++pts;
02233                 ++iPts;
02234 
02235                 /*
02236                  *  send out the buffer
02237                  */
02238                 if (iPts == NUMPTSTOBUFFER) {
02239                     tmpPtBlock = (POINTBLOCK *)malloc(sizeof(POINTBLOCK));
02240                     curPtBlock->next = tmpPtBlock;
02241                     curPtBlock = tmpPtBlock;
02242                     pts = curPtBlock->pts;
02243                     ++numFullPtBlocks;
02244                     iPts = 0;
02245                 }
02246                 EVALUATEEDGEEVENODD(pAET, pPrevAET, y)
02247             }
02248             InsertionSort(&AET);
02249         }
02250     } else {
02251         /*
02252          *  for each scanline
02253          */
02254         for (y = ET.ymin; y < ET.ymax; ++y) {
02255             /*
02256              *  Add a new edge to the active edge table when we
02257              *  get to the next edge.
02258              */
02259             if (pSLL && y == pSLL->scanline) {
02260                 loadAET(&AET, pSLL->edgelist);
02261                 computeWAET(&AET);
02262                 pSLL = pSLL->next;
02263             }
02264             pPrevAET = &AET;
02265             pAET = AET.next;
02266             pWETE = pAET;
02267 
02268             /*
02269              *  for each active edge
02270              */
02271             while (pAET) {
02272                 /*
02273                  *  add to the buffer only those edges that
02274                  *  are in the Winding active edge table.
02275                  */
02276                 if (pWETE == pAET) {
02277                     pts->setX(pAET->bres.minor_axis);
02278                     pts->setY(y);
02279                     ++pts;
02280                     ++iPts;
02281 
02282                     /*
02283                      *  send out the buffer
02284                      */
02285                     if (iPts == NUMPTSTOBUFFER) {
02286                         tmpPtBlock = static_cast<POINTBLOCK *>(malloc(sizeof(POINTBLOCK)));
02287                         curPtBlock->next = tmpPtBlock;
02288                         curPtBlock = tmpPtBlock;
02289                         pts = curPtBlock->pts;
02290                         ++numFullPtBlocks;
02291                         iPts = 0;
02292                     }
02293                     pWETE = pWETE->nextWETE;
02294                 }
02295                 EVALUATEEDGEWINDING(pAET, pPrevAET, y, fixWAET)
02296             }
02297 
02298             /*
02299              *  recompute the winding active edge table if
02300              *  we just resorted or have exited an edge.
02301              */
02302             if (InsertionSort(&AET) || fixWAET) {
02303                 computeWAET(&AET);
02304                 fixWAET = false;
02305             }
02306         }
02307     }
02308     FreeStorage(SLLBlock.next);
02309     PtsToRegion(numFullPtBlocks, iPts, &FirstPtBlock, region);
02310     for (curPtBlock = FirstPtBlock.next; --numFullPtBlocks >= 0;) {
02311         tmpPtBlock = curPtBlock->next;
02312         free(curPtBlock);
02313         curPtBlock = tmpPtBlock;
02314     }

Here is the call graph for this function:

static void PtsToRegion ( register int  numFullPtBlocks,
register int  iCurPtBlock,
POINTBLOCK FirstPtBlock,
QRegionPrivate reg 
) [static]

Definition at line 2075 of file qregion_unix.cpp.

References QRect::bottom(), QVector< T >::data(), QRegionPrivate::extents, i, QRect::left(), _POINTBLOCK::next, NUMPTSTOBUFFER, _POINTBLOCK::pts, QRegionPrivate::rects, QVector< T >::resize(), QRect::right(), QRect::setBottom(), QRect::setCoords(), QRect::setLeft(), QRect::setRight(), QRect::top(), QPoint::x(), QPoint::y(), and y.

Referenced by PolygonRegion().

02080 {
02081     register QRect *rects;
02082     register QPoint *pts;
02083     register POINTBLOCK *CurPtBlock;
02084     register int i;
02085     register QRect *extents;
02086     register int numRects;
02087 
02088     extents = &reg->extents;
02089     numRects = ((numFullPtBlocks * NUMPTSTOBUFFER) + iCurPtBlock) >> 1;
02090 
02091     reg->rects.resize(numRects);
02092 
02093     CurPtBlock = FirstPtBlock;
02094     rects = reg->rects.data() - 1;
02095     numRects = 0;
02096     extents->setLeft(INT_MAX);
02097     extents->setRight(INT_MIN);
02098 #ifdef QT_EXPERIMENTAL_REGIONS
02099     reg->innerArea = -1;
02100 #endif
02101 
02102     for (; numFullPtBlocks >= 0; --numFullPtBlocks) {
02103         /* the loop uses 2 points per iteration */
02104         i = NUMPTSTOBUFFER >> 1;
02105         if (!numFullPtBlocks)
02106             i = iCurPtBlock >> 1;
02107         if(i) {
02108             for (pts = CurPtBlock->pts; i--; pts += 2) {
02109                 if (pts->x() == pts[1].x())
02110                     continue;
02111                 if (numRects && pts->x() == rects->left() && pts->y() == rects->bottom() + 1
02112                     && pts[1].x() == rects->right()+1 && (numRects == 1 || rects[-1].top() != rects->top())
02113                                                           && (i && pts[2].y() > pts[1].y())) {
02114                         rects->setBottom(pts[1].y());
02115 #ifdef QT_EXPERIMENTAL_REGIONS
02116                         reg->updateInnerRect(*rects);
02117 #endif
02118                         continue;
02119                 }
02120                 ++numRects;
02121                 ++rects;
02122                 rects->setCoords(pts->x(), pts->y(), pts[1].x() - 1, pts[1].y());
02123                 if (rects->left() < extents->left())
02124                     extents->setLeft(rects->left());
02125                 if (rects->right() > extents->right())
02126                     extents->setRight(rects->right());
02127 #ifdef QT_EXPERIMENTAL_REGIONS
02128                 reg->updateInnerRect(*rects);
02129 #endif
02130             }
02131         }
02132         CurPtBlock = CurPtBlock->next;
02133     }
02134 
02135     if (numRects) {
02136         extents->setTop(reg->rects[0].top());
02137         extents->setBottom(rects->bottom());
02138     } else {
02139         extents->setCoords(0, 0, 0, 0);

Here is the call graph for this function:

QRegionPrivate* qt_bitmapToRegion ( const QBitmap bitmap  ) 

Definition at line 2317 of file qregion_unix.cpp.

02321 {
02322     QImage image = bitmap.toImage();
02323 
02324     QRegionPrivate *region = new QRegionPrivate;
02325     QRect xr;
02326 
02327 #define AddSpan \
02328         { \
02329             xr.setCoords(prev1, y, x-1, y); \
02330             UnionRectWithRegion(&xr, region, *region); \
02331         }
02332 
02333     const uchar zero = 0;
02334     bool little = image.format() == QImage::Format_MonoLSB;
02335 
02336     int x,
02337         y;
02338     for (y = 0; y < image.height(); ++y) {
02339         uchar *line = image.scanLine(y);
02340         int w = image.width();
02341         uchar all = zero;
02342         int prev1 = -1;
02343         for (x = 0; x < w;) {
02344             uchar byte = line[x / 8];
02345             if (x > w - 8 || byte!=all) {
02346                 if (little) {
02347                     for (int b = 8; b > 0 && x < w; --b) {
02348                         if (!(byte & 0x01) == !all) {
02349                             // More of the same
02350                         } else {
02351                             // A change.
02352                             if (all!=zero) {
02353                                 AddSpan
02354                                 all = zero;
02355                             } else {
02356                                 prev1 = x;
02357                                 all = ~zero;
02358                             }
02359                         }
02360                         byte >>= 1;
02361                         ++x;
02362                     }
02363                 } else {
02364                     for (int b = 8; b > 0 && x < w; --b) {
02365                         if (!(byte & 0x80) == !all) {
02366                             // More of the same
02367                         } else {
02368                             // A change.
02369                             if (all != zero) {
02370                                 AddSpan
02371                                 all = zero;
02372                             } else {
02373                                 prev1 = x;
02374                                 all = ~zero;
02375                             }
02376                         }
02377                         byte <<= 1;
02378                         ++x;
02379                     }
02380                 }
02381             } else {
02382                 x += 8;
02383             }
02384         }
02385         if (all != zero) {
02386             AddSpan
02387         }
02388     }
02389 #undef AddSpan

static bool RectInRegion ( register QRegionPrivate region,
int  rx,
int  ry,
uint  rwidth,
uint  rheight 
) [static]

Definition at line 1359 of file qregion_unix.cpp.

References QRect::bottom(), EXTENTCHECK, QRect::left(), RectangleIn, RectangleOut, RectanglePart, QRect::right(), and QRect::top().

01360 {
01361     register const QRect *pbox;
01362     register const QRect *pboxEnd;
01363     QRect rect(rx, ry, rwidth, rheight);
01364     register QRect *prect = &rect;
01365     int partIn, partOut;
01366 
01367     if (!region || region->numRects == 0 || !EXTENTCHECK(&region->extents, prect))
01368         return RectangleOut;
01369 
01370     partOut = false;
01371     partIn = false;
01372 
01373     /* can stop when both partOut and partIn are true, or we reach prect->y2 */
01374     for (pbox = region->rects.constData(), pboxEnd = pbox + region->numRects;
01375          pbox < pboxEnd; ++pbox) {
01376         if (pbox->bottom() < ry)
01377            continue;
01378 
01379         if (pbox->top() > ry) {
01380            partOut = true;
01381            if (partIn || pbox->top() > prect->bottom())
01382               break;
01383            ry = pbox->top();
01384         }
01385 
01386         if (pbox->right() < rx)
01387            continue;            /* not far enough over yet */
01388 
01389         if (pbox->left() > rx) {
01390            partOut = true;      /* missed part of rectangle to left */
01391            if (partIn)
01392               break;
01393         }
01394 
01395         if (pbox->left() <= prect->right()) {
01396             partIn = true;      /* definitely overlap */
01397             if (partOut)
01398                break;
01399         }
01400 
01401         if (pbox->right() >= prect->right()) {
01402            ry = pbox->bottom() + 1;     /* finished with this band */
01403            if (ry > prect->bottom())
01404               break;
01405            rx = prect->left();  /* reset x out to left again */
01406         } else {
01407             /*
01408              * Because boxes in a band are maximal width, if the first box
01409              * to overlap the rectangle doesn't completely cover it in that
01410              * band, the rectangle must be partially out, since some of it
01411              * will be uncovered in that band. partIn will have been set true
01412              * by now...
01413              */
01414             break;
01415         }
01416     }
01417     return partIn ? ((ry <= prect->bottom()) ? RectanglePart : RectangleIn) : RectangleOut;
01418 }

Here is the call graph for this function:

static void SubtractRegion ( QRegionPrivate regM,
QRegionPrivate regS,
register QRegionPrivate dest 
) [static]

Definition at line 1272 of file qregion_unix.cpp.

References EqualRegion(), EXTENTCHECK, QRegionPrivate::extents, isEmpty(), miRegionOp(), miSetExtents(), miSubtractNonO1(), and miSubtractO().

Referenced by XorRegion().

01274 {
01275    /* check for trivial reject */
01276     if (isEmpty(regM))
01277         return;
01278 
01279     if (isEmpty(regS) || !EXTENTCHECK(&regM->extents, &regS->extents)) {
01280         dest = *regM;
01281         return;
01282     }
01283 
01284 #ifdef QT_EXPERIMENTAL_REGIONS
01285     if (regS->contains(*regM)) {
01286         dest = QRegionPrivate();
01287         return;
01288     }
01289 
01290     if (EqualRegion(regM, regS)) {
01291         dest = QRegionPrivate();
01292         return;
01293     }
01294 #endif
01295 
01296     miRegionOp(dest, regM, regS, miSubtractO, miSubtractNonO1, 0);
01297 
01298     /*
01299      * Can't alter dest's extents before we call miRegionOp because
01300      * it might be one of the source regions and miRegionOp depends
01301      * on the extents of those regions being the unaltered. Besides, this
01302      * way there's no checking against rectangles that will be nuked
01303      * due to coalescing, so we have to examine fewer rectangles.
01304      */
01305     miSetExtents(dest);
01306 }

Here is the call graph for this function:

static void UnionRectWithRegion ( register const QRect rect,
const QRegionPrivate source,
QRegionPrivate dest 
) [static]

Definition at line 380 of file qregion_unix.cpp.

References QRegionPrivate::extents, QRegionPrivate::numRects, QRegionPrivate::rects, QVector< T >::resize(), and UnionRegion().

00382 {
00383     if (!rect->width() || !rect->height())
00384         return;
00385 
00386     QRegionPrivate region;
00387     region.rects.resize(1);
00388     region.numRects = 1;
00389     region.rects[0] = *rect;
00390     region.extents = *rect;
00391 #ifdef QT_EXPERIMENTAL_REGIONS
00392     region.innerRect = *rect;
00393     region.innerArea = rect->width() * rect->height();
00394 #endif
00395 
00396     UnionRegion(&region, source, dest);
00397     return;
00398 }

Here is the call graph for this function:

static void UnionRegion ( const QRegionPrivate reg1,
const QRegionPrivate reg2,
QRegionPrivate dest 
) [static]

Definition at line 1008 of file qregion_unix.cpp.

References QRect::bottom(), EqualRegion(), QRegionPrivate::extents, isEmpty(), QRect::left(), miRegionOp(), miUnionNonO(), miUnionO(), QRegionPrivate::numRects, qMax(), qMin(), QRect::right(), QRect::setCoords(), and QRect::top().

Referenced by UnionRectWithRegion(), and XorRegion().

01009 {
01010 #ifdef QT_EXPERIMENTAL_REGIONS
01011     /*
01012       Empty region
01013     */
01014     if (isEmpty(reg1)) {
01015         dest = *reg2;
01016         return;
01017     }
01018     if (isEmpty(reg2)) {
01019         dest = *reg1;
01020         return;
01021     }
01022 
01023     /*
01024       A region completely subsumes the other
01025     */
01026     if (reg1->contains(*reg2)) {
01027         dest = *reg1;
01028         return;
01029     }
01030     if (reg2->contains(*reg1)) {
01031         dest = *reg2;
01032         return;
01033     }
01034 
01035     /*
01036       Regions are equal.
01037     */
01038     if (EqualRegion(reg1, reg2)) {
01039         dest = *reg1;
01040         return;
01041     }
01042 
01043     /*
01044       Can append reg2 to reg1
01045     */
01046     if (reg1->canAppend(reg2)) {
01047         dest = *reg1;
01048         dest.append(reg2);
01049         return;
01050     }
01051 
01052     /*
01053       Can append reg1 to reg2
01054     */
01055     if (reg2->canAppend(reg1)) {
01056         dest = *reg2;
01057         dest.append(reg1);
01058         return;
01059     }
01060 #else
01061     /*
01062       Region 1 is empty or is equal to region 2.
01063     */
01064     if (reg1 == reg2 || isEmpty(reg1)) {
01065         if (!isEmpty(reg2))
01066             dest = *reg2;
01067         return;
01068     }
01069 
01070     /*
01071       Region 2 is empty (and region 1 isn't).
01072     */
01073     if (isEmpty(reg2)) {
01074         dest = *reg1;
01075         return;
01076     }
01077 
01078     /*
01079       Region 1 completely subsumes region 2.
01080      */
01081     if (reg1->numRects == 1 && reg1->extents.left() <= reg2->extents.left()
01082             && reg1->extents.top() <= reg2->extents.top()
01083             && reg1->extents.right() >= reg2->extents.right()
01084             && reg1->extents.bottom() >= reg2->extents.bottom()) {
01085         dest = *reg1;
01086         return;
01087     }
01088 
01089     /*
01090       Region 2 completely subsumes region 1.
01091      */
01092     if (reg2->numRects == 1 && reg2->extents.left() <= reg1->extents.left()
01093             && reg2->extents.top() <= reg1->extents.top()
01094             && reg2->extents.right() >= reg1->extents.right()
01095             && reg2->extents.bottom() >= reg1->extents.bottom()) {
01096         dest = *reg2;
01097         return;
01098     }
01099 #endif
01100 
01101 #ifdef QT_EXPERIMENTAL_REGIONS
01102     if (reg1->innerArea > reg2->innerArea) {
01103         dest.innerArea = reg1->innerArea;
01104         dest.innerRect = reg1->innerRect;
01105     } else {
01106         dest.innerArea = reg2->innerArea;
01107         dest.innerRect = reg2->innerRect;
01108     }
01109 #endif
01110     miRegionOp(dest, reg1, reg2, miUnionO, miUnionNonO, miUnionNonO);
01111 
01112     dest.extents.setCoords(qMin(reg1->extents.left(), reg2->extents.left()),
01113                            qMin(reg1->extents.top(), reg2->extents.top()),
01114                            qMax(reg1->extents.right(), reg2->extents.right()),
01115                            qMax(reg1->extents.bottom(), reg2->extents.bottom()));
01116 }

Here is the call graph for this function:

static void XorRegion ( QRegionPrivate sra,
QRegionPrivate srb,
QRegionPrivate dest 
) [static]

Definition at line 1308 of file qregion_unix.cpp.

References SubtractRegion(), and UnionRegion().

01309 {
01310     QRegionPrivate tra, trb;
01311 
01312     SubtractRegion(sra, srb, tra);
01313     SubtractRegion(srb, sra, trb);
01314     UnionRegion(&tra, &trb, dest);
01315 }

Here is the call graph for this function:


Generated on Thu Mar 15 13:37:27 2007 for Qt 4.2 User's Guide by  doxygen 1.5.1