#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 ®ion, 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 QRegionPrivate * | PolygonRegion (const QPoint *Pts, int Count, int rule) |
QRegionPrivate * | qt_bitmapToRegion (const QBitmap &bitmap) |
#define AddSpan |
Value:
{ \ xr.setCoords(prev1, y, x-1, y); \ UnionRectWithRegion(&xr, region, *region); \ }
#define BRESINCRPGON | ( | d, | |||
minval, | |||||
m, | |||||
m1, | |||||
incr1, | |||||
incr2 | ) |
#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, | |||||
y | ) |
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 |
#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 | ( | r | ) |
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 |
#define RectangleIn 1 |
#define RectangleOut 0 |
#define RectanglePart 2 |
#define SLLSPERBLOCK 25 |
Definition at line 1656 of file qregion_unix.cpp.
Referenced by InsertEdgeInET(), and miInsertEdgeInET().
#define SMALL_COORDINATE -LARGE_COORDINATE |
#define WindingRule 1 |
Definition at line 194 of file qregion_unix.cpp.
Referenced by QX11PaintEnginePrivate::fillPolygon_dev().
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 |
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 = ®->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 = ▭ 01365 int partIn, partOut; 01366 01367 if (!region || region->numRects == 0 || !EXTENTCHECK(®ion->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(®M->extents, ®S->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(®ion, 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: