From 1880fba971ed8ae8e813829ff3668132371e88a7 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 29 Jul 2019 14:16:00 +0200 Subject: Android: Fix QMenu on 64 bit The platform menu tags in Qt are actually the pointers, so they are 64-bit values when the build is 64 bit. Since menu IDs in Android are 32-bit ints, we cannot cast back and forth like we do. To fix this, we add a separate hash of menu IDs to allow mapping between Java and C++. For easier book-keeping, we add the hashes to the menu bar and menu classes, so that we can easily recycle old menu IDs when they are no longer in use. Note that overriding the tag on the menus by calling setTag() will not work, since Qt Widgets will later override it again by setting it back to the menu's pointer. [ChangeLog][Android] Fixed an issue where menus would not work on 64 bit builds. Task-number: QTBUG-76036 Change-Id: Icaa1d235d4166331669139251656ea0159e85195 Reviewed-by: Frederik Gladhorn --- src/plugins/platforms/android/androidjnimenu.cpp | 12 +++--- .../platforms/android/qandroidplatformmenu.cpp | 43 +++++++++++++++++++--- .../platforms/android/qandroidplatformmenu.h | 5 +++ .../platforms/android/qandroidplatformmenubar.cpp | 34 ++++++++++++++++- .../platforms/android/qandroidplatformmenubar.h | 6 +++ 5 files changed, 88 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/android/androidjnimenu.cpp b/src/plugins/platforms/android/androidjnimenu.cpp index 6f548aba52..e9359def0f 100644 --- a/src/plugins/platforms/android/androidjnimenu.cpp +++ b/src/plugins/platforms/android/androidjnimenu.cpp @@ -225,10 +225,11 @@ namespace QtAndroidMenu QString itemText = removeAmpersandEscapes(item->text()); jstring jtext = env->NewString(reinterpret_cast(itemText.data()), itemText.length()); + jint menuId = platformMenu->menuId(item); jobject menuItem = env->CallObjectMethod(menu, addMenuItemMethodID, menuNoneValue, - int(item->tag()), + menuId, order++, jtext); env->DeleteLocalRef(jtext); @@ -262,10 +263,11 @@ namespace QtAndroidMenu QString itemText = removeAmpersandEscapes(item->text()); jstring jtext = env->NewString(reinterpret_cast(itemText.data()), itemText.length()); + jint menuId = visibleMenuBar->menuId(item); jobject menuItem = env->CallObjectMethod(menu, addMenuItemMethodID, menuNoneValue, - int(item->tag()), + menuId, order++, jtext); env->DeleteLocalRef(jtext); @@ -290,7 +292,7 @@ namespace QtAndroidMenu const QAndroidPlatformMenuBar::PlatformMenusType &menus = visibleMenuBar->menus(); if (menus.size() == 1) { // Expanded menu - QAndroidPlatformMenuItem *item = static_cast(menus.front()->menuItemForTag(menuId)); + QAndroidPlatformMenuItem *item = static_cast(menus.front()->menuItemForId(menuId)); if (item) { if (item->menu()) { showContextMenu(item->menu(), QRect(), env); @@ -301,7 +303,7 @@ namespace QtAndroidMenu } } } else { - QAndroidPlatformMenu *menu = static_cast(visibleMenuBar->menuForTag(menuId)); + QAndroidPlatformMenu *menu = static_cast(visibleMenuBar->menuForId(menuId)); if (menu) showContextMenu(menu, QRect(), env); } @@ -341,7 +343,7 @@ namespace QtAndroidMenu static jboolean onContextItemSelected(JNIEnv *env, jobject /*thiz*/, jint menuId, jboolean checked) { QMutexLocker lock(&visibleMenuMutex); - QAndroidPlatformMenuItem * item = static_cast(visibleMenu->menuItemForTag(menuId)); + QAndroidPlatformMenuItem * item = static_cast(visibleMenu->menuItemForId(menuId)); if (item) { if (item->menu()) { showContextMenu(item->menu(), QRect(), env); diff --git a/src/plugins/platforms/android/qandroidplatformmenu.cpp b/src/plugins/platforms/android/qandroidplatformmenu.cpp index d9cecebf2c..7ce603831f 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenu.cpp @@ -62,6 +62,7 @@ void QAndroidPlatformMenu::insertMenuItem(QPlatformMenuItem *menuItem, QPlatform m_menuItems.end(), static_cast(before)), static_cast(menuItem)); + m_menuHash.insert(m_nextMenuId++, menuItem); } void QAndroidPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem) @@ -72,6 +73,21 @@ void QAndroidPlatformMenu::removeMenuItem(QPlatformMenuItem *menuItem) static_cast(menuItem)); if (it != m_menuItems.end()) m_menuItems.erase(it); + + { + int maxId = -1; + QHash::iterator it = m_menuHash.begin(); + while (it != m_menuHash.end()) { + if (it.value() == menuItem) { + it = m_menuHash.erase(it); + } else { + maxId = qMax(maxId, it.key()); + ++it; + } + } + + m_nextMenuId = maxId + 1; + } } void QAndroidPlatformMenu::syncMenuItem(QPlatformMenuItem *menuItem) @@ -139,6 +155,16 @@ void QAndroidPlatformMenu::showPopup(const QWindow *parentWindow, const QRect &t QtAndroidMenu::showContextMenu(this, targetRect, QJNIEnvironmentPrivate()); } +QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const +{ + for (QAndroidPlatformMenuItem *menuItem : m_menuItems) { + if (menuItem->tag() == tag) + return menuItem; + } + + return nullptr; +} + QPlatformMenuItem *QAndroidPlatformMenu::menuItemAt(int position) const { if (position < m_menuItems.size()) @@ -146,13 +172,20 @@ QPlatformMenuItem *QAndroidPlatformMenu::menuItemAt(int position) const return 0; } -QPlatformMenuItem *QAndroidPlatformMenu::menuItemForTag(quintptr tag) const +int QAndroidPlatformMenu::menuId(QPlatformMenuItem *menu) const { - for (QPlatformMenuItem *menuItem : m_menuItems) { - if (menuItem->tag() == tag) - return menuItem; + QHash::const_iterator it; + for (it = m_menuHash.constBegin(); it != m_menuHash.constEnd(); ++it) { + if (it.value() == menu) + return it.key(); } - return 0; + + return -1; +} + +QPlatformMenuItem *QAndroidPlatformMenu::menuItemForId(int menuId) const +{ + return m_menuHash.value(menuId); } QAndroidPlatformMenu::PlatformMenuItemsType QAndroidPlatformMenu::menuItems() const diff --git a/src/plugins/platforms/android/qandroidplatformmenu.h b/src/plugins/platforms/android/qandroidplatformmenu.h index 47e650f2d7..b1d6a88787 100644 --- a/src/plugins/platforms/android/qandroidplatformmenu.h +++ b/src/plugins/platforms/android/qandroidplatformmenu.h @@ -73,6 +73,8 @@ public: QPlatformMenuItem *menuItemAt(int position) const override; QPlatformMenuItem *menuItemForTag(quintptr tag) const override; + QPlatformMenuItem *menuItemForId(int menuId) const; + int menuId(QPlatformMenuItem *menuItem) const; PlatformMenuItemsType menuItems() const; QMutex *menuItemsMutex(); @@ -84,6 +86,9 @@ private: bool m_enabled; bool m_isVisible; QMutex m_menuItemsMutex; + + int m_nextMenuId = 0; + QHash m_menuHash; }; QT_END_NAMESPACE diff --git a/src/plugins/platforms/android/qandroidplatformmenubar.cpp b/src/plugins/platforms/android/qandroidplatformmenubar.cpp index 35930f0628..7c6299b4b7 100644 --- a/src/plugins/platforms/android/qandroidplatformmenubar.cpp +++ b/src/plugins/platforms/android/qandroidplatformmenubar.cpp @@ -61,6 +61,7 @@ void QAndroidPlatformMenuBar::insertMenu(QPlatformMenu *menu, QPlatformMenu *bef m_menus.end(), static_cast(before)), static_cast(menu)); + m_menuHash.insert(m_nextMenuId++, menu); } void QAndroidPlatformMenuBar::removeMenu(QPlatformMenu *menu) @@ -69,6 +70,30 @@ void QAndroidPlatformMenuBar::removeMenu(QPlatformMenu *menu) m_menus.erase(std::find(m_menus.begin(), m_menus.end(), static_cast(menu))); + + int maxId = -1; + QHash::iterator it = m_menuHash.begin(); + while (it != m_menuHash.end()) { + if (it.value() == menu) { + it = m_menuHash.erase(it); + } else { + maxId = qMax(maxId, it.key()); + ++it; + } + } + + m_nextMenuId = maxId + 1; +} + +int QAndroidPlatformMenuBar::menuId(QPlatformMenu *menu) const +{ + QHash::const_iterator it; + for (it = m_menuHash.constBegin(); it != m_menuHash.constEnd(); ++it) { + if (it.value() == menu) + return it.key(); + } + + return -1; } void QAndroidPlatformMenuBar::syncMenu(QPlatformMenu *menu) @@ -86,12 +111,17 @@ void QAndroidPlatformMenuBar::handleReparent(QWindow *newParentWindow) QPlatformMenu *QAndroidPlatformMenuBar::menuForTag(quintptr tag) const { - for (QPlatformMenu *menu : m_menus) { + for (QAndroidPlatformMenu *menu : m_menus) { if (menu->tag() == tag) return menu; } - return 0; + return nullptr; +} + +QPlatformMenu *QAndroidPlatformMenuBar::menuForId(int menuId) const +{ + return m_menuHash.value(menuId); } QWindow *QAndroidPlatformMenuBar::parentWindow() const diff --git a/src/plugins/platforms/android/qandroidplatformmenubar.h b/src/plugins/platforms/android/qandroidplatformmenubar.h index f5935b8177..81a26c72f4 100644 --- a/src/plugins/platforms/android/qandroidplatformmenubar.h +++ b/src/plugins/platforms/android/qandroidplatformmenubar.h @@ -43,6 +43,7 @@ #include #include #include +#include QT_BEGIN_NAMESPACE @@ -60,6 +61,8 @@ public: void syncMenu(QPlatformMenu *menu) override; void handleReparent(QWindow *newParentWindow) override; QPlatformMenu *menuForTag(quintptr tag) const override; + QPlatformMenu *menuForId(int menuId) const; + int menuId(QPlatformMenu *menu) const; QWindow *parentWindow() const override; PlatformMenusType menus() const; @@ -69,6 +72,9 @@ private: PlatformMenusType m_menus; QWindow *m_parentWindow; QMutex m_menusListMutex; + + int m_nextMenuId = 0; + QHash m_menuHash; }; QT_END_NAMESPACE -- cgit v1.2.3 From 79e0effead13f60676bb5170fe92615d981827e7 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Wed, 7 Aug 2019 15:25:49 +0200 Subject: Fix crash in QTextDocument::clearUndoRedoStacks() When calling QTextDocument::clearUndoRedoStacks() with UndoStack, there were two bugs: The first was that we were retrieving the item at "undoState" and deleting this. This is actually the upper limit of the for loop. If the stack does not contain any redos, then it would be == undoStack.size() and we would assert. If there were redos, then we would delete the item at undoState multiple times (actually undoState times). In addition, when the loop exited, we first removed the dangling pointers using remove() and then there was a weird resize() to the new size minus the old undoState. This would either assert because we tried to resize to a negative number, or it would arbitrarily remove items from the stack. [ChangeLog][QtGui][Text] Fixed a crash bug in QTextDocument::clearUndoRedoStacks(QTextDocument::UndoStack). Task-number: QTBUG-69546 Change-Id: I8a93e828ec27970763a2756071fa0b01678d2dcd Reviewed-by: Simon Hausmann Reviewed-by: Konstantin Ritt --- src/gui/text/qtextdocument_p.cpp | 3 +-- tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp | 13 +++++++++++++ 2 files changed, 14 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qtextdocument_p.cpp b/src/gui/text/qtextdocument_p.cpp index 66e038122c..059e665d12 100644 --- a/src/gui/text/qtextdocument_p.cpp +++ b/src/gui/text/qtextdocument_p.cpp @@ -1103,12 +1103,11 @@ void QTextDocumentPrivate::clearUndoRedoStacks(QTextDocument::Stacks stacksToCle bool redoCommandsAvailable = undoState != undoStack.size(); if (stacksToClear == QTextDocument::UndoStack && undoCommandsAvailable) { for (int i = 0; i < undoState; ++i) { - QTextUndoCommand c = undoStack.at(undoState); + QTextUndoCommand c = undoStack.at(i); if (c.command & QTextUndoCommand::Custom) delete c.custom; } undoStack.remove(0, undoState); - undoStack.resize(undoStack.size() - undoState); undoState = 0; if (emitSignals) emitUndoAvailable(false); diff --git a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp index 32131352c3..c04c841376 100644 --- a/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp +++ b/tests/auto/gui/text/qtextdocument/tst_qtextdocument.cpp @@ -188,6 +188,8 @@ private slots: void lineHeightType(); void cssLineHeightMultiplier(); + + void clearUndoRedoStacks(); private: void backgroundImage_checkExpectedHtml(const QTextDocument &doc); void buildRegExpData(); @@ -3486,5 +3488,16 @@ void tst_QTextDocument::cssLineHeightMultiplier() } } +void tst_QTextDocument::clearUndoRedoStacks() +{ + QTextDocument doc; + QTextCursor c(&doc); + c.insertText(QStringLiteral("lorem ipsum")); + QVERIFY(doc.isUndoAvailable()); + doc.clearUndoRedoStacks(QTextDocument::UndoStack); // Don't crash + QVERIFY(!doc.isUndoAvailable()); +} + + QTEST_MAIN(tst_QTextDocument) #include "tst_qtextdocument.moc" -- cgit v1.2.3 From a3dec41cf1c8078e11eae90167a0282eba2ce084 Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Tue, 30 Jul 2019 10:19:44 +0200 Subject: Add attribution for AGLFN We were missing attribution for the AGLFN tables. Task-number: QTBUG-70968 Change-Id: Ib84cbd25c9f7c49611761c9eba16624de5b77dd2 Reviewed-by: Lars Knoll --- src/gui/text/AGLFN_LICENSE.txt | 26 ++++++++++++++++++++++++++ src/gui/text/qt_attribution.json | 17 +++++++++++++++++ 2 files changed, 43 insertions(+) create mode 100644 src/gui/text/AGLFN_LICENSE.txt create mode 100644 src/gui/text/qt_attribution.json diff --git a/src/gui/text/AGLFN_LICENSE.txt b/src/gui/text/AGLFN_LICENSE.txt new file mode 100644 index 0000000000..50abffca15 --- /dev/null +++ b/src/gui/text/AGLFN_LICENSE.txt @@ -0,0 +1,26 @@ +Redistribution and use in source and binary forms, with or without +modification, are permitted provided that the following conditions are +met: + +Redistributions of source code must retain the above copyright notice, +this list of conditions and the following disclaimer. + +Redistributions in binary form must reproduce the above copyright +notice, this list of conditions and the following disclaimer in the +documentation and/or other materials provided with the distribution. + +Neither the name of Adobe Systems Incorporated nor the names of its +contributors may be used to endorse or promote products derived from +this software without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS +"AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT +LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR +A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT +HOLDER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, +SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT +LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, +DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY +THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE +OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. diff --git a/src/gui/text/qt_attribution.json b/src/gui/text/qt_attribution.json new file mode 100644 index 0000000000..c3a57267e2 --- /dev/null +++ b/src/gui/text/qt_attribution.json @@ -0,0 +1,17 @@ +[ + { + "Id": "aglfn", + "Name": "Adobe Glyph List For New Fonts", + "QDocModule": "qtgui", + "Description": "Provides standardized names for glyphs.", + "QtUsage": "Used by PDF generator to make it easier for reader applications to resolve the original contents of rendered text.", + "Path": "qfontsubset_agl.cpp", + + "Homepage": "https://github.com/adobe-type-tools/agl-aglfn", + "Version": "1.7", + "License": "BSD 3-Clause \"New\" or \"Revised\" License", + "LicenseId": "BSD-3-Clause", + "LicenseFile": "AGLFN_LICENSE.txt", + "Copyright": "Copyright 2002, 2003, 2005, 2006, 2008, 2010, 2015 Adobe Systems" + } +] -- cgit v1.2.3 From 4d9375020c59282b447aad5189c2adb12931e4a1 Mon Sep 17 00:00:00 2001 From: Jason Haslam Date: Tue, 18 Jun 2019 11:51:38 -0600 Subject: macOS: Fix tab button rendering issue This fixes rendering artifacts for the specific case of the first unselected vertical (west) tab button in a tab bar. The popup button gets drawn at the beginning of the tab bar instead of translated to the actual location of the tab. Fixes: QTBUG-76385 Change-Id: I17112c56eabacf34e470314d4cc6b263ba632ec1 Reviewed-by: Timur Pocheptsov --- src/plugins/styles/mac/qmacstyle_mac.mm | 1 + 1 file changed, 1 insertion(+) diff --git a/src/plugins/styles/mac/qmacstyle_mac.mm b/src/plugins/styles/mac/qmacstyle_mac.mm index 1ff1c22788..07651fc206 100644 --- a/src/plugins/styles/mac/qmacstyle_mac.mm +++ b/src/plugins/styles/mac/qmacstyle_mac.mm @@ -3944,6 +3944,7 @@ void QMacStyle::drawControl(ControlElement ce, const QStyleOption *opt, QPainter CGContextScaleCTM(ctx, -1, 1); CGContextTranslateCTM(ctx, -frameRect.left(), 0); } else if (tabDirection == QMacStylePrivate::West && tp == QStyleOptionTab::Beginning) { + CGContextTranslateCTM(ctx, 0, opt->rect.top()); CGContextScaleCTM(ctx, 1, -1); CGContextTranslateCTM(ctx, 0, -frameRect.right()); } else if (tabDirection == QMacStylePrivate::East && tp == QStyleOptionTab::End) { -- cgit v1.2.3 From ca20b449592ed05eca0c476d2fcf5d0851d92c36 Mon Sep 17 00:00:00 2001 From: Ville Voutilainen Date: Tue, 6 Aug 2019 10:50:52 +0300 Subject: A GCC 4.8 build fix Change-Id: Ic128486711118e1124739e8dca30547ab8ba9816 Reviewed-by: Simon Hausmann --- tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp index 5b4a5d30a5..d13c145189 100644 --- a/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp +++ b/tests/auto/widgets/kernel/qapplication/tst_qapplication.cpp @@ -486,7 +486,7 @@ void tst_QApplication::lastWindowClosed() QPointer dialog = new QDialog; dialog->setWindowTitle(QLatin1String(QTest::currentTestFunction()) + QLatin1String("Dialog")); QVERIFY(dialog->testAttribute(Qt::WA_QuitOnClose)); - QTimer::singleShot(1000, dialog, &QDialog::accept); + QTimer::singleShot(1000, dialog.data(), &QDialog::accept); dialog->exec(); QVERIFY(dialog); QCOMPARE(spy.count(), 0); -- cgit v1.2.3 From 6ac610c79bf7f311ee244d45583eb669ada58781 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Wed, 31 Jul 2019 15:42:46 +0200 Subject: Allow specifying explicit SDK version on Apple platforms MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This enables building against the latest SDK, while still opting out of features that this SDK normally enables, by lowering the SDK version set in the BUILD_VERSION/VERSION_MIN_MACOSX load command. Change-Id: Id5f13524740bfbf5eda10a5d0c2e3fda04bf3f52 Reviewed-by: Jörg Bornemann Reviewed-by: Morten Johan Sørvig Reviewed-by: Timur Pocheptsov --- mkspecs/features/mac/default_post.prf | 11 ++++++++++- 1 file changed, 10 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/mac/default_post.prf b/mkspecs/features/mac/default_post.prf index f34b305d08..60b2eb2117 100644 --- a/mkspecs/features/mac/default_post.prf +++ b/mkspecs/features/mac/default_post.prf @@ -1,5 +1,9 @@ load(default_post) +# Recompute SDK version in case the user set it explicitly +sdk_version = $$QMAKE_MAC_SDK_VERSION +QMAKE_MAC_SDK_VERSION = $$xcodeSDKInfo(SDKVersion) + contains(TEMPLATE, .*app) { !macx-xcode:if(isEmpty(BUILDS)|build_pass) { # Detect changes to the platform SDK @@ -14,7 +18,7 @@ contains(TEMPLATE, .*app) { !versionAtLeast(QMAKE_MAC_SDK_VERSION, $$QT_MAC_SDK_VERSION_MIN): \ warning("Qt requires at least version $$QT_MAC_SDK_VERSION_MIN of the platform SDK," \ - "you're using $${QMAKE_MAC_SDK_VERSION}. Please upgrade.") + "you're building against version $${QMAKE_MAC_SDK_VERSION}. Please upgrade.") !isEmpty(QT_MAC_SDK_VERSION_MAX) { # For Qt developers only @@ -244,6 +248,11 @@ macx-xcode { QMAKE_PCH_OUTPUT_EXT = _${QMAKE_PCH_ARCH}$${QMAKE_PCH_OUTPUT_EXT} } +!equals(sdk_version, $$QMAKE_MAC_SDK_VERSION) { + # Explicit SDK version has been set, respect that + QMAKE_LFLAGS += -Wl,-sdk_version -Wl,$$sdk_version +} + cache(QMAKE_XCODE_DEVELOPER_PATH, stash) !isEmpty(QMAKE_XCODE_VERSION): \ cache(QMAKE_XCODE_VERSION, stash) -- cgit v1.2.3 From afb326f07109da0035112e6f56e683e37b8a5d72 Mon Sep 17 00:00:00 2001 From: Lars Knoll Date: Fri, 17 Nov 2017 10:59:47 +0100 Subject: Refactor lockedAlphaMapForGlyph Simply return a Glyph pointer and not a QImage to avoid allocating and deleting lots of d pointers for QImage when drawing text. Saves one new/delete pair per glyph drawn and speeds up text drawing by 10% for relatively large glyphs (probably more for smaller ones). The qtext::paintLayoutToPixmap() benchmark shows a 16% improvement in performance with this change. Renamed the method to glyphData(). Change-Id: I7a353de521e4f4321c770fb1ac6043d33f6f332c Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/painting/qpaintengine_raster.cpp | 35 ++++++++++++------ src/gui/text/qfontengine.cpp | 25 ++----------- src/gui/text/qfontengine_p.h | 23 ++++++++---- .../fontdatabases/freetype/qfontengine_ft.cpp | 41 ++++------------------ .../fontdatabases/freetype/qfontengine_ft_p.h | 20 ++--------- 5 files changed, 53 insertions(+), 91 deletions(-) diff --git a/src/gui/painting/qpaintengine_raster.cpp b/src/gui/painting/qpaintengine_raster.cpp index 096e4a5c5b..885c46e121 100644 --- a/src/gui/painting/qpaintengine_raster.cpp +++ b/src/gui/painting/qpaintengine_raster.cpp @@ -2908,19 +2908,34 @@ bool QRasterPaintEngine::drawCachedGlyphs(int numGlyphs, const glyph_t *glyphs, for (int i = 0; i < numGlyphs; i++) { QFixed spp = fontEngine->subPixelPositionForX(positions[i].x); - QPoint offset; - const QImage *alphaMap = fontEngine->lockedAlphaMapForGlyph(glyphs[i], spp, neededFormat, s->matrix, - &offset); - if (alphaMap == 0 || alphaMap->isNull()) + const QFontEngine::Glyph *alphaMap = fontEngine->glyphData(glyphs[i], spp, neededFormat, s->matrix); + if (!alphaMap) continue; - alphaPenBlt(alphaMap->constBits(), alphaMap->bytesPerLine(), alphaMap->depth(), - qFloor(positions[i].x) + offset.x(), - qRound(positions[i].y) + offset.y(), - alphaMap->width(), alphaMap->height(), + int depth; + int bytesPerLine; + switch (alphaMap->format) { + case QFontEngine::Format_Mono: + depth = 1; + bytesPerLine = ((alphaMap->width + 31) & ~31) >> 3; + break; + case QFontEngine::Format_A8: + depth = 8; + bytesPerLine = (alphaMap->width + 3) & ~3; + break; + case QFontEngine::Format_A32: + depth = 32; + bytesPerLine = alphaMap->width * 4; + break; + default: + Q_UNREACHABLE(); + }; + + alphaPenBlt(alphaMap->data, bytesPerLine, depth, + qFloor(positions[i].x) + alphaMap->x, + qRound(positions[i].y) - alphaMap->y, + alphaMap->width, alphaMap->height, fontEngine->expectsGammaCorrectedBlending()); - - fontEngine->unlockAlphaMapForGlyph(); } } else { diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp index 5506d88f02..1895ac8283 100644 --- a/src/gui/text/qfontengine.cpp +++ b/src/gui/text/qfontengine.cpp @@ -923,29 +923,10 @@ QFixed QFontEngine::subPixelPositionForX(QFixed x) const return subPixelPosition; } -QImage *QFontEngine::lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, - QFontEngine::GlyphFormat neededFormat, - const QTransform &t, QPoint *offset) +QFontEngine::Glyph *QFontEngine::glyphData(glyph_t, QFixed, + QFontEngine::GlyphFormat, const QTransform &) { - Q_ASSERT(currentlyLockedAlphaMap.isNull()); - if (neededFormat == Format_None) - neededFormat = Format_A32; - - if (neededFormat != Format_A32) - currentlyLockedAlphaMap = alphaMapForGlyph(glyph, subPixelPosition, t); - else - currentlyLockedAlphaMap = alphaRGBMapForGlyph(glyph, subPixelPosition, t); - - if (offset != 0) - *offset = QPoint(0, 0); - - return ¤tlyLockedAlphaMap; -} - -void QFontEngine::unlockAlphaMapForGlyph() -{ - Q_ASSERT(!currentlyLockedAlphaMap.isNull()); - currentlyLockedAlphaMap = QImage(); + return nullptr; } QImage QFontEngine::alphaMapForGlyph(glyph_t glyph) diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index 682395ece6..48dcdbeff7 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -124,6 +124,22 @@ public: }; Q_DECLARE_FLAGS(ShaperFlags, ShaperFlag) + /* Used with the Freetype font engine. We don't cache glyphs that are too large anyway, so we can make this struct rather small */ + struct Glyph { + Glyph() = default; + ~Glyph() { delete [] data; } + short linearAdvance = 0; + unsigned char width = 0; + unsigned char height = 0; + short x = 0; + short y = 0; + short advance = 0; + signed char format = 0; + uchar *data = nullptr; + private: + Q_DISABLE_COPY(Glyph); + }; + virtual ~QFontEngine(); inline Type type() const { return m_type; } @@ -191,11 +207,7 @@ public: virtual QImage alphaMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); virtual QImage alphaRGBMapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t); virtual QImage bitmapForGlyph(glyph_t, QFixed subPixelPosition, const QTransform &t, const QColor &color = QColor()); - virtual QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, - GlyphFormat neededFormat, - const QTransform &t = QTransform(), - QPoint *offset = 0); - virtual void unlockAlphaMapForGlyph(); + virtual Glyph *glyphData(glyph_t glyph, QFixed subPixelPosition, GlyphFormat neededFormat, const QTransform &t); virtual bool hasInternalCaching() const { return false; } virtual glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed /*subPixelPosition*/, const QTransform &matrix, GlyphFormat /*format*/) @@ -346,7 +358,6 @@ public: void loadKerningPairs(QFixed scalingFactor); GlyphFormat glyphFormat; - QImage currentlyLockedAlphaMap; int m_subPixelPositionCount; // Number of positions within a single pixel for this cache inline QVariant userData() const { return m_userData; } diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp index ef80d68bfe..e132442e37 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft.cpp @@ -106,7 +106,7 @@ static bool ft_getSfntTable(void *user_data, uint tag, uchar *buffer, uint *leng return result; } -static QFontEngineFT::Glyph emptyGlyph = {0, 0, 0, 0, 0, 0, 0, 0}; +static QFontEngineFT::Glyph emptyGlyph; static const QFontEngine::HintStyle ftInitialDefaultHintStyle = #ifdef Q_OS_WIN @@ -556,11 +556,6 @@ void QFreetypeFace::addBitmapToPath(FT_GlyphSlot slot, const QFixedPoint &point, slot->bitmap.buffer, slot->bitmap.pitch, slot->bitmap.width, slot->bitmap.rows, path); } -QFontEngineFT::Glyph::~Glyph() -{ - delete [] data; -} - struct LcdFilterDummy { static inline void filterPixel(uchar &, uchar &, uchar &) @@ -1986,11 +1981,10 @@ static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEng return img; } -QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixelPosition, - QFontEngine::GlyphFormat neededFormat, - const QTransform &t, QPoint *offset) +QFontEngine::Glyph *QFontEngineFT::glyphData(glyph_t glyphIndex, QFixed subPixelPosition, + QFontEngine::GlyphFormat neededFormat, const QTransform &t) { - Q_ASSERT(currentlyLockedAlphaMap.isNull()); + Q_ASSERT(cacheEnabled); if (isBitmapFont()) neededFormat = Format_Mono; @@ -2000,33 +1994,10 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe neededFormat = Format_A8; Glyph *glyph = loadGlyphFor(glyphIndex, subPixelPosition, neededFormat, t); - - if (offset != 0 && glyph != 0) - *offset = QPoint(glyph->x, -glyph->y); - - currentlyLockedAlphaMap = alphaMapFromGlyphData(glyph, neededFormat); - - const bool glyphHasGeometry = glyph != nullptr && glyph->height != 0 && glyph->width != 0; - if (!cacheEnabled && glyph != &emptyGlyph) { - currentlyLockedAlphaMap = currentlyLockedAlphaMap.copy(); - delete glyph; - } - - if (!glyphHasGeometry) + if (!glyph || !glyph->width || !glyph->height) return nullptr; - if (currentlyLockedAlphaMap.isNull()) - return QFontEngine::lockedAlphaMapForGlyph(glyphIndex, subPixelPosition, neededFormat, t, offset); - - QImageData *data = currentlyLockedAlphaMap.data_ptr(); - data->is_locked = true; - - return ¤tlyLockedAlphaMap; -} - -void QFontEngineFT::unlockAlphaMapForGlyph() -{ - QFontEngine::unlockAlphaMapForGlyph(); + return glyph; } static inline bool is2dRotation(const QTransform &t) diff --git a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h index 109bae86e9..2863d206d2 100644 --- a/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h +++ b/src/platformsupport/fontdatabases/freetype/qfontengine_ft_p.h @@ -129,20 +129,6 @@ private: class QFontEngineFT : public QFontEngine { public: - - /* we don't cache glyphs that are too large anyway, so we can make this struct rather small */ - struct Glyph { - ~Glyph(); - int linearAdvance : 22; - unsigned char width; - unsigned char height; - short x; - short y; - short advance; - signed char format; - uchar *data; - }; - struct GlyphInfo { int linearAdvance; unsigned short width; @@ -241,11 +227,9 @@ private: QFixed subPixelPosition, const QTransform &matrix, QFontEngine::GlyphFormat format) override; - QImage *lockedAlphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, - GlyphFormat neededFormat, const QTransform &t, - QPoint *offset) override; + Glyph *glyphData(glyph_t glyph, QFixed subPixelPosition, + GlyphFormat neededFormat, const QTransform &t) override; bool hasInternalCaching() const override { return cacheEnabled; } - void unlockAlphaMapForGlyph() override; bool expectsGammaCorrectedBlending() const override; void removeGlyphFromCache(glyph_t glyph) override; -- cgit v1.2.3 From aef0fba3c550915318db5b350892f558ec7e77ff Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Wed, 7 Aug 2019 13:33:41 +0200 Subject: QCocoaMenuLoader: get rid of lastAppSpecificItem MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Look it up when needed instead. Also, simplify our ownership logic - do not retain/autorelease that is already owned by a menu (via its itemArray). Fixes: QTBUG-76523 Change-Id: I60a2ed0d192396baf99eec7b37fa5cc10e5db626 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoamenuloader.mm | 48 ++++++++++++++----------- 1 file changed, 27 insertions(+), 21 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoamenuloader.mm b/src/plugins/platforms/cocoa/qcocoamenuloader.mm index da0fc5c6a1..d384078e91 100644 --- a/src/plugins/platforms/cocoa/qcocoamenuloader.mm +++ b/src/plugins/platforms/cocoa/qcocoamenuloader.mm @@ -59,7 +59,6 @@ NSMenuItem *aboutItem; NSMenuItem *aboutQtItem; NSMenuItem *hideItem; - NSMenuItem *lastAppSpecificItem; NSMenuItem *servicesItem; NSMenuItem *hideAllOthersItem; NSMenuItem *showAllItem; @@ -118,6 +117,9 @@ [appMenu addItem:[NSMenuItem separatorItem]]; // Preferences + // We'll be adding app specific items after this. The macOS HIG state that, + // "In general, a Preferences menu item should be the first app-specific menu item." + // https://developer.apple.com/macos/human-interface-guidelines/menus/menu-bar-menus/ preferencesItem = [[QCocoaNSMenuItem alloc] init]; preferencesItem.title = @"Preferences…"; preferencesItem.keyEquivalent = @","; @@ -126,11 +128,6 @@ preferencesItem.hidden = YES; [appMenu addItem:preferencesItem]; - // We'll be adding app specific items after this. The macOS HIG state that, - // "In general, a Preferences menu item should be the first app-specific menu item." - // https://developer.apple.com/macos/human-interface-guidelines/menus/menu-bar-menus/ - lastAppSpecificItem = preferencesItem; - [appMenu addItem:[NSMenuItem separatorItem]]; // Services item and menu @@ -194,8 +191,6 @@ [showAllItem release]; [quitItem release]; - [lastAppSpecificItem release]; - [super dealloc]; } @@ -272,25 +267,20 @@ // No reason to create the item if it already exists. for (NSMenuItem *item in appMenu.itemArray) if (qt_objc_cast(item).platformMenuItem == platformItem) - return [[item retain] autorelease]; + return item; // Create an App-Specific menu item, insert it into the menu and return // it as an autorelease item. QCocoaNSMenuItem *item; if (platformItem->isSeparator()) - item = [[QCocoaNSMenuItem separatorItemWithPlatformMenuItem:platformItem] retain]; + item = [QCocoaNSMenuItem separatorItemWithPlatformMenuItem:platformItem]; else - item = [[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem]; - - const auto location = [appMenu indexOfItem:lastAppSpecificItem]; + item = [[[QCocoaNSMenuItem alloc] initWithPlatformMenuItem:platformItem] autorelease]; - if (!lastAppSpecificItem.separatorItem) - [lastAppSpecificItem release]; - lastAppSpecificItem = item; // Keep track of this for later (i.e., don't release it) + const auto location = [self indexOfLastAppSpecificMenuItem]; + [appMenu insertItem:item atIndex:NSInteger(location) + 1]; - [appMenu insertItem:item atIndex:location + 1]; - - return [[item retain] autorelease]; + return item; } - (void)orderFrontStandardAboutPanel:(id)sender @@ -344,8 +334,24 @@ - (NSArray *)mergeable { // Don't include the quitItem here, since we want it always visible and enabled regardless - // Note that lastAppSpecificItem may be nil, so we can't use @[] here. - return [NSArray arrayWithObjects:preferencesItem, aboutItem, aboutQtItem, lastAppSpecificItem, nil]; + auto items = [NSArray arrayWithObjects:preferencesItem, aboutItem, aboutQtItem, + appMenu.itemArray[[self indexOfLastAppSpecificMenuItem]], nil]; + return items; } +- (NSUInteger)indexOfLastAppSpecificMenuItem +{ + // Either the 'Preferences', which is the first app specific menu item, or something + // else we appended later (thus the reverse order): + const auto location = [appMenu.itemArray indexOfObjectWithOptions:NSEnumerationReverse + passingTest:^BOOL(NSMenuItem *item, NSUInteger, BOOL *) { + if (auto qtItem = qt_objc_cast(item)) + return qtItem != quitItem; + return NO; + }]; + Q_ASSERT(location != NSNotFound); + return location; +} + + @end -- cgit v1.2.3 From 39e937a538325c4fc40a790496f2a39d28f8eba4 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 2 Aug 2019 09:24:37 +0200 Subject: Fix host architecture detection for canadian cross builds If the host architecture is different from -platform (canadian cross build with -external-hostbindir) then we cannot use QMAKE_HOST.os to deduce the executable extension for that platform, because this value comes from the qmake binary that was pointed to by -external-hostbindir. Move the target name deduction mechanism to the actual configure test .pro files to make sure the right scopes are available, and write the deduced target name to a text file. That text file is read by qtConfTest_architecture to get the right binary to analyze. Fixes: QTBUG-77286 Change-Id: I68b844dd51dbfda6432a4b0dca6331899c82255f Reviewed-by: Kai Koehne --- config.tests/arch/arch.pro | 1 + config.tests/arch/arch_host.pro | 1 + config.tests/arch/write_info.pri | 14 ++++++++++++++ configure.pri | 20 +------------------- 4 files changed, 17 insertions(+), 19 deletions(-) create mode 100644 config.tests/arch/write_info.pri diff --git a/config.tests/arch/arch.pro b/config.tests/arch/arch.pro index 45a7eb33af..c607898b71 100644 --- a/config.tests/arch/arch.pro +++ b/config.tests/arch/arch.pro @@ -1 +1,2 @@ SOURCES = arch.cpp +include(write_info.pri) diff --git a/config.tests/arch/arch_host.pro b/config.tests/arch/arch_host.pro index cefdbc77ef..ea0d1fa572 100644 --- a/config.tests/arch/arch_host.pro +++ b/config.tests/arch/arch_host.pro @@ -1,2 +1,3 @@ option(host_build) SOURCES = arch.cpp +include(write_info.pri) diff --git a/config.tests/arch/write_info.pri b/config.tests/arch/write_info.pri new file mode 100644 index 0000000000..3b55a63f49 --- /dev/null +++ b/config.tests/arch/write_info.pri @@ -0,0 +1,14 @@ +targetinfofile = $$basename(_PRO_FILE_) +targetinfofile ~= s/pro$/target.txt/ + +win32 { + ext = .exe +} else:android { + file_prefix = lib + ext = .so +} else:wasm { + ext = .wasm +} + +content = $${file_prefix}$${TARGET}$${ext} +write_file($$OUT_PWD/$$targetinfofile, content) diff --git a/configure.pri b/configure.pri index e9fd055854..09c34af4ee 100644 --- a/configure.pri +++ b/configure.pri @@ -266,28 +266,10 @@ defineTest(qtConfTest_architecture) { !qtConfTest_compile($${1}): \ error("Could not determine $$eval($${1}.label). See config.log for details.") - host = $$eval($${1}.host) - isEmpty(host): host = false - file_prefix = - ext = - $$host { - equals(QMAKE_HOST.os, Windows): \ - ext = .exe - } else { - win32 { - ext = .exe - } else:android { - file_prefix = lib - ext = .so - } else:wasm { - ext = .wasm - } - } - test = $$eval($${1}.test) output = $$eval($${1}.output) test_out_dir = $$OUT_PWD/$$basename(QMAKE_CONFIG_TESTS_DIR)/$$test - test_out_file = $$test_out_dir/$$file_prefix$$output$$ext + test_out_file = $$test_out_dir/$$cat($$test_out_dir/$${output}.target.txt) exists($$test_out_file): \ content = $$cat($$test_out_file, blob) else: \ -- cgit v1.2.3 From 6ce9404a6e7ad6ba3ff37f6890fe400c643c3d52 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 1 Aug 2019 22:56:30 -0700 Subject: QBitArray: fix fromBits() and actually test it When I initially added it, it was ony for QCborValue, but I never added the tests. Turns out there were two bugs: [ChangeLog][QtCore][QBitArray] Fixed two bugs that caused QBitArrays created using fromBits() not to compare equal to the equivalent QBitArray created using other methods if the size was zero or not a multiple of 4. If the size modulus 8 was 5, 6, or 7, the data was actually incorrect. Fixes: QTBUG-77285 Change-Id: Ife213d861bb14c1787e1fffd15b70573d162042c Reviewed-by: Lars Knoll --- src/corelib/tools/qbitarray.cpp | 12 +++-- .../auto/corelib/tools/qbitarray/tst_qbitarray.cpp | 57 ++++++++++++++++++++++ 2 files changed, 64 insertions(+), 5 deletions(-) diff --git a/src/corelib/tools/qbitarray.cpp b/src/corelib/tools/qbitarray.cpp index 4e8e3c241e..94aadf7fdf 100644 --- a/src/corelib/tools/qbitarray.cpp +++ b/src/corelib/tools/qbitarray.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2016 The Qt Company Ltd. -** Copyright (C) 2016 Intel Corporation. +** Copyright (C) 2019 Intel Corporation. ** Contact: https://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -132,12 +132,12 @@ QT_BEGIN_NAMESPACE * We overallocate the byte array by 1 byte. The first user bit is at * d.data()[1]. On the extra first byte, we store the difference between the * number of bits in the byte array (including this byte) and the number of - * bits in the bit array. Therefore, it's always a number between 8 and 15. + * bits in the bit array. Therefore, for a non-empty QBitArray, it's always a + * number between 8 and 15. For the empty one, d is the an empty QByteArray and + * *d.constData() is the QByteArray's terminating NUL (0) byte. * * This allows for fast calculation of the bit array size: * inline int size() const { return (d.size() << 3) - *d.constData(); } - * - * Note: for an array of zero size, *d.constData() is the QByteArray implicit NUL. */ /*! @@ -326,6 +326,8 @@ void QBitArray::fill(bool value, int begin, int end) QBitArray QBitArray::fromBits(const char *data, qsizetype size) { QBitArray result; + if (size == 0) + return result; qsizetype nbytes = (size + 7) / 8; result.d = QByteArray(nbytes + 1, Qt::Uninitialized); @@ -334,7 +336,7 @@ QBitArray QBitArray::fromBits(const char *data, qsizetype size) // clear any unused bits from the last byte if (size & 7) - bits[nbytes] &= 0xffU >> (size & 7); + bits[nbytes] &= 0xffU >> (8 - (size & 7)); *bits = result.d.size() * 8 - size; return result; diff --git a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp index d19eac7530..9a7c099228 100644 --- a/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp +++ b/tests/auto/corelib/tools/qbitarray/tst_qbitarray.cpp @@ -84,6 +84,8 @@ private slots: void operator_noteq(); void resize(); + void fromBits_data(); + void fromBits(); }; void tst_QBitArray::size_data() @@ -610,5 +612,60 @@ void tst_QBitArray::resize() } +void tst_QBitArray::fromBits_data() +{ + QTest::addColumn("data"); + QTest::addColumn("size"); + QTest::addColumn("expected"); + + QTest::newRow("empty") << QByteArray() << 0 << QBitArray(); + + auto add = [](const QByteArray &tag, const char *data) { + QTest::newRow(tag) << QByteArray(data, (tag.size() + 7) / 8) << tag.size() + << QStringToQBitArray(tag); + }; + + // "0" to "0000000000000000" + for (int i = 1; i < 16; ++i) { + char zero[2] = { 0, 0 }; + QByteArray pattern(i, '0'); + add(pattern, zero); + } + + // "1" to "1111111111111111" + for (int i = 1; i < 16; ++i) { + char one[2] = { '\xff', '\xff' }; + QByteArray pattern(i, '1'); + add(pattern, one); + } + + // trailing 0 and 1 + char zero = 1; + char one = 0; + QByteArray pzero = "1"; + QByteArray pone = "0"; + for (int i = 2; i < 8; ++i) { + zero <<= 1; + pzero.prepend('0'); + add(pzero, &zero); + + one = (one << 1) | 1; + pone.prepend('1'); + add(pone, &one); + } +} + +void tst_QBitArray::fromBits() +{ + QFETCH(QByteArray, data); + QFETCH(int, size); + QFETCH(QBitArray, expected); + + QBitArray fromBits = QBitArray::fromBits(data, size); + QCOMPARE(fromBits, expected); + + QCOMPARE(QBitArray::fromBits(fromBits.bits(), fromBits.size()), expected); +} + QTEST_APPLESS_MAIN(tst_QBitArray) #include "tst_qbitarray.moc" -- cgit v1.2.3 From aca43d29f8a1c90d14069ac602cf0ba7beaba300 Mon Sep 17 00:00:00 2001 From: Simon Hausmann Date: Tue, 6 Aug 2019 14:04:35 +0200 Subject: Fix sign change warning The conversion from int to uint is deliberate here, so let's cast and avoid a warning for users compiling with warnings enabled. Change-Id: I7136d6161ace735be49f8d987338f6d401a5c78a Fixes: QTBUG-77245 Reviewed-by: Thiago Macieira --- src/corelib/serialization/qjsonvalue.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/serialization/qjsonvalue.h b/src/corelib/serialization/qjsonvalue.h index d8e121524d..4df689078e 100644 --- a/src/corelib/serialization/qjsonvalue.h +++ b/src/corelib/serialization/qjsonvalue.h @@ -173,9 +173,9 @@ class Q_CORE_EXPORT QJsonValueRef { public: QJsonValueRef(QJsonArray *array, int idx) - : a(array), is_object(false), index(idx) {} + : a(array), is_object(false), index(static_cast(idx)) {} QJsonValueRef(QJsonObject *object, int idx) - : o(object), is_object(true), index(idx) {} + : o(object), is_object(true), index(static_cast(idx)) {} inline operator QJsonValue() const { return toValue(); } QJsonValueRef &operator = (const QJsonValue &val); -- cgit v1.2.3 From a08ac1986d39b4d4614f654b3408c7b846c835c9 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Thu, 8 Aug 2019 19:12:32 -0700 Subject: Fix integer overflow in QCryptographicHash's SHA-3 support Because 256 MB * 8 = 2 Gbit, but length*8 is a signed integer overflow, hence UB. Can't really autotest this. Not all systems where we're going to test can allocate 256 MB of RAM. [ChangeLog][QtCore][QCryptographicHash] Fixed a bug that caused the SHA-3 and Keccak algorithms to crash if passed 256 MB of data or more. Fixes: QTBUG-77362 Change-Id: Iec9c051acd73484c8d94fffd15b91f4b1450f5d7 Reviewed-by: Marc Mutz --- src/corelib/tools/qcryptographichash.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/src/corelib/tools/qcryptographichash.cpp b/src/corelib/tools/qcryptographichash.cpp index 3c79bb797d..51f48503fb 100644 --- a/src/corelib/tools/qcryptographichash.cpp +++ b/src/corelib/tools/qcryptographichash.cpp @@ -387,19 +387,19 @@ void QCryptographicHash::addData(const char *data, int length) break; case RealSha3_224: case Keccak_224: - sha3Update(&d->sha3Context, reinterpret_cast(data), length*8); + sha3Update(&d->sha3Context, reinterpret_cast(data), quint64(length) * 8); break; case RealSha3_256: case Keccak_256: - sha3Update(&d->sha3Context, reinterpret_cast(data), length*8); + sha3Update(&d->sha3Context, reinterpret_cast(data), quint64(length) * 8); break; case RealSha3_384: case Keccak_384: - sha3Update(&d->sha3Context, reinterpret_cast(data), length*8); + sha3Update(&d->sha3Context, reinterpret_cast(data), quint64(length) * 8); break; case RealSha3_512: case Keccak_512: - sha3Update(&d->sha3Context, reinterpret_cast(data), length*8); + sha3Update(&d->sha3Context, reinterpret_cast(data), quint64(length) * 8); break; #endif } -- cgit v1.2.3 From 5d7f1133205d14002463456c26a97f8ba17d69b8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 7 Aug 2019 13:15:51 +0200 Subject: Add nullptr guard to QHighDScaling::scaleAndOrigin(QPlatformScreen *) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Commit b6ded193 added an unconditional dereference of the platformScreen pointer, for calls where nativePostion is non-nullptr. Change-Id: I4a6fbbd0337f91d4fcb76c17b4dc60e1b9ad10ed Reviewed-by: Tor Arne Vestbø --- src/gui/kernel/qhighdpiscaling.cpp | 2 ++ .../gui/kernel/qhighdpiscaling/tst_qhighdpiscaling.cpp | 18 ++++++++++++++++++ 2 files changed, 20 insertions(+) diff --git a/src/gui/kernel/qhighdpiscaling.cpp b/src/gui/kernel/qhighdpiscaling.cpp index 0fea416404..64f1397771 100644 --- a/src/gui/kernel/qhighdpiscaling.cpp +++ b/src/gui/kernel/qhighdpiscaling.cpp @@ -456,6 +456,8 @@ QHighDpiScaling::ScaleAndOrigin QHighDpiScaling::scaleAndOrigin(const QPlatformS { if (!m_active) return { qreal(1), QPoint() }; + if (!platformScreen) + return { m_factor, QPoint() }; // the global factor const QPlatformScreen *actualScreen = nativePosition ? platformScreen->screenForPosition(*nativePosition) : platformScreen; return { m_factor * screenSubfactor(actualScreen), actualScreen->geometry().topLeft() }; diff --git a/tests/auto/gui/kernel/qhighdpiscaling/tst_qhighdpiscaling.cpp b/tests/auto/gui/kernel/qhighdpiscaling/tst_qhighdpiscaling.cpp index 969b2351ec..ec80c2d02c 100644 --- a/tests/auto/gui/kernel/qhighdpiscaling/tst_qhighdpiscaling.cpp +++ b/tests/auto/gui/kernel/qhighdpiscaling/tst_qhighdpiscaling.cpp @@ -36,6 +36,7 @@ class tst_QHighDpiScaling: public QObject Q_OBJECT private slots: + void factor(); void scale(); }; @@ -50,6 +51,23 @@ public: QImage::Format format() const override { return QImage::Format_ARGB32_Premultiplied; } }; +void tst_QHighDpiScaling::factor() +{ + QHighDpiScaling::setGlobalFactor(2); + + // Verfy that QHighDpiScaling::factor() does not crash on nullptr contexts. + QPoint fakeNativePosition = QPoint(5, 5); + QPlatformScreen *screenContext = nullptr; + QVERIFY(QHighDpiScaling::factor(screenContext) >= 0); + QVERIFY(QHighDpiScaling::factor(screenContext, &fakeNativePosition) >= 0); + QPlatformScreen *platformScreenContext = nullptr; + QVERIFY(QHighDpiScaling::factor(platformScreenContext) >= 0); + QVERIFY(QHighDpiScaling::factor(platformScreenContext, &fakeNativePosition) >= 0); + QWindow *windowContext = nullptr; + QVERIFY(QHighDpiScaling::factor(windowContext) >= 0); + QVERIFY(QHighDpiScaling::factor(windowContext, &fakeNativePosition) >= 0); +} + // QTBUG-77255: Test some scaling overloads void tst_QHighDpiScaling::scale() { -- cgit v1.2.3 From 3729695cc9d550e831567772441ad55bd767ab1a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 9 Aug 2019 12:25:05 +0200 Subject: =?UTF-8?q?macOS:=20Don=E2=80=99t=20show=20hidden=20windows=20whil?= =?UTF-8?q?e=20z-ordering?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Calling [NSWindow orderBack] will make the window visible again, and will e.g. bring back closed menus on application modality changes. Fixes: QTBUG-77281 Change-Id: I2f89b852ea9f8ab34c709cec96d93fe305984fb9 Reviewed-by: Timur Pocheptsov Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoawindowmanager.mm | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm index 879bfaa546..9c45d8c7fc 100644 --- a/src/plugins/platforms/cocoa/qcocoawindowmanager.mm +++ b/src/plugins/platforms/cocoa/qcocoawindowmanager.mm @@ -92,7 +92,8 @@ void QCocoaWindowManager::modalSessionChanged() if (NSApp.modalWindow) { // Lower window to that of the modal windows, but no less nativeWindow.level = NSModalPanelWindowLevel; - [nativeWindow orderBack:nil]; + if ([nativeWindow isVisible]) + [nativeWindow orderBack:nil]; } else { // Restore window's natural window level, whatever that was nativeWindow.level = naturalWindowLevel; -- cgit v1.2.3 From 9bcbba36c73b8d03e8e58898629259489a24e040 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Wed, 12 Jun 2019 15:29:31 +0200 Subject: QWizard: Account for missing background image on macOS 10.14+ MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit We were loading “Background.png” from the KeyboardSetupAssistant app bundle. As of macOS 10.14 that image is no longer there. Adjust auto tests and document the behavior. Change-Id: Icb4dd73b3fa88927e87bb86db2bc9f7b4a8094f7 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/cocoa/qcocoanativeinterface.mm | 3 +++ src/widgets/dialogs/qwizard.cpp | 2 +- tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp | 19 +++++++++---------- 3 files changed, 13 insertions(+), 11 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm index 7979e430ac..9bd19dd07c 100644 --- a/src/plugins/platforms/cocoa/qcocoanativeinterface.mm +++ b/src/plugins/platforms/cocoa/qcocoanativeinterface.mm @@ -177,6 +177,9 @@ void *QCocoaNativeInterface::NSPrintInfoForPrintEngine(QPrintEngine *printEngine QPixmap QCocoaNativeInterface::defaultBackgroundPixmapForQWizard() { + // Note: starting with macOS 10.14, the KeyboardSetupAssistant app bundle no + // longer contains the "Background.png" image. This function then returns a + // null pixmap. const int ExpectedImageWidth = 242; const int ExpectedImageHeight = 414; QCFType urls = LSCopyApplicationURLsForBundleIdentifier( diff --git a/src/widgets/dialogs/qwizard.cpp b/src/widgets/dialogs/qwizard.cpp index 21e1ff2778..f19a4e99af 100644 --- a/src/widgets/dialogs/qwizard.cpp +++ b/src/widgets/dialogs/qwizard.cpp @@ -2890,7 +2890,7 @@ void QWizard::setPixmap(WizardPixmap which, const QPixmap &pixmap) Returns the pixmap set for role \a which. By default, the only pixmap that is set is the BackgroundPixmap on - \macos. + \macos version 10.13 and earlier. \sa QWizardPage::pixmap(), {Elements of a Wizard Page} */ diff --git a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp index 63f6e67a3e..da75e64d1e 100644 --- a/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp +++ b/tests/auto/widgets/dialogs/qwizard/tst_qwizard.cpp @@ -417,20 +417,19 @@ void tst_QWizard::setPixmap() QVERIFY(wizard.pixmap(QWizard::BannerPixmap).isNull()); QVERIFY(wizard.pixmap(QWizard::LogoPixmap).isNull()); QVERIFY(wizard.pixmap(QWizard::WatermarkPixmap).isNull()); -#ifdef Q_OS_OSX - QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull()); -#else - QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull()); -#endif + if (QSysInfo::macVersion() <= Q_MV_OSX(10, 13)) + QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull()); + else + QVERIFY(wizard.pixmap(QWizard::BackgroundPixmap).isNull()); QVERIFY(page->pixmap(QWizard::BannerPixmap).isNull()); QVERIFY(page->pixmap(QWizard::LogoPixmap).isNull()); QVERIFY(page->pixmap(QWizard::WatermarkPixmap).isNull()); -#ifdef Q_OS_OSX - QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull()); -#else - QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull()); -#endif + if (QSysInfo::macVersion() <= Q_MV_OSX(10, 13)) + QVERIFY(!wizard.pixmap(QWizard::BackgroundPixmap).isNull()); + else + QVERIFY(page->pixmap(QWizard::BackgroundPixmap).isNull()); + wizard.setPixmap(QWizard::BannerPixmap, p1); wizard.setPixmap(QWizard::LogoPixmap, p2); wizard.setPixmap(QWizard::WatermarkPixmap, p3); -- cgit v1.2.3 From fcc5323a08f955bcedd8a8a9750173384fa7d71f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 7 Jun 2019 16:04:23 +0200 Subject: Make test less dependent on moving the cursor The sendMouseMove() function calls QTest::mouseMove(), which again calls QCursor::setPos() to move the cursor. It then creates and sends a MouseMove event, using the constructor which picks up the global position by calling QCursor::pos(). On macOS 10.14, QCursor::setPos() may silently fail if the user does not grant the application permission to move the cursor (via a dialog). As result of this the mouse move event gets an incorrect global position. Provide the global position directly when creating the event to make sure it gets the correct value. Task-number: QTBUG-75786 Change-Id: I3e8df450fea802783a3d1dbe471753f502b42de3 Reviewed-by: Richard Moe Gustavsen --- tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp index 28df3a3c38..1456b9e35c 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsview/tst_qgraphicsview.cpp @@ -88,7 +88,7 @@ static void sendMousePress(QWidget *widget, const QPoint &point, Qt::MouseButton static void sendMouseMove(QWidget *widget, const QPoint &point, Qt::MouseButton button = Qt::NoButton, Qt::MouseButtons buttons = 0) { QTest::mouseMove(widget, point); - QMouseEvent event(QEvent::MouseMove, point, button, buttons, 0); + QMouseEvent event(QEvent::MouseMove, point, widget->mapToGlobal(point), button, buttons, 0); QApplication::sendEvent(widget, &event); QApplication::processEvents(); } -- cgit v1.2.3 From e66f247ccf345f1d303a92e53c21bb53d96c5af2 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 9 Aug 2019 15:54:00 +0200 Subject: Doc: Extend QMake's documentation of RC_FILE and RES_FILE RC_FILE is not an internal variable that "rarely needs to be modified". Mention that it's about Windows resources and link to the corresponding section. RES_FILE: Add link to RC_FILE and the more general section. Also rephrase "compiled Windows resource file" to "Windows resource compiler's output file" which is more precise. Fixes: QTBUG-8709 Change-Id: I19c61e6a9505d45fc13fefbcd0ba9441191aa42e Reviewed-by: Kai Koehne Reviewed-by: Kavindra Palaraja --- qmake/doc/src/qmake-manual.qdoc | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/qmake/doc/src/qmake-manual.qdoc b/qmake/doc/src/qmake-manual.qdoc index d3148a1e62..2e2962f86c 100644 --- a/qmake/doc/src/qmake-manual.qdoc +++ b/qmake/doc/src/qmake-manual.qdoc @@ -2541,10 +2541,8 @@ \section1 RC_FILE - Specifies the name of the resource file for the application. - The value of this variable is typically handled by - qmake or \l{#QMAKESPEC}{qmake.conf} and rarely - needs to be modified. + Windows only. Specifies the name of the Windows resource file (.rc) for the + target. See \l{Adding Windows Resource Files}. \target RC_CODEPAGE \section1 RC_CODEPAGE @@ -2607,7 +2605,9 @@ \section1 RES_FILE - Specifies the name of the compiled Windows resource file for the target. + Windows only. Specifies the name of the Windows resource compiler's output + file for this target. See \l{RC_FILE} and \l{Adding Windows Resource Files}. + The value of this variable is typically handled by qmake or \l{#QMAKESPEC}{qmake.conf} and rarely needs to be modified. -- cgit v1.2.3