diff options
author | Andreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com> | 2009-05-25 09:59:10 (GMT) |
---|---|---|
committer | Andreas Aardal Hanssen <andreas.aardal.hanssen@nokia.com> | 2009-06-09 07:20:25 (GMT) |
commit | b5c401b9aa3481886ad9e2d7816680c97839004e (patch) | |
tree | 476d42d12be47d20d8763a0cfc8365fdb781e758 /src | |
parent | cea87b08520888feff2f10d1bbf71bc8c2f1d780 (diff) | |
download | Qt-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.cpp | 82 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsscene_p.h | 3 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview.cpp | 34 | ||||
-rw-r--r-- | src/gui/graphicsview/qgraphicsview.h | 3 |
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) |