summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorQt Continuous Integration System <qt-info@nokia.com>2011-05-04 13:31:23 (GMT)
committerQt Continuous Integration System <qt-info@nokia.com>2011-05-04 13:31:23 (GMT)
commitd707b3722bf8781b79c2b88e8a99485a9687c4c8 (patch)
tree5ed6a2084a4968c3600ccf74ef5d608743c5792e
parent9fdee69ef3d08f37a2a4f5daceb4606aa5c7ae9b (diff)
parent66aafe42f9076c0d70037ee8fad0e382828ed7bb (diff)
downloadQt-d707b3722bf8781b79c2b88e8a99485a9687c4c8.zip
Qt-d707b3722bf8781b79c2b88e8a99485a9687c4c8.tar.gz
Qt-d707b3722bf8781b79c2b88e8a99485a9687c4c8.tar.bz2
Merge branch '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2 into 4.7-integration
* '4.7' of scm.dev.nokia.troll.no:qt/oslo-staging-2: Fix ordinal number conflict QPainterPath: Ignore calls with NaN/Infinite parameters memory leak fix Fixes crash in QWidget::effectiveWinId. Revert symbol addition in b033bb9
-rw-r--r--src/gui/kernel/qwidget.cpp20
-rw-r--r--src/gui/kernel/qwidget_p.h1
-rw-r--r--src/gui/painting/qpainterpath.cpp66
-rw-r--r--src/gui/text/qfontengine_ft.cpp4
-rw-r--r--src/gui/text/qtextobject.cpp7
-rw-r--r--src/gui/text/qtextobject.h2
-rw-r--r--src/s60installs/eabi/QtGuiu.def3
-rw-r--r--tests/auto/qpainterpath/tst_qpainterpath.cpp46
-rw-r--r--tests/auto/qtextblock/tst_qtextblock.cpp12
-rw-r--r--tests/auto/qwidget/tst_qwidget.cpp25
10 files changed, 146 insertions, 40 deletions
diff --git a/src/gui/kernel/qwidget.cpp b/src/gui/kernel/qwidget.cpp
index 9d9cd75..6cf5474 100644
--- a/src/gui/kernel/qwidget.cpp
+++ b/src/gui/kernel/qwidget.cpp
@@ -292,6 +292,7 @@ QWidgetPrivate::QWidgetPrivate(int version)
#ifndef QT_NO_IM
, inheritsInputMethodHints(0)
#endif
+ , inSetParent(0)
#if defined(Q_WS_X11)
, picture(0)
#elif defined(Q_WS_WIN)
@@ -2563,6 +2564,22 @@ WId QWidget::effectiveWinId() const
if (id || !testAttribute(Qt::WA_WState_Created))
return id;
QWidget *realParent = nativeParentWidget();
+ if (!realParent && d_func()->inSetParent) {
+ // In transitional state. This is really just a workaround. The real problem
+ // is that QWidgetPrivate::setParent_sys (platform specific code) first sets
+ // the window id to 0 (setWinId(0)) before it sets the Qt::WA_WState_Created
+ // attribute to false. The correct way is to do it the other way around, and
+ // in that case the Qt::WA_WState_Created logic above will kick in and
+ // return 0 whenever the widget is in a transitional state. However, changing
+ // the original logic for all platforms is far more intrusive and might
+ // break existing applications.
+ // Note: The widget can only be in a transitional state when changing its
+ // parent -- everything else is an internal error -- hence explicitly checking
+ // against 'inSetParent' rather than doing an unconditional return whenever
+ // 'realParent' is 0 (which may cause strange artifacts and headache later).
+ return 0;
+ }
+ // This widget *must* have a native parent widget.
Q_ASSERT(realParent);
Q_ASSERT(realParent->internalWinId());
return realParent->internalWinId();
@@ -10041,6 +10058,7 @@ void QWidget::setParent(QWidget *parent)
void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
{
Q_D(QWidget);
+ d->inSetParent = true;
bool resized = testAttribute(Qt::WA_Resized);
bool wasCreated = testAttribute(Qt::WA_WState_Created);
QWidget *oldtlw = window();
@@ -10195,6 +10213,8 @@ void QWidget::setParent(QWidget *parent, Qt::WindowFlags f)
ancestorProxy->d_func()->embedSubWindow(this);
}
#endif
+
+ d->inSetParent = false;
}
/*!
diff --git a/src/gui/kernel/qwidget_p.h b/src/gui/kernel/qwidget_p.h
index 377e3a7..c9dba29 100644
--- a/src/gui/kernel/qwidget_p.h
+++ b/src/gui/kernel/qwidget_p.h
@@ -759,6 +759,7 @@ public:
#ifndef QT_NO_IM
uint inheritsInputMethodHints : 1;
#endif
+ uint inSetParent : 1;
// *************************** Platform specific ************************************
#if defined(Q_WS_X11) // <----------------------------------------------------------- X11
diff --git a/src/gui/painting/qpainterpath.cpp b/src/gui/painting/qpainterpath.cpp
index 0bb2901..4744cb5 100644
--- a/src/gui/painting/qpainterpath.cpp
+++ b/src/gui/painting/qpainterpath.cpp
@@ -628,10 +628,14 @@ void QPainterPath::moveTo(const QPointF &p)
#ifdef QPP_DEBUG
printf("QPainterPath::moveTo() (%.2f,%.2f)\n", p.x(), p.y());
#endif
+
+ if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) {
#ifndef QT_NO_DEBUG
- if (qt_is_nan(p.x()) || qt_is_nan(p.y()))
- qWarning("QPainterPath::moveTo: Adding point where x or y is NaN, results are undefined");
+ qWarning("QPainterPath::moveTo: Adding point where x or y is NaN or Inf, ignoring call");
#endif
+ return;
+ }
+
ensureData();
detach();
@@ -674,10 +678,14 @@ void QPainterPath::lineTo(const QPointF &p)
#ifdef QPP_DEBUG
printf("QPainterPath::lineTo() (%.2f,%.2f)\n", p.x(), p.y());
#endif
+
+ if (!qt_is_finite(p.x()) || !qt_is_finite(p.y())) {
#ifndef QT_NO_DEBUG
- if (qt_is_nan(p.x()) || qt_is_nan(p.y()))
- qWarning("QPainterPath::lineTo: Adding point where x or y is NaN, results are undefined");
+ qWarning("QPainterPath::lineTo: Adding point where x or y is NaN or Inf, ignoring call");
#endif
+ return;
+ }
+
ensureData();
detach();
@@ -729,11 +737,15 @@ void QPainterPath::cubicTo(const QPointF &c1, const QPointF &c2, const QPointF &
printf("QPainterPath::cubicTo() (%.2f,%.2f), (%.2f,%.2f), (%.2f,%.2f)\n",
c1.x(), c1.y(), c2.x(), c2.y(), e.x(), e.y());
#endif
+
+ if (!qt_is_finite(c1.x()) || !qt_is_finite(c1.y()) || !qt_is_finite(c2.x()) || !qt_is_finite(c2.y())
+ || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) {
#ifndef QT_NO_DEBUG
- if (qt_is_nan(c1.x()) || qt_is_nan(c1.y()) || qt_is_nan(c2.x()) || qt_is_nan(c2.y())
- || qt_is_nan(e.x()) || qt_is_nan(e.y()))
- qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN, results are undefined");
+ qWarning("QPainterPath::cubicTo: Adding point where x or y is NaN or Inf, ignoring call");
#endif
+ return;
+ }
+
ensureData();
detach();
@@ -782,10 +794,14 @@ void QPainterPath::quadTo(const QPointF &c, const QPointF &e)
printf("QPainterPath::quadTo() (%.2f,%.2f), (%.2f,%.2f)\n",
c.x(), c.y(), e.x(), e.y());
#endif
+
+ if (!qt_is_finite(c.x()) || !qt_is_finite(c.y()) || !qt_is_finite(e.x()) || !qt_is_finite(e.y())) {
#ifndef QT_NO_DEBUG
- if (qt_is_nan(c.x()) || qt_is_nan(c.y()) || qt_is_nan(e.x()) || qt_is_nan(e.y()))
- qWarning("QPainterPath::quadTo: Adding point where x or y is NaN, results are undefined");
+ qWarning("QPainterPath::quadTo: Adding point where x or y is NaN or Inf, ignoring call");
#endif
+ return;
+ }
+
ensureData();
detach();
@@ -849,11 +865,15 @@ void QPainterPath::arcTo(const QRectF &rect, qreal startAngle, qreal sweepLength
printf("QPainterPath::arcTo() (%.2f, %.2f, %.2f, %.2f, angle=%.2f, sweep=%.2f\n",
rect.x(), rect.y(), rect.width(), rect.height(), startAngle, sweepLength);
#endif
+
+ if (!qt_is_finite(rect.x()) && !qt_is_finite(rect.y()) || !qt_is_finite(rect.width()) || !qt_is_finite(rect.height())
+ || !qt_is_finite(startAngle) || !qt_is_finite(sweepLength)) {
#ifndef QT_NO_DEBUG
- if (qt_is_nan(rect.x()) || qt_is_nan(rect.y()) || qt_is_nan(rect.width()) || qt_is_nan(rect.height())
- || qt_is_nan(startAngle) || qt_is_nan(sweepLength))
- qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN, results are undefined");
+ qWarning("QPainterPath::arcTo: Adding arc where a parameter is NaN or Inf, ignoring call");
#endif
+ return;
+ }
+
if (rect.isNull())
return;
@@ -952,10 +972,13 @@ QPointF QPainterPath::currentPosition() const
*/
void QPainterPath::addRect(const QRectF &r)
{
+ if (!qt_is_finite(r.x()) || !qt_is_finite(r.y()) || !qt_is_finite(r.width()) || !qt_is_finite(r.height())) {
#ifndef QT_NO_DEBUG
- if (qt_is_nan(r.x()) || qt_is_nan(r.y()) || qt_is_nan(r.width()) || qt_is_nan(r.height()))
- qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN, results are undefined");
+ qWarning("QPainterPath::addRect: Adding rect where a parameter is NaN or Inf, ignoring call");
#endif
+ return;
+ }
+
if (r.isNull())
return;
@@ -1032,11 +1055,14 @@ void QPainterPath::addPolygon(const QPolygonF &polygon)
*/
void QPainterPath::addEllipse(const QRectF &boundingRect)
{
+ if (!qt_is_finite(boundingRect.x()) || !qt_is_finite(boundingRect.y())
+ || !qt_is_finite(boundingRect.width()) || !qt_is_finite(boundingRect.height())) {
#ifndef QT_NO_DEBUG
- if (qt_is_nan(boundingRect.x()) || qt_is_nan(boundingRect.y())
- || qt_is_nan(boundingRect.width()) || qt_is_nan(boundingRect.height()))
- qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN, results are undefined");
+ qWarning("QPainterPath::addEllipse: Adding ellipse where a parameter is NaN or Inf, ignoring call");
#endif
+ return;
+ }
+
if (boundingRect.isNull())
return;
@@ -2358,10 +2384,12 @@ QDataStream &operator>>(QDataStream &s, QPainterPath &p)
s >> x;
s >> y;
Q_ASSERT(type >= 0 && type <= 3);
+ if (!qt_is_finite(x) || !qt_is_finite(y)) {
#ifndef QT_NO_DEBUG
- if (qt_is_nan(x) || qt_is_nan(y))
- qWarning("QDataStream::operator>>: Adding a NaN element to path, results are undefined");
+ qWarning("QDataStream::operator>>: NaN or Inf element found in path, skipping it");
#endif
+ continue;
+ }
QPainterPath::Element elm = { x, y, QPainterPath::ElementType(type) };
p.d_func()->elements.append(elm);
}
diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp
index e89b508..9c90964 100644
--- a/src/gui/text/qfontengine_ft.cpp
+++ b/src/gui/text/qfontengine_ft.cpp
@@ -1800,10 +1800,12 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr
} else {
glyphSet = &defaultGlyphSet;
}
+ bool needsDelete = false;
Glyph * g = glyphSet->getGlyph(glyph);
if (!g) {
face = lockFace();
g = loadGlyphMetrics(glyphSet, glyph);
+ needsDelete = true;
}
if (g) {
@@ -1812,6 +1814,8 @@ glyph_metrics_t QFontEngineFT::boundingBox(glyph_t glyph, const QTransform &matr
overall.width = g->width;
overall.height = g->height;
overall.xoff = g->advance;
+ if (needsDelete)
+ delete g;
} else {
int left = FLOOR(face->glyph->metrics.horiBearingX);
int right = CEIL(face->glyph->metrics.horiBearingX + face->glyph->metrics.width);
diff --git a/src/gui/text/qtextobject.cpp b/src/gui/text/qtextobject.cpp
index a403cc5..2a93f67 100644
--- a/src/gui/text/qtextobject.cpp
+++ b/src/gui/text/qtextobject.cpp
@@ -891,11 +891,6 @@ QTextBlockUserData::~QTextBlockUserData()
Returns true if this text block is valid; otherwise returns false.
*/
-bool QTextBlock::isValid() const
-{
- return p != 0 && p->blockMap().isValid(n);
-}
-
/*!
\fn QTextBlock &QTextBlock::operator=(const QTextBlock &other)
@@ -1493,7 +1488,7 @@ QTextBlock::iterator QTextBlock::end() const
*/
QTextBlock QTextBlock::next() const
{
- if (!isValid())
+ if (!isValid() || !p->blockMap().isValid(n))
return QTextBlock();
return QTextBlock(p, p->blockMap().next(n));
diff --git a/src/gui/text/qtextobject.h b/src/gui/text/qtextobject.h
index 73aed79..d5c1e8d 100644
--- a/src/gui/text/qtextobject.h
+++ b/src/gui/text/qtextobject.h
@@ -204,7 +204,7 @@ public:
inline QTextBlock(const QTextBlock &o) : p(o.p), n(o.n) {}
inline QTextBlock &operator=(const QTextBlock &o) { p = o.p; n = o.n; return *this; }
- bool isValid() const;
+ inline bool isValid() const { return p != 0 && n != 0; }
inline bool operator==(const QTextBlock &o) const { return p == o.p && n == o.n; }
inline bool operator!=(const QTextBlock &o) const { return p != o.p || n != o.n; }
diff --git a/src/s60installs/eabi/QtGuiu.def b/src/s60installs/eabi/QtGuiu.def
index 11ff7bc..318b394 100644
--- a/src/s60installs/eabi/QtGuiu.def
+++ b/src/s60installs/eabi/QtGuiu.def
@@ -12183,6 +12183,5 @@ EXPORTS
_ZN15QGraphicsSystem22releaseCachedResourcesEv @ 12182 NONAME
_Z32qt_s60_setPartialScreenInputModeb @ 12183 NONAME
_Z29qt_draw_decoration_for_glyphsP8QPainterPKjPK11QFixedPointiP11QFontEngineRK5QFontRK15QTextCharFormat @ 12184 NONAME
- _ZNK10QTextBlock7isValidEv @ 12185 NONAME
- _ZNK14QVolatileImage14paintingActiveEv @ 12186 NONAME
+ _ZNK14QVolatileImage14paintingActiveEv @ 12185 NONAME
diff --git a/tests/auto/qpainterpath/tst_qpainterpath.cpp b/tests/auto/qpainterpath/tst_qpainterpath.cpp
index bc3b5d9..e9f09ea 100644
--- a/tests/auto/qpainterpath/tst_qpainterpath.cpp
+++ b/tests/auto/qpainterpath/tst_qpainterpath.cpp
@@ -101,6 +101,8 @@ private slots:
void testToFillPolygons();
+ void testNaNandInfinites();
+
void closing();
void operators_data();
@@ -1159,6 +1161,50 @@ void tst_QPainterPath::testToFillPolygons()
QCOMPARE(polygons.first().count(QPointF(70, 50)), 0);
}
+void tst_QPainterPath::testNaNandInfinites()
+{
+ QPainterPath path1;
+ QPainterPath path2 = path1;
+
+ QPointF p1 = QPointF(qSNaN(), 1);
+ QPointF p2 = QPointF(qQNaN(), 1);
+ QPointF p3 = QPointF(qQNaN(), 1);
+ QPointF pInf = QPointF(qInf(), 1);
+
+ // all these operations with NaN/Inf should be ignored
+ // can't test operator>> reliably, as we can't create a path with NaN to << later
+
+ path1.moveTo(p1);
+ path1.moveTo(qSNaN(), qQNaN());
+ path1.moveTo(pInf);
+
+ path1.lineTo(p1);
+ path1.lineTo(qSNaN(), qQNaN());
+ path1.lineTo(pInf);
+
+ path1.cubicTo(p1, p2, p3);
+ path1.cubicTo(p1, QPointF(1, 1), QPointF(2, 2));
+ path1.cubicTo(pInf, QPointF(10, 10), QPointF(5, 1));
+
+ path1.quadTo(p1, p2);
+ path1.quadTo(QPointF(1, 1), p3);
+ path1.quadTo(QPointF(1, 1), pInf);
+
+ path1.arcTo(QRectF(p1, p2), 5, 5);
+ path1.arcTo(QRectF(pInf, QPointF(1, 1)), 5, 5);
+
+ path1.addRect(QRectF(p1, p2));
+ path1.addRect(QRectF(pInf, QPointF(1, 1)));
+
+ path1.addEllipse(QRectF(p1, p2));
+ path1.addEllipse(QRectF(pInf, QPointF(1, 1)));
+
+ QCOMPARE(path1, path2);
+
+ path1.lineTo(QPointF(1, 1));
+ QVERIFY(path1 != path2);
+}
+
void tst_QPainterPath::connectPathDuplicatePoint()
{
QPainterPath a;
diff --git a/tests/auto/qtextblock/tst_qtextblock.cpp b/tests/auto/qtextblock/tst_qtextblock.cpp
index 748d921..cec3a6a 100644
--- a/tests/auto/qtextblock/tst_qtextblock.cpp
+++ b/tests/auto/qtextblock/tst_qtextblock.cpp
@@ -76,7 +76,6 @@ private slots:
void excludeParagraphSeparatorFragment();
void backwardsBlockIterator();
void previousBlock_qtbug18026();
- void removedBlock_qtbug18500();
private:
QTextDocument *doc;
@@ -182,16 +181,5 @@ void tst_QTextBlock::previousBlock_qtbug18026()
QVERIFY(last.isValid());
}
-void tst_QTextBlock::removedBlock_qtbug18500()
-{
- cursor.insertText("line 1\nline 2\nline 3 \nline 4\n");
- cursor.setPosition(7);
- QTextBlock block = cursor.block();
- cursor.setPosition(21, QTextCursor::KeepAnchor);
-
- cursor.removeSelectedText();
- QVERIFY(!block.isValid());
-}
-
QTEST_MAIN(tst_QTextBlock)
#include "tst_qtextblock.moc"
diff --git a/tests/auto/qwidget/tst_qwidget.cpp b/tests/auto/qwidget/tst_qwidget.cpp
index bb8b8b4..a851d03 100644
--- a/tests/auto/qwidget/tst_qwidget.cpp
+++ b/tests/auto/qwidget/tst_qwidget.cpp
@@ -345,6 +345,7 @@ private slots:
void immediateRepaintAfterInvalidateBuffer();
#endif
void effectiveWinId();
+ void effectiveWinId2();
void customDpi();
void customDpiProperty();
@@ -8522,6 +8523,30 @@ void tst_QWidget::effectiveWinId()
QVERIFY(child.effectiveWinId());
}
+void tst_QWidget::effectiveWinId2()
+{
+ QWidget parent;
+
+ class MyWidget : public QWidget {
+ bool event(QEvent *e)
+ {
+ if (e->type() == QEvent::WinIdChange) {
+ // Shouldn't crash.
+ effectiveWinId();
+ }
+
+ return QWidget::event(e);
+ }
+ };
+
+ MyWidget child;
+ child.setParent(&parent);
+ parent.show();
+
+ child.setParent(0);
+ child.setParent(&parent);
+}
+
class CustomWidget : public QWidget
{
public: