From 7d5e8f7ff741b45d0114ea45d81c8d90118d65ab Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 26 Mar 2010 10:15:29 +0100 Subject: Designer: Fix broken resource view filtering. Another side effect of 62c72ed2fd4aa6f5e62a190abf2dde2ba0f5ff0b . Task-number: QTBUG-9262 Initial-patch-by: Jarek Kobus --- tools/designer/src/lib/shared/qtresourceview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/designer/src/lib/shared/qtresourceview.cpp b/tools/designer/src/lib/shared/qtresourceview.cpp index 3c7010c..18fd07b 100644 --- a/tools/designer/src/lib/shared/qtresourceview.cpp +++ b/tools/designer/src/lib/shared/qtresourceview.cpp @@ -421,7 +421,7 @@ void QtResourceViewPrivate::filterOutResources() // 3) we hide these items which has pathToVisible value false. const bool matchAll = m_filterPattern.isEmpty(); - const QString root(QLatin1Char(':')); + const QString root(QLatin1String(":/")); QQueue pathQueue; pathQueue.enqueue(root); -- cgit v0.12 From df0e6759e8ebc1053f951d3a5398a41156e91913 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Thu, 25 Mar 2010 20:05:35 +0100 Subject: QMetaObject::normalizeType: fix uses of const and template. 'const' was not removed from templated class This even fixes compilation errors if using const return templated types We can change the normalized signature in Qt 4.7 as it has already changed and we have code to check that if moc revision < 5 it will renormalize all the symbols cf commit b881d8fb99972f1bd04ab4c84843cc8d43ddbeed Task-number: QTBUG-7421 Reviewed-by: Brad Reviewed-by: Kent Hansen --- src/corelib/kernel/qmetaobject_p.h | 4 +++- tests/auto/moc/tst_moc.cpp | 11 +++++++++++ tests/auto/qmetaobject/tst_qmetaobject.cpp | 6 ++++++ tests/auto/qobject/tst_qobject.cpp | 20 ++++++++++++++++++++ 4 files changed, 40 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index a176149..1f4bd2f 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -196,7 +196,7 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc if (*(e-1) == '&') { // treat const reference as value t += 6; --e; - } else if (is_ident_char(*(e-1))) { // treat const value as value + } else if (is_ident_char(*(e-1)) || *(e-1) == '>') { // treat const value as value t += 6; } } @@ -294,6 +294,8 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc if (adjustConst && t != e && *t == '&') { // treat const ref as value ++t; + } else if (adjustConst && !star) { + // treat const as value } else if (!star) { // move const to the front (but not if const comes after a *) result.prepend("const "); diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index 30c2721..8890a15 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -1302,6 +1302,17 @@ void tst_Moc::QTBUG5590_dummyProperty() QCOMPARE(o.value2(), 82); } +class QTBUG7421_ReturnConstTemplate: public QObject +{ Q_OBJECT +public slots: + const QList returnConstTemplate1() { return QList(); } + QList const returnConstTemplate2() { return QList(); } + const int returnConstInt() { return 0; } + const QString returnConstString(const QString s) { return s; } + QString const returnConstString2( QString const s) { return s; } +}; + + QTEST_APPLESS_MAIN(tst_Moc) #include "tst_moc.moc" diff --git a/tests/auto/qmetaobject/tst_qmetaobject.cpp b/tests/auto/qmetaobject/tst_qmetaobject.cpp index bb4a0d2..e81607e 100644 --- a/tests/auto/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/qmetaobject/tst_qmetaobject.cpp @@ -706,6 +706,12 @@ void tst_QMetaObject::normalizedSignature_data() QTest::newRow("const6") << "void foo(QList)" << "void foo(QList)"; QTest::newRow("const7") << "void foo(QList)" << "void foo(QList)"; QTest::newRow("const8") << "void foo(QList)" << "void foo(QList)"; + QTest::newRow("const9") << "void foo(const Foo)" << "void foo(Foo)"; + QTest::newRow("const10") << "void foo(Fooconst)" << "void foo(Foo)"; + QTest::newRow("const11") << "void foo(Foo *const)" << "void foo(Foo*const)"; + QTest::newRow("const12") << "void foo(Fooconst*const *const)" << "void foo(Foo*const*const)"; + QTest::newRow("const13") << "void foo(const Foo&)" << "void foo(Foo)"; + QTest::newRow("const14") << "void foo(Fooconst&)" << "void foo(Foo)"; } void tst_QMetaObject::normalizedSignature() diff --git a/tests/auto/qobject/tst_qobject.cpp b/tests/auto/qobject/tst_qobject.cpp index 8da3484..08b7c19 100644 --- a/tests/auto/qobject/tst_qobject.cpp +++ b/tests/auto/qobject/tst_qobject.cpp @@ -2088,6 +2088,9 @@ signals: void typePointerConstRefSignal(Class * const &); + void constTemplateSignal1( Template ); + void constTemplateSignal2( Template< const int >); + public slots: void uintPointerSlot(uint *) { } void ulongPointerSlot(ulong *) { } @@ -2124,6 +2127,10 @@ public slots: void typeConstRefSlot(Template const &) {} void typePointerConstRefSlot(Class * const &) {} + + void constTemplateSlot1(Template const) {} + void constTemplateSlot2(const Template ) {} + void constTemplateSlot3(const Template< const int >) {} }; #include "oldnormalizeobject.h" @@ -2526,6 +2533,19 @@ void tst_QObject::normalize() QVERIFY(object.connect(&object, SIGNAL(typePointerConstRefSignal(Class*)), SLOT(typePointerConstRefSlot(Class*)))); + + QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template )), + &object , SLOT(constTemplateSlot1 (Template ) ) )); + QVERIFY( connect(&object, SIGNAL(constTemplateSignal1(Template )), + &object , SLOT(constTemplateSlot2 (Template ) ) )); + QVERIFY( connect(&object, SIGNAL(constTemplateSignal2(Template )), + &object , SLOT(constTemplateSlot3(Template ) ) )); + + //type does not match + QTest::ignoreMessage(QtWarningMsg, "QObject::connect: Incompatible sender/receiver arguments\n" + " NormalizeObject::constTemplateSignal1(Template) --> NormalizeObject::constTemplateSlot3(Template)"); + QVERIFY(!connect(&object, SIGNAL(constTemplateSignal1(Template )), + &object , SLOT(constTemplateSlot3(Template ) ) )); } class SiblingDeleter : public QObject -- cgit v0.12 From ff870dbf9106f2bbb2cf64f5aa35fc5917e5f4f2 Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Fri, 26 Mar 2010 11:26:42 +0100 Subject: QMetaObject::normalizeType: Fix parsing of type which contains "const" in names Regression since b881d8fb99972f1bd04ab4c84843cc8d43ddbeed Task-number: QTBUG-9354 Reviewed-by: Kent Hansen --- src/corelib/kernel/qmetaobject_p.h | 3 ++- tests/auto/moc/tst_moc.cpp | 9 +++++++++ tests/auto/qmetaobject/tst_qmetaobject.cpp | 8 ++++++++ 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/corelib/kernel/qmetaobject_p.h b/src/corelib/kernel/qmetaobject_p.h index 1f4bd2f..b538787 100644 --- a/src/corelib/kernel/qmetaobject_p.h +++ b/src/corelib/kernel/qmetaobject_p.h @@ -287,7 +287,8 @@ static QByteArray normalizeTypeInternal(const char *t, const char *e, bool fixSc } // cv qualifers can appear after the type as well - if (t != e && (e - t >= 5 && strncmp("const", t, 5) == 0)) { + if (!is_ident_char(c) && t != e && (e - t >= 5 && strncmp("const", t, 5) == 0) + && (e - t == 5 || !is_ident_char(t[5]))) { t += 5; while (t != e && is_space(*t)) ++t; diff --git a/tests/auto/moc/tst_moc.cpp b/tests/auto/moc/tst_moc.cpp index 8890a15..a56d842 100644 --- a/tests/auto/moc/tst_moc.cpp +++ b/tests/auto/moc/tst_moc.cpp @@ -1312,6 +1312,15 @@ public slots: QString const returnConstString2( QString const s) { return s; } }; +class QTBUG9354_constInName: public QObject +{ Q_OBJECT +public slots: + void slotChooseScientificConst0(struct science_constant const &) {}; + void foo(struct science_const const &) {}; + void foo(struct constconst const &) {}; + void foo(struct constconst *) {}; + void foo(struct const_ *) {}; +}; QTEST_APPLESS_MAIN(tst_Moc) #include "tst_moc.moc" diff --git a/tests/auto/qmetaobject/tst_qmetaobject.cpp b/tests/auto/qmetaobject/tst_qmetaobject.cpp index e81607e..c0b1303 100644 --- a/tests/auto/qmetaobject/tst_qmetaobject.cpp +++ b/tests/auto/qmetaobject/tst_qmetaobject.cpp @@ -740,6 +740,14 @@ void tst_QMetaObject::normalizedType_data() QTest::newRow("template7") << "QList >" << "QList >"; QTest::newRow("value1") << "const QString &" << "QString"; QTest::newRow("value2") << "QString const &" << "QString"; + QTest::newRow("constInName1") << "constconst" << "constconst"; + QTest::newRow("constInName2") << "constconst*" << "constconst*"; + QTest::newRow("constInName3") << "const constconst&" << "constconst"; + QTest::newRow("constInName4") << "constconst const*const" << "constconst*const"; + QTest::newRow("class") << "const class foo&" << "foo"; + QTest::newRow("struct") << "const struct foo*" << "const foo*"; + QTest::newRow("struct2") << "struct foo const*" << "const foo*"; + QTest::newRow("enum") << "enum foo" << "foo"; } void tst_QMetaObject::normalizedType() -- cgit v0.12 From 9a7dd6c047a8eebad94fd5f3e9fc2284c315b046 Mon Sep 17 00:00:00 2001 From: Kent Hansen Date: Fri, 26 Mar 2010 12:24:00 +0100 Subject: QtScript: Add missing API shim for signal handling The signal handling bypasses the public QScriptValue API (it calls JSC::call() directly), hence we need to insert a shim to make sure that the correct identifier table will be used. --- src/script/bridge/qscriptqobject.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/script/bridge/qscriptqobject.cpp b/src/script/bridge/qscriptqobject.cpp index 83a811b..0477454 100644 --- a/src/script/bridge/qscriptqobject.cpp +++ b/src/script/bridge/qscriptqobject.cpp @@ -2074,6 +2074,7 @@ void QObjectConnectionManager::execute(int slotIndex, void **argv) JSC::JSValue slot; JSC::JSValue senderWrapper; int signalIndex = -1; + QScript::APIShim shim(engine); for (int i = 0; i < connections.size(); ++i) { const QVector &cs = connections.at(i); for (int j = 0; j < cs.size(); ++j) { -- cgit v0.12 From c19cb39ddbfd93802bfe61ecaa4f737a1bd1c1bb Mon Sep 17 00:00:00 2001 From: Fabien Freling Date: Fri, 26 Mar 2010 12:34:54 +0100 Subject: Fix the bug where the ampersand symbol would be discarded. We are now checking that the QAction is not related to the About or Quit button on Mac OS X Task-number: QTBUG-7540 Reviewed-by: Morten Sorvig --- src/gui/styles/qmacstyle_mac.mm | 4 ++-- src/gui/widgets/qmenu_mac.mm | 6 +++++- 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/src/gui/styles/qmacstyle_mac.mm b/src/gui/styles/qmacstyle_mac.mm index 7097291..074dd89 100644 --- a/src/gui/styles/qmacstyle_mac.mm +++ b/src/gui/styles/qmacstyle_mac.mm @@ -434,13 +434,13 @@ static inline bool isTreeView(const QWidget *widget) QString qt_mac_removeMnemonics(const QString &original) { - // copied from qt_format_text (to be bug-for-bug compatible). QString returnText(original.size(), 0); int finalDest = 0; int currPos = 0; int l = original.length(); while (l) { - if (original.at(currPos) == QLatin1Char('&')) { + if (original.at(currPos) == QLatin1Char('&') + && (l == 1 || original.at(currPos + 1) != QLatin1Char('&'))) { ++currPos; --l; if (l == 0) diff --git a/src/gui/widgets/qmenu_mac.mm b/src/gui/widgets/qmenu_mac.mm index 9a14ce6..6a0eb53 100644 --- a/src/gui/widgets/qmenu_mac.mm +++ b/src/gui/widgets/qmenu_mac.mm @@ -1391,7 +1391,11 @@ QMenuPrivate::QMacMenuPrivate::syncAction(QMacMenuAction *action) } else { [item setTitle: qt_mac_QStringToNSString(finalString)]; } - [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))]; + + if (action->action->menuRole() == QAction::AboutRole || action->action->menuRole() == QAction::QuitRole) + [item setTitle:qt_mac_QStringToNSString(text)]; + else + [item setTitle:qt_mac_QStringToNSString(qt_mac_removeMnemonics(text))]; // Cocoa Enabled [item setEnabled: action->action->isEnabled()]; -- cgit v0.12 From fa40e6fd8b719e2edfdbde94ac70431c68e92449 Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Fri, 26 Mar 2010 10:54:34 +0100 Subject: Stabilize tst_QTreeView::taskQTBUG_9216_setSizeAndUniformRowHeightsWrongRepaint Non expected paint events and screen size on pulse_qws/linux-x86-g++ seem to be the reason the auto-test fails. Reviewed-by: jeremy --- tests/auto/qtreeview/tst_qtreeview.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/tests/auto/qtreeview/tst_qtreeview.cpp b/tests/auto/qtreeview/tst_qtreeview.cpp index 6871982..2de189d 100644 --- a/tests/auto/qtreeview/tst_qtreeview.cpp +++ b/tests/auto/qtreeview/tst_qtreeview.cpp @@ -3721,11 +3721,13 @@ class TreeViewQTBUG_9216 : public QTreeView public: void paintEvent(QPaintEvent *event) { - QCOMPARE(event->rect(), viewport()->rect()); + if (doCompare) + QCOMPARE(event->rect(), viewport()->rect()); QTreeView::paintEvent(event); painted++; } int painted; + bool doCompare; }; void tst_QTreeView::taskQTBUG_9216_setSizeAndUniformRowHeightsWrongRepaint() @@ -3737,15 +3739,16 @@ void tst_QTreeView::taskQTBUG_9216_setSizeAndUniformRowHeightsWrongRepaint() TreeViewQTBUG_9216 view; view.setUniformRowHeights(true); view.setModel(&model); - view.resize(800, 800); view.painted = 0; + view.doCompare = false; view.show(); QTest::qWaitForWindowShown(&view); QTRY_VERIFY(view.painted > 0); QTest::qWait(100); // This one is needed to make the test fail before the patch. view.painted = 0; - model.setData(model.index(0, 5), QVariant(QSize(100,100)), Qt::SizeHintRole); + view.doCompare = true; + model.setData(model.index(0, 0), QVariant(QSize(50, 50)), Qt::SizeHintRole); QTest::qWait(100); QTRY_VERIFY(view.painted > 0); } -- cgit v0.12 From f1bbb1648a9770f37ca39b8d68d6bd269dd06250 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jo=C3=A3o=20Abecasis?= Date: Fri, 26 Mar 2010 12:33:08 +0100 Subject: Qualify ptrdiff_t's namespace in stltest configure test Reviewed-by: Thiago Macieira Task-number: QTBUG-9046 --- config.tests/unix/stl/stltest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/config.tests/unix/stl/stltest.cpp b/config.tests/unix/stl/stltest.cpp index ff9b8f9..382f5cb 100644 --- a/config.tests/unix/stl/stltest.cpp +++ b/config.tests/unix/stl/stltest.cpp @@ -69,7 +69,7 @@ class DummyIterator public: T *i; typedef std::random_access_iterator_tag iterator_category; - typedef ptrdiff_t difference_type; + typedef std::ptrdiff_t difference_type; typedef T value_type; typedef T *pointer; typedef T &reference; -- cgit v0.12 From 75bb84ac0e6f17446d87a34ae8a644abff6009af Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Mon, 22 Mar 2010 10:48:39 +0100 Subject: Implement Texture-From-Pixmap using EGLImage extensions on X11/EGL There's lots of EGLImage extensions, split between EGL and client rendering APIs like OpenGL ES & OpenVG. To implement texture-from- pixmap using EGLImage, both EGL extensions and OpenGL ES extensions are needed. This patch resolves the EGL extension function pointers after the display is initialized in QEgl::display(). These are then exported from QtGui so they can be used in QtOpenGL. The OpenGL ES extension function pointers are resolved using the usual qglextensions.cpp mechanism. Using EGLImage seems to remove a fixed ~10 millisecond overhead per pixmap bind when compared to using EGLSurface. Exact results per bind for 100 QPixmaps are: 8x8 Pixmap: 12 -> 1.71 msecs (EGLSurface -> EGLImage) 64x64 Pixmap: 11.6 -> 1.83 msecs (EGLSurface -> EGLImage) 128x128 Pixmap: 12.8 -> 2.74 msecs (EGLSurface -> EGLImage) 256x256 Pixmap: 16 -> 6.20 msecs (EGLSurface -> EGLImage) Reviewed-By: Trond --- src/gui/egl/qegl.cpp | 9 +++ src/gui/egl/qegl_p.h | 24 ++++++- src/opengl/qgl_egl_p.h | 1 + src/opengl/qgl_x11egl.cpp | 146 ++++++++++++++++++++++++++++++++----------- src/opengl/qglextensions.cpp | 11 ++++ src/opengl/qglextensions_p.h | 36 +++++++++++ 6 files changed, 190 insertions(+), 37 deletions(-) diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index b870523..507fab3 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -528,6 +528,9 @@ QEglProperties QEglContext::configProperties() const return QEglProperties(config()); } +_eglCreateImageKHR eglCreateImageKHR = 0; +_eglDestroyImageKHR eglDestroyImageKHR = 0; + EGLDisplay QEgl::display() { static EGLDisplay dpy = EGL_NO_DISPLAY; @@ -549,6 +552,12 @@ EGLDisplay QEgl::display() qWarning() << "QEgl::display(): Cannot initialize EGL display:" << QEgl::errorString(); return EGL_NO_DISPLAY; } + + // Resolve the egl extension function pointers: + if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) { + eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); + eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); + } } return dpy; diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index 7dad9fe..b570329 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -100,13 +100,34 @@ typedef NativeDisplayType EGLNativeDisplayType; QT_END_INCLUDE_NAMESPACE #include - #include QT_BEGIN_NAMESPACE #define QEGL_NO_CONFIG ((EGLConfig)-1) +#ifndef EGLAPIENTRY +#define EGLAPIENTRY +#endif + +#if !defined(EGL_KHR_image) || !defined(EGL_KHR_image_base) + +typedef void *EGLImageKHR; +#define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) +#define EGL_IMAGE_PRESERVED_KHR 0x30D2 + +typedef EGLImageKHR (EGLAPIENTRY *_eglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*); +typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR); + +// Defined in qegl.cpp: +extern Q_GUI_EXPORT _eglCreateImageKHR eglCreateImageKHR; +extern Q_GUI_EXPORT _eglDestroyImageKHR eglDestroyImageKHR; + +#endif // !defined(EGL_KHR_image) || !defined(EGL_KHR_image_base) + +#if !defined(EGL_KHR_image) || !defined(EGL_KHR_image_pixmap) +#define EGL_NATIVE_PIXMAP_KHR 0x30B0 +#endif class QEglProperties; @@ -132,7 +153,6 @@ namespace QEgl { }; Q_DECLARE_FLAGS(ConfigOptions, ConfigOption); - // Most of the time we use the same config for things like widgets & pixmaps, so rather than // go through the eglChooseConfig loop every time, we use defaultConfig, which will return // the config for a particular device/api/option combo. This function assumes that once a diff --git a/src/opengl/qgl_egl_p.h b/src/opengl/qgl_egl_p.h index 43793cd..85d7f32 100644 --- a/src/opengl/qgl_egl_p.h +++ b/src/opengl/qgl_egl_p.h @@ -53,6 +53,7 @@ // We mean it. // +#include #include #include diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 0954e69..6980281 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -367,6 +367,30 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, cons static bool checkedForTFP = false; static bool haveTFP = false; + static bool checkedForEglImageTFP = false; + static bool haveEglImageTFP = false; + + + if (!checkedForEglImageTFP) { + checkedForEglImageTFP = true; + + // We need to be able to create an EGLImage from a native pixmap, which was split + // into a seperate EGL extension, EGL_KHR_image_pixmap. It is possible to have + // eglCreateImageKHR & eglDestroyImageKHR without support for pixmaps, so we must + // check we have the EGLImage from pixmap functionality. + if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_pixmap")) { + Q_ASSERT(eglCreateImageKHR); + Q_ASSERT(eglDestroyImageKHR); + + // Being able to create an EGLImage from a native pixmap is also pretty useless + // without the ability to bind that EGLImage as a texture, which is provided by + // the GL_OES_EGL_image extension, which we try to resolve here: + haveEglImageTFP = qt_resolve_eglimage_gl_extensions(q); + + if (haveEglImageTFP) + qDebug("Found EGL_KHR_image_pixmap & GL_OES_EGL_image extensions (preferred method)!"); + } + } if (!checkedForTFP) { // Check for texture_from_pixmap egl extension @@ -379,61 +403,113 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, cons } } - if (!haveTFP) + if (!haveTFP && !haveEglImageTFP) return 0; - QX11PixmapData *pixmapData = static_cast(pd); + + QX11PixmapData *pixmapData = static_cast(pd); bool hasAlpha = pixmapData->hasAlphaChannel(); + bool pixmapHasValidSurface = false; + bool textureIsBound = false; + GLuint textureId; + glGenTextures(1, &textureId); + glBindTexture(GL_TEXTURE_2D, textureId); - // Check to see if the surface is still valid - if (pixmapData->gl_surface && - hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) + if (haveTFP && pixmapData->gl_surface && + hasAlpha == (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) { - // Surface is invalid! - destroyGlSurfaceForPixmap(pixmapData); + pixmapHasValidSurface = true; } - if (pixmapData->gl_surface == 0) { - EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, - QEgl::OpenGL, - hasAlpha ? QEgl::Translucent : QEgl::NoOptions); + // If we already have a valid EGL surface for the pixmap, we should use it + if (pixmapHasValidSurface) { + EGLBoolean success; + success = eglBindTexImage(QEgl::display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER); + if (success == EGL_FALSE) { + qWarning() << "eglBindTexImage() failed:" << QEgl::errorString(); + eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); + pixmapData->gl_surface = (void*)EGL_NO_SURFACE; + } else + textureIsBound = true; + } - QPixmap tmpPixmap(pixmapData); //### - pixmapData->gl_surface = (void*)QEgl::createSurface(&tmpPixmap, config); - if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) { - haveTFP = false; - return 0; - } + // If the pixmap doesn't already have a valid surface, try binding it via EGLImage + // first, as going through EGLImage should be faster and better supported: + if (!textureIsBound && haveEglImageTFP) { + Q_ASSERT(eglCreateImageKHR); + + EGLImageKHR eglImage; + QPixmap tmpPixmap(pd); + + EGLint attribs[] = { + EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, + EGL_NONE + }; + eglImage = eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, + (EGLClientBuffer)QEgl::nativePixmap(&tmpPixmap), attribs); + + QGLContext* ctx = q; + glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage); + + GLint err = glGetError(); + if (err == GL_NO_ERROR) + textureIsBound = true; + + // Once the egl image is bound, the texture becomes a new sibling image and we can safely + // destroy the EGLImage we created for the pixmap: + if (eglImage != EGL_NO_IMAGE_KHR) + eglDestroyImageKHR(QEgl::display(), eglImage); } - Q_ASSERT(pixmapData->gl_surface); + if (!textureIsBound && haveTFP) { + // Check to see if the surface is still valid + if (pixmapData->gl_surface && + hasAlpha != (pixmapData->flags & QX11PixmapData::GlSurfaceCreatedWithAlpha)) + { + // Surface is invalid! + destroyGlSurfaceForPixmap(pixmapData); + } - GLuint textureId; - glGenTextures(1, &textureId); - glBindTexture(GL_TEXTURE_2D, textureId); + if (pixmapData->gl_surface == 0) { + EGLConfig config = QEgl::defaultConfig(QInternal::Pixmap, + QEgl::OpenGL, + hasAlpha ? QEgl::Translucent : QEgl::NoOptions); - // bind the egl pixmap surface to a texture - EGLBoolean success; - success = eglBindTexImage(eglContext->display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER); - if (success == EGL_FALSE) { - qWarning() << "eglBindTexImage() failed:" << QEgl::errorString(); - eglDestroySurface(eglContext->display(), (EGLSurface)pixmapData->gl_surface); - pixmapData->gl_surface = (void*)EGL_NO_SURFACE; - haveTFP = false; - return 0; + QPixmap tmpPixmap(pixmapData); //### + pixmapData->gl_surface = (void*)QEgl::createSurface(&tmpPixmap, config); + if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) + return false; + } + + EGLBoolean success; + success = eglBindTexImage(QEgl::display(), (EGLSurface)pixmapData->gl_surface, EGL_BACK_BUFFER); + if (success == EGL_FALSE) { + qWarning() << "eglBindTexImage() failed:" << QEgl::errorString(); + eglDestroySurface(QEgl::display(), (EGLSurface)pixmapData->gl_surface); + pixmapData->gl_surface = (void*)EGL_NO_SURFACE; + haveTFP = false; // If TFP isn't working, disable it's use + } else + textureIsBound = true; } - QGLTexture *texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options); - pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture; + QGLTexture *texture = 0; - // We assume the cost of bound pixmaps is zero - QGLTextureCache::instance()->insert(q, key, texture, 0); + if (textureIsBound) { + texture = new QGLTexture(q, textureId, GL_TEXTURE_2D, options); + pixmapData->flags |= QX11PixmapData::InvertedWhenBoundToTexture; + + // We assume the cost of bound pixmaps is zero + QGLTextureCache::instance()->insert(q, key, texture, 0); + + glBindTexture(GL_TEXTURE_2D, textureId); + } else + glDeleteTextures(1, &textureId); - glBindTexture(GL_TEXTURE_2D, textureId); return texture; } + void QGLContextPrivate::destroyGlSurfaceForPixmap(QPixmapData* pmd) { Q_ASSERT(pmd->classId() == QPixmapData::X11Class); diff --git a/src/opengl/qglextensions.cpp b/src/opengl/qglextensions.cpp index 02d5501..ef3c4cd 100644 --- a/src/opengl/qglextensions.cpp +++ b/src/opengl/qglextensions.cpp @@ -222,6 +222,17 @@ bool qt_resolve_buffer_extensions(QGLContext *ctx) #endif } +#ifndef QT_NO_EGL +bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx) +{ + if (glEGLImageTargetTexture2DOES || glEGLImageTargetRenderbufferStorageOES) + return true; + glEGLImageTargetTexture2DOES = (_glEGLImageTargetTexture2DOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetTexture2DOES")); + glEGLImageTargetRenderbufferStorageOES = (_glEGLImageTargetRenderbufferStorageOES) ctx->getProcAddress(QLatin1String("glEGLImageTargetRenderbufferStorageOES")); + return glEGLImageTargetTexture2DOES && glEGLImageTargetRenderbufferStorageOES; +} +#endif + bool qt_resolve_glsl_extensions(QGLContext *ctx) { // Geometry shaders are optional... diff --git a/src/opengl/qglextensions_p.h b/src/opengl/qglextensions_p.h index f6926f3..7597b33 100644 --- a/src/opengl/qglextensions_p.h +++ b/src/opengl/qglextensions_p.h @@ -68,6 +68,11 @@ # define APIENTRYP * #endif +#ifndef QT_NO_EGL +// Needed for EGLImageKHR definition: +#include +#endif + #include #ifndef GL_ARB_vertex_buffer_object @@ -210,6 +215,14 @@ typedef void (APIENTRY *_glFramebufferTextureFaceEXT)(GLenum target, GLenum atta typedef void (APIENTRY *_glCompressedTexImage2DARB) (GLenum, GLint, GLenum, GLsizei, GLsizei, GLint, GLsizei, const GLvoid *); +#ifndef QT_NO_EGL +// OES_EGL_image +// Note: We define these to take EGLImage whereas spec says they take a new GLeglImageOES +// type, which the EGL image should be cast to. +typedef void (APIENTRY *_glEGLImageTargetTexture2DOES) (GLenum, EGLImageKHR); +typedef void (APIENTRY *_glEGLImageTargetRenderbufferStorageOES) (GLenum, EGLImageKHR); +#endif + QT_BEGIN_NAMESPACE struct QGLExtensionFuncs @@ -327,6 +340,12 @@ struct QGLExtensionFuncs // Texture compression qt_glCompressedTexImage2DARB = 0; #endif + +#ifndef QT_NO_EGL + // OES_EGL_image + qt_glEGLImageTargetTexture2DOES = 0; + qt_glEGLImageTargetRenderbufferStorageOES = 0; +#endif } @@ -447,6 +466,13 @@ struct QGLExtensionFuncs // Texture compression _glCompressedTexImage2DARB qt_glCompressedTexImage2DARB; #endif + +#ifndef QT_NO_EGL + // OES_EGL_image + _glEGLImageTargetTexture2DOES qt_glEGLImageTargetTexture2DOES; + _glEGLImageTargetRenderbufferStorageOES qt_glEGLImageTargetRenderbufferStorageOES; +#endif + }; @@ -839,6 +865,12 @@ struct QGLExtensionFuncs #define glCompressedTexImage2D QGLContextPrivate::extensionFuncs(ctx).qt_glCompressedTexImage2DARB #endif +#ifndef QT_NO_EGL +// OES_EGL_image +#define glEGLImageTargetTexture2DOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetTexture2DOES +#define glEGLImageTargetRenderbufferStorageOES QGLContextPrivate::extensionFuncs(ctx).qt_glEGLImageTargetRenderbufferStorageOES +#endif + extern bool qt_resolve_framebufferobject_extensions(QGLContext *ctx); bool qt_resolve_buffer_extensions(QGLContext *ctx); @@ -849,6 +881,10 @@ bool qt_resolve_frag_program_extensions(QGLContext *ctx); bool qt_resolve_glsl_extensions(QGLContext *ctx); +#ifndef QT_NO_EGL +bool qt_resolve_eglimage_gl_extensions(QGLContext *ctx); +#endif + QT_END_NAMESPACE #endif // QGL_EXTENSIONS_P_H -- cgit v0.12 From 7488aa544bdfccc0131427669266a93c44501c42 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Mon, 22 Mar 2010 14:21:23 +0100 Subject: Avoid having to create temporary QPixmaps when binding to texture Reviewed-By: TrustMe --- src/opengl/qgl.cpp | 2 +- src/opengl/qgl_p.h | 2 +- src/opengl/qgl_x11.cpp | 6 +++--- src/opengl/qgl_x11egl.cpp | 13 +++++-------- 4 files changed, 10 insertions(+), 13 deletions(-) diff --git a/src/opengl/qgl.cpp b/src/opengl/qgl.cpp index 7aba25a..e56b149 100644 --- a/src/opengl/qgl.cpp +++ b/src/opengl/qgl.cpp @@ -2444,7 +2444,7 @@ QGLTexture *QGLContextPrivate::bindTexture(const QPixmap &pixmap, GLenum target, if (pd->classId() == QPixmapData::X11Class && pd->pixelType() == QPixmapData::PixmapType && xinfo && xinfo->screen() == pixmap.x11Info().screen()) { - texture = bindTextureFromNativePixmap(pd, key, options); + texture = bindTextureFromNativePixmap(const_cast(&pixmap), key, options); if (texture) { texture->options |= QGLContext::MemoryManagedBindOption; texture->boundPixmap = pd; diff --git a/src/opengl/qgl_p.h b/src/opengl/qgl_p.h index 45f8f30..1169533 100644 --- a/src/opengl/qgl_p.h +++ b/src/opengl/qgl_p.h @@ -361,7 +361,7 @@ public: quint32 gpm; int screen; QHash boundPixmaps; - QGLTexture *bindTextureFromNativePixmap(QPixmapData*, const qint64 key, + QGLTexture *bindTextureFromNativePixmap(QPixmap*, const qint64 key, QGLContext::BindOptions options); static void destroyGlSurfaceForPixmap(QPixmapData*); static void unbindPixmapFromTexture(QPixmapData*); diff --git a/src/opengl/qgl_x11.cpp b/src/opengl/qgl_x11.cpp index 4fa1467..e1a202f 100644 --- a/src/opengl/qgl_x11.cpp +++ b/src/opengl/qgl_x11.cpp @@ -1671,7 +1671,7 @@ static bool qt_resolveTextureFromPixmap(QPaintDevice *paintDevice) #endif //defined(GLX_VERSION_1_3) && !defined(Q_OS_HPUX) -QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, const qint64 key, +QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key, QGLContext::BindOptions options) { #if !defined(GLX_VERSION_1_3) || defined(Q_OS_HPUX) @@ -1679,12 +1679,12 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData *pmd, con #else Q_Q(QGLContext); - Q_ASSERT(pmd->classId() == QPixmapData::X11Class); + QX11PixmapData *pixmapData = static_cast(pixmap->data_ptr().data()); + Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); if (!qt_resolveTextureFromPixmap(paintDevice)) return 0; - QX11PixmapData *pixmapData = static_cast(pmd); const QX11Info &x11Info = pixmapData->xinfo; // Store the configs (Can be static because configs aren't dependent on current context) diff --git a/src/opengl/qgl_x11egl.cpp b/src/opengl/qgl_x11egl.cpp index 6980281..af0100b 100644 --- a/src/opengl/qgl_x11egl.cpp +++ b/src/opengl/qgl_x11egl.cpp @@ -354,7 +354,7 @@ void QGLWidgetPrivate::recreateEglSurface(bool force) } -QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, const qint64 key, +QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmap *pixmap, const qint64 key, QGLContext::BindOptions options) { Q_Q(QGLContext); @@ -363,7 +363,6 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, cons if (!(options & QGLContext::CanFlipNativePixmapBindOption)) return 0; - Q_ASSERT(pd->classId() == QPixmapData::X11Class); static bool checkedForTFP = false; static bool haveTFP = false; @@ -407,8 +406,8 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, cons return 0; - - QX11PixmapData *pixmapData = static_cast(pd); + QX11PixmapData *pixmapData = static_cast(pixmap->data_ptr().data()); + Q_ASSERT(pixmapData->classId() == QPixmapData::X11Class); bool hasAlpha = pixmapData->hasAlphaChannel(); bool pixmapHasValidSurface = false; bool textureIsBound = false; @@ -440,14 +439,13 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, cons Q_ASSERT(eglCreateImageKHR); EGLImageKHR eglImage; - QPixmap tmpPixmap(pd); EGLint attribs[] = { EGL_IMAGE_PRESERVED_KHR, EGL_TRUE, EGL_NONE }; eglImage = eglCreateImageKHR(QEgl::display(), EGL_NO_CONTEXT, EGL_NATIVE_PIXMAP_KHR, - (EGLClientBuffer)QEgl::nativePixmap(&tmpPixmap), attribs); + (EGLClientBuffer)QEgl::nativePixmap(pixmap), attribs); QGLContext* ctx = q; glEGLImageTargetTexture2DOES(GL_TEXTURE_2D, eglImage); @@ -476,8 +474,7 @@ QGLTexture *QGLContextPrivate::bindTextureFromNativePixmap(QPixmapData* pd, cons QEgl::OpenGL, hasAlpha ? QEgl::Translucent : QEgl::NoOptions); - QPixmap tmpPixmap(pixmapData); //### - pixmapData->gl_surface = (void*)QEgl::createSurface(&tmpPixmap, config); + pixmapData->gl_surface = (void*)QEgl::createSurface(pixmap, config); if (pixmapData->gl_surface == (void*)EGL_NO_SURFACE) return false; } -- cgit v0.12 From f8b0da8c12fcdcb9a820b208c27313cea10d8798 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 26 Mar 2010 13:37:25 +0100 Subject: Remove EGLImage create/destroy resolving from VG pixmap data eglCreateImageKHR and eglDestroyImageKHR are now defined in qegl.cpp and resolved when the display is opened with QEgl::display(). Reviewed-By: Jason Barron --- src/openvg/qpixmapdata_vg.cpp | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/openvg/qpixmapdata_vg.cpp b/src/openvg/qpixmapdata_vg.cpp index e66d80b..7550446 100644 --- a/src/openvg/qpixmapdata_vg.cpp +++ b/src/openvg/qpixmapdata_vg.cpp @@ -42,6 +42,7 @@ #include "qpixmapdata_vg_p.h" #include "qpaintengine_vg_p.h" #include +#include #include "qvg_p.h" #include "qvgimagepool_p.h" @@ -49,8 +50,6 @@ #include #ifdef QT_SYMBIAN_SUPPORTS_SGIMAGE #include -typedef EGLImageKHR (*pfnEglCreateImageKHR)(EGLDisplay, EGLContext, EGLenum, EGLClientBuffer, EGLint*); -typedef EGLBoolean (*pfnEglDestroyImageKHR)(EGLDisplay, EGLImageKHR); typedef VGImage (*pfnVgCreateEGLImageTargetKHR)(VGeglImageKHR); #endif // QT_SYMBIAN_SUPPORTS_SGIMAGE @@ -486,8 +485,6 @@ void QVGPixmapData::fromNativeType(void* pixmap, NativeType type) return; } - pfnEglCreateImageKHR eglCreateImageKHR = (pfnEglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); - pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { @@ -607,8 +604,6 @@ void* QVGPixmapData::toNativeType(NativeType type) return 0; } - pfnEglCreateImageKHR eglCreateImageKHR = (pfnEglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); - pfnEglDestroyImageKHR eglDestroyImageKHR = (pfnEglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); pfnVgCreateEGLImageTargetKHR vgCreateEGLImageTargetKHR = (pfnVgCreateEGLImageTargetKHR) eglGetProcAddress("vgCreateEGLImageTargetKHR"); if (eglGetError() != EGL_SUCCESS || !eglCreateImageKHR || !eglDestroyImageKHR || !vgCreateEGLImageTargetKHR) { -- cgit v0.12 From ed8b490ff07afbca5f23aa19d995c017e2823114 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 26 Mar 2010 15:04:24 +0100 Subject: cetest: remove source file duplicates from cetest.pro epocroot.cpp and registry.cpp are already in qmake_include.pri --- tools/qtestlib/wince/cetest/cetest.pro | 2 -- 1 file changed, 2 deletions(-) diff --git a/tools/qtestlib/wince/cetest/cetest.pro b/tools/qtestlib/wince/cetest/cetest.pro index 4f0baab..43ed18e 100644 --- a/tools/qtestlib/wince/cetest/cetest.pro +++ b/tools/qtestlib/wince/cetest/cetest.pro @@ -37,8 +37,6 @@ HEADERS += \ SOURCES += \ remoteconnection.cpp \ deployment.cpp \ - symbian/epocroot.cpp \ - windows/registry.cpp \ main.cpp LIBS += ole32.lib advapi32.lib -- cgit v0.12 From 454400ff604bcc3cd720ca0487ab6fd4b77d764c Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 26 Mar 2010 16:11:18 +0100 Subject: Round instead of ceil font metrics when ForceIntegerMetrics is enabled This matches how both the simple and complex paths in WebKit handle float to integer conversion, and looks much better. Reviewed-by: Eskil --- src/gui/text/qfontengine_mac.mm | 48 ++++++++++++++++++++--------------------- 1 file changed, 24 insertions(+), 24 deletions(-) diff --git a/src/gui/text/qfontengine_mac.mm b/src/gui/text/qfontengine_mac.mm index 3f84544..0bfdbc0 100644 --- a/src/gui/text/qfontengine_mac.mm +++ b/src/gui/text/qfontengine_mac.mm @@ -306,8 +306,8 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay outAdvances_y[idx] = QFixed::fromReal(tmpPoints[i + 1].y - tmpPoints[i].y); if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - outAdvances_x[idx] = outAdvances_x[idx].ceil(); - outAdvances_y[idx] = outAdvances_y[idx].ceil(); + outAdvances_x[idx] = outAdvances_x[idx].round(); + outAdvances_y[idx] = outAdvances_y[idx].round(); } } CGSize lastGlyphAdvance; @@ -316,7 +316,7 @@ bool QCoreTextFontEngineMulti::stringToCMap(const QChar *str, int len, QGlyphLay outGlyphs[rtl ? 0 : (glyphCount - 1)] = tmpGlyphs[glyphCount - 1] | fontIndex; outAdvances_x[rtl ? 0 : (glyphCount - 1)] = (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(lastGlyphAdvance.width).ceil() + ? QFixed::fromReal(lastGlyphAdvance.width).round() : QFixed::fromReal(lastGlyphAdvance.width); } outGlyphs += glyphCount; @@ -389,7 +389,7 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(const QGlyphLayout &glyphs) QFixed w; for (int i = 0; i < glyphs.numGlyphs; ++i) { w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? glyphs.effectiveAdvance(i).ceil() + ? glyphs.effectiveAdvance(i).round() : glyphs.effectiveAdvance(i); } return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0); @@ -409,8 +409,8 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) ret.yoff = QFixed::fromReal(advances[0].height); if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - ret.xoff = ret.xoff.ceil(); - ret.yoff = ret.yoff.ceil(); + ret.xoff = ret.xoff.round(); + ret.yoff = ret.yoff.round(); } return ret; @@ -419,14 +419,14 @@ glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph) QFixed QCoreTextFontEngine::ascent() const { return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(CTFontGetAscent(ctfont)).ceil() + ? QFixed::fromReal(CTFontGetAscent(ctfont)).round() : QFixed::fromReal(CTFontGetAscent(ctfont)); } QFixed QCoreTextFontEngine::descent() const { QFixed d = QFixed::fromReal(CTFontGetDescent(ctfont)); if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - d = d.ceil(); + d = d.round(); // subtract a pixel to even out the historical +1 in QFontMetrics::height(). // Fix in Qt 5. @@ -435,20 +435,20 @@ QFixed QCoreTextFontEngine::descent() const QFixed QCoreTextFontEngine::leading() const { return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(CTFontGetLeading(ctfont)).ceil() + ? QFixed::fromReal(CTFontGetLeading(ctfont)).round() : QFixed::fromReal(CTFontGetLeading(ctfont)); } QFixed QCoreTextFontEngine::xHeight() const { return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFixed::fromReal(CTFontGetXHeight(ctfont)).ceil() + ? QFixed::fromReal(CTFontGetXHeight(ctfont)).round() : QFixed::fromReal(CTFontGetXHeight(ctfont)); } QFixed QCoreTextFontEngine::averageCharWidth() const { // ### Need to implement properly and get the information from the OS/2 Table. return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? QFontEngine::averageCharWidth().ceil() + ? QFontEngine::averageCharWidth().round() : QFontEngine::averageCharWidth(); } @@ -888,8 +888,8 @@ static OSStatus atsuPostLayoutCallback(ATSULayoutOperationSelector selector, ATS QFixed xAdvance = FixedToQFixed(layoutData[glyphIdx + 1].realPos - layoutData[glyphIdx].realPos); if (nfo->styleStrategy & QFont::ForceIntegerMetrics) { - yAdvance = yAdvance.ceil(); - xAdvance = xAdvance.ceil(); + yAdvance = yAdvance.round(); + xAdvance = xAdvance.round(); } if (glyphId != 0xffff || i == 0) { @@ -1403,8 +1403,8 @@ void QFontEngineMac::recalcAdvances(QGlyphLayout *glyphs, QTextEngine::ShaperFla glyphs->advances_y[i] = QFixed::fromReal(metrics[i].deviceAdvance.y); if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { - glyphs->advances_x[i] = glyphs->advances_x[i].ceil(); - glyphs->advances_y[i] = glyphs->advances_y[i].ceil(); + glyphs->advances_x[i] = glyphs->advances_x[i].round(); + glyphs->advances_y[i] = glyphs->advances_y[i].round(); } } } @@ -1414,7 +1414,7 @@ glyph_metrics_t QFontEngineMac::boundingBox(const QGlyphLayout &glyphs) QFixed w; for (int i = 0; i < glyphs.numGlyphs; ++i) { w += (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? glyphs.effectiveAdvance(i).ceil() + ? glyphs.effectiveAdvance(i).round() : glyphs.effectiveAdvance(i); } return glyph_metrics_t(0, -(ascent()), w, ascent()+descent(), w, 0); @@ -1444,8 +1444,8 @@ glyph_metrics_t QFontEngineMac::boundingBox(glyph_t glyph) if (fontDef.styleStrategy & QFont::ForceIntegerMetrics) { gm.x = gm.x.floor(); gm.y = gm.y.floor(); - gm.xoff = gm.xoff.ceil(); - gm.yoff = gm.yoff.ceil(); + gm.xoff = gm.xoff.round(); + gm.yoff = gm.yoff.round(); } return gm; @@ -1454,7 +1454,7 @@ glyph_metrics_t QFontEngineMac::boundingBox(glyph_t glyph) QFixed QFontEngineMac::ascent() const { return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_ascent.ceil() + ? m_ascent.round() : m_ascent; } @@ -1463,35 +1463,35 @@ QFixed QFontEngineMac::descent() const // subtract a pixel to even out the historical +1 in QFontMetrics::height(). // Fix in Qt 5. return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_descent.ceil() - 1 + ? m_descent.round() - 1 : m_descent; } QFixed QFontEngineMac::leading() const { return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_leading.ceil() + ? m_leading.round() : m_leading; } qreal QFontEngineMac::maxCharWidth() const { return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? qCeil(m_maxCharWidth) + ? qRound(m_maxCharWidth) : m_maxCharWidth; } QFixed QFontEngineMac::xHeight() const { return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_xHeight.ceil() + ? m_xHeight.round() : m_xHeight; } QFixed QFontEngineMac::averageCharWidth() const { return (fontDef.styleStrategy & QFont::ForceIntegerMetrics) - ? m_averageCharWidth.ceil() + ? m_averageCharWidth.round() : m_averageCharWidth; } -- cgit v0.12 From a44026a3885e1505b9206a4d9a47ea21aa6d6787 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 26 Mar 2010 16:32:55 +0100 Subject: Fix build on Windows On unix platforms, QT_NO_EGL is defined by configure. However, this is not defined by windows's configure.exe so add it in opengl.pro. Reviewed-By: Brad --- src/opengl/opengl.pro | 1 + 1 file changed, 1 insertion(+) diff --git a/src/opengl/opengl.pro b/src/opengl/opengl.pro index ff42a49..9473343 100644 --- a/src/opengl/opengl.pro +++ b/src/opengl/opengl.pro @@ -116,6 +116,7 @@ mac { LIBS_PRIVATE += -framework AppKit -framework Carbon } win32:!wince*: { + DEFINES += QT_NO_EGL SOURCES += qgl_win.cpp \ qglpixelbuffer_win.cpp } -- cgit v0.12 From 345e299c512094b50868c9ee71cbba83db593444 Mon Sep 17 00:00:00 2001 From: Thierry Bastian Date: Fri, 26 Mar 2010 16:42:04 +0100 Subject: improve mingw 64 bit support --- src/network/ssl/qsslsocket_openssl.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/network/ssl/qsslsocket_openssl.cpp b/src/network/ssl/qsslsocket_openssl.cpp index 4010710..050fb1b 100644 --- a/src/network/ssl/qsslsocket_openssl.cpp +++ b/src/network/ssl/qsslsocket_openssl.cpp @@ -146,7 +146,7 @@ static void locking_function(int mode, int lockNumber, const char *, int) } static unsigned long id_function() { - return (unsigned long)QThread::currentThreadId(); + return (quintptr)QThread::currentThreadId(); } } // extern "C" -- cgit v0.12 From 0e7a43dba248030c673be5deab8ca70d14c0798f Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Fri, 26 Mar 2010 16:57:48 +0100 Subject: Define QT_NO_EGL in configure.exe This is the "proper" fix for the windows build failure introduced by 75bb84ac. a44026a3 should be reverted once configure.exe is rebuilt to incorperate this fix. Reviewed-By: Marius Storm-Olsen --- tools/configure/configureapp.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 0b14cba..dfd1196 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -3041,6 +3041,10 @@ void Configure::generateConfigfiles() if(dictionary["S60"] == "no") qconfigList += "QT_NO_S60"; if(dictionary["NATIVE_GESTURES"] == "no") qconfigList += "QT_NO_NATIVE_GESTURES"; + if(dictionary["OPENGL_ES_CM"] == "no" && + dictionary["OPENGL_ES_2"] == "no" && + dictionary["OPENVG"] == "no") qconfigList += "QT_NO_EGL"; + if(dictionary["OPENGL_ES_CM"] == "yes" || dictionary["OPENGL_ES_2"] == "yes") qconfigList += "QT_OPENGL_ES"; -- cgit v0.12 From 8db35fe685d115f136bb2ec0305300dd082b278b Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 26 Mar 2010 22:36:34 +0100 Subject: Fix a bug in greek shaping causing infinite loops Update harfbuzz to 33b9cde6a08293d26047734e046c6677a2959adb Reviewed-By: TrustMe AutoTest: qtextscriptengine Task-number: QTBUG-391 --- src/3rdparty/harfbuzz/src/harfbuzz-greek.c | 27 +++++++++------ src/3rdparty/harfbuzz/tests/shaping/main.cpp | 40 ++++++++++++++++++++-- .../qtextscriptengine/tst_qtextscriptengine.cpp | 36 +++++++++++++++++++ 3 files changed, 90 insertions(+), 13 deletions(-) diff --git a/src/3rdparty/harfbuzz/src/harfbuzz-greek.c b/src/3rdparty/harfbuzz/src/harfbuzz-greek.c index 59f3077..2e9b858 100644 --- a/src/3rdparty/harfbuzz/src/harfbuzz-greek.c +++ b/src/3rdparty/harfbuzz/src/harfbuzz-greek.c @@ -77,10 +77,12 @@ static HB_UChar16 compose_0x300(HB_UChar16 base) return 0x1fdd; return 0; } - const hb_greek_decomposition *d = decompose_0x300; - while (d->base && d->base != base) - ++d; - return d->composed; + { + const hb_greek_decomposition *d = decompose_0x300; + while (d->base && d->base != base) + ++d; + return d->composed; + } } static const hb_greek_decomposition decompose_0x301[] = { @@ -115,10 +117,12 @@ static HB_UChar16 compose_0x301(HB_UChar16 base) if (base == 0x1ffe) return 0x1fde; } - const hb_greek_decomposition *d = decompose_0x301; - while (d->base && d->base != base) - ++d; - return d->composed; + { + const hb_greek_decomposition *d = decompose_0x301; + while (d->base && d->base != base) + ++d; + return d->composed; + } } static const hb_greek_decomposition decompose_0x304[] = { @@ -351,8 +355,7 @@ static HB_UChar16 compose_0x345(HB_UChar16 base) */ HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item) { - assert(shaper_item->item.script == HB_Script_Greek); - + const int availableGlyphs = shaper_item->num_glyphs; const HB_UChar16 *uc = shaper_item->string + shaper_item->item.pos; unsigned short *logClusters = shaper_item->log_clusters; HB_GlyphAttributes *attributes = shaper_item->attributes; @@ -363,6 +366,9 @@ HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item) hb_uint32 i; HB_STACKARRAY(HB_UChar16, shapedChars, 2 * shaper_item->item.length); + + assert(shaper_item->item.script == HB_Script_Greek); + *shapedChars = *uc; logClusters[0] = 0; @@ -430,7 +436,6 @@ HB_Bool HB_GreekShape(HB_ShaperItem *shaper_item) #ifndef NO_OPENTYPE if (HB_SelectScript(shaper_item, greek_features)) { - const int availableGlyphs = shaper_item->num_glyphs; HB_OpenTypeShape(shaper_item, /*properties*/0); return HB_OpenTypePosition(shaper_item, availableGlyphs, /*doLogClusters*/TRUE); } diff --git a/src/3rdparty/harfbuzz/tests/shaping/main.cpp b/src/3rdparty/harfbuzz/tests/shaping/main.cpp index b48b0a9..320e8ee 100644 --- a/src/3rdparty/harfbuzz/tests/shaping/main.cpp +++ b/src/3rdparty/harfbuzz/tests/shaping/main.cpp @@ -272,7 +272,6 @@ Shaper::Shaper(FT_Face face, HB_Script script, const QString &str) } -#if defined(Q_WS_X11) static bool decomposedShaping(FT_Face face, HB_Script script, const QChar &ch) { QString uc = QString().append(ch); @@ -318,7 +317,6 @@ static bool decomposedShaping(FT_Face face, HB_Script script, const QChar &ch) qDebug(" decomposed glyph result = %s", str.toLatin1().constData()); return false; } -#endif struct ShapeTable { unsigned short unicode[16]; @@ -382,6 +380,44 @@ void tst_QScriptEngine::greek() continue; QVERIFY( decomposedShaping(face, HB_Script_Greek, QChar(uc)) ); } + FT_Done_Face(face); + } else { + QSKIP("couln't find DejaVu Sans", SkipAll); + } + + + face = loadFace("SBL_grk.ttf"); + if (face) { + for (int uc = 0x1f00; uc <= 0x1fff; ++uc) { + QString str; + str.append(uc); + if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) { + //qDebug() << "skipping" << hex << uc; + continue; + } + if (uc == 0x1fc1 || uc == 0x1fed) + continue; + QVERIFY( decomposedShaping(face, HB_Script_Greek, QChar(uc)) ); + + } + + const ShapeTable shape_table [] = { + { { 0x3b1, 0x300, 0x313, 0x0 }, + { 0xb8, 0x3d3, 0x3c7, 0x0 } }, + { { 0x3b1, 0x313, 0x300, 0x0 }, + { 0xd4, 0x0 } }, + + { {0}, {0} } + }; + + + const ShapeTable *s = shape_table; + while (s->unicode[0]) { + QVERIFY( shaping(face, s, HB_Script_Greek) ); + ++s; + } + + FT_Done_Face(face); } else { QSKIP("couln't find DejaVu Sans", SkipAll); } diff --git a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp index 841f5b9..018c036 100644 --- a/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp +++ b/tests/auto/qtextscriptengine/tst_qtextscriptengine.cpp @@ -1068,6 +1068,42 @@ void tst_QTextScriptEngine::greek() QSKIP("couln't find DejaVu Sans", SkipAll); } } + + { + if (QFontDatabase().families(QFontDatabase::Any).contains("SBL Greek")) { + QFont f("SBL Greek"); + for (int uc = 0x1f00; uc <= 0x1fff; ++uc) { + QString str; + str.append(uc); + if (str.normalized(QString::NormalizationForm_D).normalized(QString::NormalizationForm_C) != str) { + //qDebug() << "skipping" << hex << uc; + continue; + } + if (uc == 0x1fc1 || uc == 0x1fed) + continue; + QVERIFY( decomposedShaping(f, QChar(uc) ) ); + + } + + const ShapeTable shape_table [] = { + { { 0x3b1, 0x300, 0x313, 0x0 }, + { 0xb8, 0x3d3, 0x3c7, 0x0 } }, + { { 0x3b1, 0x313, 0x300, 0x0 }, + { 0xd4, 0x0 } }, + + { {0}, {0} } + }; + + + const ShapeTable *s = shape_table; + while (s->unicode[0]) { + QVERIFY( shaping(f, s) ); + ++s; + } + } else { + QSKIP("couln't find SBL_grk", SkipAll); + } + } #else QSKIP("X11 specific test", SkipAll); #endif -- cgit v0.12 From d8419cf58ffea2b9cab4986389472c991e2a2f63 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Mon, 29 Mar 2010 08:18:09 +0200 Subject: Protect EGLImage function definitions in #ifdef This should fix the build on Symbian. Reviewed-By: TrustMe --- src/gui/egl/qegl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 507fab3..3417781 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -528,8 +528,10 @@ QEglProperties QEglContext::configProperties() const return QEglProperties(config()); } +#if !defined(EGL_KHR_image) || !defined(EGL_KHR_image_base) _eglCreateImageKHR eglCreateImageKHR = 0; _eglDestroyImageKHR eglDestroyImageKHR = 0; +#endif EGLDisplay QEgl::display() { -- cgit v0.12 From 0056c0a654a930fe082787ec7e8579a6e74d9ad5 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Mon, 29 Mar 2010 08:35:39 +0200 Subject: Change ORs to ANDs when checking EGLImage extension defines We should only define the EGLImage functions if both EGL_KHR_image _and_ EGL_KHR_image_base are undefined. Reviewed-By: TrustMe --- src/gui/egl/qegl.cpp | 2 +- src/gui/egl/qegl_p.h | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 3417781..9a552cf 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -528,7 +528,7 @@ QEglProperties QEglContext::configProperties() const return QEglProperties(config()); } -#if !defined(EGL_KHR_image) || !defined(EGL_KHR_image_base) +#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base) _eglCreateImageKHR eglCreateImageKHR = 0; _eglDestroyImageKHR eglDestroyImageKHR = 0; #endif diff --git a/src/gui/egl/qegl_p.h b/src/gui/egl/qegl_p.h index b570329..c659796 100644 --- a/src/gui/egl/qegl_p.h +++ b/src/gui/egl/qegl_p.h @@ -110,7 +110,7 @@ QT_BEGIN_NAMESPACE #define EGLAPIENTRY #endif -#if !defined(EGL_KHR_image) || !defined(EGL_KHR_image_base) +#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base) typedef void *EGLImageKHR; #define EGL_NO_IMAGE_KHR ((EGLImageKHR)0) @@ -123,9 +123,9 @@ typedef EGLBoolean (EGLAPIENTRY *_eglDestroyImageKHR)(EGLDisplay, EGLImageKHR); extern Q_GUI_EXPORT _eglCreateImageKHR eglCreateImageKHR; extern Q_GUI_EXPORT _eglDestroyImageKHR eglDestroyImageKHR; -#endif // !defined(EGL_KHR_image) || !defined(EGL_KHR_image_base) +#endif // !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base) -#if !defined(EGL_KHR_image) || !defined(EGL_KHR_image_pixmap) +#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_pixmap) #define EGL_NATIVE_PIXMAP_KHR 0x30B0 #endif -- cgit v0.12 From 62b082833d904688e44e1bac4849bfa54bf5fe82 Mon Sep 17 00:00:00 2001 From: Tom Cooksey Date: Mon, 29 Mar 2010 12:21:40 +0200 Subject: Don't try to resolve EGLImage function pointers if they are defined We assume the presence of EGL_KHR_image or EGL_KHR_image_base means that the eglCreateImageKHR/eglDestroyImageKHR methods are exported by the EGL library and thus do not need to be resolved. Reviewed-By: TrustMe --- src/gui/egl/qegl.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/egl/qegl.cpp b/src/gui/egl/qegl.cpp index 9a552cf..f36904d 100644 --- a/src/gui/egl/qegl.cpp +++ b/src/gui/egl/qegl.cpp @@ -556,10 +556,12 @@ EGLDisplay QEgl::display() } // Resolve the egl extension function pointers: +#if !defined(EGL_KHR_image) && !defined(EGL_KHR_image_base) if (QEgl::hasExtension("EGL_KHR_image") || QEgl::hasExtension("EGL_KHR_image_base")) { eglCreateImageKHR = (_eglCreateImageKHR) eglGetProcAddress("eglCreateImageKHR"); eglDestroyImageKHR = (_eglDestroyImageKHR) eglGetProcAddress("eglDestroyImageKHR"); } +#endif } return dpy; -- cgit v0.12 From 809583a34cb69367ecb4218f798a5928de9aacec Mon Sep 17 00:00:00 2001 From: Olivier Goffart Date: Mon, 29 Mar 2010 10:34:23 +0200 Subject: QVarLenghtArray: add some API to be consistant to QVector That way it is easier to have QVarLenghtArray as a drop-in replacement for QVector Reviewed-by: Joao --- src/corelib/tools/qvarlengtharray.h | 19 +++++++++++++ src/corelib/tools/qvarlengtharray.qdoc | 32 +++++++++++++++++++++- tests/auto/qvarlengtharray/tst_qvarlengtharray.cpp | 13 +++++++++ 3 files changed, 63 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qvarlengtharray.h b/src/corelib/tools/qvarlengtharray.h index aecb66e..9773d4b 100644 --- a/src/corelib/tools/qvarlengtharray.h +++ b/src/corelib/tools/qvarlengtharray.h @@ -107,6 +107,10 @@ public: Q_ASSERT(idx >= 0 && idx < s); return ptr[idx]; } + inline const T &at(int idx) const { return operator[](idx); } + + T value(int i) const; + T value(int i, const T &defaultValue) const; inline void append(const T &t) { if (s == a) // i.e. s != 0 @@ -248,6 +252,21 @@ Q_OUTOFLINE_TEMPLATE void QVarLengthArray::realloc(int asize, int a } } +template +Q_OUTOFLINE_TEMPLATE T QVarLengthArray::value(int i) const +{ + if (i < 0 || i >= size()) { + return T(); + } + return at(i); +} +template +Q_OUTOFLINE_TEMPLATE T QVarLengthArray::value(int i, const T &defaultValue) const +{ + return (i < 0 || i >= size()) ? defaultValue : at(i); +} + + QT_END_NAMESPACE QT_END_HEADER diff --git a/src/corelib/tools/qvarlengtharray.qdoc b/src/corelib/tools/qvarlengtharray.qdoc index bb7a3de..38901e5 100644 --- a/src/corelib/tools/qvarlengtharray.qdoc +++ b/src/corelib/tools/qvarlengtharray.qdoc @@ -197,7 +197,7 @@ \a i must be a valid index position in the array (i.e., 0 <= \a i < size()). - \sa data() + \sa data(), at() */ /*! \fn const T &QVarLengthArray::operator[](int i) const @@ -272,3 +272,33 @@ Constructs a copy of \a other. */ +/*! \fn const T &QVarLengthArray::at(int i) const + + Returns a reference to the item at index position \a i. + + \a i must be a valid index position in the array (i.e., 0 <= \a i + < size()). + + \sa value(), operator[]() +*/ + +/*! \fn T QVarLengthArray::value(int i) const + + Returns the value at index position \a i. + + If the index \a i is out of bounds, the function returns + a \l{default-constructed value}. If you are certain that + \a i is within bounds, you can use at() instead, which is slightly + faster. + + \sa at(), operator[]() +*/ + +/*! \fn T QVarLengthArray::value(int i, const T &defaultValue) const + + \overload + + If the index \a i is out of bounds, the function returns + \a defaultValue. +*/ + diff --git a/tests/auto/qvarlengtharray/tst_qvarlengtharray.cpp b/tests/auto/qvarlengtharray/tst_qvarlengtharray.cpp index 1c43069..5708726 100644 --- a/tests/auto/qvarlengtharray/tst_qvarlengtharray.cpp +++ b/tests/auto/qvarlengtharray/tst_qvarlengtharray.cpp @@ -133,6 +133,12 @@ void tst_QVarLengthArray::oldTests() QVERIFY(sa.data() == &sa[0]); QVERIFY(sa[0] == 0xfee); QVERIFY(sa[10] == 0xff); + QVERIFY(sa.at(0) == 0xfee); + QVERIFY(sa.at(10) == 0xff); + QVERIFY(sa.value(0) == 0xfee); + QVERIFY(sa.value(10) == 0xff); + QVERIFY(sa.value(1000) == 0); + QVERIFY(sa.value(1000, 12) == 12); QVERIFY(sa.size() == 512); sa.reserve(1024); QVERIFY(sa.capacity() == 1024); @@ -168,6 +174,13 @@ void tst_QVarLengthArray::oldTests() QCOMPARE(sa.size(), 12); QCOMPARE(sa[10], QString("hello")); QCOMPARE(sa[11], QString("world")); + QCOMPARE(sa.at(10), QString("hello")); + QCOMPARE(sa.at(11), QString("world")); + QCOMPARE(sa.value(10), QString("hello")); + QCOMPARE(sa.value(11), QString("world")); + QCOMPARE(sa.value(10000), QString()); + QCOMPARE(sa.value(1212112, QString("none")), QString("none")); + QCOMPARE(sa.value(-12, QString("neg")), QString("neg")); sa.append(arr, 1); QCOMPARE(sa.size(), 13); -- cgit v0.12