From 32767aa5699937a3737b9515f4f82acc04ccdfcd Mon Sep 17 00:00:00 2001 From: Bjoern Erik Nilsen Date: Fri, 3 Apr 2009 11:47:59 +0200 Subject: Fixes: Optimize the way we adjust rectangles. RevBy: Olivier AutoTest: Still pass --- src/gui/graphicsview/qgraphicsitem.cpp | 39 ++++++++--------- src/gui/graphicsview/qgraphicsscene.cpp | 76 +++++++++++++++++++++------------ 2 files changed, 68 insertions(+), 47 deletions(-) diff --git a/src/gui/graphicsview/qgraphicsitem.cpp b/src/gui/graphicsview/qgraphicsitem.cpp index 11a03b6..8478561 100644 --- a/src/gui/graphicsview/qgraphicsitem.cpp +++ b/src/gui/graphicsview/qgraphicsitem.cpp @@ -528,25 +528,22 @@ QT_BEGIN_NAMESPACE // QRectF::intersects() returns false always if either the source or target // rectangle's width or height are 0. This works around that problem. -static QRectF _q_adjustedRect(const QRectF &rect) -{ - static const qreal p = (qreal)0.00001; - QRectF r = rect; - if (!r.width()) - r.adjust(-p, 0, p, 0); - if (!r.height()) - r.adjust(0, -p, 0, p); - return r; +static inline void _q_adjustRect(QRectF *rect) +{ + Q_ASSERT(rect); + if (!rect->width()) + rect->adjust(-0.00001, 0, 0.00001, 0); + if (!rect->height()) + rect->adjust(0, -0.00001, 0, 0.00001); } -static QRect _q_adjustedRect(const QRect &rect) +static inline void _q_adjustRect(QRect *rect) { - QRect r = rect; - if (!r.width()) - r.adjust(0, 0, 1, 0); - if (!r.height()) - r.adjust(0, 0, 0, 1); - return r; + Q_ASSERT(rect); + if (!rect->width()) + rect->adjust(0, 0, 1, 0); + if (!rect->height()) + rect->adjust(0, 0, 0, 1); } /* @@ -3305,8 +3302,10 @@ bool QGraphicsItem::collidesWithPath(const QPainterPath &path, Qt::ItemSelection return false; } - const QRectF rectA = _q_adjustedRect(boundingRect()); - const QRectF rectB = _q_adjustedRect(path.controlPointRect()); + QRectF rectA(boundingRect()); + _q_adjustRect(&rectA); + QRectF rectB(path.controlPointRect()); + _q_adjustRect(&rectB); if (!rectA.intersects(rectB)) { // This we can determine efficiently. If the two rects neither // intersect nor contain eachother, then the two items do not collide. @@ -3489,7 +3488,9 @@ QRegion QGraphicsItem::boundingRegion(const QTransform &itemToDeviceTransform) c // into the bitmap, converts the result to a QRegion and scales the region // back to device space with inverse granularity. qreal granularity = boundingRegionGranularity(); - QRect deviceRect = _q_adjustedRect(itemToDeviceTransform.mapRect(boundingRect()).toRect()); + QRectF adjustedMappedBoundingRect(itemToDeviceTransform.mapRect(boundingRect())); + _q_adjustRect(&adjustedMappedBoundingRect); + QRect deviceRect = adjustedMappedBoundingRect.toRect(); if (granularity == 0.0) return QRegion(deviceRect); diff --git a/src/gui/graphicsview/qgraphicsscene.cpp b/src/gui/graphicsview/qgraphicsscene.cpp index bcc329e..a5fec69 100644 --- a/src/gui/graphicsview/qgraphicsscene.cpp +++ b/src/gui/graphicsview/qgraphicsscene.cpp @@ -292,15 +292,21 @@ static inline bool QRectF_intersects(const QRectF &s, const QRectF &r) // QRectF::intersects() returns false always if either the source or target // rectangle's width or height are 0. This works around that problem. -static QRectF _q_adjustedRect(const QRectF &rect) +static inline void _q_adjustRect(QRectF *rect) { - static const qreal p = (qreal)0.00001; - QRectF r = rect; - if (!r.width()) - r.adjust(-p, 0, p, 0); - if (!r.height()) - r.adjust(0, -p, 0, p); - return r; + Q_ASSERT(rect); + if (!rect->width()) + rect->adjust(-0.00001, 0, 0.00001, 0); + if (!rect->height()) + rect->adjust(0, -0.00001, 0, 0.00001); +} + +static inline QRectF adjustedItemBoundingRect(const QGraphicsItem *item) +{ + Q_ASSERT(item); + QRectF boundingRect(item->boundingRect()); + _q_adjustRect(&boundingRect); + return boundingRect; } static void _q_hoverFromMouseEvent(QGraphicsSceneHoverEvent *hover, const QGraphicsSceneMouseEvent *mouseEvent) @@ -1374,7 +1380,7 @@ QList QGraphicsScenePrivate::items_helper(const QPointF &pos) c // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); // Rect intersects/contains item's shape if (QRectF_intersects(adjustedRect, x.mapRect(br))) { bool ok; @@ -1410,7 +1416,8 @@ QList QGraphicsScenePrivate::items_helper(const QRectF &rect, // The index returns a rough estimate of what items are inside the rect. // Refine it by iterating through all returned items. - QRectF adjustedRect = _q_adjustedRect(rect); + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); foreach (QGraphicsItem *item, estimateItemsInRect(adjustedRect)) { // Find the item's scene transform in a clever way. QTransform x = item->sceneTransform(); @@ -1419,7 +1426,7 @@ QList QGraphicsScenePrivate::items_helper(const QRectF &rect, // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Rect intersects/contains item's bounding rect QRectF mbr = x.mapRect(br); @@ -1471,7 +1478,8 @@ QList QGraphicsScenePrivate::items_helper(const QPolygonF &poly { QList items; - QRectF polyRect = _q_adjustedRect(polygon.boundingRect()); + QRectF polyRect(polygon.boundingRect()); + _q_adjustRect(&polyRect); QPainterPath path; // The index returns a rough estimate of what items are inside the rect. @@ -1484,7 +1492,7 @@ QList QGraphicsScenePrivate::items_helper(const QPolygonF &poly // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Polygon contains/intersects item's bounding rect if (path == QPainterPath()) @@ -1529,7 +1537,8 @@ QList QGraphicsScenePrivate::items_helper(const QPainterPath &p Qt::SortOrder order) const { QList items; - const QRectF pathRect = _q_adjustedRect(path.controlPointRect()); + QRectF pathRect(path.controlPointRect()); + _q_adjustRect(&pathRect); // The index returns a rough estimate of what items are inside the rect. // Refine it by iterating through all returned items. @@ -1541,7 +1550,7 @@ QList QGraphicsScenePrivate::items_helper(const QPainterPath &p // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Path contains/intersects item's bounding rect if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(x.mapRect(br))) @@ -1620,7 +1629,9 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); if (parentClip && parent->d_ptr->isClippedAway()) return; - QRectF r = !parentClip ? _q_adjustedRect(rect) : _q_adjustedRect(rect).intersected(_q_adjustedRect(parent->boundingRect())); + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); + QRectF r = !parentClip ? adjustedRect : adjustedRect.intersected(adjustedItemBoundingRect(parent)); if (r.isEmpty()) return; @@ -1640,7 +1651,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); QRectF mbr = item->mapRectToParent(br); if (mode >= Qt::ContainsItemBoundingRect) { // Rect intersects/contains item's bounding rect @@ -1684,8 +1695,9 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); if (parentClip && parent->d_ptr->isClippedAway()) return; - QRectF polyRect = _q_adjustedRect(polygon.boundingRect()); - QRectF r = !parentClip ? polyRect : polyRect.intersected(_q_adjustedRect(parent->boundingRect())); + QRectF polyRect(polygon.boundingRect()); + _q_adjustRect(&polyRect); + QRectF r = !parentClip ? polyRect : polyRect.intersected(adjustedItemBoundingRect(parent)); if (r.isEmpty()) return; @@ -1705,7 +1717,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Polygon contains/intersects item's bounding rect if (path == QPainterPath()) @@ -1743,8 +1755,9 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, bool parentClip = (parent->flags() & QGraphicsItem::ItemClipsChildrenToShape); if (parentClip && parent->d_ptr->isClippedAway()) return; - QRectF pathRect = _q_adjustedRect(path.boundingRect()); - QRectF r = !parentClip ? pathRect : pathRect.intersected(_q_adjustedRect(parent->boundingRect())); + QRectF pathRect(path.boundingRect()); + _q_adjustRect(&pathRect); + QRectF r = !parentClip ? pathRect : pathRect.intersected(adjustedItemBoundingRect(parent)); if (r.isEmpty()) return; @@ -1763,7 +1776,7 @@ void QGraphicsScenePrivate::childItems_helper(QList *items, // ### _q_adjustedRect is only needed because QRectF::intersects, // QRectF::contains and QTransform::map() and friends don't work with // flat rectangles. - QRectF br = _q_adjustedRect(item->boundingRect()); + const QRectF br(adjustedItemBoundingRect(item)); if (mode >= Qt::ContainsItemBoundingRect) { // Polygon contains/intersects item's bounding rect if ((mode == Qt::IntersectsItemBoundingRect && path.intersects(item->mapRectToParent(br))) @@ -4690,7 +4703,9 @@ void QGraphicsScenePrivate::drawItemHelper(QGraphicsItem *item, QPainter *painte // Item's (local) bounding rect QRectF brect = item->boundingRect(); - if (_q_adjustedRect(brect).isEmpty()) + QRectF adjustedBrect(brect); + _q_adjustRect(&adjustedBrect); + if (adjustedBrect.isEmpty()) return; // Fetch the off-screen transparent buffer and exposed area info. @@ -5232,9 +5247,12 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect) update(item->sceneBoundingRect()); } else { // ### Remove _q_adjustedRects(). - QRectF boundingRect = _q_adjustedRect(item->boundingRect()); - if (!rect.isNull()) - boundingRect &= _q_adjustedRect(rect); + QRectF boundingRect(adjustedItemBoundingRect(item)); + if (!rect.isNull()) { + QRectF adjustedRect(rect); + _q_adjustRect(&adjustedRect); + boundingRect &= adjustedRect; + } // Update each view directly. for (int i = 0; i < d->views.size(); ++i) @@ -5264,7 +5282,9 @@ void QGraphicsScene::itemUpdated(QGraphicsItem *item, const QRectF &rect) // defined scene rect. if (!d->hasSceneRect) { QRectF oldGrowingItemsBoundingRect = d->growingItemsBoundingRect; - d->growingItemsBoundingRect |= _q_adjustedRect(item->sceneBoundingRect()); + QRectF adjustedItemSceneBoundingRect(item->sceneBoundingRect()); + _q_adjustRect(&adjustedItemSceneBoundingRect); + d->growingItemsBoundingRect |= adjustedItemSceneBoundingRect; if (d->growingItemsBoundingRect != oldGrowingItemsBoundingRect) emit sceneRectChanged(d->growingItemsBoundingRect); } -- cgit v0.12