summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-05-25 09:59:10 (GMT)
committerAndreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com>2009-06-09 07:20:25 (GMT)
commitb5c401b9aa3481886ad9e2d7816680c97839004e (patch)
tree476d42d12be47d20d8763a0cfc8365fdb781e758 /src
parentcea87b08520888feff2f10d1bbf71bc8c2f1d780 (diff)
downloadQt-b5c401b9aa3481886ad9e2d7816680c97839004e.zip
Qt-b5c401b9aa3481886ad9e2d7816680c97839004e.tar.gz
Qt-b5c401b9aa3481886ad9e2d7816680c97839004e.tar.bz2
Add recursive drawing method to QGraphicsScene. For now it's opt-in, but
the important thing is by effectively implementing Simple Canvas' approach to drawing, we're in theory (and in practise measured on the desktop) as fast as Simple Canvas when rendering.
Diffstat (limited to 'src')
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp82
-rw-r--r--src/gui/graphicsview/qgraphicsscene_p.h3
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp34
-rw-r--r--src/gui/graphicsview/qgraphicsview.h3
4 files changed, 107 insertions, 15 deletions
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index 49c2329..362d66d 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -1870,6 +1870,11 @@ inline bool qt_closestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item
return z1 != z2 ? z1 > z2 : d1->siblingIndex > d2->siblingIndex;
}
+static inline bool qt_notclosestLeaf(const QGraphicsItem *item1, const QGraphicsItem *item2)
+{
+ return qt_closestLeaf(item2, item1);
+}
+
/*!
\internal
@@ -5013,6 +5018,83 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte
}
}
+void QGraphicsScenePrivate::drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform,
+ const QRegion &exposedRegion, QWidget *widget)
+{
+ if (item && (!item->isVisible() || qFuzzyIsNull(item->opacity())))
+ return;
+
+ painter->save();
+
+ // Set transform
+ if (item) {
+ if (item->d_ptr->itemIsUntransformable()) {
+ painter->setWorldTransform(item->deviceTransform(viewTransform), false);
+ } else {
+ const QPointF &pos = item->d_ptr->pos;
+ bool posNull = pos.isNull();
+ if (!posNull || item->d_ptr->hasTransform) {
+ if (item->d_ptr->hasTransform) {
+ QTransform x = item->transform();
+ if (!posNull)
+ x *= QTransform::fromTranslate(pos.x(), pos.y());
+ painter->setWorldTransform(x, true);
+ } else {
+ painter->setWorldTransform(QTransform::fromTranslate(pos.x(), pos.y()), true);
+ }
+ }
+ }
+ }
+
+ // Setup recursive clipping.
+ if (item && (item->flags() & QGraphicsItem::ItemClipsChildrenToShape))
+ painter->setClipPath(item->shape(), Qt::IntersectClip);
+
+#if 0
+ const QList<QGraphicsItem *> &children = item ? item->d_ptr->children : topLevelItems;
+#else
+ // ### if we ensure all children are sorted by Z by default, we don't have
+ // to sort this list for each paint.
+ QList<QGraphicsItem *> children = item ? item->d_ptr->children : topLevelItems;
+ qSort(children.begin(), children.end(), qt_notclosestLeaf);
+#endif
+
+ // Draw children behind
+ int i;
+ for (i = 0; i < children.size(); ++i) {
+ QGraphicsItem *child = children.at(i);
+ if (!(child->flags() & QGraphicsItem::ItemStacksBehindParent))
+ break;
+ drawSubtreeRecursive(child, painter, viewTransform, exposedRegion, widget);
+ }
+
+ // Draw item
+ if (item) {
+ QRect itemViewRect = painter->worldTransform().mapRect(item->boundingRect()).toRect().adjusted(-1, -1, 1, 1);
+ if (itemViewRect.intersects(exposedRegion.boundingRect())) {
+ QStyleOptionGraphicsItem option;
+ item->d_ptr->initStyleOption(&option, painter->worldTransform(), exposedRegion);
+
+ bool clipsToShape = (item->flags() & QGraphicsItem::ItemClipsToShape);
+ if (clipsToShape) {
+ painter->save();
+ painter->setClipPath(item->shape(), Qt::IntersectClip);
+ }
+
+ drawItemHelper(item, painter, &option, widget, false);
+
+ if (clipsToShape)
+ painter->restore();
+ }
+ }
+
+ // Draw children in front
+ for (; i < children.size(); ++i)
+ drawSubtreeRecursive(children.at(i), painter, viewTransform, exposedRegion, widget);
+
+ painter->restore();
+}
+
/*!
Paints the given \a items using the provided \a painter, after the
background has been drawn, and before the foreground has been
diff --git a/src/gui/graphicsview/qgraphicsscene_p.h b/src/gui/graphicsview/qgraphicsscene_p.h
index 9ace725..369b0ef 100644
--- a/src/gui/graphicsview/qgraphicsscene_p.h
+++ b/src/gui/graphicsview/qgraphicsscene_p.h
@@ -253,6 +253,9 @@ public:
const QStyleOptionGraphicsItem *option, QWidget *widget,
bool painterStateProtection);
+ void drawSubtreeRecursive(QGraphicsItem *item, QPainter *painter, const QTransform &viewTransform,
+ const QRegion &exposedRegion, QWidget *widget);
+
QStyle *style;
QFont font;
void setFont_helper(const QFont &font);
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 10b837a..2459c49 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -3387,10 +3387,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
bool allItems = false;
QList<QGraphicsItem *> itemList = d->findItems(exposedRegion, &allItems);
-#ifdef QGRAPHICSVIEW_DEBUG
- int exposedTime = stopWatch.elapsed();
-#endif
-
if ((d->cacheMode & CacheBackground)
#ifdef Q_WS_X11
&& X11->use_xrender
@@ -3436,16 +3432,26 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
int backgroundTime = stopWatch.elapsed() - exposedTime;
#endif
- if (!itemList.isEmpty()) {
- // Generate the style options.
- const int numItems = itemList.size();
- QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
- QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
- for (int i = 0; i < numItems; ++i)
- itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, exposedRegion, allItems);
- // Draw the items.
- drawItems(&painter, numItems, itemArray, styleOptionArray);
- d->freeStyleOptionsArray(styleOptionArray);
+ const char *directEnv = getenv("QGRAPHICSVIEW_DIRECT");
+ bool overrideDirectPaint = directEnv && atoi(directEnv) != 0;
+ if (overrideDirectPaint || (d->optimizationFlags & BypassDrawItems)) {
+ d->scene->d_func()->drawSubtreeRecursive(0, &painter, viewTransform, exposedRegion, viewport());
+ } else {
+ // Find all exposed items
+ bool allItems = false;
+ QList<QGraphicsItem *> itemList = d->findItems(exposedRegion, &allItems);
+
+ if (!itemList.isEmpty()) {
+ // Generate the style options.
+ const int numItems = itemList.size();
+ QGraphicsItem **itemArray = &itemList[0]; // Relies on QList internals, but is perfectly valid.
+ QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
+ for (int i = 0; i < numItems; ++i)
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], viewTransform, exposedRegion, allItems);
+ // Draw the items.
+ drawItems(&painter, numItems, itemArray, styleOptionArray);
+ d->freeStyleOptionsArray(styleOptionArray);
+ }
}
#ifdef QGRAPHICSVIEW_DEBUG
diff --git a/src/gui/graphicsview/qgraphicsview.h b/src/gui/graphicsview/qgraphicsview.h
index c3ea6e5..7692e16 100644
--- a/src/gui/graphicsview/qgraphicsview.h
+++ b/src/gui/graphicsview/qgraphicsview.h
@@ -112,7 +112,8 @@ public:
enum OptimizationFlag {
DontClipPainter = 0x1, // obsolete
DontSavePainterState = 0x2,
- DontAdjustForAntialiasing = 0x4
+ DontAdjustForAntialiasing = 0x4,
+ BypassDrawItems = 0x8
};
Q_DECLARE_FLAGS(OptimizationFlags, OptimizationFlag)