summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/gui/painting/qpainter.cpp55
-rw-r--r--src/gui/painting/qpainter.h2
-rw-r--r--tests/auto/qpainter/tst_qpainter.cpp37
3 files changed, 94 insertions, 0 deletions
diff --git a/src/gui/painting/qpainter.cpp b/src/gui/painting/qpainter.cpp
index f24eafd..c4de7f0 100644
--- a/src/gui/painting/qpainter.cpp
+++ b/src/gui/painting/qpainter.cpp
@@ -2702,6 +2702,61 @@ QPainterPath QPainter::clipPath() const
}
/*!
+ Returns the bounding rectangle of the current clip if there is a clip;
+ otherwise returns an empty rectangle. Note that the clip region is
+ given in logical coordinates.
+
+ The bounding rectangle is not guaranteed to be tight.
+
+ \sa setClipRect(), setClipPath(), setClipRegion()
+
+ \since 4.8
+ */
+
+QRectF QPainter::clipBoundingRect() const
+{
+ Q_D(const QPainter);
+
+ if (!d->engine) {
+ qWarning("QPainter::clipBoundingRect: Painter not active");
+ return QRectF();
+ }
+
+ // Accumulate the bounding box in device space. This is not 100%
+ // precise, but it fits within the guarantee and it is resonably
+ // fast.
+ QRectF bounds;
+ for (int i=0; i<d->state->clipInfo.size(); ++i) {
+ QRectF r;
+ const QPainterClipInfo &info = d->state->clipInfo.at(i);
+
+ if (info.clipType == QPainterClipInfo::RectClip)
+ r = info.rect;
+ else if (info.clipType == QPainterClipInfo::RegionClip)
+ r = info.region.boundingRect();
+ else
+ r = info.path.boundingRect();
+
+ r = info.matrix.mapRect(r);
+
+ if (i == 0)
+ bounds = r;
+ else if (info.operation == Qt::IntersectClip)
+ bounds &= r;
+ else if (info.operation == Qt::UniteClip)
+ bounds |= r;
+ }
+
+
+ // Map the rectangle back into logical space using the inverse
+ // matrix.
+ if (!d->txinv)
+ const_cast<QPainter *>(this)->d_ptr->updateInvMatrix();
+
+ return d->invMatrix.mapRect(bounds);
+}
+
+/*!
\fn void QPainter::setClipRect(const QRectF &rectangle, Qt::ClipOperation operation)
Enables clipping, and sets the clip region to the given \a
diff --git a/src/gui/painting/qpainter.h b/src/gui/painting/qpainter.h
index 85751a9..96305e3 100644
--- a/src/gui/painting/qpainter.h
+++ b/src/gui/painting/qpainter.h
@@ -222,6 +222,8 @@ public:
void setClipping(bool enable);
bool hasClipping() const;
+ QRectF clipBoundingRect() const;
+
void save();
void restore();
diff --git a/tests/auto/qpainter/tst_qpainter.cpp b/tests/auto/qpainter/tst_qpainter.cpp
index f358681..9ed212f 100644
--- a/tests/auto/qpainter/tst_qpainter.cpp
+++ b/tests/auto/qpainter/tst_qpainter.cpp
@@ -168,6 +168,8 @@ private slots:
void clippedText();
+ void clipBoundingRect();
+
void setOpacity_data();
void setOpacity();
@@ -4522,6 +4524,41 @@ void tst_QPainter::QTBUG5939_attachPainterPrivate()
QCOMPARE(widget->deviceTransform, proxy->deviceTransform);
}
+void tst_QPainter::clipBoundingRect()
+{
+ QPixmap pix(500, 500);
+
+ QPainter p(&pix);
+
+ // Test a basic rectangle
+ p.setClipRect(100, 100, 200, 100);
+ QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
+ p.setClipRect(120, 120, 20, 20, Qt::IntersectClip);
+ QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+
+ // Test a basic path + region
+ QPainterPath path;
+ path.addRect(100, 100, 200, 100);
+ p.setClipPath(path);
+ QVERIFY(p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(50, 50, 300, 200)));
+ p.setClipRegion(QRegion(120, 120, 20, 20), Qt::IntersectClip);
+ QVERIFY(p.clipBoundingRect().contains(QRect(120, 120, 20, 20)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(100, 100, 200, 100)));
+
+ p.setClipRect(0, 0, 500, 500);
+ p.translate(250, 250);
+ for (int i=0; i<360; ++i) {
+ p.rotate(1);
+ p.setClipRect(-100, -100, 200, 200, Qt::IntersectClip);
+ }
+ QVERIFY(p.clipBoundingRect().contains(QRectF(-100, -100, 200, 200)));
+ QVERIFY(!p.clipBoundingRect().contains(QRectF(-250, -250, 500, 500)));
+
+}
+
QTEST_MAIN(tst_QPainter)
#include "tst_qpainter.moc"