From 80e114ad0b7974894858a17153d6f54546835066 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Bj=C3=B8rn=20Erik=20Nilsen?= <bjorn.nilsen@nokia.com>
Date: Wed, 3 Feb 2010 11:17:19 +0100
Subject: QGraphicsScene: Use QPainter::setClipRect instead of setClipPath if
 possible.

Using QPainter::setClipPath results in complex (and slow) alphamasking
so this must be avoided if possible.

Task-number: QTBUG-7790
Reviewed-by: samuel
---
 src/gui/graphicsview/qgraphicsscene.cpp | 18 +++++++++++++++---
 src/gui/painting/qpathclipper.cpp       |  4 +---
 src/gui/painting/qpathclipper_p.h       |  2 ++
 3 files changed, 18 insertions(+), 6 deletions(-)

diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 842d368..4bfe9ad 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -251,6 +251,7 @@
 #endif
 #include <private/qgraphicseffect_p.h>
 #include <private/qgesturemanager_p.h>
+#include <private/qpathclipper_p.h>
 
 // #define GESTURE_DEBUG
 #ifndef GESTURE_DEBUG
@@ -4765,7 +4766,12 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
                 painter->setWorldTransform(*transformPtr * *effectTransform);
             else
                 painter->setWorldTransform(*transformPtr);
-            painter->setClipPath(item->shape(), Qt::IntersectClip);
+            QRectF clipRect;
+            const QPainterPath clipPath(item->shape());
+            if (QPathClipper::pathToRect(clipPath, &clipRect))
+                painter->setClipRect(clipRect, Qt::IntersectClip);
+            else
+                painter->setClipPath(clipPath, Qt::IntersectClip);
         }
 
         // Draw children behind
@@ -4801,8 +4807,14 @@ void QGraphicsScenePrivate::draw(QGraphicsItem *item, QPainter *painter, const Q
                 painter->setWorldTransform(*transformPtr);
         }
 
-        if (itemClipsToShape)
-            painter->setClipPath(item->shape(), Qt::IntersectClip);
+        if (itemClipsToShape) {
+            QRectF clipRect;
+            const QPainterPath clipPath(item->shape());
+            if (QPathClipper::pathToRect(clipPath, &clipRect))
+                painter->setClipRect(clipRect, Qt::IntersectClip);
+            else
+                painter->setClipPath(clipPath, Qt::IntersectClip);
+        }
         painter->setOpacity(opacity);
 
         if (!item->d_ptr->cacheMode && !item->d_ptr->isWidget)
diff --git a/src/gui/painting/qpathclipper.cpp b/src/gui/painting/qpathclipper.cpp
index 7997e77..5702ede 100644
--- a/src/gui/painting/qpathclipper.cpp
+++ b/src/gui/painting/qpathclipper.cpp
@@ -90,8 +90,6 @@ static QPointF normalize(const QPointF &p)
     return p / qSqrt(p.x() * p.x() + p.y() * p.y());
 }
 
-static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
-
 struct QIntersection
 {
     qreal alphaA;
@@ -1660,7 +1658,7 @@ static bool fuzzyCompare(qreal a, qreal b)
     return qFuzzyCompare(a, b);
 }
 
-static bool pathToRect(const QPainterPath &path, QRectF *rect)
+bool QPathClipper::pathToRect(const QPainterPath &path, QRectF *rect)
 {
     if (path.elementCount() != 5)
         return false;
diff --git a/src/gui/painting/qpathclipper_p.h b/src/gui/painting/qpathclipper_p.h
index 0d2c049..b900862 100644
--- a/src/gui/painting/qpathclipper_p.h
+++ b/src/gui/painting/qpathclipper_p.h
@@ -86,6 +86,8 @@ public:
     bool intersect();
     bool contains();
 
+    static bool pathToRect(const QPainterPath &path, QRectF *rect = 0);
+
 private:
     Q_DISABLE_COPY(QPathClipper)
 
-- 
cgit v0.12