diff options
author | Titta Heikkala <titta.heikkala@digia.com> | 2013-08-23 12:38:29 +0300 |
---|---|---|
committer | Titta Heikkala <titta.heikkala@digia.com> | 2013-08-26 12:07:10 +0300 |
commit | 1e4c29e111d4c5a2344f7370c399625c565ba72c (patch) | |
tree | 35a758319b5a65ca020c64002d6bb0b51b55976e /src | |
parent | 2e0922f74ba527c2ee6d9226e15f5baf0f6ae4b5 (diff) |
Fix zooming in crash
The bounding rect has to fit inside int limits when zooming in, meaning
that the height and width both have to be within the int limits
(INT_MAX). QWidget::update() uses a region (based on bounding rect)
that has to be compatible with QRect. The geometry change is only done
if the bounding rect fulfills this requirement.
Task-number: QTRD-1907
Change-Id: I4e874de355390c5fc983ac1e0976bf0d21e2d10c
Reviewed-by: Miikka Heikkinen <miikka.heikkinen@digia.com>
Diffstat (limited to 'src')
-rw-r--r-- | src/areachart/areachartitem.cpp | 14 | ||||
-rw-r--r-- | src/linechart/linechartitem.cpp | 23 | ||||
-rw-r--r-- | src/scatterchart/scatterchartitem.cpp | 53 | ||||
-rw-r--r-- | src/splinechart/splinechartitem.cpp | 17 |
4 files changed, 70 insertions, 37 deletions
diff --git a/src/areachart/areachartitem.cpp b/src/areachart/areachartitem.cpp index 8b04084d..adb540d8 100644 --- a/src/areachart/areachartitem.cpp +++ b/src/areachart/areachartitem.cpp @@ -110,10 +110,16 @@ void AreaChartItem::updatePath() } } path.closeSubpath(); - prepareGeometryChange(); - m_path = path; - m_rect = path.boundingRect(); - update(); + + // Only zoom in if the bounding rect of the path fits inside int limits. QWidget::update() uses + // a region that has to be compatible with QRect. + if (path.boundingRect().height() <= INT_MAX + && path.boundingRect().width() <= INT_MAX) { + prepareGeometryChange(); + m_path = path; + m_rect = path.boundingRect(); + update(); + } } void AreaChartItem::handleUpdated() diff --git a/src/linechart/linechartitem.cpp b/src/linechart/linechartitem.cpp index 0c517df6..13558671 100644 --- a/src/linechart/linechartitem.cpp +++ b/src/linechart/linechartitem.cpp @@ -276,13 +276,26 @@ void LineChartItem::updateGeometry() stroker.setCapStyle(Qt::SquareCap); stroker.setMiterLimit(m_linePen.miterLimit()); - prepareGeometryChange(); + QPainterPath checkShapePath = stroker.createStroke(fullPath); + + // Only zoom in if the bounding rects of the paths fit inside int limits. QWidget::update() uses + // a region that has to be compatible with QRect. + if (checkShapePath.boundingRect().height() <= INT_MAX + && checkShapePath.boundingRect().width() <= INT_MAX + && linePath.boundingRect().height() <= INT_MAX + && linePath.boundingRect().width() <= INT_MAX + && fullPath.boundingRect().height() <= INT_MAX + && fullPath.boundingRect().width() <= INT_MAX) { + prepareGeometryChange(); - m_linePath = linePath; - m_fullPath = fullPath; - m_shapePath = stroker.createStroke(fullPath); + m_linePath = linePath; + m_fullPath = fullPath; + m_shapePath = checkShapePath; - m_rect = m_shapePath.boundingRect(); + m_rect = m_shapePath.boundingRect(); + } else { + update(); + } } void LineChartItem::handleUpdated() diff --git a/src/scatterchart/scatterchartitem.cpp b/src/scatterchart/scatterchartitem.cpp index 200eda82..89a991e3 100644 --- a/src/scatterchart/scatterchartitem.cpp +++ b/src/scatterchart/scatterchartitem.cpp @@ -126,31 +126,36 @@ void ScatterChartItem::updateGeometry() QRectF clipRect(QPointF(0,0),domain()->size()); - QVector<bool> offGridStatus = offGridStatusVector(); - const int seriesLastIndex = m_series->count() - 1; - - for (int i = 0; i < points.size(); i++) { - QGraphicsItem *item = items.at(i); - const QPointF &point = points.at(i); - const QRectF &rect = item->boundingRect(); - // During remove animation series may have different number of points, - // so ensure we don't go over the index. Animation handling itself ensures that - // if there is actually no points in the series, then it won't generate a fake point, - // so we can be assured there is always at least one point in m_series here. - // Note that marker map values can be technically incorrect during the animation, - // if it was caused by an insert, but this shouldn't be a problem as the points are - // fake anyway. After remove animation stops, geometry is updated to correct one. - m_markerMap[item] = m_series->at(qMin(seriesLastIndex, i)); - item->setPos(point.x() - rect.width() / 2, point.y() - rect.height() / 2); - - if (!m_visible || offGridStatus.at(i)) - item->setVisible(false); - else - item->setVisible(true); - } + // Only zoom in if the clipRect fits inside int limits. QWidget::update() uses + // a region that has to be compatible with QRect. + if (clipRect.height() <= INT_MAX + && clipRect.width() <= INT_MAX) { + QVector<bool> offGridStatus = offGridStatusVector(); + const int seriesLastIndex = m_series->count() - 1; + + for (int i = 0; i < points.size(); i++) { + QGraphicsItem *item = items.at(i); + const QPointF &point = points.at(i); + const QRectF &rect = item->boundingRect(); + // During remove animation series may have different number of points, + // so ensure we don't go over the index. Animation handling itself ensures that + // if there is actually no points in the series, then it won't generate a fake point, + // so we can be assured there is always at least one point in m_series here. + // Note that marker map values can be technically incorrect during the animation, + // if it was caused by an insert, but this shouldn't be a problem as the points are + // fake anyway. After remove animation stops, geometry is updated to correct one. + m_markerMap[item] = m_series->at(qMin(seriesLastIndex, i)); + item->setPos(point.x() - rect.width() / 2, point.y() - rect.height() / 2); + + if (!m_visible || offGridStatus.at(i)) + item->setVisible(false); + else + item->setVisible(true); + } - prepareGeometryChange(); - m_rect = clipRect; + prepareGeometryChange(); + m_rect = clipRect; + } } void ScatterChartItem::paint(QPainter *painter, const QStyleOptionGraphicsItem *option, QWidget *widget) diff --git a/src/splinechart/splinechartitem.cpp b/src/splinechart/splinechartitem.cpp index 11f9ac9b..fc42f529 100644 --- a/src/splinechart/splinechartitem.cpp +++ b/src/splinechart/splinechartitem.cpp @@ -267,7 +267,6 @@ void SplineChartItem::updateGeometry() } fullPath = splinePath; } - m_path = splinePath; QPainterPathStroker stroker; // The full path is comprised of three separate paths. @@ -278,10 +277,20 @@ void SplineChartItem::updateGeometry() stroker.setCapStyle(Qt::SquareCap); stroker.setMiterLimit(m_linePen.miterLimit()); - prepareGeometryChange(); + // Only zoom in if the bounding rects of the path fit inside int limits. QWidget::update() uses + // a region that has to be compatible with QRect. + QPainterPath checkShapePath = stroker.createStroke(fullPath); + if (checkShapePath.boundingRect().height() <= INT_MAX + && checkShapePath.boundingRect().width() <= INT_MAX + && splinePath.boundingRect().height() <= INT_MAX + && splinePath.boundingRect().width() <= INT_MAX) { + m_path = splinePath; - m_fullPath = stroker.createStroke(fullPath); - m_rect = m_fullPath.boundingRect(); + prepareGeometryChange(); + + m_fullPath = checkShapePath; + m_rect = m_fullPath.boundingRect(); + } } /*! |