summaryrefslogtreecommitdiffstats
path: root/src/gui/graphicsview
diff options
context:
space:
mode:
authorBjoern Erik Nilsen <bjorn.nilsen@nokia.com>2009-05-08 14:00:57 (GMT)
committerBjørn Erik Nilsen <bjorn.nilsen@nokia.com>2009-05-15 15:55:44 (GMT)
commit59cc08796bfb88bc0010006f365f1361462761aa (patch)
tree44eebedc40e44546a5788cfb3ac497f1bab7e7d6 /src/gui/graphicsview
parentb0095f7f8925cf571224d348124f08c56f7f46e9 (diff)
downloadQt-59cc08796bfb88bc0010006f365f1361462761aa.zip
Qt-59cc08796bfb88bc0010006f365f1361462761aa.tar.gz
Qt-59cc08796bfb88bc0010006f365f1361462761aa.tar.bz2
Graphics View Optimization: Use a simple style option by default.
QStyleOptionGraphicsItem extends QStyleOption with three values: 1) matrix, 2) levelOfDetail, 3) exposedRect, and they all involve expensive QTranform operations when calculated. We pass style option(s) to drawItems() and paint(), but the extended values are usually not in use. We can therefore gain quite some nice speedup by making them opt-in with the QGraphicsItem::ItemUsesExtendedStyleOption flag. Additionally, QStyleOptionGraphicsItem::levelOfDetail has been obsoleted, and a new function QStyleOptionGraphicsItem:: levelOfDetailFromTransform(const QTransform &) has been added. Me and Andreas don't consider this change to be too controversial even though it changes the behavior. Auto tests still pass. Reviewed-by: Andreas
Diffstat (limited to 'src/gui/graphicsview')
-rw-r--r--src/gui/graphicsview/qgraphicsitem.cpp67
-rw-r--r--src/gui/graphicsview/qgraphicsitem.h4
-rw-r--r--src/gui/graphicsview/qgraphicsitem_p.h13
-rw-r--r--src/gui/graphicsview/qgraphicsscene.cpp34
-rw-r--r--src/gui/graphicsview/qgraphicsview.cpp120
-rw-r--r--src/gui/graphicsview/qgraphicsview_p.h7
-rw-r--r--src/gui/graphicsview/qgraphicswidget_p.cpp1
7 files changed, 90 insertions, 156 deletions
diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp
index aa55908..ec08aaf 100644
--- a/src/gui/graphicsview/qgraphicsitem.cpp
+++ b/src/gui/graphicsview/qgraphicsitem.cpp
@@ -274,6 +274,15 @@
this flag, the child will be stacked behind it. This flag is useful for
drop shadow effects and for decoration objects that follow the parent
item's geometry without drawing on top of it.
+
+ \value ItemUsesExtendedStyleOption The item makes use of either
+ QStyleOptionGraphicsItem::exposedRect or QStyleOptionGraphicsItem::matrix.
+ By default, the exposedRect is initialized to the item's boundingRect and
+ the matrix is untransformed. Enable this flag for more fine-grained values.
+ Note that QStyleOptionGraphicsItem::levelOfDetail is unaffected by this flag
+ and is always initialized to 1.
+ Use QStyleOptionGraphicsItem::levelOfDetailFromTransform for a more
+ fine-grained value.
*/
/*!
@@ -914,6 +923,53 @@ void QGraphicsItemPrivate::childrenBoundingRectHelper(QTransform *x, QRectF *rec
}
}
+void QGraphicsItemPrivate::initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
+ const QRegion &exposedRegion, bool allItems) const
+{
+ Q_ASSERT(option);
+ Q_Q(const QGraphicsItem);
+
+ // Initialize standard QStyleOption values.
+ const QRectF brect = q->boundingRect();
+ option->state = QStyle::State_None;
+ option->rect = brect.toRect();
+ option->levelOfDetail = 1;
+ option->exposedRect = brect;
+ if (selected)
+ option->state |= QStyle::State_Selected;
+ if (enabled)
+ option->state |= QStyle::State_Enabled;
+ if (q->hasFocus())
+ option->state |= QStyle::State_HasFocus;
+ if (scene) {
+ if (scene->d_func()->hoverItems.contains(q_ptr))
+ option->state |= QStyle::State_MouseOver;
+ if (q == scene->mouseGrabberItem())
+ option->state |= QStyle::State_Sunken;
+ }
+
+ if (!(flags & QGraphicsItem::ItemUsesExtendedStyleOption))
+ return;
+
+ // Initialize QStyleOptionGraphicsItem specific values (matrix, exposedRect).
+
+ const QTransform itemToViewportTransform = q->deviceTransform(worldTransform);
+ option->matrix = itemToViewportTransform.toAffine(); //### discards perspective
+
+ if (!allItems) {
+ // Determine the item's exposed area
+ option->exposedRect = QRectF();
+ const QTransform reverseMap = itemToViewportTransform.inverted();
+ const QVector<QRect> exposedRects(exposedRegion.rects());
+ for (int i = 0; i < exposedRects.size(); ++i) {
+ option->exposedRect |= reverseMap.mapRect(exposedRects.at(i));
+ if (option->exposedRect.contains(brect))
+ break;
+ }
+ option->exposedRect &= brect;
+ }
+}
+
/*!
\internal
@@ -3671,7 +3727,7 @@ void QGraphicsItem::setBoundingRegionGranularity(qreal granularity)
All painting is done in local coordinates.
- \sa setCacheMode(), QPen::width(), {Item Coordinates}
+ \sa setCacheMode(), QPen::width(), {Item Coordinates}, ItemUsesExtendedStyleOption
*/
/*!
@@ -7635,9 +7691,7 @@ void QGraphicsPixmapItem::paint(QPainter *painter, const QStyleOptionGraphicsIte
painter->setRenderHint(QPainter::SmoothPixmapTransform,
(d->transformationMode == Qt::SmoothTransformation));
- QRectF exposed = option->exposedRect.adjusted(-1, -1, 1, 1);
- exposed &= QRectF(d->offset.x(), d->offset.y(), d->pixmap.width(), d->pixmap.height());
- painter->drawPixmap(exposed, d->pixmap, exposed.translated(-d->offset));
+ painter->drawPixmap(d->offset, d->pixmap);
if (option->state & QStyle::State_Selected)
qt_graphicsItem_highlightSelected(this, painter, option);
@@ -7803,6 +7857,7 @@ QGraphicsTextItem::QGraphicsTextItem(const QString &text, QGraphicsItem *parent
setPlainText(text);
setAcceptDrops(true);
setAcceptHoverEvents(true);
+ setFlags(ItemUsesExtendedStyleOption);
}
/*!
@@ -7822,6 +7877,7 @@ QGraphicsTextItem::QGraphicsTextItem(QGraphicsItem *parent
dd->qq = this;
setAcceptDrops(true);
setAcceptHoverEvents(true);
+ setFlag(ItemUsesExtendedStyleOption);
}
/*!
@@ -9167,6 +9223,9 @@ QDebug operator<<(QDebug debug, QGraphicsItem::GraphicsItemFlag flag)
case QGraphicsItem::ItemStacksBehindParent:
str = "ItemStacksBehindParent";
break;
+ case QGraphicsItem::ItemUsesExtendedStyleOption:
+ str = "ItemUsesExtendedStyleOption";
+ break;
}
debug << str;
return debug;
diff --git a/src/gui/graphicsview/qgraphicsitem.h b/src/gui/graphicsview/qgraphicsitem.h
index b98882d..0a0179e 100644
--- a/src/gui/graphicsview/qgraphicsitem.h
+++ b/src/gui/graphicsview/qgraphicsitem.h
@@ -94,7 +94,9 @@ public:
ItemIgnoresTransformations = 0x20,
ItemIgnoresParentOpacity = 0x40,
ItemDoesntPropagateOpacityToChildren = 0x80,
- ItemStacksBehindParent = 0x100
+ ItemStacksBehindParent = 0x100,
+ ItemUsesExtendedStyleOption = 0x200
+ // NB! Don't forget to increase the d_ptr->flags bit field by 1 when adding a new flag.
};
Q_DECLARE_FLAGS(GraphicsItemFlags, GraphicsItemFlag)
diff --git a/src/gui/graphicsview/qgraphicsitem_p.h b/src/gui/graphicsview/qgraphicsitem_p.h
index 2936cf1..82a48fb 100644
--- a/src/gui/graphicsview/qgraphicsitem_p.h
+++ b/src/gui/graphicsview/qgraphicsitem_p.h
@@ -132,7 +132,6 @@ public:
ancestorFlags(0),
cacheMode(0),
hasBoundingRegionGranularity(0),
- flags(0),
hasOpacity(0),
hasEffectiveOpacity(0),
isWidget(0),
@@ -142,6 +141,7 @@ public:
dirtyClipPath(1),
emptyClipPath(0),
inSetPosHelper(0),
+ flags(0),
allChildrenCombineOpacity(1),
globalStackingOrder(-1),
sceneTransformIndex(-1),
@@ -178,6 +178,8 @@ public:
void removeChild(QGraphicsItem *child);
void setParentItemHelper(QGraphicsItem *parent, bool deleting);
void childrenBoundingRectHelper(QTransform *x, QRectF *rect);
+ void initStyleOption(QStyleOptionGraphicsItem *option, const QTransform &worldTransform,
+ const QRegion &exposedRegion, bool allItems = false) const;
virtual void resolveFont(uint inheritedMask)
{
@@ -297,7 +299,7 @@ public:
int index;
int depth;
- // Packed 32 bytes
+ // Packed 32 bits
quint32 acceptedMouseButtons : 5;
quint32 visible : 1;
quint32 explicitlyHidden : 1;
@@ -314,9 +316,6 @@ public:
quint32 ancestorFlags : 3;
quint32 cacheMode : 2;
quint32 hasBoundingRegionGranularity : 1;
- quint32 flags : 9;
-
- // New 32 bytes
quint32 hasOpacity : 1;
quint32 hasEffectiveOpacity : 1;
quint32 isWidget : 1;
@@ -326,7 +325,11 @@ public:
quint32 dirtyClipPath : 1;
quint32 emptyClipPath : 1;
quint32 inSetPosHelper : 1;
+
+ // New 32 bits
+ quint32 flags : 10;
quint32 allChildrenCombineOpacity : 1;
+ quint32 padding : 21; // feel free to use
// Optional stacking order
int globalStackingOrder;
diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp
index c421f05..7318fa5 100644
--- a/src/gui/graphicsview/qgraphicsscene.cpp
+++ b/src/gui/graphicsview/qgraphicsscene.cpp
@@ -2247,8 +2247,6 @@ void QGraphicsScene::setSceneRect(const QRectF &rect)
void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRectF &source,
Qt::AspectRatioMode aspectRatioMode)
{
- Q_D(QGraphicsScene);
-
// Default source rect = scene rect
QRectF sourceRect = source;
if (sourceRect.isNull())
@@ -2305,36 +2303,8 @@ void QGraphicsScene::render(QPainter *painter, const QRectF &target, const QRect
// Generate the style options
QStyleOptionGraphicsItem *styleOptionArray = new QStyleOptionGraphicsItem[numItems];
- for (int i = 0; i < numItems; ++i) {
- QGraphicsItem *item = itemArray[i];
-
- QStyleOptionGraphicsItem option;
- option.state = QStyle::State_None;
- option.rect = item->boundingRect().toRect();
- if (item->isSelected())
- option.state |= QStyle::State_Selected;
- if (item->isEnabled())
- option.state |= QStyle::State_Enabled;
- if (item->hasFocus())
- option.state |= QStyle::State_HasFocus;
- if (d->hoverItems.contains(item))
- option.state |= QStyle::State_MouseOver;
- if (item == mouseGrabberItem())
- option.state |= QStyle::State_Sunken;
-
- // Calculate a simple level-of-detail metric.
- // ### almost identical code in QGraphicsView::paintEvent()
- // and QGraphicsView::render() - consider refactoring
- QTransform itemToDeviceTransform = item->deviceTransform(painterTransform);
-
- option.levelOfDetail = qSqrt(itemToDeviceTransform.map(v1).length() * itemToDeviceTransform.map(v2).length());
- option.matrix = itemToDeviceTransform.toAffine(); //### discards perspective
-
- option.exposedRect = item->boundingRect();
- option.exposedRect &= itemToDeviceTransform.inverted().mapRect(targetRect);
-
- styleOptionArray[i] = option;
- }
+ for (int i = 0; i < numItems; ++i)
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterTransform, targetRect.toRect());
// Render the scene.
drawBackground(painter, sourceRect);
diff --git a/src/gui/graphicsview/qgraphicsview.cpp b/src/gui/graphicsview/qgraphicsview.cpp
index 7181045..396618c 100644
--- a/src/gui/graphicsview/qgraphicsview.cpp
+++ b/src/gui/graphicsview/qgraphicsview.cpp
@@ -1127,69 +1127,6 @@ QList<QGraphicsItem *> QGraphicsViewPrivate::findItems(const QRegion &exposedReg
return itemsInArea(exposedPath, Qt::IntersectsItemBoundingRect, Qt::DescendingOrder);
}
-void QGraphicsViewPrivate::generateStyleOptions(const QList<QGraphicsItem *> &itemList,
- QGraphicsItem **itemArray,
- QStyleOptionGraphicsItem *styleOptionArray,
- const QTransform &worldTransform,
- bool allItems,
- const QRegion &exposedRegion) const
-{
- // Two unit vectors.
- QLineF v1(0, 0, 1, 0);
- QLineF v2(0, 0, 0, 1);
- QTransform itemToViewportTransform;
- QRectF brect;
- QTransform reverseMap;
-
- for (int i = 0; i < itemList.size(); ++i) {
- QGraphicsItem *item = itemArray[i] = itemList[i];
-
- QStyleOptionGraphicsItem &option = styleOptionArray[i];
- brect = item->boundingRect();
- option.state = QStyle::State_None;
- option.rect = brect.toRect();
- option.exposedRect = QRectF();
- if (item->d_ptr->selected)
- option.state |= QStyle::State_Selected;
- if (item->d_ptr->enabled)
- option.state |= QStyle::State_Enabled;
- if (item->hasFocus())
- option.state |= QStyle::State_HasFocus;
- if (scene->d_func()->hoverItems.contains(item))
- option.state |= QStyle::State_MouseOver;
- if (item == scene->mouseGrabberItem())
- option.state |= QStyle::State_Sunken;
-
- // Calculate a simple level-of-detail metric.
- // ### almost identical code in QGraphicsScene::render()
- // and QGraphicsView::render() - consider refactoring
- itemToViewportTransform = item->deviceTransform(worldTransform);
-
- if (itemToViewportTransform.type() <= QTransform::TxTranslate) {
- // Translation and rotation only? The LOD is 1.
- option.levelOfDetail = 1;
- } else {
- // LOD is the transformed area of a 1x1 rectangle.
- option.levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length());
- }
- option.matrix = itemToViewportTransform.toAffine(); //### discards perspective
-
- if (!allItems) {
- // Determine the item's exposed area
- reverseMap = itemToViewportTransform.inverted();
- foreach (const QRect &rect, exposedRegion.rects()) {
- option.exposedRect |= reverseMap.mapRect(QRectF(rect.adjusted(-1, -1, 1, 1)));
- if (option.exposedRect.contains(brect))
- break;
- }
- option.exposedRect &= brect;
- } else {
- // The whole item is exposed
- option.exposedRect = brect;
- }
- }
-}
-
/*!
Constructs a QGraphicsView. \a parent is passed to QWidget's constructor.
*/
@@ -2146,40 +2083,10 @@ void QGraphicsView::render(QPainter *painter, const QRectF &target, const QRect
.scale(xratio, yratio)
.translate(-sourceRect.left(), -sourceRect.top());
- // Two unit vectors.
- QLineF v1(0, 0, 1, 0);
- QLineF v2(0, 0, 0, 1);
-
// Generate the style options
QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(numItems);
- QStyleOptionGraphicsItem* option = styleOptionArray;
- for (int i = 0; i < numItems; ++i, ++option) {
- QGraphicsItem *item = itemArray[i];
-
- option->state = QStyle::State_None;
- option->rect = item->boundingRect().toRect();
- if (item->isSelected())
- option->state |= QStyle::State_Selected;
- if (item->isEnabled())
- option->state |= QStyle::State_Enabled;
- if (item->hasFocus())
- option->state |= QStyle::State_HasFocus;
- if (d->scene->d_func()->hoverItems.contains(item))
- option->state |= QStyle::State_MouseOver;
- if (item == d->scene->mouseGrabberItem())
- option->state |= QStyle::State_Sunken;
-
- // Calculate a simple level-of-detail metric.
- // ### almost identical code in QGraphicsScene::render()
- // and QGraphicsView::paintEvent() - consider refactoring
- QTransform itemToViewportTransform = item->deviceTransform(painterMatrix);
-
- option->levelOfDetail = qSqrt(itemToViewportTransform.map(v1).length() * itemToViewportTransform.map(v2).length());
- option->matrix = itemToViewportTransform.toAffine();
-
- option->exposedRect = item->boundingRect();
- option->exposedRect &= itemToViewportTransform.inverted().mapRect(targetRect);
- }
+ for (int i = 0; i < numItems; ++i)
+ itemArray[i]->d_ptr->initStyleOption(&styleOptionArray[i], painterMatrix, targetRect.toRect());
painter->save();
@@ -3538,15 +3445,17 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
int backgroundTime = stopWatch.elapsed() - exposedTime;
#endif
- // Generate the style options
- QGraphicsItem **itemArray = new QGraphicsItem *[itemList.size()];
- QStyleOptionGraphicsItem *styleOptionArray = d->allocStyleOptionsArray(itemList.size());
-
- d->generateStyleOptions(itemList, itemArray, styleOptionArray, viewTransform,
- allItems, exposedRegion);
-
- // Items
- drawItems(&painter, itemList.size(), itemArray, styleOptionArray);
+ 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
int itemsTime = stopWatch.elapsed() - exposedTime - backgroundTime;
@@ -3555,9 +3464,6 @@ void QGraphicsView::paintEvent(QPaintEvent *event)
// Foreground
drawForeground(&painter, exposedSceneRect);
- delete [] itemArray;
- d->freeStyleOptionsArray(styleOptionArray);
-
#ifdef QGRAPHICSVIEW_DEBUG
int foregroundTime = stopWatch.elapsed() - exposedTime - backgroundTime - itemsTime;
#endif
diff --git a/src/gui/graphicsview/qgraphicsview_p.h b/src/gui/graphicsview/qgraphicsview_p.h
index d573e8f..c18f85d 100644
--- a/src/gui/graphicsview/qgraphicsview_p.h
+++ b/src/gui/graphicsview/qgraphicsview_p.h
@@ -174,13 +174,6 @@ public:
bool updateSceneSlotReimplementedChecked;
QList<QGraphicsItem *> findItems(const QRegion &exposedRegion, bool *allItems) const;
-
- void generateStyleOptions(const QList<QGraphicsItem *> &itemList,
- QGraphicsItem **itemArray,
- QStyleOptionGraphicsItem *styleOptionArray,
- const QTransform &worldTransform,
- bool allItems,
- const QRegion &exposedRegion) const;
};
QT_END_NAMESPACE
diff --git a/src/gui/graphicsview/qgraphicswidget_p.cpp b/src/gui/graphicsview/qgraphicswidget_p.cpp
index 8ced47a..a435758 100644
--- a/src/gui/graphicsview/qgraphicswidget_p.cpp
+++ b/src/gui/graphicsview/qgraphicswidget_p.cpp
@@ -76,6 +76,7 @@ void QGraphicsWidgetPrivate::init(QGraphicsItem *parentItem, Qt::WindowFlags wFl
resolveLayoutDirection();
q->unsetWindowFrameMargins();
+ q->setFlag(QGraphicsItem::ItemUsesExtendedStyleOption);
}
qreal QGraphicsWidgetPrivate::titleBarHeight(const QStyleOptionTitleBar &options) const
{