forked from qt-creator/qt-creator
QmlProfiler: Prevent integer overflows in timelinerenderer
When zooming in the x offset and width of events can be larger than 2^31. We can restrict them to the visible area, though. Task-number: QTCREATORBUG-11879 Change-Id: I841300b55cdd583d5c3fa58b196101038f6f6036 Reviewed-by: Kai Koehne <kai.koehne@digia.com>
This commit is contained in:
@@ -44,7 +44,7 @@ using namespace QmlProfiler::Internal;
|
|||||||
const int DefaultRowHeight = 30;
|
const int DefaultRowHeight = 30;
|
||||||
|
|
||||||
TimelineRenderer::TimelineRenderer(QQuickPaintedItem *parent) :
|
TimelineRenderer::TimelineRenderer(QQuickPaintedItem *parent) :
|
||||||
QQuickPaintedItem(parent), m_startTime(0), m_endTime(0), m_spacing(0),
|
QQuickPaintedItem(parent), m_startTime(0), m_endTime(0), m_spacing(0), m_spacedDuration(0),
|
||||||
m_lastStartTime(0), m_lastEndTime(0)
|
m_lastStartTime(0), m_lastEndTime(0)
|
||||||
, m_profilerModelProxy(0)
|
, m_profilerModelProxy(0)
|
||||||
{
|
{
|
||||||
@@ -82,6 +82,20 @@ void TimelineRenderer::requestPaint()
|
|||||||
update();
|
update();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
inline void TimelineRenderer::getItemXExtent(int modelIndex, int i, int ¤tX, int &itemWidth)
|
||||||
|
{
|
||||||
|
qint64 start = m_profilerModelProxy->getStartTime(modelIndex, i) - m_startTime;
|
||||||
|
if (start > 0) {
|
||||||
|
currentX = start * m_spacing;
|
||||||
|
itemWidth = qMax(1.0, (qMin(m_profilerModelProxy->getDuration(modelIndex, i) *
|
||||||
|
m_spacing, m_spacedDuration)));
|
||||||
|
} else {
|
||||||
|
currentX = -OutOfScreenMargin;
|
||||||
|
itemWidth = qMax(1.0, (qMin((m_profilerModelProxy->getDuration(modelIndex, i) + start) *
|
||||||
|
m_spacing + OutOfScreenMargin, m_spacedDuration)));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
void TimelineRenderer::paint(QPainter *p)
|
void TimelineRenderer::paint(QPainter *p)
|
||||||
{
|
{
|
||||||
qint64 windowDuration = m_endTime - m_startTime;
|
qint64 windowDuration = m_endTime - m_startTime;
|
||||||
@@ -89,6 +103,7 @@ void TimelineRenderer::paint(QPainter *p)
|
|||||||
return;
|
return;
|
||||||
|
|
||||||
m_spacing = qreal(width()) / windowDuration;
|
m_spacing = qreal(width()) / windowDuration;
|
||||||
|
m_spacedDuration = (m_endTime - m_startTime) * m_spacing + 2 * OutOfScreenMargin;
|
||||||
|
|
||||||
p->setPen(Qt::transparent);
|
p->setPen(Qt::transparent);
|
||||||
|
|
||||||
@@ -119,22 +134,19 @@ void TimelineRenderer::drawItemsToPainter(QPainter *p, int modelIndex, int fromI
|
|||||||
|
|
||||||
for (int i = fromIndex; i <= toIndex; i++) {
|
for (int i = fromIndex; i <= toIndex; i++) {
|
||||||
int currentX, currentY, itemWidth, itemHeight;
|
int currentX, currentY, itemWidth, itemHeight;
|
||||||
currentX = (m_profilerModelProxy->getStartTime(modelIndex, i) - m_startTime) * m_spacing;
|
|
||||||
|
|
||||||
int rowNumber = m_profilerModelProxy->getEventRow(modelIndex, i);
|
int rowNumber = m_profilerModelProxy->getEventRow(modelIndex, i);
|
||||||
currentY = (modelRowStart + rowNumber) * DefaultRowHeight - y();
|
currentY = (modelRowStart + rowNumber) * DefaultRowHeight - y();
|
||||||
if (currentY >= height())
|
if (currentY >= height())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
itemWidth = m_profilerModelProxy->getDuration(modelIndex, i) * m_spacing;
|
|
||||||
if (itemWidth < 1)
|
|
||||||
itemWidth = 1;
|
|
||||||
|
|
||||||
itemHeight = DefaultRowHeight * m_profilerModelProxy->getHeight(modelIndex, i);
|
itemHeight = DefaultRowHeight * m_profilerModelProxy->getHeight(modelIndex, i);
|
||||||
currentY += DefaultRowHeight - itemHeight;
|
currentY += DefaultRowHeight - itemHeight;
|
||||||
if (currentY + itemHeight < 0)
|
if (currentY + itemHeight < 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
|
getItemXExtent(modelIndex, i, currentX, itemWidth);
|
||||||
|
|
||||||
// normal events
|
// normal events
|
||||||
p->setBrush(m_profilerModelProxy->getColor(modelIndex, i));
|
p->setBrush(m_profilerModelProxy->getColor(modelIndex, i));
|
||||||
p->drawRect(currentX, currentY, itemWidth, itemHeight);
|
p->drawRect(currentX, currentY, itemWidth, itemHeight);
|
||||||
@@ -171,14 +183,11 @@ void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromI
|
|||||||
if (m_profilerModelProxy->getEventId(modelIndex, i) != id)
|
if (m_profilerModelProxy->getEventId(modelIndex, i) != id)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
currentX = (m_profilerModelProxy->getStartTime(modelIndex, i) - m_startTime) * m_spacing;
|
|
||||||
currentY = (modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, i)) * DefaultRowHeight - y();
|
currentY = (modelRowStart + m_profilerModelProxy->getEventRow(modelIndex, i)) * DefaultRowHeight - y();
|
||||||
if (currentY + DefaultRowHeight < 0 || height() < currentY)
|
if (currentY + DefaultRowHeight < 0 || height() < currentY)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
itemWidth = m_profilerModelProxy->getDuration(modelIndex, i) * m_spacing;
|
getItemXExtent(modelIndex, i, currentX, itemWidth);
|
||||||
if (itemWidth < 1)
|
|
||||||
itemWidth = 1;
|
|
||||||
|
|
||||||
if (i == m_selectedItem)
|
if (i == m_selectedItem)
|
||||||
selectedItemRect = QRect(currentX, currentY - 1, itemWidth, DefaultRowHeight + 1);
|
selectedItemRect = QRect(currentX, currentY - 1, itemWidth, DefaultRowHeight + 1);
|
||||||
@@ -198,7 +207,7 @@ void TimelineRenderer::drawSelectionBoxes(QPainter *p, int modelIndex, int fromI
|
|||||||
void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int fromIndex, int toIndex)
|
void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int fromIndex, int toIndex)
|
||||||
{
|
{
|
||||||
int destindex;
|
int destindex;
|
||||||
int xfrom, xto;
|
int xfrom, xto, width;
|
||||||
int yfrom, yto;
|
int yfrom, yto;
|
||||||
int radius = DefaultRowHeight / 3;
|
int radius = DefaultRowHeight / 3;
|
||||||
QPen shadowPen = QPen(QColor("grey"),2);
|
QPen shadowPen = QPen(QColor("grey"),2);
|
||||||
@@ -210,23 +219,20 @@ void TimelineRenderer::drawBindingLoopMarkers(QPainter *p, int modelIndex, int f
|
|||||||
for (int i = fromIndex; i <= toIndex; i++) {
|
for (int i = fromIndex; i <= toIndex; i++) {
|
||||||
destindex = m_profilerModelProxy->getBindingLoopDest(modelIndex, i);
|
destindex = m_profilerModelProxy->getBindingLoopDest(modelIndex, i);
|
||||||
if (destindex >= 0) {
|
if (destindex >= 0) {
|
||||||
// from
|
|
||||||
xfrom = (m_profilerModelProxy->getStartTime(modelIndex, i) +
|
|
||||||
m_profilerModelProxy->getDuration(modelIndex, i)/2 -
|
|
||||||
m_startTime) * m_spacing;
|
|
||||||
yfrom = getYPosition(modelIndex, i) + DefaultRowHeight / 2 - y();
|
|
||||||
|
|
||||||
// to
|
// to
|
||||||
xto = (m_profilerModelProxy->getStartTime(modelIndex, destindex) +
|
getItemXExtent(modelIndex, destindex, xto, width);
|
||||||
m_profilerModelProxy->getDuration(modelIndex, destindex)/2 -
|
xto += width / 2;
|
||||||
m_startTime) * m_spacing;
|
|
||||||
yto = getYPosition(modelIndex, destindex) + DefaultRowHeight / 2 - y();
|
yto = getYPosition(modelIndex, destindex) + DefaultRowHeight / 2 - y();
|
||||||
|
|
||||||
// radius
|
// from
|
||||||
int eventWidth = m_profilerModelProxy->getDuration(modelIndex, i) * m_spacing;
|
getItemXExtent(modelIndex, i, xfrom, width);
|
||||||
|
xfrom += width / 2;
|
||||||
|
yfrom = getYPosition(modelIndex, i) + DefaultRowHeight / 2 - y();
|
||||||
|
|
||||||
|
// radius (derived from width of origin event)
|
||||||
radius = 5;
|
radius = 5;
|
||||||
if (radius * 2 > eventWidth)
|
if (radius * 2 > width)
|
||||||
radius = eventWidth / 2;
|
radius = width / 2;
|
||||||
if (radius < 2)
|
if (radius < 2)
|
||||||
radius = 2;
|
radius = 2;
|
||||||
|
|
||||||
|
|||||||
@@ -195,9 +195,14 @@ private:
|
|||||||
}
|
}
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
static const int OutOfScreenMargin = 3; // margin to make sure the rectangles stay invisible
|
||||||
|
inline void getItemXExtent(int modelIndex, int i, int ¤tX, int &itemWidth);
|
||||||
|
|
||||||
qint64 m_startTime;
|
qint64 m_startTime;
|
||||||
qint64 m_endTime;
|
qint64 m_endTime;
|
||||||
qreal m_spacing;
|
qreal m_spacing;
|
||||||
|
qreal m_spacedDuration;
|
||||||
|
|
||||||
qint64 m_lastStartTime;
|
qint64 m_lastStartTime;
|
||||||
qint64 m_lastEndTime;
|
qint64 m_lastEndTime;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user