From 833341e301bf5ffc786e42a3c4be2ec25dbd8115 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 9 Nov 2015 14:00:22 +0100 Subject: Detect alpha8 as having alpha-pixels Change-Id: I09025da7e3df84b6092295ec1a02698bd7b24bed Reviewed-by: Gunnar Sletta --- src/gui/image/qimage.cpp | 19 +++++++++++++++++-- 1 file changed, 17 insertions(+), 2 deletions(-) diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp index b3d8563614..01cacad630 100644 --- a/src/gui/image/qimage.cpp +++ b/src/gui/image/qimage.cpp @@ -192,7 +192,9 @@ bool QImageData::checkForAlphaPixels() const case QImage::Format_Indexed8: has_alpha_pixels = has_alpha_clut; break; - + case QImage::Format_Alpha8: + has_alpha_pixels = true; + break; case QImage::Format_ARGB32: case QImage::Format_ARGB32_Premultiplied: { uchar *bits = data; @@ -266,7 +268,20 @@ bool QImageData::checkForAlphaPixels() const } } break; - default: + case QImage::Format_RGB32: + case QImage::Format_RGB16: + case QImage::Format_RGB444: + case QImage::Format_RGB555: + case QImage::Format_RGB666: + case QImage::Format_RGB888: + case QImage::Format_RGBX8888: + case QImage::Format_BGR30: + case QImage::Format_RGB30: + case QImage::Format_Grayscale8: + break; + case QImage::Format_Invalid: + case QImage::NImageFormats: + Q_UNREACHABLE(); break; } -- cgit v1.2.3 From 6c222297ab19e1bc6b74c4290446c1cb61f6fda8 Mon Sep 17 00:00:00 2001 From: Martin Afanasjew Date: Mon, 19 Oct 2015 23:52:10 +0200 Subject: Make -no-rpath build more useful on Apple platforms [ChangeLog][Platform Specific Changes][OS X] Configure with -no-rpath will now yield Qt dynamic libraries and frameworks with an absolute install name (based in -libdir). OS X package managers like Homebrew install Qt in a fixed location. This change simplifies deployment for such package managers and is consistent with the default expectation on Apple platforms for libraries with a fixed location to also have absolute install names. While a relocatable installation (the default) also works in this scenario, it requires all software that depends on Qt to be aware of this and to embed a suitable RPATH into application binaries (which is not automatic for non-qmake builds). This might not be true for some select fallback search locations, but as package managers on OS X tend not to use those, embedding an RPATH becomes practically mandatory. In a default Homebrew installation, Qt is configured such that the frameworks end up in /usr/local/Cellar/qt5//lib and that will be later symlinked to /usr/local/opt/qt5/lib, both of which are not searched by the dynamic linker by default. Task-number: QTBUG-48958 Change-Id: I4395df98771e06a2ce8a293d11dc755bdc50757f Reviewed-by: Oswald Buddenhagen --- configure | 4 +++- mkspecs/features/qt_module.prf | 2 ++ 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/configure b/configure index cea62fbc0c..c29c113da3 100755 --- a/configure +++ b/configure @@ -2557,7 +2557,9 @@ Additional options: -l ........ Add an explicit library. -no-rpath .......... Do not use the library install path as a runtime - library path. + library path. On Apple platforms, this implies using + absolute install names (based in -libdir) for dynamic + libraries and frameworks. + -rpath ............. Link Qt libraries and executables using the library install path as a runtime library path. Equivalent to -R install_libpath diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index c89b6d2793..f187b85b6d 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -135,6 +135,8 @@ mac { contains(QT_CONFIG, rpath): \ QMAKE_SONAME_PREFIX = @rpath + else: \ + CONFIG += absolute_library_soname } DEFINES += QT_BUILDING_QT -- cgit v1.2.3 From 2398e225abdea36321670d34a8238b6e64dba281 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 8 Sep 2015 20:35:33 -0300 Subject: Auto-detect whether 64-bit std::atomic really works The C++ standard says it must, but some badly-configured toolchains seem to be lacking support. In particular, for some 32-bit platforms without native support for them, GCC implements 64-bit atomics via out-of-line functions in libatomic. If that library is missing... well, then std::atomic 64-bit doesn't work and we mustn't try to use it. This was found when trying to compile Qt 5.6 for MIPS 32-bit: Linking library libQt5Core.so.5.6.0 .obj/qsimd.o: In function `std::__atomic_base::load(std::memory_order) const': /opt/poky/1.7/sysroots/mips32r2-poky-linux/usr/include/c++/4.9.1/bits/atomic_base.h:500: undefined reference to `__atomic_load_8' .obj/qsimd.o: In function `std::__atomic_base::store(unsigned long long, std::memory_order)': /opt/poky/1.7/sysroots/mips32r2-poky-linux/usr/include/c++/4.9.1/bits/atomic_base.h:478: undefined reference to `__atomic_store_8' Yocto bug report: https://bugzilla.yoctoproject.org/show_bug.cgi?id=8274 Change-Id: I42e7ef1a481840699a8dffff140224d6614e5c36 Reviewed-by: Oswald Buddenhagen Reviewed-by: Lars Knoll Reviewed-by: Thiago Macieira (cherry picked from commit 3d7586b760550b7d89594c8d7462fc30b868ecc6) Reviewed-by: Dmitry Shachnev --- config.tests/common/atomic64/atomic64.cpp | 54 +++++++++++++++++++++++++++++++ config.tests/common/atomic64/atomic64.pro | 3 ++ configure | 20 +++++++++++- src/corelib/arch/arch.pri | 2 ++ src/corelib/arch/qatomic_cxx11.h | 12 ++++--- tools/configure/configureapp.cpp | 17 +++++++++- 6 files changed, 101 insertions(+), 7 deletions(-) create mode 100644 config.tests/common/atomic64/atomic64.cpp create mode 100644 config.tests/common/atomic64/atomic64.pro diff --git a/config.tests/common/atomic64/atomic64.cpp b/config.tests/common/atomic64/atomic64.cpp new file mode 100644 index 0000000000..8dbea96c8b --- /dev/null +++ b/config.tests/common/atomic64/atomic64.cpp @@ -0,0 +1,54 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Intel Corporation. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the FOO module of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL21$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 2.1 or version 3 as published by the Free +** Software Foundation and appearing in the file LICENSE.LGPLv21 and +** LICENSE.LGPLv3 included in the packaging of this file. Please review the +** following information to ensure the GNU Lesser General Public License +** requirements will be met: https://www.gnu.org/licenses/lgpl.html and +** http://www.gnu.org/licenses/old-licenses/lgpl-2.1.html. +** +** As a special exception, The Qt Company gives you certain additional +** rights. These rights are described in The Qt Company LGPL Exception +** version 1.1, included in the file LGPL_EXCEPTION.txt in this package. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + +#include +#include + +void test(volatile std::atomic &a) +{ + std::int64_t v = a.load(std::memory_order_acquire); + while (!a.compare_exchange_strong(v, v + 1, + std::memory_order_acq_rel, + std::memory_order_acquire)) { + v = a.exchange(v - 1); + } + + a.store(v + 1, std::memory_order_release); +} + +int main(int, char **) +{ + void *ptr = (void*)0xffffffc0; // any random pointer + test(*reinterpret_cast *>(ptr)); + return 0; +} diff --git a/config.tests/common/atomic64/atomic64.pro b/config.tests/common/atomic64/atomic64.pro new file mode 100644 index 0000000000..c9a85817ca --- /dev/null +++ b/config.tests/common/atomic64/atomic64.pro @@ -0,0 +1,3 @@ +SOURCES = atomic64.cpp +CONFIG += c++11 console +CONFIG -= qt diff --git a/configure b/configure index c29c113da3..61f0ea0bea 100755 --- a/configure +++ b/configure @@ -2,7 +2,7 @@ ############################################################################# ## ## Copyright (C) 2015 The Qt Company Ltd. -## Copyright (C) 2013 Intel Corporation. +## Copyright (C) 2015 Intel Corporation. ## Contact: http://www.qt.io/licensing/ ## ## This file is the build configuration utility of the Qt Toolkit. @@ -661,6 +661,7 @@ CFG_SYSTEM_PROXIES=no CFG_ANDROID_STYLE_ASSETS=yes CFG_GSTREAMER=auto CFG_GSTREAMER_VERSION="" +CFG_ATOMIC64=auto # Target architecture CFG_ARCH= @@ -4328,6 +4329,15 @@ if [ "$CFG_CXX11" != "no" ]; then fi fi +# Detect whether 64-bit std::atomic works -- some 32-bit platforms require extra library support +if compileTest common/atomic64 "64-bit std::atomic"; then + CFG_ATOMIC64=yes +elif compileTest common/atomic64 "64-bit std::atomic in -latomic" -latomic; then + CFG_ATOMIC64=libatomic +else + CFG_ATOMIC64=no +fi + # detect sse2 support if [ "${CFG_SSE2}" = "auto" ]; then if compileTest common/sse2 "sse2"; then @@ -6016,6 +6026,10 @@ fi [ "$CFG_CXX11" = "yes" ] && QT_CONFIG="$QT_CONFIG c++11" +if [ "$CFG_ATOMIC64" = "libatomic" ]; then + QMAKE_CONFIG="$QMAKE_CONFIG atomic64-libatomic" +fi + if [ "$CFG_SILENT" = "yes" ]; then QMAKE_CONFIG="$QMAKE_CONFIG silent" fi @@ -6567,6 +6581,10 @@ else echo "#define QT_POINTER_SIZE $?" >>"$outpath/src/corelib/global/qconfig.h.new" fi +if [ "$CFG_ATOMIC64" = "no" ]; then + echo "#define QT_NO_STD_ATOMIC64" >> "$outpath/src/corelib/global/qconfig.h.new" +fi + #REDUCE_RELOCATIONS is a elf/unix only thing, so not in windows configure.exe if [ "$CFG_REDUCE_RELOCATIONS" = "yes" ]; then echo "#define QT_REDUCE_RELOCATIONS" >>"$outpath/src/corelib/global/qconfig.h.new" diff --git a/src/corelib/arch/arch.pri b/src/corelib/arch/arch.pri index 16fe8b8e5c..083d912331 100644 --- a/src/corelib/arch/arch.pri +++ b/src/corelib/arch/arch.pri @@ -10,6 +10,8 @@ HEADERS += \ arch/qatomic_gcc.h \ arch/qatomic_cxx11.h +atomic64-libatomic: LIBS += -latomic + unix { # fallback implementation when no other appropriate qatomic_*.h exists HEADERS += arch/qatomic_unix.h diff --git a/src/corelib/arch/qatomic_cxx11.h b/src/corelib/arch/qatomic_cxx11.h index 0e06ca951a..4136e09ce2 100644 --- a/src/corelib/arch/qatomic_cxx11.h +++ b/src/corelib/arch/qatomic_cxx11.h @@ -78,11 +78,13 @@ template<> struct QAtomicOpsSupport<8> { enum { IsSupported = 1 }; }; #define Q_ATOMIC_INT16_FETCH_AND_STORE_IS_ALWAYS_NATIVE #define Q_ATOMIC_INT16_FETCH_AND_ADD_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_IS_SUPPORTED -#define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE -#define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#ifndef QT_NO_STD_ATOMIC64 +# define Q_ATOMIC_INT64_IS_SUPPORTED +# define Q_ATOMIC_INT64_REFERENCE_COUNTING_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_TEST_AND_SET_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_STORE_IS_ALWAYS_NATIVE +# define Q_ATOMIC_INT64_FETCH_AND_ADD_IS_ALWAYS_NATIVE +#endif template struct QAtomicOps { diff --git a/tools/configure/configureapp.cpp b/tools/configure/configureapp.cpp index 3bf0546ac1..5df8f7d645 100644 --- a/tools/configure/configureapp.cpp +++ b/tools/configure/configureapp.cpp @@ -1,7 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. -** Copyright (C) 2014 Intel Corporation +** Copyright (C) 2015 Intel Corporation ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the tools applications of the Qt Toolkit. @@ -192,6 +192,7 @@ Configure::Configure(int& argc, char** argv) dictionary[ "SYSTEM_PROXIES" ] = "no"; dictionary[ "WERROR" ] = "auto"; dictionary[ "QREAL" ] = "double"; + dictionary[ "ATOMIC64" ] = "auto"; //Only used when cross compiling. dictionary[ "QT_INSTALL_SETTINGS" ] = "/etc/xdg"; @@ -2195,6 +2196,12 @@ bool Configure::checkAvailability(const QString &part) else if (part == "OBJCOPY") available = tryCompileProject("unix/objcopy"); + else if (part == "ATOMIC64") + available = tryCompileProject("common/atomic64"); + + else if (part == "ATOMIC64-LIBATOMIC") + available = tryCompileProject("common/atomic64", "LIBS+=-latomic"); + else if (part == "ZLIB") available = findFile("zlib.h"); @@ -2343,6 +2350,10 @@ void Configure::autoDetection() dictionary["C++11"] = tryCompileProject("common/c++11") ? "yes" : "no"; } + if (dictionary["ATOMIC64"] == "auto") + dictionary["ATOMIC64"] = checkAvailability("ATOMIC64") ? "yes" : + checkAvailability("ATOMIC64-LIBATOMIC") ? "libatomic" : "no"; + // Style detection if (dictionary["STYLE_WINDOWSXP"] == "auto") dictionary["STYLE_WINDOWSXP"] = checkAvailability("STYLE_WINDOWSXP") ? defaultTo("STYLE_WINDOWSXP") : "no"; @@ -2862,6 +2873,9 @@ void Configure::generateOutputVars() } } + if (dictionary["ATOMIC64"] == "libatomic") + qmakeConfig += "atomic64-libatomic"; + if (dictionary[ "ACCESSIBILITY" ] == "yes") qtConfig += "accessibility"; @@ -3661,6 +3675,7 @@ void Configure::generateConfigfiles() if (dictionary["QT_GLIB"] == "no") qconfigList += "QT_NO_GLIB"; if (dictionary["QT_INOTIFY"] == "no") qconfigList += "QT_NO_INOTIFY"; if (dictionary["QT_EVENTFD"] == "no") qconfigList += "QT_NO_EVENTFD"; + if (dictionary["ATOMIC64"] == "no") qconfigList += "QT_NO_STD_ATOMIC64"; if (dictionary["REDUCE_EXPORTS"] == "yes") qconfigList += "QT_VISIBILITY_AVAILABLE"; if (dictionary["REDUCE_RELOCATIONS"] == "yes") qconfigList += "QT_REDUCE_RELOCATIONS"; -- cgit v1.2.3 From f0d0192652019ed2842741196bf3ace870e09429 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 16 Nov 2015 10:12:24 -0800 Subject: Remove "FOO module" from config.tests/common Change-Id: I14839ba5678944c2864bffff1417413f16d4ffeb Reviewed-by: Oswald Buddenhagen --- config.tests/common/atomic64/atomic64.cpp | 2 +- config.tests/common/c++11/c++11.cpp | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/config.tests/common/atomic64/atomic64.cpp b/config.tests/common/atomic64/atomic64.cpp index 8dbea96c8b..20fbeca740 100644 --- a/config.tests/common/atomic64/atomic64.cpp +++ b/config.tests/common/atomic64/atomic64.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2015 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the FOO module of the Qt Toolkit. +** This file is part of the configuration of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage diff --git a/config.tests/common/c++11/c++11.cpp b/config.tests/common/c++11/c++11.cpp index 30934951d7..2560113c3f 100644 --- a/config.tests/common/c++11/c++11.cpp +++ b/config.tests/common/c++11/c++11.cpp @@ -3,7 +3,7 @@ ** Copyright (C) 2015 The Qt Company Ltd. ** Contact: http://www.qt.io/licensing/ ** -** This file is part of the FOO module of the Qt Toolkit. +** This file is part of the configuration of the Qt Toolkit. ** ** $QT_BEGIN_LICENSE:LGPL21$ ** Commercial License Usage -- cgit v1.2.3 From ca3933f90d770fe4ea080fe12311793262aae751 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Fri, 20 Nov 2015 17:41:46 +0100 Subject: Add missing \since to QSslCipher QString overload. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This was added in 5.3 in 30d199a76c7d30d9d70eb6cd7594826e7bf6de61. Change-Id: I35a209fcfe417cb14605c4db19a3d2e85b67ee49 Reviewed-by: Michał Dutkiewicz Reviewed-by: Marc Mutz --- src/network/ssl/qsslcipher.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/network/ssl/qsslcipher.cpp b/src/network/ssl/qsslcipher.cpp index c480b79371..302ba530d4 100644 --- a/src/network/ssl/qsslcipher.cpp +++ b/src/network/ssl/qsslcipher.cpp @@ -71,6 +71,8 @@ QSslCipher::QSslCipher() } /*! + \since 5.3 + Constructs a QSslCipher object for the cipher determined by \a name. The constructor accepts only supported ciphers (i.e., the \a name must identify a cipher in the list of ciphers returned by -- cgit v1.2.3 From 2223d4a368057106443dbe276bbccb5478b8f0a1 Mon Sep 17 00:00:00 2001 From: Florian Bruhin Date: Wed, 4 Nov 2015 08:16:57 +0100 Subject: doc: Remove wrong statement about cache filenames. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The cache actually generates paths like "http/data8/f/lr9un1so.d". Change-Id: Ie564494a241c3d1c87b2f0f17b42bd0349948640 Reviewed-by: Jędrzej Nowacki Reviewed-by: Marc Mutz Reviewed-by: Andy Shaw --- src/network/access/qnetworkdiskcache.cpp | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/network/access/qnetworkdiskcache.cpp b/src/network/access/qnetworkdiskcache.cpp index 3f705450dd..1d87d63f5d 100644 --- a/src/network/access/qnetworkdiskcache.cpp +++ b/src/network/access/qnetworkdiskcache.cpp @@ -67,8 +67,7 @@ QT_BEGIN_NAMESPACE QNetworkDiskCache stores each url in its own file inside of the cacheDirectory using QDataStream. Files with a text MimeType - are compressed using qCompress. Each cache file starts with "cache_" - and ends in ".cache". Data is written to disk only in insert() + are compressed using qCompress. Data is written to disk only in insert() and updateMetaData(). Currently you cannot share the same cache files with more than -- cgit v1.2.3 From 1641a9ae4379d008c342dd7af8aac069b8b31d84 Mon Sep 17 00:00:00 2001 From: Rainer Keller Date: Fri, 4 Dec 2015 10:36:16 +0100 Subject: Remove additional copyright notice MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I181579d755a79e2e0a26ff2de119d9642183a2ca Reviewed-by: Jani Heikkinen Reviewed-by: Topi Reiniö (cherry picked from commit 2766215c9ec68bf175c0ddafbd7be5a03b403795) Reviewed-by: Oswald Buddenhagen Reviewed-by: Simon Hausmann --- src/widgets/doc/snippets/qlistview-dnd/model.cpp | 10 ---------- src/widgets/doc/snippets/qlistview-dnd/model.h | 10 ---------- 2 files changed, 20 deletions(-) diff --git a/src/widgets/doc/snippets/qlistview-dnd/model.cpp b/src/widgets/doc/snippets/qlistview-dnd/model.cpp index 846ca94e14..80b2a4ec1f 100644 --- a/src/widgets/doc/snippets/qlistview-dnd/model.cpp +++ b/src/widgets/doc/snippets/qlistview-dnd/model.cpp @@ -38,16 +38,6 @@ ** ****************************************************************************/ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of an example program for Qt. -** EDITIONS: NOLIMITS -** -****************************************************************************/ - /* model.cpp diff --git a/src/widgets/doc/snippets/qlistview-dnd/model.h b/src/widgets/doc/snippets/qlistview-dnd/model.h index b4c8196341..fd00a9b986 100644 --- a/src/widgets/doc/snippets/qlistview-dnd/model.h +++ b/src/widgets/doc/snippets/qlistview-dnd/model.h @@ -38,16 +38,6 @@ ** ****************************************************************************/ -/**************************************************************************** -** -** Copyright (C) 2015 The Qt Company Ltd. -** Contact: http://www.qt.io/licensing/ -** -** This file is part of an example program for Qt. -** EDITIONS: NOLIMITS -** -****************************************************************************/ - #ifndef MODEL_H #define MODEL_H -- cgit v1.2.3 From faf4865b8008da895ce587091950e711744df55f Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 4 Dec 2015 12:10:48 +0100 Subject: Use unique shortcuts for the different actions MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: Ibc143ffac83dfb30facc9e93651e5f18550ab612 Reviewed-by: Topi Reiniö --- examples/widgets/graphicsview/diagramscene/mainwindow.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/examples/widgets/graphicsview/diagramscene/mainwindow.cpp b/examples/widgets/graphicsview/diagramscene/mainwindow.cpp index a57dbaa9a0..02479c1a5a 100644 --- a/examples/widgets/graphicsview/diagramscene/mainwindow.cpp +++ b/examples/widgets/graphicsview/diagramscene/mainwindow.cpp @@ -389,7 +389,7 @@ void MainWindow::createActions() //! [23] sendBackAction = new QAction(QIcon(":/images/sendtoback.png"), tr("Send to &Back"), this); - sendBackAction->setShortcut(tr("Ctrl+B")); + sendBackAction->setShortcut(tr("Ctrl+T")); sendBackAction->setStatusTip(tr("Send item to back")); connect(sendBackAction, SIGNAL(triggered()), this, SLOT(sendToBack())); @@ -421,7 +421,7 @@ void MainWindow::createActions() connect(underlineAction, SIGNAL(triggered()), this, SLOT(handleFontChange())); aboutAction = new QAction(tr("A&bout"), this); - aboutAction->setShortcut(tr("Ctrl+B")); + aboutAction->setShortcut(tr("F1")); connect(aboutAction, SIGNAL(triggered()), this, SLOT(about())); } -- cgit v1.2.3 From 1440c13c8c1ed8eaa99c5d5edbd6fa61fd5eee8b Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 10 Dec 2015 11:37:59 +0100 Subject: Check if the file is writable even while QT_BOOTSTRAPPED QConfFile::isWritable() has the extra effect that it will try and create the path where the file should be if it does not already exist. So this cannot be omitted as 'qmake -set' may be used in a situation where the path does not yet exist. Change-Id: I0113644259f78d090a0687c44cf60d400be9c859 Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qsettings.cpp | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qsettings.cpp b/src/corelib/io/qsettings.cpp index 413f5693f0..52bcb153ae 100644 --- a/src/corelib/io/qsettings.cpp +++ b/src/corelib/io/qsettings.cpp @@ -1383,13 +1383,17 @@ void QConfFileSettingsPrivate::syncConfFile(int confFileNo) Concurrent read and write are not a problem because the writing operation is atomic. */ QLockFile lockFile(confFile->name + QLatin1String(".lock")); +#endif if (!readOnly) { - if (!confFile->isWritable() || !lockFile.lock() ) { + if (!confFile->isWritable() +#ifndef QT_BOOTSTRAPPED + || !lockFile.lock() +#endif + ) { setStatus(QSettings::AccessError); return; } } -#endif /* We hold the lock. Let's reread the file if it has changed -- cgit v1.2.3 From 6e14d63db023fdad223d9dc35b0e1ba31aac997d Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 7 Dec 2015 14:52:33 +0100 Subject: Add explicit note about removeMappings() not disconnecting the signal MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit There can be a bit of confusion here regarding what removeMappings() will do in this case so add an explicit note to be clearer. Task-number: QTBUG-49499 Change-Id: Iabcf5cb2653f0b747727b2c92a244e95ec1836f8 Reviewed-by: Topi Reiniö --- src/corelib/kernel/qsignalmapper.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/corelib/kernel/qsignalmapper.cpp b/src/corelib/kernel/qsignalmapper.cpp index 00aa31383f..5e8ce0c251 100644 --- a/src/corelib/kernel/qsignalmapper.cpp +++ b/src/corelib/kernel/qsignalmapper.cpp @@ -220,6 +220,9 @@ QObject *QSignalMapper::mapping(QObject *object) const Removes all mappings for \a sender. This is done automatically when mapped objects are destroyed. + + \note This does not disconnect any signals. If \a sender is not destroyed + then this will need to be done explicitly if required. */ void QSignalMapper::removeMappings(QObject *sender) { -- cgit v1.2.3 From 672f7dfdcd00d124cd0f973e04e3e2d6445d5483 Mon Sep 17 00:00:00 2001 From: Juha Turunen Date: Tue, 8 Dec 2015 00:51:54 -0800 Subject: Fix a crash when calling QOpenGLTexture::setData with a null QImage. Change-Id: Idf8ae00cff6929114b38dcb003c259c83a11dbaa Reviewed-by: Laszlo Agocs --- src/gui/opengl/qopengltexture.cpp | 6 ++++++ tests/auto/gui/qopengl/tst_qopengl.cpp | 15 ++++++++++++++- 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/src/gui/opengl/qopengltexture.cpp b/src/gui/opengl/qopengltexture.cpp index 5271826015..c58ddbd71e 100644 --- a/src/gui/opengl/qopengltexture.cpp +++ b/src/gui/opengl/qopengltexture.cpp @@ -3050,6 +3050,12 @@ void QOpenGLTexture::setData(const QImage& image, MipMapGeneration genMipMaps) qWarning("QOpenGLTexture::setData() requires a valid current context"); return; } + + if (image.isNull()) { + qWarning("QOpenGLTexture::setData() tried to set a null image"); + return; + } + if (context->isOpenGLES() && context->format().majorVersion() < 3) setFormat(QOpenGLTexture::RGBAFormat); else diff --git a/tests/auto/gui/qopengl/tst_qopengl.cpp b/tests/auto/gui/qopengl/tst_qopengl.cpp index 8c6c28b492..3e66bcbf70 100644 --- a/tests/auto/gui/qopengl/tst_qopengl.cpp +++ b/tests/auto/gui/qopengl/tst_qopengl.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include #include #include @@ -97,8 +98,8 @@ private slots: void textureblitterFullTargetRectTransform(); void textureblitterPartTargetRectTransform(); void defaultSurfaceFormat(); - void imageFormatPainting(); + void nullTextureInitializtion(); #ifdef USE_GLX void glxContextWrap(); @@ -1367,6 +1368,18 @@ void tst_QOpenGL::bufferMapRange() ctx->doneCurrent(); } +void tst_QOpenGL::nullTextureInitializtion() +{ + QScopedPointer surface(createSurface(QSurface::Window)); + QOpenGLContext ctx; + ctx.create(); + ctx.makeCurrent(surface.data()); + + QImage i; + QOpenGLTexture t(i); + QVERIFY(!t.isCreated()); +} + QTEST_MAIN(tst_QOpenGL) #include "tst_qopengl.moc" -- cgit v1.2.3 From b2c7c489ab40efb1f2f64aba5b90f5f4fb8d8536 Mon Sep 17 00:00:00 2001 From: David Fries Date: Tue, 24 Nov 2015 17:29:59 -0600 Subject: QLockFile: decide on locking strategy per path It is filesystem dependent if flock and fcntl locks are independent or the same underlying lock (which causes getting the second lock to fail). A temporary file in /tmp might be on a local file system and pass while the lock file is placed on NFS and fail with: setNativeLocks failed: Resource temporarily unavailable Instead check for lock conflicts per path and cache the result. Change-Id: I39c59bb240cd99ef0a0ec271243770ffd5df8a7d Reviewed-by: David Faure --- src/corelib/io/qlockfile_p.h | 2 +- src/corelib/io/qlockfile_unix.cpp | 42 +++++++++++++++++++++++++++------------ 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/src/corelib/io/qlockfile_p.h b/src/corelib/io/qlockfile_p.h index 168062f467..48b642abd0 100644 --- a/src/corelib/io/qlockfile_p.h +++ b/src/corelib/io/qlockfile_p.h @@ -78,7 +78,7 @@ public: static QString processNameByPid(qint64 pid); #ifdef Q_OS_UNIX - static int checkFcntlWorksAfterFlock(); + static int checkFcntlWorksAfterFlock(const QString &fn); #endif QString fileName; diff --git a/src/corelib/io/qlockfile_unix.cpp b/src/corelib/io/qlockfile_unix.cpp index bd9f8a5988..667b108ba0 100644 --- a/src/corelib/io/qlockfile_unix.cpp +++ b/src/corelib/io/qlockfile_unix.cpp @@ -39,6 +39,10 @@ #include "QtCore/qfileinfo.h" #include "QtCore/qdebug.h" #include "QtCore/qdatetime.h" +#include "QtCore/qfileinfo.h" +#include "QtCore/qcache.h" +#include "QtCore/qglobalstatic.h" +#include "QtCore/qmutex.h" #include "private/qcore_unix_p.h" // qt_safe_open #include "private/qabstractfileengine_p.h" @@ -89,10 +93,10 @@ static qint64 qt_write_loop(int fd, const char *data, qint64 len) return pos; } -int QLockFilePrivate::checkFcntlWorksAfterFlock() +int QLockFilePrivate::checkFcntlWorksAfterFlock(const QString &fn) { #ifndef QT_NO_TEMPORARYFILE - QTemporaryFile file; + QTemporaryFile file(fn); if (!file.open()) return 0; const int fd = file.d_func()->engine()->handle(); @@ -114,24 +118,34 @@ int QLockFilePrivate::checkFcntlWorksAfterFlock() #endif } -static QBasicAtomicInt fcntlOK = Q_BASIC_ATOMIC_INITIALIZER(-1); +// Cache the result of checkFcntlWorksAfterFlock for each directory a lock +// file is created in because in some filesystems, like NFS, both locks +// are the same. This does not take into account a filesystem changing. +// QCache is set to hold a maximum of 10 entries, this is to avoid unbounded +// growth, this is caching directories of files and it is assumed a low number +// will be sufficient. +typedef QCache CacheType; +Q_GLOBAL_STATIC_WITH_ARGS(CacheType, fcntlOK, (10)); +static QBasicMutex fcntlLock; /*! \internal Checks that the OS isn't using POSIX locks to emulate flock(). OS X is one of those. */ -static bool fcntlWorksAfterFlock() +static bool fcntlWorksAfterFlock(const QString &fn) { - int value = fcntlOK.load(); - if (Q_UNLIKELY(value == -1)) { - value = QLockFilePrivate::checkFcntlWorksAfterFlock(); - fcntlOK.store(value); + QMutexLocker lock(&fcntlLock); + bool *worksPtr = fcntlOK->object(fn); + if (!worksPtr) { + worksPtr = new bool(QLockFilePrivate::checkFcntlWorksAfterFlock(fn)); + fcntlOK->insert(fn, worksPtr); } - return value == 1; + + return *worksPtr; } -static bool setNativeLocks(int fd) +static bool setNativeLocks(const QString &fileName, int fd) { #if defined(LOCK_EX) && defined(LOCK_NB) if (flock(fd, LOCK_EX | LOCK_NB) == -1) // other threads, and other processes on a local fs @@ -143,8 +157,10 @@ static bool setNativeLocks(int fd) flockData.l_start = 0; flockData.l_len = 0; // 0 = entire file flockData.l_pid = getpid(); - if (fcntlWorksAfterFlock() && fcntl(fd, F_SETLK, &flockData) == -1) // for networked filesystems + if (fcntlWorksAfterFlock(QDir::cleanPath(QFileInfo(fileName).absolutePath()) + QString('/')) + && fcntl(fd, F_SETLK, &flockData) == -1) { // for networked filesystems return false; + } return true; } @@ -171,7 +187,7 @@ QLockFile::LockError QLockFilePrivate::tryLock_sys() } } // Ensure nobody else can delete the file while we have it - if (!setNativeLocks(fd)) { + if (!setNativeLocks(fileName, fd)) { const int errnoSaved = errno; qWarning() << "setNativeLocks failed:" << qt_error_string(errnoSaved); } @@ -195,7 +211,7 @@ bool QLockFilePrivate::removeStaleLock() const int fd = qt_safe_open(lockFileName.constData(), O_WRONLY, 0644); if (fd < 0) // gone already? return false; - bool success = setNativeLocks(fd) && (::unlink(lockFileName) == 0); + bool success = setNativeLocks(fileName, fd) && (::unlink(lockFileName) == 0); close(fd); return success; } -- cgit v1.2.3 From e8eaf82e584c2d27bdeb0a50055e10d55d9c00dc Mon Sep 17 00:00:00 2001 From: Vincas Dargis Date: Sat, 5 Dec 2015 15:20:34 +0200 Subject: PostgreSQL: Fix memory leak in QPSQLDriverPrivate::getPSQLVersion() Memory leak occurs when 'release' pointer variable is overwritten for second use without releasing resources it is currently pointing to. Leak occurs only in specific edge case depending on client/server versions. Task-number: QTBUG-49789 Change-Id: Ie5be8996ed158309f20dbb3574f956d2eb137460 Reviewed-by: Mark Brand --- src/sql/drivers/psql/qsql_psql.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/src/sql/drivers/psql/qsql_psql.cpp b/src/sql/drivers/psql/qsql_psql.cpp index f4e40b6582..4795738b66 100644 --- a/src/sql/drivers/psql/qsql_psql.cpp +++ b/src/sql/drivers/psql/qsql_psql.cpp @@ -757,6 +757,7 @@ QPSQLDriver::Protocol QPSQLDriverPrivate::getPSQLVersion() //Client version before QPSQLDriver::Version9 only supports escape mode for bytea type, //but bytea format is set to hex by default in PSQL 9 and above. So need to force the //server use the old escape mode when connects to the new server with old client library. + PQclear(result); result = exec("SET bytea_output=escape; "); status = PQresultStatus(result); } else if (serverVersion == QPSQLDriver::VersionUnknown) { -- cgit v1.2.3 From 7ac5228144b692e40d40dfcfe2e3799f2ad4c620 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pasi=20Pet=C3=A4j=C3=A4j=C3=A4rvi?= Date: Thu, 12 Nov 2015 16:23:42 +0200 Subject: Delete QInputDeviceManager when deleting QGuiApplication Without deleting m_inputDeviceManager instance it will remain in process and causes crash when creating+destroying QGuiApplication multiple times in process. Crash happens because m_inputDeviceManager already exists when creating new instance of QGuiApplication and metadata for QInputDeviceManager is not anymore valid and crash when accessing it e.g. using connect() function. Change-Id: I5acb1c5f6ce2ba9665fa893047210a913debe4e4 Reviewed-by: Laszlo Agocs --- src/gui/kernel/qguiapplication.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp index 64be8ee3d9..c2b561aa93 100644 --- a/src/gui/kernel/qguiapplication.cpp +++ b/src/gui/kernel/qguiapplication.cpp @@ -603,6 +603,8 @@ QGuiApplication::~QGuiApplication() QGuiApplicationPrivate::platform_name = 0; delete QGuiApplicationPrivate::displayName; QGuiApplicationPrivate::displayName = 0; + delete QGuiApplicationPrivate::m_inputDeviceManager; + QGuiApplicationPrivate::m_inputDeviceManager = 0; } QGuiApplicationPrivate::QGuiApplicationPrivate(int &argc, char **argv, int flags) -- cgit v1.2.3 From 3fb0d851a08b7912152f98096c7308b3c430e605 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Mon, 14 Dec 2015 11:51:33 +0100 Subject: Emit the activated signal when the platform menu item is selected. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I3485501643c60f28ef188100146ac305e3ef9073 Reviewed-by: Tor Arne Vestbø Reviewed-by: Timur Pocheptsov --- src/widgets/widgets/qcombobox.cpp | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/widgets/widgets/qcombobox.cpp b/src/widgets/widgets/qcombobox.cpp index c97159d4cb..b04aa7053a 100644 --- a/src/widgets/widgets/qcombobox.cpp +++ b/src/widgets/widgets/qcombobox.cpp @@ -2425,7 +2425,11 @@ struct IndexSetter { int index; QComboBox *cb; - void operator()(void) { cb->setCurrentIndex(index); } + void operator()(void) + { + cb->setCurrentIndex(index); + emit cb->activated(index); + } }; } -- cgit v1.2.3 From e109b8a0f3c89c595f0da689e7ee847130e2ee47 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Thu, 10 Dec 2015 08:35:14 +0100 Subject: Decrease the cache if necessary when adding a new font It was possible for the cache to increase too quickly since it was relying on the timer to decrease which caused problems with FreeType. So by checking if it will be increased to be over the limit first before adding the new font, we can decrease it earlier in preparation. Task-number: QTBUG-47812 Task-number: QTBUG-49535 Change-Id: Iedc042d8903949140aa8c5257a9d54cde31a51be Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfont.cpp | 12 +++++++++++- src/gui/text/qfont_p.h | 1 + 2 files changed, 12 insertions(+), 1 deletion(-) diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp index 3c6709e685..16550c0b3c 100644 --- a/src/gui/text/qfont.cpp +++ b/src/gui/text/qfont.cpp @@ -2793,6 +2793,10 @@ void QFontCache::insertEngineData(const QFontDef &def, QFontEngineData *engineDa Q_ASSERT(!engineDataCache.contains(def)); engineData->ref.ref(); + // Decrease now rather than waiting + if (total_cost > min_cost * 2) + decreaseCache(); + engineDataCache.insert(def, engineData); increaseCost(sizeof(QFontEngineData)); } @@ -2830,8 +2834,10 @@ void QFontCache::insertEngine(const Key &key, QFontEngine *engine, bool insertMu key.def.pixelSize, key.def.weight, key.def.style, key.def.fixedPitch); } #endif - engine->ref.ref(); + // Decrease now rather than waiting + if (total_cost > min_cost * 2) + decreaseCache(); Engine data(engine); data.timestamp = ++current_timestamp; @@ -2892,7 +2898,11 @@ void QFontCache::timerEvent(QTimerEvent *) return; } + decreaseCache(); +} +void QFontCache::decreaseCache() +{ // go through the cache and count up everything in use uint in_use_cost = 0; diff --git a/src/gui/text/qfont_p.h b/src/gui/text/qfont_p.h index 25b5ef0b0e..ff9265ca19 100644 --- a/src/gui/text/qfont_p.h +++ b/src/gui/text/qfont_p.h @@ -276,6 +276,7 @@ private: void increaseCost(uint cost); void decreaseCost(uint cost); void timerEvent(QTimerEvent *event) Q_DECL_OVERRIDE; + void decreaseCache(); static const uint min_cost; uint total_cost, max_cost; -- cgit v1.2.3 From a88da6377da2e10998574ccc709bec014e2b75a5 Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Wed, 16 Dec 2015 13:59:54 +0100 Subject: The cache_cost is measured in bytes and not kilobytes. When increaseCost() is called then it will convert from bytes to kilobytes so we need to specify the cache_cost to be in bytes. Task-number: QTBUG-47812 Change-Id: I842514c9ab4d86b60b2beb6c80979156ea0de59c Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontengine_ft.cpp | 2 +- src/gui/text/qfontengine_p.h | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/src/gui/text/qfontengine_ft.cpp b/src/gui/text/qfontengine_ft.cpp index 37be0afccf..1177305f6e 100644 --- a/src/gui/text/qfontengine_ft.cpp +++ b/src/gui/text/qfontengine_ft.cpp @@ -621,7 +621,7 @@ QFontEngineFT::QFontEngineFT(const QFontDef &fd) matrix.yy = 0x10000; matrix.xy = 0; matrix.yx = 0; - cache_cost = 100; + cache_cost = 100 * 1024; kerning_pairs_loaded = false; transform = false; embolden = false; diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h index bb34155d31..6f4fabe1f6 100644 --- a/src/gui/text/qfontengine_p.h +++ b/src/gui/text/qfontengine_p.h @@ -277,7 +277,7 @@ public: qt_get_font_table_func_t get_font_table; } faceData; - uint cache_cost; // amount of mem used in kb by the font + uint cache_cost; // amount of mem used in bytes by the font uint fsType : 16; bool symbol; struct KernPair { -- cgit v1.2.3 From ad5c768fc8b93e22201fb557561b2edd4fcdc26b Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 7 Dec 2015 14:53:22 +0100 Subject: Update bundled libpng to version 1.6.19 Merged in the upstream version, which obsoleted some local patches. The remaining diff to clean 1.6.19 is archived in the qtpatches.diff file. Change-Id: I676df2dab2c52c7fe576de284d472d70206f0a8c Reviewed-by: Konstantin Ritt Reviewed-by: aavit --- src/3rdparty/libpng/ANNOUNCE | 137 ++++-- src/3rdparty/libpng/CHANGES | 298 ++++++++++-- src/3rdparty/libpng/INSTALL | 20 - src/3rdparty/libpng/LICENSE | 55 +-- src/3rdparty/libpng/README | 4 +- src/3rdparty/libpng/libpng-manual.txt | 356 +++++++------- src/3rdparty/libpng/png.c | 164 ++++--- src/3rdparty/libpng/png.h | 471 ++++++------------- src/3rdparty/libpng/pngconf.h | 24 +- src/3rdparty/libpng/pnglibconf.h | 8 +- src/3rdparty/libpng/pngmem.c | 3 + src/3rdparty/libpng/pngpread.c | 113 +---- src/3rdparty/libpng/pngpriv.h | 45 +- src/3rdparty/libpng/pngread.c | 31 +- src/3rdparty/libpng/pngrio.c | 2 +- src/3rdparty/libpng/pngrtran.c | 30 +- src/3rdparty/libpng/pngrutil.c | 386 ++++++++------- src/3rdparty/libpng/pngset.c | 33 +- src/3rdparty/libpng/pngstruct.h | 32 +- src/3rdparty/libpng/pngtrans.c | 8 +- src/3rdparty/libpng/pngwio.c | 2 +- src/3rdparty/libpng/pngwrite.c | 599 ++++++++--------------- src/3rdparty/libpng/pngwtran.c | 14 +- src/3rdparty/libpng/pngwutil.c | 860 +++++++++++----------------------- src/3rdparty/libpng/qtpatches.diff | 37 +- 25 files changed, 1612 insertions(+), 2120 deletions(-) diff --git a/src/3rdparty/libpng/ANNOUNCE b/src/3rdparty/libpng/ANNOUNCE index 131e0aa369..9f1b665834 100644 --- a/src/3rdparty/libpng/ANNOUNCE +++ b/src/3rdparty/libpng/ANNOUNCE @@ -1,4 +1,4 @@ -Libpng 1.6.17 - March 26, 2015 +Libpng 1.6.19 - November 12, 2015 This is a public release of libpng, intended for use in production codes. @@ -7,61 +7,104 @@ Files available for download: Source files with LF line endings (for Unix/Linux) and with a "configure" script - libpng-1.6.17.tar.xz (LZMA-compressed, recommended) - libpng-1.6.17.tar.gz + libpng-1.6.19.tar.xz (LZMA-compressed, recommended) + libpng-1.6.19.tar.gz Source files with CRLF line endings (for Windows), without the "configure" script - lpng1617.7z (LZMA-compressed, recommended) - lpng1617.zip + lpng1619.7z (LZMA-compressed, recommended) + lpng1619.zip Other information: - libpng-1.6.17-README.txt - libpng-1.6.17-LICENSE.txt - libpng-1.6.17-*.asc (armored detached GPG signatures) + libpng-1.6.19-README.txt + libpng-1.6.19-LICENSE.txt + libpng-1.6.19-*.asc (armored detached GPG signatures) -Changes since the last public release (1.6.16): +Changes since the last public release (1.6.18): - Removed duplicate PNG_SAFE_LIMITS_SUPPORTED handling from pngconf.h - Corrected the width limit calculation in png_check_IHDR(). - Removed user limits from pngfix. Also pass NULL pointers to - png_read_row to skip the unnecessary row de-interlace stuff. - Added testing of png_set_packing() to pngvalid.c - Regenerated configure scripts in the *.tar distributions with libtool-2.4.4 - Implement previously untested cases of libpng transforms in pngvalid.c - Fixed byte order in 2-byte filler, in png_do_read_filler(). - Made the check for out-of-range values in png_set_tRNS() detect - values that are exactly 2^bit_depth, and work on 16-bit platforms. - Merged some parts of libpng-1.6.17beta01 and libpng-1.7.0beta47. - Added #ifndef __COVERITY__ where needed in png.c, pngrutil.c and - pngset.c to avoid warnings about dead code. - Do not build png_product2() when it is unused. - Display user limits in the output from pngtest. - Eliminated the PNG_SAFE_LIMITS macro and restored the 1-million-column - and 1-million-row default limits in pnglibconf.dfa, that can be reset - by the user at build time or run time. This provides a more robust - defense against DOS and as-yet undiscovered overflows. - Added PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED macro, on by default. - Allow user to call png_get_IHDR() with NULL arguments (Reuben Hawkins). - Rebuilt configure scripts with automake-1.15 and libtool-2.4.6 - Moved png_set_filter() prototype into a PNG_WRITE_SUPPORTED block - of png.h. - Avoid runtime checks when converting integer to png_byte with - Visual Studio (Sergey Kosarevsky) - Removed some comments that the configure script did not handle - properly from scripts/pnglibconf.dfa and pnglibconf.h.prebuilt. - Free the unknown_chunks structure even when it contains no data. - Updated CMakeLists.txt to add OSX framework, change YES/NO to ON/OFF - for consistency, and remove some useless tests (Alexey Petruchik). - Remove pnglibconf.h, pnglibconf.c, pnglibconf.pre, pnglibconf.dfn, - and pnglibconf.out instead of pnglibconf.* in "make clean" (Cosmin). - Fixed simplified 8-bit-linear to sRGB alpha. The calculated alpha - value was wrong. It's not clear if this affected the final stored - value; in the obvious code path the upper and lower 8-bits of the - alpha value were identical and the alpha was truncated to 8-bits - rather than dividing by 257 (John Bowler). + Updated obsolete information about the simplified API macros in the + manual pages (Bug report by Arc Riley). + Avoid potentially dereferencing NULL info_ptr in png_info_init_3(). + Rearranged png.h to put the major sections in the same order as + in libpng17. + Eliminated unused PNG_COST_SHIFT, PNG_WEIGHT_SHIFT, PNG_COST_FACTOR, and + PNG_WEIGHT_FACTOR macros. + Suppressed some warnings from the Borland C++ 5.5.1/5.82 compiler + (Bug report by Viktor Szakats). Several warnings remain and are + unavoidable, where we test for overflow. + Fixed potential leak of png_pixels in contrib/pngminus/pnm2png.c + Fixed uninitialized variable in contrib/gregbook/rpng2-x.c + Moved config.h.in~ from the "libpng_autotools_files" list to the + "libpng_autotools_extra" list in autogen.sh because it was causing a + false positive for missing files (bug report by Robert C. Seacord). + Removed unreachable "break" statements in png.c, pngread.c, and pngrtran.c + to suppress clang warnings (Bug report by Viktor Szakats). + Fixed some bad links in the man page. + Changed "n bit" to "n-bit" in comments. + Added signed/unsigned 16-bit safety net. This removes the dubious + 0x8000 flag definitions on 16-bit systems. They aren't supported + yet the defs *probably* work, however it seems much safer to do this + and be advised if anyone, contrary to advice, is building libpng 1.6 + on a 16-bit system. It also adds back various switch default clauses + for GCC; GCC errors out if they are not present (with an appropriately + high level of warnings). + Safely convert num_bytes to a png_byte in png_set_sig_bytes() (Robert + Seacord). + Fixed the recently reported 1's complement security issue by replacing + the value that is illegal in the PNG spec, in both signed and unsigned + values, with 0. Illegal unsigned values (anything greater than or equal + to 0x80000000) can still pass through, but since these are not illegal + in ANSI-C (unlike 0x80000000 in the signed case) the checking that + occurs later can catch them (John Bowler). + Fixed png_save_int_32 when int is not 2's complement (John Bowler). + Updated libpng16 with all the recent test changes from libpng17, + including changes to pngvalid.c to ensure that the original, + distributed, version of contrib/visupng/cexcept.h can be used + (John Bowler). + pngvalid contains the correction to the use of SAVE/STORE_ + UNKNOWN_CHUNKS; a bug revealed by changes in libpng 1.7. More + tests contain the --strict option to detect warnings and the + pngvalid-standard test has been corrected so that it does not + turn on progressive-read. There is a separate test which does + that. (John Bowler) + Also made some signed/unsigned fixes. + Make pngstest error limits version specific. Splitting the machine + generated error structs out to a file allows the values to be updated + without changing pngstest.c itself. Since libpng 1.6 and 1.7 have + slightly different error limits this simplifies maintenance. The + makepngs.sh script has also been updated to more accurately reflect + current problems in libpng 1.7 (John Bowler). + Incorporated new test PNG files into make check. tests/pngstest-* + are changed so that the new test files are divided into 8 groups by + gamma and alpha channel. These tests have considerably better code + and pixel-value coverage than contrib/pngsuite; however,coverage is + still incomplete (John Bowler). + Removed the '--strict' in 1.6 because of the double-gamma-correction + warning, updated pngstest-errors.h for the errors detected with the + new contrib/testspngs PNG test files (John Bowler). + Worked around rgb-to-gray issues in libpng 1.6. The previous + attempts to ignore the errors in the code aren't quite enough to + deal with the 'channel selection' encoding added to libpng 1.7; abort. + Fixed 'pow' macros in pngvalid.c. It is legal for 'pow' to be a + macro, therefore the argument list cannot contain preprocessing + directives. Make sure pow is a function where this happens. This is + a minimal safe fix, the issue only arises in non-performance-critical + code (bug report by Curtis Leach, fix by John Bowler). + Added sPLT support to pngtest.c + Prevent setting or writing over-length PLTE chunk (Cosmin Truta). + Silently truncate over-length PLTE chunk while reading. + Libpng incorrectly calculated the output rowbytes when the application + decreased either the number of channels or the bit depth (or both) in + a user transform. This was safe; libpng overallocated buffer space + (potentially by quite a lot; up to 4 times the amount required) but, + from 1.5.4 on, resulted in a png_error (John Bowler). + Fixed some inconsequential cut-and-paste typos in png_set_cHRM_XYZ_fixed(). + Clarified COPYRIGHT information to state explicitly that versions + are derived from previous versions. + Removed much of the long list of previous versions from png.h and + libpng.3. Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit diff --git a/src/3rdparty/libpng/CHANGES b/src/3rdparty/libpng/CHANGES index 1be09e9385..2e4d2bb292 100644 --- a/src/3rdparty/libpng/CHANGES +++ b/src/3rdparty/libpng/CHANGES @@ -1,11 +1,14 @@ - +#if 0 CHANGES - changes for libpng -Version 0.2 +version 0.1 [March 29, 1995] + initial work-in-progress release + +version 0.2 [April 1, 1995] added reader into png.h fixed small problems in stub file -Version 0.3 +version 0.3 [April 8, 1995] added pull reader split up pngwrite.c to several files added pnglib.txt @@ -14,9 +17,9 @@ Version 0.3 fixed some bugs in writer interfaced with zlib 0.5 added K&R support - added check for 64 KB blocks for 16-bit machines + added check for 64 KB blocks for 16 bit machines -Version 0.4 +version 0.4 [April 26, 1995] cleaned up code and commented code simplified time handling into png_time created png_color_16 and png_color_8 to handle color needs @@ -27,28 +30,29 @@ Version 0.4 cleaned up zTXt reader and writer (using zlib's Reset functions) split transformations into pngrtran.c and pngwtran.c -Version 0.5 +version 0.5 [April 30, 1995] interfaced with zlib 0.8 fixed many reading and writing bugs saved using 3 spaces instead of tabs -Version 0.6 +version 0.6 [May 1, 1995] + first beta release added png_large_malloc() and png_large_free() added png_size_t cleaned up some compiler warnings added png_start_read_image() -Version 0.7 +version 0.7 [June 24, 1995] cleaned up lots of bugs finished dithering and other stuff added test program changed name from pnglib to libpng -Version 0.71 [June, 1995] +version 0.71 [June 26, 1995] changed pngtest.png for zlib 0.93 fixed error in libpng.txt and example.c -Version 0.8 +version 0.8 [August 20, 1995] cleaned up some bugs added png_set_filler() split up pngstub.c into pngmem.c, pngio.c, and pngerror.c @@ -91,7 +95,7 @@ Version 0.88 [January, 1996] cleaned up documentation added callbacks for read/write and warning/error functions -Version 0.89 [July, 1996] +Version 0.89 [June 5, 1996] Added new initialization API to make libpng work better with shared libs we now have png_create_read_struct(), png_create_write_struct(), png_create_info_struct(), png_destroy_read_struct(), and @@ -118,6 +122,9 @@ Version 0.89 [July, 1996] New pngtest image also has interlacing and zTXt Updated documentation to reflect new API +Version 0.89c [June 17, 1996] + Bug fixes. + Version 0.90 [January, 1997] Made CRC errors/warnings on critical and ancillary chunks configurable libpng will use the zlib CRC routines by (compile-time) default @@ -158,7 +165,7 @@ Version 0.95 [March, 1997] Added new pCAL chunk read/write support Added experimental filter selection weighting (Greg Roelofs) Removed old png_set_rgbx() and png_set_xrgb() functions that have been - obsolete for about 2 years now (use png_set_filler() instead) + obsolete for about 2 years now (use png_set_filler() instead) Added macros to read 16- and 32-bit ints directly from buffer, to be used only on those systems that support it (namely PowerPC and 680x0) With some testing, this may become the default for MACOS/PPC systems. @@ -440,7 +447,7 @@ Version 1.0.3 [January 14, 1999] Version 1.0.3a [August 12, 1999] Added check for PNG_READ_INTERLACE_SUPPORTED in pngread.c; issue a warning - if an attempt is made to read an interlaced image when it's not supported. + if an attempt is made to read an interlaced image when it's not supported. Added check if png_ptr->trans is defined before freeing it in pngread.c Modified the Y2K statement to include versions back to version 0.71 Fixed a bug in the check for valid IHDR bit_depth/color_types in pngrutil.c @@ -448,7 +455,7 @@ Version 1.0.3a [August 12, 1999] Replaced leading blanks with tab characters in makefile.hux Changed "dworkin.wustl.edu" to "ccrc.wustl.edu" in various documents. Changed (float)red and (float)green to (double)red, (double)green - in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. + in png_set_rgb_to_gray() to avoid "promotion" problems in AIX. Fixed a bug in pngconf.h that omitted when PNG_DEBUG==0 (K Bracey). Reformatted libpng.3 and libpngpf.3 with proper fonts (script by J. vanZandt). Updated documentation to refer to the PNG-1.2 specification. @@ -491,7 +498,7 @@ Version 1.0.3d [September 4, 1999] Added new png_expand functions to scripts/pngdef.pas and pngos2.def Added a demo read_user_transform_fn that examines the row filters in pngtest.c -Version 1.0.4 [September 24, 1999] +Version 1.0.4 [September 24, 1999, not distributed publicly] Define PNG_ALWAYS_EXTERN in pngconf.h if __STDC__ is defined Delete #define PNG_INTERNAL and include "png.h" from pngasmrd.h Made several minor corrections to pngtest.c @@ -518,6 +525,7 @@ Version 1.0.4c [October 1, 1999] Added a "png_check_version" function in png.c and pngtest.c that will generate a helpful compiler error if an old png.h is found in the search path. Changed type of png_user_transform_depth|channels from int to png_byte. + Added "Libpng is OSI Certified Open Source Software" statement to png.h Version 1.0.4d [October 6, 1999] Changed 0.45 to 0.45455 in png_set_sRGB() @@ -904,7 +912,7 @@ Version 1.0.7 [July 1, 2000] Version 1.0.8beta1 [July 8, 2000] Added png_free(png_ptr, key) two places in pngpread.c to stop memory leaks. Changed PNG_NO_STDIO to PNG_NO_CONSOLE_IO, several places in pngrutil.c and - pngwutil.c. + pngwutil.c. Changed PNG_EXPORT_VAR to use PNG_IMPEXP, in pngconf.h. Removed unused "#include " from png.c Added WindowsCE support. @@ -912,12 +920,12 @@ Version 1.0.8beta1 [July 8, 2000] Version 1.0.8beta2 [July 10, 2000] Added project files to the wince directory and made further revisions - of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. + of pngtest.c, pngrio.c, and pngwio.c in support of WindowsCE. Version 1.0.8beta3 [July 11, 2000] Only set the PNG_FLAG_FREE_TRNS or PNG_FREE_TRNS flag in png_handle_tRNS() - for indexed-color input files to avoid potential double-freeing trans array - under some unusual conditions; problem was introduced in version 1.0.6f. + for indexed-color input files to avoid potential double-freeing trans array + under some unusual conditions; problem was introduced in version 1.0.6f. Further revisions to pngtest.c and files in the wince subdirectory. Version 1.0.8beta4 [July 14, 2000] @@ -1089,16 +1097,16 @@ Version 1.2.0beta3 [May 17, 2001] Version 1.2.0beta4 [June 23, 2001] Check for missing profile length field in iCCP chunk and free chunk_data - in case of truncated iCCP chunk. + in case of truncated iCCP chunk. Bumped shared-library number to 3 in makefile.sgi and makefile.sggcc Bumped dll-number from 2 to 3 in makefile.cygwin Revised contrib/gregbook/rpng*-x.c to avoid a memory leak and to exit cleanly - if user attempts to run it on an 8-bit display. + if user attempts to run it on an 8-bit display. Updated contrib/gregbook Use png_malloc instead of png_zalloc to allocate palette in pngset.c Updated makefile.ibmc Added some typecasts to eliminate gcc 3.0 warnings. Changed prototypes - of png_write_oFFS width and height from png_uint_32 to png_int_32. + of png_write_oFFS width and height from png_uint_32 to png_int_32. Updated example.c Revised prototypes for png_debug_malloc and png_debug_free in pngtest.c @@ -1106,9 +1114,9 @@ Version 1.2.0beta5 [August 8, 2001] Revised contrib/gregbook Revised makefile.gcmmx Revised pnggccrd.c to conditionally compile some thread-unsafe code only - when PNG_THREAD_UNSAFE_OK is defined. + when PNG_THREAD_UNSAFE_OK is defined. Added tests to prevent pngwutil.c from writing a bKGD or tRNS chunk with - value exceeding 2^bit_depth-1 + value exceeding 2^bit_depth-1 Revised makefile.sgi and makefile.sggcc Replaced calls to fprintf(stderr,...) with png_warning() in pnggccrd.c Removed restriction that do_invert_mono only operate on 1-bit opaque files @@ -1449,8 +1457,9 @@ Version 1.2.6beta4 [July 28, 2004] Use png_malloc instead of png_zalloc to allocate the pallete. Version 1.0.16rc1 and 1.2.6rc1 [August 4, 2004] - Fixed buffer overflow vulnerability in png_handle_tRNS() - Fixed integer arithmetic overflow vulnerability in png_read_png(). + Fixed buffer overflow vulnerability (CVE-2004-0597) in png_handle_tRNS(). + Fixed NULL dereference vulnerability (CVE-2004-0598) in png_handle_iCCP(). + Fixed integer overflow vulnerability (CVE-2004-0599) in png_read_png(). Fixed some harmless bugs in png_handle_sBIT, etc, that would cause duplicate chunk types to go undetected. Fixed some timestamps in the -config version @@ -1493,7 +1502,7 @@ Version 1.0.16rc4 and 1.2.6rc4 [August 10, 2004] Version 1.0.16rc5 and 1.2.6rc5 [August 10, 2004] Moved "PNG_HANDLE_CHUNK_*" macros out of PNG_ASSEMBLER_CODE_SUPPORTED - section of png.h where they were inadvertently placed in version rc3. + section of png.h where they were inadvertently placed in version rc3. Version 1.2.6 and 1.0.16 [August 15, 2004] Revised pngtest so memory allocation testing is only done when PNG_DEBUG==1. @@ -2325,7 +2334,7 @@ Version 1.4.0beta63 [June 15, 2009] Version 1.4.0beta64 [June 24, 2009] Eliminated PNG_LEGACY_SUPPORTED code. Moved the various unknown chunk macro definitions outside of the - PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. + PNG_READ|WRITE_ANCILLARY_CHUNK_SUPPORTED blocks. Version 1.4.0beta65 [June 26, 2009] Added a reference to the libpng license in each file. @@ -3747,8 +3756,9 @@ Version 1.5.7beta04 [November 17, 2011] Version 1.5.7beta05 [November 25, 2011] Removed "zTXt" from warning in generic chunk decompression function. - Validate time settings passed to pngset() and png_convert_to_rfc1123() - (Frank Busse). + Validate time settings passed to png_set_tIME() and png_convert_to_rfc1123() + (Frank Busse). Note: This prevented CVE-2015-7981 from affecting + libpng-1.5.7 and later. Added MINGW support to CMakeLists.txt Reject invalid compression flag or method when reading the iTXt chunk. Backed out 'simplified' API changes. The API seems too complex and there @@ -3794,12 +3804,13 @@ Version 1.6.0beta01 [December 15, 2011] (the other two required headers aren't used). Non-ANSI systems that don't have stddef.h or limits.h will have to provide an appropriate fake containing the relevant types and #defines. - The use of FAR/far has been eliminated and the definition of png_alloc_size_t - is now controlled by a flag so that 'small size_t' systems can select it - if necessary. Libpng 1.6 may not currently work on such systems -- it - seems likely that it will ask 'malloc' for more than 65535 bytes with any - image that has a sufficiently large row size (rather than simply failing - to read such images). + Dropped support for 16-bit platforms. The use of FAR/far has been eliminated + and the definition of png_alloc_size_t is now controlled by a flag so + that 'small size_t' systems can select it if necessary. Libpng 1.6 may + not currently work on such systems -- it seems likely that it will + ask 'malloc' for more than 65535 bytes with any image that has a + sufficiently large row size (rather than simply failing to read such + images). New tools directory containing tools used to generate libpng code. Fixed race conditions in parallel make builds. With higher degrees of parallelism during 'make' the use of the same temporary file names such @@ -4411,7 +4422,7 @@ Version 1.6.1beta02 [February 19, 2013] Version 1.6.1beta03 [February 22, 2013] Fixed ALIGNED_MEMORY support. - Allow run-time ARM NEON checking to be disabled. A new configure option: + Added a new configure option: --enable-arm-neon=always will stop the run-time checks. New checks within arm/arm_init.c will cause the code not to be compiled unless __ARM_NEON__ is set. This should make it fail safe (if someone asks @@ -4430,10 +4441,10 @@ Version 1.6.1beta05 [March 1, 2013] Version 1.6.1beta06 [March 4, 2013] Better documentation of unknown handling API interactions. Corrected Android builds and corrected libpng.vers with symbol - prefixing. This adds an API to set optimization options externally, + prefixing. It also makes those tests compile and link on Android. + Added an API png_set_option() to set optimization options externally, providing an alternative and general solution for the non-portable - run-time tests used by the ARM Neon code. It also makes those tests - compile and link on Android. + run-time tests used by the ARM Neon code, using the PNG_ARM_NEON option. The order of settings vs options in pnglibconf.h is reversed to allow settings to depend on options and options can now set (or override) the defaults for settings. @@ -4525,13 +4536,14 @@ Version 1.6.3beta03 [April 30, 2013] Expanded manual paragraph about writing private chunks, particularly the need to call png_set_keep_unknown_chunks() when writing them. Avoid dereferencing NULL pointer possibly returned from - png_create_write_struct() (Andrew Church). + png_create_write_struct() (Andrew Church). Version 1.6.3beta05 [May 9, 2013] Calculate our own zlib windowBits when decoding rather than trusting the CMF bytes in the PNG datastream. Added an option to force maximum window size for inflating, which was - the behavior of libpng15 and earlier. + the behavior of libpng15 and earlier, via a new PNG_MAXIMUM_INFLATE_WINDOW + option for png_set_options(). Added png-fix-itxt and png-fix-too-far-back to the built programs and removed warnings from the source code and timepng that are revealed as a result. @@ -5134,14 +5146,16 @@ Version 1.6.17beta01 [January 29, 2015] Added testing of png_set_packing() to pngvalid.c Regenerated configure scripts in the *.tar distributions with libtool-2.4.4 Implement previously untested cases of libpng transforms in pngvalid.c - Fixed byte order in 2-byte filler, in png_do_read_filler(). + Fixed byte order in png_do_read_filler() with 16-bit input. Previously + the high and low bytes of the filler, from png_set_filler() or from + png_set_add_alpha(), were read in the wrong order. Made the check for out-of-range values in png_set_tRNS() detect values that are exactly 2^bit_depth, and work on 16-bit platforms. Merged some parts of libpng-1.6.17beta01 and libpng-1.7.0beta47. Added #ifndef __COVERITY__ where needed in png.c, pngrutil.c and pngset.c to avoid warnings about dead code. Added "& 0xff" to many instances of expressions that are typecast - to (png_byte), to avoid Coverity gripes. + to (png_byte), to avoid Coverity warnings. Version 1.6.17beta02 [February 7, 2015] Work around one more Coverity-scan dead-code warning. @@ -5205,6 +5219,201 @@ Version 1.6.17rc06 [March 23, 2015] Version 1.6.17 [March 26, 2015] No changes. +Version 1.6.18beta01 [April 1, 2015] + Removed PNG_SET_CHUNK_[CACHE|MALLOC]_LIMIT_SUPPORTED macros. They + have been combined with PNG_SET_USER_LIMITS_SUPPORTED (resolves + bug report by Andrew Church). + Fixed rgb_to_gray checks and added tRNS checks to pngvalid.c. This + fixes some arithmetic errors that caused some tests to fail on + some 32-bit platforms (Bug reports by Peter Breitenlohner [i686] + and Petr Gajdos [i586]). + +Version 1.6.18beta02 [April 26, 2015] + Suppressed some warnings from the Borland C++ 5.5.1/5.82 compiler + (Bug report by Viktor Szakats). + +Version 1.6.18beta03 [May 6, 2015] + Replaced "unexpected" with an integer (0xabadca11) in pngset.c + where a long was expected, to avoid a compiler warning when PNG_DEBUG > 1. + Added contrib/examples/simpleover.c, to demonstrate how to handle + alpha compositing of multiple images, using the "simplified API" + and an example PNG generation tool, contrib/examples/genpng.c + (John Bowler). + +Version 1.6.18beta04 [May 20, 2015] + PNG_RELEASE_BUILD replaces tests where the code depended on the build base + type and can be defined on the command line, allowing testing in beta + builds (John Bowler). + Avoid Coverity issue 80858 (REVERSE NULL) in pngtest.c PNG_DEBUG builds. + Avoid a harmless potential integer overflow in png_XYZ_from_xy() (Bug + report from Christopher Ferris). + +Version 1.6.18beta05 [May 31, 2015] + Backport filter selection code from libpng-1.7.0beta51, to combine + sub_row, up_row, avg_row, and paeth_row into try_row and tst_row. + Changed png_voidcast(), etc., to voidcast(), etc., in contrib/tools/pngfix.c + to avoid confusion with the libpng private macros. + Fixed old cut&paste bug in the weighted filter selection code in + pngwutil.c, introduced in libpng-0.95, March 1997. + +Version 1.6.18beta06 [June 1, 2015] + Removed WRITE_WEIGHTED_FILTERED code, to save a few kbytes of the + compiled library size. It never worked properly and as far as we can + tell, no one uses it. The png_set_filter_heuristics() and + png_set_filter_heuristics_fixed() APIs are retained but deprecated + and do nothing. + +Version 1.6.18beta07 [June 6, 2015] + Removed non-working progressive reader 'skip' function. This + function has apparently never been used. It was implemented + to support back-door modification of png_struct in libpng-1.4.x + but (because it does nothing and cannot do anything) was apparently + never tested (John Bowler). + Fixed cexcept.h in which GCC 5 now reports that one of the auto + variables in the Try macro needs to be volatile to prevent value + being lost over the setjmp (John Bowler). + Fixed NO_WRITE_FILTER and -Wconversion build breaks (John Bowler). + Fix g++ build breaks (John Bowler). + Quieted some Coverity issues in pngfix.c, png-fix-itxt.c, pngvalid.c, + pngstest.c, and pngimage.c. Most seem harmless, but png-fix-itxt + would only work with iTXt chunks with length 255 or less. + Added #ifdef's to contrib/examples programs so people don't try + to compile them without the minimum required support enabled + (suggested by Flavio Medeiros). + +Version 1.6.18beta08 [June 30, 2015] + Eliminated the final two Coverity defects (insecure temporary file + handling in contrib/libtests/pngstest.c; possible overflow of + unsigned char in contrib/tools/png-fix-itxt.c). To use the "secure" + file handling, define PNG_USE_MKSTEMP, otherwise "tmpfile()" will + be used. + Removed some unused WEIGHTED_FILTER macros from png.h and pngstruct.h + +Version 1.6.18beta09 [July 5, 2015] + Removed some useless typecasts from contrib/tools/png-fix-itxt.c + Fixed a new signed-unsigned comparison in pngrtran.c (Max Stepin). + Replaced arbitrary use of 'extern' with #define PNG_LINKAGE_*. To + preserve API compatibility, the new defines all default to "extern" + (requested by Jan Nijtmans). + +Version 1.6.18rc01 [July 9, 2015] + Belatedly added Mans Rullgard and James Yu to the list of Contributing + Authors. + +Version 1.6.18rc02 [July 12, 2015] + Restored unused FILTER_HEURISTIC macros removed at libpng-1.6.18beta08 + to png.h to avoid compatibility warnings. + +Version 1.6.18rc03 [July 15, 2015] + Minor changes to the man page + +Version 1.6.18 [July 23, 2015] + No changes. + +Version 1.6.19beta01 [July 30, 2015] + Updated obsolete information about the simplified API macros in the + manual pages (Bug report by Arc Riley). + Avoid potentially dereferencing NULL info_ptr in png_info_init_3(). + Rearranged png.h to put the major sections in the same order as + in libpng17. + Eliminated unused PNG_COST_SHIFT, PNG_WEIGHT_SHIFT, PNG_COST_FACTOR, and + PNG_WEIGHT_FACTOR macros. + Suppressed some warnings from the Borland C++ 5.5.1/5.82 compiler + (Bug report by Viktor Szakats). Several warnings remain and are + unavoidable, where we test for overflow. + Fixed potential leak of png_pixels in contrib/pngminus/pnm2png.c + Fixed uninitialized variable in contrib/gregbook/rpng2-x.c + +Version 1.6.19beta02 [August 19, 2015] + Moved config.h.in~ from the "libpng_autotools_files" list to the + "libpng_autotools_extra" list in autogen.sh because it was causing a + false positive for missing files (bug report by Robert C. Seacord). + Removed unreachable "break" statements in png.c, pngread.c, and pngrtran.c + to suppress clang warnings (Bug report by Viktor Szakats). + Fixed some bad links in the man page. + Changed "n bit" to "n-bit" in comments. + Added signed/unsigned 16-bit safety net. This removes the dubious + 0x8000 flag definitions on 16-bit systems. They aren't supported + yet the defs *probably* work, however it seems much safer to do this + and be advised if anyone, contrary to advice, is building libpng 1.6 + on a 16-bit system. It also adds back various switch default clauses + for GCC; GCC errors out if they are not present (with an appropriately + high level of warnings). + Safely convert num_bytes to a png_byte in png_set_sig_bytes() (Robert + Seacord). + Fixed the recently reported 1's complement security issue by replacing + the value that is illegal in the PNG spec, in both signed and unsigned + values, with 0. Illegal unsigned values (anything greater than or equal + to 0x80000000) can still pass through, but since these are not illegal + in ANSI-C (unlike 0x80000000 in the signed case) the checking that + occurs later can catch them (John Bowler). + +Version 1.6.19beta03 [September 26, 2015] + Fixed png_save_int_32 when int is not 2's complement (John Bowler). + Updated libpng16 with all the recent test changes from libpng17, + including changes to pngvalid.c to ensure that the original, + distributed, version of contrib/visupng/cexcept.h can be used + (John Bowler). + pngvalid contains the correction to the use of SAVE/STORE_ + UNKNOWN_CHUNKS; a bug revealed by changes in libpng 1.7. More + tests contain the --strict option to detect warnings and the + pngvalid-standard test has been corrected so that it does not + turn on progressive-read. There is a separate test which does + that. (John Bowler) + Also made some signed/unsigned fixes. + Make pngstest error limits version specific. Splitting the machine + generated error structs out to a file allows the values to be updated + without changing pngstest.c itself. Since libpng 1.6 and 1.7 have + slightly different error limits this simplifies maintenance. The + makepngs.sh script has also been updated to more accurately reflect + current problems in libpng 1.7 (John Bowler). + Incorporated new test PNG files into make check. tests/pngstest-* + are changed so that the new test files are divided into 8 groups by + gamma and alpha channel. These tests have considerably better code + and pixel-value coverage than contrib/pngsuite; however,coverage is + still incomplete (John Bowler). + Removed the '--strict' in 1.6 because of the double-gamma-correction + warning, updated pngstest-errors.h for the errors detected with the + new contrib/testspngs PNG test files (John Bowler). + +Version 1.6.19beta04 [October 15, 2015] + Worked around rgb-to-gray issues in libpng 1.6. The previous + attempts to ignore the errors in the code aren't quite enough to + deal with the 'channel selection' encoding added to libpng 1.7; abort. + pngvalid.c is changed to drop this encoding in prior versions. + Fixed 'pow' macros in pngvalid.c. It is legal for 'pow' to be a + macro, therefore the argument list cannot contain preprocessing + directives. Make sure pow is a function where this happens. This is + a minimal safe fix, the issue only arises in non-performance-critical + code (bug report by Curtis Leach, fix by John Bowler). + Added sPLT support to pngtest.c + +Version 1.6.19rc01 [October 23, 2015] + No changes. + +Version 1.6.19rc02 [October 31, 2015] + Prevent setting or writing over-length PLTE chunk (Cosmin Truta). + Silently truncate over-length PLTE chunk while reading. + Libpng incorrectly calculated the output rowbytes when the application + decreased either the number of channels or the bit depth (or both) in + a user transform. This was safe; libpng overallocated buffer space + (potentially by quite a lot; up to 4 times the amount required) but, + from 1.5.4 on, resulted in a png_error (John Bowler). + +Version 1.6.19rc03 [November 3, 2015] + Fixed some inconsequential cut-and-paste typos in png_set_cHRM_XYZ_fixed(). + Clarified COPYRIGHT information to state explicitly that versions + are derived from previous versions. + Removed much of the long list of previous versions from png.h and + libpng.3. + +Version 1.6.19rc04 [November 5, 2015] + Fixed new bug with CRC error after reading an over-length palette + (bug report by Cosmin Truta). + +Version 1.6.19 [November 12, 2015] + Cleaned up coding style in png_handle_PLTE(). + Send comments/corrections/commendations to png-mng-implement at lists.sf.net (subscription required; visit https://lists.sourceforge.net/lists/listinfo/png-mng-implement @@ -5212,3 +5421,4 @@ to subscribe) or to glennrp at users.sourceforge.net Glenn R-P +#endif diff --git a/src/3rdparty/libpng/INSTALL b/src/3rdparty/libpng/INSTALL index a294ffe633..531652abe0 100644 --- a/src/3rdparty/libpng/INSTALL +++ b/src/3rdparty/libpng/INSTALL @@ -385,23 +385,3 @@ XVI. Other sources of information about libpng: Further information can be found in the README and libpng-manual.txt files, in the individual makefiles, in png.h, and the manual pages libpng.3 and png.5. - -Using the ./configure script -- 16 December 2002. -================================================= - -The ./configure script should work compatibly with what scripts/makefile.* -did, however there are some options you might need to add to configure -explicitly, which previously was done semi-automatically (if you didn't edit -scripts/makefile.* yourself, that is) - -CFLAGS="-Wall -O -funroll-loops \ --malign-loops=2 -malign-functions=2" ./configure --prefix=/usr/include \ ---with-pkgconfigdir=/usr/lib/pkgconfig --includedir=/usr/include - -You can alternatively specify --includedir=/usr/include, /usr/local/include, -/usr/include/libpng16, or whatever. - -If you find that the configure script is out-of-date or is not supporting -your platform properly, try running autogen.sh to regenerate "configure", -"Makefile.in", and the other configuration files. Then try configure again. - diff --git a/src/3rdparty/libpng/LICENSE b/src/3rdparty/libpng/LICENSE index eb4a9a9da4..11f6ffe5db 100644 --- a/src/3rdparty/libpng/LICENSE +++ b/src/3rdparty/libpng/LICENSE @@ -10,21 +10,18 @@ this sentence. This code is released under the libpng license. -libpng versions 1.2.6, August 15, 2004, through 1.6.17, March 26, 2015, are -Copyright (c) 2004, 2006-2015 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.2.5 -with the following individual added to the list of Contributing Authors - - Cosmin Truta - -libpng versions 1.0.7, July 1, 2000, through 1.2.5 - October 3, 2002, are -Copyright (c) 2000-2002 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-1.0.6 -with the following individuals added to the list of Contributing Authors +libpng versions 1.0.7, July 1, 2000, through 1.6.19, November 12, 2015, are +Copyright (c) 2000-2002, 2004, 2006-2015 Glenn Randers-Pehrson, are +derived from libpng-1.0.6, and are distributed according to the same +disclaimer and license as libpng-1.0.6 with the following individuals +added to the list of Contributing Authors: Simon-Pierre Cadieux Eric S. Raymond + Mans Rullgard + Cosmin Truta Gilles Vollant + James Yu and with the following additions to the disclaimer: @@ -36,18 +33,20 @@ and with the following additions to the disclaimer: the user. libpng versions 0.97, January 1998, through 1.0.6, March 20, 2000, are -Copyright (c) 1998, 1999 Glenn Randers-Pehrson, and are -distributed according to the same disclaimer and license as libpng-0.96, -with the following individuals added to the list of Contributing Authors: +Copyright (c) 1998-2000 Glenn Randers-Pehrson, are derived from +libpng-0.96, and are distributed according to the same disclaimer and +license as libpng-0.96, with the following individuals added to the list +of Contributing Authors: Tom Lane Glenn Randers-Pehrson Willem van Schaik libpng versions 0.89, June 1996, through 0.96, May 1997, are -Copyright (c) 1996, 1997 Andreas Dilger -Distributed according to the same disclaimer and license as libpng-0.88, -with the following individuals added to the list of Contributing Authors: +Copyright (c) 1996-1997 Andreas Dilger, are derived from libpng-0.88, +and are distributed according to the same disclaimer and license as +libpng-0.88, with the following individuals added to the list of +Contributing Authors: John Bowler Kevin Bracey @@ -57,7 +56,7 @@ with the following individuals added to the list of Contributing Authors: Tom Tanner libpng versions 0.5, May 1995, through 0.88, January 1996, are -Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc. +Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc. For the purposes of this copyright and license, "Contributing Authors" is defined as the following set of individuals: @@ -80,13 +79,13 @@ Permission is hereby granted to use, copy, modify, and distribute this source code, or portions hereof, for any purpose, without fee, subject to the following restrictions: -1. The origin of this source code must not be misrepresented. + 1. The origin of this source code must not be misrepresented. -2. Altered versions must be plainly marked as such and must not - be misrepresented as being the original source. + 2. Altered versions must be plainly marked as such and must not + be misrepresented as being the original source. -3. This Copyright notice may not be removed or altered from any - source or altered source distribution. + 3. This Copyright notice may not be removed or altered from any + source or altered source distribution. The Contributing Authors and Group 42, Inc. specifically permit, without fee, and encourage the use of this source code as a component to @@ -94,18 +93,20 @@ supporting the PNG file format in commercial products. If you use this source code in a product, acknowledgment is not required but would be appreciated. +END OF COPYRIGHT NOTICE, DISCLAIMER, and LICENSE. A "png_get_copyright" function is available, for convenient use in "about" boxes and the like: - printf("%s",png_get_copyright(NULL)); + printf("%s", png_get_copyright(NULL)); Also, the PNG logo (in PNG format, of course) is supplied in the files "pngbar.png" and "pngbar.jpg (88x31) and "pngnow.png" (98x31). -Libpng is OSI Certified Open Source Software. OSI Certified Open Source is a -certification mark of the Open Source Initiative. +Libpng is OSI Certified Open Source Software. OSI Certified Open Source is +a certification mark of the Open Source Initiative. OSI has not addressed +the additional disclaimers inserted at version 1.0.7. Glenn Randers-Pehrson glennrp at users.sourceforge.net -March 26, 2015 +November 12, 2015 diff --git a/src/3rdparty/libpng/README b/src/3rdparty/libpng/README index a158ea8a77..17484e0fd7 100644 --- a/src/3rdparty/libpng/README +++ b/src/3rdparty/libpng/README @@ -1,4 +1,4 @@ -README for libpng version 1.6.17 - March 26, 2015 (shared library 16.0) +README for libpng version 1.6.19 - November 12, 2015 (shared library 16.0) See the note about version numbers near the top of png.h See INSTALL for instructions on how to install libpng. @@ -134,7 +134,7 @@ and ...". If in doubt, send questions to me. I'll bounce them to others, if necessary. Please do not send suggestions on how to change PNG. We have -been discussing PNG for nineteen years now, and it is official and +been discussing PNG for twenty years now, and it is official and finished. If you have suggestions for libpng, however, I'll gladly listen. Even if your suggestion is not used immediately, it may be used later. diff --git a/src/3rdparty/libpng/libpng-manual.txt b/src/3rdparty/libpng/libpng-manual.txt index f0dae987f9..bc7a441cf2 100644 --- a/src/3rdparty/libpng/libpng-manual.txt +++ b/src/3rdparty/libpng/libpng-manual.txt @@ -1,6 +1,6 @@ libpng-manual.txt - A description on how to use and modify libpng - libpng version 1.6.17 - March 26, 2015 + libpng version 1.6.19 - November 12, 2015 Updated and distributed by Glenn Randers-Pehrson Copyright (c) 1998-2015 Glenn Randers-Pehrson @@ -11,7 +11,7 @@ libpng-manual.txt - A description on how to use and modify libpng Based on: - libpng versions 0.97, January 1998, through 1.6.17 - March 26, 2015 + libpng versions 0.97, January 1998, through 1.6.19 - November 12, 2015 Updated and distributed by Glenn Randers-Pehrson Copyright (c) 1998-2015 Glenn Randers-Pehrson @@ -70,15 +70,16 @@ a W3C Recommendation and as an ISO Standard (ISO/IEC 15948:2004 (E)) at The W3C and ISO documents have identical technical content. The PNG-1.2 specification is available at -. It is technically equivalent +. +It is technically equivalent to the PNG specification (second edition) but has some additional material. -The PNG-1.0 specification is available -as RFC 2083 and as a -W3C Recommendation . +The PNG-1.0 specification is available as RFC 2083 + and as a +W3C Recommendation . Some additional chunks are described in the special-purpose public chunks -documents at . +documents at Other information about PNG, and the latest version of libpng, can be found at the PNG home @@ -100,7 +101,7 @@ majority of the needs of its users. Libpng uses zlib for its compression and decompression of PNG files. Further information about zlib, and the latest version of zlib, can -be found at the zlib home page, . +be found at the zlib home page, . The zlib compression utility is a general purpose utility that is useful for more than PNG files, and can be used without libpng. See the documentation delivered with zlib for more details. @@ -649,6 +650,7 @@ User limits The PNG specification allows the width and height of an image to be as large as 2^31-1 (0x7fffffff), or about 2.147 billion rows and columns. +For safety, libpng imposes a default limit of 1 million rows and columns. Larger images will be rejected immediately with a png_error() call. If you wish to change these limits, you can use @@ -669,8 +671,11 @@ If you need to retrieve the limits that are being applied, use height_max = png_get_user_height_max(png_ptr); The PNG specification sets no limit on the number of ancillary chunks -allowed in a PNG datastream. You can impose a limit on the total number -of sPLT, tEXt, iTXt, zTXt, and unknown chunks that will be stored, with +allowed in a PNG datastream. By default, libpng imposes a limit of +a total of 1000 sPLT, tEXt, iTXt, zTXt, and unknown chunks to be stored. +If you have set up both info_ptr and end_info_ptr, the limit applies +separately to each. You can change the limit on the total number of such +chunks that will be stored, with png_set_chunk_cache_max(png_ptr, user_chunk_cache_max); @@ -678,8 +683,9 @@ where 0x7fffffffL means unlimited. You can retrieve this limit with chunk_cache_max = png_get_chunk_cache_max(png_ptr); -You can also set a limit on the amount of memory that a compressed chunk -other than IDAT can occupy, with +Libpng imposes a limit of 8 Megabytes (8,000,000 bytes) on the amount of +memory that a compressed chunk other than IDAT can occupy, when decompressed. +You can change this limit with png_set_chunk_malloc_max(png_ptr, user_chunk_malloc_max); @@ -1679,15 +1685,16 @@ described below. Data will be decoded into the supplied row buffers packed into bytes unless the library has been told to transform it into another format. For example, 4 bit/pixel paletted or grayscale data will be returned -2 pixels/byte with the leftmost pixel in the high-order bits of the -byte, unless png_set_packing() is called. 8-bit RGB data will be stored +2 pixels/byte with the leftmost pixel in the high-order bits of the byte, +unless png_set_packing() is called. 8-bit RGB data will be stored in RGB RGB RGB format unless png_set_filler() or png_set_add_alpha() is called to insert filler bytes, either before or after each RGB triplet. + 16-bit RGB data will be returned RRGGBB RRGGBB, with the most significant byte of the color value first, unless png_set_scale_16() is called to transform it to regular RGB RGB triplets, or png_set_filler() or -png_set_add alpha() is called to insert filler bytes, either before or -after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can +png_set_add alpha() is called to insert two filler bytes, either before +or after each RRGGBB triplet. Similarly, 8-bit or 16-bit grayscale data can be modified with png_set_filler(), png_set_add_alpha(), png_set_strip_16(), or png_set_scale_16(). @@ -1844,12 +1851,13 @@ into 4 or 8 bytes for windowing systems that need them in this format: if (color_type == PNG_COLOR_TYPE_RGB) png_set_filler(png_ptr, filler, PNG_FILLER_BEFORE); -where "filler" is the 8 or 16-bit number to fill with, and the location is -either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether -you want the filler before the RGB or after. This transformation -does not affect images that already have full alpha channels. To add an -opaque alpha channel, use filler=0xff or 0xffff and PNG_FILLER_AFTER which -will generate RGBA pixels. +where "filler" is the 8-bit or 16-bit number to fill with, and the location +is either PNG_FILLER_BEFORE or PNG_FILLER_AFTER, depending upon whether +you want the filler before the RGB or after. When filling an 8-bit pixel, +the least significant 8 bits of the number are used, if a 16-bit number is +supplied. This transformation does not affect images that already have full +alpha channels. To add an opaque alpha channel, use filler=0xffff and +PNG_FILLER_AFTER which will generate RGBA pixels. Note that png_set_filler() does not change the color type. If you want to do that, you can add a true alpha channel with @@ -1859,7 +1867,7 @@ to do that, you can add a true alpha channel with png_set_add_alpha(png_ptr, filler, PNG_FILLER_AFTER); where "filler" contains the alpha value to assign to each pixel. -This function was added in libpng-1.2.7. +The png_set_add_alpha() function was added in libpng-1.2.7. If you are reading an image with an alpha channel, and you need the data as ARGB instead of the normal PNG format RGBA: @@ -1917,9 +1925,9 @@ data for sBIT, regardless of the error_action setting. The default values come from the PNG file cHRM chunk if present; otherwise, the defaults correspond to the ITU-R recommendation 709, and also the sRGB color space, as recommended in the Charles Poynton's Colour FAQ, -, in section 9: +Copyright (c) 2006-11-28 Charles Poynton, in section 9: - + Y = 0.2126 * R + 0.7152 * G + 0.0722 * B @@ -3716,21 +3724,26 @@ as a wide variety of APIs to manipulate ancilliary information. To read a PNG file using the simplified API: - 1) Declare a 'png_image' structure (see below) on the - stack and memset() it to all zero. + 1) Declare a 'png_image' structure (see below) on the stack, set the + version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + (this is REQUIRED, your program may crash if you don't do it.) 2) Call the appropriate png_image_begin_read... function. - 3) Set the png_image 'format' member to the required - format and allocate a buffer for the image. + 3) Set the png_image 'format' member to the required sample format. + + 4) Allocate a buffer for the image and, if required, the color-map. - 4) Call png_image_finish_read to read the image into - your buffer. + 5) Call png_image_finish_read to read the image and, if required, the + color-map into your buffers. There are no restrictions on the format of the PNG input itself; all valid color types, bit depths, and interlace methods are acceptable, and the input image is transformed as necessary to the requested in-memory format -during the png_image_finish_read() step. +during the png_image_finish_read() step. The only caveat is that if you +request a color-mapped image from a PNG that is full-color or makes +complex use of an alpha channel the transformation is extremely lossy and the +result may look terrible. To write a PNG file using the simplified API: @@ -3739,34 +3752,35 @@ To write a PNG file using the simplified API: 2) Initialize the members of the structure that describe the image, setting the 'format' member to the format of the - image in memory. + image samples. 3) Call the appropriate png_image_write... function with a - pointer to the image to write the PNG data. + pointer to the image and, if necessary, the color-map to write + the PNG data. png_image is a structure that describes the in-memory format of an image -when it is being read or define the in-memory format of an image that you +when it is being read or defines the in-memory format of an image that you need to write. The "png_image" structure contains the following members: + png_controlp opaque Initialize to NULL, free with png_image_free png_uint_32 version Set to PNG_IMAGE_VERSION png_uint_32 width Image width in pixels (columns) png_uint_32 height Image height in pixels (rows) png_uint_32 format Image format as defined below png_uint_32 flags A bit mask containing informational flags - png_controlp opaque Initialize to NULL, free with png_image_free png_uint_32 colormap_entries; Number of entries in the color-map png_uint_32 warning_or_error; char message[64]; -In the event of an error or warning the following field warning_or_error +In the event of an error or warning the "warning_or_error" field will be set to a non-zero value and the 'message' field will contain a '\0' terminated string with the libpng error or warning message. If both warnings and an error were encountered, only the error is recorded. If there are multiple warnings, only the first one is recorded. -The upper 30 bits of this value are reserved; the low two bits contain -a two bit code such that a value more than 1 indicates a failure in the API -just called: +The upper 30 bits of the "warning_or_error" value are reserved; the low two +bits contain a two bit code such that a value more than 1 indicates a failure +in the API just called: 0 - no warning or error 1 - warning @@ -3798,64 +3812,72 @@ channels are linear. Color channels use the RGB encoding (RGB end-points) of the sRGB specification. This encoding is identified by the PNG_FORMAT_FLAG_LINEAR flag below. +When the simplified API needs to convert between sRGB and linear colorspaces, +the actual sRGB transfer curve defined in the sRGB specification (see the +article at http://en.wikipedia.org/wiki/SRGB) is used, not the gamma=1/2.2 +approximation used elsewhere in libpng. + When an alpha channel is present it is expected to denote pixel coverage of the color or luminance channels and is returned as an associated alpha channel: the color/gray channels are scaled (pre-multiplied) by the alpha value. -When a color-mapped image is used as a result of calling -png_image_read_colormap or png_image_write_colormap the channels are encoded -in the color-map and the descriptions above apply to the color-map entries. -The image data is encoded as small integers, value 0..255, that index the -entries in the color-map. One integer (one byte) is stored for each pixel. +The samples are either contained directly in the image data, between 1 and 8 +bytes per pixel according to the encoding, or are held in a color-map indexed +by bytes in the image data. In the case of a color-map the color-map entries +are individual samples, encoded as above, and the image data has one byte per +pixel to select the relevant sample from the color-map. PNG_FORMAT_* The #defines to be used in png_image::format. Each #define identifies a particular layout of channel data and, if present, alpha values. There are -separate defines for each of the two channel encodings. +separate defines for each of the two component encodings. -A format is built up using single bit flag values. Not all combinations are -valid: use the bit flag values below for testing a format returned by the -read APIs, but set formats from the derived values. +A format is built up using single bit flag values. All combinations are +valid. Formats can be built up from the flag values or you can use one of +the predefined values below. When testing formats always use the FORMAT_FLAG +macros to test for individual features - future versions of the library may +add new flags. When reading or writing color-mapped images the format should be set to the format of the entries in the color-map then png_image_{read,write}_colormap called to read or write the color-map and set the format correctly for the image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! -NOTE: libpng can be built with particular features disabled, if you see +NOTE: libpng can be built with particular features disabled. If you see compiler errors because the definition of one of the following flags has been compiled out it is because libpng does not have the required support. It is possible, however, for the libpng configuration to enable the format on just -read or just write; in that case you may see an error at run time. You can -guard against this by checking for the definition of: +read or just write; in that case you may see an error at run time. +You can guard against this by checking for the definition of the +appropriate "_SUPPORTED" macro, one of: PNG_SIMPLIFIED_{READ,WRITE}_{BGR,AFIRST}_SUPPORTED - PNG_FORMAT_FLAG_ALPHA 0x01 format with an alpha channel - PNG_FORMAT_FLAG_COLOR 0x02 color format: otherwise grayscale - PNG_FORMAT_FLAG_LINEAR 0x04 png_uint_16 channels else png_byte - PNG_FORMAT_FLAG_COLORMAP 0x08 libpng use only - PNG_FORMAT_FLAG_BGR 0x10 BGR colors, else order is RGB - PNG_FORMAT_FLAG_AFIRST 0x20 alpha channel comes first + PNG_FORMAT_FLAG_ALPHA format with an alpha channel + PNG_FORMAT_FLAG_COLOR color format: otherwise grayscale + PNG_FORMAT_FLAG_LINEAR 2-byte channels else 1-byte + PNG_FORMAT_FLAG_COLORMAP image data is color-mapped + PNG_FORMAT_FLAG_BGR BGR colors, else order is RGB + PNG_FORMAT_FLAG_AFIRST alpha channel comes first Supported formats are as follows. Future versions of libpng may support more formats; for compatibility with older versions simply check if the format macro is defined using #ifdef. These defines describe the in-memory layout of the components of the pixels of the image. -First the single byte formats: +First the single byte (sRGB) formats: - PNG_FORMAT_GRAY 0 - PNG_FORMAT_GA PNG_FORMAT_FLAG_ALPHA - PNG_FORMAT_AG (PNG_FORMAT_GA|PNG_FORMAT_FLAG_AFIRST) - PNG_FORMAT_RGB PNG_FORMAT_FLAG_COLOR - PNG_FORMAT_BGR (PNG_FORMAT_FLAG_COLOR|PNG_FORMAT_FLAG_BGR) - PNG_FORMAT_RGBA (PNG_FORMAT_RGB|PNG_FORMAT_FLAG_ALPHA) - PNG_FORMAT_ARGB (PNG_FORMAT_RGBA|PNG_FORMAT_FLAG_AFIRST) - PNG_FORMAT_BGRA (PNG_FORMAT_BGR|PNG_FORMAT_FLAG_ALPHA) - PNG_FORMAT_ABGR (PNG_FORMAT_BGRA|PNG_FORMAT_FLAG_AFIRST) + PNG_FORMAT_GRAY + PNG_FORMAT_GA + PNG_FORMAT_AG + PNG_FORMAT_RGB + PNG_FORMAT_BGR + PNG_FORMAT_RGBA + PNG_FORMAT_ARGB + PNG_FORMAT_BGRA + PNG_FORMAT_ABGR Then the linear 2-byte formats. When naming these "Y" is used to indicate a luminance (gray) channel. The component order within the pixel @@ -3864,22 +3886,22 @@ components in the linear format. The components are 16-bit integers in the native byte order for your platform, and there is no provision for swapping the bytes to a different endian condition. - PNG_FORMAT_LINEAR_Y PNG_FORMAT_FLAG_LINEAR + PNG_FORMAT_LINEAR_Y PNG_FORMAT_LINEAR_Y_ALPHA - (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_ALPHA) PNG_FORMAT_LINEAR_RGB - (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR) PNG_FORMAT_LINEAR_RGB_ALPHA - (PNG_FORMAT_FLAG_LINEAR|PNG_FORMAT_FLAG_COLOR| - PNG_FORMAT_FLAG_ALPHA) -Color-mapped formats are obtained by calling png_image_{read,write}_colormap, -as appropriate after setting png_image::format to the format of the color-map -to be read or written. Applications may check the value of -PNG_FORMAT_FLAG_COLORMAP to see if they have called the colormap API. The -format of the color-map may be extracted using the following macro. +With color-mapped formats the image data is one byte for each pixel. The byte +is an index into the color-map which is formatted as above. To obtain a +color-mapped format it is sufficient just to add the PNG_FOMAT_FLAG_COLORMAP +to one of the above definitions, or you can use one of the definitions below. - PNG_FORMAT_OF_COLORMAP(fmt) ((fmt) & ~PNG_FORMAT_FLAG_COLORMAP) + PNG_FORMAT_RGB_COLORMAP + PNG_FORMAT_BGR_COLORMAP + PNG_FORMAT_RGBA_COLORMAP + PNG_FORMAT_ARGB_COLORMAP + PNG_FORMAT_BGRA_COLORMAP + PNG_FORMAT_ABGR_COLORMAP PNG_IMAGE macros @@ -3887,9 +3909,9 @@ These are convenience macros to derive information from a png_image structure. The PNG_IMAGE_SAMPLE_ macros return values appropriate to the actual image sample values - either the entries in the color-map or the pixels in the image. The PNG_IMAGE_PIXEL_ macros return corresponding values -for the pixels and will always return 1 after a call to -png_image_{read,write}_colormap. The remaining macros return information -about the rows in the image and the complete image. +for the pixels and will always return 1 for color-mapped formats. The +remaining macros return information about the rows in the image and the +complete image. NOTE: All the macros that take a png_image::format parameter are compile time constants if the format parameter is, itself, a constant. Therefore these @@ -3897,46 +3919,39 @@ macros can be used in array declarations and case labels where required. Similarly the macros are also pre-processor constants (sizeof is not used) so they can be used in #if tests. -First the information about the samples. - PNG_IMAGE_SAMPLE_CHANNELS(fmt) Returns the total number of channels in a given format: 1..4 PNG_IMAGE_SAMPLE_COMPONENT_SIZE(fmt) Returns the size in bytes of a single component of a pixel or color-map - entry (as appropriate) in the image. + entry (as appropriate) in the image: 1 or 2. PNG_IMAGE_SAMPLE_SIZE(fmt) This is the size of the sample data for one sample. If the image is color-mapped it is the size of one color-map entry (and image pixels are one byte in size), otherwise it is the size of one image pixel. + PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt) + The maximum size of the color-map required by the format expressed in a + count of components. This can be used to compile-time allocate a + color-map: + + png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; + + png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; + + Alternatively use the PNG_IMAGE_COLORMAP_SIZE macro below to use the + information from one of the png_image_begin_read_ APIs and dynamically + allocate the required memory. + PNG_IMAGE_COLORMAP_SIZE(fmt) The size of the color-map required by the format; this is the size of the - color-map buffer passed to the png_image_{read,write}_colormap APIs, it is + color-map buffer passed to the png_image_{read,write}_colormap APIs. It is a fixed number determined by the format so can easily be allocated on the stack if necessary. -#define PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(fmt)\ - (PNG_IMAGE_SAMPLE_CHANNELS(fmt) * 256) - /* The maximum size of the color-map required by the format expressed in a - * count of components. This can be used to compile-time allocate a - * color-map: - * - * png_uint_16 colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(linear_fmt)]; - * - * png_byte colormap[PNG_IMAGE_MAXIMUM_COLORMAP_COMPONENTS(sRGB_fmt)]; - * - * Alternatively, use the PNG_IMAGE_COLORMAP_SIZE macro below to use the - * information from one of the png_image_begin_read_ APIs and dynamically - * allocate the required memory. - */ - - Corresponding information about the pixels - PNG_IMAGE_PIXEL_(test,fmt) - PNG_IMAGE_PIXEL_CHANNELS(fmt) The number of separate channels (components) in a pixel; 1 for a color-mapped image. @@ -3962,19 +3977,54 @@ Information about the whole row, or whole image to start the next row on a 4-byte boundary. PNG_IMAGE_BUFFER_SIZE(image, row_stride) - Returns the size, in bytes, of an image buffer given a png_image and a row - stride - the number of components to leave space for in each row. This - macro takes care of multiplying row_stride by PNG_IMAGE_PIXEL_COMONENT_SIZE - when the image has 2-byte components. + Return the size, in bytes, of an image buffer given a png_image and a row + stride - the number of components to leave space for in each row. + + PNG_IMAGE_SIZE(image) + Return the size, in bytes, of the image in memory given just a png_image; + the row stride is the minimum stride required for the image. + + PNG_IMAGE_COLORMAP_SIZE(image) + Return the size, in bytes, of the color-map of this image. If the image + format is not a color-map format this will return a size sufficient for + 256 entries in the given format; check PNG_FORMAT_FLAG_COLORMAP if + you don't want to allocate a color-map in this case. + +PNG_IMAGE_FLAG_* + +Flags containing additional information about the image are held in +the 'flags' field of png_image. PNG_IMAGE_FLAG_COLORSPACE_NOT_sRGB == 0x01 This indicates the the RGB values of the in-memory bitmap do not correspond to the red, green and blue end-points defined by sRGB. - PNG_IMAGE_FLAG_COLORMAP == 0x02 - The PNG is color-mapped. If this flag is set png_image_read_colormap - can be used without further loss of image information. If it is not set - png_image_read_colormap will cause significant loss if the image has any + PNG_IMAGE_FLAG_FAST == 0x02 + On write emphasise speed over compression; the resultant PNG file will be + larger but will be produced significantly faster, particular for large + images. Do not use this option for images which will be distributed, only + used it when producing intermediate files that will be read back in + repeatedly. For a typical 24-bit image the option will double the read + speed at the cost of increasing the image size by 25%, however for many + more compressible images the PNG file can be 10 times larger with only a + slight speed gain. + + PNG_IMAGE_FLAG_16BIT_sRGB == 0x04 + On read if the image is a 16-bit per component image and there is no gAMA + or sRGB chunk assume that the components are sRGB encoded. Notice that + images output by the simplified API always have gamma information; setting + this flag only affects the interpretation of 16-bit images from an + external source. It is recommended that the application expose this flag + to the user; the user can normally easily recognize the difference between + linear and sRGB encoding. This flag has no effect on write - the data + passed to the write APIs must have the correct encoding (as defined + above.) + + If the flag is not set (the default) input 16-bit per component data is + assumed to be linear. + + NOTE: the flag can only be set after the png_image_begin_read_ call, + because that call initializes the 'flags' field. READ APIs @@ -4065,10 +4115,11 @@ a 16-bit linear encoded PNG file is written. With all APIs row_stride is handled as in the read APIs - it is the spacing from one row to the next in component sized units (float) and if negative -indicates a bottom-up row layout in the buffer. +indicates a bottom-up row layout in the buffer. If you pass zero, libpng will +calculate the row_stride for you from the width and number of channels. Note that the write API does not support interlacing, sub-8-bit pixels, -and indexed (paletted) images. +indexed (paletted) images, or most ancillary chunks. VI. Modifying/Customizing libpng @@ -4356,41 +4407,6 @@ is called for the first time.) same as the value of filter_method used in png_set_IHDR(). -It is also possible to influence how libpng chooses from among the -available filters. This is done in one or both of two ways - by -telling it how important it is to keep the same filter for successive -rows, and by telling it the relative computational costs of the filters. - - double weights[3] = {1.5, 1.3, 1.1}, - costs[PNG_FILTER_VALUE_LAST] = - {1.0, 1.3, 1.3, 1.5, 1.7}; - - png_set_filter_heuristics(png_ptr, - PNG_FILTER_HEURISTIC_WEIGHTED, 3, - weights, costs); - -The weights are multiplying factors that indicate to libpng that the -row filter should be the same for successive rows unless another row filter -is that many times better than the previous filter. In the above example, -if the previous 3 filters were SUB, SUB, NONE, the SUB filter could have a -"sum of absolute differences" 1.5 x 1.3 times higher than other filters -and still be chosen, while the NONE filter could have a sum 1.1 times -higher than other filters and still be chosen. Unspecified weights are -taken to be 1.0, and the specified weights should probably be declining -like those above in order to emphasize recent filters over older filters. - -The filter costs specify for each filter type a relative decoding cost -to be considered when selecting row filters. This means that filters -with higher costs are less likely to be chosen over filters with lower -costs, unless their "sum of absolute differences" is that much smaller. -The costs do not necessarily reflect the exact computational speeds of -the various filters, since this would unduly influence the final image -size. - -Note that the numbers above were invented purely for this example and -are given only to help explain the function usage. Little testing has -been done to find optimum values for either the costs or the weights. - Requesting debug printout The macro definition PNG_DEBUG can be used to request debugging @@ -4890,7 +4906,7 @@ limits are now png_user_chunk_malloc_max 0 (unlimited) 8,000,000 The png_set_option() function (and the "options" member of the png struct) was -added to libpng-1.5.15. +added to libpng-1.5.15, with option PNG_ARM_NEON. The library now supports a complete fixed point implementation and can thus be used on systems that have no floating point support or very @@ -5032,9 +5048,9 @@ The signatures of many exported functions were changed, such that png_infop became png_inforp or png_const_inforp where "rp" indicates a "restricted pointer". -The support for FAR/far types has been eliminated and the definition of -png_alloc_size_t is now controlled by a flag so that 'small size_t' systems -can select it if necessary. +Dropped support for 16-bit platforms. The support for FAR/far types has +been eliminated and the definition of png_alloc_size_t is now controlled +by a flag so that 'small size_t' systems can select it if necessary. Error detection in some chunks has improved; in particular the iCCP chunk reader now does pretty complete validation of the basic format. Some bad @@ -5109,6 +5125,28 @@ length, which resulted in PNG files that cannot be read beyond the bad iTXt chunk. This error was fixed in libpng-1.6.3, and a tool (called contrib/tools/png-fix-itxt) has been added to the libpng distribution. +Starting with libpng-1.6.17, the PNG_SAFE_LIMITS macro was eliminated +and safe limits are used by default (users who need larger limits +can still override them at compile time or run time, as described above). + +The new limits are + default spec limit + png_user_width_max 1,000,000 2,147,483,647 + png_user_height_max 1,000,000 2,147,483,647 + png_user_chunk_cache_max 128 unlimited + png_user_chunk_malloc_max 8,000,000 unlimited + +Starting with libpng-1.6.18, a PNG_RELEASE_BUILD macro was added, which allows +library builders to control compilation for an installed system (a release build). +It can be set for testing debug or beta builds to ensure that they will compile +when the build type is switched to RC or STABLE. In essence this overrides the +PNG_LIBPNG_BUILD_BASE_TYPE definition which is not directly user controllable. + +Starting with libpng-1.6.19, attempting to set an over-length PLTE chunk +is an error. Previously this requirement of the PNG specification was not +enforced, and the palette was always limited to 256 entries. An over-length +PLTE chunk found in an input PNG is silently truncated. + XIII. Detecting libpng The png_get_io_ptr() function has been present since libpng-0.88, has never @@ -5262,10 +5300,12 @@ We prefer #ifdef and #ifndef to #if defined() and #if !defined() when there is only one macro being tested. We always use parentheses with "defined". -We prefer to express integers that are used as bit masks in hex format, -with an even number of lower-case hex digits (e.g., 0x00, 0xff, 0x0100). +We express integer constants that are used as bit masks in hex format, +with an even number of lower-case hex digits, and to make them unsigned +(e.g., 0x00U, 0xffU, 0x0100U) and long if they are greater than 0x7fff +(e.g., 0xffffUL). -We prefer to use underscores in variable names rather than camelCase, except +We prefer to use underscores rather than camelCase in names, except for a few type names that we inherit from zlib.h. We prefer "if (something != 0)" and "if (something == 0)" @@ -5279,13 +5319,11 @@ Other rules can be inferred by inspecting the libpng source. XVI. Y2K Compliance in libpng -March 26, 2015 - Since the PNG Development group is an ad-hoc body, we can't make an official declaration. This is your unofficial assurance that libpng from version 0.71 and -upward through 1.6.17 are Y2K compliant. It is my belief that earlier +upward through 1.6.19 are Y2K compliant. It is my belief that earlier versions were also Y2K compliant. Libpng only has two year fields. One is a 2-byte unsigned integer diff --git a/src/3rdparty/libpng/png.c b/src/3rdparty/libpng/png.c index 7575ede97b..6fcfad72ec 100644 --- a/src/3rdparty/libpng/png.c +++ b/src/3rdparty/libpng/png.c @@ -1,7 +1,7 @@ /* png.c - location for general purpose libpng functions * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -14,7 +14,7 @@ #include "pngpriv.h" /* Generate a compiler error if there is an old png.h in the search path. */ -typedef png_libpng_version_1_6_17 Your_png_h_is_not_version_1_6_17; +typedef png_libpng_version_1_6_19 Your_png_h_is_not_version_1_6_19; /* Tells libpng that we have already handled the first "num_bytes" bytes * of the PNG file signature. If the PNG data is embedded into another @@ -26,15 +26,20 @@ typedef png_libpng_version_1_6_17 Your_png_h_is_not_version_1_6_17; void PNGAPI png_set_sig_bytes(png_structrp png_ptr, int num_bytes) { + unsigned int nb = (unsigned int)num_bytes; + png_debug(1, "in png_set_sig_bytes"); if (png_ptr == NULL) return; - if (num_bytes > 8) + if (num_bytes < 0) + nb = 0; + + if (nb > 8) png_error(png_ptr, "Too many bytes for PNG signature"); - png_ptr->sig_bytes = (png_byte)((num_bytes < 0 ? 0 : num_bytes) & 0xff); + png_ptr->sig_bytes = (png_byte)nb; } /* Checks whether the supplied bytes match the PNG signature. We allow @@ -101,7 +106,7 @@ png_zfree(voidpf png_ptr, voidpf ptr) void /* PRIVATE */ png_reset_crc(png_structrp png_ptr) { - /* The cast is safe because the crc is a 32 bit value. */ + /* The cast is safe because the crc is a 32-bit value. */ png_ptr->crc = (png_uint_32)crc32(0, Z_NULL, 0); } @@ -129,7 +134,7 @@ png_calculate_crc(png_structrp png_ptr, png_const_bytep ptr, png_size_t length) } /* 'uLong' is defined in zlib.h as unsigned long; this means that on some - * systems it is a 64 bit value. crc32, however, returns 32 bits so the + * systems it is a 64-bit value. crc32, however, returns 32 bits so the * following cast is safe. 'uInt' may be no more than 16 bits, so it is * necessary to perform a loop here. */ @@ -243,15 +248,15 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, create_struct.user_height_max = PNG_USER_HEIGHT_MAX; # ifdef PNG_USER_CHUNK_CACHE_MAX - /* Added at libpng-1.2.43 and 1.4.0 */ - create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; + /* Added at libpng-1.2.43 and 1.4.0 */ + create_struct.user_chunk_cache_max = PNG_USER_CHUNK_CACHE_MAX; # endif # ifdef PNG_USER_CHUNK_MALLOC_MAX - /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists - * in png_struct regardless. - */ - create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; + /* Added at libpng-1.2.43 and 1.4.1, required only for read but exists + * in png_struct regardless. + */ + create_struct.user_chunk_malloc_max = PNG_USER_CHUNK_MALLOC_MAX; # endif # endif @@ -275,7 +280,9 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, # ifdef PNG_SETJMP_SUPPORTED if (!setjmp(create_jmp_buf)) +# endif { +# ifdef PNG_SETJMP_SUPPORTED /* Temporarily fake out the longjmp information until we have * successfully completed this function. This only works if we have * setjmp() support compiled in, but it is safe - this stuff should @@ -284,8 +291,6 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, create_struct.jmp_buf_ptr = &create_jmp_buf; create_struct.jmp_buf_size = 0; /*stack allocation*/ create_struct.longjmp_fn = longjmp; -# else - { # endif /* Call the general version checker (shared with read and write code): */ @@ -304,10 +309,10 @@ png_create_png_struct,(png_const_charp user_png_ver, png_voidp error_ptr, create_struct.zstream.opaque = png_ptr; # ifdef PNG_SETJMP_SUPPORTED - /* Eliminate the local error handling: */ - create_struct.jmp_buf_ptr = NULL; - create_struct.jmp_buf_size = 0; - create_struct.longjmp_fn = 0; + /* Eliminate the local error handling: */ + create_struct.jmp_buf_ptr = NULL; + create_struct.jmp_buf_size = 0; + create_struct.longjmp_fn = 0; # endif *png_ptr = create_struct; @@ -413,6 +418,8 @@ png_info_init_3,(png_infopp ptr_ptr, png_size_t png_info_struct_size), free(info_ptr); info_ptr = png_voidcast(png_inforp, png_malloc_base(NULL, (sizeof *info_ptr))); + if (info_ptr == NULL) + return; *ptr_ptr = info_ptr; } @@ -664,19 +671,20 @@ png_init_io(png_structrp png_ptr, png_FILE_p fp) # endif # ifdef PNG_SAVE_INT_32_SUPPORTED -/* The png_save_int_32 function assumes integers are stored in two's - * complement format. If this isn't the case, then this routine needs to - * be modified to write data in two's complement format. Note that, - * the following works correctly even if png_int_32 has more than 32 bits - * (compare the more complex code required on read for sign extension.) +/* PNG signed integers are saved in 32-bit 2's complement format. ANSI C-90 + * defines a cast of a signed integer to an unsigned integer either to preserve + * the value, if it is positive, or to calculate: + * + * (UNSIGNED_MAX+1) + integer + * + * Where UNSIGNED_MAX is the appropriate maximum unsigned value, so when the + * negative integral value is added the result will be an unsigned value + * correspnding to the 2's complement representation. */ void PNGAPI png_save_int_32(png_bytep buf, png_int_32 i) { - buf[0] = (png_byte)((i >> 24) & 0xff); - buf[1] = (png_byte)((i >> 16) & 0xff); - buf[2] = (png_byte)((i >> 8) & 0xff); - buf[3] = (png_byte)(i & 0xff); + png_save_uint_32(buf, i); } # endif @@ -722,6 +730,7 @@ png_convert_to_rfc1123_buffer(char out[29], png_const_timep ptime) APPEND(':'); APPEND_NUMBER(PNG_NUMBER_FORMAT_02u, (unsigned)ptime->second); APPEND_STRING(" +0000"); /* This reliably terminates the buffer */ + PNG_UNUSED (pos) # undef APPEND # undef APPEND_NUMBER @@ -766,13 +775,13 @@ png_get_copyright(png_const_structrp png_ptr) #else # ifdef __STDC__ return PNG_STRING_NEWLINE \ - "libpng version 1.6.17 - March 26, 2015" PNG_STRING_NEWLINE \ - "Copyright (c) 1998-2015 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ - "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ - "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ - PNG_STRING_NEWLINE; + "libpng version 1.6.19 - November 12, 2015" PNG_STRING_NEWLINE \ + "Copyright (c) 1998-2015 Glenn Randers-Pehrson" PNG_STRING_NEWLINE \ + "Copyright (c) 1996-1997 Andreas Dilger" PNG_STRING_NEWLINE \ + "Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc." \ + PNG_STRING_NEWLINE; # else - return "libpng version 1.6.17 - March 26, 2015\ + return "libpng version 1.6.19 - November 12, 2015\ Copyright (c) 1998-2015 Glenn Randers-Pehrson\ Copyright (c) 1996-1997 Andreas Dilger\ Copyright (c) 1995-1996 Guy Eric Schalnat, Group 42, Inc."; @@ -811,9 +820,9 @@ png_get_header_version(png_const_structrp png_ptr) #ifdef __STDC__ return PNG_HEADER_VERSION_STRING # ifndef PNG_READ_SUPPORTED - " (NO READ SUPPORT)" + " (NO READ SUPPORT)" # endif - PNG_STRING_NEWLINE; + PNG_STRING_NEWLINE; #else return PNG_HEADER_VERSION_STRING; #endif @@ -1086,10 +1095,10 @@ png_colorspace_set_gamma(png_const_structrp png_ptr, errmsg = "gamma value out of range"; # ifdef PNG_READ_gAMA_SUPPORTED - /* Allow the application to set the gamma value more than once */ - else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && - (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0) - errmsg = "duplicate"; + /* Allow the application to set the gamma value more than once */ + else if ((png_ptr->mode & PNG_IS_READ_STRUCT) != 0 && + (colorspace->flags & PNG_COLORSPACE_FROM_gAMA) != 0) + errmsg = "duplicate"; # endif /* Do nothing if the colorspace is already invalid */ @@ -1130,31 +1139,31 @@ png_colorspace_sync_info(png_const_structrp png_ptr, png_inforp info_ptr) PNG_INFO_iCCP); # ifdef PNG_COLORSPACE_SUPPORTED - /* Clean up the iCCP profile now if it won't be used. */ - png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/); + /* Clean up the iCCP profile now if it won't be used. */ + png_free_data(png_ptr, info_ptr, PNG_FREE_ICCP, -1/*not used*/); # else - PNG_UNUSED(png_ptr) + PNG_UNUSED(png_ptr) # endif } else { # ifdef PNG_COLORSPACE_SUPPORTED - /* Leave the INFO_iCCP flag set if the pngset.c code has already set - * it; this allows a PNG to contain a profile which matches sRGB and - * yet still have that profile retrievable by the application. - */ - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0) - info_ptr->valid |= PNG_INFO_sRGB; + /* Leave the INFO_iCCP flag set if the pngset.c code has already set + * it; this allows a PNG to contain a profile which matches sRGB and + * yet still have that profile retrievable by the application. + */ + if ((info_ptr->colorspace.flags & PNG_COLORSPACE_MATCHES_sRGB) != 0) + info_ptr->valid |= PNG_INFO_sRGB; - else - info_ptr->valid &= ~PNG_INFO_sRGB; + else + info_ptr->valid &= ~PNG_INFO_sRGB; - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) - info_ptr->valid |= PNG_INFO_cHRM; + if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_ENDPOINTS) != 0) + info_ptr->valid |= PNG_INFO_cHRM; - else - info_ptr->valid &= ~PNG_INFO_cHRM; + else + info_ptr->valid &= ~PNG_INFO_cHRM; # endif if ((info_ptr->colorspace.flags & PNG_COLORSPACE_HAVE_GAMMA) != 0) @@ -1235,16 +1244,17 @@ png_XYZ_from_xy(png_XYZ *XYZ, const png_xy *xy) /* Check xy and, implicitly, z. Note that wide gamut color spaces typically * have end points with 0 tristimulus values (these are impossible end - * points, but they are used to cover the possible colors.) + * points, but they are used to cover the possible colors). We check + * xy->whitey against 5, not 0, to avoid a possible integer overflow. */ - if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; - if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; + if (xy->redx < 0 || xy->redx > PNG_FP_1) return 1; + if (xy->redy < 0 || xy->redy > PNG_FP_1-xy->redx) return 1; if (xy->greenx < 0 || xy->greenx > PNG_FP_1) return 1; if (xy->greeny < 0 || xy->greeny > PNG_FP_1-xy->greenx) return 1; - if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; - if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; + if (xy->bluex < 0 || xy->bluex > PNG_FP_1) return 1; + if (xy->bluey < 0 || xy->bluey > PNG_FP_1-xy->bluex) return 1; if (xy->whitex < 0 || xy->whitex > PNG_FP_1) return 1; - if (xy->whitey < 0 || xy->whitey > PNG_FP_1-xy->whitex) return 1; + if (xy->whitey < 5 || xy->whitey > PNG_FP_1-xy->whitex) return 1; /* The reverse calculation is more difficult because the original tristimulus * value had 9 independent values (red,green,blue)x(X,Y,Z) however only 8 @@ -1702,7 +1712,6 @@ png_colorspace_set_chromaticities(png_const_structrp png_ptr, */ colorspace->flags |= PNG_COLORSPACE_INVALID; png_error(png_ptr, "internal error checking chromaticities"); - break; } return 0; /* failed */ @@ -1730,7 +1739,6 @@ png_colorspace_set_endpoints(png_const_structrp png_ptr, default: colorspace->flags |= PNG_COLORSPACE_INVALID; png_error(png_ptr, "internal error checking chromaticities"); - break; } return 0; /* failed */ @@ -2056,8 +2064,8 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, temp = png_get_uint_32(profile+12); /* profile/device class */ switch (temp) { - case 0x73636E72: /* 'scnr' */ - case 0x6D6E7472: /* 'mntr' */ + case 0x73636e72: /* 'scnr' */ + case 0x6d6e7472: /* 'mntr' */ case 0x70727472: /* 'prtr' */ case 0x73706163: /* 'spac' */ /* All supported */ @@ -2068,7 +2076,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, return png_icc_profile_error(png_ptr, colorspace, name, temp, "invalid embedded Abstract ICC profile"); - case 0x6C696E6B: /* 'link' */ + case 0x6c696e6b: /* 'link' */ /* DeviceLink profiles cannot be interpreted in a non-device specific * fashion, if an app uses the AToB0Tag in the profile the results are * undefined unless the result is sent to the intended device, @@ -2078,7 +2086,7 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, return png_icc_profile_error(png_ptr, colorspace, name, temp, "unexpected DeviceLink ICC profile class"); - case 0x6E6D636C: /* 'nmcl' */ + case 0x6e6d636c: /* 'nmcl' */ /* A NamedColor profile is also device specific, however it doesn't * contain an AToB0 tag that is open to misinterpretation. Almost * certainly it will fail the tests below. @@ -2104,8 +2112,8 @@ png_icc_check_header(png_const_structrp png_ptr, png_colorspacerp colorspace, temp = png_get_uint_32(profile+20); switch (temp) { - case 0x58595A20: /* 'XYZ ' */ - case 0x4C616220: /* 'Lab ' */ + case 0x58595a20: /* 'XYZ ' */ + case 0x4c616220: /* 'Lab ' */ break; default: @@ -2275,8 +2283,8 @@ png_compare_ICC_profile_with_sRGB(png_const_structrp png_ptr, } /* Length *and* intent must match */ - if (length == png_sRGB_checks[i].length && - intent == png_sRGB_checks[i].intent) + if (length == (png_uint_32) png_sRGB_checks[i].length && + intent == (png_uint_32) png_sRGB_checks[i].intent) { /* Now calculate the adler32 if not done already. */ if (adler == 0) @@ -2843,7 +2851,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, if (fp >= DBL_MIN && fp <= DBL_MAX) { - int exp_b10; /* A base 10 exponent */ + int exp_b10; /* A base 10 exponent */ double base; /* 10^exp_b10 */ /* First extract a base 10 exponent of the number, @@ -2891,7 +2899,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, */ { - int czero, clead, cdigits; + unsigned int czero, clead, cdigits; char exponent[10]; /* Allow up to two leading zeros - this will not lengthen @@ -2921,7 +2929,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, * of the loop don't break the number into parts so * that the final digit is rounded. */ - if (cdigits+czero-clead+1 < (int)precision) + if (cdigits+czero+1 < precision+clead) fp = modf(fp, &d); else @@ -3027,7 +3035,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, *ascii++ = (char)(48 + (int)d), ++cdigits; } } - while (cdigits+czero-clead < (int)precision && fp > DBL_MIN); + while (cdigits+czero < precision+clead && fp > DBL_MIN); /* The total output count (max) is now 4+precision */ @@ -3095,7 +3103,7 @@ png_ascii_from_fp(png_const_structrp png_ptr, png_charp ascii, png_size_t size, /* Need another size check here for the exponent digits, so * this need not be considered above. */ - if ((int)size > cdigits) + if (size > cdigits) { while (cdigits > 0) *ascii++ = exponent[--cdigits]; @@ -3143,7 +3151,7 @@ png_ascii_from_fixed(png_const_structrp png_ptr, png_charp ascii, /* Avoid overflow here on the minimum integer. */ if (fp < 0) - *ascii++ = 45, --size, num = -fp; + *ascii++ = 45, num = -fp; else num = fp; @@ -3674,7 +3682,7 @@ png_exp(png_fixed_point x) if (x > 0 && x <= 0xfffff) /* Else overflow or zero (underflow) */ { /* Obtain a 4-bit approximation */ - png_uint_32 e = png_32bit_exp[(x >> 12) & 0xf]; + png_uint_32 e = png_32bit_exp[(x >> 12) & 0x0f]; /* Incorporate the low 12 bits - these decrease the returned value by * multiplying by a number less than 1 if the bit is set. The multiplier @@ -4236,7 +4244,7 @@ png_set_option(png_structrp png_ptr, int option, int onoff) * contrib/tools/makesRGB.c. The actual sRGB transfer curve defined in the * specification (see the article at http://en.wikipedia.org/wiki/SRGB) * is used, not the gamma=1/2.2 approximation use elsewhere in libpng. - * The sRGB to linear table is exact (to the nearest 16 bit linear fraction). + * The sRGB to linear table is exact (to the nearest 16-bit linear fraction). * The inverse (linear to sRGB) table has accuracies as follows: * * For all possible (255*65535+1) input values: diff --git a/src/3rdparty/libpng/png.h b/src/3rdparty/libpng/png.h index 372599bfb4..c83051b1ca 100644 --- a/src/3rdparty/libpng/png.h +++ b/src/3rdparty/libpng/png.h @@ -1,7 +1,7 @@ /* png.h - header file for PNG reference library * - * libpng version 1.6.17, March 26, 2015 + * libpng version 1.6.19, November 12, 2015 * * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -11,232 +11,9 @@ * * Authors and maintainers: * libpng versions 0.71, May 1995, through 0.88, January 1996: Guy Schalnat - * libpng versions 0.89c, June 1996, through 0.96, May 1997: Andreas Dilger - * libpng versions 0.97, January 1998, through 1.6.17, March 26, 2015: Glenn + * libpng versions 0.89, June 1996, through 0.96, May 1997: Andreas Dilger + * libpng versions 0.97, January 1998, through 1.6.19, November 12, 2015: Glenn * See also "Contributing Authors", below. - * - * Note about libpng version numbers: - * - * Due to various miscommunications, unforeseen code incompatibilities - * and occasional factors outside the authors' control, version numbering - * on the library has not always been consistent and straightforward. - * The following table summarizes matters since version 0.89c, which was - * the first widely used release: - * - * source png.h png.h shared-lib - * version string int version - * ------- ------ ----- ---------- - * 0.89c "1.0 beta 3" 0.89 89 1.0.89 - * 0.90 "1.0 beta 4" 0.90 90 0.90 [should have been 2.0.90] - * 0.95 "1.0 beta 5" 0.95 95 0.95 [should have been 2.0.95] - * 0.96 "1.0 beta 6" 0.96 96 0.96 [should have been 2.0.96] - * 0.97b "1.00.97 beta 7" 1.00.97 97 1.0.1 [should have been 2.0.97] - * 0.97c 0.97 97 2.0.97 - * 0.98 0.98 98 2.0.98 - * 0.99 0.99 98 2.0.99 - * 0.99a-m 0.99 99 2.0.99 - * 1.00 1.00 100 2.1.0 [100 should be 10000] - * 1.0.0 (from here on, the 100 2.1.0 [100 should be 10000] - * 1.0.1 png.h string is 10001 2.1.0 - * 1.0.1a-e identical to the 10002 from here on, the shared library - * 1.0.2 source version) 10002 is 2.V where V is the source code - * 1.0.2a-b 10003 version, except as noted. - * 1.0.3 10003 - * 1.0.3a-d 10004 - * 1.0.4 10004 - * 1.0.4a-f 10005 - * 1.0.5 (+ 2 patches) 10005 - * 1.0.5a-d 10006 - * 1.0.5e-r 10100 (not source compatible) - * 1.0.5s-v 10006 (not binary compatible) - * 1.0.6 (+ 3 patches) 10006 (still binary incompatible) - * 1.0.6d-f 10007 (still binary incompatible) - * 1.0.6g 10007 - * 1.0.6h 10007 10.6h (testing xy.z so-numbering) - * 1.0.6i 10007 10.6i - * 1.0.6j 10007 2.1.0.6j (incompatible with 1.0.0) - * 1.0.7beta11-14 DLLNUM 10007 2.1.0.7beta11-14 (binary compatible) - * 1.0.7beta15-18 1 10007 2.1.0.7beta15-18 (binary compatible) - * 1.0.7rc1-2 1 10007 2.1.0.7rc1-2 (binary compatible) - * 1.0.7 1 10007 (still compatible) - * 1.0.8beta1-4 1 10008 2.1.0.8beta1-4 - * 1.0.8rc1 1 10008 2.1.0.8rc1 - * 1.0.8 1 10008 2.1.0.8 - * 1.0.9beta1-6 1 10009 2.1.0.9beta1-6 - * 1.0.9rc1 1 10009 2.1.0.9rc1 - * 1.0.9beta7-10 1 10009 2.1.0.9beta7-10 - * 1.0.9rc2 1 10009 2.1.0.9rc2 - * 1.0.9 1 10009 2.1.0.9 - * 1.0.10beta1 1 10010 2.1.0.10beta1 - * 1.0.10rc1 1 10010 2.1.0.10rc1 - * 1.0.10 1 10010 2.1.0.10 - * 1.0.11beta1-3 1 10011 2.1.0.11beta1-3 - * 1.0.11rc1 1 10011 2.1.0.11rc1 - * 1.0.11 1 10011 2.1.0.11 - * 1.0.12beta1-2 2 10012 2.1.0.12beta1-2 - * 1.0.12rc1 2 10012 2.1.0.12rc1 - * 1.0.12 2 10012 2.1.0.12 - * 1.1.0a-f - 10100 2.1.1.0a-f (branch abandoned) - * 1.2.0beta1-2 2 10200 2.1.2.0beta1-2 - * 1.2.0beta3-5 3 10200 3.1.2.0beta3-5 - * 1.2.0rc1 3 10200 3.1.2.0rc1 - * 1.2.0 3 10200 3.1.2.0 - * 1.2.1beta1-4 3 10201 3.1.2.1beta1-4 - * 1.2.1rc1-2 3 10201 3.1.2.1rc1-2 - * 1.2.1 3 10201 3.1.2.1 - * 1.2.2beta1-6 12 10202 12.so.0.1.2.2beta1-6 - * 1.0.13beta1 10 10013 10.so.0.1.0.13beta1 - * 1.0.13rc1 10 10013 10.so.0.1.0.13rc1 - * 1.2.2rc1 12 10202 12.so.0.1.2.2rc1 - * 1.0.13 10 10013 10.so.0.1.0.13 - * 1.2.2 12 10202 12.so.0.1.2.2 - * 1.2.3rc1-6 12 10203 12.so.0.1.2.3rc1-6 - * 1.2.3 12 10203 12.so.0.1.2.3 - * 1.2.4beta1-3 13 10204 12.so.0.1.2.4beta1-3 - * 1.0.14rc1 13 10014 10.so.0.1.0.14rc1 - * 1.2.4rc1 13 10204 12.so.0.1.2.4rc1 - * 1.0.14 10 10014 10.so.0.1.0.14 - * 1.2.4 13 10204 12.so.0.1.2.4 - * 1.2.5beta1-2 13 10205 12.so.0.1.2.5beta1-2 - * 1.0.15rc1-3 10 10015 10.so.0.1.0.15rc1-3 - * 1.2.5rc1-3 13 10205 12.so.0.1.2.5rc1-3 - * 1.0.15 10 10015 10.so.0.1.0.15 - * 1.2.5 13 10205 12.so.0.1.2.5 - * 1.2.6beta1-4 13 10206 12.so.0.1.2.6beta1-4 - * 1.0.16 10 10016 10.so.0.1.0.16 - * 1.2.6 13 10206 12.so.0.1.2.6 - * 1.2.7beta1-2 13 10207 12.so.0.1.2.7beta1-2 - * 1.0.17rc1 10 10017 12.so.0.1.0.17rc1 - * 1.2.7rc1 13 10207 12.so.0.1.2.7rc1 - * 1.0.17 10 10017 12.so.0.1.0.17 - * 1.2.7 13 10207 12.so.0.1.2.7 - * 1.2.8beta1-5 13 10208 12.so.0.1.2.8beta1-5 - * 1.0.18rc1-5 10 10018 12.so.0.1.0.18rc1-5 - * 1.2.8rc1-5 13 10208 12.so.0.1.2.8rc1-5 - * 1.0.18 10 10018 12.so.0.1.0.18 - * 1.2.8 13 10208 12.so.0.1.2.8 - * 1.2.9beta1-3 13 10209 12.so.0.1.2.9beta1-3 - * 1.2.9beta4-11 13 10209 12.so.0.9[.0] - * 1.2.9rc1 13 10209 12.so.0.9[.0] - * 1.2.9 13 10209 12.so.0.9[.0] - * 1.2.10beta1-7 13 10210 12.so.0.10[.0] - * 1.2.10rc1-2 13 10210 12.so.0.10[.0] - * 1.2.10 13 10210 12.so.0.10[.0] - * 1.4.0beta1-5 14 10400 14.so.0.0[.0] - * 1.2.11beta1-4 13 10211 12.so.0.11[.0] - * 1.4.0beta7-8 14 10400 14.so.0.0[.0] - * 1.2.11 13 10211 12.so.0.11[.0] - * 1.2.12 13 10212 12.so.0.12[.0] - * 1.4.0beta9-14 14 10400 14.so.0.0[.0] - * 1.2.13 13 10213 12.so.0.13[.0] - * 1.4.0beta15-36 14 10400 14.so.0.0[.0] - * 1.4.0beta37-87 14 10400 14.so.14.0[.0] - * 1.4.0rc01 14 10400 14.so.14.0[.0] - * 1.4.0beta88-109 14 10400 14.so.14.0[.0] - * 1.4.0rc02-08 14 10400 14.so.14.0[.0] - * 1.4.0 14 10400 14.so.14.0[.0] - * 1.4.1beta01-03 14 10401 14.so.14.1[.0] - * 1.4.1rc01 14 10401 14.so.14.1[.0] - * 1.4.1beta04-12 14 10401 14.so.14.1[.0] - * 1.4.1 14 10401 14.so.14.1[.0] - * 1.4.2 14 10402 14.so.14.2[.0] - * 1.4.3 14 10403 14.so.14.3[.0] - * 1.4.4 14 10404 14.so.14.4[.0] - * 1.5.0beta01-58 15 10500 15.so.15.0[.0] - * 1.5.0rc01-07 15 10500 15.so.15.0[.0] - * 1.5.0 15 10500 15.so.15.0[.0] - * 1.5.1beta01-11 15 10501 15.so.15.1[.0] - * 1.5.1rc01-02 15 10501 15.so.15.1[.0] - * 1.5.1 15 10501 15.so.15.1[.0] - * 1.5.2beta01-03 15 10502 15.so.15.2[.0] - * 1.5.2rc01-03 15 10502 15.so.15.2[.0] - * 1.5.2 15 10502 15.so.15.2[.0] - * 1.5.3beta01-10 15 10503 15.so.15.3[.0] - * 1.5.3rc01-02 15 10503 15.so.15.3[.0] - * 1.5.3beta11 15 10503 15.so.15.3[.0] - * 1.5.3 [omitted] - * 1.5.4beta01-08 15 10504 15.so.15.4[.0] - * 1.5.4rc01 15 10504 15.so.15.4[.0] - * 1.5.4 15 10504 15.so.15.4[.0] - * 1.5.5beta01-08 15 10505 15.so.15.5[.0] - * 1.5.5rc01 15 10505 15.so.15.5[.0] - * 1.5.5 15 10505 15.so.15.5[.0] - * 1.5.6beta01-07 15 10506 15.so.15.6[.0] - * 1.5.6rc01-03 15 10506 15.so.15.6[.0] - * 1.5.6 15 10506 15.so.15.6[.0] - * 1.5.7beta01-05 15 10507 15.so.15.7[.0] - * 1.5.7rc01-03 15 10507 15.so.15.7[.0] - * 1.5.7 15 10507 15.so.15.7[.0] - * 1.6.0beta01-40 16 10600 16.so.16.0[.0] - * 1.6.0rc01-08 16 10600 16.so.16.0[.0] - * 1.6.0 16 10600 16.so.16.0[.0] - * 1.6.1beta01-09 16 10601 16.so.16.1[.0] - * 1.6.1rc01 16 10601 16.so.16.1[.0] - * 1.6.1 16 10601 16.so.16.1[.0] - * 1.6.2beta01 16 10602 16.so.16.2[.0] - * 1.6.2rc01-06 16 10602 16.so.16.2[.0] - * 1.6.2 16 10602 16.so.16.2[.0] - * 1.6.3beta01-11 16 10603 16.so.16.3[.0] - * 1.6.3rc01 16 10603 16.so.16.3[.0] - * 1.6.3 16 10603 16.so.16.3[.0] - * 1.6.4beta01-02 16 10604 16.so.16.4[.0] - * 1.6.4rc01 16 10604 16.so.16.4[.0] - * 1.6.4 16 10604 16.so.16.4[.0] - * 1.6.5 16 10605 16.so.16.5[.0] - * 1.6.6 16 10606 16.so.16.6[.0] - * 1.6.7beta01-04 16 10607 16.so.16.7[.0] - * 1.6.7rc01-03 16 10607 16.so.16.7[.0] - * 1.6.7 16 10607 16.so.16.7[.0] - * 1.6.8beta01-02 16 10608 16.so.16.8[.0] - * 1.6.8rc01-02 16 10608 16.so.16.8[.0] - * 1.6.8 16 10608 16.so.16.8[.0] - * 1.6.9beta01-04 16 10609 16.so.16.9[.0] - * 1.6.9rc01-02 16 10609 16.so.16.9[.0] - * 1.6.9 16 10609 16.so.16.9[.0] - * 1.6.10beta01-03 16 10610 16.so.16.10[.0] - * 1.6.10rc01-03 16 10610 16.so.16.10[.0] - * 1.6.10 16 10610 16.so.16.10[.0] - * 1.6.11beta01-06 16 10611 16.so.16.11[.0] - * 1.6.11rc01-02 16 10611 16.so.16.11[.0] - * 1.6.11 16 10611 16.so.16.11[.0] - * 1.6.12rc01-03 16 10612 16.so.16.12[.0] - * 1.6.12 16 10612 16.so.16.12[.0] - * 1.6.13beta01-04 16 10613 16.so.16.13[.0] - * 1.6.13rc01-02 16 10613 16.so.16.13[.0] - * 1.6.13 16 10613 16.so.16.13[.0] - * 1.6.14beta01-07 16 10614 16.so.16.14[.0] - * 1.6.14rc01-02 16 10614 16.so.16.14[.0] - * 1.6.14 16 10614 16.so.16.14[.0] - * 1.6.15beta01-08 16 10615 16.so.16.15[.0] - * 1.6.15rc01-03 16 10615 16.so.16.15[.0] - * 1.6.15 16 10615 16.so.16.15[.0] - * 1.6.16beta01-03 16 10616 16.so.16.16[.0] - * 1.6.16rc01-02 16 10616 16.so.16.16[.0] - * 1.6.16 16 10616 16.so.16.16[.0] - * 1.6.17beta01-06 16 10617 16.so.16.17[.0] - * 1.6.17rc01-06 16 10617 16.so.16.17[.0] - * 1.6.17 16 10617 16.so.16.17[.0] - * - * Henceforth the source version will match the shared-library major - * and minor numbers; the shared-library major version number will be - * used for changes in backward compatibility, as it is intended. The - * PNG_LIBPNG_VER macro, which is not used within libpng but is available - * for applications, is an unsigned integer of the form xyyzz corresponding - * to the source version x.y.z (leading zeros in y and z). Beta versions - * were given the previous public release number plus a letter, until - * version 1.0.6j; from then on they were given the upcoming public - * release number plus "betaNN" or "rcNN". - * - * Binary incompatibility exists only when applications make direct access - * to the info_ptr or png_ptr members through png.h, and the compiled - * application is loaded with a different version of the library. - * - * DLLNUM will change each time there are forward or backward changes - * in binary compatibility (e.g., when a new feature is added). - * - * See libpng-manual.txt or libpng.3 for more information. The PNG - * specification is available as a W3C Recommendation and as an ISO - * Specification, = 0x8000 /* else this might break */ #define PNG_INFO_IDAT 0x8000 /* ESR, 1.0.6 */ +#endif /* This is used for the transformation routines, as some of them * change these values for the row. It also should enable using @@ -993,7 +854,9 @@ PNG_FUNCTION(void, (PNGCAPI *png_longjmp_ptr), PNGARG((jmp_buf, int)), typedef); #define PNG_TRANSFORM_GRAY_TO_RGB 0x2000 /* read only */ /* Added to libpng-1.5.4 */ #define PNG_TRANSFORM_EXPAND_16 0x4000 /* read only */ +#if INT_MAX >= 0x8000 /* else this might break */ #define PNG_TRANSFORM_SCALE_16 0x8000 /* read only */ +#endif /* Flags for MNG supported features */ #define PNG_FLAG_MNG_EMPTY_PLTE 0x01 @@ -1010,7 +873,7 @@ typedef PNG_CALLBACK(png_voidp, *png_malloc_ptr, (png_structp, png_alloc_size_t)); typedef PNG_CALLBACK(void, *png_free_ptr, (png_structp, png_voidp)); -/* Section 3: exported functions +/* Section 4: exported functions * Here are the function definitions most commonly used. This is not * the place to find out how to use libpng. See libpng-manual.txt for the * full explanation, see example.c for the summary. This just provides @@ -1383,13 +1246,13 @@ PNG_EXPORT(38, void, png_set_invert_alpha, (png_structrp png_ptr)); #endif #if defined(PNG_READ_FILLER_SUPPORTED) || defined(PNG_WRITE_FILLER_SUPPORTED) -/* Add a filler byte to 8-bit Gray or 24-bit RGB images. */ +/* Add a filler byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ PNG_EXPORT(39, void, png_set_filler, (png_structrp png_ptr, png_uint_32 filler, int flags)); /* The values of the PNG_FILLER_ defines should NOT be changed */ # define PNG_FILLER_BEFORE 0 # define PNG_FILLER_AFTER 1 -/* Add an alpha byte to 8-bit Gray or 24-bit RGB images. */ +/* Add an alpha byte to 8-bit or 16-bit Gray or 24-bit or 48-bit RGB images. */ PNG_EXPORT(40, void, png_set_add_alpha, (png_structrp png_ptr, png_uint_32 filler, int flags)); #endif /* READ_FILLER || WRITE_FILLER */ @@ -1623,35 +1486,7 @@ PNG_EXPORT(67, void, png_set_filter, (png_structrp png_ptr, int method, #define PNG_FILTER_VALUE_LAST 5 #ifdef PNG_WRITE_SUPPORTED -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* EXPERIMENTAL */ -/* The "heuristic_method" is given by one of the PNG_FILTER_HEURISTIC_ - * defines, either the default (minimum-sum-of-absolute-differences), or - * the experimental method (weighted-minimum-sum-of-absolute-differences). - * - * Weights are factors >= 1.0, indicating how important it is to keep the - * filter type consistent between rows. Larger numbers mean the current - * filter is that many times as likely to be the same as the "num_weights" - * previous filters. This is cumulative for each previous row with a weight. - * There needs to be "num_weights" values in "filter_weights", or it can be - * NULL if the weights aren't being specified. Weights have no influence on - * the selection of the first row filter. Well chosen weights can (in theory) - * improve the compression for a given image. - * - * Costs are factors >= 1.0 indicating the relative decoding costs of a - * filter type. Higher costs indicate more decoding expense, and are - * therefore less likely to be selected over a filter with lower computational - * costs. There needs to be a value in "filter_costs" for each valid filter - * type (given by PNG_FILTER_VALUE_LAST), or it can be NULL if you aren't - * setting the costs. Costs try to improve the speed of decompression without - * unduly increasing the compressed image size. - * - * A negative weight or cost indicates the default value is to be used, and - * values in the range [0.0, 1.0) indicate the value is to remain unchanged. - * The default values for both weights and costs are currently 1.0, but may - * change if good general weighting/cost heuristics can be found. If both - * the weights and costs are set to 1.0, this degenerates the WEIGHTED method - * to the UNWEIGHTED method, but with added encoding time/computation. - */ +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ PNG_FP_EXPORT(68, void, png_set_filter_heuristics, (png_structrp png_ptr, int heuristic_method, int num_weights, png_const_doublep filter_weights, png_const_doublep filter_costs)) @@ -1661,9 +1496,7 @@ PNG_FIXED_EXPORT(209, void, png_set_filter_heuristics_fixed, png_const_fixed_point_p filter_costs)) #endif /* WRITE_WEIGHTED_FILTER */ -/* Heuristic used for row filter selection. These defines should NOT be - * changed. - */ +/* The following are no longer used and will be removed from libpng-1.7: */ #define PNG_FILTER_HEURISTIC_DEFAULT 0 /* Currently "UNWEIGHTED" */ #define PNG_FILTER_HEURISTIC_UNWEIGHTED 1 /* Used by libpng < 0.95 */ #define PNG_FILTER_HEURISTIC_WEIGHTED 2 /* Experimental feature */ @@ -2744,7 +2577,7 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); # define PNG_get_int_32(buf) \ ((png_int_32)((*(buf) & 0x80) \ - ? -((png_int_32)((png_get_uint_32(buf) ^ 0xffffffffL) + 1)) \ + ? -((png_int_32)(((png_get_uint_32(buf)^0xffffffffU)+1U)&0x7fffffffU)) \ : (png_int_32)png_get_uint_32(buf))) /* If PNG_PREFIX is defined the same thing as below happens in pnglibconf.h, @@ -2764,10 +2597,17 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); # endif #endif -#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ - defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) +#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED +PNG_EXPORT(242, void, png_set_check_for_invalid_index, + (png_structrp png_ptr, int allowed)); +# ifdef PNG_GET_PALETTE_MAX_SUPPORTED +PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, + png_const_infop info_ptr)); +# endif +#endif /* CHECK_FOR_INVALID_INDEX */ + /******************************************************************************* - * SIMPLIFIED API + * Section 5: SIMPLIFIED API ******************************************************************************* * * Please read the documentation in libpng-manual.txt (TODO: write said @@ -2783,8 +2623,9 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); * * To read a PNG file using the simplified API: * - * 1) Declare a 'png_image' structure (see below) on the stack and set the - * version field to PNG_IMAGE_VERSION. + * 1) Declare a 'png_image' structure (see below) on the stack, set the + * version field to PNG_IMAGE_VERSION and the 'opaque' pointer to NULL + * (this is REQUIRED, your program may crash if you don't do it.) * 2) Call the appropriate png_image_begin_read... function. * 3) Set the png_image 'format' member to the required sample format. * 4) Allocate a buffer for the image and, if required, the color-map. @@ -2811,6 +2652,9 @@ PNG_EXPORT(207, void, png_save_uint_16, (png_bytep buf, unsigned int i)); * when it is being read or defines the in-memory format of an image that you * need to write: */ +#if defined(PNG_SIMPLIFIED_READ_SUPPORTED) || \ + defined(PNG_SIMPLIFIED_WRITE_SUPPORTED) + #define PNG_IMAGE_VERSION 1 typedef struct png_control *png_controlp; @@ -2910,7 +2754,7 @@ typedef struct * called to read or write the color-map and set the format correctly for the * image data. Do not set the PNG_FORMAT_FLAG_COLORMAP bit directly! * - * NOTE: libpng can be built with particular features disabled, if you see + * NOTE: libpng can be built with particular features disabled. If you see * compiler errors because the definition of one of the following flags has been * compiled out it is because libpng does not have the required support. It is * possible, however, for the libpng configuration to enable the format on just @@ -2922,7 +2766,7 @@ typedef struct */ #define PNG_FORMAT_FLAG_ALPHA 0x01U /* format with an alpha channel */ #define PNG_FORMAT_FLAG_COLOR 0x02U /* color format: otherwise grayscale */ -#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2 byte channels else 1 byte */ +#define PNG_FORMAT_FLAG_LINEAR 0x04U /* 2-byte channels else 1-byte */ #define PNG_FORMAT_FLAG_COLORMAP 0x08U /* image data is color-mapped */ #ifdef PNG_FORMAT_BGR_SUPPORTED @@ -3209,9 +3053,11 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, * * With all APIs row_stride is handled as in the read APIs - it is the spacing * from one row to the next in component sized units (1 or 2 bytes) and if - * negative indicates a bottom-up row layout in the buffer. + * negative indicates a bottom-up row layout in the buffer. If row_stride is zero, + * libpng will calculate it for you from the image width and number of channels. * - * Note that the write API does not support interlacing or sub-8-bit pixels. + * Note that the write API does not support interlacing, sub-8-bit pixels, indexed + * PNG (color_type 3) or most ancillary chunks. */ #endif /* STDIO */ #endif /* SIMPLIFIED_WRITE */ @@ -3220,17 +3066,8 @@ PNG_EXPORT(240, int, png_image_write_to_stdio, (png_imagep image, FILE *file, ******************************************************************************/ #endif /* SIMPLIFIED_{READ|WRITE} */ -#ifdef PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED -PNG_EXPORT(242, void, png_set_check_for_invalid_index, - (png_structrp png_ptr, int allowed)); -# ifdef PNG_GET_PALETTE_MAX_SUPPORTED -PNG_EXPORT(243, int, png_get_palette_max, (png_const_structp png_ptr, - png_const_infop info_ptr)); -# endif -#endif /* CHECK_FOR_INVALID_INDEX */ - /******************************************************************************* - * IMPLEMENTATION OPTIONS + * Section 6: IMPLEMENTATION OPTIONS ******************************************************************************* * * Support for arbitrary implementation-specific optimizations. The API allows diff --git a/src/3rdparty/libpng/pngconf.h b/src/3rdparty/libpng/pngconf.h index 3f9493e438..f1b795b478 100644 --- a/src/3rdparty/libpng/pngconf.h +++ b/src/3rdparty/libpng/pngconf.h @@ -1,7 +1,7 @@ /* pngconf.h - machine configurable file for libpng * - * libpng version 1.6.17, March 26, 2015 + * libpng version 1.6.19, July 23, 2015 * * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) @@ -63,7 +63,7 @@ */ #define PNG_CONST const /* backward compatibility only */ -/* This controls optimization of the reading of 16 and 32 bit values +/* This controls optimization of the reading of 16-bit and 32-bit values * from PNG files. It can be set on a per-app-file basis - it * just changes whether a macro is used when the function is called. * The library builder sets the default; if read functions are not @@ -295,11 +295,11 @@ * table entries, so we discard it here. See the .dfn files in the * scripts directory. */ -#ifndef PNG_EXPORTA -# define PNG_EXPORTA(ordinal, type, name, args, attributes)\ - PNG_FUNCTION(PNG_EXPORT_TYPE(type),(PNGAPI name),PNGARG(args), \ - extern attributes) +#ifndef PNG_EXPORTA +# define PNG_EXPORTA(ordinal, type, name, args, attributes) \ + PNG_FUNCTION(PNG_EXPORT_TYPE(type), (PNGAPI name), PNGARG(args), \ + PNG_LINKAGE_API attributes) #endif /* ANSI-C (C90) does not permit a macro to be invoked with an empty argument, @@ -307,7 +307,7 @@ */ #define PNG_EMPTY /*empty list*/ -#define PNG_EXPORT(ordinal, type, name, args)\ +#define PNG_EXPORT(ordinal, type, name, args) \ PNG_EXPORTA(ordinal, type, name, args, PNG_EMPTY) /* Use PNG_REMOVED to comment out a removed interface. */ @@ -480,7 +480,7 @@ #if CHAR_BIT == 8 && UCHAR_MAX == 255 typedef unsigned char png_byte; #else -# error "libpng requires 8 bit bytes" +# error "libpng requires 8-bit bytes" #endif #if INT_MIN == -32768 && INT_MAX == 32767 @@ -488,7 +488,7 @@ #elif SHRT_MIN == -32768 && SHRT_MAX == 32767 typedef short png_int_16; #else -# error "libpng requires a signed 16 bit type" +# error "libpng requires a signed 16-bit type" #endif #if UINT_MAX == 65535 @@ -496,7 +496,7 @@ #elif USHRT_MAX == 65535 typedef unsigned short png_uint_16; #else -# error "libpng requires an unsigned 16 bit type" +# error "libpng requires an unsigned 16-bit type" #endif #if INT_MIN < -2147483646 && INT_MAX > 2147483646 @@ -504,7 +504,7 @@ #elif LONG_MIN < -2147483646 && LONG_MAX > 2147483646 typedef long int png_int_32; #else -# error "libpng requires a signed 32 bit (or more) type" +# error "libpng requires a signed 32-bit (or more) type" #endif #if UINT_MAX > 4294967294 @@ -512,7 +512,7 @@ #elif ULONG_MAX > 4294967294 typedef unsigned long int png_uint_32; #else -# error "libpng requires an unsigned 32 bit (or more) type" +# error "libpng requires an unsigned 32-bit (or more) type" #endif /* Prior to 1.6.0 it was possible to disable the use of size_t, 1.6.0, however, diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h index f0fdcf8068..8b6da9eb2c 100644 --- a/src/3rdparty/libpng/pnglibconf.h +++ b/src/3rdparty/libpng/pnglibconf.h @@ -1,8 +1,6 @@ -/* libpng 1.6.17 STANDARD API DEFINITION */ - /* pnglibconf.h - library build configuration */ -/* Libpng version 1.6.17 - March 26, 2015 */ +/* libpng version 1.6.19, July 23, 2015 */ /* Copyright (c) 1998-2014 Glenn Randers-Pehrson */ @@ -196,6 +194,10 @@ #define PNG_GAMMA_THRESHOLD_FIXED 5000 #define PNG_IDAT_READ_SIZE PNG_ZBUF_SIZE #define PNG_INFLATE_BUF_SIZE 1024 +#define PNG_LINKAGE_API extern +#define PNG_LINKAGE_CALLBACK extern +#define PNG_LINKAGE_DATA extern +#define PNG_LINKAGE_FUNCTION extern #define PNG_MAX_GAMMA_8 11 #define PNG_QUANTIZE_BLUE_BITS 5 #define PNG_QUANTIZE_GREEN_BITS 5 diff --git a/src/3rdparty/libpng/pngmem.c b/src/3rdparty/libpng/pngmem.c index 8b157e54d2..45ac5579b2 100644 --- a/src/3rdparty/libpng/pngmem.c +++ b/src/3rdparty/libpng/pngmem.c @@ -77,6 +77,9 @@ png_malloc_base,(png_const_structrp png_ptr, png_alloc_size_t size), PNG_UNUSED(png_ptr) #endif + /* Some compilers complain that this is always true. However, it + * can be false when integer overflow happens. + */ if (size > 0 && size <= PNG_SIZE_MAX # ifdef PNG_MAX_MALLOC_64K && size <= 65536U diff --git a/src/3rdparty/libpng/pngpread.c b/src/3rdparty/libpng/pngpread.c index 823dcad8c0..9f68f99023 100644 --- a/src/3rdparty/libpng/pngpread.c +++ b/src/3rdparty/libpng/pngpread.c @@ -1,7 +1,7 @@ /* pngpread.c - read a png file in push mode * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.18 [July 23, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -19,7 +19,6 @@ #define PNG_READ_SIG_MODE 0 #define PNG_READ_CHUNK_MODE 1 #define PNG_READ_IDAT_MODE 2 -#define PNG_SKIP_MODE 3 #define PNG_READ_tEXt_MODE 4 #define PNG_READ_zTXt_MODE 5 #define PNG_READ_DONE_MODE 6 @@ -78,32 +77,14 @@ png_process_data_pause(png_structrp png_ptr, int save) png_uint_32 PNGAPI png_process_data_skip(png_structrp png_ptr) { - png_uint_32 remaining = 0; - - if (png_ptr != NULL && png_ptr->process_mode == PNG_SKIP_MODE && - png_ptr->skip_length > 0) - { - /* At the end of png_process_data the buffer size must be 0 (see the loop - * above) so we can detect a broken call here: - */ - if (png_ptr->buffer_size != 0) - png_error(png_ptr, - "png_process_data_skip called inside png_process_data"); - - /* If is impossible for there to be a saved buffer at this point - - * otherwise we could not be in SKIP mode. This will also happen if - * png_process_skip is called inside png_process_data (but only very - * rarely.) - */ - if (png_ptr->save_buffer_size != 0) - png_error(png_ptr, "png_process_data_skip called with saved data"); - - remaining = png_ptr->skip_length; - png_ptr->skip_length = 0; - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } - - return remaining; + /* TODO: Deprecate and remove this API. + * Somewhere the implementation of this seems to have been lost, + * or abandoned. It was only to support some internal back-door access + * to png_struct) in libpng-1.4.x. + */ + png_app_warning(png_ptr, +"png_process_data_skip is not implemented in any current version of libpng"); + return 0; } /* What we do with the incoming data depends on what we were previously @@ -135,12 +116,6 @@ png_process_some_data(png_structrp png_ptr, png_inforp info_ptr) break; } - case PNG_SKIP_MODE: - { - png_push_crc_finish(png_ptr); - break; - } - default: { png_ptr->buffer_size = 0; @@ -159,7 +134,7 @@ void /* PRIVATE */ png_push_read_sig(png_structrp png_ptr, png_inforp info_ptr) { png_size_t num_checked = png_ptr->sig_bytes, /* SAFE, does not exceed 8 */ - num_to_check = 8 - num_checked; + num_to_check = 8 - num_checked; if (png_ptr->buffer_size < num_to_check) { @@ -439,69 +414,6 @@ png_push_read_chunk(png_structrp png_ptr, png_inforp info_ptr) png_ptr->mode &= ~PNG_HAVE_CHUNK_HEADER; } -void /* PRIVATE */ -png_push_crc_skip(png_structrp png_ptr, png_uint_32 skip) -{ - png_ptr->process_mode = PNG_SKIP_MODE; - png_ptr->skip_length = skip; -} - -void /* PRIVATE */ -png_push_crc_finish(png_structrp png_ptr) -{ - if (png_ptr->skip_length != 0 && png_ptr->save_buffer_size != 0) - { - png_size_t save_size = png_ptr->save_buffer_size; - png_uint_32 skip_length = png_ptr->skip_length; - - /* We want the smaller of 'skip_length' and 'save_buffer_size', but - * they are of different types and we don't know which variable has the - * fewest bits. Carefully select the smaller and cast it to the type of - * the larger - this cannot overflow. Do not cast in the following test - * - it will break on either 16 or 64 bit platforms. - */ - if (skip_length < save_size) - save_size = (png_size_t)skip_length; - - else - skip_length = (png_uint_32)save_size; - - png_calculate_crc(png_ptr, png_ptr->save_buffer_ptr, save_size); - - png_ptr->skip_length -= skip_length; - png_ptr->buffer_size -= save_size; - png_ptr->save_buffer_size -= save_size; - png_ptr->save_buffer_ptr += save_size; - } - if (png_ptr->skip_length != 0 && png_ptr->current_buffer_size != 0) - { - png_size_t save_size = png_ptr->current_buffer_size; - png_uint_32 skip_length = png_ptr->skip_length; - - /* We want the smaller of 'skip_length' and 'current_buffer_size', here, - * the same problem exists as above and the same solution. - */ - if (skip_length < save_size) - save_size = (png_size_t)skip_length; - - else - skip_length = (png_uint_32)save_size; - - png_calculate_crc(png_ptr, png_ptr->current_buffer_ptr, save_size); - - png_ptr->skip_length -= skip_length; - png_ptr->buffer_size -= save_size; - png_ptr->current_buffer_size -= save_size; - png_ptr->current_buffer_ptr += save_size; - } - if (png_ptr->skip_length == 0) - { - PNG_PUSH_SAVE_BUFFER_IF_LT(4) - png_crc_finish(png_ptr, 0); - png_ptr->process_mode = PNG_READ_CHUNK_MODE; - } -} - void PNGCBAPI png_push_fill_buffer(png_structp png_ptr, png_bytep buffer, png_size_t length) { @@ -584,13 +496,11 @@ png_push_save_buffer(png_structrp png_ptr) if (png_ptr->save_buffer == NULL) { png_free(png_ptr, old_buffer); - old_buffer = NULL; png_error(png_ptr, "Insufficient memory for save_buffer"); } memcpy(png_ptr->save_buffer, old_buffer, png_ptr->save_buffer_size); png_free(png_ptr, old_buffer); - old_buffer = NULL; png_ptr->save_buffer_max = new_max; } if (png_ptr->current_buffer_size) @@ -653,7 +563,7 @@ png_push_read_IDAT(png_structrp png_ptr) * are of different types and we don't know which variable has the fewest * bits. Carefully select the smaller and cast it to the type of the * larger - this cannot overflow. Do not cast in the following test - it - * will break on either 16 or 64 bit platforms. + * will break on either 16-bit or 64-bit platforms. */ if (idat_size < save_size) save_size = (png_size_t)idat_size; @@ -696,6 +606,7 @@ png_push_read_IDAT(png_structrp png_ptr) png_ptr->current_buffer_size -= save_size; png_ptr->current_buffer_ptr += save_size; } + if (png_ptr->idat_size == 0) { PNG_PUSH_SAVE_BUFFER_IF_LT(4) diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h index 7185444f2c..f7a45477a4 100644 --- a/src/3rdparty/libpng/pngpriv.h +++ b/src/3rdparty/libpng/pngpriv.h @@ -1,7 +1,7 @@ /* pngpriv.h - private declarations for use inside libpng * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.18 [July 23, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -124,8 +124,12 @@ * to compile with an appropriate #error if ALIGNED_MEMORY has been turned * off. * - * Note that gcc-4.9 defines __ARM_NEON instead of __ARM_NEON__, so we - * check both variants. + * Note that gcc-4.9 defines __ARM_NEON instead of the deprecated + * __ARM_NEON__, so we check both variants. + * + * To disable ARM_NEON optimizations entirely, and skip compiling the + * associated assembler code, pass --enable-arm-neon=no to configure + * or put -DPNG_ARM_NEON_OPT=0 in CPPFLAGS. */ # if (defined(__ARM_NEON__) || defined(__ARM_NEON)) && \ defined(PNG_ALIGNED_MEMORY_SUPPORTED) @@ -259,17 +263,18 @@ * always be used to declare an extern data or function object in this file. */ #ifndef PNG_INTERNAL_DATA -# define PNG_INTERNAL_DATA(type, name, array) extern type name array +# define PNG_INTERNAL_DATA(type, name, array) PNG_LINKAGE_DATA type name array #endif #ifndef PNG_INTERNAL_FUNCTION # define PNG_INTERNAL_FUNCTION(type, name, args, attributes)\ - extern PNG_FUNCTION(type, name, args, PNG_EMPTY attributes) + PNG_LINKAGE_FUNCTION PNG_FUNCTION(type, name, args, PNG_EMPTY attributes) #endif #ifndef PNG_INTERNAL_CALLBACK # define PNG_INTERNAL_CALLBACK(type, name, args, attributes)\ - extern PNG_FUNCTION(type, (PNGCBAPI name), args, PNG_EMPTY attributes) + PNG_LINKAGE_CALLBACK PNG_FUNCTION(type, (PNGCBAPI name), args,\ + PNG_EMPTY attributes) #endif /* If floating or fixed point APIs are disabled they may still be compiled @@ -307,6 +312,22 @@ # define PNG_DLL_EXPORT #endif +/* This is a global switch to set the compilation for an installed system + * (a release build). It can be set for testing debug builds to ensure that + * they will compile when the build type is switched to RC or STABLE, the + * default is just to use PNG_LIBPNG_BUILD_BASE_TYPE. Set this in CPPFLAGS + * with either: + * + * -DPNG_RELEASE_BUILD Turns on the release compile path + * -DPNG_RELEASE_BUILD=0 Turns it off + * or in your pngusr.h with + * #define PNG_RELEASE_BUILD=1 Turns on the release compile path + * #define PNG_RELEASE_BUILD=0 Turns it off + */ +#ifndef PNG_RELEASE_BUILD +# define PNG_RELEASE_BUILD (PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC) +#endif + /* SECURITY and SAFETY: * * libpng is built with support for internal limits on image dimensions and @@ -568,10 +589,6 @@ #define PNG_STRUCT_PNG 0x0001 #define PNG_STRUCT_INFO 0x0002 -/* Scaling factor for filter heuristic weighting calculations */ -#define PNG_WEIGHT_FACTOR (1<<(PNG_WEIGHT_SHIFT)) -#define PNG_COST_FACTOR (1<<(PNG_COST_SHIFT)) - /* Flags for the png_ptr->flags rather than declaring a byte for each one */ #define PNG_FLAG_ZLIB_CUSTOM_STRATEGY 0x0001 #define PNG_FLAG_ZSTREAM_INITIALIZED 0x0002 /* Added to libpng-1.6.0 */ @@ -662,7 +679,7 @@ /* The fixed point conversion performs range checking and evaluates * its argument multiple times, so must be used with care. The * range checking uses the PNG specification values for a signed - * 32 bit fixed point value except that the values are deliberately + * 32-bit fixed point value except that the values are deliberately * rounded-to-zero to an integral value - 21474 (21474.83 is roughly * (2^31-1) * 100000). 's' is a string that describes the value being * converted. @@ -809,7 +826,7 @@ */ #endif -/* This is used for 16 bit gamma tables -- only the top level pointers are +/* This is used for 16-bit gamma tables -- only the top level pointers are * const; this could be changed: */ typedef const png_uint_16p * png_const_uint_16pp; @@ -1386,10 +1403,6 @@ PNG_INTERNAL_FUNCTION(void,png_push_read_chunk,(png_structrp png_ptr, PNG_INTERNAL_FUNCTION(void,png_push_read_sig,(png_structrp png_ptr, png_inforp info_ptr),PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_check_crc,(png_structrp png_ptr),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_crc_skip,(png_structrp png_ptr, - png_uint_32 length),PNG_EMPTY); -PNG_INTERNAL_FUNCTION(void,png_push_crc_finish,(png_structrp png_ptr), - PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_save_buffer,(png_structrp png_ptr), PNG_EMPTY); PNG_INTERNAL_FUNCTION(void,png_push_restore_buffer,(png_structrp png_ptr, diff --git a/src/3rdparty/libpng/pngread.c b/src/3rdparty/libpng/pngread.c index 6764dbe561..48aae84881 100644 --- a/src/3rdparty/libpng/pngread.c +++ b/src/3rdparty/libpng/pngread.c @@ -63,7 +63,7 @@ png_create_read_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, /* In stable builds only warn if an application error can be completely * handled. */ -# if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC +# if PNG_RELEASE_BUILD png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; # endif # endif @@ -1043,9 +1043,9 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, /* Tell libpng to strip 16-bit/color files down to 8 bits per color. */ if ((transforms & PNG_TRANSFORM_SCALE_16) != 0) - /* Added at libpng-1.5.4. "strip_16" produces the same result that it - * did in earlier versions, while "scale_16" is now more accurate. - */ + /* Added at libpng-1.5.4. "strip_16" produces the same result that it + * did in earlier versions, while "scale_16" is now more accurate. + */ #ifdef PNG_READ_SCALE_16_TO_8_SUPPORTED png_set_scale_16(png_ptr); #else @@ -1209,7 +1209,7 @@ png_read_png(png_structrp png_ptr, png_inforp info_ptr, for (iptr = 0; iptr < info_ptr->height; iptr++) info_ptr->row_pointers[iptr] = png_voidcast(png_bytep, - png_malloc(png_ptr, info_ptr->rowbytes)); + png_malloc(png_ptr, info_ptr->rowbytes)); } png_read_image(png_ptr, info_ptr->row_pointers); @@ -1683,10 +1683,11 @@ decode_gamma(png_image_read_control *display, png_uint_32 value, int encoding) value *= 257; break; +#ifdef __GNUC__ default: png_error(display->image->opaque->png_ptr, "unexpected encoding (internal error)"); - break; +#endif } return value; @@ -2847,10 +2848,6 @@ png_image_read_colormap(png_voidp argument) switch (data_encoding) { - default: - png_error(png_ptr, "bad data option (internal error)"); - break; - case P_sRGB: /* Change to 8-bit sRGB */ png_set_alpha_mode_fixed(png_ptr, PNG_ALPHA_PNG, PNG_GAMMA_sRGB); @@ -2860,6 +2857,11 @@ png_image_read_colormap(png_voidp argument) if (png_ptr->bit_depth > 8) png_set_scale_16(png_ptr); break; + +#ifdef __GNUC__ + default: + png_error(png_ptr, "bad data option (internal error)"); +#endif } if (cmap_entries > 256 || cmap_entries > image->colormap_entries) @@ -3410,10 +3412,6 @@ png_image_read_background(png_voidp argument) */ switch (info_ptr->bit_depth) { - default: - png_error(png_ptr, "unexpected bit depth"); - break; - case 8: /* 8-bit sRGB gray values with an alpha channel; the alpha channel is * to be removed by composing on a background: either the row if @@ -3631,6 +3629,11 @@ png_image_read_background(png_voidp argument) } } break; + +#ifdef __GNUC__ + default: + png_error(png_ptr, "unexpected bit depth"); +#endif } return 1; diff --git a/src/3rdparty/libpng/pngrio.c b/src/3rdparty/libpng/pngrio.c index bb5c825109..38f7fd49d6 100644 --- a/src/3rdparty/libpng/pngrio.c +++ b/src/3rdparty/libpng/pngrio.c @@ -26,7 +26,7 @@ * reads from a file pointer. Note that this routine sometimes gets called * with very small lengths, so you should implement some kind of simple * buffering if you are using unbuffered reads. This should never be asked - * to read more than 64K on a 16 bit machine. + * to read more than 64K on a 16-bit machine. */ void /* PRIVATE */ png_read_data(png_structrp png_ptr, png_bytep data, png_size_t length) diff --git a/src/3rdparty/libpng/pngrtran.c b/src/3rdparty/libpng/pngrtran.c index cad7a8daa5..f129ef129c 100644 --- a/src/3rdparty/libpng/pngrtran.c +++ b/src/3rdparty/libpng/pngrtran.c @@ -1,7 +1,7 @@ /* pngrtran.c - transforms the data in a row for PNG readers * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -976,7 +976,6 @@ png_set_rgb_to_gray_fixed(png_structrp png_ptr, int error_action, default: png_error(png_ptr, "invalid error action to rgb_to_gray"); - break; } if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) @@ -1997,7 +1996,7 @@ png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) # endif # else - /* No 16 bit support: force chopping 16-bit input down to 8, in this case + /* No 16-bit support: force chopping 16-bit input down to 8, in this case * the app program can chose if both APIs are available by setting the * correct scaling to use. */ @@ -2098,10 +2097,10 @@ png_read_transform_info(png_structrp png_ptr, png_inforp info_ptr) defined(PNG_READ_USER_TRANSFORM_SUPPORTED) if ((png_ptr->transformations & PNG_USER_TRANSFORM) != 0) { - if (info_ptr->bit_depth < png_ptr->user_transform_depth) + if (png_ptr->user_transform_depth != 0) info_ptr->bit_depth = png_ptr->user_transform_depth; - if (info_ptr->channels < png_ptr->user_transform_channels) + if (png_ptr->user_transform_channels != 0) info_ptr->channels = png_ptr->user_transform_channels; } #endif @@ -2382,8 +2381,8 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) while (sp < ep) { - /* The input is an array of 16 bit components, these must be scaled to - * 8 bits each. For a 16 bit value V the required value (from the PNG + /* The input is an array of 16-bit components, these must be scaled to + * 8 bits each. For a 16-bit value V the required value (from the PNG * specification) is: * * (V * 255) / 65535 @@ -2404,7 +2403,7 @@ png_do_scale_16_to_8(png_row_infop row_info, png_bytep row) * * The approximate differs from the exact answer only when (vlo-vhi) is * 128; it then gives a correction of +1 when the exact correction is - * 0. This gives 128 errors. The exact answer (correct for all 16 bit + * 0. This gives 128 errors. The exact answer (correct for all 16-bit * input values) is: * * error = (vlo-vhi+128)*65535 >> 24; @@ -3148,9 +3147,9 @@ png_do_rgb_to_gray(png_structrp png_ptr, png_row_infop row_info, png_bytep row) if (red != green || red != blue) rgb_error |= 1; - /* From 1.5.5 in the 16 bit case do the accurate conversion even + /* From 1.5.5 in the 16-bit case do the accurate conversion even * in the 'fast' case - this is because this is where the code - * ends up when handling linear 16 bit data. + * ends up when handling linear 16-bit data. */ gray16 = (png_uint_16)((rc*red + gc*green + bc*blue + 16384) >> 15); @@ -3315,7 +3314,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) if ((png_uint_16)((*sp >> shift) & 0x0f) == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0xf0f >> (4 - shift)); + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); tmp |= png_ptr->background.gray << shift; *sp = (png_byte)(tmp & 0xff); } @@ -3325,7 +3324,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) unsigned int p = (*sp >> shift) & 0x0f; unsigned int g = (gamma_table[p | (p << 4)] >> 4) & 0x0f; - unsigned int tmp = *sp & (0xf0f >> (4 - shift)); + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); tmp |= g << shift; *sp = (png_byte)(tmp & 0xff); } @@ -3351,7 +3350,7 @@ png_do_compose(png_row_infop row_info, png_bytep row, png_structrp png_ptr) if ((png_uint_16)((*sp >> shift) & 0x0f) == png_ptr->trans_color.gray) { - unsigned int tmp = *sp & (0xf0f >> (4 - shift)); + unsigned int tmp = *sp & (0x0f0f >> (4 - shift)); tmp |= png_ptr->background.gray << shift; *sp = (png_byte)(tmp & 0xff); } @@ -4460,7 +4459,7 @@ png_do_expand(png_row_infop row_info, png_bytep row, for (i = 0; i < row_width; i++) { - if (*sp == gray) + if ((*sp & 0xffU) == gray) *dp-- = 0; else @@ -4478,7 +4477,8 @@ png_do_expand(png_row_infop row_info, png_bytep row, dp = row + (row_info->rowbytes << 1) - 1; for (i = 0; i < row_width; i++) { - if (*(sp - 1) == gray_high && *(sp) == gray_low) + if ((*(sp - 1) & 0xffU) == gray_high && + (*(sp) & 0xffU) == gray_low) { *dp-- = 0; *dp-- = 0; diff --git a/src/3rdparty/libpng/pngrutil.c b/src/3rdparty/libpng/pngrutil.c index 6c5c37526b..ee584a8c40 100644 --- a/src/3rdparty/libpng/pngrutil.c +++ b/src/3rdparty/libpng/pngrutil.c @@ -1,7 +1,7 @@ /* pngrutil.c - utilities to read a PNG file * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -89,7 +89,13 @@ png_get_int_32)(png_const_bytep buf) return uval; uval = (uval ^ 0xffffffff) + 1; /* 2's complement: -x = ~x+1 */ - return -(png_int_32)uval; + if ((uval & 0x80000000) == 0) /* no overflow */ + return -(png_int_32)uval; + /* The following has to be safe; this function only gets called on PNG data + * and if we get here that data is invalid. 0 is the most safe value and + * if not then an attacker would surely just generate a PNG with 0 instead. + */ + return 0; } /* Grab an unsigned 16-bit integer from a buffer in big-endian format. */ @@ -98,7 +104,7 @@ png_get_uint_16)(png_const_bytep buf) { /* ANSI-C requires an int value to accomodate at least 16 bits so this * works and allows the compiler not to worry about possible narrowing - * on 32 bit systems. (Pre-ANSI systems did not make integers smaller + * on 32-bit systems. (Pre-ANSI systems did not make integers smaller * than 16 bits either.) */ unsigned int val = @@ -341,7 +347,7 @@ png_inflate_claim(png_structrp png_ptr, png_uint_32 owner) * are minimal. */ (void)png_safecat(msg, (sizeof msg), 4, " using zstream"); -#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC +#if PNG_RELEASE_BUILD png_chunk_warning(png_ptr, msg); png_ptr->zowner = 0; #else @@ -575,7 +581,7 @@ png_decompress_chunk(png_structrp png_ptr, */ png_alloc_size_t limit = PNG_SIZE_MAX; -# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED +# ifdef PNG_SET_USER_LIMITS_SUPPORTED if (png_ptr->user_chunk_malloc_max > 0 && png_ptr->user_chunk_malloc_max < limit) limit = png_ptr->user_chunk_malloc_max; @@ -670,7 +676,6 @@ png_decompress_chunk(png_structrp png_ptr, * success) */ png_free(png_ptr, text); - text = NULL; /* This really is very benign, but it's still an error because * the extra space may otherwise be used as a Trojan Horse. @@ -867,7 +872,7 @@ void /* PRIVATE */ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) { png_color palette[PNG_MAX_PALETTE_LENGTH]; - int num, i; + int max_palette_length, num, i; #ifdef PNG_POINTER_INDEXING_SUPPORTED png_colorp pal_ptr; #endif @@ -928,6 +933,19 @@ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) /* The cast is safe because 'length' is less than 3*PNG_MAX_PALETTE_LENGTH */ num = (int)length / 3; + /* If the palette has 256 or fewer entries but is too large for the bit + * depth, we don't issue an error, to preserve the behavior of previous + * libpng versions. We silently truncate the unused extra palette entries + * here. + */ + if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) + max_palette_length = (1 << png_ptr->bit_depth); + else + max_palette_length = PNG_MAX_PALETTE_LENGTH; + + if (num > max_palette_length) + num = max_palette_length; + #ifdef PNG_POINTER_INDEXING_SUPPORTED for (i = 0, pal_ptr = palette; i < num; i++, pal_ptr++) { @@ -960,7 +978,7 @@ png_handle_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) #endif { - png_crc_finish(png_ptr, 0); + png_crc_finish(png_ptr, (int) length - num * 3); } #ifndef PNG_READ_OPT_PLTE_SUPPORTED @@ -1147,11 +1165,13 @@ png_handle_sBIT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) return; for (i=0; i sample_depth) { png_chunk_benign_error(png_ptr, "invalid"); return; } + } if ((png_ptr->color_type & PNG_COLOR_MASK_COLOR) != 0) { @@ -1462,10 +1482,10 @@ png_handle_iCCP(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) finished = 1; # ifdef PNG_sRGB_SUPPORTED - /* Check for a match against sRGB */ - png_icc_set_sRGB(png_ptr, - &png_ptr->colorspace, profile, - png_ptr->zstream.adler); + /* Check for a match against sRGB */ + png_icc_set_sRGB(png_ptr, + &png_ptr->colorspace, profile, + png_ptr->zstream.adler); # endif /* Steal the profile for info_ptr. */ @@ -1675,8 +1695,8 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (dl > max_dl) { - png_warning(png_ptr, "sPLT chunk too long"); - return; + png_warning(png_ptr, "sPLT chunk too long"); + return; } new_palette.nentries = (png_int_32)(data_length / entry_size); @@ -1686,8 +1706,8 @@ png_handle_sPLT(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) if (new_palette.entries == NULL) { - png_warning(png_ptr, "sPLT chunk requires too much memory"); - return; + png_warning(png_ptr, "sPLT chunk requires too much memory"); + return; } #ifdef PNG_POINTER_INDEXING_SUPPORTED @@ -1817,7 +1837,8 @@ png_handle_tRNS(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) return; } - if (length > png_ptr->num_palette || length > PNG_MAX_PALETTE_LENGTH || + if (length > (unsigned int) png_ptr->num_palette || + length > (unsigned int) PNG_MAX_PALETTE_LENGTH || length == 0) { png_crc_finish(png_ptr, length); @@ -1980,7 +2001,8 @@ png_handle_hIST(png_structrp png_ptr, png_inforp info_ptr, png_uint_32 length) num = length / 2 ; - if (num != png_ptr->num_palette || num > PNG_MAX_PALETTE_LENGTH) + if (num != (unsigned int) png_ptr->num_palette || + num > (unsigned int) PNG_MAX_PALETTE_LENGTH) { png_crc_finish(png_ptr, length); png_chunk_benign_error(png_ptr, "invalid"); @@ -2715,14 +2737,14 @@ png_cache_unknown_chunk(png_structrp png_ptr, png_uint_32 length) png_ptr->unknown_chunk.data = NULL; } -# ifdef PNG_SET_CHUNK_MALLOC_LIMIT_SUPPORTED - if (png_ptr->user_chunk_malloc_max > 0 && - png_ptr->user_chunk_malloc_max < limit) - limit = png_ptr->user_chunk_malloc_max; +# ifdef PNG_SET_USER_LIMITS_SUPPORTED + if (png_ptr->user_chunk_malloc_max > 0 && + png_ptr->user_chunk_malloc_max < limit) + limit = png_ptr->user_chunk_malloc_max; # elif PNG_USER_CHUNK_MALLOC_MAX > 0 - if (PNG_USER_CHUNK_MALLOC_MAX < limit) - limit = PNG_USER_CHUNK_MALLOC_MAX; + if (PNG_USER_CHUNK_MALLOC_MAX < limit) + limit = PNG_USER_CHUNK_MALLOC_MAX; # endif if (length <= limit) @@ -2785,7 +2807,7 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, */ # ifndef PNG_HANDLE_AS_UNKNOWN_SUPPORTED # ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name); + keep = png_chunk_unknown_handling(png_ptr, png_ptr->chunk_name); # endif # endif @@ -2794,153 +2816,153 @@ png_handle_unknown(png_structrp png_ptr, png_inforp info_ptr, * PNG_READ_UNKNOWN_CHUNKS_SUPPORTED) */ # ifdef PNG_READ_USER_CHUNKS_SUPPORTED - /* The user callback takes precedence over the chunk keep value, but the - * keep value is still required to validate a save of a critical chunk. - */ - if (png_ptr->read_user_chunk_fn != NULL) + /* The user callback takes precedence over the chunk keep value, but the + * keep value is still required to validate a save of a critical chunk. + */ + if (png_ptr->read_user_chunk_fn != NULL) + { + if (png_cache_unknown_chunk(png_ptr, length) != 0) { - if (png_cache_unknown_chunk(png_ptr, length) != 0) + /* Callback to user unknown chunk handler */ + int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr, + &png_ptr->unknown_chunk); + + /* ret is: + * negative: An error occurred; png_chunk_error will be called. + * zero: The chunk was not handled, the chunk will be discarded + * unless png_set_keep_unknown_chunks has been used to set + * a 'keep' behavior for this particular chunk, in which + * case that will be used. A critical chunk will cause an + * error at this point unless it is to be saved. + * positive: The chunk was handled, libpng will ignore/discard it. + */ + if (ret < 0) + png_chunk_error(png_ptr, "error in user chunk"); + + else if (ret == 0) { - /* Callback to user unknown chunk handler */ - int ret = (*(png_ptr->read_user_chunk_fn))(png_ptr, - &png_ptr->unknown_chunk); - - /* ret is: - * negative: An error occurred; png_chunk_error will be called. - * zero: The chunk was not handled, the chunk will be discarded - * unless png_set_keep_unknown_chunks has been used to set - * a 'keep' behavior for this particular chunk, in which - * case that will be used. A critical chunk will cause an - * error at this point unless it is to be saved. - * positive: The chunk was handled, libpng will ignore/discard it. + /* If the keep value is 'default' or 'never' override it, but + * still error out on critical chunks unless the keep value is + * 'always' While this is weird it is the behavior in 1.4.12. + * A possible improvement would be to obey the value set for the + * chunk, but this would be an API change that would probably + * damage some applications. + * + * The png_app_warning below catches the case that matters, where + * the application has not set specific save or ignore for this + * chunk or global save or ignore. */ - if (ret < 0) - png_chunk_error(png_ptr, "error in user chunk"); - - else if (ret == 0) + if (keep < PNG_HANDLE_CHUNK_IF_SAFE) { - /* If the keep value is 'default' or 'never' override it, but - * still error out on critical chunks unless the keep value is - * 'always' While this is weird it is the behavior in 1.4.12. - * A possible improvement would be to obey the value set for the - * chunk, but this would be an API change that would probably - * damage some applications. - * - * The png_app_warning below catches the case that matters, where - * the application has not set specific save or ignore for this - * chunk or global save or ignore. - */ - if (keep < PNG_HANDLE_CHUNK_IF_SAFE) +# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED + if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE) { -# ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - if (png_ptr->unknown_default < PNG_HANDLE_CHUNK_IF_SAFE) - { - png_chunk_warning(png_ptr, "Saving unknown chunk:"); - png_app_warning(png_ptr, - "forcing save of an unhandled chunk;" - " please call png_set_keep_unknown_chunks"); - /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */ - } -# endif - keep = PNG_HANDLE_CHUNK_IF_SAFE; + png_chunk_warning(png_ptr, "Saving unknown chunk:"); + png_app_warning(png_ptr, + "forcing save of an unhandled chunk;" + " please call png_set_keep_unknown_chunks"); + /* with keep = PNG_HANDLE_CHUNK_IF_SAFE */ } - } - - else /* chunk was handled */ - { - handled = 1; - /* Critical chunks can be safely discarded at this point. */ - keep = PNG_HANDLE_CHUNK_NEVER; +# endif + keep = PNG_HANDLE_CHUNK_IF_SAFE; } } - else - keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */ + else /* chunk was handled */ + { + handled = 1; + /* Critical chunks can be safely discarded at this point. */ + keep = PNG_HANDLE_CHUNK_NEVER; + } } else - /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */ + keep = PNG_HANDLE_CHUNK_NEVER; /* insufficient memory */ + } + + else + /* Use the SAVE_UNKNOWN_CHUNKS code or skip the chunk */ # endif /* READ_USER_CHUNKS */ # ifdef PNG_SAVE_UNKNOWN_CHUNKS_SUPPORTED - { - /* keep is currently just the per-chunk setting, if there was no - * setting change it to the global default now (not that this may - * still be AS_DEFAULT) then obtain the cache of the chunk if required, - * if not simply skip the chunk. - */ - if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT) - keep = png_ptr->unknown_default; - - if (keep == PNG_HANDLE_CHUNK_ALWAYS || - (keep == PNG_HANDLE_CHUNK_IF_SAFE && - PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) - { - if (png_cache_unknown_chunk(png_ptr, length) == 0) - keep = PNG_HANDLE_CHUNK_NEVER; - } + { + /* keep is currently just the per-chunk setting, if there was no + * setting change it to the global default now (not that this may + * still be AS_DEFAULT) then obtain the cache of the chunk if required, + * if not simply skip the chunk. + */ + if (keep == PNG_HANDLE_CHUNK_AS_DEFAULT) + keep = png_ptr->unknown_default; - else - png_crc_finish(png_ptr, length); + if (keep == PNG_HANDLE_CHUNK_ALWAYS || + (keep == PNG_HANDLE_CHUNK_IF_SAFE && + PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) + { + if (png_cache_unknown_chunk(png_ptr, length) == 0) + keep = PNG_HANDLE_CHUNK_NEVER; } + + else + png_crc_finish(png_ptr, length); + } # else # ifndef PNG_READ_USER_CHUNKS_SUPPORTED # error no method to support READ_UNKNOWN_CHUNKS # endif - { - /* If here there is no read callback pointer set and no support is - * compiled in to just save the unknown chunks, so simply skip this - * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then - * the app has erroneously asked for unknown chunk saving when there - * is no support. - */ - if (keep > PNG_HANDLE_CHUNK_NEVER) - png_app_error(png_ptr, "no unknown chunk support available"); + { + /* If here there is no read callback pointer set and no support is + * compiled in to just save the unknown chunks, so simply skip this + * chunk. If 'keep' is something other than AS_DEFAULT or NEVER then + * the app has erroneously asked for unknown chunk saving when there + * is no support. + */ + if (keep > PNG_HANDLE_CHUNK_NEVER) + png_app_error(png_ptr, "no unknown chunk support available"); - png_crc_finish(png_ptr, length); - } + png_crc_finish(png_ptr, length); + } # endif # ifdef PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED - /* Now store the chunk in the chunk list if appropriate, and if the limits - * permit it. - */ - if (keep == PNG_HANDLE_CHUNK_ALWAYS || - (keep == PNG_HANDLE_CHUNK_IF_SAFE && - PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) - { -# ifdef PNG_USER_LIMITS_SUPPORTED - switch (png_ptr->user_chunk_cache_max) - { - case 2: - png_ptr->user_chunk_cache_max = 1; - png_chunk_benign_error(png_ptr, "no space in chunk cache"); - /* FALL THROUGH */ - case 1: - /* NOTE: prior to 1.6.0 this case resulted in an unknown critical - * chunk being skipped, now there will be a hard error below. - */ - break; - - default: /* not at limit */ - --(png_ptr->user_chunk_cache_max); - /* FALL THROUGH */ - case 0: /* no limit */ -# endif /* USER_LIMITS */ - /* Here when the limit isn't reached or when limits are compiled - * out; store the chunk. - */ - png_set_unknown_chunks(png_ptr, info_ptr, - &png_ptr->unknown_chunk, 1); - handled = 1; + /* Now store the chunk in the chunk list if appropriate, and if the limits + * permit it. + */ + if (keep == PNG_HANDLE_CHUNK_ALWAYS || + (keep == PNG_HANDLE_CHUNK_IF_SAFE && + PNG_CHUNK_ANCILLARY(png_ptr->chunk_name))) + { # ifdef PNG_USER_LIMITS_SUPPORTED - break; - } -# endif + switch (png_ptr->user_chunk_cache_max) + { + case 2: + png_ptr->user_chunk_cache_max = 1; + png_chunk_benign_error(png_ptr, "no space in chunk cache"); + /* FALL THROUGH */ + case 1: + /* NOTE: prior to 1.6.0 this case resulted in an unknown critical + * chunk being skipped, now there will be a hard error below. + */ + break; + + default: /* not at limit */ + --(png_ptr->user_chunk_cache_max); + /* FALL THROUGH */ + case 0: /* no limit */ +# endif /* USER_LIMITS */ + /* Here when the limit isn't reached or when limits are compiled + * out; store the chunk. + */ + png_set_unknown_chunks(png_ptr, info_ptr, + &png_ptr->unknown_chunk, 1); + handled = 1; +# ifdef PNG_USER_LIMITS_SUPPORTED + break; } +# endif + } # else /* no store support: the chunk must be handled by the user callback */ - PNG_UNUSED(info_ptr) + PNG_UNUSED(info_ptr) # endif /* Regardless of the error handling below the cached data (if any) can be @@ -3042,13 +3064,13 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) end_ptr = dp + PNG_ROWBYTES(pixel_depth, row_width) - 1; end_byte = *end_ptr; # ifdef PNG_READ_PACKSWAP_SUPPORTED - if ((png_ptr->transformations & PNG_PACKSWAP) != 0) - /* little-endian byte */ - end_mask = 0xff << end_mask; + if ((png_ptr->transformations & PNG_PACKSWAP) != 0) + /* little-endian byte */ + end_mask = 0xff << end_mask; - else /* big-endian byte */ + else /* big-endian byte */ # endif - end_mask = 0xff >> end_mask; + end_mask = 0xff >> end_mask; /* end_mask is now the bits to *keep* from the destination row */ } @@ -3206,12 +3228,12 @@ png_combine_row(png_const_structrp png_ptr, png_bytep dp, int display) png_uint_32 mask; # ifdef PNG_READ_PACKSWAP_SUPPORTED - if ((png_ptr->transformations & PNG_PACKSWAP) != 0) - mask = MASK(pass, pixel_depth, display, 0); + if ((png_ptr->transformations & PNG_PACKSWAP) != 0) + mask = MASK(pass, pixel_depth, display, 0); - else + else # endif - mask = MASK(pass, pixel_depth, display, 1); + mask = MASK(pass, pixel_depth, display, 1); for (;;) { @@ -3812,15 +3834,15 @@ png_read_filter_row_paeth_1byte_pixel(png_row_infop row_info, png_bytep row, p = b - c; pc = a - c; -# ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -# else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -# endif +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif /* Find the best predictor, the least of pa, pb, pc favoring the earlier * ones in the case of a tie. @@ -3867,15 +3889,15 @@ png_read_filter_row_paeth_multibyte_pixel(png_row_infop row_info, png_bytep row, p = b - c; pc = a - c; -# ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -# else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -# endif +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif if (pb < pa) pa = pb, a = b; if (pc < pa) a = c; @@ -4280,18 +4302,18 @@ png_read_start_row(png_structrp png_ptr) #ifdef PNG_READ_EXPAND_16_SUPPORTED if ((png_ptr->transformations & PNG_EXPAND_16) != 0) { -# ifdef PNG_READ_EXPAND_SUPPORTED - /* In fact it is an error if it isn't supported, but checking is - * the safe way. - */ - if ((png_ptr->transformations & PNG_EXPAND) != 0) - { - if (png_ptr->bit_depth < 16) - max_pixel_depth *= 2; - } - else -# endif - png_ptr->transformations &= ~PNG_EXPAND_16; +# ifdef PNG_READ_EXPAND_SUPPORTED + /* In fact it is an error if it isn't supported, but checking is + * the safe way. + */ + if ((png_ptr->transformations & PNG_EXPAND) != 0) + { + if (png_ptr->bit_depth < 16) + max_pixel_depth *= 2; + } + else +# endif + png_ptr->transformations &= ~PNG_EXPAND_16; } #endif diff --git a/src/3rdparty/libpng/pngset.c b/src/3rdparty/libpng/pngset.c index fce3039168..05a2134dbb 100644 --- a/src/3rdparty/libpng/pngset.c +++ b/src/3rdparty/libpng/pngset.c @@ -1,7 +1,7 @@ /* pngset.c - storage of image information into info struct * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -123,12 +123,12 @@ png_set_cHRM_XYZ(png_const_structrp png_ptr, png_inforp info_ptr, double red_X, png_fixed(png_ptr, red_X, "cHRM Red X"), png_fixed(png_ptr, red_Y, "cHRM Red Y"), png_fixed(png_ptr, red_Z, "cHRM Red Z"), - png_fixed(png_ptr, green_X, "cHRM Red X"), - png_fixed(png_ptr, green_Y, "cHRM Red Y"), - png_fixed(png_ptr, green_Z, "cHRM Red Z"), - png_fixed(png_ptr, blue_X, "cHRM Red X"), - png_fixed(png_ptr, blue_Y, "cHRM Red Y"), - png_fixed(png_ptr, blue_Z, "cHRM Red Z")); + png_fixed(png_ptr, green_X, "cHRM Green X"), + png_fixed(png_ptr, green_Y, "cHRM Green Y"), + png_fixed(png_ptr, green_Z, "cHRM Green Z"), + png_fixed(png_ptr, blue_X, "cHRM Blue X"), + png_fixed(png_ptr, blue_Y, "cHRM Blue Y"), + png_fixed(png_ptr, blue_Z, "cHRM Blue Z")); } # endif /* FLOATING_POINT */ @@ -513,12 +513,17 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_const_colorp palette, int num_palette) { + png_uint_32 max_palette_length; + png_debug1(1, "in %s storage function", "PLTE"); if (png_ptr == NULL || info_ptr == NULL) return; - if (num_palette < 0 || num_palette > PNG_MAX_PALETTE_LENGTH) + max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? + (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; + + if (num_palette < 0 || num_palette > (int) max_palette_length) { if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) png_error(png_ptr, "Invalid palette length"); @@ -551,8 +556,8 @@ png_set_PLTE(png_structrp png_ptr, png_inforp info_ptr, png_free_data(png_ptr, info_ptr, PNG_FREE_PLTE, 0); /* Changed in libpng-1.2.1 to allocate PNG_MAX_PALETTE_LENGTH instead - * of num_palette entries, in case of an invalid PNG file that has - * too-large sample values. + * of num_palette entries, in case of an invalid PNG file or incorrect + * call to png_set_PLTE() with too-large sample values. */ png_ptr->palette = png_voidcast(png_colorp, png_calloc(png_ptr, PNG_MAX_PALETTE_LENGTH * (sizeof (png_color)))); @@ -673,7 +678,6 @@ png_set_iCCP(png_const_structrp png_ptr, png_inforp info_ptr, if (new_iccp_profile == NULL) { png_free(png_ptr, new_iccp_name); - new_iccp_name = NULL; png_benign_error(png_ptr, "Insufficient memory to process iCCP profile"); @@ -710,7 +714,7 @@ png_set_text_2(png_const_structrp png_ptr, png_inforp info_ptr, { int i; - png_debug1(1, "in %lx storage function", png_ptr == NULL ? "unexpected" : + png_debug1(1, "in %lx storage function", png_ptr == NULL ? 0xabadca11U : (unsigned long)png_ptr->chunk_name); if (png_ptr == NULL || info_ptr == NULL || num_text <= 0 || text_ptr == NULL) @@ -1522,6 +1526,9 @@ png_set_compression_buffer_size(png_structrp png_ptr, png_size_t size) } #ifndef __COVERITY__ + /* Some compilers complain that this is always false. However, it + * can be true when integer overflow happens. + */ if (size > ZLIB_IO_MAX) { png_warning(png_ptr, @@ -1566,7 +1573,7 @@ png_set_user_limits (png_structrp png_ptr, png_uint_32 user_width_max, { /* Images with dimensions larger than these limits will be * rejected by png_set_IHDR(). To accept any PNG datastream - * regardless of dimensions, set both limits to 0x7ffffffL. + * regardless of dimensions, set both limits to 0x7ffffff. */ if (png_ptr == NULL) return; diff --git a/src/3rdparty/libpng/pngstruct.h b/src/3rdparty/libpng/pngstruct.h index 8420d09972..c8c0e46e8b 100644 --- a/src/3rdparty/libpng/pngstruct.h +++ b/src/3rdparty/libpng/pngstruct.h @@ -1,8 +1,8 @@ /* pngstruct.h - header file for PNG reference library * - * Last changed in libpng 1.6.1 [March 28, 2013] - * Copyright (c) 1998-2013 Glenn Randers-Pehrson + * Last changed in libpng 1.6.18 [July 23, 2015] + * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) * @@ -219,16 +219,18 @@ struct png_struct_def png_uint_32 row_number; /* current row in interlace pass */ png_uint_32 chunk_name; /* PNG_CHUNK() id of current chunk */ png_bytep prev_row; /* buffer to save previous (unfiltered) row. - * This is a pointer into big_prev_row + * While reading this is a pointer into + * big_prev_row; while writing it is separately + * allocated if needed. */ png_bytep row_buf; /* buffer to save current (unfiltered) row. - * This is a pointer into big_row_buf + * While reading, this is a pointer into + * big_row_buf; while writing it is separately + * allocated. */ -#ifdef PNG_WRITE_SUPPORTED - png_bytep sub_row; /* buffer to save "sub" row when filtering */ - png_bytep up_row; /* buffer to save "up" row when filtering */ - png_bytep avg_row; /* buffer to save "avg" row when filtering */ - png_bytep paeth_row; /* buffer to save "Paeth" row when filtering */ +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_bytep try_row; /* buffer to save trial row when filtering */ + png_bytep tst_row; /* buffer to save best trial row when filtering */ #endif png_size_t info_rowbytes; /* Added in 1.5.4: cache of updated row bytes */ @@ -346,17 +348,7 @@ struct png_struct_def png_bytep quantize_index; /* index translation for palette files */ #endif -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - png_byte heuristic_method; /* heuristic for row filter selection */ - png_byte num_prev_filters; /* number of weights for previous rows */ - png_bytep prev_filters; /* filter type(s) of previous row(s) */ - png_uint_16p filter_weights; /* weight(s) for previous line(s) */ - png_uint_16p inv_filter_weights; /* 1/weight(s) for previous line(s) */ - png_uint_16p filter_costs; /* relative filter calculation cost */ - png_uint_16p inv_filter_costs; /* 1/relative filter calculation cost */ -#endif - - /* Options */ +/* Options */ #ifdef PNG_SET_OPTION_SUPPORTED png_byte options; /* On/off state (up to 4 options) */ #endif diff --git a/src/3rdparty/libpng/pngtrans.c b/src/3rdparty/libpng/pngtrans.c index cd3a79b6fa..0c0d92d8fd 100644 --- a/src/3rdparty/libpng/pngtrans.c +++ b/src/3rdparty/libpng/pngtrans.c @@ -1,7 +1,7 @@ /* pngtrans.c - transforms the data in a row (used by both readers and writers) * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.18 [July 23, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -30,7 +30,7 @@ png_set_bgr(png_structrp png_ptr) #endif #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Turn on 16 bit byte swapping */ +/* Turn on 16-bit byte swapping */ void PNGAPI png_set_swap(png_structrp png_ptr) { @@ -313,7 +313,7 @@ png_do_invert(png_row_infop row_info, png_bytep row) #ifdef PNG_16BIT_SUPPORTED #if defined(PNG_READ_SWAP_SUPPORTED) || defined(PNG_WRITE_SWAP_SUPPORTED) -/* Swaps byte order on 16 bit depth images */ +/* Swaps byte order on 16-bit depth images */ void /* PRIVATE */ png_do_swap(png_row_infop row_info, png_bytep row) { @@ -704,7 +704,7 @@ png_do_check_palette_indexes(png_structrp png_ptr, png_row_infop row_info) */ for (; rp > png_ptr->row_buf; rp--) { - if (*rp >> padding != 0) + if ((*rp >> padding) != 0) png_ptr->num_palette_max = 1; padding = 0; } diff --git a/src/3rdparty/libpng/pngwio.c b/src/3rdparty/libpng/pngwio.c index 0a40948aab..db76e6b8d7 100644 --- a/src/3rdparty/libpng/pngwio.c +++ b/src/3rdparty/libpng/pngwio.c @@ -26,7 +26,7 @@ * writes to a file pointer. Note that this routine sometimes gets called * with very small lengths, so you should implement some kind of simple * buffering if you are using unbuffered writes. This should never be asked - * to write more than 64K on a 16 bit machine. + * to write more than 64K on a 16-bit machine. */ void /* PRIVATE */ diff --git a/src/3rdparty/libpng/pngwrite.c b/src/3rdparty/libpng/pngwrite.c index e3c203496e..0d4ee9f7ae 100644 --- a/src/3rdparty/libpng/pngwrite.c +++ b/src/3rdparty/libpng/pngwrite.c @@ -1,7 +1,7 @@ /* pngwrite.c - general routines to write a PNG file * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -90,43 +90,44 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) if ((png_ptr->mode & PNG_WROTE_INFO_BEFORE_PLTE) == 0) { - /* Write PNG signature */ - png_write_sig(png_ptr); + /* Write PNG signature */ + png_write_sig(png_ptr); #ifdef PNG_MNG_FEATURES_SUPPORTED - if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \ - png_ptr->mng_features_permitted != 0) - { - png_warning(png_ptr, "MNG features are not allowed in a PNG datastream"); - png_ptr->mng_features_permitted = 0; - } + if ((png_ptr->mode & PNG_HAVE_PNG_SIGNATURE) != 0 && \ + png_ptr->mng_features_permitted != 0) + { + png_warning(png_ptr, + "MNG features are not allowed in a PNG datastream"); + png_ptr->mng_features_permitted = 0; + } #endif - /* Write IHDR information. */ - png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, - info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, - info_ptr->filter_type, + /* Write IHDR information. */ + png_write_IHDR(png_ptr, info_ptr->width, info_ptr->height, + info_ptr->bit_depth, info_ptr->color_type, info_ptr->compression_type, + info_ptr->filter_type, #ifdef PNG_WRITE_INTERLACING_SUPPORTED - info_ptr->interlace_type + info_ptr->interlace_type #else - 0 + 0 #endif - ); + ); - /* The rest of these check to see if the valid field has the appropriate - * flag set, and if it does, writes the chunk. - * - * 1.6.0: COLORSPACE support controls the writing of these chunks too, and - * the chunks will be written if the WRITE routine is there and information - * is available in the COLORSPACE. (See png_colorspace_sync_info in png.c - * for where the valid flags get set.) - * - * Under certain circumstances the colorspace can be invalidated without - * syncing the info_struct 'valid' flags; this happens if libpng detects and - * error and calls png_error while the color space is being set, yet the - * application continues writing the PNG. So check the 'invalid' flag here - * too. - */ + /* The rest of these check to see if the valid field has the appropriate + * flag set, and if it does, writes the chunk. + * + * 1.6.0: COLORSPACE support controls the writing of these chunks too, and + * the chunks will be written if the WRITE routine is there and + * information * is available in the COLORSPACE. (See + * png_colorspace_sync_info in png.c for where the valid flags get set.) + * + * Under certain circumstances the colorspace can be invalidated without + * syncing the info_struct 'valid' flags; this happens if libpng detects + * an error and calls png_error while the color space is being set, yet + * the application continues writing the PNG. So check the 'invalid' + * flag here too. + */ #ifdef PNG_GAMMA_SUPPORTED # ifdef PNG_WRITE_gAMA_SUPPORTED if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && @@ -137,50 +138,50 @@ png_write_info_before_PLTE(png_structrp png_ptr, png_const_inforp info_ptr) #endif #ifdef PNG_COLORSPACE_SUPPORTED - /* Write only one of sRGB or an ICC profile. If a profile was supplied - * and it matches one of the known sRGB ones issue a warning. - */ + /* Write only one of sRGB or an ICC profile. If a profile was supplied + * and it matches one of the known sRGB ones issue a warning. + */ # ifdef PNG_WRITE_iCCP_SUPPORTED - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && - (info_ptr->valid & PNG_INFO_iCCP) != 0) - { -# ifdef PNG_WRITE_sRGB_SUPPORTED - if ((info_ptr->valid & PNG_INFO_sRGB) != 0) - png_app_warning(png_ptr, - "profile matches sRGB but writing iCCP instead"); -# endif - - png_write_iCCP(png_ptr, info_ptr->iccp_name, - info_ptr->iccp_profile); - } + if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && + (info_ptr->valid & PNG_INFO_iCCP) != 0) + { +# ifdef PNG_WRITE_sRGB_SUPPORTED + if ((info_ptr->valid & PNG_INFO_sRGB) != 0) + png_app_warning(png_ptr, + "profile matches sRGB but writing iCCP instead"); +# endif + + png_write_iCCP(png_ptr, info_ptr->iccp_name, + info_ptr->iccp_profile); + } # ifdef PNG_WRITE_sRGB_SUPPORTED else # endif # endif # ifdef PNG_WRITE_sRGB_SUPPORTED - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && - (info_ptr->valid & PNG_INFO_sRGB) != 0) - png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); + if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && + (info_ptr->valid & PNG_INFO_sRGB) != 0) + png_write_sRGB(png_ptr, info_ptr->colorspace.rendering_intent); # endif /* WRITE_sRGB */ #endif /* COLORSPACE */ #ifdef PNG_WRITE_sBIT_SUPPORTED - if ((info_ptr->valid & PNG_INFO_sBIT) != 0) - png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); + if ((info_ptr->valid & PNG_INFO_sBIT) != 0) + png_write_sBIT(png_ptr, &(info_ptr->sig_bit), info_ptr->color_type); #endif #ifdef PNG_COLORSPACE_SUPPORTED # ifdef PNG_WRITE_cHRM_SUPPORTED - if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && - (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 && - (info_ptr->valid & PNG_INFO_cHRM) != 0) - png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy); + if ((info_ptr->colorspace.flags & PNG_COLORSPACE_INVALID) == 0 && + (info_ptr->colorspace.flags & PNG_COLORSPACE_FROM_cHRM) != 0 && + (info_ptr->valid & PNG_INFO_cHRM) != 0) + png_write_cHRM_fixed(png_ptr, &info_ptr->colorspace.end_points_xy); # endif #endif #ifdef PNG_WRITE_UNKNOWN_CHUNKS_SUPPORTED - write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); + write_unknown_chunks(png_ptr, info_ptr, PNG_HAVE_IHDR); #endif png_ptr->mode |= PNG_WROTE_INFO_BEFORE_PLTE; @@ -205,7 +206,7 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) png_write_PLTE(png_ptr, info_ptr->palette, (png_uint_32)info_ptr->num_palette); - else if ((info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) !=0) + else if (info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) png_error(png_ptr, "Valid palette required for paletted images"); #ifdef PNG_WRITE_tRNS_SUPPORTED @@ -216,8 +217,13 @@ png_write_info(png_structrp png_ptr, png_const_inforp info_ptr) if ((png_ptr->transformations & PNG_INVERT_ALPHA) != 0 && info_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { - int j; - for (j = 0; j<(int)info_ptr->num_trans; j++) + int j, jend; + + jend = info_ptr->num_trans; + if (jend > PNG_MAX_PALETTE_LENGTH) + jend = PNG_MAX_PALETTE_LENGTH; + + for (j = 0; jtrans_alpha[j] = (png_byte)(255 - info_ptr->trans_alpha[j]); } @@ -538,7 +544,7 @@ png_create_write_struct_2,(png_const_charp user_png_ver, png_voidp error_ptr, /* App warnings are warnings in release (or release candidate) builds but * are errors during development. */ -#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC +#if PNG_RELEASE_BUILD png_ptr->flags |= PNG_FLAG_APP_WARNINGS_WARN; #endif @@ -849,7 +855,7 @@ png_write_row(png_structrp png_ptr, png_const_bytep row) * which is also the output depth. */ if (row_info.pixel_depth != png_ptr->pixel_depth || - row_info.pixel_depth != png_ptr->transformed_pixel_depth) + row_info.pixel_depth != png_ptr->transformed_pixel_depth) png_error(png_ptr, "internal write transform logic error"); #ifdef PNG_MNG_FEATURES_SUPPORTED @@ -917,10 +923,6 @@ png_write_flush(png_structrp png_ptr) } #endif /* WRITE_FLUSH */ -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED -static void png_reset_filter_heuristics(png_structrp png_ptr);/* forward decl */ -#endif - /* Free any memory used in png_ptr struct without freeing the struct itself. */ static void png_write_destroy(png_structrp png_ptr) @@ -937,24 +939,11 @@ png_write_destroy(png_structrp png_ptr) png_ptr->row_buf = NULL; #ifdef PNG_WRITE_FILTER_SUPPORTED png_free(png_ptr, png_ptr->prev_row); - png_free(png_ptr, png_ptr->sub_row); - png_free(png_ptr, png_ptr->up_row); - png_free(png_ptr, png_ptr->avg_row); - png_free(png_ptr, png_ptr->paeth_row); + png_free(png_ptr, png_ptr->try_row); + png_free(png_ptr, png_ptr->tst_row); png_ptr->prev_row = NULL; - png_ptr->sub_row = NULL; - png_ptr->up_row = NULL; - png_ptr->avg_row = NULL; - png_ptr->paeth_row = NULL; -#endif - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - /* Use this to save a little code space, it doesn't free the filter_costs */ - png_reset_filter_heuristics(png_ptr); - png_free(png_ptr, png_ptr->filter_costs); - png_free(png_ptr, png_ptr->inv_filter_costs); - png_ptr->filter_costs = NULL; - png_ptr->inv_filter_costs = NULL; + png_ptr->try_row = NULL; + png_ptr->tst_row = NULL; #endif #ifdef PNG_SET_UNKNOWN_CHUNKS_SUPPORTED @@ -1044,6 +1033,7 @@ png_set_filter(png_structrp png_ptr, int method, int filters) #endif /* WRITE_FILTER */ } +#ifdef PNG_WRITE_FILTER_SUPPORTED /* If we have allocated the row_buf, this means we have already started * with the image and we should have allocated all of the filter buffers * that have been selected. If prev_row isn't already allocated, then @@ -1052,203 +1042,76 @@ png_set_filter(png_structrp png_ptr, int method, int filters) * wants to start and stop using particular filters during compression, * it should start out with all of the filters, and then remove them * or add them back after the start of compression. + * + * NOTE: this is a nasty constraint on the code, because it means that the + * prev_row buffer must be maintained even if there are currently no + * 'prev_row' requiring filters active. */ if (png_ptr->row_buf != NULL) { -#ifdef PNG_WRITE_FILTER_SUPPORTED - if ((png_ptr->do_filter & PNG_FILTER_SUB) != 0 && - png_ptr->sub_row == NULL) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } + int num_filters; + png_alloc_size_t buf_size; - if ((png_ptr->do_filter & PNG_FILTER_UP) != 0 && - png_ptr->up_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Up filter after starting"); - png_ptr->do_filter = (png_byte)(png_ptr->do_filter & - ~PNG_FILTER_UP); - } + /* Repeat the checks in png_write_start_row; 1 pixel high or wide + * images cannot benefit from certain filters. If this isn't done here + * the check below will fire on 1 pixel high images. + */ + if (png_ptr->height == 1) + filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); - else - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } - } + if (png_ptr->width == 1) + filters &= ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); - if ((png_ptr->do_filter & PNG_FILTER_AVG) != 0 && - png_ptr->avg_row == NULL) + if ((filters & (PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH)) != 0 + && png_ptr->prev_row == NULL) { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Average filter after starting"); - png_ptr->do_filter = (png_byte)(png_ptr->do_filter & - ~PNG_FILTER_AVG); - } - - else - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } + /* This is the error case, however it is benign - the previous row + * is not available so the filter can't be used. Just warn here. + */ + png_app_warning(png_ptr, + "png_set_filter: UP/AVG/PAETH cannot be added after start"); + filters &= ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); } - if ((png_ptr->do_filter & PNG_FILTER_PAETH) != 0 && - png_ptr->paeth_row == NULL) - { - if (png_ptr->prev_row == NULL) - { - png_warning(png_ptr, "Can't add Paeth filter after starting"); - png_ptr->do_filter &= (png_byte)(~PNG_FILTER_PAETH); - } + num_filters = 0; - else - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - (png_ptr->rowbytes + 1)); - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } - } + if (filters & PNG_FILTER_SUB) + num_filters++; - if (png_ptr->do_filter == PNG_NO_FILTERS) -#endif /* WRITE_FILTER */ - png_ptr->do_filter = PNG_FILTER_NONE; - } - } - else - png_error(png_ptr, "Unknown custom filter method"); -} + if (filters & PNG_FILTER_UP) + num_filters++; -/* This allows us to influence the way in which libpng chooses the "best" - * filter for the current scanline. While the "minimum-sum-of-absolute- - * differences metric is relatively fast and effective, there is some - * question as to whether it can be improved upon by trying to keep the - * filtered data going to zlib more consistent, hopefully resulting in - * better compression. - */ -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* GRR 970116 */ -/* Convenience reset API. */ -static void -png_reset_filter_heuristics(png_structrp png_ptr) -{ - /* Clear out any old values in the 'weights' - this must be done because if - * the app calls set_filter_heuristics multiple times with different - * 'num_weights' values we would otherwise potentially have wrong sized - * arrays. - */ - png_ptr->num_prev_filters = 0; - png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_UNWEIGHTED; - if (png_ptr->prev_filters != NULL) - { - png_bytep old = png_ptr->prev_filters; - png_ptr->prev_filters = NULL; - png_free(png_ptr, old); - } - if (png_ptr->filter_weights != NULL) - { - png_uint_16p old = png_ptr->filter_weights; - png_ptr->filter_weights = NULL; - png_free(png_ptr, old); - } - - if (png_ptr->inv_filter_weights != NULL) - { - png_uint_16p old = png_ptr->inv_filter_weights; - png_ptr->inv_filter_weights = NULL; - png_free(png_ptr, old); - } - - /* Leave the filter_costs - this array is fixed size. */ -} - -static int -png_init_filter_heuristics(png_structrp png_ptr, int heuristic_method, - int num_weights) -{ - if (png_ptr == NULL) - return 0; + if (filters & PNG_FILTER_AVG) + num_filters++; - /* Clear out the arrays */ - png_reset_filter_heuristics(png_ptr); + if (filters & PNG_FILTER_PAETH) + num_filters++; - /* Check arguments; the 'reset' function makes the correct settings for the - * unweighted case, but we must handle the weight case by initializing the - * arrays for the caller. - */ - if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int i; - - if (num_weights > 0) - { - png_ptr->prev_filters = (png_bytep)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_byte)) * num_weights)); - - /* To make sure that the weighting starts out fairly */ - for (i = 0; i < num_weights; i++) - { - png_ptr->prev_filters[i] = 255; - } - - png_ptr->filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_uint_16)) * num_weights)); + /* Allocate needed row buffers if they have not already been + * allocated. + */ + buf_size = PNG_ROWBYTES(png_ptr->usr_channels * png_ptr->usr_bit_depth, + png_ptr->width) + 1; - png_ptr->inv_filter_weights = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_uint_16)) * num_weights)); + if (png_ptr->try_row == NULL) + png_ptr->try_row = png_voidcast(png_bytep, + png_malloc(png_ptr, buf_size)); - for (i = 0; i < num_weights; i++) + if (num_filters > 1) { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; + if (png_ptr->tst_row == NULL) + png_ptr->tst_row = png_voidcast(png_bytep, + png_malloc(png_ptr, buf_size)); } - - /* Safe to set this now */ - png_ptr->num_prev_filters = (png_byte)num_weights; } - - /* If, in the future, there are other filter methods, this would - * need to be based on png_ptr->filter. - */ - if (png_ptr->filter_costs == NULL) - { - png_ptr->filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST)); - - png_ptr->inv_filter_costs = (png_uint_16p)png_malloc(png_ptr, - (png_uint_32)((sizeof (png_uint_16)) * PNG_FILTER_VALUE_LAST)); - } - - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) - { - png_ptr->inv_filter_costs[i] = - png_ptr->filter_costs[i] = PNG_COST_FACTOR; - } - - /* All the arrays are inited, safe to set this: */ - png_ptr->heuristic_method = PNG_FILTER_HEURISTIC_WEIGHTED; - - /* Return the 'ok' code. */ - return 1; - } - else if (heuristic_method == PNG_FILTER_HEURISTIC_DEFAULT || - heuristic_method == PNG_FILTER_HEURISTIC_UNWEIGHTED) - { - return 1; + png_ptr->do_filter = (png_byte)filters; +#endif } else - { - png_warning(png_ptr, "Unknown filter heuristic method"); - return 0; - } + png_error(png_ptr, "Unknown custom filter method"); } +#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED /* DEPRECATED */ /* Provide floating and fixed point APIs */ #ifdef PNG_FLOATING_POINT_SUPPORTED void PNGAPI @@ -1256,52 +1119,11 @@ png_set_filter_heuristics(png_structrp png_ptr, int heuristic_method, int num_weights, png_const_doublep filter_weights, png_const_doublep filter_costs) { - png_debug(1, "in png_set_filter_heuristics"); - - /* The internal API allocates all the arrays and ensures that the elements of - * those arrays are set to the default value. - */ - if (png_init_filter_heuristics(png_ptr, heuristic_method, num_weights) == 0) - return; - - /* If using the weighted method copy in the weights. */ - if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int i; - for (i = 0; i < num_weights; i++) - { - if (filter_weights[i] <= 0.0) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - - else - { - png_ptr->inv_filter_weights[i] = - (png_uint_16)(PNG_WEIGHT_FACTOR*filter_weights[i]+.5); - - png_ptr->filter_weights[i] = - (png_uint_16)(PNG_WEIGHT_FACTOR/filter_weights[i]+.5); - } - } - - /* Here is where we set the relative costs of the different filters. We - * should take the desired compression level into account when setting - * the costs, so that Paeth, for instance, has a high relative cost at low - * compression levels, while it has a lower relative cost at higher - * compression settings. The filter types are in order of increasing - * relative cost, so it would be possible to do this with an algorithm. - */ - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) if (filter_costs[i] >= 1.0) - { - png_ptr->inv_filter_costs[i] = - (png_uint_16)(PNG_COST_FACTOR / filter_costs[i] + .5); - - png_ptr->filter_costs[i] = - (png_uint_16)(PNG_COST_FACTOR * filter_costs[i] + .5); - } - } + PNG_UNUSED(png_ptr) + PNG_UNUSED(heuristic_method) + PNG_UNUSED(num_weights) + PNG_UNUSED(filter_weights) + PNG_UNUSED(filter_costs) } #endif /* FLOATING_POINT */ @@ -1311,63 +1133,11 @@ png_set_filter_heuristics_fixed(png_structrp png_ptr, int heuristic_method, int num_weights, png_const_fixed_point_p filter_weights, png_const_fixed_point_p filter_costs) { - png_debug(1, "in png_set_filter_heuristics_fixed"); - - /* The internal API allocates all the arrays and ensures that the elements of - * those arrays are set to the default value. - */ - if (png_init_filter_heuristics(png_ptr, heuristic_method, num_weights) == 0) - return; - - /* If using the weighted method copy in the weights. */ - if (heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int i; - for (i = 0; i < num_weights; i++) - { - if (filter_weights[i] <= 0) - { - png_ptr->inv_filter_weights[i] = - png_ptr->filter_weights[i] = PNG_WEIGHT_FACTOR; - } - - else - { - png_ptr->inv_filter_weights[i] = (png_uint_16) - ((PNG_WEIGHT_FACTOR*filter_weights[i]+PNG_FP_HALF)/PNG_FP_1); - - png_ptr->filter_weights[i] = (png_uint_16)((PNG_WEIGHT_FACTOR* - PNG_FP_1+(filter_weights[i]/2))/filter_weights[i]); - } - } - - /* Here is where we set the relative costs of the different filters. We - * should take the desired compression level into account when setting - * the costs, so that Paeth, for instance, has a high relative cost at low - * compression levels, while it has a lower relative cost at higher - * compression settings. The filter types are in order of increasing - * relative cost, so it would be possible to do this with an algorithm. - */ - for (i = 0; i < PNG_FILTER_VALUE_LAST; i++) - if (filter_costs[i] >= PNG_FP_1) - { - png_uint_32 tmp; - - /* Use a 32 bit unsigned temporary here because otherwise the - * intermediate value will be a 32 bit *signed* integer (ANSI rules) - * and this will get the wrong answer on division. - */ - tmp = PNG_COST_FACTOR*PNG_FP_1 + (filter_costs[i]/2); - tmp /= filter_costs[i]; - - png_ptr->inv_filter_costs[i] = (png_uint_16)tmp; - - tmp = PNG_COST_FACTOR * filter_costs[i] + PNG_FP_HALF; - tmp /= PNG_FP_1; - - png_ptr->filter_costs[i] = (png_uint_16)tmp; - } - } + PNG_UNUSED(png_ptr) + PNG_UNUSED(heuristic_method) + PNG_UNUSED(num_weights) + PNG_UNUSED(filter_weights) + PNG_UNUSED(filter_costs) } #endif /* FIXED_POINT */ #endif /* WRITE_WEIGHTED_FILTER */ @@ -1616,14 +1386,14 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr, * alpha channel. */ if ((transforms & (PNG_TRANSFORM_STRIP_FILLER_AFTER| - PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0) + PNG_TRANSFORM_STRIP_FILLER_BEFORE)) != 0) { #ifdef PNG_WRITE_FILLER_SUPPORTED if ((transforms & PNG_TRANSFORM_STRIP_FILLER_AFTER) != 0) { if ((transforms & PNG_TRANSFORM_STRIP_FILLER_BEFORE) != 0) png_app_error(png_ptr, - "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported"); + "PNG_TRANSFORM_STRIP_FILLER: BEFORE+AFTER not supported"); /* Continue if ignored - this is the pre-1.6.10 behavior */ png_set_filler(png_ptr, 0, PNG_FILLER_AFTER); @@ -1652,7 +1422,7 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr, png_app_error(png_ptr, "PNG_TRANSFORM_SWAP_ENDIAN not supported"); #endif - /* Swap bits of 1, 2, 4 bit packed pixel formats */ + /* Swap bits of 1-bit, 2-bit, 4-bit packed pixel formats */ if ((transforms & PNG_TRANSFORM_PACKSWAP) != 0) #ifdef PNG_WRITE_PACKSWAP_SUPPORTED png_set_packswap(png_ptr); @@ -1682,13 +1452,13 @@ png_write_png(png_structrp png_ptr, png_inforp info_ptr, #ifdef PNG_SIMPLIFIED_WRITE_SUPPORTED -#ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */ +# ifdef PNG_STDIO_SUPPORTED /* currently required for png_image_write_* */ /* Initialize the write structure - general purpose utility. */ static int png_image_write_init(png_imagep image) { png_structp png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, image, - png_safe_error, png_safe_warning); + png_safe_error, png_safe_warning); if (png_ptr != NULL) { @@ -1697,7 +1467,7 @@ png_image_write_init(png_imagep image) if (info_ptr != NULL) { png_controlp control = png_voidcast(png_controlp, - png_malloc_warn(png_ptr, (sizeof *control))); + png_malloc_warn(png_ptr, (sizeof *control))); if (control != NULL) { @@ -1744,12 +1514,12 @@ static int png_write_image_16bit(png_voidp argument) { png_image_write_control *display = png_voidcast(png_image_write_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, - display->first_row); + display->first_row); png_uint_16p output_row = png_voidcast(png_uint_16p, display->local_row); png_uint_16p row_end; const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; @@ -1758,17 +1528,18 @@ png_write_image_16bit(png_voidp argument) if ((image->format & PNG_FORMAT_FLAG_ALPHA) != 0) { -# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED - if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) - { - aindex = -1; - ++input_row; /* To point to the first component */ - ++output_row; - } - +# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED + if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) + { + aindex = -1; + ++input_row; /* To point to the first component */ + ++output_row; + } else -# endif + aindex = channels; +# else aindex = channels; +# endif } else @@ -1850,7 +1621,7 @@ png_write_image_16bit(png_voidp argument) * calculation can be done to 15 bits of accuracy; however, the output needs to * be scaled in the range 0..255*65535, so include that scaling here. */ -#define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) +# define UNP_RECIPROCAL(alpha) ((((0xffff*0xff)<<7)+(alpha>>1))/alpha) static png_byte png_unpremultiply(png_uint_32 component, png_uint_32 alpha, @@ -1901,12 +1672,12 @@ static int png_write_image_8bit(png_voidp argument) { png_image_write_control *display = png_voidcast(png_image_write_control*, - argument); + argument); png_imagep image = display->image; png_structrp png_ptr = image->opaque->png_ptr; png_const_uint_16p input_row = png_voidcast(png_const_uint_16p, - display->first_row); + display->first_row); png_bytep output_row = png_voidcast(png_bytep, display->local_row); png_uint_32 y = image->height; const int channels = (image->format & PNG_FORMAT_FLAG_COLOR) != 0 ? 3 : 1; @@ -1916,17 +1687,17 @@ png_write_image_8bit(png_voidp argument) png_bytep row_end; int aindex; -# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED - if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) - { - aindex = -1; - ++input_row; /* To point to the first component */ - ++output_row; - } +# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED + if ((image->format & PNG_FORMAT_FLAG_AFIRST) != 0) + { + aindex = -1; + ++input_row; /* To point to the first component */ + ++output_row; + } - else -# endif - aindex = channels; + else +# endif + aindex = channels; /* Use row_end in place of a loop counter: */ row_end = output_row + image->width * (channels+1); @@ -1960,7 +1731,7 @@ png_write_image_8bit(png_voidp argument) } /* while out_ptr < row_end */ png_write_row(png_ptr, png_voidcast(png_const_bytep, - display->local_row)); + display->local_row)); input_row += display->row_bytes/(sizeof (png_uint_16)); } /* while y */ } @@ -1999,25 +1770,25 @@ png_image_set_PLTE(png_image_write_control *display) const png_imagep image = display->image; const void *cmap = display->colormap; const int entries = image->colormap_entries > 256 ? 256 : - (int)image->colormap_entries; + (int)image->colormap_entries; /* NOTE: the caller must check for cmap != NULL and entries != 0 */ const png_uint_32 format = image->format; const int channels = PNG_IMAGE_SAMPLE_CHANNELS(format); -# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\ +# if defined(PNG_FORMAT_BGR_SUPPORTED) &&\ defined(PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED) const int afirst = (format & PNG_FORMAT_FLAG_AFIRST) != 0 && - (format & PNG_FORMAT_FLAG_ALPHA) != 0; -# else + (format & PNG_FORMAT_FLAG_ALPHA) != 0; +# else # define afirst 0 -# endif +# endif -# ifdef PNG_FORMAT_BGR_SUPPORTED +# ifdef PNG_FORMAT_BGR_SUPPORTED const int bgr = (format & PNG_FORMAT_FLAG_BGR) != 0 ? 2 : 0; -# else +# else # define bgr 0 -# endif +# endif int i, num_trans; png_color palette[256]; @@ -2042,11 +1813,11 @@ png_image_set_PLTE(png_image_write_control *display) if (channels >= 3) /* RGB */ { palette[i].blue = (png_byte)PNG_sRGB_FROM_LINEAR(255 * - entry[(2 ^ bgr)]); + entry[(2 ^ bgr)]); palette[i].green = (png_byte)PNG_sRGB_FROM_LINEAR(255 * - entry[1]); + entry[1]); palette[i].red = (png_byte)PNG_sRGB_FROM_LINEAR(255 * - entry[bgr]); + entry[bgr]); } else /* Gray */ @@ -2122,12 +1893,12 @@ png_image_set_PLTE(png_image_write_control *display) } } -# ifdef afirst +# ifdef afirst # undef afirst -# endif -# ifdef bgr +# endif +# ifdef bgr # undef bgr -# endif +# endif png_set_PLTE(image->opaque->png_ptr, image->opaque->info_ptr, palette, entries); @@ -2155,10 +1926,10 @@ png_image_write_main(png_voidp argument) int alpha = !colormap && (format & PNG_FORMAT_FLAG_ALPHA); int write_16bit = linear && !colormap && (display->convert_to_8bit == 0); -# ifdef PNG_BENIGN_ERRORS_SUPPORTED +# ifdef PNG_BENIGN_ERRORS_SUPPORTED /* Make sure we error out on any bad situation */ png_set_benign_errors(png_ptr, 0/*error*/); -# endif +# endif /* Default the 'row_stride' parameter if required. */ if (display->row_stride == 0) @@ -2227,7 +1998,7 @@ png_image_write_main(png_voidp argument) /* Now set up the data transformations (*after* the header is written), * remove the handled transformations from the 'format' flags for checking. * - * First check for a little endian system if writing 16 bit files. + * First check for a little endian system if writing 16-bit files. */ if (write_16bit != 0) { @@ -2237,23 +2008,23 @@ png_image_write_main(png_voidp argument) png_set_swap(png_ptr); } -# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED +# ifdef PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED if ((format & PNG_FORMAT_FLAG_BGR) != 0) { if (colormap == 0 && (format & PNG_FORMAT_FLAG_COLOR) != 0) png_set_bgr(png_ptr); format &= ~PNG_FORMAT_FLAG_BGR; } -# endif +# endif -# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED +# ifdef PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED if ((format & PNG_FORMAT_FLAG_AFIRST) != 0) { if (colormap == 0 && (format & PNG_FORMAT_FLAG_ALPHA) != 0) png_set_swap_alpha(png_ptr); format &= ~PNG_FORMAT_FLAG_AFIRST; } -# endif +# endif /* If there are 16 or fewer color-map entries we wrote a lower bit depth * above, but the application data is still byte packed. @@ -2289,9 +2060,9 @@ png_image_write_main(png_voidp argument) * it about 50 times. The speed-up in pngstest was about 10-20% of the * total (user) time on a heavily loaded system. */ -#ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED +# ifdef PNG_WRITE_CUSTOMIZE_COMPRESSION_SUPPORTED png_set_compression_level(png_ptr, 3); -#endif +# endif } /* Check for the cases that currently require a pre-transform on the row @@ -2454,6 +2225,6 @@ png_image_write_to_file(png_imagep image, const char *file_name, else return 0; } -#endif /* STDIO */ +# endif /* STDIO */ #endif /* SIMPLIFIED_WRITE */ #endif /* WRITE */ diff --git a/src/3rdparty/libpng/pngwtran.c b/src/3rdparty/libpng/pngwtran.c index db82e27bce..5dc949157d 100644 --- a/src/3rdparty/libpng/pngwtran.c +++ b/src/3rdparty/libpng/pngwtran.c @@ -1,7 +1,7 @@ /* pngwtran.c - transforms the data in a row for PNG writers * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.18 [July 23, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -71,7 +71,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) case 2: { png_bytep sp, dp; - int shift, v; + unsigned int shift; + int v; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -110,7 +111,8 @@ png_do_pack(png_row_infop row_info, png_bytep row, png_uint_32 bit_depth) case 4: { png_bytep sp, dp; - int shift, v; + unsigned int shift; + int v; png_uint_32 i; png_uint_32 row_width = row_info->width; @@ -422,7 +424,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) *(dp++) = *(sp++); */ sp+=3; dp = sp; - *(dp++) = (png_byte)(255 - *(sp++)); + *dp = (png_byte)(255 - *(sp++)); } } @@ -446,7 +448,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) */ sp+=6; dp = sp; *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); + *dp = (png_byte)(255 - *(sp++)); } } #endif /* WRITE_16BIT */ @@ -484,7 +486,7 @@ png_do_write_invert_alpha(png_row_infop row_info, png_bytep row) */ sp+=2; dp = sp; *(dp++) = (png_byte)(255 - *(sp++)); - *(dp++) = (png_byte)(255 - *(sp++)); + *dp = (png_byte)(255 - *(sp++)); } } #endif /* WRITE_16BIT */ diff --git a/src/3rdparty/libpng/pngwutil.c b/src/3rdparty/libpng/pngwutil.c index b289671d12..adc4729c24 100644 --- a/src/3rdparty/libpng/pngwutil.c +++ b/src/3rdparty/libpng/pngwutil.c @@ -1,7 +1,7 @@ /* pngwutil.c - utilities to write a PNG file * - * Last changed in libpng 1.6.17 [March 26, 2015] + * Last changed in libpng 1.6.19 [November 12, 2015] * Copyright (c) 1998-2015 Glenn Randers-Pehrson * (Version 0.96 Copyright (c) 1996, 1997 Andreas Dilger) * (Version 0.88 Copyright (c) 1995, 1996 Guy Eric Schalnat, Group 42, Inc.) @@ -179,7 +179,7 @@ png_write_complete_chunk(png_structrp png_ptr, png_uint_32 chunk_name, if (png_ptr == NULL) return; - /* On 64 bit architectures 'length' may not fit in a png_uint_32. */ + /* On 64-bit architectures 'length' may not fit in a png_uint_32. */ if (length > PNG_UINT_31_MAX) png_error(png_ptr, "length exceeds PNG maximum"); @@ -308,7 +308,7 @@ png_deflate_claim(png_structrp png_ptr, png_uint_32 owner, */ (void)png_safecat(msg, (sizeof msg), 10, " using zstream"); #endif -#if PNG_LIBPNG_BUILD_BASE_TYPE >= PNG_LIBPNG_BUILD_RC +#if PNG_RELEASE_BUILD png_warning(png_ptr, msg); /* Attempt sane error recovery */ @@ -922,17 +922,20 @@ void /* PRIVATE */ png_write_PLTE(png_structrp png_ptr, png_const_colorp palette, png_uint_32 num_pal) { - png_uint_32 i; + png_uint_32 max_palette_length, i; png_const_colorp pal_ptr; png_byte buf[3]; png_debug(1, "in png_write_PLTE"); + max_palette_length = (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) ? + (1 << png_ptr->bit_depth) : PNG_MAX_PALETTE_LENGTH; + if (( #ifdef PNG_MNG_FEATURES_SUPPORTED (png_ptr->mng_features_permitted & PNG_FLAG_MNG_EMPTY_PLTE) == 0 && #endif - num_pal == 0) || num_pal > 256) + num_pal == 0) || num_pal > max_palette_length) { if (png_ptr->color_type == PNG_COLOR_TYPE_PALETTE) { @@ -1444,7 +1447,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, else if (color_type == PNG_COLOR_TYPE_GRAY) { - /* One 16 bit value */ + /* One 16-bit value */ if (tran->gray >= (1 << png_ptr->bit_depth)) { png_app_warning(png_ptr, @@ -1459,7 +1462,7 @@ png_write_tRNS(png_structrp png_ptr, png_const_bytep trans_alpha, else if (color_type == PNG_COLOR_TYPE_RGB) { - /* Three 16 bit values */ + /* Three 16-bit values */ png_save_uint_16(buf, tran->red); png_save_uint_16(buf + 2, tran->green); png_save_uint_16(buf + 4, tran->blue); @@ -1961,6 +1964,10 @@ png_write_start_row(png_structrp png_ptr) png_alloc_size_t buf_size; int usr_pixel_depth; +#ifdef PNG_WRITE_FILTER_SUPPORTED + png_byte filters; +#endif + png_debug(1, "in png_write_start_row"); usr_pixel_depth = png_ptr->usr_channels * png_ptr->usr_bit_depth; @@ -1971,50 +1978,54 @@ png_write_start_row(png_structrp png_ptr) png_ptr->maximum_pixel_depth = (png_byte)usr_pixel_depth; /* Set up row buffer */ - png_ptr->row_buf = (png_bytep)png_malloc(png_ptr, buf_size); + png_ptr->row_buf = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); png_ptr->row_buf[0] = PNG_FILTER_VALUE_NONE; #ifdef PNG_WRITE_FILTER_SUPPORTED - /* Set up filtering buffer, if using this filter */ - if (png_ptr->do_filter & PNG_FILTER_SUB) - { - png_ptr->sub_row = (png_bytep)png_malloc(png_ptr, png_ptr->rowbytes + 1); + filters = png_ptr->do_filter; - png_ptr->sub_row[0] = PNG_FILTER_VALUE_SUB; - } + if (png_ptr->height == 1) + filters &= 0xff & ~(PNG_FILTER_UP|PNG_FILTER_AVG|PNG_FILTER_PAETH); + + if (png_ptr->width == 1) + filters &= 0xff & ~(PNG_FILTER_SUB|PNG_FILTER_AVG|PNG_FILTER_PAETH); + + if (filters == 0) + filters = PNG_FILTER_NONE; - /* We only need to keep the previous row if we are using one of these. */ - if ((png_ptr->do_filter & - (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0) + png_ptr->do_filter = filters; + + if (((filters & (PNG_FILTER_SUB | PNG_FILTER_UP | PNG_FILTER_AVG | + PNG_FILTER_PAETH)) != 0) && png_ptr->try_row == NULL) { - /* Set up previous row buffer */ - png_ptr->prev_row = (png_bytep)png_calloc(png_ptr, buf_size); + int num_filters = 0; - if ((png_ptr->do_filter & PNG_FILTER_UP) != 0) - { - png_ptr->up_row = (png_bytep)png_malloc(png_ptr, - png_ptr->rowbytes + 1); + png_ptr->try_row = png_voidcast(png_bytep, png_malloc(png_ptr, buf_size)); - png_ptr->up_row[0] = PNG_FILTER_VALUE_UP; - } + if (filters & PNG_FILTER_SUB) + num_filters++; - if ((png_ptr->do_filter & PNG_FILTER_AVG) != 0) - { - png_ptr->avg_row = (png_bytep)png_malloc(png_ptr, - png_ptr->rowbytes + 1); + if (filters & PNG_FILTER_UP) + num_filters++; - png_ptr->avg_row[0] = PNG_FILTER_VALUE_AVG; - } + if (filters & PNG_FILTER_AVG) + num_filters++; - if ((png_ptr->do_filter & PNG_FILTER_PAETH) != 0) - { - png_ptr->paeth_row = (png_bytep)png_malloc(png_ptr, - png_ptr->rowbytes + 1); + if (filters & PNG_FILTER_PAETH) + num_filters++; - png_ptr->paeth_row[0] = PNG_FILTER_VALUE_PAETH; - } + if (num_filters > 1) + png_ptr->tst_row = png_voidcast(png_bytep, png_malloc(png_ptr, + buf_size)); } + + /* We only need to keep the previous row if we are using one of the following + * filters. + */ + if ((filters & (PNG_FILTER_AVG | PNG_FILTER_UP | PNG_FILTER_PAETH)) != 0) + png_ptr->prev_row = png_voidcast(png_bytep, + png_calloc(png_ptr, buf_size)); #endif /* WRITE_FILTER */ #ifdef PNG_WRITE_INTERLACING_SUPPORTED @@ -2160,7 +2171,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) { png_bytep sp; png_bytep dp; - int shift; + unsigned int shift; int d; int value; png_uint_32 i; @@ -2198,7 +2209,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) { png_bytep sp; png_bytep dp; - int shift; + unsigned int shift; int d; int value; png_uint_32 i; @@ -2235,7 +2246,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) { png_bytep sp; png_bytep dp; - int shift; + unsigned int shift; int d; int value; png_uint_32 i; @@ -2310,6 +2321,7 @@ png_do_write_interlace(png_row_infop row_info, png_bytep row, int pass) } #endif + /* This filters the row, chooses which filter to use, if it has not already * been specified by the application, and then writes the row out with the * chosen filter. @@ -2318,42 +2330,172 @@ static void /* PRIVATE */ png_write_filtered_row(png_structrp png_ptr, png_bytep filtered_row, png_size_t row_bytes); -#define PNG_MAXSUM (((png_uint_32)(-1)) >> 1) -#define PNG_HISHIFT 10 -#define PNG_LOMASK ((png_uint_32)0xffffL) -#define PNG_HIMASK ((png_uint_32)(~PNG_LOMASK >> PNG_HISHIFT)) +#ifdef PNG_WRITE_FILTER_SUPPORTED +static png_size_t /* PRIVATE */ +png_setup_sub_row(png_structrp png_ptr, const png_uint_32 bpp, + const png_size_t row_bytes, const png_size_t lmins) +{ + png_bytep rp, dp, lp; + png_size_t i; + png_size_t sum = 0; + int v; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_SUB; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1; i < bpp; + i++, rp++, dp++) + { + v = *dp = *rp; + sum += (v < 128) ? v : 256 - v; + } + + for (lp = png_ptr->row_buf + 1; i < row_bytes; + i++, rp++, lp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*lp) & 0xff); + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + + return (sum); +} + +static png_size_t /* PRIVATE */ +png_setup_up_row(png_structrp png_ptr, const png_size_t row_bytes, + const png_size_t lmins) +{ + png_bytep rp, dp, pp; + png_size_t i; + png_size_t sum = 0; + int v; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_UP; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, + pp = png_ptr->prev_row + 1; i < row_bytes; + i++, rp++, pp++, dp++) + { + v = *dp = (png_byte)(((int)*rp - (int)*pp) & 0xff); + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + + return (sum); +} + +static png_size_t /* PRIVATE */ +png_setup_avg_row(png_structrp png_ptr, const png_uint_32 bpp, + const png_size_t row_bytes, const png_size_t lmins) +{ + png_bytep rp, dp, pp, lp; + png_uint_32 i; + png_size_t sum = 0; + int v; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_AVG; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, + pp = png_ptr->prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - ((int)*pp++ / 2)) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = png_ptr->row_buf + 1; i < row_bytes; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)) + & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + + return (sum); +} + +static png_size_t /* PRIVATE */ +png_setup_paeth_row(png_structrp png_ptr, const png_uint_32 bpp, + const png_size_t row_bytes, const png_size_t lmins) +{ + png_bytep rp, dp, pp, cp, lp; + png_size_t i; + png_size_t sum = 0; + int v; + + png_ptr->try_row[0] = PNG_FILTER_VALUE_PAETH; + + for (i = 0, rp = png_ptr->row_buf + 1, dp = png_ptr->try_row + 1, + pp = png_ptr->prev_row + 1; i < bpp; i++) + { + v = *dp++ = (png_byte)(((int)*rp++ - (int)*pp++) & 0xff); + + sum += (v < 128) ? v : 256 - v; + } + + for (lp = png_ptr->row_buf + 1, cp = png_ptr->prev_row + 1; i < row_bytes; + i++) + { + int a, b, c, pa, pb, pc, p; + + b = *pp++; + c = *cp++; + a = *lp++; + + p = b - c; + pc = a - c; + +#ifdef PNG_USE_ABS + pa = abs(p); + pb = abs(pc); + pc = abs(p + pc); +#else + pa = p < 0 ? -p : p; + pb = pc < 0 ? -pc : pc; + pc = (p + pc) < 0 ? -(p + pc) : p + pc; +#endif + + p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; + + v = *dp++ = (png_byte)(((int)*rp++ - p) & 0xff); + + sum += (v < 128) ? v : 256 - v; + + if (sum > lmins) /* We are already worse, don't continue. */ + break; + } + + return (sum); +} +#endif /* WRITE_FILTER */ + void /* PRIVATE */ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) { - png_bytep best_row; -#ifdef PNG_WRITE_FILTER_SUPPORTED - png_bytep prev_row, row_buf; - png_uint_32 mins, bpp; +#ifndef PNG_WRITE_FILTER_SUPPORTED + png_write_filtered_row(png_ptr, png_ptr->row_buf, row_info->rowbytes+1); +#else png_byte filter_to_do = png_ptr->do_filter; + png_bytep row_buf; + png_bytep best_row; + png_uint_32 bpp; + png_size_t mins; png_size_t row_bytes = row_info->rowbytes; -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - int num_p_filters = png_ptr->num_prev_filters; -#endif png_debug(1, "in png_write_find_filter"); -#ifndef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->row_number == 0 && filter_to_do == PNG_ALL_FILTERS) - { - /* These will never be selected so we need not test them. */ - filter_to_do &= ~(PNG_FILTER_UP | PNG_FILTER_PAETH); - } -#endif - /* Find out how many bytes offset each pixel is */ bpp = (row_info->pixel_depth + 7) >> 3; - prev_row = png_ptr->prev_row; -#endif - best_row = png_ptr->row_buf; -#ifdef PNG_WRITE_FILTER_SUPPORTED - row_buf = best_row; - mins = PNG_MAXSUM; + row_buf = png_ptr->row_buf; + mins = PNG_SIZE_MAX - 256/* so we can detect potential overflow of the + running sum */; /* The prediction method we use is to find which method provides the * smallest value when summing the absolute values of the distances @@ -2383,57 +2525,37 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) /* We don't need to test the 'no filter' case if this is the only filter * that has been chosen, as it doesn't actually do anything to the data. */ + best_row = png_ptr->row_buf; + + if ((filter_to_do & PNG_FILTER_NONE) != 0 && filter_to_do != PNG_FILTER_NONE) { png_bytep rp; - png_uint_32 sum = 0; + png_size_t sum = 0; png_size_t i; int v; - for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + if (PNG_SIZE_MAX/128 <= row_bytes) { - v = *rp; - sum += (v < 128) ? v : 256 - v; - } + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) + { + /* Check for overflow */ + if (sum > PNG_SIZE_MAX/128 - 256) + break; -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + v = *rp; + sum += (v < 128) ? v : 256 - v; + } + } + else /* Overflow is not possible */ { - png_uint_32 sumhi, sumlo; - int j; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; /* Gives us some footroom */ - - /* Reduce the sum if we match any of the previous rows */ - for (j = 0; j < num_p_filters; j++) + for (i = 0, rp = row_buf + 1; i < row_bytes; i++, rp++) { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } + v = *rp; + sum += (v < 128) ? v : 256 - v; } - - /* Factor in the cost of this filter (this is here for completeness, - * but it makes no sense to have a "cost" for the NONE filter, as - * it has the minimum possible computational cost - none). - */ - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; - - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_NONE]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; } -#endif + mins = sum; } @@ -2441,553 +2563,109 @@ png_write_find_filter(png_structrp png_ptr, png_row_infop row_info) if (filter_to_do == PNG_FILTER_SUB) /* It's the only filter so no testing is needed */ { - png_bytep rp, lp, dp; - png_size_t i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - *dp = *rp; - } - - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - *dp = (png_byte)((int)*rp - (int)*lp); - } - - best_row = png_ptr->sub_row; + (void) png_setup_sub_row(png_ptr, bpp, row_bytes, mins); + best_row = png_ptr->try_row; } else if ((filter_to_do & PNG_FILTER_SUB) != 0) { - png_bytep rp, dp, lp; - png_uint_32 sum = 0, lmins = mins; - png_size_t i; - int v; - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - /* We temporarily increase the "minimum sum" by the factor we - * would reduce the sum of this filter, so that we can do the - * early exit comparison without scaling the sum each time. - */ - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; + png_size_t sum; + png_size_t lmins = mins; - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->sub_row + 1; i < bpp; - i++, rp++, dp++) - { - v = *dp = *rp; - - sum += (v < 128) ? v : 256 - v; - } - - for (lp = row_buf + 1; i < row_bytes; - i++, rp++, lp++, dp++) - { - v = *dp = (png_byte)((int)*rp - (int)*lp); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_SUB) - { - sumlo = (sumlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - sumhi = (sumhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_SUB]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif + sum = png_setup_sub_row(png_ptr, bpp, row_bytes, lmins); if (sum < mins) { mins = sum; - best_row = png_ptr->sub_row; + best_row = png_ptr->try_row; + if (png_ptr->tst_row != NULL) + { + png_ptr->try_row = png_ptr->tst_row; + png_ptr->tst_row = best_row; + } } } /* Up filter */ if (filter_to_do == PNG_FILTER_UP) { - png_bytep rp, dp, pp; - png_size_t i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; - i++, rp++, pp++, dp++) - { - *dp = (png_byte)((int)*rp - (int)*pp); - } - - best_row = png_ptr->up_row; + (void) png_setup_up_row(png_ptr, row_bytes, mins); + best_row = png_ptr->try_row; } else if ((filter_to_do & PNG_FILTER_UP) != 0) { - png_bytep rp, dp, pp; - png_uint_32 sum = 0, lmins = mins; - png_size_t i; - int v; - - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->up_row + 1, - pp = prev_row + 1; i < row_bytes; i++) - { - v = *dp++ = (png_byte)((int)*rp++ - (int)*pp++); + png_size_t sum; + png_size_t lmins = mins; - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_UP) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_UP]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif + sum = png_setup_up_row(png_ptr, row_bytes, lmins); if (sum < mins) { mins = sum; - best_row = png_ptr->up_row; + best_row = png_ptr->try_row; + if (png_ptr->tst_row != NULL) + { + png_ptr->try_row = png_ptr->tst_row; + png_ptr->tst_row = best_row; + } } } /* Avg filter */ if (filter_to_do == PNG_FILTER_AVG) { - png_bytep rp, dp, pp, lp; - png_uint_32 i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)((int)*rp++ - ((int)*pp++ / 2)); - } - - for (lp = row_buf + 1; i < row_bytes; i++) - { - *dp++ = - (png_byte)((int)*rp++ - (((int)*pp++ + (int)*lp++) / 2)); - } - best_row = png_ptr->avg_row; + (void) png_setup_avg_row(png_ptr, bpp, row_bytes, mins); + best_row = png_ptr->try_row; } else if ((filter_to_do & PNG_FILTER_AVG) != 0) { - png_bytep rp, dp, pp, lp; - png_uint_32 sum = 0, lmins = mins; - png_size_t i; - int v; - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_AVG) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->avg_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)((int)*rp++ - ((int)*pp++ / 2)); - - sum += (v < 128) ? v : 256 - v; - } - - for (lp = row_buf + 1; i < row_bytes; i++) - { - v = *dp++ = - (png_byte)(((int)*rp++ - ((int)*pp++ + (int)*lp++) / 2)); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_NONE) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; + png_size_t sum; + png_size_t lmins = mins; - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_AVG]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif + sum= png_setup_avg_row(png_ptr, bpp, row_bytes, lmins); if (sum < mins) { mins = sum; - best_row = png_ptr->avg_row; + best_row = png_ptr->try_row; + if (png_ptr->tst_row != NULL) + { + png_ptr->try_row = png_ptr->tst_row; + png_ptr->tst_row = best_row; + } } } /* Paeth filter */ if ((filter_to_do == PNG_FILTER_PAETH) != 0) { - png_bytep rp, dp, pp, cp, lp; - png_size_t i; - - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - *dp++ = (png_byte)((int)*rp++ - (int)*pp++); - } - - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; - - b = *pp++; - c = *cp++; - a = *lp++; - - p = b - c; - pc = a - c; - -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; - - *dp++ = (png_byte)((int)*rp++ - p); - } - best_row = png_ptr->paeth_row; + (void) png_setup_paeth_row(png_ptr, bpp, row_bytes, mins); + best_row = png_ptr->try_row; } else if ((filter_to_do & PNG_FILTER_PAETH) != 0) { - png_bytep rp, dp, pp, cp, lp; - png_uint_32 sum = 0, lmins = mins; - png_size_t i; - int v; - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) - { - int j; - png_uint_32 lmhi, lmlo; - lmlo = lmins & PNG_LOMASK; - lmhi = (lmins >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) - { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - lmlo = (lmlo * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } - } - - lmlo = (lmlo * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - lmhi = (lmhi * png_ptr->inv_filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - if (lmhi > PNG_HIMASK) - lmins = PNG_MAXSUM; - - else - lmins = (lmhi << PNG_HISHIFT) + lmlo; - } -#endif - - for (i = 0, rp = row_buf + 1, dp = png_ptr->paeth_row + 1, - pp = prev_row + 1; i < bpp; i++) - { - v = *dp++ = (png_byte)((int)*rp++ - (int)*pp++); + png_size_t sum; + png_size_t lmins = mins; - sum += (v < 128) ? v : 256 - v; - } - - for (lp = row_buf + 1, cp = prev_row + 1; i < row_bytes; i++) - { - int a, b, c, pa, pb, pc, p; + sum = png_setup_paeth_row(png_ptr, bpp, row_bytes, lmins); - b = *pp++; - c = *cp++; - a = *lp++; - -#ifndef PNG_SLOW_PAETH - p = b - c; - pc = a - c; -#ifdef PNG_USE_ABS - pa = abs(p); - pb = abs(pc); - pc = abs(p + pc); -#else - pa = p < 0 ? -p : p; - pb = pc < 0 ? -pc : pc; - pc = (p + pc) < 0 ? -(p + pc) : p + pc; -#endif - p = (pa <= pb && pa <=pc) ? a : (pb <= pc) ? b : c; -#else /* SLOW_PAETH */ - p = a + b - c; - pa = abs(p - a); - pb = abs(p - b); - pc = abs(p - c); - - if (pa <= pb && pa <= pc) - p = a; - - else if (pb <= pc) - p = b; - - else - p = c; -#endif /* SLOW_PAETH */ - - v = *dp++ = (png_byte)((int)*rp++ - p); - - sum += (v < 128) ? v : 256 - v; - - if (sum > lmins) /* We are already worse, don't continue. */ - break; - } - -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - if (png_ptr->heuristic_method == PNG_FILTER_HEURISTIC_WEIGHTED) + if (sum < mins) { - int j; - png_uint_32 sumhi, sumlo; - sumlo = sum & PNG_LOMASK; - sumhi = (sum >> PNG_HISHIFT) & PNG_HIMASK; - - for (j = 0; j < num_p_filters; j++) + best_row = png_ptr->try_row; + if (png_ptr->tst_row != NULL) { - if (png_ptr->prev_filters[j] == PNG_FILTER_VALUE_PAETH) - { - sumlo = (sumlo * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - - sumhi = (sumhi * png_ptr->filter_weights[j]) >> - PNG_WEIGHT_SHIFT; - } + png_ptr->try_row = png_ptr->tst_row; + png_ptr->tst_row = best_row; } - - sumlo = (sumlo * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - sumhi = (sumhi * png_ptr->filter_costs[PNG_FILTER_VALUE_PAETH]) >> - PNG_COST_SHIFT; - - if (sumhi > PNG_HIMASK) - sum = PNG_MAXSUM; - - else - sum = (sumhi << PNG_HISHIFT) + sumlo; - } -#endif - - if (sum < mins) - { - best_row = png_ptr->paeth_row; } } -#endif /* WRITE_FILTER */ /* Do the actual writing of the filtered row data from the chosen filter. */ png_write_filtered_row(png_ptr, best_row, row_info->rowbytes+1); -#ifdef PNG_WRITE_FILTER_SUPPORTED -#ifdef PNG_WRITE_WEIGHTED_FILTER_SUPPORTED - /* Save the type of filter we picked this time for future calculations */ - if (png_ptr->num_prev_filters > 0) - { - int j; - - for (j = 1; j < num_p_filters; j++) - { - png_ptr->prev_filters[j] = png_ptr->prev_filters[j - 1]; - } - - png_ptr->prev_filters[j] = best_row[0]; - } -#endif #endif /* WRITE_FILTER */ } diff --git a/src/3rdparty/libpng/qtpatches.diff b/src/3rdparty/libpng/qtpatches.diff index 1fb9b3f0c0..82ee104545 100644 --- a/src/3rdparty/libpng/qtpatches.diff +++ b/src/3rdparty/libpng/qtpatches.diff @@ -1,34 +1,5 @@ -diff --git a/src/3rdparty/libpng/pnglibconf.h b/src/3rdparty/libpng/pnglibconf.h -index b4ec3c3..f0fdcf8 100644 ---- a/src/3rdparty/libpng/pnglibconf.h -+++ b/src/3rdparty/libpng/pnglibconf.h -@@ -27,7 +27,9 @@ - #define PNG_CHECK_FOR_INVALID_INDEX_SUPPORTED - #define PNG_COLORSPACE_SUPPORTED - #define PNG_CONSOLE_IO_SUPPORTED -+#ifndef _WIN32_WCE - #define PNG_CONVERT_tIME_SUPPORTED -+#endif - #define PNG_EASY_ACCESS_SUPPORTED - /*#undef PNG_ERROR_NUMBERS_SUPPORTED*/ - #define PNG_ERROR_TEXT_SUPPORTED -@@ -106,12 +108,14 @@ - #define PNG_SET_OPTION_SUPPORTED - #define PNG_SET_UNKNOWN_CHUNKS_SUPPORTED - #define PNG_SET_USER_LIMITS_SUPPORTED -+#ifndef _WIN32_WCE - #define PNG_SIMPLIFIED_READ_AFIRST_SUPPORTED - #define PNG_SIMPLIFIED_READ_BGR_SUPPORTED - #define PNG_SIMPLIFIED_READ_SUPPORTED - #define PNG_SIMPLIFIED_WRITE_AFIRST_SUPPORTED - #define PNG_SIMPLIFIED_WRITE_BGR_SUPPORTED - #define PNG_SIMPLIFIED_WRITE_SUPPORTED -+#endif - #define PNG_STDIO_SUPPORTED - #define PNG_STORE_UNKNOWN_CHUNKS_SUPPORTED - #define PNG_TEXT_SUPPORTED diff --git a/src/3rdparty/libpng/pngpriv.h b/src/3rdparty/libpng/pngpriv.h -index 5980a3f..7185444 100644 +index c466d4b..f7a4547 100644 --- a/src/3rdparty/libpng/pngpriv.h +++ b/src/3rdparty/libpng/pngpriv.h @@ -23,6 +23,12 @@ @@ -44,7 +15,7 @@ index 5980a3f..7185444 100644 /* Feature Test Macros. The following are defined here to ensure that correctly * implemented libraries reveal the APIs libpng needs to build and hide those * that are not needed and potentially damaging to the compilation. -@@ -215,6 +221,11 @@ +@@ -219,6 +225,11 @@ # endif #endif /* Setting PNG_BUILD_DLL if required */ @@ -56,7 +27,7 @@ index 5980a3f..7185444 100644 /* See pngconf.h for more details: the builder of the library may set this on * the command line to the right thing for the specific compilation system or it * may be automagically set above (at present we know of no system where it does -@@ -426,6 +437,9 @@ +@@ -447,6 +458,9 @@ #if defined(WIN32) || defined(_Windows) || defined(_WINDOWS) || \ defined(_WIN32) || defined(__WIN32__) # include /* defines _WINDOWS_ macro */ @@ -66,7 +37,7 @@ index 5980a3f..7185444 100644 #endif #endif /* PNG_VERSION_INFO_ONLY */ -@@ -436,7 +450,7 @@ +@@ -457,7 +471,7 @@ /* Memory model/platform independent fns */ #ifndef PNG_ABORT -- cgit v1.2.3 From 33c9059f03a67d83123933426ea9164d57399d4c Mon Sep 17 00:00:00 2001 From: Maxim Mikityanskiy Date: Sun, 9 Aug 2015 13:47:12 +0300 Subject: Fix XI2 smooth scroll with inverted direction When touchpad scroll direction is inverted, verticalIncrement and horizontalIncrement of scrollingDevice are negative, and rawDelta remains unfilled. It leads to pixelDelta.isNull() being true in wheel event handler even when XI2 smooth scrolling is available on the system. Fix that and fill rawDelta with correct values when inverted scroll direction is used. Change-Id: I9c0bdbad2c6b9bbed765eaa895dca300c5c70e86 Reviewed-by: Shawn Rutledge --- src/plugins/platforms/xcb/qxcbconnection_xi2.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp index d7688be0ff..5aa1933859 100644 --- a/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp +++ b/src/plugins/platforms/xcb/qxcbconnection_xi2.cpp @@ -859,6 +859,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin // We do not set "pixel" delta if it is only measured in ticks. if (scrollingDevice.verticalIncrement > 1) rawDelta.setY(delta); + else if (scrollingDevice.verticalIncrement < -1) + rawDelta.setY(-delta); } } if (scrollingDevice.orientations & Qt::Horizontal) { @@ -869,6 +871,8 @@ void QXcbConnection::xi2HandleScrollEvent(void *event, ScrollingDevice &scrollin // We do not set "pixel" delta if it is only measured in ticks. if (scrollingDevice.horizontalIncrement > 1) rawDelta.setX(delta); + else if (scrollingDevice.horizontalIncrement < -1) + rawDelta.setX(-delta); } } if (!angleDelta.isNull()) { -- cgit v1.2.3 From 0629e879422eae8751973b62ac29a61ca546f78c Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Tue, 24 Nov 2015 14:46:05 +0200 Subject: Fix extract style on Android 6.0 A few things were changed in Android 6.0 Task-number: QTBUG-49323 Change-Id: I3112d885881dce541d5c4f3a1561f6c34d75e319 Reviewed-by: Christian Stromme (cherry picked from commit 361e24b79ef835e1df040c64a71b9f42f90f14ad) Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java index 12ae8a65d8..f5dac1fa60 100644 --- a/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java +++ b/src/android/jar/src/org/qtproject/qt5/android/ExtractStyle.java @@ -671,7 +671,7 @@ public class ExtractStyle { json.put("gradient",gradientStateClass.getField("mGradient").getInt(obj)); GradientDrawable.Orientation orientation=(Orientation) gradientStateClass.getField("mOrientation").get(obj); json.put("orientation",orientation.name()); - int [] intArray=(int[]) gradientStateClass.getField("mColors").get(obj); + int [] intArray=(int[]) gradientStateClass.getField((Build.VERSION.SDK_INT < 23) ? "mColors" : "mGradientColors").get(obj); if (intArray != null) json.put("colors",getJsonArray(intArray, 0, intArray.length)); json.put("positions",getJsonArray((float[]) gradientStateClass.getField("mPositions").get(obj))); @@ -707,7 +707,10 @@ public class ExtractStyle { json.put("type", "rotate"); Object obj = drawable.getConstantState(); Class rotateStateClass = obj.getClass(); - json.put("drawable", getDrawable(getAccessibleField(rotateStateClass, "mDrawable").get(obj), filename, null)); + if (Build.VERSION.SDK_INT < 23) + json.put("drawable", getDrawable(getAccessibleField(rotateStateClass, "mDrawable").get(obj), filename, null)); + else + json.put("drawable", getDrawable(drawable.getClass().getMethod("getDrawable").invoke(drawable), filename, null)); json.put("pivotX", getAccessibleField(rotateStateClass, "mPivotX").getFloat(obj)); json.put("pivotXRel", getAccessibleField(rotateStateClass, "mPivotXRel").getBoolean(obj)); json.put("pivotY", getAccessibleField(rotateStateClass, "mPivotY").getFloat(obj)); -- cgit v1.2.3 From 1823c8f2ddd0a5c1b4301e7af7109796090a3c9a Mon Sep 17 00:00:00 2001 From: Erik Verbruggen Date: Wed, 16 Dec 2015 14:04:27 +0100 Subject: Fix utf8->utf16 BOM/ZWNBSP decoding. When the byte sequence for a BOM occurs in the middle of a utf8 stream, it is a ZWNBSP. When a ZWNBSP occurs in the middle of a utf8 character sequence, and the SIMD conversion does some work (meaning: the length is at least 16 characters long), it would not recognize the fact some charactes were already decoded. So the conversion would then strip the ZWNBSP out, thinking it's a BOM. The non-SIMD conversion did not have this problem: the very first character conversion would already set the headerdone flag. Change-Id: I39aacf607e2e068107106254021a8042d164f628 Reviewed-by: Thiago Macieira --- src/corelib/codecs/qutfcodec.cpp | 9 ++++++--- tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp | 13 ++++++++++--- 2 files changed, 16 insertions(+), 6 deletions(-) diff --git a/src/corelib/codecs/qutfcodec.cpp b/src/corelib/codecs/qutfcodec.cpp index 98d4b2e4e3..a33c1bc9ce 100644 --- a/src/corelib/codecs/qutfcodec.cpp +++ b/src/corelib/codecs/qutfcodec.cpp @@ -364,6 +364,7 @@ QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::Converte // main body, stateless decoding res = 0; const uchar *nextAscii = src; + const uchar *start = src; while (res >= 0 && src < end) { if (src >= nextAscii && simdDecodeAscii(dst, nextAscii, src, end)) break; @@ -372,9 +373,11 @@ QString QUtf8::convertToUnicode(const char *chars, int len, QTextCodec::Converte res = QUtf8Functions::fromUtf8(ch, dst, src, end); if (!headerdone && res >= 0) { headerdone = true; - // eat the UTF-8 BOM - if (dst[-1] == 0xfeff) - --dst; + if (src == start + 3) { // 3 == sizeof(utf8-bom) + // eat the UTF-8 BOM (it can only appear at the beginning of the string). + if (dst[-1] == 0xfeff) + --dst; + } } if (res == QUtf8BaseTraits::Error) { res = 0; diff --git a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp index 3aa06d237d..8a9ae0cd72 100644 --- a/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp +++ b/tests/auto/corelib/codecs/qtextcodec/tst_qtextcodec.cpp @@ -1588,10 +1588,17 @@ void tst_QTextCodec::utf8bom_data() << QString("a"); } - { + { // test the non-SIMD code-path static const ushort data[] = { 0x61, 0xfeff, 0x62 }; - QTest::newRow("middle-bom") - << QByteArray("a\357\273\277b", 5) + QTest::newRow("middle-bom (non SIMD)") + << QByteArray("a\357\273\277b") + << QString::fromUtf16(data, sizeof(data)/sizeof(short)); + } + + { // test the SIMD code-path + static const ushort data[] = { 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0xfeff, 0x6d }; + QTest::newRow("middle-bom (SIMD)") + << QByteArray("abcdefghijkl\357\273\277m") << QString::fromUtf16(data, sizeof(data)/sizeof(short)); } } -- cgit v1.2.3 From e96fa5a780665e24fe4710868e399b3216a5d3b3 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Mon, 21 Dec 2015 11:37:49 +0100 Subject: Fix timeout calculations using qt_subtract_from_timeout Commit ed0c0070 introduced qt_subtract_from_timeout but used it incorrectly in several places. Change-Id: I80ea16088707929a45d5a61ec6f3370f8e63d1cd Reviewed-by: Oswald Buddenhagen --- src/corelib/io/qwinoverlappedionotifier.cpp | 2 +- .../other/networkselftest/tst_networkselftest.cpp | 20 ++++++++++++-------- 2 files changed, 13 insertions(+), 9 deletions(-) diff --git a/src/corelib/io/qwinoverlappedionotifier.cpp b/src/corelib/io/qwinoverlappedionotifier.cpp index c6ce15c2c9..8b7d70cf71 100644 --- a/src/corelib/io/qwinoverlappedionotifier.cpp +++ b/src/corelib/io/qwinoverlappedionotifier.cpp @@ -364,7 +364,7 @@ bool QWinOverlappedIoNotifier::waitForNotified(int msecs, OVERLAPPED *overlapped return false; if (triggeredOverlapped == overlapped) return true; - msecs = qt_subtract_from_timeout(msecs, stopWatch.elapsed()); + t = qt_subtract_from_timeout(msecs, stopWatch.elapsed()); if (t == 0) return false; } diff --git a/tests/auto/other/networkselftest/tst_networkselftest.cpp b/tests/auto/other/networkselftest/tst_networkselftest.cpp index 5612260cca..ca321fb6fd 100644 --- a/tests/auto/other/networkselftest/tst_networkselftest.cpp +++ b/tests/auto/other/networkselftest/tst_networkselftest.cpp @@ -169,14 +169,16 @@ static bool doSocketRead(QTcpSocket *socket, int minBytesAvailable, int timeout { QElapsedTimer timer; timer.start(); + int t = timeout; forever { if (socket->bytesAvailable() >= minBytesAvailable) return true; - timeout = qt_subtract_from_timeout(timeout, timer.elapsed()); - if (socket->state() == QAbstractSocket::UnconnectedState - || timeout == 0) + if (socket->state() == QAbstractSocket::UnconnectedState) return false; - if (!socket->waitForReadyRead(timeout)) + if (!socket->waitForReadyRead(t)) + return false; + t = qt_subtract_from_timeout(timeout, timer.elapsed()); + if (t == 0) return false; } } @@ -197,6 +199,7 @@ static bool doSocketFlush(QTcpSocket *socket, int timeout = 4000) #endif QTime timer; timer.start(); + int t = timeout; forever { if (socket->bytesToWrite() == 0 #ifndef QT_NO_SSL @@ -204,11 +207,12 @@ static bool doSocketFlush(QTcpSocket *socket, int timeout = 4000) #endif ) return true; - timeout = qt_subtract_from_timeout(timeout, timer.elapsed()); - if (socket->state() == QAbstractSocket::UnconnectedState - || timeout == 0) + if (socket->state() == QAbstractSocket::UnconnectedState) + return false; + if (!socket->waitForBytesWritten(t)) return false; - if (!socket->waitForBytesWritten(timeout)) + t = qt_subtract_from_timeout(timeout, timer.elapsed()); + if (t == 0) return false; } } -- cgit v1.2.3 From 64481bcc671892cd140ce5415eaec7fef3e2a35d Mon Sep 17 00:00:00 2001 From: Gabriel de Dietrich Date: Wed, 9 Dec 2015 16:57:54 -0800 Subject: QWidgetWindow: The alien widget should be from the window's hierarchy This partially reverts commit 025d6a778ceb377e688f1. Change-Id: I7b964b0d598abe46137c22177fe2b5dcca5bb812 Task-number: QTBUG-49831 Reviewed-by: Gabriel de Dietrich Reviewed-by: Andy Shaw --- src/widgets/kernel/qwidgetwindow.cpp | 2 +- .../widgets/widgets/qcombobox/tst_qcombobox.cpp | 32 ++++++++++++++++++++++ 2 files changed, 33 insertions(+), 1 deletion(-) diff --git a/src/widgets/kernel/qwidgetwindow.cpp b/src/widgets/kernel/qwidgetwindow.cpp index 24ef7de1cf..cc50cde799 100644 --- a/src/widgets/kernel/qwidgetwindow.cpp +++ b/src/widgets/kernel/qwidgetwindow.cpp @@ -445,7 +445,7 @@ void QWidgetWindow::handleMouseEvent(QMouseEvent *event) receiver = popupChild; if (receiver != popup) widgetPos = receiver->mapFromGlobal(event->globalPos()); - QWidget *alien = receiver->childAt(receiver->mapFromGlobal(event->globalPos())); + QWidget *alien = m_widget->childAt(m_widget->mapFromGlobal(event->globalPos())); QMouseEvent e(event->type(), widgetPos, event->windowPos(), event->screenPos(), event->button(), event->buttons(), event->modifiers()); QGuiApplicationPrivate::setMouseEventSource(&e, QGuiApplicationPrivate::mouseEventSource(event)); e.setTimestamp(event->timestamp()); diff --git a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp index 21446de069..00636e50a8 100644 --- a/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp +++ b/tests/auto/widgets/widgets/qcombobox/tst_qcombobox.cpp @@ -165,6 +165,7 @@ private slots: void setCustomModelAndView(); void updateDelegateOnEditableChange(); void task_QTBUG_39088_inputMethodHints(); + void task_QTBUG_49831_scrollerNotActivated(); }; class MyAbstractItemDelegate : public QAbstractItemDelegate @@ -3184,5 +3185,36 @@ void tst_QComboBox::task_QTBUG_39088_inputMethodHints() QCOMPARE(box.lineEdit()->inputMethodHints(), Qt::ImhNoPredictiveText); } +void tst_QComboBox::task_QTBUG_49831_scrollerNotActivated() +{ + QStringList modelData; + for (int i = 0; i < 1000; i++) + modelData << QStringLiteral("Item %1").arg(i); + QStringListModel model(modelData); + + QComboBox box; + box.setModel(&model); + box.setCurrentIndex(500); + box.show(); + QTest::qWaitForWindowShown(&box); + QTest::mouseMove(&box, QPoint(5, 5), 100); + box.showPopup(); + QFrame *container = box.findChild(); + QVERIFY(container); + QTest::qWaitForWindowShown(container); + + QList scrollers = container->findChildren(); + // Not all styles support scrollers. We rely only on those platforms that do to catch any regression. + if (!scrollers.isEmpty()) { + Q_FOREACH (QComboBoxPrivateScroller *scroller, scrollers) { + if (scroller->isVisible()) { + QSignalSpy doScrollSpy(scroller, SIGNAL(doScroll(int))); + QTest::mouseMove(scroller, QPoint(5, 5), 500); + QTRY_VERIFY(doScrollSpy.count() > 0); + } + } + } +} + QTEST_MAIN(tst_QComboBox) #include "tst_qcombobox.moc" -- cgit v1.2.3 From 1e2d35d4880574b20537677729093df279658965 Mon Sep 17 00:00:00 2001 From: Christian Kamm Date: Wed, 2 Sep 2015 10:36:40 +0200 Subject: QSystemTrayIcon: Fix double connection with qpa. install_sys_qpa() is called for each QSystemTrayIcon::show(), leading to spurious calls of user slots if the signal isn't disconnected on remove_sys_qpa(). Task-number: QTBUG-48068 Change-Id: Ic830250c71fee6b584550ab5aabf54289e478fcb Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Richard Rondu Reviewed-by: Shawn Rutledge --- src/widgets/util/qsystemtrayicon.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/widgets/util/qsystemtrayicon.cpp b/src/widgets/util/qsystemtrayicon.cpp index 358e4c38d6..df3c291840 100644 --- a/src/widgets/util/qsystemtrayicon.cpp +++ b/src/widgets/util/qsystemtrayicon.cpp @@ -693,6 +693,10 @@ void QSystemTrayIconPrivate::install_sys_qpa() void QSystemTrayIconPrivate::remove_sys_qpa() { + QObject::disconnect(qpa_sys, SIGNAL(activated(QPlatformSystemTrayIcon::ActivationReason)), + q_func(), SLOT(_q_emitActivated(QPlatformSystemTrayIcon::ActivationReason))); + QObject::disconnect(qpa_sys, &QPlatformSystemTrayIcon::messageClicked, + q_func(), &QSystemTrayIcon::messageClicked); qpa_sys->cleanup(); } -- cgit v1.2.3 From 6b6955c2ffdb23c461812ffcda12a2296ef58513 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Wed, 23 Dec 2015 13:10:30 +0200 Subject: QAbstractSocket: do not enable read notifications on TCP in bind() In bind+connect scenario, rejected connection can trigger a read notification while the socket is opened. But unlike UDP, reading from the socket engine or emitting a readyRead() signal is not allowed for the TCP socket in bound or connecting state. To make a bind+connect scenario work properly, disable the read notifications until a connection is established. Task-number: QTBUG-50124 Change-Id: I7b3d015b0f6021fb9ff9f83560478aa5545f41f5 Reviewed-by: Richard J. Moore --- src/network/socket/qabstractsocket.cpp | 3 ++- .../network/socket/qtcpsocket/tst_qtcpsocket.cpp | 21 +++++++++++++++++++++ 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qabstractsocket.cpp b/src/network/socket/qabstractsocket.cpp index 5b1c5fa601..e22c5ccca4 100644 --- a/src/network/socket/qabstractsocket.cpp +++ b/src/network/socket/qabstractsocket.cpp @@ -1530,7 +1530,8 @@ bool QAbstractSocketPrivate::bind(const QHostAddress &address, quint16 port, QAb localPort = socketEngine->localPort(); emit q->stateChanged(state); - socketEngine->setReadNotificationEnabled(true); + if (socketType == QAbstractSocket::UdpSocket) + socketEngine->setReadNotificationEnabled(true); return true; } diff --git a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp index 0ba9b6a58c..e8a942e6c4 100644 --- a/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp +++ b/tests/auto/network/socket/qtcpsocket/tst_qtcpsocket.cpp @@ -200,6 +200,7 @@ private slots: void setSocketOption(); void clientSendDataOnDelayedDisconnect(); + void readNotificationsAfterBind(); protected slots: void nonBlockingIMAP_hostFound(); @@ -2984,5 +2985,25 @@ void tst_QTcpSocket::clientSendDataOnDelayedDisconnect() delete socket; } +// Test that the socket does not enable the read notifications in bind() +void tst_QTcpSocket::readNotificationsAfterBind() +{ + QFETCH_GLOBAL(bool, setProxy); + if (setProxy) + return; + + QAbstractSocket socket(QAbstractSocket::TcpSocket, Q_NULLPTR); + QVERIFY2(socket.bind(), "Bind error!"); + + connect(&socket, SIGNAL(error(QAbstractSocket::SocketError)), &QTestEventLoop::instance(), SLOT(exitLoop())); + QSignalSpy spyReadyRead(&socket, SIGNAL(readyRead())); + socket.connectToHost(QtNetworkSettings::serverName(), 12346); + + QTestEventLoop::instance().enterLoop(10); + QVERIFY2(!QTestEventLoop::instance().timeout(), "Connection to closed port timed out instead of refusing, something is wrong"); + QVERIFY2(socket.state() == QAbstractSocket::UnconnectedState, "Socket connected unexpectedly!"); + QCOMPARE(spyReadyRead.count(), 0); +} + QTEST_MAIN(tst_QTcpSocket) #include "tst_qtcpsocket.moc" -- cgit v1.2.3 From c8c4ad0c62cacec749b6c42e0a58339446093bba Mon Sep 17 00:00:00 2001 From: Raphael Kubo da Costa Date: Sat, 26 Dec 2015 02:30:58 +0100 Subject: forkfd: Define __BSD_VISIBLE and _NETBSD_SOURCE. pipe2's availability on BSD operating systems depends on the __BSD_VISIBLE macro on FreeBSD and OpenBSD and _NETBSD_SOURCE on NetBSD (DragonFly BSD appears to define it unconditionally). Those two macros are generally set by default, except when _POSIX_C_SOURCE is set. Since we consciously set _POSIX_C_SOURCE but need pipe2, explicitly define the visibility macros. This fixes the -no-pch build on FreeBSD at least. Change-Id: Icc77f6b5d1f9a5bf7bd8048cabbb01f8f89397cc Reviewed-by: Thiago Macieira --- src/3rdparty/forkfd/forkfd.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index e35b66ae2c..099a0ff574 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -25,8 +25,10 @@ #ifndef _GNU_SOURCE # define _GNU_SOURCE +# define _NETBSD_SOURCE 1 # define _POSIX_C_SOURCE 200809L # define _XOPEN_SOURCE 700 +# define __BSD_VISIBLE 1 #endif #include "forkfd.h" -- cgit v1.2.3 From 655246969eaa916fbc098a7315dc24830f5b8b5d Mon Sep 17 00:00:00 2001 From: Raphael Kubo da Costa Date: Mon, 28 Dec 2015 11:43:36 +0100 Subject: forkfd: Also define BSD visibility macros in forkfd_qt.cpp. This is a follow-up to c8c4ad0 ("forkfd: Define __BSD_VISIBLE and _NETBSD_SOURCE"). Defining those macros in forkfd.c is not enough: forkfd_qt.cpp also sets _POSIX_C_SOURCE, and sys/cdefs.h can be included implicitly via Qt's headers ( ends up pulling unistd.h that leads to sys/cdefs.h and sys/types.h with both libstdc++ and older libc++ versions). In this case, __BSD_VISIBLE/_NETBSD_SOURCE are not defined, _POSIX_C_SOURCE is, several type definitions are omitted and by the time we include sys/time.h in forkfd.c the build fails. On FreeBSD < 11, the error looks like this: In file included from io/../../3rdparty/forkfd/forkfd.c:36, from io/forkfd_qt.cpp:80: /usr/include/sys/time.h:94: error: 'u_int' has not been declared Change-Id: I01fa2f5861027d99936d3026faeee9f0db3ecabd Reviewed-by: Thiago Macieira --- src/corelib/io/forkfd_qt.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/src/corelib/io/forkfd_qt.cpp b/src/corelib/io/forkfd_qt.cpp index 6704ec6f2a..d282c08fbd 100644 --- a/src/corelib/io/forkfd_qt.cpp +++ b/src/corelib/io/forkfd_qt.cpp @@ -39,6 +39,15 @@ # define _XOPEN_SOURCE 700 #endif +// Define BSD visibility macros. These are also defined in forkfd.c, but the +// headers using them may be included before forkfd.c itself. +#ifndef _NETBSD_SOURCE +# define _NETBSD_SOURCE 1 +#endif +#ifndef __BSD_VISIBLE +# define __BSD_VISIBLE 1 +#endif + #include #include "qprocess_p.h" -- cgit v1.2.3 From 090bf50771ec1e5d089b0ae0488059a5643883b2 Mon Sep 17 00:00:00 2001 From: Raphael Kubo da Costa Date: Sun, 27 Dec 2015 01:24:34 +0100 Subject: forkfd: Only enable pipe2 on FreeBSD >= 10.0. The system call is not present on earlier releases, and since the 9.x series will be supported until the end of 2016, add a check for the __FreeBSD_version macro and only enable pipe2 support if the value is high enough. Change-Id: I5633531cec7e95d42ff5f4b14afe772ae8d7d66d Reviewed-by: Thiago Macieira --- src/3rdparty/forkfd/forkfd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/3rdparty/forkfd/forkfd.c b/src/3rdparty/forkfd/forkfd.c index 099a0ff574..cff717fe0c 100644 --- a/src/3rdparty/forkfd/forkfd.c +++ b/src/3rdparty/forkfd/forkfd.c @@ -64,7 +64,7 @@ # undef HAVE_WAITID #endif -#if defined(__FreeBSD__) +#if defined(__FreeBSD__) && defined(__FreeBSD_version) && __FreeBSD_version >= 1000032 # define HAVE_PIPE2 1 #endif -- cgit v1.2.3 From 55f0343a99ffd920e2e14ba2bb7669d78224fe42 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Tue, 8 Dec 2015 16:14:57 +0200 Subject: Do not discard WSAECONNRESET error code from UDP under Windows When a datagram is sent to a closed host/port combination, the host will likely send back an ICMP error message. In the regular socket API, there isn't a good way of actually receiving this error, so some Windows kernels wired that message back up to the call to WSARecvFrom() as a synthetic datagram. Reading this datagram results in a WSAECONNRESET error code, which should reported to the user as a refused connection attempt. To make the errors a bit more informative, the native error strings for WSAECONNRESET and WSAENETRESET were also added. Task-number: QTBUG-49301 Change-Id: If659be54ba1b39965b5f481f0c0cb9eeea0a06d2 Reviewed-by: Oswald Buddenhagen Reviewed-by: Markus Goetz (Woboq GmbH) --- src/network/socket/qnativesocketengine.cpp | 6 ++++++ src/network/socket/qnativesocketengine_p.h | 2 ++ src/network/socket/qnativesocketengine_win.cpp | 12 +++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qnativesocketengine.cpp b/src/network/socket/qnativesocketengine.cpp index 386e0e2cc7..dfece60036 100644 --- a/src/network/socket/qnativesocketengine.cpp +++ b/src/network/socket/qnativesocketengine.cpp @@ -275,6 +275,12 @@ void QNativeSocketEnginePrivate::setError(QAbstractSocket::SocketError error, Er case TemporaryErrorString: socketErrorString = QNativeSocketEngine::tr("Temporary error"); break; + case NetworkDroppedConnectionErrorString: + socketErrorString = QNativeSocketEngine::tr("Network dropped connection on reset"); + break; + case ConnectionResetErrorString: + socketErrorString = QNativeSocketEngine::tr("Connection reset by peer"); + break; case UnknownSocketErrorString: socketErrorString = QNativeSocketEngine::tr("Unknown error"); break; diff --git a/src/network/socket/qnativesocketengine_p.h b/src/network/socket/qnativesocketengine_p.h index c49ef2c3ad..e540b47069 100644 --- a/src/network/socket/qnativesocketengine_p.h +++ b/src/network/socket/qnativesocketengine_p.h @@ -229,6 +229,8 @@ public: NotSocketErrorString, InvalidProxyTypeString, TemporaryErrorString, + NetworkDroppedConnectionErrorString, + ConnectionResetErrorString, UnknownSocketErrorString = -1 }; diff --git a/src/network/socket/qnativesocketengine_win.cpp b/src/network/socket/qnativesocketengine_win.cpp index 708be2dea7..d673d3a15e 100644 --- a/src/network/socket/qnativesocketengine_win.cpp +++ b/src/network/socket/qnativesocketengine_win.cpp @@ -1250,7 +1250,17 @@ qint64 QNativeSocketEnginePrivate::nativeReceiveDatagram(char *data, qint64 maxL ret = qint64(bytesRead) > maxLength ? maxLength : qint64(bytesRead); } else { WS_ERROR_DEBUG(err); - setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); + switch (err) { + case WSAENETRESET: + setError(QAbstractSocket::NetworkError, NetworkDroppedConnectionErrorString); + break; + case WSAECONNRESET: + setError(QAbstractSocket::ConnectionRefusedError, ConnectionResetErrorString); + break; + default: + setError(QAbstractSocket::NetworkError, ReceiveDatagramErrorString); + break; + } ret = -1; } } else { -- cgit v1.2.3 From 4829edfa4ec4829c25246c46d3fcf236e6e59657 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 4 Jan 2016 19:43:00 +0100 Subject: QTreeView: take into account the min/max size of the header view MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Mimicking what QTableView is already doing correctly, the header's height needs to be constrained by its own minimum/maximum height. Task-number: QTBUG-49277 Change-Id: I695a4398991b738c4b4c924716176b9ad2152e87 Reviewed-by: Thorbjørn Lund Martsum Reviewed-by: David Faure --- src/widgets/itemviews/qtreeview.cpp | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/widgets/itemviews/qtreeview.cpp b/src/widgets/itemviews/qtreeview.cpp index 57092a7cdc..0ccb989198 100644 --- a/src/widgets/itemviews/qtreeview.cpp +++ b/src/widgets/itemviews/qtreeview.cpp @@ -2830,10 +2830,14 @@ void QTreeView::updateGeometries() if (d->geometryRecursionBlock) return; d->geometryRecursionBlock = true; - QSize hint = d->header->isHidden() ? QSize(0, 0) : d->header->sizeHint(); - setViewportMargins(0, hint.height(), 0, 0); + int height = 0; + if (!d->header->isHidden()) { + height = qMax(d->header->minimumHeight(), d->header->sizeHint().height()); + height = qMin(height, d->header->maximumHeight()); + } + setViewportMargins(0, height, 0, 0); QRect vg = d->viewport->geometry(); - QRect geometryRect(vg.left(), vg.top() - hint.height(), vg.width(), hint.height()); + QRect geometryRect(vg.left(), vg.top() - height, vg.width(), height); d->header->setGeometry(geometryRect); QMetaObject::invokeMethod(d->header, "updateGeometries"); d->updateScrollBars(); -- cgit v1.2.3 From 38c8af7231823429ca6cb9ea6418e2dcef3691a0 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 22 Dec 2015 17:15:57 +0100 Subject: Revert "Fix global coordinate mapping for child widgets in QGraphicsView." This reverts commit 56aad2ad6074237537fecf10d0cda0f3872e7f71. QWidget::mapFromGlobal() does not work correctly when the widget is a child widget of another widget embedded into a QGraphicsView with a transformation (scaling/rotation). It starts applying offsets going up the widget tree (just as mapToGlobal) until it hits the embedded widget not taking into account the transformation. It would need to go in from to top to bottom or better be reimplemented such that a QTransform for mapping coordinates from/to global is determined which is then applied in reverse. Task-number: QTBUG-50030 Task-number: QTBUG-50136 Change-Id: Iadeb891d793be1938c64942bfbf38d541a281c33 Reviewed-by: Marc Mutz --- src/widgets/kernel/qwidget.cpp | 46 +++++++++++----------- .../tst_qgraphicsproxywidget.cpp | 8 +++- 2 files changed, 29 insertions(+), 25 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 7c3c4fe8da..7136714d39 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -12305,21 +12305,20 @@ QPaintEngine *QWidget::paintEngine() const */ QPoint QWidget::mapToGlobal(const QPoint &pos) const { - int x = pos.x(), y = pos.y(); - const QWidget *w = this; - while (w) { #ifndef QT_NO_GRAPHICSVIEW - const QWidgetPrivate *d = w->d_func(); - if (d->extra && d->extra->proxyWidget && d->extra->proxyWidget->scene()) { - const QList views = d->extra->proxyWidget->scene()->views(); - if (!views.isEmpty()) { - const QPointF scenePos = d->extra->proxyWidget->mapToScene(QPoint(x, y)); - const QPoint viewPortPos = views.first()->mapFromScene(scenePos); - return views.first()->viewport()->mapToGlobal(viewPortPos); - } + Q_D(const QWidget); + if (d->extra && d->extra->proxyWidget && d->extra->proxyWidget->scene()) { + const QList views = d->extra->proxyWidget->scene()->views(); + if (!views.isEmpty()) { + const QPointF scenePos = d->extra->proxyWidget->mapToScene(pos); + const QPoint viewPortPos = views.first()->mapFromScene(scenePos); + return views.first()->viewport()->mapToGlobal(viewPortPos); } + } #endif // !QT_NO_GRAPHICSVIEW - + int x = pos.x(), y = pos.y(); + const QWidget *w = this; + while (w) { QWindow *window = w->windowHandle(); if (window && window->handle()) return window->mapToGlobal(QPoint(x, y)); @@ -12341,21 +12340,20 @@ QPoint QWidget::mapToGlobal(const QPoint &pos) const */ QPoint QWidget::mapFromGlobal(const QPoint &pos) const { - int x = pos.x(), y = pos.y(); - const QWidget *w = this; - while (w) { #ifndef QT_NO_GRAPHICSVIEW - const QWidgetPrivate *d = w->d_func(); - if (d->extra && d->extra->proxyWidget && d->extra->proxyWidget->scene()) { - const QList views = d->extra->proxyWidget->scene()->views(); - if (!views.isEmpty()) { - const QPoint viewPortPos = views.first()->viewport()->mapFromGlobal(QPoint(x, y)); - const QPointF scenePos = views.first()->mapToScene(viewPortPos); - return d->extra->proxyWidget->mapFromScene(scenePos).toPoint(); - } + Q_D(const QWidget); + if (d->extra && d->extra->proxyWidget && d->extra->proxyWidget->scene()) { + const QList views = d->extra->proxyWidget->scene()->views(); + if (!views.isEmpty()) { + const QPoint viewPortPos = views.first()->viewport()->mapFromGlobal(pos); + const QPointF scenePos = views.first()->mapToScene(viewPortPos); + return d->extra->proxyWidget->mapFromScene(scenePos).toPoint(); } + } #endif // !QT_NO_GRAPHICSVIEW - + int x = pos.x(), y = pos.y(); + const QWidget *w = this; + while (w) { QWindow *window = w->windowHandle(); if (window && window->handle()) return window->mapFromGlobal(QPoint(x, y)); diff --git a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp index cd40c5541c..f3a683fe8b 100644 --- a/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp +++ b/tests/auto/widgets/graphicsview/qgraphicsproxywidget/tst_qgraphicsproxywidget.cpp @@ -3684,6 +3684,7 @@ void tst_QGraphicsProxyWidget::mapToGlobal() // QTBUG-41135 const QSize size = availableGeometry.size() / 5; QGraphicsScene scene; QGraphicsView view(&scene); + view.setTransform(QTransform::fromScale(2, 2)); // QTBUG-50136, use transform. view.setWindowTitle(QTest::currentTestFunction()); view.resize(size); view.move(availableGeometry.bottomRight() - QPoint(size.width(), size.height()) - QPoint(100, 100)); @@ -3706,10 +3707,15 @@ void tst_QGraphicsProxyWidget::mapToGlobal() // QTBUG-41135 QVERIFY2((viewCenter - embeddedCenterGlobal).manhattanLength() <= 2, msgPointMismatch(embeddedCenterGlobal, viewCenter).constData()); - // Same test with child centered on embeddedWidget + // Same test with child centered on embeddedWidget. The correct + // mapping is not implemented yet, but at least make sure + // the roundtrip maptoGlobal()/mapFromGlobal() returns the same + // point since that is important for mouse event handling (QTBUG-50030, + // QTBUG-50136). const QPoint childCenter = childWidget->rect().center(); const QPoint childCenterGlobal = childWidget->mapToGlobal(childCenter); QCOMPARE(childWidget->mapFromGlobal(childCenterGlobal), childCenter); + QEXPECT_FAIL("", "Not implemented for child widgets of embedded widgets", Continue); QVERIFY2((viewCenter - childCenterGlobal).manhattanLength() <= 4, msgPointMismatch(childCenterGlobal, viewCenter).constData()); } -- cgit v1.2.3 From e0a5f661e52fd09611f406ae82128b6ef81fe90e Mon Sep 17 00:00:00 2001 From: Masaru Ueki Date: Sat, 26 Dec 2015 16:01:25 +0900 Subject: QStateMachine: fix ignore high-priority events. When a high-priority event is posted in overrided 'QStateMachine::beginSelectTransitions', the event may be remained in event queue, and be not dispatched until another event posted. Change-Id: Ifda288d9c00ac7985e426b9cc02bda382ebaac35 Reviewed-by: Erik Verbruggen --- src/corelib/statemachine/qstatemachine.cpp | 10 +++++--- .../qstatemachine/tst_qstatemachine.cpp | 29 ++++++++++++++++++++++ 2 files changed, 35 insertions(+), 4 deletions(-) diff --git a/src/corelib/statemachine/qstatemachine.cpp b/src/corelib/statemachine/qstatemachine.cpp index e5d019dc8b..ee522218ee 100644 --- a/src/corelib/statemachine/qstatemachine.cpp +++ b/src/corelib/statemachine/qstatemachine.cpp @@ -1946,12 +1946,14 @@ void QStateMachinePrivate::_q_process() } } if (enabledTransitions.isEmpty()) { - processing = false; - stopProcessingReason = EventQueueEmpty; - noMicrostep(); + if (isInternalEventQueueEmpty()) { + processing = false; + stopProcessingReason = EventQueueEmpty; + noMicrostep(); #ifdef QSTATEMACHINE_DEBUG - qDebug() << q << ": no transitions enabled"; + qDebug() << q << ": no transitions enabled"; #endif + } } else { didChange = true; q->beginMicrostep(e); diff --git a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp index 1292c3b98f..e60b1c983c 100644 --- a/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp +++ b/tests/auto/corelib/statemachine/qstatemachine/tst_qstatemachine.cpp @@ -250,6 +250,7 @@ private slots: void internalTransition(); void conflictingTransition(); void qtbug_46059(); + void postEventFromBeginSelectTransitions(); }; class TestState : public QState @@ -6485,5 +6486,33 @@ void tst_QStateMachine::qtbug_46059() QVERIFY(machine.isRunning()); } +void tst_QStateMachine::postEventFromBeginSelectTransitions() +{ + class StateMachine : public QStateMachine { + protected: + void beginSelectTransitions(QEvent* e) Q_DECL_OVERRIDE { + if (e->type() == QEvent::Type(QEvent::User + 2)) + postEvent(new QEvent(QEvent::Type(QEvent::User + 1)), QStateMachine::HighPriority); + } + } machine; + QState a(&machine); + QState success(&machine); + + machine.setInitialState(&a); + a.addTransition(new EventTransition(QEvent::Type(QEvent::User + 1), &success)); + + machine.start(); + + QTRY_COMPARE(machine.configuration().contains(&a), true); + QTRY_COMPARE(machine.configuration().contains(&success), false); + + machine.postEvent(new QEvent(QEvent::Type(QEvent::User + 2)), QStateMachine::NormalPriority); + + QTRY_COMPARE(machine.configuration().contains(&a), false); + QTRY_COMPARE(machine.configuration().contains(&success), true); + + QVERIFY(machine.isRunning()); +} + QTEST_MAIN(tst_QStateMachine) #include "tst_qstatemachine.moc" -- cgit v1.2.3 From 02f70004c266f4c35f098f49cfb3ca0284e28cac Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sat, 5 Dec 2015 23:55:17 +0200 Subject: Allow socket events processing with a foreign event loop on Windows While a native dialog is open, the application message queue is handled by the native event loop which is external to Qt. In this case, QEventDispatcherWin32::processEvents() does not run and socket notifiers will not be activated. So, this patch moves the notifier activation code into the window procedure, which enables socket event processing with native dialogs. Task-number: QTBUG-49782 Task-number: QTBUG-48901 Change-Id: Icbdd96b2e80c50b73505f4fe74957575b83d6cf1 Reviewed-by: Oswald Buddenhagen Reviewed-by: Kai Koehne Reviewed-by: Joerg Bornemann --- src/corelib/kernel/qeventdispatcher_win.cpp | 44 +++++++++++++++------- src/corelib/kernel/qeventdispatcher_win_p.h | 2 + tests/auto/gui/kernel/kernel.pro | 2 +- .../gui/kernel/noqteventloop/noqteventloop.pro | 2 +- .../gui/kernel/noqteventloop/tst_noqteventloop.cpp | 34 +++++++++++++++++ 5 files changed, 69 insertions(+), 15 deletions(-) diff --git a/src/corelib/kernel/qeventdispatcher_win.cpp b/src/corelib/kernel/qeventdispatcher_win.cpp index 695eb3d5d0..812494372d 100644 --- a/src/corelib/kernel/qeventdispatcher_win.cpp +++ b/src/corelib/kernel/qeventdispatcher_win.cpp @@ -79,6 +79,7 @@ extern uint qGlobalPostedEventsCount(); enum { WM_QT_SOCKETNOTIFIER = WM_USER, WM_QT_SENDPOSTEDEVENTS = WM_USER + 1, + WM_QT_ACTIVATENOTIFIERS = WM_USER + 2, SendPostedEventsWindowsTimerId = ~1u }; @@ -309,7 +310,7 @@ static void resolveTimerAPI() QEventDispatcherWin32Private::QEventDispatcherWin32Private() : threadId(GetCurrentThreadId()), interrupt(false), closingDown(false), internalHwnd(0), getMessageHook(0), serialNumber(0), lastSerialNumber(0), sendPostedEventsWindowsTimerId(0), - wakeUps(0) + wakeUps(0), activateNotifiersPosted(false) { resolveTimerAPI(); } @@ -393,6 +394,7 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA if (sn) { d->doWsaAsyncSelect(sn->fd, 0); d->active_fd[sn->fd].selected = false; + d->postActivateSocketNotifiers(); if (type < 3) { QEvent event(QEvent::SockAct); QCoreApplication::sendEvent(sn->obj, &event); @@ -403,6 +405,20 @@ LRESULT QT_WIN_CALLBACK qt_internal_proc(HWND hwnd, UINT message, WPARAM wp, LPA } } return 0; + } else if (message == WM_QT_ACTIVATENOTIFIERS) { + Q_ASSERT(d != 0); + + // register all socket notifiers + for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end(); + it != end; ++it) { + QSockFd &sd = it.value(); + if (!sd.selected) { + d->doWsaAsyncSelect(it.key(), sd.event); + sd.selected = true; + } + } + d->activateNotifiersPosted = false; + return 0; } else if (message == WM_QT_SENDPOSTEDEVENTS // we also use a Windows timer to send posted events when the message queue is full || (message == WM_TIMER @@ -643,6 +659,12 @@ void QEventDispatcherWin32Private::doWsaAsyncSelect(int socket, long event) WSAAsyncSelect(socket, internalHwnd, event ? int(WM_QT_SOCKETNOTIFIER) : 0, event); } +void QEventDispatcherWin32Private::postActivateSocketNotifiers() +{ + if (!activateNotifiersPosted) + activateNotifiersPosted = PostMessage(internalHwnd, WM_QT_ACTIVATENOTIFIERS, 0, 0); +} + void QEventDispatcherWin32::createInternalHwnd() { Q_D(QEventDispatcherWin32); @@ -761,16 +783,6 @@ bool QEventDispatcherWin32::processEvents(QEventLoop::ProcessEventsFlags flags) d->queuedSocketEvents.append(msg); continue; } - } else if (!(flags & QEventLoop::ExcludeSocketNotifiers)) { - // register all socket notifiers - for (QSFDict::iterator it = d->active_fd.begin(), end = d->active_fd.end(); - it != end; ++it) { - QSockFd &sd = it.value(); - if (!sd.selected) { - d->doWsaAsyncSelect(it.key(), sd.event); - sd.selected = true; - } - } } } if (!haveMessage) { @@ -891,6 +903,8 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) "same socket %d and type %s", sockfd, t[type]); } + createInternalHwnd(); + QSockNot *sn = new QSockNot; sn->obj = notifier; sn->fd = sockfd; @@ -915,6 +929,8 @@ void QEventDispatcherWin32::registerSocketNotifier(QSocketNotifier *notifier) } else { d->active_fd.insert(sockfd, QSockFd(event)); } + + d->postActivateSocketNotifiers(); } void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) @@ -940,10 +956,12 @@ void QEventDispatcherWin32::unregisterSocketNotifier(QSocketNotifier *notifier) d->doWsaAsyncSelect(sockfd, 0); const long event[3] = { FD_READ | FD_CLOSE | FD_ACCEPT, FD_WRITE | FD_CONNECT, FD_OOB }; sd.event ^= event[type]; - if (sd.event == 0) + if (sd.event == 0) { d->active_fd.erase(it); - else + } else if (sd.selected) { sd.selected = false; + d->postActivateSocketNotifiers(); + } } QSNDict *sn_vec[3] = { &d->sn_read, &d->sn_write, &d->sn_except }; diff --git a/src/corelib/kernel/qeventdispatcher_win_p.h b/src/corelib/kernel/qeventdispatcher_win_p.h index 8578110ee4..9a53e06730 100644 --- a/src/corelib/kernel/qeventdispatcher_win_p.h +++ b/src/corelib/kernel/qeventdispatcher_win_p.h @@ -178,7 +178,9 @@ public: QSNDict sn_write; QSNDict sn_except; QSFDict active_fd; + bool activateNotifiersPosted; void doWsaAsyncSelect(int socket, long event); + void postActivateSocketNotifiers(); QList winEventNotifierList; void activateEventNotifier(QWinEventNotifier * wen); diff --git a/tests/auto/gui/kernel/kernel.pro b/tests/auto/gui/kernel/kernel.pro index b03a117f83..5254e755d4 100644 --- a/tests/auto/gui/kernel/kernel.pro +++ b/tests/auto/gui/kernel/kernel.pro @@ -24,7 +24,7 @@ SUBDIRS=\ qopenglwindow \ qrasterwindow -win32:!wince*:!winrt: SUBDIRS += noqteventloop +win32:!wince:!winrt:qtHaveModule(network): SUBDIRS += noqteventloop !qtHaveModule(widgets): SUBDIRS -= \ qmouseevent_modal \ diff --git a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro index de5715e147..a42b359f29 100644 --- a/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro +++ b/tests/auto/gui/kernel/noqteventloop/noqteventloop.pro @@ -1,7 +1,7 @@ CONFIG += testcase TARGET = tst_noqteventloop -QT += core-private gui-private testlib +QT += core-private network gui-private testlib SOURCES += tst_noqteventloop.cpp diff --git a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp index d21569dcc0..735d23b137 100644 --- a/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp +++ b/tests/auto/gui/kernel/noqteventloop/tst_noqteventloop.cpp @@ -36,6 +36,9 @@ #include #include #include +#include +#include +#include #include @@ -47,6 +50,7 @@ private slots: void initTestCase(); void cleanup(); void consumeMouseEvents(); + void consumeSocketEvents(); }; @@ -265,6 +269,36 @@ void tst_NoQtEventLoop::consumeMouseEvents() } +void tst_NoQtEventLoop::consumeSocketEvents() +{ + int argc = 1; + char *argv[] = { const_cast("test"), 0 }; + QGuiApplication app(argc, argv); + QTcpServer server; + QTcpSocket client; + + QVERIFY(server.listen(QHostAddress::LocalHost)); + client.connectToHost(server.serverAddress(), server.serverPort()); + QVERIFY(client.waitForConnected()); + + QElapsedTimer elapsedTimer; + elapsedTimer.start(); + + // Exec own message loop + MSG msg; + forever { + if (elapsedTimer.hasExpired(3000) || server.hasPendingConnections()) + break; + + if (::PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) { + ::TranslateMessage(&msg); + ::DispatchMessage(&msg); + } + } + + QVERIFY(server.hasPendingConnections()); +} + #include QTEST_APPLESS_MAIN(tst_NoQtEventLoop) -- cgit v1.2.3 From 7e876bfcf747c9b81a91c5e6bf1e1f84d9aeb7e6 Mon Sep 17 00:00:00 2001 From: Dmitry Shachnev Date: Sat, 2 Jan 2016 18:29:15 +0300 Subject: qt_functions.prf: Add missing $$eval Change-Id: I3d60617bdc887447f433c47ac6af3c1e13756c28 Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt_functions.prf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index a1c499610b..0468c51f81 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -291,7 +291,7 @@ defineTest(qtAddTargetEnv) { pluginpath.value = ppaths = $$[QT_INSTALL_PLUGINS/get] for(qplug, QT_PLUGINS): \ - contains(ptypes, QT_PLUGIN.$${qplug}.TYPE): \ + contains(ptypes, $$eval(QT_PLUGIN.$${qplug}.TYPE)): \ ppaths += $$eval(QT_PLUGIN.$${qplug}.PATH) ppaths = $$unique(ppaths) for(qplug, ppaths) { -- cgit v1.2.3 From 4f48c3a309a6b055ef5293e9d6c1a9a442eb65e2 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Tue, 29 Dec 2015 16:34:18 +0100 Subject: Add missing qxml_p.h to src/xml/sax/sax.pri Change-Id: I32acaebd53d8bee23f509ed404e360c1004f4a58 Reviewed-by: Friedemann Kleint --- src/xml/sax/sax.pri | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xml/sax/sax.pri b/src/xml/sax/sax.pri index 65916271bd..5793996898 100644 --- a/src/xml/sax/sax.pri +++ b/src/xml/sax/sax.pri @@ -1,2 +1,3 @@ SOURCES += $$PWD/qxml.cpp -HEADERS += $$PWD/qxml.h +HEADERS += $$PWD/qxml_p.h \ + $$PWD/qxml.h -- cgit v1.2.3 From 033205bb598fe49e6ca4c90fb4e046e996c20252 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 12:51:02 +0100 Subject: Fix UB in tst_QIODevice::getSetCheck() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The reinterpret cast from a QTcpSocket → QAbstractSocket → QIODevice to MyIODevice → QIODevice was undefined. Fix by simply instantiating a MyIODevice, which must then inherit from QTcpSocket, of course. Instead of fixing the class name in the overridden setOpenMode() method, simply make the base class' implementation public with a using declaration. Found by UBSan: qtbase/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp:84:22: runtime error: member call on address 0x7ffcca2d23f0 which does not point to an object of type 'MyIODevice' 0x7ffcca2d23f0: note: object is of type 'QTcpSocket' Change-Id: I939b3548949b9b5765df4a6cc81875e169fd69dd Reviewed-by: Alex Trotsenko Reviewed-by: Olivier Goffart (Woboq GmbH) --- tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) diff --git a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp index 565ca18899..af79de06d5 100644 --- a/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp +++ b/tests/auto/corelib/io/qiodevice/tst_qiodevice.cpp @@ -74,16 +74,15 @@ void tst_QIODevice::getSetCheck() { // OpenMode QIODevice::openMode() // void QIODevice::setOpenMode(OpenMode) - class MyIODevice : public QIODevice { + class MyIODevice : public QTcpSocket { public: - void setOpenMode(OpenMode openMode) { QIODevice::setOpenMode(openMode); } + using QTcpSocket::setOpenMode; }; - QTcpSocket var1; - MyIODevice *obj1 = reinterpret_cast(&var1); - obj1->setOpenMode(QIODevice::OpenMode(QIODevice::NotOpen)); - QCOMPARE(QIODevice::OpenMode(QIODevice::NotOpen), obj1->openMode()); - obj1->setOpenMode(QIODevice::OpenMode(QIODevice::ReadWrite)); - QCOMPARE(QIODevice::OpenMode(QIODevice::ReadWrite), obj1->openMode()); + MyIODevice var1; + var1.setOpenMode(QIODevice::OpenMode(QIODevice::NotOpen)); + QCOMPARE(QIODevice::OpenMode(QIODevice::NotOpen), var1.openMode()); + var1.setOpenMode(QIODevice::OpenMode(QIODevice::ReadWrite)); + QCOMPARE(QIODevice::OpenMode(QIODevice::ReadWrite), var1.openMode()); } //---------------------------------------------------------------------------------- -- cgit v1.2.3 From bccbb70de548c5defcb2ab58a987ef2e966788bc Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 16:56:26 +0100 Subject: Fix UB in tst_QMetaType Don't pass around meta-type IDs in QMetaType::Type variables. It leads to reading values from an enum variable that are invalid. Fix by passing the IDs around as int. Found by UBSan: tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp:408:5: runtime error: load of value 4028, which is not a valid value for type 'Type' Change-Id: Idd106ee3d7960fe3d8fefc0fc5830fc22d38a513 Reviewed-by: Olivier Goffart (Woboq GmbH) --- .../corelib/kernel/qmetatype/tst_qmetatype.cpp | 86 +++++++++++----------- 1 file changed, 43 insertions(+), 43 deletions(-) diff --git a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp index 9cdb1f47f8..a4bfc8ac9b 100644 --- a/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp +++ b/tests/auto/corelib/kernel/qmetatype/tst_qmetatype.cpp @@ -369,40 +369,40 @@ void tst_QMetaType::normalizedTypes() } #define TYPENAME_DATA(MetaTypeName, MetaTypeId, RealType)\ - QTest::newRow(#RealType) << QMetaType::MetaTypeName << #RealType; + QTest::newRow(#RealType) << int(QMetaType::MetaTypeName) << #RealType; void tst_QMetaType::typeName_data() { - QTest::addColumn("aType"); + QTest::addColumn("aType"); QTest::addColumn("aTypeName"); QT_FOR_EACH_STATIC_TYPE(TYPENAME_DATA) - QTest::newRow("QMetaType::UnknownType") << QMetaType::UnknownType << static_cast(0); + QTest::newRow("QMetaType::UnknownType") << int(QMetaType::UnknownType) << static_cast(0); - QTest::newRow("Whity") << static_cast(::qMetaTypeId >()) << QString::fromLatin1("Whity"); - QTest::newRow("Whity") << static_cast(::qMetaTypeId >()) << QString::fromLatin1("Whity"); - QTest::newRow("Testspace::Foo") << static_cast(::qMetaTypeId()) << QString::fromLatin1("TestSpace::Foo"); + QTest::newRow("Whity") << ::qMetaTypeId >() << QString::fromLatin1("Whity"); + QTest::newRow("Whity") << ::qMetaTypeId >() << QString::fromLatin1("Whity"); + QTest::newRow("Testspace::Foo") << ::qMetaTypeId() << QString::fromLatin1("TestSpace::Foo"); - QTest::newRow("-1") << QMetaType::Type(-1) << QString(); - QTest::newRow("-124125534") << QMetaType::Type(-124125534) << QString(); - QTest::newRow("124125534") << QMetaType::Type(124125534) << QString(); + QTest::newRow("-1") << -1 << QString(); + QTest::newRow("-124125534") << -124125534 << QString(); + QTest::newRow("124125534") << 124125534 << QString(); // automatic registration - QTest::newRow("QList") << static_cast(::qMetaTypeId >()) << QString::fromLatin1("QList"); - QTest::newRow("QHash") << static_cast(::qMetaTypeId >()) << QString::fromLatin1("QHash"); - QTest::newRow("QMap") << static_cast(::qMetaTypeId >()) << QString::fromLatin1("QMap"); - QTest::newRow("QVector>") << static_cast(::qMetaTypeId > >()) << QString::fromLatin1("QVector >"); - QTest::newRow("QVector>") << static_cast(::qMetaTypeId > >()) << QString::fromLatin1("QVector >"); + QTest::newRow("QList") << ::qMetaTypeId >() << QString::fromLatin1("QList"); + QTest::newRow("QHash") << ::qMetaTypeId >() << QString::fromLatin1("QHash"); + QTest::newRow("QMap") << ::qMetaTypeId >() << QString::fromLatin1("QMap"); + QTest::newRow("QVector>") << ::qMetaTypeId > >() << QString::fromLatin1("QVector >"); + QTest::newRow("QVector>") << ::qMetaTypeId > >() << QString::fromLatin1("QVector >"); - QTest::newRow("CustomQObject*") << static_cast(::qMetaTypeId()) << QString::fromLatin1("CustomQObject*"); - QTest::newRow("CustomGadget") << static_cast(::qMetaTypeId()) << QString::fromLatin1("CustomGadget"); - QTest::newRow("CustomQObject::CustomQEnum") << static_cast(::qMetaTypeId()) << QString::fromLatin1("CustomQObject::CustomQEnum"); - QTest::newRow("Qt::ArrowType") << static_cast(::qMetaTypeId()) << QString::fromLatin1("Qt::ArrowType"); + QTest::newRow("CustomQObject*") << ::qMetaTypeId() << QString::fromLatin1("CustomQObject*"); + QTest::newRow("CustomGadget") << ::qMetaTypeId() << QString::fromLatin1("CustomGadget"); + QTest::newRow("CustomQObject::CustomQEnum") << ::qMetaTypeId() << QString::fromLatin1("CustomQObject::CustomQEnum"); + QTest::newRow("Qt::ArrowType") << ::qMetaTypeId() << QString::fromLatin1("Qt::ArrowType"); } void tst_QMetaType::typeName() { - QFETCH(QMetaType::Type, aType); + QFETCH(int, aType); QFETCH(QString, aTypeName); QString name = QString::fromLatin1(QMetaType::typeName(aType)); @@ -413,15 +413,15 @@ void tst_QMetaType::typeName() void tst_QMetaType::type_data() { - QTest::addColumn("aType"); + QTest::addColumn("aType"); QTest::addColumn("aTypeName"); #define TST_QMETATYPE_TYPE_DATA(MetaTypeName, MetaTypeId, RealType)\ - QTest::newRow(#RealType) << QMetaType::MetaTypeName << QByteArray( #RealType ); + QTest::newRow(#RealType) << int(QMetaType::MetaTypeName) << QByteArray( #RealType ); #define TST_QMETATYPE_TYPE_DATA_ALIAS(MetaTypeName, MetaTypeId, AliasType, RealTypeString)\ - QTest::newRow(RealTypeString) << QMetaType::MetaTypeName << QByteArray( #AliasType ); + QTest::newRow(RealTypeString) << int(QMetaType::MetaTypeName) << QByteArray( #AliasType ); - QTest::newRow("empty") << QMetaType::UnknownType << QByteArray(); + QTest::newRow("empty") << int(QMetaType::UnknownType) << QByteArray(); QT_FOR_EACH_STATIC_TYPE(TST_QMETATYPE_TYPE_DATA) QT_FOR_EACH_STATIC_ALIAS_TYPE(TST_QMETATYPE_TYPE_DATA_ALIAS) @@ -432,13 +432,13 @@ void tst_QMetaType::type_data() void tst_QMetaType::type() { - QFETCH(QMetaType::Type, aType); + QFETCH(int, aType); QFETCH(QByteArray, aTypeName); // QMetaType::type(QByteArray) - QCOMPARE(QMetaType::type(aTypeName), int(aType)); + QCOMPARE(QMetaType::type(aTypeName), aType); // QMetaType::type(const char *) - QCOMPARE(QMetaType::type(aTypeName.constData()), int(aType)); + QCOMPARE(QMetaType::type(aTypeName.constData()), aType); } void tst_QMetaType::type_fromSubString_data() @@ -727,9 +727,9 @@ template<> struct TestValueFactory { void tst_QMetaType::create_data() { - QTest::addColumn("type"); + QTest::addColumn("type"); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ - QTest::newRow(QMetaType::typeName(QMetaType::MetaTypeName)) << QMetaType::MetaTypeName; + QTest::newRow(QMetaType::typeName(QMetaType::MetaTypeName)) << int(QMetaType::MetaTypeName); FOR_EACH_CORE_METATYPE(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW } @@ -781,7 +781,7 @@ FOR_EACH_CORE_METATYPE(RETURN_CREATE_FUNCTION) } }; - QFETCH(QMetaType::Type, type); + QFETCH(int, type); TypeTestFunctionGetter::get(type)(); } @@ -832,33 +832,33 @@ FOR_EACH_CORE_METATYPE(RETURN_CREATE_COPY_FUNCTION) } }; - QFETCH(QMetaType::Type, type); + QFETCH(int, type); TypeTestFunctionGetter::get(type)(); } void tst_QMetaType::sizeOf_data() { - QTest::addColumn("type"); + QTest::addColumn("type"); QTest::addColumn("size"); - QTest::newRow("QMetaType::UnknownType") << QMetaType::UnknownType << size_t(0); + QTest::newRow("QMetaType::UnknownType") << int(QMetaType::UnknownType) << size_t(0); #define ADD_METATYPE_TEST_ROW(MetaTypeName, MetaTypeId, RealType) \ - QTest::newRow(#RealType) << QMetaType::MetaTypeName << size_t(QTypeInfo::sizeOf); + QTest::newRow(#RealType) << int(QMetaType::MetaTypeName) << size_t(QTypeInfo::sizeOf); FOR_EACH_CORE_METATYPE(ADD_METATYPE_TEST_ROW) #undef ADD_METATYPE_TEST_ROW - QTest::newRow("Whity") << static_cast(::qMetaTypeId >()) << sizeof(Whity); -QTest::newRow("Whity") << static_cast(::qMetaTypeId >()) << sizeof(Whity); - QTest::newRow("Testspace::Foo") << static_cast(::qMetaTypeId()) << sizeof(TestSpace::Foo); + QTest::newRow("Whity") << ::qMetaTypeId >() << sizeof(Whity); + QTest::newRow("Whity") << ::qMetaTypeId >() << sizeof(Whity); + QTest::newRow("Testspace::Foo") << ::qMetaTypeId() << sizeof(TestSpace::Foo); - QTest::newRow("-1") << QMetaType::Type(-1) << size_t(0); - QTest::newRow("-124125534") << QMetaType::Type(-124125534) << size_t(0); - QTest::newRow("124125534") << QMetaType::Type(124125534) << size_t(0); + QTest::newRow("-1") << -1 << size_t(0); + QTest::newRow("-124125534") << -124125534 << size_t(0); + QTest::newRow("124125534") << 124125534 << size_t(0); } void tst_QMetaType::sizeOf() { - QFETCH(QMetaType::Type, type); + QFETCH(int, type); QFETCH(size_t, size); QCOMPARE(size_t(QMetaType::sizeOf(type)), size); } @@ -870,7 +870,7 @@ void tst_QMetaType::sizeOfStaticLess_data() void tst_QMetaType::sizeOfStaticLess() { - QFETCH(QMetaType::Type, type); + QFETCH(int, type); QFETCH(size_t, size); QCOMPARE(size_t(QMetaType(type).sizeOf()), size); } @@ -1126,7 +1126,7 @@ FOR_EACH_CORE_METATYPE(RETURN_CONSTRUCT_FUNCTION) } }; - QFETCH(QMetaType::Type, type); + QFETCH(int, type); TypeTestFunctionGetter::get(type)(); } @@ -1194,7 +1194,7 @@ FOR_EACH_CORE_METATYPE(RETURN_CONSTRUCT_COPY_FUNCTION) } }; - QFETCH(QMetaType::Type, type); + QFETCH(int, type); TypeTestFunctionGetter::get(type)(); } -- cgit v1.2.3 From f5291bf8b4f74e7dcaa4911594fae8c929e28229 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 17:46:11 +0100 Subject: Fix UB in tst_QObject::noDeclarativeParentChangedOnDestruction() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit If QObjectPrivate::declarativeData is set, it is in various places in Qt expected to point to a QAbstractDeclarativeDataImpl, from which ownedByQml1 is unconditionally read. In noDeclarativeParentChangedOnDestruction(), the declarativeData pointer is, however, set to a local QAbstractDeclarativeData instance, which, being an empty class, has size 1 and alignment 1. Depending on the compiler's idea of bit field order, this code either read uninitialized data from the dummy object, or else some random stack memory outside any (valid) object. What caught UBSan's attention, though, was the difference in alignment between the two classes: src/corelib/kernel/qobject.cpp:917:9: runtime error: member access within misaligned address 0x7fffc9cf706f for type 'struct QAbstractDeclarativeDataImpl', which requires 4 byte alignment Fix by providing a properly initialized object of the correct type. Change-Id: Iae83a949ee5a7bc98df13e35ea614c063085fa13 Reviewed-by: Lars Knoll Reviewed-by: Jędrzej Nowacki Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Oswald Buddenhagen --- tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index 4617ce5e74..aa6ab31065 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -6396,7 +6396,8 @@ void tst_QObject::noDeclarativeParentChangedOnDestruction() QObject *parent = new QObject; QObject *child = new QObject; - QAbstractDeclarativeData dummy; + QAbstractDeclarativeDataImpl dummy; + dummy.ownedByQml1 = false; QObjectPrivate::get(child)->declarativeData = &dummy; parentChangeCalled = false; -- cgit v1.2.3 From 9c7be0a7ec92a28d5d489fb78c500dad3f01d9ec Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 23:10:12 +0100 Subject: Fix UB in tst_QDialog::showExtension() Don't cast a QDialog to a subclass it is not. Fix by creating it as the required subclass in the first place. Found by UBSan: tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp:203:20: runtime error: downcast of address 0x2b5f5000ad40 which does not point to an object of type 'DummyDialog' tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp:203:46: runtime error: member call on address 0x2b5f5000ad40 which does not point to an object of type 'DummyDialog' Change-Id: I63ae7e782bda6a78d11af5c2bc2f7d88aacd0ac0 Reviewed-by: David Faure Reviewed-by: Lars Knoll --- tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp | 23 +++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp index e62ce3ceb5..a23938959b 100644 --- a/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp +++ b/tests/auto/widgets/dialogs/qdialog/tst_qdialog.cpp @@ -49,6 +49,14 @@ QT_FORWARD_DECLARE_CLASS(QDialog) +// work around function being protected +class DummyDialog : public QDialog +{ +public: + DummyDialog(): QDialog(0, Qt::X11BypassWindowManagerHint) {} + using QDialog::showExtension; +}; + class tst_QDialog : public QObject { Q_OBJECT @@ -82,7 +90,7 @@ private slots: void transientParent(); private: - QDialog *testWidget; + DummyDialog *testWidget; }; // Testing get/set functions @@ -108,13 +116,6 @@ void tst_QDialog::getSetCheck() QCOMPARE(INT_MAX, obj1.result()); } -// work around function being protected -class DummyDialog : public QDialog { -public: - DummyDialog(): QDialog(0) {} - void showExtension( bool b ) { QDialog::showExtension( b ); } -}; - class ToolDialog : public QDialog { public: @@ -148,7 +149,7 @@ tst_QDialog::tst_QDialog() void tst_QDialog::initTestCase() { // Create the test class - testWidget = new QDialog(0, Qt::X11BypassWindowManagerHint); + testWidget = new DummyDialog; testWidget->resize(200,200); testWidget->show(); qApp->setActiveWindow(testWidget); @@ -193,7 +194,7 @@ void tst_QDialog::showExtension() QPoint oldPosition = testWidget->pos(); // show - ((DummyDialog*)testWidget)->showExtension( true ); + testWidget->showExtension( true ); // while ( testWidget->size() == dlgSize ) // qApp->processEvents(); @@ -202,7 +203,7 @@ void tst_QDialog::showExtension() QCOMPARE(testWidget->pos(), oldPosition); // hide extension. back to old size ? - ((DummyDialog*)testWidget)->showExtension( false ); + testWidget->showExtension( false ); QCOMPARE( testWidget->size(), dlgSize ); testWidget->setExtension( 0 ); -- cgit v1.2.3 From c38b14e2519a2bdbd835e52ee699ae9ac3f45d00 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 23:17:03 +0100 Subject: Fix UB in tst_QSharedPointer::basics() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Binding a reference to the nullptr is undefined behavior. Just skip that particular test when 'ptr' is null. Found by UBSan: tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp:258:32: runtime error: reference binding to null pointer of type 'struct Data' Change-Id: I125588b9d269a6f76716d660d03142f409513885 Reviewed-by: Jędrzej Nowacki Reviewed-by: Lars Knoll Reviewed-by: Olivier Goffart (Woboq GmbH) --- tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp index 7741803224..7538eaf378 100644 --- a/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp +++ b/tests/auto/corelib/tools/qsharedpointer/tst_qsharedpointer.cpp @@ -246,8 +246,10 @@ void tst_QSharedPointer::basics() QCOMPARE(ptr.data(), aData); QCOMPARE(ptr.operator->(), aData); - Data &dataReference = *ptr; - QCOMPARE(&dataReference, aData); + if (!isNull) { + Data &dataReference = *ptr; + QCOMPARE(&dataReference, aData); + } QVERIFY(ptr == aData); QVERIFY(!(ptr != aData)); -- cgit v1.2.3 From 889fcfbf2b97c71146d182277068e7fbdb06587f Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 7 Jan 2016 16:56:39 +0100 Subject: fix quoting in makeabs() 'local' is treated as a command, so its arguments need to be quoted, unlike in a real variable assignment. amends 4b557751e. Change-Id: I5a4c929e52e2344a6129c8e9dd4c0c80cd408ff0 Reviewed-by: Joerg Bornemann --- configure | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/configure b/configure index 61f0ea0bea..254542fc6c 100755 --- a/configure +++ b/configure @@ -126,8 +126,8 @@ shellQuoteLines() makeabs() { - local FILE=$1 - local RES=$FILE + local FILE="$1" + local RES="$FILE" if [ -z "${FILE##/*}" ]; then true elif [ "$OSTYPE" = "msys" -a -z "${FILE##[a-zA-Z]:[/\\]*}" ]; then -- cgit v1.2.3 From 1e2b42523f3a04fc3403ef6864bbcba447e4362c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 17:46:11 +0100 Subject: Fix UB in tst_QObject::disconnectDoesNotLeakFunctor() If CountedStruct is passed a GetSenderObject object, it will attempt to call a member on it from within its own destructor. That works usually quite well, but in this test case, which tests for function object leaks when a connection is torn down because the sender object is destroyed, the destruction of the CountedStruct happens when all connections are severed in ~QObject. At that point, what used to be a GetSenderObject instance no longer is one and the call into one of its member functions invokes undefined behavior. Fix by making QObject::sender() public by a using declaration instead of a wrapper function. Found by UBSan: tests/auto/corelib/kernel/qobject/tst_qobject.cpp:6007:104: runtime error: member call on address 0x7ffc6e7538b0 which does not point to an object of type 'GetSenderObject' 0x7ffc6e7538b0: note: object is of type 'QObject' Change-Id: Ia973140037b3c1b5a670a8a3949d09b956f40349 Reviewed-by: Olivier Goffart (Woboq GmbH) --- tests/auto/corelib/kernel/qobject/tst_qobject.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp index aa6ab31065..5b1dad78cf 100644 --- a/tests/auto/corelib/kernel/qobject/tst_qobject.cpp +++ b/tests/auto/corelib/kernel/qobject/tst_qobject.cpp @@ -5987,7 +5987,7 @@ class GetSenderObject : public QObject { Q_OBJECT public: - QObject *accessSender() { return sender(); } + using QObject::sender; // make public public Q_SLOTS: void triggerSignal() { Q_EMIT aSignal(); } @@ -6003,8 +6003,8 @@ struct CountedStruct CountedStruct(GetSenderObject *sender) : sender(sender) { ++countedStructObjectsCount; } CountedStruct(const CountedStruct &o) : sender(o.sender) { ++countedStructObjectsCount; } CountedStruct &operator=(const CountedStruct &) { return *this; } - // accessSender here allows us to check if there's a deadlock - ~CountedStruct() { --countedStructObjectsCount; if (sender != Q_NULLPTR) (void)sender->accessSender(); } + // calling sender() here allows us to check if there's a deadlock + ~CountedStruct() { --countedStructObjectsCount; if (sender) (void)sender->sender(); } void operator()() const { } GetSenderObject *sender; -- cgit v1.2.3 From c8af3160d2514fb973a0d00d5bac324d4f7159f7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?D=C4=81vis=20Mos=C4=81ns?= Date: Fri, 8 Jan 2016 04:12:13 +0200 Subject: Don't pass NULL Display to glXGetClientString MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit glXGetCurrentDisplay can return NULL so need to check for that. Change-Id: I1b85a5c575d1deb24dcce4719b6f737283adeabe Reviewed-by: Błażej Szczygieł Reviewed-by: Laszlo Agocs --- .../platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 5 ++++- .../platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp | 5 ++++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 8b14fc7d70..3412f3f3fc 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -644,7 +644,10 @@ void QGLXContext::queryDummyContext() oldSurface = oldContext->surface(); QScopedPointer surface; - const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR); + Display *display = glXGetCurrentDisplay(); + const char *glxvendor = 0; + if (display) + glxvendor = glXGetClientString(display, GLX_VENDOR); if (glxvendor && !strcmp(glxvendor, "ATI")) { QWindow *window = new QWindow; window->resize(64, 64); diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index ce72cb64d0..cd4949af5c 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -195,7 +195,10 @@ QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QO static bool glxPbufferUsable = true; if (!vendorChecked) { vendorChecked = true; - const char *glxvendor = glXGetClientString(glXGetCurrentDisplay(), GLX_VENDOR); + Display *display = glXGetCurrentDisplay(); + const char *glxvendor = 0; + if (display) + glxvendor = glXGetClientString(display, GLX_VENDOR); if (glxvendor && !strcmp(glxvendor, "ATI")) glxPbufferUsable = false; } -- cgit v1.2.3 From 71ea41f999c1dbe83cba2491f5ac99d6c5a3d98c Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 13:50:56 +0100 Subject: Fix UB in QVariant::canConvert() MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 'currentType' was not sanitized before being used as a shift. Fix by checking for a valid shift amount before shifting. Also change the shifted value from 1 (int) to 1U (uint). It's just the right thing to do. Found by UBSan: qtbase/src/corelib/kernel/qvariant.cpp:3131:59: runtime error: shift exponent 1114 is too large for 32-bit type 'unsigned int' Change-Id: Id3910d6d7f166fd7c80adf5ce1699f0eeb453562 Reviewed-by: Jędrzej Nowacki Reviewed-by: Thiago Macieira --- src/corelib/kernel/qvariant.cpp | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp index f7a4abbf68..811483d74f 100644 --- a/src/corelib/kernel/qvariant.cpp +++ b/src/corelib/kernel/qvariant.cpp @@ -2891,6 +2891,7 @@ static const quint32 qCanConvertMatrix[QVariant::LastCoreType + 1] = /*QUuid*/ 1 << QVariant::String }; +static const size_t qCanConvertMatrixMaximumTargetType = 8 * sizeof(*qCanConvertMatrix); #ifndef QT_BOOTSTRAPPED /*! @@ -3140,8 +3141,9 @@ bool QVariant::canConvert(int targetTypeId) const case QMetaType::ULong: case QMetaType::Short: case QMetaType::UShort: - return qCanConvertMatrix[QVariant::Int] & (1 << currentType) - || currentType == QVariant::Int + return currentType == QVariant::Int + || (currentType < qCanConvertMatrixMaximumTargetType + && qCanConvertMatrix[QVariant::Int] & (1U << currentType)) || QMetaType::typeFlags(currentType) & QMetaType::IsEnumeration; case QMetaType::QObjectStar: return canConvertMetaObject(currentType, targetTypeId, d.data.o); @@ -3152,7 +3154,8 @@ bool QVariant::canConvert(int targetTypeId) const if (targetTypeId == String && currentType == StringList) return v_cast(&d)->count() == 1; - return qCanConvertMatrix[targetTypeId] & (1 << currentType); + return currentType < qCanConvertMatrixMaximumTargetType + && qCanConvertMatrix[targetTypeId] & (1U << currentType); } /*! -- cgit v1.2.3 From b4ab4868bc8422e09590d13d35c2bba7a195ccf5 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 12:58:56 +0100 Subject: Fix UB in QFSFileEnginePrivate::writeFdFh() Apparently, it is considered valid to call the function with 'data' set to nullptr, and 'len' to zero. But doing so invokes undefined behavior because nullptr is passed to fwrite(). Fix by protecting the loops with 'if (len)'. Found by UBSan: qtbase/src/corelib/io/qfsfileengine.cpp:732:84: runtime error: null pointer passed as argument 1, which is declared to never be null Change-Id: Idfe23875c868ebb21d2164550de3304d2f01e9df Reviewed-by: Oswald Buddenhagen Reviewed-by: Thiago Macieira --- src/corelib/io/qfsfileengine.cpp | 46 ++++++++++++++++++++++------------------ 1 file changed, 25 insertions(+), 21 deletions(-) diff --git a/src/corelib/io/qfsfileengine.cpp b/src/corelib/io/qfsfileengine.cpp index 429c40da1a..10e116a23a 100644 --- a/src/corelib/io/qfsfileengine.cpp +++ b/src/corelib/io/qfsfileengine.cpp @@ -724,29 +724,33 @@ qint64 QFSFileEnginePrivate::writeFdFh(const char *data, qint64 len) qint64 writtenBytes = 0; - if (fh) { - // Buffered stdlib mode. - - size_t result; - do { - result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh); - writtenBytes += result; - } while (result == 0 ? errno == EINTR : writtenBytes < len); + if (len) { // avoid passing nullptr to fwrite() or QT_WRITE() (UB) - } else if (fd != -1) { - // Unbuffered stdio mode. + if (fh) { + // Buffered stdlib mode. + + size_t result; + do { + result = fwrite(data + writtenBytes, 1, size_t(len - writtenBytes), fh); + writtenBytes += result; + } while (result == 0 ? errno == EINTR : writtenBytes < len); + + } else if (fd != -1) { + // Unbuffered stdio mode. + + SignedIOType result; + do { + // calculate the chunk size + // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks + // we limit to the size of the signed type, otherwise we could get a negative number as a result + quint64 wantedBytes = quint64(len) - quint64(writtenBytes); + UnsignedIOType chunkSize = std::numeric_limits::max(); + if (chunkSize > wantedBytes) + chunkSize = wantedBytes; + result = QT_WRITE(fd, data + writtenBytes, chunkSize); + } while (result > 0 && (writtenBytes += result) < len); + } - SignedIOType result; - do { - // calculate the chunk size - // on Windows or 32-bit no-largefile Unix, we'll need to read in chunks - // we limit to the size of the signed type, otherwise we could get a negative number as a result - quint64 wantedBytes = quint64(len) - quint64(writtenBytes); - UnsignedIOType chunkSize = std::numeric_limits::max(); - if (chunkSize > wantedBytes) - chunkSize = wantedBytes; - result = QT_WRITE(fd, data + writtenBytes, chunkSize); - } while (result > 0 && (writtenBytes += result) < len); } if (len && writtenBytes == 0) { -- cgit v1.2.3 From 13189360e50a429ee43ce927c29ebcd3948619b7 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 13:31:11 +0100 Subject: Fix UB in QFileDevice::writeData() Passing nullptr as the 2nd argument of memcpy constitutes undefined behavior. Fix by protecting the block with 'if (len)', which, presumably, is the only valid case where 'data' may be nullptr. Change-Id: I7647d7e0808b1f26444ea3cf8bbf5cda9ddc9e6c Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/io/qfiledevice.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/io/qfiledevice.cpp b/src/corelib/io/qfiledevice.cpp index 3ee0e33573..2d6be5fb80 100644 --- a/src/corelib/io/qfiledevice.cpp +++ b/src/corelib/io/qfiledevice.cpp @@ -560,7 +560,7 @@ qint64 QFileDevice::writeData(const char *data, qint64 len) char *writePointer = d->writeBuffer.reserve(len); if (len == 1) *writePointer = *data; - else + else if (len) ::memcpy(writePointer, data, len); return len; } -- cgit v1.2.3 From 08775e4bd745276bcc6a5a9fdc4bed7aca225112 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Mon, 11 Jan 2016 16:10:00 +0100 Subject: Revert "QString: preserve embedded NULs when converting from QByteArray" MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This partially reverts commit e486d69133178ccce7c75cf48201ab28efb20e44. It broke too many users, even though all of them deserved to be broken. The new functionality will be provided by differently-named functions, where possible (problem: equality operators). I did not revert the fix for the off-by-one error in tst_qtextdocumentfragment.cpp. I also didn't revert the change in the inequality relational operators, since for all strings s1, s2 and s2' where s2' is s2 truncated at the first NUL, s1 < s2 ⟺ s1 < s2' (since NUL < c for any c != 0), and, trivially, for ≤, >, ≥, too. This does not hold for = and ≠, of course, since "foo\0bar" ≠ "foo". [ChangeLog][Important Behavior Changes][EDITORIAL] Reverted: All conversions from QByteArray to QString now preserve embedded NULs... Change-Id: If4b47048b39ae5be6ed08e6d91809626a67ea7f5 Reviewed-by: Thiago Macieira --- src/corelib/tools/qstring.h | 18 +++++------ tests/auto/corelib/tools/qstring/tst_qstring.cpp | 39 ++++++++++++++++++++++-- 2 files changed, 46 insertions(+), 11 deletions(-) diff --git a/src/corelib/tools/qstring.h b/src/corelib/tools/qstring.h index 1d04bcb457..1fbcff35d1 100644 --- a/src/corelib/tools/qstring.h +++ b/src/corelib/tools/qstring.h @@ -86,7 +86,7 @@ public: Q_DECL_CONSTEXPR inline QLatin1String() Q_DECL_NOTHROW : m_size(0), m_data(Q_NULLPTR) {} Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s) Q_DECL_NOTHROW : m_size(s ? int(strlen(s)) : 0), m_data(s) {} Q_DECL_CONSTEXPR inline explicit QLatin1String(const char *s, int sz) Q_DECL_NOTHROW : m_size(sz), m_data(s) {} - inline explicit QLatin1String(const QByteArray &s) Q_DECL_NOTHROW : m_size(s.size()), m_data(s.constData()) {} + inline explicit QLatin1String(const QByteArray &s) Q_DECL_NOTHROW : m_size(int(qstrnlen(s.constData(), s.size()))), m_data(s.constData()) {} Q_DECL_CONSTEXPR const char *latin1() const Q_DECL_NOTHROW { return m_data; } Q_DECL_CONSTEXPR int size() const Q_DECL_NOTHROW { return m_size; } @@ -539,11 +539,11 @@ public: return fromLocal8Bit_helper(str, (str && size == -1) ? int(strlen(str)) : size); } static inline QString fromLatin1(const QByteArray &str) - { return str.isNull() ? QString() : fromLatin1(str.data(), str.size()); } + { return str.isNull() ? QString() : fromLatin1(str.data(), qstrnlen(str.constData(), str.size())); } static inline QString fromUtf8(const QByteArray &str) - { return str.isNull() ? QString() : fromUtf8(str.data(), str.size()); } + { return str.isNull() ? QString() : fromUtf8(str.data(), qstrnlen(str.constData(), str.size())); } static inline QString fromLocal8Bit(const QByteArray &str) - { return str.isNull() ? QString() : fromLocal8Bit(str.data(), str.size()); } + { return str.isNull() ? QString() : fromLocal8Bit(str.data(), qstrnlen(str.constData(), str.size())); } static QString fromUtf16(const ushort *, int size = -1); static QString fromUcs4(const uint *, int size = -1); static QString fromRawData(const QChar *, int size); @@ -655,7 +655,7 @@ public: : d(fromAscii_helper(ch, ch ? int(strlen(ch)) : -1)) {} inline QT_ASCII_CAST_WARN QString(const QByteArray &a) - : d(fromAscii_helper(a.constData(), a.size())) + : d(fromAscii_helper(a.constData(), qstrnlen(a.constData(), a.size()))) {} inline QT_ASCII_CAST_WARN QString &operator=(const char *ch) { return (*this = fromUtf8(ch)); } @@ -1223,9 +1223,9 @@ inline QT_ASCII_CAST_WARN bool QLatin1String::operator>=(const QByteArray &s) co { return QString::fromUtf8(s) <= *this; } inline QT_ASCII_CAST_WARN bool QString::operator==(const QByteArray &s) const -{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) == 0; } +{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) == 0; } inline QT_ASCII_CAST_WARN bool QString::operator!=(const QByteArray &s) const -{ return QString::compare_helper(constData(), size(), s.constData(), s.size()) != 0; } +{ return QString::compare_helper(constData(), size(), s.constData(), qstrnlen(s.constData(), s.size())) != 0; } inline QT_ASCII_CAST_WARN bool QString::operator<(const QByteArray &s) const { return QString::compare_helper(constData(), size(), s.constData(), s.size()) < 0; } inline QT_ASCII_CAST_WARN bool QString::operator>(const QByteArray &s) const @@ -1236,9 +1236,9 @@ inline QT_ASCII_CAST_WARN bool QString::operator>=(const QByteArray &s) const { return QString::compare_helper(constData(), size(), s.constData(), s.size()) >= 0; } inline bool QByteArray::operator==(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) == 0; } +{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) == 0; } inline bool QByteArray::operator!=(const QString &s) const -{ return QString::compare_helper(s.constData(), s.size(), constData(), size()) != 0; } +{ return QString::compare_helper(s.constData(), s.size(), constData(), qstrnlen(constData(), size())) != 0; } inline bool QByteArray::operator<(const QString &s) const { return QString::compare_helper(s.constData(), s.size(), constData(), size()) > 0; } inline bool QByteArray::operator>(const QString &s) const diff --git a/tests/auto/corelib/tools/qstring/tst_qstring.cpp b/tests/auto/corelib/tools/qstring/tst_qstring.cpp index 907dcf17e1..a922e3ad27 100644 --- a/tests/auto/corelib/tools/qstring/tst_qstring.cpp +++ b/tests/auto/corelib/tools/qstring/tst_qstring.cpp @@ -1148,7 +1148,7 @@ void tst_QString::constructorQByteArray_data() ba1[5] = 'e'; ba1[6] = 'f'; - QTest::newRow( "2" ) << ba1 << QStringLiteral("abc\0def"); + QTest::newRow( "2" ) << ba1 << QString("abc"); QTest::newRow( "3" ) << QByteArray::fromRawData("abcd", 3) << QString("abc"); QTest::newRow( "4" ) << QByteArray("\xc3\xa9") << QString("\xc3\xa9"); @@ -1169,6 +1169,12 @@ void tst_QString::constructorQByteArray() QCOMPARE( strBA, expected ); // test operator= too + if (src.constData()[src.length()] == '\0') { + str1.clear(); + str1 = src.constData(); + QCOMPARE( str1, expected ); + } + strBA.clear(); strBA = src; QCOMPARE( strBA, expected ); @@ -2569,6 +2575,14 @@ void tst_QString::append_bytearray_special_cases() QTEST( str, "res" ); } + + QFETCH( QByteArray, ba ); + if (ba.constData()[ba.length()] == '\0') { + QFETCH( QString, str ); + + str.append(ba.constData()); + QTEST( str, "res" ); + } } void tst_QString::operator_pluseq_data(bool emptyIsNoop) @@ -2599,6 +2613,14 @@ void tst_QString::operator_pluseq_bytearray_special_cases() QTEST( str, "res" ); } + + QFETCH( QByteArray, ba ); + if (ba.constData()[ba.length()] == '\0') { + QFETCH( QString, str ); + + str += ba.constData(); + QTEST( str, "res" ); + } } void tst_QString::operator_eqeq_bytearray_data() @@ -2613,6 +2635,11 @@ void tst_QString::operator_eqeq_bytearray() QVERIFY(expected == src); QVERIFY(!(expected != src)); + + if (src.constData()[src.length()] == '\0') { + QVERIFY(expected == src.constData()); + QVERIFY(!(expected != src.constData())); + } } void tst_QString::swap() @@ -2670,7 +2697,7 @@ void tst_QString::prepend_bytearray_special_cases_data() // byte array with only a 0 ba.resize( 1 ); ba[0] = 0; - QTest::newRow( "emptyString" ) << QString("foobar ") << ba << QStringLiteral("\0foobar "); + QTest::newRow( "emptyString" ) << QString("foobar ") << ba << QString("foobar "); // empty byte array ba.resize( 0 ); @@ -2700,6 +2727,14 @@ void tst_QString::prepend_bytearray_special_cases() QTEST( str, "res" ); } + + QFETCH( QByteArray, ba ); + if (ba.constData()[ba.length()] == '\0') { + QFETCH( QString, str ); + + str.prepend(ba.constData()); + QTEST( str, "res" ); + } } void tst_QString::replace_uint_uint() -- cgit v1.2.3 From 81858bf1722081d99fdea72f55e67c04c5bb3d92 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 4 Nov 2015 10:26:37 +0100 Subject: Don't pretend we know what DST to use for an offset date. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit When QDateTime::addDate() and friends sanitize their end-state, they were using the DST status of their start-state (if known) to control it. This lead to misguided results and, in particular, inconsistent results given that a raw-constructed QDateTime comes into being ignorant of its DST, while a .toLocalTime() one knows its DST. Furthermore, the code to do this was triplicated, tricky and poorly explained. So pull it out into a local static function and explain what it's doing, and why, more clearly and only once. Task-number: QTBUG-49008 Change-Id: Ia4bb3c5e9267fff8bb963ea705267998218ed623 Reviewed-by: Jędrzej Nowacki --- src/corelib/tools/qdatetime.cpp | 68 ++++++++++++---------- .../auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 2 - 2 files changed, 38 insertions(+), 32 deletions(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index 241b02df1b..fa4ac2b00f 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -3652,6 +3652,40 @@ QString QDateTime::toString(const QString& format) const } #endif //QT_NO_DATESTRING +static void massageAdjustedDateTime(Qt::TimeSpec spec, +#ifndef QT_BOOTSTRAPPED + const QTimeZone &zone, +#endif // QT_BOOTSTRAPPED + QDate *date, + QTime *time) +{ + /* + If we have just adjusted to a day with a DST transition, our given time + may lie in the transition hour (either missing or duplicated). For any + other time, telling mktime (deep in the bowels of localMSecsToEpochMSecs) + we don't know its DST-ness will produce no adjustment (just a decision as + to its DST-ness); but for a time in spring's missing hour it'll adjust the + time while picking a DST-ness. (Handling of autumn is trickier, as either + DST-ness is valid, without adjusting the time. We might want to propagate + d->daylightStatus() in that case, but it's hard to do so without breaking + (far more common) other cases; and it makes little difference, as the two + answers do then differ only in DST-ness.) + */ + if (spec == Qt::LocalTime) { + QDateTimePrivate::DaylightStatus status = QDateTimePrivate::UnknownDaylightTime; + localMSecsToEpochMSecs(timeToMSecs(*date, *time), &status, date, time); +#ifndef QT_BOOTSTRAPPED + } else if (spec == Qt::TimeZone) { + QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(*date, *time), zone, date, time); +#endif // QT_BOOTSTRAPPED + } +} +#ifdef QT_BOOTSTRAPPED // Avoid duplicate #if-ery in uses. +#define MASSAGEADJUSTEDDATETIME(s, z, d, t) massageAdjustedDateTime(s, d, t) +#else +#define MASSAGEADJUSTEDDATETIME(s, z, d, t) massageAdjustedDateTime(s, z, d, t) +#endif // QT_BOOTSTRAPPED + /*! Returns a QDateTime object containing a datetime \a ndays days later than the datetime of this object (or earlier if \a ndays is @@ -3673,16 +3707,7 @@ QDateTime QDateTime::addDays(qint64 ndays) const QDate &date = p.first; QTime &time = p.second; date = date.addDays(ndays); - // Result might fall into "missing" DaylightTime transition hour, - // so call conversion and use the adjusted returned time - if (d->m_spec == Qt::LocalTime) { - QDateTimePrivate::DaylightStatus status = d->daylightStatus(); - localMSecsToEpochMSecs(timeToMSecs(date, time), &status, &date, &time); -#ifndef QT_BOOTSTRAPPED - } else if (d->m_spec == Qt::TimeZone) { - QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(date, time), d->m_timeZone, &date, &time); -#endif // QT_BOOTSTRAPPED - } + MASSAGEADJUSTEDDATETIME(d->m_spec, d->m_timeZone, &date, &time); dt.d->setDateTime(date, time); return dt; } @@ -3708,16 +3733,7 @@ QDateTime QDateTime::addMonths(int nmonths) const QDate &date = p.first; QTime &time = p.second; date = date.addMonths(nmonths); - // Result might fall into "missing" DaylightTime transition hour, - // so call conversion and use the adjusted returned time - if (d->m_spec == Qt::LocalTime) { - QDateTimePrivate::DaylightStatus status = d->daylightStatus(); - localMSecsToEpochMSecs(timeToMSecs(date, time), &status, &date, &time); -#ifndef QT_BOOTSTRAPPED - } else if (d->m_spec == Qt::TimeZone) { - QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(date, time), d->m_timeZone, &date, &time); -#endif // QT_BOOTSTRAPPED - } + MASSAGEADJUSTEDDATETIME(d->m_spec, d->m_timeZone, &date, &time); dt.d->setDateTime(date, time); return dt; } @@ -3743,19 +3759,11 @@ QDateTime QDateTime::addYears(int nyears) const QDate &date = p.first; QTime &time = p.second; date = date.addYears(nyears); - // Result might fall into "missing" DaylightTime transition hour, - // so call conversion and use the adjusted returned time - if (d->m_spec == Qt::LocalTime) { - QDateTimePrivate::DaylightStatus status = d->daylightStatus(); - localMSecsToEpochMSecs(timeToMSecs(date, time), &status, &date, &time); -#ifndef QT_BOOTSTRAPPED - } else if (d->m_spec == Qt::TimeZone) { - QDateTimePrivate::zoneMSecsToEpochMSecs(timeToMSecs(date, time), d->m_timeZone, &date, &time); -#endif // QT_BOOTSTRAPPED - } + MASSAGEADJUSTEDDATETIME(d->m_spec, d->m_timeZone, &date, &time); dt.d->setDateTime(date, time); return dt; } +#undef MASSAGEADJUSTEDDATETIME /*! Returns a QDateTime object containing a datetime \a s seconds diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 216c670aee..228ce73c6b 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -1616,9 +1616,7 @@ void tst_QDateTime::springForward_data() if (europeanTimeZone) { QTest::newRow("Europe from day before") << QDate(2015, 3, 29) << QTime(2, 30, 0) << 1 << 60; -#if 0 // FIXME: fails QTest::newRow("Europe from day after") << QDate(2015, 3, 29) << QTime(2, 30, 0) << -1 << 120; -#endif // } else if (otherZone) { } else { QSKIP("No spring forward test data for this TZ"); -- cgit v1.2.3 From 20c7ab44c6821e3ecc10008e005b52b465ac78e4 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 18 Nov 2015 17:19:46 +0100 Subject: rework include path construction in the module system the main objective was to fix the bootstrap modules in framework builds. bootstrapped modules which "borrow" headers from "proper" modules can specify this in a clean way now. a side effect of this is that the bootstrap-dbus module now has its own syncqt call. most includepath-related setup from qt_module_pris.prf was moved to qt_module_headers.prf. Change-Id: Ie0d8192cfac1a8cdae0ddd0bc0cd8c3092b1e85b Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt_module.prf | 4 +- mkspecs/features/qt_module_headers.prf | 62 ++++++++++++++++++++++++++++- mkspecs/features/qt_module_pris.prf | 42 +++++-------------- src/angle/angle.pro | 3 +- src/src.pro | 4 +- src/tools/bootstrap-dbus/bootstrap-dbus.pro | 8 +--- src/tools/bootstrap/bootstrap.pro | 18 +-------- 7 files changed, 81 insertions(+), 60 deletions(-) diff --git a/mkspecs/features/qt_module.prf b/mkspecs/features/qt_module.prf index 6ed75a4416..fdce486c00 100644 --- a/mkspecs/features/qt_module.prf +++ b/mkspecs/features/qt_module.prf @@ -80,10 +80,10 @@ CONFIG += qmake_cache target_qt QMAKE_DOCS_TARGETDIR = qt$${MODULE} -load(qt_module_pris) load(qt_common) - !no_module_headers: load(qt_module_headers) +load(qt_module_pris) + INCLUDEPATH *= $$eval(QT.$${MODULE}.includes) $$eval(QT.$${MODULE}_private.includes) # If Qt was configured with -debug-and-release then build the module the same way diff --git a/mkspecs/features/qt_module_headers.prf b/mkspecs/features/qt_module_headers.prf index 892a9a2c4b..eb1db08405 100644 --- a/mkspecs/features/qt_module_headers.prf +++ b/mkspecs/features/qt_module_headers.prf @@ -18,10 +18,11 @@ load(qt_build_paths) } else { contains(QT_CONFIG, private_tests): \ # -developer-build QMAKE_SYNCQT += -check-includes - QMAKE_SYNCQT += -module $$MODULE_INCNAME -version $$VERSION } + for(mod, MODULE_INCNAME): \ + QMAKE_SYNCQT += -module $$mod QMAKE_SYNCQT += \ - -outdir $$system_quote($$MODULE_BASE_OUTDIR) $$MODULE_SYNCQT_DIR + -version $$VERSION -outdir $$system_quote($$MODULE_BASE_OUTDIR) $$MODULE_SYNCQT_DIR !silent: message($$QMAKE_SYNCQT) system($$QMAKE_SYNCQT)|error("Failed to run: $$QMAKE_SYNCQT") @@ -33,6 +34,63 @@ load(qt_build_paths) } } +# Pre-generated headers in the source tree (tar-ball) and +# - shadow build or +# - non-shadow non-prefix build of a module which is not qtbase +# (because the build-time generated headers all end up in qtbase). +!git_build: \ + if(!equals(_PRO_FILE_PWD_, $$OUT_PWD) \ + |if(!prefix_build:!equals(MODULE_BASE_INDIR, $$[QT_HOST_PREFIX]))): \ + CONFIG += split_incpath + +# To avoid stuffing the code with repetetive conditionals, +# we parametrize the names of the variables we assign to. + +# Internal modules have no private part - they *are* private. +!internal_module: \ + prv = _PRIVATE + +# When doing a framework build with a prefix, the module needs to point +# into the frameworks' Headers dirs directly, as no shared include/ dir +# is installed. +# However, during the build, it needs to point into the shared include/ +# dir, as the framework doesn't even exist yet. For bootstrapped modules +# which borrow headers from "proper" modules, this situation persists +# even beyond the module's own build. The implication of this is that +# qmake might never use a framework's headers in a non-prefix build, +# as there is no separate set of .pri files for users outside Qt. +prefix_build:lib_bundle: \ + fwd = _FWD +# When using a split include path during the build, the installed module's +# include path is also structurally different from that in the build dir. +prefix_build:split_incpath: \ + sfwd = _FWD + +ibase = \$\$QT_MODULE_INCLUDE_BASE +MODULE$${fwd}_INCLUDES = $$ibase +split_incpath { + bibase = $$val_escape(MODULE_BASE_OUTDIR)/include + MODULE$${sfwd}_INCLUDES += $$bibase +} +for(mod, MODULE_INCNAME) { + mibase = $$ibase/$$mod + MODULE$${fwd}_INCLUDES += $$mibase + MODULE$${fwd}$${prv}_INCLUDES += $$mibase/$$VERSION $$mibase/$$VERSION/$$mod + split_incpath { + mbibase = $$bibase/$$mod + MODULE$${sfwd}_INCLUDES += $$mbibase + generated_privates: \ + MODULE$${sfwd}$${prv}_INCLUDES += $$mbibase/$$VERSION $$mbibase/$$VERSION/$$mod + } + prefix_build:lib_bundle { + mfbase = \$\$QT_MODULE_LIB_BASE/$${mod}.framework/Headers + MODULE_INCLUDES += $$mfbase + MODULE$${prv}_INCLUDES += $$mfbase/$$VERSION $$mfbase/$$VERSION/$$mod + } +} +MODULE_INCLUDES += $$MODULE_AUX_INCLUDES +MODULE_PRIVATE_INCLUDES += $$MODULE_PRIVATE_AUX_INCLUDES + minimal_syncqt: return() #load up the headers info diff --git a/mkspecs/features/qt_module_pris.prf b/mkspecs/features/qt_module_pris.prf index 3f21a0f7d5..fdcb9df270 100644 --- a/mkspecs/features/qt_module_pris.prf +++ b/mkspecs/features/qt_module_pris.prf @@ -10,14 +10,7 @@ # load(qt_build_paths) -# Pre-generated headers in the source tree and -# - shadow build or -# - non-shadow non-prefix build of a module which is not qtbase (because the build-time -# generated headers all end up in qtbase). -!git_build:if(!equals(_PRO_FILE_PWD_, $$OUT_PWD) \ - |if(!prefix_build:!equals(MODULE_BASE_INDIR, $$[QT_HOST_PREFIX]))): \ - CONFIG += split_incpath -force_independent|split_incpath: \ +force_independent|!isEmpty(MODULE_FWD_INCLUDES): \ CONFIG += need_fwd_pri mod_work_pfx = $$MODULE_QMAKE_OUTDIR/mkspecs/modules need_fwd_pri: \ @@ -77,27 +70,6 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri module_master = "QT.$${MODULE_ID}.master_header = $$MODULE_MASTER_HEADER" else: \ module_master = - !no_module_headers:!minimal_syncqt { - MODULE_INCLUDES = \$\$QT_MODULE_INCLUDE_BASE \$\$QT_MODULE_INCLUDE_BASE/$$MODULE_INCNAME - MODULE_PRIVATE_INCLUDES = \$\$QT_MODULE_INCLUDE_BASE/$$MODULE_INCNAME/$$VERSION \ - \$\$QT_MODULE_INCLUDE_BASE/$$MODULE_INCNAME/$$VERSION/$$MODULE_INCNAME - } - split_incpath { - MODULE_SHADOW_INCLUDES = $$replace(MODULE_INCLUDES, ^\\\$\\\$QT_MODULE_INCLUDE_BASE, \ - $$MODULE_BASE_OUTDIR/include) - generated_privates: \ - MODULE_SHADOW_PRIVATE_INCLUDES = $$replace(MODULE_PRIVATE_INCLUDES, ^\\\$\\\$QT_MODULE_INCLUDE_BASE, \ - $$MODULE_BASE_OUTDIR/include) - } - MODULE_INCLUDES += $$MODULE_AUX_INCLUDES - MODULE_PRIVATE_INCLUDES += $$MODULE_PRIVATE_AUX_INCLUDES - internal_module: \ - MODULE_INCLUDES += $$MODULE_PRIVATE_INCLUDES - split_incpath { - MODULE_FWD_PRI_CONT_SUFFIX += "QT.$${MODULE_ID}.includes += $$val_escape(MODULE_SHADOW_INCLUDES)" - generated_privates: \ - MODULE_FWD_PRI_CONT_SUFFIX += "QT.$${MODULE}_private.includes += $$val_escape(MODULE_SHADOW_PRIVATE_INCLUDES)" - } MODULE_PRI_CONT = \ "QT.$${MODULE_ID}.VERSION = $${VERSION}" \ "QT.$${MODULE_ID}.MAJOR_VERSION = $$section(VERSION, ., 0, 0)" \ @@ -143,7 +115,7 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri need_fwd_pri { - split_incpath: \ + !git_build: \ MODULE_BASE_INCDIR = $$MODULE_BASE_INDIR else: \ MODULE_BASE_INCDIR = $$MODULE_BASE_OUTDIR @@ -163,7 +135,15 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri !internal_module:!no_private_module: MODULE_FWD_PRI_CONT += \ "include($$val_escape(MODULE_PRIVATE_PRI))" \ "QT.$${MODULE}_private.priority = 1" - MODULE_FWD_PRI_CONT += $$MODULE_FWD_PRI_CONT_SUFFIX + !isEmpty(MODULE_FWD_INCLUDES) { + !lib_bundle: \ + pls = + + MODULE_FWD_PRI_CONT += \ + "QT.$${MODULE_ID}.includes $$pls= $$MODULE_FWD_INCLUDES" + !internal_module: \ + MODULE_FWD_PRI_CONT += \ + "QT.$${MODULE}_private.includes $$pls= $$MODULE_FWD_PRIVATE_INCLUDES" + } write_file($$MODULE_FWD_PRI, MODULE_FWD_PRI_CONT)|error("Aborting.") touch($$MODULE_FWD_PRI, $$MODULE_PRI) MODULE_PRI_FILES += $$MODULE_FWD_PRI diff --git a/src/angle/angle.pro b/src/angle/angle.pro index c454fee8f9..8fae66dfb9 100644 --- a/src/angle/angle.pro +++ b/src/angle/angle.pro @@ -6,5 +6,6 @@ SUBDIRS += src # 2) If we made a 'QtANGLE' module, the include directory would be flattened which won't work since # we need to support "#include " CONFIG += minimal_syncqt -QMAKE_SYNCQT_OPTIONS = -module QtANGLE/KHR -module QtANGLE/EGL -module QtANGLE/GLES2 -module QtANGLE/GLES3 -version none +MODULE_INCNAME = QtANGLE/KHR QtANGLE/EGL QtANGLE/GLES2 QtANGLE/GLES3 +VERSION = none load(qt_module_headers) diff --git a/src/src.pro b/src/src.pro index df5c85fa53..167133859b 100644 --- a/src/src.pro +++ b/src/src.pro @@ -63,6 +63,7 @@ src_xml.depends = src_corelib src_dbus.subdir = $$PWD/dbus src_dbus.target = sub-dbus src_dbus.depends = src_corelib +force_bootstrap: src_dbus.depends += src_tools_bootstrap_dbus # avoid syncqt race src_concurrent.subdir = $$PWD/concurrent src_concurrent.target = sub-concurrent @@ -139,9 +140,8 @@ TOOLS = src_tools_moc src_tools_rcc src_tools_qlalr win32:SUBDIRS += src_winmain SUBDIRS += src_network src_sql src_xml src_testlib contains(QT_CONFIG, dbus) { - SUBDIRS += src_dbus force_bootstrap: SUBDIRS += src_tools_bootstrap_dbus - SUBDIRS += src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml + SUBDIRS += src_dbus src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml TOOLS += src_tools_qdbusxml2cpp src_tools_qdbuscpp2xml contains(QT_CONFIG, accessibility-atspi-bridge): \ src_platformsupport.depends += src_dbus src_tools_qdbusxml2cpp diff --git a/src/tools/bootstrap-dbus/bootstrap-dbus.pro b/src/tools/bootstrap-dbus/bootstrap-dbus.pro index fb06b4d8a2..4c466ba0e9 100644 --- a/src/tools/bootstrap-dbus/bootstrap-dbus.pro +++ b/src/tools/bootstrap-dbus/bootstrap-dbus.pro @@ -2,16 +2,12 @@ option(host_build) MODULE = bootstrap_dbus TARGET = QtBootstrapDBus -CONFIG += no_module_headers internal_module force_bootstrap +CONFIG += minimal_syncqt internal_module force_bootstrap DEFINES += \ QT_NO_CAST_FROM_ASCII -MODULE_INCLUDES = \ - \$\$QT_MODULE_INCLUDE_BASE/QtDBus -MODULE_PRIVATE_INCLUDES = \ - \$\$QT_MODULE_INCLUDE_BASE/QtDBus/$$QT_VERSION \ - \$\$QT_MODULE_INCLUDE_BASE/QtDBus/$$QT_VERSION/QtDBus +MODULE_INCNAME = QtDBus load(qt_module) diff --git a/src/tools/bootstrap/bootstrap.pro b/src/tools/bootstrap/bootstrap.pro index ca05f804a2..4f2456cf79 100644 --- a/src/tools/bootstrap/bootstrap.pro +++ b/src/tools/bootstrap/bootstrap.pro @@ -2,8 +2,9 @@ option(host_build) TARGET = QtBootstrap QT = -CONFIG += internal_module force_bootstrap +CONFIG += minimal_syncqt internal_module force_bootstrap +MODULE_INCNAME = QtCore QtXml MODULE_DEFINES = \ QT_BOOTSTRAPPED \ QT_LITE_UNICODE \ @@ -26,21 +27,6 @@ DEFINES += \ DEFINES -= QT_EVAL -MODULE_INCLUDES = \ - \$\$QT_MODULE_INCLUDE_BASE \ - \$\$QT_MODULE_INCLUDE_BASE/QtCore \ - \$\$QT_MODULE_INCLUDE_BASE/QtXml -MODULE_PRIVATE_INCLUDES = \ - \$\$QT_MODULE_INCLUDE_BASE/QtCore/$$QT_VERSION \ - \$\$QT_MODULE_INCLUDE_BASE/QtCore/$$QT_VERSION/QtCore \ - \$\$QT_MODULE_INCLUDE_BASE/QtXml/$$QT_VERSION \ - \$\$QT_MODULE_INCLUDE_BASE/QtXml/$$QT_VERSION/QtXml - -# We need the forwarding headers before their respective modules are built, -# so do a minimal syncqt run. -CONFIG += minimal_syncqt -QMAKE_SYNCQT_OPTIONS = -module QtCore -module QtDBus -module QtXml -version $$QT_VERSION - load(qt_module) # otherwise mingw headers do not declare common functions like putenv -- cgit v1.2.3 From d8cfa6a144e7c592c7b9d77f01bbcd3f57617b33 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Wed, 23 Sep 2015 18:46:04 +0200 Subject: disable install targets for non-prefix builds one reason to do that is some users' persistence in destroying their non-prefix builds by trying an installation. another reason is the fact that qt.pro's relative_qt_rpath is triggered by the presence of an install rule for the target, which is of course not helpful when the install dir is bogus. Task-number: QTBUG-48406 Change-Id: I75f3940be79fcb5b86e34b975b789692423c92cb Reviewed-by: Joerg Bornemann --- mkspecs/features/qt_build_config.prf | 6 ++++++ mkspecs/features/qt_clear_installs.prf | 12 ++++++++++++ 2 files changed, 18 insertions(+) create mode 100644 mkspecs/features/qt_clear_installs.prf diff --git a/mkspecs/features/qt_build_config.prf b/mkspecs/features/qt_build_config.prf index eaf23cf63a..518fd93f04 100644 --- a/mkspecs/features/qt_build_config.prf +++ b/mkspecs/features/qt_build_config.prf @@ -52,6 +52,12 @@ QMAKE_DIR_REPLACE_SANE = PRECOMPILED_DIR OBJECTS_DIR MOC_DIR RCC_DIR UI_DIR unset(modpath) } +# Don't actually try to install anything in non-prefix builds. +# This is much easier and safer than making every single INSTALLS +# assignment conditional. +!prefix_build: \ + CONFIG += qt_clear_installs + cross_compile: \ CONFIG += force_bootstrap diff --git a/mkspecs/features/qt_clear_installs.prf b/mkspecs/features/qt_clear_installs.prf new file mode 100644 index 0000000000..66d12f9d6d --- /dev/null +++ b/mkspecs/features/qt_clear_installs.prf @@ -0,0 +1,12 @@ +# +# W A R N I N G +# ------------- +# +# This file is not part of the Qt API. It exists purely as an +# implementation detail. It may change from version to version +# without notice, or even be removed. +# +# We mean it. +# + +INSTALLS = -- cgit v1.2.3 From 650b4d0f49a533858327204f1b6a930a63c7986a Mon Sep 17 00:00:00 2001 From: Romain Pokrzywka Date: Mon, 26 Oct 2015 17:50:45 -0700 Subject: Append the environment's QT_PLUGIN_PATH to 'make check' targets Without this, any test executable requiring a plugin path from the environment's QT_PLUGIN_PATH will fail to run since the path is overwritten when generating the 'make check' command, for example: QT_PLUGIN_PATH=/path/to/qt/plugins \ LD_LIBRARY_PATH=/path/to/qt/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} \ ./test_foo A prepend config option is used for *PATH to preserve the envvar value, so use the same option for QT_PLUGIN_PATH. The command above then becomes: QT_PLUGIN_PATH=/path/to/qt/plugins${QT_PLUGIN_PATH:+:$QT_PLUGIN_PATH} \ LD_LIBRARY_PATH=/path/to/qt/lib${LD_LIBRARY_PATH:+:$LD_LIBRARY_PATH} \ ./test_foo Change-Id: I69b43327974915eae52f299fc4001effe93a491a Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt_functions.prf | 1 + 1 file changed, 1 insertion(+) diff --git a/mkspecs/features/qt_functions.prf b/mkspecs/features/qt_functions.prf index c23d006d82..e239db2454 100644 --- a/mkspecs/features/qt_functions.prf +++ b/mkspecs/features/qt_functions.prf @@ -206,6 +206,7 @@ defineTest(qtAddTargetEnv) { pluginpath.value += $$system_path($$qplug) } pluginpath.name = QT_PLUGIN_PATH + pluginpath.CONFIG = prepend QT_TOOL_ENV += deppath pluginpath } -- cgit v1.2.3 From 5e1a5a78d912896b7e03ac01f336ed1b109a2b22 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Mon, 11 Jan 2016 16:23:18 -0800 Subject: QVariant: make sure to default-initialize in v_construct MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Otherwise it's possible to get garbage for primitive types (trivially constructible) under some conditions. Change-Id: I408dcb81ba654c929f25ffff142885fc62395948 Reviewed-by: Marc Mutz Reviewed-by: Jędrzej Nowacki Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/corelib/kernel/qvariant_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index d84d702982..4a090b5f12 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -121,7 +121,7 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) if (copy) new (&x->data.ptr) T(*static_cast(copy)); else - new (&x->data.ptr) T; + new (&x->data.ptr) T(); } } -- cgit v1.2.3 From 9f09fed72f87c9379fcbfd51cd6463b5c470814f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 3 Jan 2016 11:24:07 -0200 Subject: QVariant: use v_construct instead of duplicating logic MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit v_construct does what we want, so use it. This is required for the next commit, which solves a GCC 6 warning issue. Change-Id: Ibc83b9f7e3bc4962ae35ffff1425ed5f035f631a Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qvariant_p.h | 35 ++++------------------------------- 1 file changed, 4 insertions(+), 31 deletions(-) diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 4a090b5f12..4a7df1ad8d 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -1,6 +1,7 @@ /**************************************************************************** ** ** Copyright (C) 2015 The Qt Company Ltd. +** Copyright (C) 2016 Intel Corporation. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the QtCore module of the Qt Toolkit. @@ -116,13 +117,13 @@ inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) if (!QVariantIntegrator::CanUseInternalSpace) { x->data.shared = copy ? new QVariantPrivateSharedEx(*static_cast(copy)) : new QVariantPrivateSharedEx; - x->is_shared = true; } else { if (copy) new (&x->data.ptr) T(*static_cast(copy)); else new (&x->data.ptr) T(); } + x->is_shared = !QVariantIntegrator::CanUseInternalSpace; } template @@ -130,10 +131,10 @@ inline void v_construct(QVariant::Private *x, const T &t) { if (!QVariantIntegrator::CanUseInternalSpace) { x->data.shared = new QVariantPrivateSharedEx(t); - x->is_shared = true; } else { new (&x->data.ptr) T(t); } + x->is_shared = !QVariantIntegrator::CanUseInternalSpace; } // deletes the internal structures @@ -327,39 +328,11 @@ protected: template class QVariantConstructor { - template::CanUseInternalSpace> - struct CallConstructor {}; - - template - struct CallConstructor - { - CallConstructor(const QVariantConstructor &tc) - { - if (tc.m_copy) - new (&tc.m_x->data.ptr) T(*static_cast(tc.m_copy)); - else - new (&tc.m_x->data.ptr) T(); - tc.m_x->is_shared = false; - } - }; - - template - struct CallConstructor - { - CallConstructor(const QVariantConstructor &tc) - { - Q_STATIC_ASSERT(QTypeInfo::isComplex || sizeof(T) > sizeof(QVariant::Private::Data)); - tc.m_x->data.shared = tc.m_copy ? new QVariantPrivateSharedEx(*static_cast(tc.m_copy)) - : new QVariantPrivateSharedEx; - tc.m_x->is_shared = true; - } - }; - template::IsAccepted> struct FilteredConstructor { FilteredConstructor(const QVariantConstructor &tc) { - CallConstructor tmp(tc); + v_construct(tc.m_x, tc.m_copy); tc.m_x->is_null = !tc.m_copy; } }; -- cgit v1.2.3 From 70092c9a47840e1ca7606b90075b364c69876656 Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Sun, 3 Jan 2016 11:27:09 -0200 Subject: Fix GCC 6 warning about placement-new operator on too little space MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit GCC 6 is able to detect when you use a placement new of an object in a space that is too small to contain it. qvariant_p.h: In instantiation of ‘void v_construct(QVariant::Private*, const T&) [with T = QRectF]’: qvariant_p.h:142:9: error: placement new constructing an object of type ‘QRectF’ and size ‘32’ in a region of type ‘void*’ and size ‘8’ [-Werror=placement-new] new (&x->data.ptr) T(t); ^~~~~~~~~~~~~~~~~~~~~~~ This happens even for the false branch of a constant expression (the enum). So split the v_construct function in two pairs, one pair for being able to use the internal space and one pair not so. Change-Id: Ibc83b9f7e3bc4962ae35ffff1425ed898f279dea Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Jędrzej Nowacki --- src/corelib/kernel/qvariant_p.h | 55 +++++++++++++++++++++++++++-------------- 1 file changed, 37 insertions(+), 18 deletions(-) diff --git a/src/corelib/kernel/qvariant_p.h b/src/corelib/kernel/qvariant_p.h index 4a7df1ad8d..337e1406ec 100644 --- a/src/corelib/kernel/qvariant_p.h +++ b/src/corelib/kernel/qvariant_p.h @@ -60,6 +60,7 @@ struct QVariantIntegrator { static const bool CanUseInternalSpace = sizeof(T) <= sizeof(QVariant::Private::Data) && ((QTypeInfoQuery::isRelocatable) || Q_IS_ENUM(T)); + typedef QtPrivate::integral_constant CanUseInternalSpace_t; }; Q_STATIC_ASSERT(QVariantIntegrator::CanUseInternalSpace); Q_STATIC_ASSERT(QVariantIntegrator::CanUseInternalSpace); @@ -110,31 +111,49 @@ private: T m_t; }; -// constructs a new variant if copy is 0, otherwise copy-constructs template -inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) +inline void v_construct_helper(QVariant::Private *x, const T &t, QtPrivate::true_type) { - if (!QVariantIntegrator::CanUseInternalSpace) { - x->data.shared = copy ? new QVariantPrivateSharedEx(*static_cast(copy)) - : new QVariantPrivateSharedEx; - } else { - if (copy) - new (&x->data.ptr) T(*static_cast(copy)); - else - new (&x->data.ptr) T(); - } - x->is_shared = !QVariantIntegrator::CanUseInternalSpace; + new (&x->data) T(t); + x->is_shared = false; +} + +template +inline void v_construct_helper(QVariant::Private *x, const T &t, QtPrivate::false_type) +{ + x->data.shared = new QVariantPrivateSharedEx(t); + x->is_shared = true; +} + +template +inline void v_construct_helper(QVariant::Private *x, QtPrivate::true_type) +{ + new (&x->data) T(); + x->is_shared = false; +} + +template +inline void v_construct_helper(QVariant::Private *x, QtPrivate::false_type) +{ + x->data.shared = new QVariantPrivateSharedEx; + x->is_shared = true; } template inline void v_construct(QVariant::Private *x, const T &t) { - if (!QVariantIntegrator::CanUseInternalSpace) { - x->data.shared = new QVariantPrivateSharedEx(t); - } else { - new (&x->data.ptr) T(t); - } - x->is_shared = !QVariantIntegrator::CanUseInternalSpace; + // dispatch + v_construct_helper(x, t, typename QVariantIntegrator::CanUseInternalSpace_t()); +} + +// constructs a new variant if copy is 0, otherwise copy-constructs +template +inline void v_construct(QVariant::Private *x, const void *copy, T * = 0) +{ + if (copy) + v_construct(x, *static_cast(copy)); + else + v_construct_helper(x, typename QVariantIntegrator::CanUseInternalSpace_t()); } // deletes the internal structures -- cgit v1.2.3 From af45b352d7c29c42035196bb2d7c5c76a2f303da Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Mon, 11 Jan 2016 19:25:05 +0100 Subject: Fix reentrancy regression in QShortcutMap after c7e5e1d9e When closing a popup dialog using a shortcut, when the popup was originally opened using a shortcut, the closing-shortcut would interfere with the state of the first shortcut, and we ended up sending a key event for the original shortcut. Task-number: QTBUG-50360 Change-Id: I62e5ddb9ca43b28519ede629775bc0d7598dccc4 Reviewed-by: Simon Hausmann --- src/gui/kernel/qshortcutmap.cpp | 8 ++++++-- .../widgets/kernel/qshortcut/tst_qshortcut.cpp | 23 ++++++++++++++++++++-- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/gui/kernel/qshortcutmap.cpp b/src/gui/kernel/qshortcutmap.cpp index 9c8218b7b5..3941f7233f 100644 --- a/src/gui/kernel/qshortcutmap.cpp +++ b/src/gui/kernel/qshortcutmap.cpp @@ -336,12 +336,16 @@ bool QShortcutMap::tryShortcut(QKeyEvent *e) // For a partial match we don't know yet if we will handle the shortcut // but we need to say we did, so that we get the follow-up key-presses. return true; - case QKeySequence::ExactMatch: + case QKeySequence::ExactMatch: { + // Save number of identical matches before dispatching + // to keep QShortcutMap and tryShortcut reentrant. + const int identicalMatches = d->identicals.count(); resetState(); dispatchEvent(e); // If there are no identicals we've only found disabled shortcuts, and // shouldn't say that we handled the event. - return d->identicals.count() > 0; + return identicalMatches > 0; + } default: Q_UNREACHABLE(); } diff --git a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp index f206a5fe9a..15aef8d503 100644 --- a/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp +++ b/tests/auto/widgets/kernel/qshortcut/tst_qshortcut.cpp @@ -72,7 +72,8 @@ public: TriggerSlot4, TriggerSlot5, TriggerSlot6, - TriggerSlot7 + TriggerSlot7, + SendKeyEvent }; enum Result { @@ -84,6 +85,7 @@ public: Slot5Triggered, Slot6Triggered, Slot7Triggered, + SentKeyEvent, Ambiguous } currentResult; @@ -104,6 +106,7 @@ public slots: void ambigSlot7() { currentResult = Ambiguous; ambigResult = Slot7Triggered; } void statusMessage( const QString& message ) { sbText = message; } void shortcutDestroyed(QObject* obj); + void sendKeyEvent() { sendKeyEvents(edit, Qt::CTRL + Qt::Key_B, 0); currentResult = SentKeyEvent; } public slots: void initTestCase(); @@ -981,6 +984,19 @@ void tst_QShortcut::keypressConsumption() QVERIFY(edit->toPlainText().endsWith("a")); clearAllShortcuts(); + edit->clear(); + QCOMPARE(edit->toPlainText().size(), 0); + + setupShortcut(edit, "first", SendKeyEvent, "Ctrl+A"); + + // Verify reentrancy when a non-shortcut is triggered as part + // of shortcut processing. + currentResult = NoResult; + ambigResult = NoResult; + sendKeyEvents(edit, Qt::CTRL + Qt::Key_A, 0); + QCOMPARE(currentResult, SentKeyEvent); + QCOMPARE(ambigResult, NoResult); + QCOMPARE(edit->toPlainText(), QString(QString(""))); } // ------------------------------------------------------------------ @@ -1182,9 +1198,12 @@ QShortcut *tst_QShortcut::setupShortcut(QWidget *parent, const char *name, int t normal = SLOT(slotTrig7()); ambig = SLOT(ambigSlot7()); break; + case SendKeyEvent: + normal = SLOT(sendKeyEvent()); } connect(cut, SIGNAL(activated()), this, normal); - connect(cut, SIGNAL(activatedAmbiguously()), this, ambig); + if (ambig) + connect(cut, SIGNAL(activatedAmbiguously()), this, ambig); connect(cut, SIGNAL(destroyed(QObject*)), this, SLOT(shortcutDestroyed(QObject*))); shortcuts.append(cut); return cut; -- cgit v1.2.3 From 1e15b428b59c3134a0f584bfb303e95d0682e45d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Tue, 12 Jan 2016 16:52:03 +0100 Subject: Fix shortcut modifiers not being propagated after c7e5e1d9e MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The code-path used by non-OSX platforms were not passing on the native scan-code, virtual key, and modifiers, breaking QKeyMapper::possibleKeys in the process. Task-number: QTBUG-50360 Change-Id: Idc36380a234f0a37d016dbeaca594aeb82c496d2 Reviewed-by: Simon Hausmann Reviewed-by: Błażej Szczygieł --- src/gui/kernel/qwindowsysteminterface.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/gui/kernel/qwindowsysteminterface.cpp b/src/gui/kernel/qwindowsysteminterface.cpp index 8a46e7009b..d17a1f1d5b 100644 --- a/src/gui/kernel/qwindowsysteminterface.cpp +++ b/src/gui/kernel/qwindowsysteminterface.cpp @@ -275,8 +275,10 @@ bool QWindowSystemInterface::handleExtendedKeyEvent(QWindow *tlw, ulong timestam const QString& text, bool autorep, ushort count, bool tryShortcutOverride) { - if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(tlw, timestamp, key, modifiers, 0, 0, 0, text, autorep, count)) + if (tryShortcutOverride && type == QEvent::KeyPress && QWindowSystemInterface::handleShortcutEvent(tlw, + timestamp, key, modifiers, nativeScanCode, nativeVirtualKey, nativeModifiers, text, autorep, count)) { return true; + } QWindowSystemInterfacePrivate::KeyEvent * e = new QWindowSystemInterfacePrivate::KeyEvent(tlw, timestamp, type, key, modifiers, -- cgit v1.2.3 From e770728a336d3218ad8b13c04bbea3324d241b48 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?S=C3=A9rgio=20Martins?= Date: Tue, 12 Jan 2016 00:21:26 +0000 Subject: Add Qt6 TODO to remove copy-assign operator and copy-ctor Change-Id: I5d80b272f31ada58d4eb7c19051fe447d6241633 Reviewed-by: Marc Mutz --- src/corelib/thread/qexception.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/thread/qexception.h b/src/corelib/thread/qexception.h index b15ae5095a..dc988f9020 100644 --- a/src/corelib/thread/qexception.h +++ b/src/corelib/thread/qexception.h @@ -86,7 +86,7 @@ class Q_CORE_EXPORT ExceptionHolder public: ExceptionHolder(QException *exception = Q_NULLPTR); ExceptionHolder(const ExceptionHolder &other); - void operator=(const ExceptionHolder &other); + void operator=(const ExceptionHolder &other); // ### Qt6: copy-assign operator shouldn't return void. Remove this method and the copy-ctor, they are unneeded. ~ExceptionHolder(); QException *exception() const; QExplicitlySharedDataPointer base; -- cgit v1.2.3 From 61169b72c24b336af23702fda1e86d1d1c2c8095 Mon Sep 17 00:00:00 2001 From: Marc Mutz Date: Wed, 6 Jan 2016 10:36:41 +0100 Subject: Fix UB in QIODevicePrivate Passing nullptr as the second argument of memcpy/memmove constitutes undefined behavior, even if the length argument is zero at the same time. Fix by protecting mem{cpy,move,chr} from nullptrs. Found by UBSan: qtbase/src/corelib/io/qiodevice_p.h:105:33: runtime error: null pointer passed as argument 2, which is declared to never be null qtbase/src/corelib/io/qiodevice_p.h:175:53: runtime error: null pointer passed as argument 2, which is declared to never be null Change-Id: I979158b0a74169ca4eb459928398ebc40f77dfb5 Reviewed-by: Alex Trotsenko Reviewed-by: Thiago Macieira --- src/corelib/io/qiodevice_p.h | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/src/corelib/io/qiodevice_p.h b/src/corelib/io/qiodevice_p.h index f4cf387eb5..8342176cff 100644 --- a/src/corelib/io/qiodevice_p.h +++ b/src/corelib/io/qiodevice_p.h @@ -102,14 +102,17 @@ public: } qint64 read(char* target, qint64 size) { qint64 r = qMin(size, len); - memcpy(target, first, r); - len -= r; - first += r; + if (r) { + memcpy(target, first, r); + len -= r; + first += r; + } return r; } qint64 peek(char* target, qint64 size) { qint64 r = qMin(size, len); - memcpy(target, first, r); + if (r) + memcpy(target, first, r); return r; } char* reserve(qint64 size) { @@ -141,7 +144,7 @@ public: return r; } bool canReadLine() const { - return memchr(first, '\n', len); + return first && memchr(first, '\n', len); } void ungetChar(char c) { if (first == buf) { @@ -172,7 +175,8 @@ private: if (newCapacity > capacity) { // allocate more space char* newBuf = new char[newCapacity]; - memmove(newBuf + moveOffset, first, len); + if (first) + memmove(newBuf + moveOffset, first, len); delete [] buf; buf = newBuf; capacity = newCapacity; -- cgit v1.2.3 From 8c89a8b1ef3e4ce549a5d0bbc4168c199e44f8cf Mon Sep 17 00:00:00 2001 From: Andy Shaw Date: Fri, 8 Jan 2016 13:45:44 +0100 Subject: [Android]: Java uses some deprecated locale codes so account for these There are three deprecated language codes that Java still uses for the locale so we need to account for these inside QLocale by mapping them to the right language. Task-number: QTBUG-49632 Change-Id: Ib66b3f2763e085f7384228f2490b048bb56be259 Reviewed-by: Lars Knoll --- src/corelib/tools/qlocale.cpp | 7 +++++++ tests/auto/corelib/tools/qlocale/tst_qlocale.cpp | 3 ++- 2 files changed, 9 insertions(+), 1 deletion(-) diff --git a/src/corelib/tools/qlocale.cpp b/src/corelib/tools/qlocale.cpp index b1f53dc7a2..890a8fb95d 100644 --- a/src/corelib/tools/qlocale.cpp +++ b/src/corelib/tools/qlocale.cpp @@ -116,6 +116,13 @@ QLocale::Language QLocalePrivate::codeToLanguage(const QString &code) Q_STATIC_ASSERT(QLocale::Moldavian == QLocale::Romanian); return QLocale::Moldavian; } + // Android uses the following deprecated codes + if (uc1 == 'i' && uc2 == 'w' && uc3 == 0) // iw -> he + return QLocale::Hebrew; + if (uc1 == 'i' && uc2 == 'n' && uc3 == 0) // in -> id + return QLocale::Indonesian; + if (uc1 == 'j' && uc2 == 'i' && uc3 == 0) // ji -> yi + return QLocale::Yiddish; return QLocale::C; } diff --git a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp index 0466ced10a..5f046575c4 100644 --- a/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp +++ b/tests/auto/corelib/tools/qlocale/tst_qlocale.cpp @@ -613,7 +613,8 @@ void tst_QLocale::legacyNames() TEST_CTOR("no", Norwegian, Norway) TEST_CTOR("sh_ME", Serbian, Montenegro) TEST_CTOR("tl", Filipino, Philippines) - + TEST_CTOR("iw", Hebrew, Israel) + TEST_CTOR("in", Indonesian, Indonesia) #undef TEST_CTOR } -- cgit v1.2.3 From eef772577594b59d9cee5d55da5c47cd81008735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Tue, 12 Jan 2016 13:02:05 +0100 Subject: eglfs: Round value returned from pixelDensity() Avoid returning fractional scale factors, which we do not support. This matches the pixelDensity() implementation for the Xcb and Windows platform plugins. Change-Id: I79156e802a0a436b9344f12d35d1f4861e20e7fa Reviewed-by: Mitch Curtis --- src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp index 8af48a893b..1fb6020d69 100644 --- a/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp +++ b/src/plugins/platforms/eglfs/qeglfsdeviceintegration.cpp @@ -224,7 +224,7 @@ QDpi QEGLDeviceIntegration::logicalDpi() const qreal QEGLDeviceIntegration::pixelDensity() const { - return logicalDpi().first / qreal(100); + return qRound(logicalDpi().first / qreal(100)); } Qt::ScreenOrientation QEGLDeviceIntegration::nativeOrientation() const -- cgit v1.2.3 From cd9625fc3cacb4efd0da57d9f5780671f5c1310f Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Wed, 6 Jan 2016 14:40:50 +0100 Subject: Correct floordiv() to cope with implementation-defined division. Irrelevant once we get to C++11 (so we can revert this in 5.7), but division's rounding direction is implementation defined when either operand is negative [0]. The prior code assumed C++11's truncation (a.k.a. round towards zero), but rounding may be downwards instead. [0] http://en.cppreference.com/w/cpp/language/operator_arithmetic#Multiplicative_operators Change-Id: I2b6b27e1cf629def48b25433e81b9ed8230d8795 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetime.cpp | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qdatetime.cpp b/src/corelib/tools/qdatetime.cpp index fa4ac2b00f..ff20c57166 100644 --- a/src/corelib/tools/qdatetime.cpp +++ b/src/corelib/tools/qdatetime.cpp @@ -90,14 +90,25 @@ static inline QDate fixedDate(int y, int m, int d) return result; } +/* + Until C++11, rounding direction is implementation-defined. + + For negative operands, implementations may chose to round down instead of + towards zero (truncation). We only actually care about the case a < 0, as all + uses of floordiv have b > 0. In this case, if rounding is down we have a % b + >= 0 and simple division works fine; but a % b = a - (a / b) * b always, so + rounding towards zero gives a % b <= 0; when < 0, we need to adjust. + + Once we assume C++11, we can safely test a < 0 instead of a % b < 0. + */ static inline qint64 floordiv(qint64 a, int b) { - return (a - (a < 0 ? b-1 : 0)) / b; + return (a - (a % b < 0 ? b - 1 : 0)) / b; } static inline int floordiv(int a, int b) { - return (a - (a < 0 ? b-1 : 0)) / b; + return (a - (a % b < 0 ? b - 1 : 0)) / b; } static inline qint64 julianDayFromDate(int year, int month, int day) -- cgit v1.2.3 From dc1f65d4cf4a758ea99effe1781f859f92f9d1fc Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Thu, 19 Nov 2015 17:11:05 +0100 Subject: make module .pri files more flexible save the actual library/framework name and framework paths in the .pri file instead of computing them again at use time in qt.prf. qt_no_framework_direct_includes inherently requires a use-time decision, so this ugliness remains. Change-Id: I09b2775e7d8e1d52e3af0d663e1babde10ae4814 Reviewed-by: Joerg Bornemann Reviewed-by: Oswald Buddenhagen --- mkspecs/features/qt.prf | 78 ++++++++++++++++++++----------------- mkspecs/features/qt_module_pris.prf | 30 ++++++++------ 2 files changed, 62 insertions(+), 46 deletions(-) diff --git a/mkspecs/features/qt.prf b/mkspecs/features/qt.prf index 72632a14ee..f62b6bb139 100644 --- a/mkspecs/features/qt.prf +++ b/mkspecs/features/qt.prf @@ -67,8 +67,10 @@ for(ever) { unset(BAD_QT) for(QTLIB, FULL_QT$$var_sfx) { MODULE_NAME = $$eval(QT.$${QTLIB}.name) + MODULE_MODULE = $$eval(QT.$${QTLIB}.module) MODULE_INCLUDES = $$eval(QT.$${QTLIB}.includes) MODULE_LIBS = $$eval(QT.$${QTLIB}.libs) + MODULE_FRAMEWORKS = $$eval(QT.$${QTLIB}.frameworks) MODULE_CONFIG = $$eval(QT.$${QTLIB}.module_config) isEmpty(MODULE_NAME) { @@ -88,49 +90,55 @@ for(ever) { MODULE_LIBS_ADD = $$MODULE_LIBS MODULE_LIBS_ADD -= $$QMAKE_DEFAULT_LIBDIRS - LINKAGE = - contains(MODULE_CONFIG, lib_bundle) { - FRAMEWORK_INCLUDE = $${MODULE_LIBS}/$${MODULE_NAME}.framework/Headers - !qt_no_framework_direct_includes { - INCLUDEPATH *= $$FRAMEWORK_INCLUDE + !contains(MODULE_CONFIG, v2) { + # Backwards compatibility with pre-5.6 module .pri files + + contains(MODULE_CONFIG, lib_bundle) { + MODULE_FRAMEWORKS = $$MODULE_LIBS + inc = $$MODULE_LIBS/$${MODULE_NAME}.framework/Headers + MODULE_INCLUDES = $$inc + contains(MODULE_CONFIG, internal_module): \ + MODULE_INCLUDES += \ + $$inc/$$eval(QT.$${QTLIB}.VERSION) \ + $$inc/$$eval(QT.$${QTLIB}.VERSION)/$$MODULE_NAME + } else { + # Re-insert the major version in the library name (cf qt5LibraryTarget above) + MODULE_NAME ~= s,^Qt,Qt$$QT_MAJOR_VERSION, } - contains(MODULE_CONFIG, internal_module): \ - INCLUDEPATH += \ - $$FRAMEWORK_INCLUDE/$$eval(QT.$${QTLIB}.VERSION) \ - $$FRAMEWORK_INCLUDE/$$eval(QT.$${QTLIB}.VERSION)/$$MODULE_NAME - QMAKE_FRAMEWORKPATH *= $${MODULE_LIBS} - !contains(MODULE_CONFIG, no_link): \ - LINKAGE += -framework $${MODULE_NAME}$${QT_LIBINFIX} - } else { - INCLUDEPATH *= $$MODULE_INCLUDES - } - - # Only link to this module if a libs directory is set, else this is just a module - # to give access to sources or include files, and not for linking. - !isEmpty(MODULE_LIBS):!contains(MODULE_CONFIG, no_link) { - # Re-insert the major version in the library name (cf qt5LibraryTarget above) - # unless it's a framework build - !contains(MODULE_CONFIG, lib_bundle): \ - MODULE_NAME ~= s,^Qt,Qt$$QT_MAJOR_VERSION, + # Only link to this module if a libs directory is set, else this is just a module + # to give access to sources or include files, and not for linking. + !isEmpty(MODULE_LIBS):!contains(MODULE_CONFIG, no_link): \ + MODULE_MODULE = $${MODULE_NAME}$${QT_LIBINFIX} + } - isEmpty(LINKAGE) { + # Frameworks shouldn't need include paths, but much code does not use + # module-qualified #includes, so by default we add paths which point + # directly into the frameworks. Private modules have somewhat convoluted + # header paths, so adding them is necessary in every case. + !if(contains(MODULE_CONFIG, lib_bundle):qt_no_framework_direct_includes) \ + |contains(MODULE_CONFIG, internal_module): \ + INCLUDEPATH *= $$MODULE_INCLUDES + QMAKE_FRAMEWORKPATH *= $$MODULE_FRAMEWORKS + !isEmpty(MODULE_MODULE) { + contains(MODULE_CONFIG, lib_bundle) { + LIBS$$var_sfx += -framework $$MODULE_MODULE + } else { !isEmpty(MODULE_LIBS_ADD): \ - LINKAGE = -L$$MODULE_LIBS_ADD - lib = $${MODULE_NAME}$${QT_LIBINFIX}$$qtPlatformTargetSuffix() - LINKAGE += -l$$lib + LIBS$$var_sfx += -L$$MODULE_LIBS_ADD + + lib = $$MODULE_MODULE$$qtPlatformTargetSuffix() + LIBS$$var_sfx += -l$$lib contains(MODULE_CONFIG, staticlib): \ PRE_TARGETDEPS *= $$MODULE_LIBS/$${QMAKE_PREFIX_STATICLIB}$${lib}.$${QMAKE_EXTENSION_STATICLIB} - } - LIBS$$var_sfx += $$LINKAGE - - !isEmpty(QMAKE_LSB) { - !isEmpty(MODULE_LIBS_ADD): \ - QMAKE_LFLAGS *= --lsb-libpath=$$MODULE_LIBS_ADD - QMAKE_LFLAGS *= --lsb-shared-libs=$${MODULE_NAME}$${QT_LIBINFIX} - QMAKE_LIBDIR *= /opt/lsb/lib + !isEmpty(QMAKE_LSB) { + !isEmpty(MODULE_LIBS_ADD): \ + QMAKE_LFLAGS *= --lsb-libpath=$$MODULE_LIBS_ADD + QMAKE_LFLAGS *= --lsb-shared-libs=$$lib + QMAKE_LIBDIR *= /opt/lsb/lib + } } } } diff --git a/mkspecs/features/qt_module_pris.prf b/mkspecs/features/qt_module_pris.prf index fdcb9df270..e293a0a4e5 100644 --- a/mkspecs/features/qt_module_pris.prf +++ b/mkspecs/features/qt_module_pris.prf @@ -46,18 +46,22 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri module_rundep = "QT.$${MODULE_ID}.run_depends = $$replace(QT_PRIVATE, -private$, _private)" else: \ module_rundep = + module_build_type = v2 static: \ - module_build_type = staticlib - else: lib_bundle: \ - module_build_type = lib_bundle - else: \ - module_build_type = - equals(TEMPLATE, aux): \ - module_build_type += no_link + module_build_type += staticlib + lib_bundle { + module_build_type += lib_bundle + MODULE_FRAMEWORKS = " \$\$QT_MODULE_LIB_BASE" + } internal_module: \ module_build_type += internal_module ltcg: \ module_build_type += ltcg + module_module = + !equals(TEMPLATE, aux) { + module_module = $$TARGET$$QT_LIBINFIX + !lib_bundle: module_module ~= s,^Qt,Qt$$QT_MAJOR_VERSION, + } !isEmpty(MODULE_CONFIG): \ module_config = "QT.$${MODULE_ID}.CONFIG = $$MODULE_CONFIG" else: \ @@ -77,9 +81,11 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri "QT.$${MODULE_ID}.PATCH_VERSION = $$section(VERSION, ., 2, 2)" \ "" \ "QT.$${MODULE_ID}.name = $$TARGET" \ + "QT.$${MODULE_ID}.module = $$module_module" \ "QT.$${MODULE_ID}.libs = $$module_libs" \ $$module_master \ - "QT.$${MODULE_ID}.includes = $$MODULE_INCLUDES" + "QT.$${MODULE_ID}.includes = $$MODULE_INCLUDES" \ + "QT.$${MODULE_ID}.frameworks =$$MODULE_FRAMEWORKS" !host_build: MODULE_PRI_CONT += \ "QT.$${MODULE_ID}.bins = \$\$QT_MODULE_BIN_BASE" \ "QT.$${MODULE_ID}.libexecs = \$\$QT_MODULE_LIBEXEC_BASE" \ @@ -97,7 +103,7 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri "QT_MODULES += $$MODULE" write_file($$MODULE_PRI, MODULE_PRI_CONT)|error("Aborting.") !internal_module:!no_private_module { - module_build_type += internal_module no_link + module_build_type += internal_module MODULE_PRIVATE_PRI_CONT = \ "QT.$${MODULE}_private.VERSION = $${VERSION}" \ "QT.$${MODULE}_private.MAJOR_VERSION = $$section(VERSION, ., 0, 0)" \ @@ -105,8 +111,10 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri "QT.$${MODULE}_private.PATCH_VERSION = $$section(VERSION, ., 2, 2)" \ "" \ "QT.$${MODULE}_private.name = $${TARGET}" \ # Same name as base module + "QT.$${MODULE}_private.module =" \ "QT.$${MODULE}_private.libs = $$module_libs" \ "QT.$${MODULE}_private.includes = $$MODULE_PRIVATE_INCLUDES" \ + "QT.$${MODULE}_private.frameworks =" \ "QT.$${MODULE}_private.depends = $$replace($$list($$MODULE $$QT_FOR_PRIVATE), -private$, _private)" \ "QT.$${MODULE}_private.module_config =$$join(module_build_type, " ", " ")" write_file($$MODULE_PRIVATE_PRI, MODULE_PRIVATE_PRI_CONT)|error("Aborting.") @@ -169,8 +177,8 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri include($$mod_work_pfx/qt_lib_$${pri}.pri) for(mod, mods_to_load) { for(var, $$list(VERSION MAJOR_VERSION MINOR_VERSION PATCH_VERSION \ - name depends run_depends plugin_types module_config CONFIG DEFINES \ - priority includes bins libs libexecs plugins imports qml \ + name module depends run_depends plugin_types module_config CONFIG DEFINES \ + priority includes bins libs frameworks libexecs plugins imports qml \ )):defined(QT.$${mod}.$$var, var):cache(QT.$${mod}.$$var, transient) } cache(QT_MODULES, transient) -- cgit v1.2.3 From b8bee40726fc93db9a025324712de6fff6a084d5 Mon Sep 17 00:00:00 2001 From: Oswald Buddenhagen Date: Fri, 8 Jan 2016 18:45:21 +0100 Subject: unbreak propagation of dependencies on private modules most module project files define two logical modules: a public one and the corresponding private one. these are really separate modules as far as qmake is concerned (even though the private one contains just headers), and consequently have separate dependencies - QT and QT_FOR_PRIVATE. as public modules cannot depend on private ones, all private dependencies would have to go to QT_FOR_PRIVATE, and a dependency on the respective public module would have to be added to QT. this would be a bit tedious, so we have a convenience feature which allows putting private dependencies into QT, but automatically "downgrades" them to their public counterpart when creating the public module's .pri file. however, we failed to put verbatim versions of these private dependencies into the private modules, which meant that these dependencies were not pulled in transitively by the private modules' users. note that this entirely unrelated to QT_PRIVATE - this one defines the private (non-propagated) dependencies of the module's implementation, i.e., the libraries (and headers) that are not part of the link interface. there is no QT_PRIVATE_FOR_PRIVATE, because there is obviously no point in assigning the dependencies to a particular logical submodule when neither one inherits them as far as the qt module system is concerned. Change-Id: Ib056b47dde3341ef9a52ffff13efaf8ef8e6817b Reviewed-by: Joerg Bornemann Reviewed-by: Thiago Macieira --- mkspecs/features/qt_module_pris.prf | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/qt_module_pris.prf b/mkspecs/features/qt_module_pris.prf index e293a0a4e5..5f5639a1cf 100644 --- a/mkspecs/features/qt_module_pris.prf +++ b/mkspecs/features/qt_module_pris.prf @@ -104,6 +104,10 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri write_file($$MODULE_PRI, MODULE_PRI_CONT)|error("Aborting.") !internal_module:!no_private_module { module_build_type += internal_module + private_deps = $$QT + private_deps -= $$MODULE_DEPENDS + private_deps += $$MODULE $$QT_FOR_PRIVATE + private_deps ~= s,-private$,_private,g MODULE_PRIVATE_PRI_CONT = \ "QT.$${MODULE}_private.VERSION = $${VERSION}" \ "QT.$${MODULE}_private.MAJOR_VERSION = $$section(VERSION, ., 0, 0)" \ @@ -115,7 +119,7 @@ MODULE_FWD_PRI = $$mod_work_pfx/qt_lib_$${MODULE_ID}.pri "QT.$${MODULE}_private.libs = $$module_libs" \ "QT.$${MODULE}_private.includes = $$MODULE_PRIVATE_INCLUDES" \ "QT.$${MODULE}_private.frameworks =" \ - "QT.$${MODULE}_private.depends = $$replace($$list($$MODULE $$QT_FOR_PRIVATE), -private$, _private)" \ + "QT.$${MODULE}_private.depends = $$private_deps" \ "QT.$${MODULE}_private.module_config =$$join(module_build_type, " ", " ")" write_file($$MODULE_PRIVATE_PRI, MODULE_PRIVATE_PRI_CONT)|error("Aborting.") } -- cgit v1.2.3 From a9c0a83207599599c2ff67ff00fc7e0cc638a870 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Wed, 13 Jan 2016 13:17:43 +0100 Subject: xcb: Don't duplicate expose events MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Use ExposeCompressor for mapping the window to prevent duplicating expose event when window is mapped. Remove sending expose event from configure notivy event. Change-Id: I6836c06047ffebd65775aa8aca90750afba6efe8 Reviewed-by: Tor Arne Vestbø --- src/plugins/platforms/xcb/qxcbwindow.cpp | 37 ++++++++++++++------------------ src/plugins/platforms/xcb/qxcbwindow.h | 2 ++ 2 files changed, 18 insertions(+), 21 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbwindow.cpp b/src/plugins/platforms/xcb/qxcbwindow.cpp index 4e4a0cdaef..c6eb5aa66b 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.cpp +++ b/src/plugins/platforms/xcb/qxcbwindow.cpp @@ -1885,6 +1885,17 @@ private: bool m_pending; }; +bool QXcbWindow::compressExposeEvent(QRegion &exposeRegion) +{ + ExposeCompressor compressor(m_window, &exposeRegion); + xcb_generic_event_t *filter = 0; + do { + filter = connection()->checkEvent(compressor); + free(filter); + } while (filter); + return compressor.pending(); +} + bool QXcbWindow::handleGenericEvent(xcb_generic_event_t *event, long *result) { return QWindowSystemInterface::handleNativeEvent(window(), @@ -1902,15 +1913,10 @@ void QXcbWindow::handleExposeEvent(const xcb_expose_event_t *event) else m_exposeRegion |= rect; - ExposeCompressor compressor(m_window, &m_exposeRegion); - xcb_generic_event_t *filter = 0; - do { - filter = connection()->checkEvent(compressor); - free(filter); - } while (filter); + bool pending = compressExposeEvent(m_exposeRegion); // if count is non-zero there are more expose events pending - if (event->count == 0 || !compressor.pending()) { + if (event->count == 0 || !pending) { QWindowSystemInterface::handleExposeEvent(window(), m_exposeRegion); m_exposeRegion = QRegion(); } @@ -1997,10 +2003,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * } } - // The original geometry requested by setGeometry() might be different - // from what we end up with after applying window constraints. - QRect requestedGeometry = geometry(); - const QRect actualGeometry = QRect(pos, QSize(event->width, event->height)); QPlatformScreen *newScreen = parent() ? parent()->screen() : screenForGeometry(actualGeometry); if (!newScreen) @@ -2021,15 +2023,6 @@ void QXcbWindow::handleConfigureNotifyEvent(const xcb_configure_notify_event_t * // will make the comparison later. QWindowSystemInterface::handleWindowScreenChanged(window(), newScreen->screen()); - // For expose events we have no way of telling QGuiApplication to used the locally - // cached version of the previous state, so we may in some situations end up with - // an additional expose event. - QRect previousGeometry = requestedGeometry != actualGeometry ? - requestedGeometry : qt_window_private(window())->geometry; - - if (m_mapped && actualGeometry.size() != previousGeometry.size()) - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), actualGeometry.size())); - if (m_usingSyncProtocol && m_syncState == SyncReceived) m_syncState = SyncAndConfigureReceived; @@ -2096,7 +2089,9 @@ void QXcbWindow::handleMapNotifyEvent(const xcb_map_notify_event_t *event) if (m_deferredActivation) requestActivateWindow(); - QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); + QRegion exposeRegion = QRect(QPoint(), geometry().size()); + compressExposeEvent(exposeRegion); + QWindowSystemInterface::handleExposeEvent(window(), exposeRegion); } } diff --git a/src/plugins/platforms/xcb/qxcbwindow.h b/src/plugins/platforms/xcb/qxcbwindow.h index 3cfa71c9e0..d2c02fe3df 100644 --- a/src/plugins/platforms/xcb/qxcbwindow.h +++ b/src/plugins/platforms/xcb/qxcbwindow.h @@ -201,6 +201,8 @@ protected: void doFocusIn(); void doFocusOut(); + bool compressExposeEvent(QRegion &exposeRegion); + void handleButtonPressEvent(int event_x, int event_y, int root_x, int root_y, int detail, Qt::KeyboardModifiers modifiers, xcb_timestamp_t timestamp); -- cgit v1.2.3 From 7b63c45df58a97bb3e800dd5fe20f41e11f92c62 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Sat, 2 Jan 2016 23:04:09 +0100 Subject: QtWidgets: Don't show window of native widget with WA_OutsideWSRange This patch prevents visibility of native widgets which for some reasons has width or height of 0. Due to async expose event in Qt5 we must force "hide_sys()" during resizing for widgets with WA_OutsideWSRange flag. This avoid problems for non-native and visible widgets which are converted to native and then resized: child->winId(); child->resize(0, 0); Task-number: QTBUG-49445 Change-Id: Ied62a4f253f89447941b2dc03316db8c168f4bb5 Reviewed-by: Ulf Hermann --- src/widgets/kernel/qwidget.cpp | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/widgets/kernel/qwidget.cpp b/src/widgets/kernel/qwidget.cpp index 229cfc0f85..d2e760da90 100644 --- a/src/widgets/kernel/qwidget.cpp +++ b/src/widgets/kernel/qwidget.cpp @@ -1487,9 +1487,12 @@ void QWidgetPrivate::create_sys(WId window, bool initializeWindow, bool destroyO if (extra && !extra->mask.isEmpty()) setMask_sys(extra->mask); - // If widget is already shown, set window visible, too - if (q->isVisible()) + if (data.crect.width() == 0 || data.crect.height() == 0) { + q->setAttribute(Qt::WA_OutsideWSRange, true); + } else if (q->isVisible()) { + // If widget is already shown, set window visible, too win->setVisible(true); + } } #ifdef Q_OS_WIN @@ -7210,7 +7213,7 @@ void QWidgetPrivate::setGeometry_sys(int x, int y, int w, int h, bool isMove) if (q->isWindow() || q->windowHandle()) { if (!(data.window_state & Qt::WindowFullScreen) && (w == 0 || h == 0)) { q->setAttribute(Qt::WA_OutsideWSRange, true); - if (q->isVisible() && q->testAttribute(Qt::WA_Mapped)) + if (q->isVisible()) hide_sys(); data.crect = QRect(x, y, w, h); } else if (q->isVisible() && q->testAttribute(Qt::WA_OutsideWSRange)) { @@ -7927,8 +7930,10 @@ void QWidgetPrivate::show_sys() else QApplication::postEvent(q, new QUpdateLaterEvent(q->rect())); - if (!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow)) + if ((!q->isWindow() && !q->testAttribute(Qt::WA_NativeWindow)) + || q->testAttribute(Qt::WA_OutsideWSRange)) { return; + } if (window) { if (q->isWindow()) -- cgit v1.2.3 From b5447f9c331cf5367ac7a35f57e5099c5c100b73 Mon Sep 17 00:00:00 2001 From: Volker Krause Date: Tue, 12 Jan 2016 10:40:43 +0100 Subject: QtConcurrent: Avoid an allocation in ExceptionHolder if there is no exception to store. Qt3D hits this several times per frame. Change-Id: Iaadcfbe79f146bd73b36f01325580dc24a10225c Reviewed-by: Marc Mutz --- src/corelib/thread/qexception.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/corelib/thread/qexception.cpp b/src/corelib/thread/qexception.cpp index 04a03b8623..cecd69c273 100644 --- a/src/corelib/thread/qexception.cpp +++ b/src/corelib/thread/qexception.cpp @@ -165,7 +165,7 @@ public: }; ExceptionHolder::ExceptionHolder(QException *exception) -: base(new Base(exception)) {} +: base(exception ? new Base(exception) : Q_NULLPTR) {} ExceptionHolder::ExceptionHolder(const ExceptionHolder &other) : base(other.base) @@ -181,6 +181,8 @@ ExceptionHolder::~ExceptionHolder() QException *ExceptionHolder::exception() const { + if (!base) + return Q_NULLPTR; return base->exception; } -- cgit v1.2.3 From f831c97a084d0781ecaa378cc8f54cf8ba4716fd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= Date: Wed, 13 Jan 2016 21:24:15 +0100 Subject: Replace QStringLiteral with QLatin1String in QFileSelector Change-Id: I5c109d26bf5252947ae016465db5675e38cd68c9 Reviewed-by: Marc Mutz --- src/corelib/io/qfileselector.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index 85d9b0bfcb..f033392df8 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -227,9 +227,9 @@ QString QFileSelector::select(const QString &filePath) const static bool isLocalScheme(const QString &file) { - bool local = file == QStringLiteral("qrc"); + bool local = file == QLatin1String("qrc"); #ifdef Q_OS_ANDROID - local |= file == QStringLiteral("assets"); + local |= file == QLatin1String("assets"); #endif return local; } -- cgit v1.2.3 From c3376ed3f90179586aa7a82730fa972dcd4cf5cd Mon Sep 17 00:00:00 2001 From: Maurice Kalinowski Date: Wed, 13 Jan 2016 12:57:18 +0100 Subject: winrt: enable hardware buttons for Windows 10 Previously the hardware and camera button handler were guarded inside a Q_OS_WINPHONE which does not apply to Windows 10. Instead use WINAPI_PARTITION_FAMILY like on other places, this covers Windows Phone 8.1 as well as Windows 10. To find windows.phone.ui.input.h at build time the Mobile Extension directory needs to be added to the include paths inside qmake. On runtime we need to check whether we have hardware buttons or not. In case they exist, register the handlers, otherwise skip registration. Skipping also helps to keep WACK succeeding. Task-number: QTBUG-50427 Change-Id: Ibeae15dbde12553cebd2b73b1a40b754c014f426 Reviewed-by: Oliver Wolff --- qmake/generators/win32/msvc_nmake.cpp | 3 + src/plugins/platforms/winrt/qwinrtintegration.cpp | 97 +++++++++++++++-------- src/plugins/platforms/winrt/qwinrtintegration.h | 4 +- 3 files changed, 67 insertions(+), 37 deletions(-) diff --git a/qmake/generators/win32/msvc_nmake.cpp b/qmake/generators/win32/msvc_nmake.cpp index 06c99b6e38..d6753b4ed6 100644 --- a/qmake/generators/win32/msvc_nmake.cpp +++ b/qmake/generators/win32/msvc_nmake.cpp @@ -193,6 +193,9 @@ NmakeMakefileGenerator::writeMakefile(QTextStream &t) incDirs << crtInclude + QStringLiteral("/shared"); incDirs << crtInclude + QStringLiteral("/winrt"); + incDirs << kitDir + QStringLiteral("Extension SDKs/WindowsMobile/") + + crtVersion + QStringLiteral("/Include/WinRT"); + libDirs << vcInstallDir + QStringLiteral("lib/store/") + compilerArch; libDirs << vcInstallDir + QStringLiteral("atlmfc/lib") + compilerArch; diff --git a/src/plugins/platforms/winrt/qwinrtintegration.cpp b/src/plugins/platforms/winrt/qwinrtintegration.cpp index 71e92f33ca..2281bf56cc 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.cpp +++ b/src/plugins/platforms/winrt/qwinrtintegration.cpp @@ -59,10 +59,16 @@ #include #include #include -#ifdef Q_OS_WINPHONE + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) # include +# if _MSC_VER >= 1900 +# include + using namespace ABI::Windows::Foundation::Metadata; +# endif #endif + using namespace Microsoft::WRL; using namespace Microsoft::WRL::Wrappers; using namespace ABI::Windows::Foundation; @@ -73,13 +79,13 @@ using namespace ABI::Windows::UI::Core; using namespace ABI::Windows::UI::ViewManagement; using namespace ABI::Windows::Graphics::Display; using namespace ABI::Windows::ApplicationModel::Core; -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) using namespace ABI::Windows::Phone::UI::Input; #endif typedef IEventHandler ResumeHandler; typedef IEventHandler SuspendHandler; -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) typedef IEventHandler BackPressedHandler; typedef IEventHandler CameraButtonHandler; #endif @@ -88,7 +94,7 @@ QT_BEGIN_NAMESPACE typedef HRESULT (__stdcall ICoreApplication::*CoreApplicationCallbackRemover)(EventRegistrationToken); uint qHash(CoreApplicationCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) typedef HRESULT (__stdcall IHardwareButtonsStatics::*HardwareButtonsCallbackRemover)(EventRegistrationToken); uint qHash(HardwareButtonsCallbackRemover key) { void *ptr = *(void **)(&key); return qHash(ptr); } typedef HRESULT (__stdcall IHardwareButtonsStatics2::*HardwareButtons2CallbackRemover)(EventRegistrationToken); @@ -105,11 +111,12 @@ public: ComPtr application; QHash applicationTokens; -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) ComPtr hardwareButtons; QHash buttonsTokens; ComPtr cameraButtons; QHash cameraTokens; + boolean hasHardwareButtons; bool cameraHalfPressed : 1; bool cameraPressed : 1; #endif @@ -132,31 +139,48 @@ QWinRTIntegration::QWinRTIntegration() : d_ptr(new QWinRTIntegrationPrivate) &d->applicationTokens[&ICoreApplication::remove_Resuming]); Q_ASSERT_SUCCEEDED(hr); -#ifdef Q_OS_WINPHONE - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), - IID_PPV_ARGS(&d->hardwareButtons)); - Q_ASSERT_SUCCEEDED(hr); - hr = d->hardwareButtons->add_BackPressed(Callback(this, &QWinRTIntegration::onBackButtonPressed).Get(), - &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]); - Q_ASSERT_SUCCEEDED(hr); +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) +#if _MSC_VER >= 1900 + d->hasHardwareButtons = false; + ComPtr apiInformationStatics; + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Foundation_Metadata_ApiInformation).Get(), + IID_PPV_ARGS(&apiInformationStatics)); - hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), - IID_PPV_ARGS(&d->cameraButtons)); - Q_ASSERT_SUCCEEDED(hr); - if (qEnvironmentVariableIntValue("QT_QPA_ENABLE_CAMERA_KEYS")) { - hr = d->cameraButtons->add_CameraPressed(Callback(this, &QWinRTIntegration::onCameraPressed).Get(), - &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraPressed]); + if (SUCCEEDED(hr)) { + const HStringReference valueRef(L"Windows.Phone.UI.Input.HardwareButtons"); + hr = apiInformationStatics->IsTypePresent(valueRef.Get(), &d->hasHardwareButtons); + } +#else + d->hasHardwareButtons = true; +#endif // _MSC_VER >= 1900 + + if (d->hasHardwareButtons) { + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), + IID_PPV_ARGS(&d->hardwareButtons)); Q_ASSERT_SUCCEEDED(hr); - hr = d->cameraButtons->add_CameraHalfPressed(Callback(this, &QWinRTIntegration::onCameraHalfPressed).Get(), - &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraHalfPressed]); + hr = d->hardwareButtons->add_BackPressed(Callback(this, &QWinRTIntegration::onBackButtonPressed).Get(), + &d->buttonsTokens[&IHardwareButtonsStatics::remove_BackPressed]); Q_ASSERT_SUCCEEDED(hr); - hr = d->cameraButtons->add_CameraReleased(Callback(this, &QWinRTIntegration::onCameraReleased).Get(), - &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraReleased]); + + hr = RoGetActivationFactory(HString::MakeReference(RuntimeClass_Windows_Phone_UI_Input_HardwareButtons).Get(), + IID_PPV_ARGS(&d->cameraButtons)); Q_ASSERT_SUCCEEDED(hr); + if (qEnvironmentVariableIntValue("QT_QPA_ENABLE_CAMERA_KEYS")) { + hr = d->cameraButtons->add_CameraPressed(Callback(this, &QWinRTIntegration::onCameraPressed).Get(), + &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraPressed]); + Q_ASSERT_SUCCEEDED(hr); + hr = d->cameraButtons->add_CameraHalfPressed(Callback(this, &QWinRTIntegration::onCameraHalfPressed).Get(), + &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraHalfPressed]); + Q_ASSERT_SUCCEEDED(hr); + hr = d->cameraButtons->add_CameraReleased(Callback(this, &QWinRTIntegration::onCameraReleased).Get(), + &d->cameraTokens[&IHardwareButtonsStatics2::remove_CameraReleased]); + Q_ASSERT_SUCCEEDED(hr); + } + d->cameraPressed = false; + d->cameraHalfPressed = false; } - d->cameraPressed = false; - d->cameraHalfPressed = false; -#endif // Q_OS_WINPHONE +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) + QEventDispatcherWinRT::runOnXamlThread([d]() { d->mainScreen = new QWinRTScreen; @@ -172,14 +196,17 @@ QWinRTIntegration::~QWinRTIntegration() { Q_D(QWinRTIntegration); HRESULT hr; -#ifdef Q_OS_WINPHONE - for (QHash::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) { - hr = (d->hardwareButtons.Get()->*i.key())(i.value()); - Q_ASSERT_SUCCEEDED(hr); - } - for (QHash::const_iterator i = d->cameraTokens.begin(); i != d->cameraTokens.end(); ++i) { - hr = (d->cameraButtons.Get()->*i.key())(i.value()); - Q_ASSERT_SUCCEEDED(hr); + +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) + if (d->hasHardwareButtons) { + for (QHash::const_iterator i = d->buttonsTokens.begin(); i != d->buttonsTokens.end(); ++i) { + hr = (d->hardwareButtons.Get()->*i.key())(i.value()); + Q_ASSERT_SUCCEEDED(hr); + } + for (QHash::const_iterator i = d->cameraTokens.begin(); i != d->cameraTokens.end(); ++i) { + hr = (d->cameraButtons.Get()->*i.key())(i.value()); + Q_ASSERT_SUCCEEDED(hr); + } } #endif // Do not execute this on Windows Phone as the application is already @@ -289,7 +316,7 @@ QPlatformTheme *QWinRTIntegration::createPlatformTheme(const QString &name) cons // System-level integration points -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) HRESULT QWinRTIntegration::onBackButtonPressed(IInspectable *, IBackPressedEventArgs *args) { Q_D(QWinRTIntegration); @@ -339,7 +366,7 @@ HRESULT QWinRTIntegration::onCameraReleased(IInspectable *, ICameraEventArgs *) d->cameraPressed = false; return S_OK; } -#endif // Q_OS_WINPHONE +#endif // WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) HRESULT QWinRTIntegration::onSuspended(IInspectable *, ISuspendingEventArgs *) { diff --git a/src/plugins/platforms/winrt/qwinrtintegration.h b/src/plugins/platforms/winrt/qwinrtintegration.h index 31a3ce7c1c..9bf5d27973 100644 --- a/src/plugins/platforms/winrt/qwinrtintegration.h +++ b/src/plugins/platforms/winrt/qwinrtintegration.h @@ -47,7 +47,7 @@ namespace ABI { namespace Foundation { struct IAsyncAction; } -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) namespace Phone { namespace UI { namespace Input { @@ -100,7 +100,7 @@ public: QPlatformOffscreenSurface *createPlatformOffscreenSurface(QOffscreenSurface *surface) const Q_DECL_OVERRIDE; private: -#ifdef Q_OS_WINPHONE +#if WINAPI_FAMILY_PARTITION(WINAPI_PARTITION_PHONE_APP) HRESULT onBackButtonPressed(IInspectable *, ABI::Windows::Phone::UI::Input::IBackPressedEventArgs *args); HRESULT onCameraPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *); HRESULT onCameraHalfPressed(IInspectable *, ABI::Windows::Phone::UI::Input::ICameraEventArgs *); -- cgit v1.2.3 From 18119a58def4e3537dd92b86e9c6115e6a21e866 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Thu, 14 Jan 2016 01:50:38 +0100 Subject: xcb: Don't clear alpha on every repaint Since 1bcfc3de7586ddb9f5d1b778b97b26ae3dc9584d every image has alpha in XCB even if it is not used by window. This patch prevents clearing the alpha channel on every repaint when window is not transparent. Change-Id: Icfdd39f8636401906ace77ea3c2fa25386979d5f Reviewed-by: Allan Sandfeld Jensen --- src/plugins/platforms/xcb/qxcbbackingstore.cpp | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) diff --git a/src/plugins/platforms/xcb/qxcbbackingstore.cpp b/src/plugins/platforms/xcb/qxcbbackingstore.cpp index 006df320fe..c34bea0242 100644 --- a/src/plugins/platforms/xcb/qxcbbackingstore.cpp +++ b/src/plugins/platforms/xcb/qxcbbackingstore.cpp @@ -67,6 +67,8 @@ public: QSize size() const { return m_qimage.size(); } + bool hasAlpha() const { return m_hasAlpha; } + void put(xcb_window_t window, const QPoint &dst, const QRect &source); void preparePaint(const QRegion ®ion); @@ -84,6 +86,8 @@ private: xcb_window_t m_gc_window; QRegion m_dirty; + + bool m_hasAlpha; }; class QXcbShmGraphicsBuffer : public QPlatformGraphicsBuffer @@ -173,7 +177,8 @@ QXcbShmImage::QXcbShmImage(QXcbScreen *screen, const QSize &size, uint depth, QI qWarning() << "QXcbBackingStore: Error while marking the shared memory segment to be destroyed"; } - if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::IgnoresAlpha) + m_hasAlpha = QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha; + if (!m_hasAlpha) format = qt_alphaVersionForPainting(format); m_qimage = QImage( (uchar*) m_xcb_image->data, m_xcb_image->width, m_xcb_image->height, m_xcb_image->stride, format); @@ -324,7 +329,7 @@ void QXcbBackingStore::beginPaint(const QRegion ®ion) m_paintRegion = region; m_image->preparePaint(m_paintRegion); - if (m_image->image()->hasAlphaChannel()) { + if (m_image->hasAlpha()) { QPainter p(paintDevice()); p.setCompositionMode(QPainter::CompositionMode_Source); const QVector rects = m_paintRegion.rects(); -- cgit v1.2.3 From 0bc4288689882e731fc1811c4de11fbc6d0c28ff Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 11 Jan 2016 11:32:44 +0100 Subject: Optimize OpenGL binding of ARGB32PM backing store Detect premultiplied backing store and upload it without conversion and adjust blend to not multiply alpha again. Task-number: QTBUG-50381 Change-Id: I51939c4f82fbb0c48eaca6e2475bf4cf3722bc2d Reviewed-by: Laszlo Agocs Reviewed-by: Gunnar Sletta --- src/gui/kernel/qplatformgraphicsbufferhelper.cpp | 34 ++++++++++++++++----- src/gui/kernel/qplatformgraphicsbufferhelper.h | 4 +-- src/gui/painting/qplatformbackingstore.cpp | 38 ++++++++++++++++++------ src/gui/painting/qplatformbackingstore.h | 3 +- 4 files changed, 60 insertions(+), 19 deletions(-) diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp index 1d59c38598..7f2672bc5e 100644 --- a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp +++ b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp @@ -64,7 +64,7 @@ QT_BEGIN_NAMESPACE bound texture, otherwise returns false. */ bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, - bool *swizzle, + bool *swizzle, bool *premultiplied, const QRect &rect) { if (graphicsBuffer->lock(QPlatformGraphicsBuffer::TextureAccess)) { @@ -74,8 +74,10 @@ bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer } if (swizzle) *swizzle = false; + if (premultiplied) + *premultiplied = false; } else if (graphicsBuffer->lock(QPlatformGraphicsBuffer::SWReadAccess)) { - if (!bindSWToTexture(graphicsBuffer, swizzle, rect)) { + if (!bindSWToTexture(graphicsBuffer, swizzle, premultiplied, rect)) { qWarning("Failed to bind %sgraphicsbuffer to texture", "SW "); return false; } @@ -109,7 +111,7 @@ bool QPlatformGraphicsBufferHelper::lockAndBindToTexture(QPlatformGraphicsBuffer Returns true on success, otherwise false. */ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, - bool *swizzleRandB, + bool *swizzleRandB, bool *premultipliedB, const QRect &subRect) { #ifndef QT_NO_OPENGL @@ -124,14 +126,30 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe Q_ASSERT(subRect.isEmpty() || QRect(QPoint(0,0), size).contains(subRect)); bool swizzle = false; + bool premultiplied = false; QImage::Format imageformat = QImage::toImageFormat(graphicsBuffer->format()); QImage image(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), imageformat); if (graphicsBuffer->bytesPerLine() != (size.width() * 4)) { image = image.convertToFormat(QImage::Format_RGBA8888); - } else if (imageformat == QImage::Format_RGB32) { - swizzle = true; - } else if (imageformat != QImage::Format_RGBA8888) { - image = image.convertToFormat(QImage::Format_RGBA8888); + } else { + switch (imageformat) { + case QImage::Format_ARGB32_Premultiplied: + premultiplied = true; + // no break + case QImage::Format_RGB32: + case QImage::Format_ARGB32: + swizzle = true; + break; + case QImage::Format_RGBA8888_Premultiplied: + premultiplied = true; + // no break + case QImage::Format_RGBX8888: + case QImage::Format_RGBA8888: + break; + default: + image = image.convertToFormat(QImage::Format_RGBA8888); + break; + } } QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); @@ -170,6 +188,8 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe } if (swizzleRandB) *swizzleRandB = swizzle; + if (premultipliedB) + *premultipliedB = premultiplied; return true; diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.h b/src/gui/kernel/qplatformgraphicsbufferhelper.h index ded7810608..cc1a4918cd 100644 --- a/src/gui/kernel/qplatformgraphicsbufferhelper.h +++ b/src/gui/kernel/qplatformgraphicsbufferhelper.h @@ -39,8 +39,8 @@ QT_BEGIN_NAMESPACE namespace QPlatformGraphicsBufferHelper { - bool lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB, const QRect &rect = QRect()); - bool bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB = Q_NULLPTR, const QRect &rect = QRect()); + bool lockAndBindToTexture(QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB, bool *premultipliedB, const QRect &rect = QRect()); + bool bindSWToTexture(const QPlatformGraphicsBuffer *graphicsBuffer, bool *swizzleRandB = Q_NULLPTR, bool *premultipliedB = Q_NULLPTR, const QRect &rect = QRect()); } QT_END_NAMESPACE diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index 4b725fc79f..ef1652b48b 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -92,6 +92,7 @@ public: mutable GLuint textureId; mutable QSize textureSize; mutable bool needsSwizzle; + mutable bool premultiplied; QOpenGLTextureBlitter *blitter; #endif }; @@ -323,9 +324,6 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i blitTextureForWidget(textures, i, window, deviceWindowRect, d_ptr->blitter, offset); } - funcs->glEnable(GL_BLEND); - funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); - // Backingstore texture with the normal widgets. GLuint textureId = 0; QOpenGLTextureBlitter::Origin origin = QOpenGLTextureBlitter::OriginTopLeft; @@ -345,7 +343,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - if (QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle)) { + if (QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle, &d_ptr->premultiplied)) { d_ptr->textureSize = graphicsBuffer->size(); } else { d_ptr->textureSize = QSize(0,0); @@ -354,7 +352,7 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i graphicsBuffer->unlock(); } else if (!region.isEmpty()){ funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); - QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle); + QPlatformGraphicsBufferHelper::lockAndBindToTexture(graphicsBuffer, &d_ptr->needsSwizzle, &d_ptr->premultiplied); } if (graphicsBuffer->origin() == QPlatformGraphicsBuffer::OriginBottomLeft) @@ -364,10 +362,17 @@ void QPlatformBackingStore::composeAndFlush(QWindow *window, const QRegion ®i TextureFlags flags = 0; textureId = toTexture(deviceRegion(region, window, offset), &d_ptr->textureSize, &flags); d_ptr->needsSwizzle = (flags & TextureSwizzle) != 0; + d_ptr->premultiplied = (flags & TexturePremultiplied) != 0; if (flags & TextureFlip) origin = QOpenGLTextureBlitter::OriginBottomLeft; } + funcs->glEnable(GL_BLEND); + if (d_ptr->premultiplied) + funcs->glBlendFuncSeparate(GL_ONE, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + else + funcs->glBlendFuncSeparate(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA, GL_ONE, GL_ONE); + if (textureId) { if (d_ptr->needsSwizzle) d_ptr->blitter->setSwizzleRB(true); @@ -443,10 +448,26 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu QImage image = toImage(); QSize imageSize = image.size(); + bool needConvert = false; *flags = 0; - if (image.format() == QImage::Format_RGB32) + switch (image.format()) { + case QImage::Format_ARGB32_Premultiplied: + *flags |= TexturePremultiplied; + // no break + case QImage::Format_RGB32: + case QImage::Format_ARGB32: *flags |= TextureSwizzle; - + break; + case QImage::Format_RGBA8888_Premultiplied: + *flags |= TexturePremultiplied; + // no break + case QImage::Format_RGBX8888: + case QImage::Format_RGBA8888: + break; + default: + needConvert = true; + break; + } if (imageSize.isEmpty()) { *textureSize = imageSize; return 0; @@ -460,8 +481,7 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu *textureSize = imageSize; - // Fast path for RGB32 and RGBA8888, convert everything else to RGBA8888. - if (image.format() != QImage::Format_RGB32 && image.format() != QImage::Format_RGBA8888) + if (needConvert) image = image.convertToFormat(QImage::Format_RGBA8888); QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); diff --git a/src/gui/painting/qplatformbackingstore.h b/src/gui/painting/qplatformbackingstore.h index eac97e9cf6..9c8da0d1db 100644 --- a/src/gui/painting/qplatformbackingstore.h +++ b/src/gui/painting/qplatformbackingstore.h @@ -118,7 +118,8 @@ public: virtual QImage toImage() const; enum TextureFlag { TextureSwizzle = 0x01, - TextureFlip = 0x02 + TextureFlip = 0x02, + TexturePremultiplied = 0x04, }; Q_DECLARE_FLAGS(TextureFlags, TextureFlag) virtual GLuint toTexture(const QRegion &dirtyRegion, QSize *textureSize, TextureFlags *flags) const; -- cgit v1.2.3 From b6c086ad6cc3525013abc225d96c53c392a04756 Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Thu, 14 Jan 2016 15:57:54 +0100 Subject: Windows/Direct2D QPA plugins: Fix overrides. Fix warnings found by clang. Change-Id: Ia8e7a271e9d33011eded1e63e61dbcaeaf692600 Reviewed-by: Joerg Bornemann --- .../direct2d/qwindowsdirect2dbackingstore.h | 4 +- .../direct2d/qwindowsdirect2dplatformpixmap.h | 3 +- .../platforms/windows/qwindowsdialoghelpers.cpp | 52 +++++++++++----------- src/plugins/platforms/windows/qwindowsdrag.cpp | 2 +- .../platforms/windows/qwindowsfontdatabase_ft.h | 11 +++-- src/plugins/platforms/windows/qwindowsfontengine.h | 2 +- .../windows/qwindowsfontenginedirectwrite.h | 42 ++++++++--------- .../platforms/windows/qwindowsintegration.h | 8 ++-- src/plugins/platforms/windows/qwindowsmime.cpp | 48 ++++++++++---------- src/plugins/platforms/windows/qwindowstheme.h | 4 +- src/plugins/platforms/windows/qwindowswindow.h | 12 ++--- 11 files changed, 95 insertions(+), 93 deletions(-) diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h index 1c7f65a12d..08bfaa1240 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dbackingstore.h @@ -48,8 +48,8 @@ public: QWindowsDirect2DBackingStore(QWindow *window); ~QWindowsDirect2DBackingStore(); - void beginPaint(const QRegion &); - void endPaint(); + void beginPaint(const QRegion &) Q_DECL_OVERRIDE; + void endPaint() Q_DECL_OVERRIDE; QPaintDevice *paintDevice() Q_DECL_OVERRIDE; void flush(QWindow *targetWindow, const QRegion ®ion, const QPoint &offset) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h index 5720f84853..a9591a493a 100644 --- a/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h +++ b/src/plugins/platforms/direct2d/qwindowsdirect2dplatformpixmap.h @@ -54,8 +54,7 @@ public: ~QWindowsDirect2DPlatformPixmap(); void resize(int width, int height) Q_DECL_OVERRIDE; - virtual void fromImage(const QImage &image, - Qt::ImageConversionFlags flags); + void fromImage(const QImage &image, Qt::ImageConversionFlags flags) Q_DECL_OVERRIDE; int metric(QPaintDevice::PaintDeviceMetric metric) const Q_DECL_OVERRIDE; void fill(const QColor &color) Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp index b983ba3354..9211fd1320 100644 --- a/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp +++ b/src/plugins/platforms/windows/qwindowsdialoghelpers.cpp @@ -876,12 +876,12 @@ public: inline static QWindowsNativeFileDialogBase *create(QFileDialogOptions::AcceptMode am, const QWindowsFileDialogSharedData &data); - virtual void setWindowTitle(const QString &title); + void setWindowTitle(const QString &title) Q_DECL_OVERRIDE; inline void setMode(QFileDialogOptions::FileMode mode, QFileDialogOptions::AcceptMode acceptMode, QFileDialogOptions::FileDialogOptions options); inline void setDirectory(const QUrl &directory); inline void updateDirectory() { setDirectory(m_data.directory()); } inline QString directory() const; - virtual void doExec(HWND owner = 0); + void doExec(HWND owner = 0) Q_DECL_OVERRIDE; virtual void setNameFilters(const QStringList &f); inline void selectNameFilter(const QString &filter); inline void updateSelectedNameFilter() { selectNameFilter(m_data.selectedNameFilter()); } @@ -910,7 +910,7 @@ signals: void filterSelected(const QString & filter); public slots: - virtual void close(); + void close() Q_DECL_OVERRIDE; protected: explicit QWindowsNativeFileDialogBase(const QWindowsFileDialogSharedData &data); @@ -1460,9 +1460,9 @@ class QWindowsNativeSaveFileDialog : public QWindowsNativeFileDialogBase public: explicit QWindowsNativeSaveFileDialog(const QWindowsFileDialogSharedData &data) : QWindowsNativeFileDialogBase(data) {} - virtual void setNameFilters(const QStringList &f); - virtual QList selectedFiles() const; - virtual QList dialogResult() const; + void setNameFilters(const QStringList &f) Q_DECL_OVERRIDE; + QList selectedFiles() const Q_DECL_OVERRIDE; + QList dialogResult() const Q_DECL_OVERRIDE; }; // Return the first suffix from the name filter "Foo files (*.foo;*.bar)" -> "foo". @@ -1531,8 +1531,8 @@ class QWindowsNativeOpenFileDialog : public QWindowsNativeFileDialogBase public: explicit QWindowsNativeOpenFileDialog(const QWindowsFileDialogSharedData &data) : QWindowsNativeFileDialogBase(data) {} - virtual QList selectedFiles() const; - virtual QList dialogResult() const; + QList selectedFiles() const Q_DECL_OVERRIDE; + QList dialogResult() const Q_DECL_OVERRIDE; private: inline IFileOpenDialog *openFileDialog() const @@ -1616,7 +1616,7 @@ public: virtual QString selectedNameFilter() const Q_DECL_OVERRIDE; private: - virtual QWindowsNativeDialogBase *createNativeDialog(); + QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE; inline QWindowsNativeFileDialogBase *nativeFileDialog() const { return static_cast(nativeDialog()); } @@ -1744,14 +1744,13 @@ public: static QWindowsXpNativeFileDialog *create(const OptionsPtr &options, const QWindowsFileDialogSharedData &data); - virtual void setWindowTitle(const QString &t) { m_title = t; } - virtual void doExec(HWND owner = 0); - virtual QPlatformDialogHelper::DialogCode result() const { return m_result; } + void setWindowTitle(const QString &t) Q_DECL_OVERRIDE { m_title = t; } + void doExec(HWND owner = 0) Q_DECL_OVERRIDE; int existingDirCallback(HWND hwnd, UINT uMsg, LPARAM lParam); public slots: - virtual void close() {} + void close() Q_DECL_OVERRIDE {} private: typedef BOOL (APIENTRY *PtrGetOpenFileNameW)(LPOPENFILENAMEW); @@ -1987,19 +1986,19 @@ class QWindowsXpFileDialogHelper : public QWindowsDialogHelperBase selectedFiles() const Q_DECL_OVERRIDE; - virtual void setFilter() Q_DECL_OVERRIDE {} - virtual void selectNameFilter(const QString &) Q_DECL_OVERRIDE; - virtual QString selectedNameFilter() const Q_DECL_OVERRIDE; + void setDirectory(const QUrl &directory) Q_DECL_OVERRIDE; + QUrl directory() const Q_DECL_OVERRIDE; + void selectFile(const QUrl &url) Q_DECL_OVERRIDE; + QList selectedFiles() const Q_DECL_OVERRIDE; + void setFilter() Q_DECL_OVERRIDE {} + void selectNameFilter(const QString &) Q_DECL_OVERRIDE; + QString selectedNameFilter() const Q_DECL_OVERRIDE; private: - virtual QWindowsNativeDialogBase *createNativeDialog(); + QWindowsNativeDialogBase *createNativeDialog() Q_DECL_OVERRIDE; inline QWindowsXpNativeFileDialog *nativeFileDialog() const { return static_cast(nativeDialog()); } @@ -2073,14 +2072,13 @@ public: explicit QWindowsNativeColorDialog(const SharedPointerColor &color); - virtual void setWindowTitle(const QString &) {} - virtual QPlatformDialogHelper::DialogCode result() const { return m_code; } + void setWindowTitle(const QString &) Q_DECL_OVERRIDE {} public slots: - virtual void close() {} + void close() Q_DECL_OVERRIDE {} private: - virtual void doExec(HWND owner = 0); + void doExec(HWND owner = 0) Q_DECL_OVERRIDE; COLORREF m_customColors[CustomColorCount]; QPlatformDialogHelper::DialogCode m_code; diff --git a/src/plugins/platforms/windows/qwindowsdrag.cpp b/src/plugins/platforms/windows/qwindowsdrag.cpp index 021058fa33..16079576a2 100644 --- a/src/plugins/platforms/windows/qwindowsdrag.cpp +++ b/src/plugins/platforms/windows/qwindowsdrag.cpp @@ -78,7 +78,7 @@ public: void setPixmap(const QPixmap &p); protected: - void paintEvent(QPaintEvent *) + void paintEvent(QPaintEvent *) Q_DECL_OVERRIDE { QPainter painter(this); painter.drawPixmap(0, 0, m_pixmap); diff --git a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h index ad5c005ffa..f65dc38801 100644 --- a/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h +++ b/src/plugins/platforms/windows/qwindowsfontdatabase_ft.h @@ -43,12 +43,15 @@ QT_BEGIN_NAMESPACE class QWindowsFontDatabaseFT : public QBasicFontDatabase { public: - void populateFontDatabase(); + void populateFontDatabase() Q_DECL_OVERRIDE; void populateFamily(const QString &familyName) Q_DECL_OVERRIDE; - QFontEngine *fontEngine(const QFontDef &fontDef, void *handle); - QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, QFont::HintingPreference hintingPreference); + QFontEngine *fontEngine(const QFontDef &fontDef, void *handle) Q_DECL_OVERRIDE; + QFontEngine *fontEngine(const QByteArray &fontData, qreal pixelSize, + QFont::HintingPreference hintingPreference) Q_DECL_OVERRIDE; - QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) const; + QStringList fallbacksForFamily(const QString &family, QFont::Style style, + QFont::StyleHint styleHint, + QChar::Script script) const Q_DECL_OVERRIDE; QString fontDir() const Q_DECL_OVERRIDE; QFont defaultFont() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsfontengine.h b/src/plugins/platforms/windows/qwindowsfontengine.h index 409b44264e..5317368455 100644 --- a/src/plugins/platforms/windows/qwindowsfontengine.h +++ b/src/plugins/platforms/windows/qwindowsfontengine.h @@ -84,7 +84,7 @@ public: void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; virtual void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); + QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; HGDIOBJ selectDesignFont() const; diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h index cee8691d69..07e040ed33 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.h @@ -61,35 +61,37 @@ public: void initFontInfo(const QFontDef &request, int dpi, IDWriteFont *font); - QFixed lineThickness() const; - QFixed underlinePosition() const; - bool getSfntTableData(uint tag, uchar *buffer, uint *length) const; - QFixed emSquareSize() const; + QFixed lineThickness() const Q_DECL_OVERRIDE; + QFixed underlinePosition() const Q_DECL_OVERRIDE; + bool getSfntTableData(uint tag, uchar *buffer, uint *length) const Q_DECL_OVERRIDE; + QFixed emSquareSize() const Q_DECL_OVERRIDE; glyph_t glyphIndex(uint ucs4) const Q_DECL_OVERRIDE; - bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const; - void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const; + bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, + ShaperFlags flags) const Q_DECL_OVERRIDE; + void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const Q_DECL_OVERRIDE; void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs, - QPainterPath *path, QTextItem::RenderFlags flags); + QPainterPath *path, QTextItem::RenderFlags flags) Q_DECL_OVERRIDE; - glyph_metrics_t boundingBox(const QGlyphLayout &glyphs); - glyph_metrics_t boundingBox(glyph_t g); - glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, const QTransform &matrix, GlyphFormat); + glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) Q_DECL_OVERRIDE; + glyph_metrics_t boundingBox(glyph_t g) Q_DECL_OVERRIDE; + glyph_metrics_t alphaMapBoundingBox(glyph_t glyph, QFixed, + const QTransform &matrix, GlyphFormat) Q_DECL_OVERRIDE; - QFixed ascent() const; - QFixed descent() const; - QFixed leading() const; - QFixed xHeight() const; - qreal maxCharWidth() const; + QFixed ascent() const Q_DECL_OVERRIDE; + QFixed descent() const Q_DECL_OVERRIDE; + QFixed leading() const Q_DECL_OVERRIDE; + QFixed xHeight() const Q_DECL_OVERRIDE; + qreal maxCharWidth() const Q_DECL_OVERRIDE; - bool supportsSubPixelPositions() const; + bool supportsSubPixelPositions() const Q_DECL_OVERRIDE; - QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition); - QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t); - QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform); + QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition) Q_DECL_OVERRIDE; + QImage alphaMapForGlyph(glyph_t glyph, QFixed subPixelPosition, const QTransform &t) Q_DECL_OVERRIDE; + QImage alphaRGBMapForGlyph(glyph_t t, QFixed subPixelPosition, const QTransform &xform) Q_DECL_OVERRIDE; - QFontEngine *cloneWithSize(qreal pixelSize) const; + QFontEngine *cloneWithSize(qreal pixelSize) const Q_DECL_OVERRIDE; const QSharedPointer &fontEngineData() const { return m_fontEngineData; } diff --git a/src/plugins/platforms/windows/qwindowsintegration.h b/src/plugins/platforms/windows/qwindowsintegration.h index cb10bf08f5..da20d9261a 100644 --- a/src/plugins/platforms/windows/qwindowsintegration.h +++ b/src/plugins/platforms/windows/qwindowsintegration.h @@ -60,12 +60,12 @@ public: explicit QWindowsIntegration(const QStringList ¶mList); virtual ~QWindowsIntegration(); - bool hasCapability(QPlatformIntegration::Capability cap) const; + bool hasCapability(QPlatformIntegration::Capability cap) const Q_DECL_OVERRIDE; - QPlatformWindow *createPlatformWindow(QWindow *window) const; + QPlatformWindow *createPlatformWindow(QWindow *window) const Q_DECL_OVERRIDE; #ifndef QT_NO_OPENGL QPlatformOpenGLContext *createPlatformOpenGLContext(QOpenGLContext *context) const Q_DECL_OVERRIDE; - QOpenGLContext::OpenGLModuleType openGLModuleType(); + QOpenGLContext::OpenGLModuleType openGLModuleType() Q_DECL_OVERRIDE; static QWindowsStaticOpenGLContext *staticOpenGLContext(); #endif QAbstractEventDispatcher *createEventDispatcher() const Q_DECL_OVERRIDE; @@ -83,7 +83,7 @@ public: QPlatformFontDatabase *fontDatabase() const Q_DECL_OVERRIDE; QStringList themeNames() const Q_DECL_OVERRIDE; QPlatformTheme *createPlatformTheme(const QString &name) const Q_DECL_OVERRIDE; - QPlatformServices *services() const; + QPlatformServices *services() const Q_DECL_OVERRIDE; QVariant styleHint(StyleHint hint) const Q_DECL_OVERRIDE; Qt::KeyboardModifiers queryKeyboardModifiers() const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowsmime.cpp b/src/plugins/platforms/windows/qwindowsmime.cpp index 0a2ba9b0e7..171ace5c20 100644 --- a/src/plugins/platforms/windows/qwindowsmime.cpp +++ b/src/plugins/platforms/windows/qwindowsmime.cpp @@ -897,14 +897,14 @@ public: QWindowsMimeHtml(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: int CF_HTML; @@ -1029,14 +1029,14 @@ class QWindowsMimeImage : public QWindowsMime public: QWindowsMimeImage(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: bool hasOriginalDIBV5(IDataObject *pDataObj) const; UINT CF_PNG; @@ -1183,14 +1183,14 @@ public: QBuiltInMimes(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: QMap outFormats; @@ -1303,14 +1303,14 @@ public: QLastResortMimes(); // for converting from Qt - bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const; - bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const; - QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const; + bool canConvertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData) const Q_DECL_OVERRIDE; + bool convertFromMime(const FORMATETC &formatetc, const QMimeData *mimeData, STGMEDIUM * pmedium) const Q_DECL_OVERRIDE; + QVector formatsForMime(const QString &mimeType, const QMimeData *mimeData) const Q_DECL_OVERRIDE; // for converting to Qt - bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const; - QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const; - QString mimeForFormat(const FORMATETC &formatetc) const; + bool canConvertToMime(const QString &mimeType, IDataObject *pDataObj) const Q_DECL_OVERRIDE; + QVariant convertToMime(const QString &mime, IDataObject *pDataObj, QVariant::Type preferredType) const Q_DECL_OVERRIDE; + QString mimeForFormat(const FORMATETC &formatetc) const Q_DECL_OVERRIDE; private: QMap formats; diff --git a/src/plugins/platforms/windows/qwindowstheme.h b/src/plugins/platforms/windows/qwindowstheme.h index b2f8e13b64..fc004b68c8 100644 --- a/src/plugins/platforms/windows/qwindowstheme.h +++ b/src/plugins/platforms/windows/qwindowstheme.h @@ -51,9 +51,9 @@ public: bool usePlatformNativeDialog(DialogType type) const Q_DECL_OVERRIDE; QPlatformDialogHelper *createPlatformDialogHelper(DialogType type) const Q_DECL_OVERRIDE; QVariant themeHint(ThemeHint) const Q_DECL_OVERRIDE; - virtual const QPalette *palette(Palette type = SystemPalette) const + const QPalette *palette(Palette type = SystemPalette) const Q_DECL_OVERRIDE { return m_palettes[type]; } - virtual const QFont *font(Font type = SystemFont) const + const QFont *font(Font type = SystemFont) const Q_DECL_OVERRIDE { return m_fonts[type]; } QPixmap standardPixmap(StandardPixmap sp, const QSizeF &size) const Q_DECL_OVERRIDE; diff --git a/src/plugins/platforms/windows/qwindowswindow.h b/src/plugins/platforms/windows/qwindowswindow.h index 710cab8597..6fffa1e6e9 100644 --- a/src/plugins/platforms/windows/qwindowswindow.h +++ b/src/plugins/platforms/windows/qwindowswindow.h @@ -171,7 +171,7 @@ public: void raise() Q_DECL_OVERRIDE; void lower() Q_DECL_OVERRIDE; - void windowEvent(QEvent *event); + void windowEvent(QEvent *event) Q_DECL_OVERRIDE; void propagateSizeHints() Q_DECL_OVERRIDE; static bool handleGeometryChangingMessage(MSG *message, const QWindow *qWindow, const QMargins &marginsDp); @@ -189,8 +189,8 @@ public: bool startSystemResize(const QPoint &pos, Qt::Corner corner) Q_DECL_OVERRIDE; - void setFrameStrutEventsEnabled(bool enabled); - bool frameStrutEventsEnabled() const { return testFlag(FrameStrutEventsEnabled); } + void setFrameStrutEventsEnabled(bool enabled) Q_DECL_OVERRIDE; + bool frameStrutEventsEnabled() const Q_DECL_OVERRIDE { return testFlag(FrameStrutEventsEnabled); } QMargins customMargins() const { return m_data.customMargins; } void setCustomMargins(const QMargins &m); @@ -237,15 +237,15 @@ public: void setEnabled(bool enabled); bool isEnabled() const; - void setWindowIcon(const QIcon &icon); + void setWindowIcon(const QIcon &icon) Q_DECL_OVERRIDE; void *surface(void *nativeConfig, int *err); void invalidateSurface() Q_DECL_OVERRIDE; void aboutToMakeCurrent(); #ifndef Q_OS_WINCE - void setAlertState(bool enabled); - bool isAlertState() const { return testFlag(AlertState); } + void setAlertState(bool enabled) Q_DECL_OVERRIDE; + bool isAlertState() const Q_DECL_OVERRIDE { return testFlag(AlertState); } void alertWindow(int durationMs = 0); void stopAlertWindow(); #endif -- cgit v1.2.3 From d53f614740abcda84a1fae7f09fa68b94583e79f Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Wed, 13 Jan 2016 14:18:35 -0800 Subject: Doc: add missing semi-colon MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Change-Id: I408dcb81ba654c929f25ffff14291c57198e7367 Reviewed-by: Giuseppe D'Angelo Reviewed-by: Topi Reiniö --- src/gui/opengl/qopenglfunctions.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/gui/opengl/qopenglfunctions.cpp b/src/gui/opengl/qopenglfunctions.cpp index d614ad8401..be1a979c37 100644 --- a/src/gui/opengl/qopenglfunctions.cpp +++ b/src/gui/opengl/qopenglfunctions.cpp @@ -96,7 +96,7 @@ Q_LOGGING_CATEGORY(lcGLES3, "qt.opengl.es3") // Setup scene and render it initializeGL(); - paintGL() + paintGL(); } void MyGLWindow::initializeGL() -- cgit v1.2.3 From 434302eae1a0c5d3016fe07c7d343bdbad118a8a Mon Sep 17 00:00:00 2001 From: Thiago Macieira Date: Tue, 12 Jan 2016 13:55:01 -0800 Subject: Fix non-Latin1 strings in QJsonDocument on big-endian platforms QJsonDocument stores the entire JSON tree in its binary format. Since the binary format is the same on-disk as in-memory, it has a fixed endianness. But when converting from QString to the little-endian format, the code accidentally converted twice (from little endian, to little endian), which resulted in a no-op and the string got stored as big-endian. It's like encrypting with double-ROT13. No new testcase because tst_QtJson::removeNonLatinKey was already failing and gets fixed by this commit. Task-number: QTBUG-50419 Change-Id: I408dcb81ba654c929f25ffff1428cc79472bbe13 Reviewed-by: Olivier Goffart (Woboq GmbH) Reviewed-by: Lars Knoll --- src/corelib/json/qjson_p.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/json/qjson_p.h b/src/corelib/json/qjson_p.h index 5fc021c841..17f49d41c8 100644 --- a/src/corelib/json/qjson_p.h +++ b/src/corelib/json/qjson_p.h @@ -305,7 +305,7 @@ public: { d->length = str.length(); #if Q_BYTE_ORDER == Q_BIG_ENDIAN - const qle_ushort *uc = (const qle_ushort *)str.unicode(); + const ushort *uc = (const ushort *)str.unicode(); for (int i = 0; i < str.length(); ++i) d->utf16[i] = uc[i]; #else -- cgit v1.2.3 From 4f71654385438a015931a0c7be52f2c7188c9f7d Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Mon, 11 Jan 2016 16:33:45 +0100 Subject: Handle RGB30 formats in OpenGL backing-store integration Optimizes composition on platforms that may use 10-bit per color channel formats. Change-Id: Ib303c391d47795c79a4ba55d78dbb1c3c702d90a Reviewed-by: Laszlo Agocs --- src/gui/kernel/qplatformgraphicsbufferhelper.cpp | 54 ++++++++++++++++++++---- src/gui/painting/qplatformbackingstore.cpp | 48 ++++++++++++++++----- 2 files changed, 83 insertions(+), 19 deletions(-) diff --git a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp index 7f2672bc5e..c0c51b8d5e 100644 --- a/src/gui/kernel/qplatformgraphicsbufferhelper.cpp +++ b/src/gui/kernel/qplatformgraphicsbufferhelper.cpp @@ -40,6 +40,14 @@ #include #include +#ifndef GL_RGB10_A2 +#define GL_RGB10_A2 0x8059 +#endif + +#ifndef GL_UNSIGNED_INT_2_10_10_10_REV +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#endif + QT_BEGIN_NAMESPACE /*! @@ -115,7 +123,8 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe const QRect &subRect) { #ifndef QT_NO_OPENGL - if (!QOpenGLContext::currentContext()) + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + if (!ctx) return false; if (!(graphicsBuffer->isLocked() & QPlatformGraphicsBuffer::SWReadAccess)) @@ -125,12 +134,16 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe Q_ASSERT(subRect.isEmpty() || QRect(QPoint(0,0), size).contains(subRect)); + GLenum internalFormat = GL_RGBA; + GLuint pixelType = GL_UNSIGNED_BYTE; + + bool needsConversion = false; bool swizzle = false; bool premultiplied = false; QImage::Format imageformat = QImage::toImageFormat(graphicsBuffer->format()); QImage image(graphicsBuffer->data(), size.width(), size.height(), graphicsBuffer->bytesPerLine(), imageformat); if (graphicsBuffer->bytesPerLine() != (size.width() * 4)) { - image = image.convertToFormat(QImage::Format_RGBA8888); + needsConversion = true; } else { switch (imageformat) { case QImage::Format_ARGB32_Premultiplied: @@ -146,22 +159,45 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe case QImage::Format_RGBX8888: case QImage::Format_RGBA8888: break; + case QImage::Format_BGR30: + case QImage::Format_A2BGR30_Premultiplied: + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; + internalFormat = GL_RGB10_A2; + premultiplied = true; + } else { + needsConversion = true; + } + break; + case QImage::Format_RGB30: + case QImage::Format_A2RGB30_Premultiplied: + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; + internalFormat = GL_RGB10_A2; + premultiplied = true; + swizzle = true; + } else { + needsConversion = true; + } + break; default: - image = image.convertToFormat(QImage::Format_RGBA8888); + needsConversion = true; break; } } + if (needsConversion) + image = image.convertToFormat(QImage::Format_RGBA8888); - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + QOpenGLFunctions *funcs = ctx->functions(); QRect rect = subRect; if (rect.isNull() || rect == QRect(QPoint(0,0),size)) { - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, size.width(), size.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, image.constBits()); + funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, size.width(), size.height(), 0, GL_RGBA, pixelType, image.constBits()); } else { #ifndef QT_OPENGL_ES_2 - if (!QOpenGLContext::currentContext()->isOpenGLES()) { + if (!ctx->isOpenGLES()) { funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width()); - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, image.constScanLine(rect.y()) + rect.x() * 4); funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else @@ -178,10 +214,10 @@ bool QPlatformGraphicsBufferHelper::bindSWToTexture(const QPlatformGraphicsBuffe // OpenGL instead of copying, since there's no gap between scanlines if (rect.width() == size.width()) { - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, image.constScanLine(rect.y())); } else { - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, image.copy(rect).constBits()); } } diff --git a/src/gui/painting/qplatformbackingstore.cpp b/src/gui/painting/qplatformbackingstore.cpp index ef1652b48b..83b75ae605 100644 --- a/src/gui/painting/qplatformbackingstore.cpp +++ b/src/gui/painting/qplatformbackingstore.cpp @@ -57,6 +57,12 @@ #ifndef GL_UNPACK_ROW_LENGTH #define GL_UNPACK_ROW_LENGTH 0x0CF2 #endif +#ifndef GL_RGB10_A2 +#define GL_RGB10_A2 0x8059 +#endif +#ifndef GL_UNSIGNED_INT_2_10_10_10_REV +#define GL_UNSIGNED_INT_2_10_10_10_REV 0x8368 +#endif QT_BEGIN_NAMESPACE @@ -448,7 +454,11 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu QImage image = toImage(); QSize imageSize = image.size(); - bool needConvert = false; + QOpenGLContext *ctx = QOpenGLContext::currentContext(); + GLenum internalFormat = GL_RGBA; + GLuint pixelType = GL_UNSIGNED_BYTE; + + bool needsConversion = false; *flags = 0; switch (image.format()) { case QImage::Format_ARGB32_Premultiplied: @@ -464,8 +474,28 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu case QImage::Format_RGBX8888: case QImage::Format_RGBA8888: break; + case QImage::Format_BGR30: + case QImage::Format_A2BGR30_Premultiplied: + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; + internalFormat = GL_RGB10_A2; + *flags |= TexturePremultiplied; + } else { + needsConversion = true; + } + break; + case QImage::Format_RGB30: + case QImage::Format_A2RGB30_Premultiplied: + if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { + pixelType = GL_UNSIGNED_INT_2_10_10_10_REV; + internalFormat = GL_RGB10_A2; + *flags |= TextureSwizzle | TexturePremultiplied; + } else { + needsConversion = true; + } + break; default: - needConvert = true; + needsConversion = true; break; } if (imageSize.isEmpty()) { @@ -481,16 +511,15 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu *textureSize = imageSize; - if (needConvert) + if (needsConversion) image = image.convertToFormat(QImage::Format_RGBA8888); - QOpenGLFunctions *funcs = QOpenGLContext::currentContext()->functions(); + QOpenGLFunctions *funcs = ctx->functions(); if (resized) { if (d_ptr->textureId) funcs->glDeleteTextures(1, &d_ptr->textureId); funcs->glGenTextures(1, &d_ptr->textureId); funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); - QOpenGLContext *ctx = QOpenGLContext::currentContext(); if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_BASE_LEVEL, 0); funcs->glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAX_LEVEL, 0); @@ -500,17 +529,16 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE); funcs->glTexParameterf(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE); - funcs->glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, imageSize.width(), imageSize.height(), 0, GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexImage2D(GL_TEXTURE_2D, 0, internalFormat, imageSize.width(), imageSize.height(), 0, GL_RGBA, pixelType, const_cast(image.constBits())); } else { funcs->glBindTexture(GL_TEXTURE_2D, d_ptr->textureId); QRect imageRect = image.rect(); QRect rect = dirtyRegion.boundingRect() & imageRect; - QOpenGLContext *ctx = QOpenGLContext::currentContext(); if (!ctx->isOpenGLES() || ctx->format().majorVersion() >= 3) { funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, image.width()); - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, image.constScanLine(rect.y()) + rect.x() * 4); funcs->glPixelStorei(GL_UNPACK_ROW_LENGTH, 0); } else { @@ -525,10 +553,10 @@ GLuint QPlatformBackingStore::toTexture(const QRegion &dirtyRegion, QSize *textu // OpenGL instead of copying, since there's no gap between scanlines if (rect.width() == imageRect.width()) { - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, 0, rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, image.constScanLine(rect.y())); } else { - funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, GL_UNSIGNED_BYTE, + funcs->glTexSubImage2D(GL_TEXTURE_2D, 0, rect.x(), rect.y(), rect.width(), rect.height(), GL_RGBA, pixelType, image.copy(rect).constBits()); } } -- cgit v1.2.3 From 5ef14c52d0275e721153b15acfb0410b9889014a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andr=C3=A9=20Klitzing?= Date: Wed, 13 Jan 2016 15:20:37 +0100 Subject: Fix QFileSelector::select if called with QUrl and scheme "assets" QFileSelector::select(QUrl) will use ":" for scheme "qrc" to call QFileSelector::select(QString). Scheme "assets" needs to remain "assets:" for select(QString), otherwise it won't recognize the file in "assets". Following failed because it was passed as ":/qml/example.qml" to select(QString): select(QUrl("assets:/qml/example.qml")); This will call select(QString) to: select("assets:/qml/example.qml"); Change-Id: I6bdeed6bb67992498ae3b8e1273c20e70049381a Task-number: QTBUG-50435 Reviewed-by: BogDan Vatra --- src/corelib/io/qfileselector.cpp | 11 +++++++++-- 1 file changed, 9 insertions(+), 2 deletions(-) diff --git a/src/corelib/io/qfileselector.cpp b/src/corelib/io/qfileselector.cpp index 85d9b0bfcb..af8d9b2b36 100644 --- a/src/corelib/io/qfileselector.cpp +++ b/src/corelib/io/qfileselector.cpp @@ -248,9 +248,16 @@ QUrl QFileSelector::select(const QUrl &filePath) const return filePath; QUrl ret(filePath); if (isLocalScheme(filePath.scheme())) { - QString equivalentPath = QLatin1Char(':') + filePath.path(); + QLatin1String scheme(":"); +#ifdef Q_OS_ANDROID + // use other scheme because ":" means "qrc" here + if (filePath.scheme() == QLatin1String("assets")) + scheme = QLatin1String("assets:"); +#endif + + QString equivalentPath = scheme + filePath.path(); QString selectedPath = d->select(equivalentPath); - ret.setPath(selectedPath.remove(0, 1)); + ret.setPath(selectedPath.remove(0, scheme.size())); } else { ret = QUrl::fromLocalFile(d->select(ret.toLocalFile())); } -- cgit v1.2.3 From 8fd75739efd49a424e90938a51802f38c8c504e6 Mon Sep 17 00:00:00 2001 From: Allan Sandfeld Jensen Date: Wed, 13 Jan 2016 14:54:48 +0100 Subject: Lock qfontdatabase mutex in qt_fallbacksForFamily When called from outside of qfontdatabase, the qfontdatabase mutex will not be locked upon entry to qt_fallbacksForFamily, so we need to add it to the exported version. Change-Id: I16a21708d7cca15730c12de3dbeeaab13ffbd315 Reviewed-by: Konstantin Ritt Reviewed-by: Oswald Buddenhagen Reviewed-by: Eskil Abrahamsen Blomfeldt --- src/gui/text/qfontdatabase.cpp | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp index 1b9852c20c..aae84dc988 100644 --- a/src/gui/text/qfontdatabase.cpp +++ b/src/gui/text/qfontdatabase.cpp @@ -838,7 +838,7 @@ QStringList QPlatformFontDatabase::fallbacksForFamily(const QString &family, QFo return retList; } -QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) +static QStringList fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) { QFontDatabasePrivate *db = privateDb(); @@ -870,6 +870,12 @@ QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFo return retList; } +QStringList qt_fallbacksForFamily(const QString &family, QFont::Style style, QFont::StyleHint styleHint, QChar::Script script) +{ + QMutexLocker locker(fontDatabaseMutex()); + return fallbacksForFamily(family, style, styleHint, script); +} + static void registerFont(QFontDatabasePrivate::ApplicationFont *fnt); static void initializeDb() @@ -984,7 +990,7 @@ QFontEngine *loadEngine(int script, const QFontDef &request, if (styleHint == QFont::AnyStyle && request.fixedPitch) styleHint = QFont::TypeWriter; - fallbacks += qt_fallbacksForFamily(family->name, QFont::Style(style->key.style), styleHint, QChar::Script(script)); + fallbacks += fallbacksForFamily(family->name, QFont::Style(style->key.style), styleHint, QChar::Script(script)); pfMultiEngine->setFallbackFamiliesList(fallbacks); } @@ -2664,10 +2670,10 @@ QFontEngine *QFontDatabase::findFont(const QFontDef &request, int script) styleHint = QFont::TypeWriter; QStringList fallbacks = request.fallBackFamilies - + qt_fallbacksForFamily(request.family, - QFont::Style(request.style), - styleHint, - QChar::Script(script)); + + fallbacksForFamily(request.family, + QFont::Style(request.style), + styleHint, + QChar::Script(script)); if (script > QChar::Script_Common) fallbacks += QString(); // Find the first font matching the specified script. -- cgit v1.2.3 From c26562033b7b71e26527ec013f3750d07ec6100a Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Fri, 15 Jan 2016 11:33:14 +0100 Subject: QFileDialog: Check whether sizeHint() is valid before resizing. Fixes a regression appearing in 5.5 where QtWidgets-based file dialogs showed up too small on Windows. Change-Id: I5f74ab01d4368d67ab79d3a1b145fb63bdd69ca0 Reviewed-by: Shawn Rutledge --- src/widgets/dialogs/qfiledialog.cpp | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/widgets/dialogs/qfiledialog.cpp b/src/widgets/dialogs/qfiledialog.cpp index bdfa27282f..06102ec1d6 100644 --- a/src/widgets/dialogs/qfiledialog.cpp +++ b/src/widgets/dialogs/qfiledialog.cpp @@ -2822,7 +2822,9 @@ void QFileDialogPrivate::init(const QUrl &directory, const QString &nameFilter, qFileDialogUi->sidebar->hide(); #endif - q->resize(q->sizeHint()); + const QSize sizeHint = q->sizeHint(); + if (sizeHint.isValid()) + q->resize(sizeHint); } /*! -- cgit v1.2.3 From 9bb24615ad8644cfb7879ed42ee36b4497541805 Mon Sep 17 00:00:00 2001 From: BogDan Vatra Date: Mon, 11 Jan 2016 14:53:48 +0200 Subject: Android: fix native libs dir. On Andorid 64 bit O.S.s the libs are not located anymore on dataDir/lib/ but they are located on dataDir/lib//. Using nativeLibraryDir instead of dataDir we'll get the right folder. Change-Id: I40ef9513eb5b51f81032bd41f9943ab7b959ad51 Task-number: QTBUG-50394 Reviewed-by: Christian Stromme --- .../java/src/org/qtproject/qt5/android/bindings/QtActivity.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java index 146d6b34f2..f370b4f667 100644 --- a/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java +++ b/src/android/java/src/org/qtproject/qt5/android/bindings/QtActivity.java @@ -454,7 +454,7 @@ public class QtActivity extends Activity { ArrayList libs = new ArrayList(); - String dataDir = getApplicationInfo().dataDir + "/"; + String libsDir = getApplicationInfo().nativeLibraryDir + "/"; long packageVersion = -1; try { @@ -489,7 +489,7 @@ public class QtActivity extends Activity for (String bundledImportBinary : list) { String[] split = bundledImportBinary.split(":"); - String sourceFileName = dataDir + "lib/" + split[0]; + String sourceFileName = libsDir + split[0]; String destinationFileName = pluginsPrefix + split[1]; createBundledBinary(sourceFileName, destinationFileName); } -- cgit v1.2.3 From 1172e18c3c180f2f3641e6c29688199eb5c46650 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Thu, 14 Jan 2016 17:48:38 +0100 Subject: Promote backingstore image format to alpha Like xcb does since 1bcfc3de7586ddb9f5d1b778b97b26ae3dc9584d. For TranslucentBackground (ARGB32_Premultiplied) there is no change in practice. For RGB32 we will promote to ARGB32_Premultiplied but everything should behave like before, except that we do not rely on undefined behavior anymore when QOpenGL/QuickWidget is in use. For RGB16 this will enable QOpenGL/QuickWidget since there the hole punching mechanism needs an alpha channel always. Change-Id: Id04ea548cee245ec91642f1358a5e501b62ff64c Reviewed-by: Friedemann Kleint Reviewed-by: Allan Sandfeld Jensen --- src/plugins/platforms/windows/qwindowsbackingstore.cpp | 18 ++++++++++++++---- src/plugins/platforms/windows/qwindowsbackingstore.h | 1 + 2 files changed, 15 insertions(+), 4 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.cpp b/src/plugins/platforms/windows/qwindowsbackingstore.cpp index 135c9eb601..a6b1d0af26 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.cpp +++ b/src/plugins/platforms/windows/qwindowsbackingstore.cpp @@ -39,6 +39,7 @@ #include #include #include +#include #include @@ -52,7 +53,8 @@ QT_BEGIN_NAMESPACE */ QWindowsBackingStore::QWindowsBackingStore(QWindow *window) : - QPlatformBackingStore(window) + QPlatformBackingStore(window), + m_alphaNeedsFill(false) { qCDebug(lcQpaBackingStore) << __FUNCTION__ << this << window; } @@ -144,8 +146,16 @@ void QWindowsBackingStore::resize(const QSize &size, const QRegion ®ion) << " from: " << (m_image.isNull() ? QSize() : m_image->image().size()); } #endif - const QImage::Format format = window()->format().hasAlpha() ? - QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat(); + QImage::Format format = window()->format().hasAlpha() ? + QImage::Format_ARGB32_Premultiplied : QWindowsNativeImage::systemFormat(); + + // The backingstore composition (enabling render-to-texture widgets) + // punches holes in the backingstores using the alpha channel. Hence + // the need for a true alpha format. + if (QImage::toPixelFormat(format).alphaUsage() == QPixelFormat::UsesAlpha) + m_alphaNeedsFill = true; + else // upgrade but here we know app painting does not rely on alpha hence no need to fill + format = qt_alphaVersionForPainting(format); QWindowsNativeImage *oldwni = m_image.data(); QWindowsNativeImage *newwni = new QWindowsNativeImage(size.width(), size.height(), format); @@ -186,7 +196,7 @@ void QWindowsBackingStore::beginPaint(const QRegion ®ion) if (QWindowsContext::verbose > 1) qCDebug(lcQpaBackingStore) <<__FUNCTION__ << region; - if (m_image->image().hasAlphaChannel()) { + if (m_alphaNeedsFill) { QPainter p(&m_image->image()); p.setCompositionMode(QPainter::CompositionMode_Source); const QColor blank = Qt::transparent; diff --git a/src/plugins/platforms/windows/qwindowsbackingstore.h b/src/plugins/platforms/windows/qwindowsbackingstore.h index 4badcf1b09..1d644923bb 100644 --- a/src/plugins/platforms/windows/qwindowsbackingstore.h +++ b/src/plugins/platforms/windows/qwindowsbackingstore.h @@ -65,6 +65,7 @@ public: private: QScopedPointer m_image; + bool m_alphaNeedsFill; }; QT_END_NAMESPACE -- cgit v1.2.3 From bfd367c6ec37c9d883c51316a149447b63005011 Mon Sep 17 00:00:00 2001 From: Eirik Aavitsland Date: Thu, 10 Dec 2015 11:01:29 +0100 Subject: Mirclient: update with upstream changes Merge in the changes up to revision 306 of the lp:qtubuntu repo. Change-Id: I55dcb9e06e0a3503d6abe4b0894d5ef5a785b6bb Reviewed-by: Christian Stromme --- src/plugins/platforms/mirclient/mirclient.pro | 2 + .../platforms/mirclient/qmirclientclipboard.cpp | 51 +- .../platforms/mirclient/qmirclientcursor.cpp | 201 ++++++ src/plugins/platforms/mirclient/qmirclientcursor.h | 61 ++ .../platforms/mirclient/qmirclientglcontext.cpp | 14 +- .../platforms/mirclient/qmirclientglcontext.h | 2 +- .../platforms/mirclient/qmirclientinput.cpp | 95 ++- src/plugins/platforms/mirclient/qmirclientinput.h | 13 +- .../platforms/mirclient/qmirclientintegration.cpp | 62 +- .../platforms/mirclient/qmirclientintegration.h | 5 +- .../mirclient/qmirclientnativeinterface.cpp | 29 +- .../mirclient/qmirclientnativeinterface.h | 5 +- .../mirclient/qmirclientorientationchangeevent_p.h | 10 +- .../platforms/mirclient/qmirclientplugin.cpp | 4 +- .../platforms/mirclient/qmirclientscreen.cpp | 21 +- src/plugins/platforms/mirclient/qmirclientscreen.h | 12 +- .../platforms/mirclient/qmirclientwindow.cpp | 710 +++++++++++++-------- src/plugins/platforms/mirclient/qmirclientwindow.h | 33 +- 18 files changed, 956 insertions(+), 374 deletions(-) create mode 100644 src/plugins/platforms/mirclient/qmirclientcursor.cpp create mode 100644 src/plugins/platforms/mirclient/qmirclientcursor.h diff --git a/src/plugins/platforms/mirclient/mirclient.pro b/src/plugins/platforms/mirclient/mirclient.pro index 033ce579b9..0851e8d719 100644 --- a/src/plugins/platforms/mirclient/mirclient.pro +++ b/src/plugins/platforms/mirclient/mirclient.pro @@ -21,6 +21,7 @@ PKGCONFIG += egl mirclient ubuntu-platform-api SOURCES = \ qmirclientbackingstore.cpp \ qmirclientclipboard.cpp \ + qmirclientcursor.cpp \ qmirclientglcontext.cpp \ qmirclientinput.cpp \ qmirclientintegration.cpp \ @@ -34,6 +35,7 @@ SOURCES = \ HEADERS = \ qmirclientbackingstore.h \ qmirclientclipboard.h \ + qmirclientcursor.h \ qmirclientglcontext.h \ qmirclientinput.h \ qmirclientintegration.h \ diff --git a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp index aa2ddf2103..53246f66c0 100644 --- a/src/plugins/platforms/mirclient/qmirclientclipboard.cpp +++ b/src/plugins/platforms/mirclient/qmirclientclipboard.cpp @@ -87,12 +87,12 @@ void QMirClientClipboard::requestDBusClipboardContents() if (!mPendingGetContentsCall.isNull()) return; - QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("GetContents"); + QDBusPendingCall pendingCall = mDBusClipboard->asyncCall(QStringLiteral("GetContents")); mPendingGetContentsCall = new QDBusPendingCallWatcher(pendingCall, this); - QObject::connect(mPendingGetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher*))); + QObject::connect(mPendingGetContentsCall.data(), &QDBusPendingCallWatcher::finished, + this, &QMirClientClipboard::onDBusClipboardGetContentsFinished); } void QMirClientClipboard::onDBusClipboardGetContentsFinished(QDBusPendingCallWatcher* call) @@ -143,18 +143,18 @@ void QMirClientClipboard::setupDBus() QDBusConnection dbusConnection = QDBusConnection::sessionBus(); bool ok = dbusConnection.connect( - "com.canonical.QtMir", - "/com/canonical/QtMir/Clipboard", - "com.canonical.QtMir.Clipboard", - "ContentsChanged", + QStringLiteral("com.canonical.QtMir"), + QStringLiteral("/com/canonical/QtMir/Clipboard"), + QStringLiteral("com.canonical.QtMir.Clipboard"), + QStringLiteral("ContentsChanged"), this, SLOT(updateMimeData(QByteArray))); if (!ok) { qCritical("QMirClientClipboard - Failed to connect to ContentsChanged signal form the D-Bus system clipboard."); } - mDBusClipboard = new QDBusInterface("com.canonical.QtMir", - "/com/canonical/QtMir/Clipboard", - "com.canonical.QtMir.Clipboard", + mDBusClipboard = new QDBusInterface(QStringLiteral("com.canonical.QtMir"), + QStringLiteral("/com/canonical/QtMir/Clipboard"), + QStringLiteral("com.canonical.QtMir.Clipboard"), dbusConnection); mDBusSetupDone = true; @@ -162,6 +162,8 @@ void QMirClientClipboard::setupDBus() QByteArray QMirClientClipboard::serializeMimeData(QMimeData *mimeData) const { + Q_ASSERT(mimeData != nullptr); + const QStringList formats = mimeData->formats(); const int formatCount = qMin(formats.size(), maxFormatsCount); const int headerSize = sizeof(int) + (formatCount * 4 * sizeof(int)); @@ -180,12 +182,13 @@ QByteArray QMirClientClipboard::serializeMimeData(QMimeData *mimeData) const int offset = headerSize; header[0] = formatCount; for (int i = 0; i < formatCount; i++) { + const QByteArray data = mimeData->data(formats[i]); const int formatOffset = offset; const int formatSize = formats[i].size(); const int dataOffset = offset + formatSize; - const int dataSize = mimeData->data(formats[i]).size(); + const int dataSize = data.size(); memcpy(&buffer[formatOffset], formats[i].toLatin1().data(), formatSize); - memcpy(&buffer[dataOffset], mimeData->data(formats[i]).data(), dataSize); + memcpy(&buffer[dataOffset], data.data(), dataSize); header[i*4+1] = formatOffset; header[i*4+2] = formatSize; header[i*4+3] = dataOffset; @@ -265,13 +268,15 @@ void QMirClientClipboard::setMimeData(QMimeData* mimeData, QClipboard::Mode mode delete mPendingGetContentsCall.data(); } - QByteArray serializedMimeData = serializeMimeData(mimeData); - if (!serializedMimeData.isEmpty()) { - setDBusClipboardContents(serializedMimeData); - } + if (mimeData != nullptr) { + QByteArray serializedMimeData = serializeMimeData(mimeData); + if (!serializedMimeData.isEmpty()) { + setDBusClipboardContents(serializedMimeData); + } - mMimeData = mimeData; - emitChanged(QClipboard::Clipboard); + mMimeData = mimeData; + emitChanged(QClipboard::Clipboard); + } } bool QMirClientClipboard::supportsMode(QClipboard::Mode mode) const @@ -287,6 +292,10 @@ bool QMirClientClipboard::ownsMode(QClipboard::Mode mode) const void QMirClientClipboard::setDBusClipboardContents(const QByteArray &clipboardContents) { + if (!mDBusSetupDone) { + setupDBus(); + } + if (!mPendingSetContentsCall.isNull()) { // Ignore any previous set call as we are going to overwrite it anyway QObject::disconnect(mPendingSetContentsCall.data(), 0, this, 0); @@ -296,10 +305,10 @@ void QMirClientClipboard::setDBusClipboardContents(const QByteArray &clipboardCo delete mPendingSetContentsCall.data(); } - QDBusPendingCall pendingCall = mDBusClipboard->asyncCall("SetContents", clipboardContents); + QDBusPendingCall pendingCall = mDBusClipboard->asyncCall(QStringLiteral("SetContents"), clipboardContents); mPendingSetContentsCall = new QDBusPendingCallWatcher(pendingCall, this); - QObject::connect(mPendingSetContentsCall.data(), SIGNAL(finished(QDBusPendingCallWatcher*)), - this, SLOT(onDBusClipboardSetContentsFinished(QDBusPendingCallWatcher*))); + QObject::connect(mPendingSetContentsCall.data(), &QDBusPendingCallWatcher::finished, + this, &QMirClientClipboard::onDBusClipboardSetContentsFinished); } diff --git a/src/plugins/platforms/mirclient/qmirclientcursor.cpp b/src/plugins/platforms/mirclient/qmirclientcursor.cpp new file mode 100644 index 0000000000..1d6ec8391e --- /dev/null +++ b/src/plugins/platforms/mirclient/qmirclientcursor.cpp @@ -0,0 +1,201 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Canonical, Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#include "qmirclientcursor.h" + +#include "qmirclientlogging.h" +#include "qmirclientwindow.h" + +#include + +QMirClientCursor::QMirClientCursor(MirConnection *connection) + : mConnection(connection) +{ + mShapeToCursorName[Qt::ArrowCursor] = "left_ptr"; + mShapeToCursorName[Qt::UpArrowCursor] = "up_arrow"; + mShapeToCursorName[Qt::CrossCursor] = "cross"; + mShapeToCursorName[Qt::WaitCursor] = "watch"; + mShapeToCursorName[Qt::IBeamCursor] = "xterm"; + mShapeToCursorName[Qt::SizeVerCursor] = "size_ver"; + mShapeToCursorName[Qt::SizeHorCursor] = "size_hor"; + mShapeToCursorName[Qt::SizeBDiagCursor] = "size_bdiag"; + mShapeToCursorName[Qt::SizeFDiagCursor] = "size_fdiag"; + mShapeToCursorName[Qt::SizeAllCursor] = "size_all"; + mShapeToCursorName[Qt::BlankCursor] = "blank"; + mShapeToCursorName[Qt::SplitVCursor] = "split_v"; + mShapeToCursorName[Qt::SplitHCursor] = "split_h"; + mShapeToCursorName[Qt::PointingHandCursor] = "hand"; + mShapeToCursorName[Qt::ForbiddenCursor] = "forbidden"; + mShapeToCursorName[Qt::WhatsThisCursor] = "whats_this"; + mShapeToCursorName[Qt::BusyCursor] = "left_ptr_watch"; + mShapeToCursorName[Qt::OpenHandCursor] = "openhand"; + mShapeToCursorName[Qt::ClosedHandCursor] = "closedhand"; + mShapeToCursorName[Qt::DragCopyCursor] = "dnd-copy"; + mShapeToCursorName[Qt::DragMoveCursor] = "dnd-move"; + mShapeToCursorName[Qt::DragLinkCursor] = "dnd-link"; +} + +namespace { +#if !defined(QT_NO_DEBUG) +const char *qtCursorShapeToStr(Qt::CursorShape shape) +{ + switch (shape) { + case Qt::ArrowCursor: + return "Arrow"; + case Qt::UpArrowCursor: + return "UpArrow"; + case Qt::CrossCursor: + return "Cross"; + case Qt::WaitCursor: + return "Wait"; + case Qt::IBeamCursor: + return "IBeam"; + case Qt::SizeVerCursor: + return "SizeVer"; + case Qt::SizeHorCursor: + return "SizeHor"; + case Qt::SizeBDiagCursor: + return "SizeBDiag"; + case Qt::SizeFDiagCursor: + return "SizeFDiag"; + case Qt::SizeAllCursor: + return "SizeAll"; + case Qt::BlankCursor: + return "Blank"; + case Qt::SplitVCursor: + return "SplitV"; + case Qt::SplitHCursor: + return "SplitH"; + case Qt::PointingHandCursor: + return "PointingHand"; + case Qt::ForbiddenCursor: + return "Forbidden"; + case Qt::WhatsThisCursor: + return "WhatsThis"; + case Qt::BusyCursor: + return "Busy"; + case Qt::OpenHandCursor: + return "OpenHand"; + case Qt::ClosedHandCursor: + return "ClosedHand"; + case Qt::DragCopyCursor: + return "DragCopy"; + case Qt::DragMoveCursor: + return "DragMove"; + case Qt::DragLinkCursor: + return "DragLink"; + case Qt::BitmapCursor: + return "Bitmap"; + default: + return "???"; + } +} +#endif // !defined(QT_NO_DEBUG) +} // anonymous namespace + +void QMirClientCursor::changeCursor(QCursor *windowCursor, QWindow *window) +{ + if (!window) { + return; + } + + MirSurface *surface = static_cast(window->handle())->mirSurface(); + + if (!surface) { + return; + } + + + if (windowCursor) { + DLOG("[ubuntumirclient QPA] changeCursor shape=%s, window=%p\n", qtCursorShapeToStr(windowCursor->shape()), window); + if (!windowCursor->pixmap().isNull()) { + configureMirCursorWithPixmapQCursor(surface, *windowCursor); + } else if (windowCursor->shape() == Qt::BitmapCursor) { + // TODO: Implement bitmap cursor support + applyDefaultCursorConfiguration(surface); + } else { + const auto &cursorName = mShapeToCursorName.value(windowCursor->shape(), QByteArray("left_ptr")); + auto cursorConfiguration = mir_cursor_configuration_from_name(cursorName.data()); + mir_surface_configure_cursor(surface, cursorConfiguration); + mir_cursor_configuration_destroy(cursorConfiguration); + } + } else { + applyDefaultCursorConfiguration(surface); + } + +} + +void QMirClientCursor::configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor) +{ + QImage image = cursor.pixmap().toImage(); + + if (image.format() != QImage::Format_ARGB32) { + image.convertToFormat(QImage::Format_ARGB32); + } + + MirBufferStream *bufferStream = mir_connection_create_buffer_stream_sync(mConnection, + image.width(), image.height(), mir_pixel_format_argb_8888, mir_buffer_usage_software); + + { + MirGraphicsRegion region; + mir_buffer_stream_get_graphics_region(bufferStream, ®ion); + + char *regionLine = region.vaddr; + Q_ASSERT(image.bytesPerLine() <= region.stride); + for (int i = 0; i < image.height(); ++i) { + memcpy(regionLine, image.scanLine(i), image.bytesPerLine()); + regionLine += region.stride; + } + } + + mir_buffer_stream_swap_buffers_sync(bufferStream); + + { + auto configuration = mir_cursor_configuration_from_buffer_stream(bufferStream, cursor.hotSpot().x(), cursor.hotSpot().y()); + mir_surface_configure_cursor(surface, configuration); + mir_cursor_configuration_destroy(configuration); + } + + mir_buffer_stream_release_sync(bufferStream); +} + +void QMirClientCursor::applyDefaultCursorConfiguration(MirSurface *surface) +{ + auto cursorConfiguration = mir_cursor_configuration_from_name("left_ptr"); + mir_surface_configure_cursor(surface, cursorConfiguration); + mir_cursor_configuration_destroy(cursorConfiguration); +} diff --git a/src/plugins/platforms/mirclient/qmirclientcursor.h b/src/plugins/platforms/mirclient/qmirclientcursor.h new file mode 100644 index 0000000000..8bb151ddda --- /dev/null +++ b/src/plugins/platforms/mirclient/qmirclientcursor.h @@ -0,0 +1,61 @@ +/**************************************************************************** +** +** Copyright (C) 2015 Canonical, Ltd. +** Contact: http://www.qt.io/licensing/ +** +** This file is part of the plugins of the Qt Toolkit. +** +** $QT_BEGIN_LICENSE:LGPL3$ +** Commercial License Usage +** Licensees holding valid commercial Qt licenses may use this file in +** accordance with the commercial license agreement provided with the +** Software or, alternatively, in accordance with the terms contained in +** a written agreement between you and The Qt Company. For licensing terms +** and conditions see http://www.qt.io/terms-conditions. For further +** information use the contact form at http://www.qt.io/contact-us. +** +** GNU Lesser General Public License Usage +** Alternatively, this file may be used under the terms of the GNU Lesser +** General Public License version 3 as published by the Free Software +** Foundation and appearing in the file LICENSE.LGPLv3 included in the +** packaging of this file. Please review the following information to +** ensure the GNU Lesser General Public License version 3 requirements +** will be met: https://www.gnu.org/licenses/lgpl.html. +** +** GNU General Public License Usage +** Alternatively, this file may be used under the terms of the GNU +** General Public License version 2.0 or later as published by the Free +** Software Foundation and appearing in the file LICENSE.GPL included in +** the packaging of this file. Please review the following information to +** ensure the GNU General Public License version 2.0 requirements will be +** met: http://www.gnu.org/licenses/gpl-2.0.html. +** +** $QT_END_LICENSE$ +** +****************************************************************************/ + + +#ifndef QMIRCLIENTCURSOR_H +#define QMIRCLIENTCURSOR_H + +#include + +#include +#include + +struct MirConnection; +struct MirSurface; + +class QMirClientCursor : public QPlatformCursor +{ +public: + QMirClientCursor(MirConnection *connection); + void changeCursor(QCursor *windowCursor, QWindow *window) override; +private: + void configureMirCursorWithPixmapQCursor(MirSurface *surface, QCursor &cursor); + void applyDefaultCursorConfiguration(MirSurface *surface); + QMap mShapeToCursorName; + MirConnection *mConnection; +}; + +#endif // QMIRCLIENTCURSOR_H diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp index bfba5051e5..01db3b8d61 100644 --- a/src/plugins/platforms/mirclient/qmirclientglcontext.cpp +++ b/src/plugins/platforms/mirclient/qmirclientglcontext.cpp @@ -130,19 +130,7 @@ void QMirClientOpenGLContext::swapBuffers(QPlatformSurface* surface) ASSERT(eglSwapBuffers(mEglDisplay, eglSurface) == EGL_TRUE); #endif - // "Technique" copied from mir, in examples/eglapp.c around line 96 - EGLint newBufferWidth = -1; - EGLint newBufferHeight = -1; - /* - * Querying the surface (actually the current buffer) dimensions here is - * the only truly safe way to be sure that the dimensions we think we - * have are those of the buffer being rendered to. But this should be - * improved in future; https://bugs.launchpad.net/mir/+bug/1194384 - */ - eglQuerySurface(mEglDisplay, eglSurface, EGL_WIDTH, &newBufferWidth); - eglQuerySurface(mEglDisplay, eglSurface, EGL_HEIGHT, &newBufferHeight); - - ubuntuWindow->onBuffersSwapped_threadSafe(newBufferWidth, newBufferHeight); + ubuntuWindow->onSwapBuffersDone(); } void (*QMirClientOpenGLContext::getProcAddress(const QByteArray& procName)) () diff --git a/src/plugins/platforms/mirclient/qmirclientglcontext.h b/src/plugins/platforms/mirclient/qmirclientglcontext.h index cc40298259..29c196ce5c 100644 --- a/src/plugins/platforms/mirclient/qmirclientglcontext.h +++ b/src/plugins/platforms/mirclient/qmirclientglcontext.h @@ -53,7 +53,7 @@ public: bool makeCurrent(QPlatformSurface* surface) override; void doneCurrent() override; bool isValid() const override { return mEglContext != EGL_NO_CONTEXT; } - void (*getProcAddress(const QByteArray& procName)) (); + void (*getProcAddress(const QByteArray& procName)) () override; EGLContext eglContext() const { return mEglContext; } diff --git a/src/plugins/platforms/mirclient/qmirclientinput.cpp b/src/plugins/platforms/mirclient/qmirclientinput.cpp index 56bc21f420..addeda634c 100644 --- a/src/plugins/platforms/mirclient/qmirclientinput.cpp +++ b/src/plugins/platforms/mirclient/qmirclientinput.cpp @@ -163,6 +163,7 @@ QMirClientInput::QMirClientInput(QMirClientClientIntegration* integration) , mEventFilterType(static_cast( integration->nativeInterface())->genericEventFilterType()) , mEventType(static_cast(QEvent::registerEventType())) + , mLastFocusedWindow(nullptr) { // Initialize touch device. mTouchDevice = new QTouchDevice; @@ -234,7 +235,7 @@ void QMirClientInput::customEvent(QEvent* event) switch (mir_event_get_type(nativeEvent)) { case mir_event_type_input: - dispatchInputEvent(ubuntuEvent->window->window(), mir_event_get_input_event(nativeEvent)); + dispatchInputEvent(ubuntuEvent->window, mir_event_get_input_event(nativeEvent)); break; case mir_event_type_resize: { @@ -246,7 +247,7 @@ void QMirClientInput::customEvent(QEvent* event) mir_resize_event_get_width(resizeEvent), mir_resize_event_get_height(resizeEvent)); - ubuntuEvent->window->handleSurfaceResize(mir_resize_event_get_width(resizeEvent), + ubuntuEvent->window->handleSurfaceResized(mir_resize_event_get_width(resizeEvent), mir_resize_event_get_height(resizeEvent)); break; } @@ -254,8 +255,24 @@ void QMirClientInput::customEvent(QEvent* event) { auto surfaceEvent = mir_event_get_surface_event(nativeEvent); if (mir_surface_event_get_attribute(surfaceEvent) == mir_surface_attrib_focus) { - ubuntuEvent->window->handleSurfaceFocusChange(mir_surface_event_get_attribute_value(surfaceEvent) == - mir_surface_focused); + const bool focused = mir_surface_event_get_attribute_value(surfaceEvent) == mir_surface_focused; + // Mir may have sent a pair of focus lost/gained events, so we need to "peek" into the queue + // so that we don't deactivate windows prematurely. + if (focused) { + mPendingFocusGainedEvents--; + ubuntuEvent->window->handleSurfaceFocused(); + QWindowSystemInterface::handleWindowActivated(ubuntuEvent->window->window(), Qt::ActiveWindowFocusReason); + + // NB: Since processing of system events is queued, never check qGuiApp->applicationState() + // as it might be outdated. Always call handleApplicationStateChanged() with the latest + // state regardless. + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive); + + } else if (!mPendingFocusGainedEvents) { + DLOG("[ubuntumirclient QPA] No windows have focus"); + QWindowSystemInterface::handleWindowActivated(nullptr, Qt::ActiveWindowFocusReason); + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); + } } break; } @@ -274,6 +291,17 @@ void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent { QWindow *window = platformWindow->window(); + const auto eventType = mir_event_get_type(event); + if (mir_event_type_surface == eventType) { + auto surfaceEvent = mir_event_get_surface_event(event); + if (mir_surface_attrib_focus == mir_surface_event_get_attribute(surfaceEvent)) { + const bool focused = mir_surface_event_get_attribute_value(surfaceEvent) == mir_surface_focused; + if (focused) { + mPendingFocusGainedEvents++; + } + } + } + QCoreApplication::postEvent(this, new QMirClientEvent( platformWindow, event, mEventType)); @@ -284,7 +312,7 @@ void QMirClientInput::postEvent(QMirClientWindow *platformWindow, const MirEvent } } -void QMirClientInput::dispatchInputEvent(QWindow *window, const MirInputEvent *ev) +void QMirClientInput::dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *ev) { switch (mir_input_event_get_type(ev)) { @@ -302,7 +330,7 @@ void QMirClientInput::dispatchInputEvent(QWindow *window, const MirInputEvent *e } } -void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *ev) +void QMirClientInput::dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *ev) { const MirTouchEvent *tev = mir_input_event_get_touch_event(ev); @@ -333,6 +361,7 @@ void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *e switch (touch_action) { case mir_touch_action_down: + mLastFocusedWindow = window; touchPoint.state = Qt::TouchPointPressed; break; case mir_touch_action_up: @@ -347,7 +376,7 @@ void QMirClientInput::dispatchTouchEvent(QWindow *window, const MirInputEvent *e } ulong timestamp = mir_input_event_get_event_time(ev) / 1000000; - QWindowSystemInterface::handleTouchEvent(window, timestamp, + QWindowSystemInterface::handleTouchEvent(window->window(), timestamp, mTouchDevice, touchPoints); } @@ -390,7 +419,7 @@ Qt::KeyboardModifiers qt_modifiers_from_mir(MirInputEventModifiers modifiers) } } -void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *event) +void QMirClientInput::dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event) { const MirKeyboardEvent *key_event = mir_input_event_get_keyboard_event(event); @@ -404,6 +433,9 @@ void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *eve QEvent::Type keyType = action == mir_keyboard_action_up ? QEvent::KeyRelease : QEvent::KeyPress; + if (action == mir_keyboard_action_down) + mLastFocusedWindow = window; + char s[2]; int sym = translateKeysym(xk_sym, s, sizeof(s)); QString text = QString::fromLatin1(s); @@ -420,7 +452,7 @@ void QMirClientInput::dispatchKeyEvent(QWindow *window, const MirInputEvent *eve } } - QWindowSystemInterface::handleKeyEvent(window, timestamp, keyType, sym, modifiers, text, is_auto_rep); + QWindowSystemInterface::handleKeyEvent(window->window(), timestamp, keyType, sym, modifiers, text, is_auto_rep); } namespace @@ -433,27 +465,54 @@ Qt::MouseButtons extract_buttons(const MirPointerEvent *pev) if (mir_pointer_event_button_state(pev, mir_pointer_button_secondary)) buttons |= Qt::RightButton; if (mir_pointer_event_button_state(pev, mir_pointer_button_tertiary)) - buttons |= Qt::MidButton; + buttons |= Qt::MiddleButton; + if (mir_pointer_event_button_state(pev, mir_pointer_button_back)) + buttons |= Qt::BackButton; + if (mir_pointer_event_button_state(pev, mir_pointer_button_forward)) + buttons |= Qt::ForwardButton; - // TODO: Should mir back and forward buttons exist? - // should they be Qt::X button 1 and 2? return buttons; } } -void QMirClientInput::dispatchPointerEvent(QWindow *window, const MirInputEvent *ev) +void QMirClientInput::dispatchPointerEvent(QMirClientWindow *platformWindow, const MirInputEvent *ev) { + auto window = platformWindow->window(); auto timestamp = mir_input_event_get_event_time(ev) / 1000000; auto pev = mir_input_event_get_pointer_event(ev); + auto action = mir_pointer_event_action(pev); + auto localPoint = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x), + mir_pointer_event_axis_value(pev, mir_pointer_axis_y)); auto modifiers = qt_modifiers_from_mir(mir_pointer_event_modifiers(pev)); - auto buttons = extract_buttons(pev); - auto local_point = QPointF(mir_pointer_event_axis_value(pev, mir_pointer_axis_x), - mir_pointer_event_axis_value(pev, mir_pointer_axis_y)); + switch (action) { + case mir_pointer_action_button_up: + case mir_pointer_action_button_down: + case mir_pointer_action_motion: + { + const float hDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_hscroll); + const float vDelta = mir_pointer_event_axis_value(pev, mir_pointer_axis_vscroll); - QWindowSystemInterface::handleMouseEvent(window, timestamp, local_point, local_point /* Should we omit global point instead? */, - buttons, modifiers); + if (hDelta != 0 || vDelta != 0) { + const QPoint angleDelta = QPoint(hDelta * 15, vDelta * 15); + QWindowSystemInterface::handleWheelEvent(window, timestamp, localPoint, window->position() + localPoint, + QPoint(), angleDelta, modifiers, Qt::ScrollUpdate); + } + auto buttons = extract_buttons(pev); + QWindowSystemInterface::handleMouseEvent(window, timestamp, localPoint, window->position() + localPoint /* Should we omit global point instead? */, + buttons, modifiers); + break; + } + case mir_pointer_action_enter: + QWindowSystemInterface::handleEnterEvent(window, localPoint, window->position() + localPoint); + break; + case mir_pointer_action_leave: + QWindowSystemInterface::handleLeaveEvent(window); + break; + default: + DLOG("Unrecognized pointer event"); + } } #if (LOG_EVENTS != 0) diff --git a/src/plugins/platforms/mirclient/qmirclientinput.h b/src/plugins/platforms/mirclient/qmirclientinput.h index c987d18c12..3ed887419e 100644 --- a/src/plugins/platforms/mirclient/qmirclientinput.h +++ b/src/plugins/platforms/mirclient/qmirclientinput.h @@ -40,6 +40,7 @@ // Qt #include +#include #include @@ -59,12 +60,13 @@ public: void postEvent(QMirClientWindow* window, const MirEvent *event); QMirClientClientIntegration* integration() const { return mIntegration; } + QMirClientWindow *lastFocusedWindow() const {return mLastFocusedWindow; } protected: - void dispatchKeyEvent(QWindow *window, const MirInputEvent *event); - void dispatchPointerEvent(QWindow *window, const MirInputEvent *event); - void dispatchTouchEvent(QWindow *window, const MirInputEvent *event); - void dispatchInputEvent(QWindow *window, const MirInputEvent *event); + void dispatchKeyEvent(QMirClientWindow *window, const MirInputEvent *event); + void dispatchPointerEvent(QMirClientWindow *window, const MirInputEvent *event); + void dispatchTouchEvent(QMirClientWindow *window, const MirInputEvent *event); + void dispatchInputEvent(QMirClientWindow *window, const MirInputEvent *event); void dispatchOrientationEvent(QWindow* window, const MirOrientationEvent *event); @@ -73,6 +75,9 @@ private: QTouchDevice* mTouchDevice; const QByteArray mEventFilterType; const QEvent::Type mEventType; + + QMirClientWindow *mLastFocusedWindow; + QAtomicInt mPendingFocusGainedEvents; }; #endif // QMIRCLIENTINPUT_H diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.cpp b/src/plugins/platforms/mirclient/qmirclientintegration.cpp index a234f4eac6..4b2572ce0d 100644 --- a/src/plugins/platforms/mirclient/qmirclientintegration.cpp +++ b/src/plugins/platforms/mirclient/qmirclientintegration.cpp @@ -35,28 +35,28 @@ ****************************************************************************/ -// Qt -#include -#include -#include -#include -#include -#include -#include -#include - // Local +#include "qmirclientintegration.h" #include "qmirclientbackingstore.h" #include "qmirclientclipboard.h" #include "qmirclientglcontext.h" #include "qmirclientinput.h" -#include "qmirclientintegration.h" #include "qmirclientlogging.h" #include "qmirclientnativeinterface.h" #include "qmirclientscreen.h" #include "qmirclienttheme.h" #include "qmirclientwindow.h" +// Qt +#include +#include +#include +#include +#include +#include +#include +#include + // platform-api #include #include @@ -67,8 +67,11 @@ static void resumedCallback(const UApplicationOptions *options, void* context) Q_UNUSED(options) Q_UNUSED(context) DASSERT(context != NULL); - QCoreApplication::postEvent(QCoreApplication::instance(), - new QEvent(QEvent::ApplicationActivate)); + if (qGuiApp->focusWindow()) { + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationActive); + } else { + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationInactive); + } } static void aboutToStopCallback(UApplicationArchive *archive, void* context) @@ -76,9 +79,13 @@ static void aboutToStopCallback(UApplicationArchive *archive, void* context) Q_UNUSED(archive) DASSERT(context != NULL); QMirClientClientIntegration* integration = static_cast(context); - integration->inputContext()->hideInputPanel(); - QCoreApplication::postEvent(QCoreApplication::instance(), - new QEvent(QEvent::ApplicationDeactivate)); + QPlatformInputContext *inputContext = integration->inputContext(); + if (inputContext) { + inputContext->hideInputPanel(); + } else { + qWarning("QMirClientClientIntegration aboutToStopCallback(): no input context"); + } + QWindowSystemInterface::handleApplicationStateChanged(Qt::ApplicationSuspended); } QMirClientClientIntegration::QMirClientClientIntegration() @@ -100,6 +107,8 @@ QMirClientClientIntegration::QMirClientClientIntegration() "running, and the correct socket is being used and is accessible. The shell may have\n" "rejected the incoming connection, so check its log file"); + mNativeInterface->setMirConnection(u_application_instance_get_mir_connection(mInstance)); + // Create default screen. mScreen = new QMirClientScreen(u_application_instance_get_mir_connection(mInstance)); screenAdded(mScreen); @@ -176,10 +185,8 @@ QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* wind QPlatformWindow* QMirClientClientIntegration::createPlatformWindow(QWindow* window) { - QPlatformWindow* platformWindow = new QMirClientWindow( - window, mClipboard, static_cast(mScreen), mInput, u_application_instance_get_mir_connection(mInstance)); - platformWindow->requestActivateWindow(); - return platformWindow; + return new QMirClientWindow(window, mClipboard, static_cast(mScreen), + mInput, u_application_instance_get_mir_connection(mInstance)); } bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability cap) const @@ -187,11 +194,12 @@ bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability switch (cap) { case ThreadedPixmaps: return true; - break; case OpenGL: return true; - break; + + case ApplicationState: + return true; case ThreadedOpenGL: if (qEnvironmentVariableIsEmpty("QTUBUNTU_NO_THREADED_OPENGL")) { @@ -200,8 +208,9 @@ bool QMirClientClientIntegration::hasCapability(QPlatformIntegration::Capability DLOG("ubuntumirclient: disabled threaded OpenGL"); return false; } - break; - + case MultipleWindows: + case NonFullScreenWindows: + return true; default: return QPlatformIntegration::hasCapability(cap); } @@ -262,3 +271,8 @@ QPlatformClipboard* QMirClientClientIntegration::clipboard() const { return mClipboard.data(); } + +QPlatformNativeInterface* QMirClientClientIntegration::nativeInterface() const +{ + return mNativeInterface; +} diff --git a/src/plugins/platforms/mirclient/qmirclientintegration.h b/src/plugins/platforms/mirclient/qmirclientintegration.h index 2960209691..e41cbe2cee 100644 --- a/src/plugins/platforms/mirclient/qmirclientintegration.h +++ b/src/plugins/platforms/mirclient/qmirclientintegration.h @@ -49,6 +49,7 @@ class QMirClientClipboard; class QMirClientInput; +class QMirClientNativeInterface; class QMirClientScreen; class QMirClientClientIntegration : public QPlatformIntegration { @@ -59,7 +60,7 @@ public: // QPlatformIntegration methods. bool hasCapability(QPlatformIntegration::Capability cap) const override; QAbstractEventDispatcher *createEventDispatcher() const override; - QPlatformNativeInterface* nativeInterface() const override { return mNativeInterface; } + QPlatformNativeInterface* nativeInterface() const override; QPlatformBackingStore* createPlatformBackingStore(QWindow* window) const override; QPlatformOpenGLContext* createPlatformOpenGLContext(QOpenGLContext* context) const override; QPlatformFontDatabase* fontDatabase() const override { return mFontDb; } @@ -79,7 +80,7 @@ private: void setupOptions(); void setupDescription(); - QPlatformNativeInterface* mNativeInterface; + QMirClientNativeInterface* mNativeInterface; QPlatformFontDatabase* mFontDb; QMirClientPlatformServices* mServices; diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp index a0bb932df3..1b4c20153b 100644 --- a/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp +++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.cpp @@ -35,17 +35,17 @@ ****************************************************************************/ +// Local +#include "qmirclientnativeinterface.h" +#include "qmirclientscreen.h" +#include "qmirclientglcontext.h" + // Qt #include #include #include #include -// Local -#include "qmirclientnativeinterface.h" -#include "qmirclientscreen.h" -#include "qmirclientglcontext.h" - class QMirClientResourceMap : public QMap { public: @@ -55,6 +55,7 @@ public: insert("eglcontext", QMirClientNativeInterface::EglContext); insert("nativeorientation", QMirClientNativeInterface::NativeOrientation); insert("display", QMirClientNativeInterface::Display); + insert("mirconnection", QMirClientNativeInterface::MirConnection); } }; @@ -63,6 +64,7 @@ Q_GLOBAL_STATIC(QMirClientResourceMap, ubuntuResourceMap) QMirClientNativeInterface::QMirClientNativeInterface() : mGenericEventFilterType(QByteArrayLiteral("Event")) , mNativeOrientation(nullptr) + , mMirConnection(nullptr) { } @@ -72,6 +74,23 @@ QMirClientNativeInterface::~QMirClientNativeInterface() mNativeOrientation = nullptr; } +void* QMirClientNativeInterface::nativeResourceForIntegration(const QByteArray &resourceString) +{ + const QByteArray lowerCaseResource = resourceString.toLower(); + + if (!ubuntuResourceMap()->contains(lowerCaseResource)) { + return nullptr; + } + + const ResourceType resourceType = ubuntuResourceMap()->value(lowerCaseResource); + + if (resourceType == QMirClientNativeInterface::MirConnection) { + return mMirConnection; + } else { + return nullptr; + } +} + void* QMirClientNativeInterface::nativeResourceForContext( const QByteArray& resourceString, QOpenGLContext* context) { diff --git a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h index 84f03bb915..7df646e73a 100644 --- a/src/plugins/platforms/mirclient/qmirclientnativeinterface.h +++ b/src/plugins/platforms/mirclient/qmirclientnativeinterface.h @@ -42,12 +42,13 @@ class QMirClientNativeInterface : public QPlatformNativeInterface { public: - enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display }; + enum ResourceType { EglDisplay, EglContext, NativeOrientation, Display, MirConnection }; QMirClientNativeInterface(); ~QMirClientNativeInterface(); // QPlatformNativeInterface methods. + void* nativeResourceForIntegration(const QByteArray &resource) override; void* nativeResourceForContext(const QByteArray& resourceString, QOpenGLContext* context) override; void* nativeResourceForWindow(const QByteArray& resourceString, @@ -57,10 +58,12 @@ public: // New methods. const QByteArray& genericEventFilterType() const { return mGenericEventFilterType; } + void setMirConnection(void *mirConnection) { mMirConnection = mirConnection; } private: const QByteArray mGenericEventFilterType; Qt::ScreenOrientation* mNativeOrientation; + void *mMirConnection; }; #endif // QMIRCLIENTNATIVEINTERFACE_H diff --git a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h index 24d7307faa..2a1ed9c09f 100644 --- a/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h +++ b/src/plugins/platforms/mirclient/qmirclientorientationchangeevent_p.h @@ -43,15 +43,7 @@ class OrientationChangeEvent : public QEvent { public: - enum Orientation { - Undefined = 0, - TopUp, - TopDown, - LeftUp, - RightUp, - FaceUp, - FaceDown - }; + enum Orientation { TopUp, LeftUp, TopDown, RightUp }; OrientationChangeEvent(QEvent::Type type, Orientation orientation) : QEvent(type) diff --git a/src/plugins/platforms/mirclient/qmirclientplugin.cpp b/src/plugins/platforms/mirclient/qmirclientplugin.cpp index 203a1cbfd8..75561f7fd3 100644 --- a/src/plugins/platforms/mirclient/qmirclientplugin.cpp +++ b/src/plugins/platforms/mirclient/qmirclientplugin.cpp @@ -41,14 +41,14 @@ QStringList QMirClientIntegrationPlugin::keys() const { QStringList list; - list << "mirclient"; + list << QStringLiteral("mirclient"); return list; } QPlatformIntegration* QMirClientIntegrationPlugin::create(const QString &system, const QStringList &) { - if (system.toLower() == "mirclient") { + if (system.toLower() == QLatin1String("mirclient")) { return new QMirClientClientIntegration; } else { return 0; diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.cpp b/src/plugins/platforms/mirclient/qmirclientscreen.cpp index 5c4b1cd0d6..3eb01f816a 100644 --- a/src/plugins/platforms/mirclient/qmirclientscreen.cpp +++ b/src/plugins/platforms/mirclient/qmirclientscreen.cpp @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Canonical, Ltd. +** Copyright (C) 2014-2015 Canonical, Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -35,6 +35,11 @@ ****************************************************************************/ +// local +#include "qmirclientscreen.h" +#include "qmirclientlogging.h" +#include "qmirclientorientationchangeevent_p.h" + #include // Qt @@ -45,12 +50,7 @@ #include #include -// local -#include "qmirclientscreen.h" -#include "qmirclientlogging.h" -#include "qmirclientorientationchangeevent_p.h" - -#include "memory" +#include static const int kSwapInterval = 1; @@ -149,9 +149,11 @@ static const MirDisplayOutput *find_active_output( QMirClientScreen::QMirClientScreen(MirConnection *connection) : mFormat(QImage::Format_RGB32) , mDepth(32) + , mOutputId(0) , mSurfaceFormat() , mEglDisplay(EGL_NO_DISPLAY) , mEglConfig(nullptr) + , mCursor(connection) { // Initialize EGL. ASSERT(eglBindAPI(EGL_OPENGL_ES_API) == EGL_TRUE); @@ -203,6 +205,11 @@ QMirClientScreen::QMirClientScreen(MirConnection *connection) auto const displayOutput = find_active_output(displayConfig.get()); ASSERT(displayOutput != nullptr); + mOutputId = displayOutput->output_id; + + mPhysicalSize = QSizeF(displayOutput->physical_width_mm, displayOutput->physical_height_mm); + DLOG("ubuntumirclient: screen physical size: %.2fx%.2f", mPhysicalSize.width(), mPhysicalSize.height()); + const MirDisplayMode *mode = &displayOutput->modes[displayOutput->current_mode]; const int kScreenWidth = mode->horizontal_resolution; const int kScreenHeight = mode->vertical_resolution; diff --git a/src/plugins/platforms/mirclient/qmirclientscreen.h b/src/plugins/platforms/mirclient/qmirclientscreen.h index 5d9325354f..a6b4f442da 100644 --- a/src/plugins/platforms/mirclient/qmirclientscreen.h +++ b/src/plugins/platforms/mirclient/qmirclientscreen.h @@ -1,6 +1,6 @@ /**************************************************************************** ** -** Copyright (C) 2014 Canonical, Ltd. +** Copyright (C) 2014-2015 Canonical, Ltd. ** Contact: http://www.qt.io/licensing/ ** ** This file is part of the plugins of the Qt Toolkit. @@ -42,6 +42,8 @@ #include #include +#include "qmirclientcursor.h" + struct MirConnection; class QMirClientScreen : public QObject, public QPlatformScreen @@ -56,8 +58,10 @@ public: int depth() const override { return mDepth; } QRect geometry() const override { return mGeometry; } QRect availableGeometry() const override { return mGeometry; } + QSizeF physicalSize() const override { return mPhysicalSize; } Qt::ScreenOrientation nativeOrientation() const override { return mNativeOrientation; } Qt::ScreenOrientation orientation() const override { return mNativeOrientation; } + QPlatformCursor *cursor() const override { return const_cast(&mCursor); } // New methods. QSurfaceFormat surfaceFormat() const { return mSurfaceFormat; } @@ -65,20 +69,24 @@ public: EGLConfig eglConfig() const { return mEglConfig; } EGLNativeDisplayType eglNativeDisplay() const { return mEglNativeDisplay; } void handleWindowSurfaceResize(int width, int height); + uint32_t mirOutputId() const { return mOutputId; } // QObject methods. - void customEvent(QEvent* event); + void customEvent(QEvent* event) override; private: QRect mGeometry; + QSizeF mPhysicalSize; Qt::ScreenOrientation mNativeOrientation; Qt::ScreenOrientation mCurrentOrientation; QImage::Format mFormat; int mDepth; + uint32_t mOutputId; QSurfaceFormat mSurfaceFormat; EGLDisplay mEglDisplay; EGLConfig mEglConfig; EGLNativeDisplayType mEglNativeDisplay; + QMirClientCursor mCursor; }; #endif // QMIRCLIENTSCREEN_H diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.cpp b/src/plugins/platforms/mirclient/qmirclientwindow.cpp index 3d1e5377e5..9a72c2f9dc 100644 --- a/src/plugins/platforms/mirclient/qmirclientwindow.cpp +++ b/src/plugins/platforms/mirclient/qmirclientwindow.cpp @@ -36,16 +36,16 @@ // Local +#include "qmirclientwindow.h" #include "qmirclientclipboard.h" #include "qmirclientinput.h" -#include "qmirclientwindow.h" #include "qmirclientscreen.h" #include "qmirclientlogging.h" +#include + // Qt #include -#include -#include #include #include #include @@ -55,25 +55,46 @@ #include -#define IS_OPAQUE_FLAG 1 - namespace { + +// FIXME: this used to be defined by platform-api, but it's been removed in v3. Change ubuntu-keyboard to use +// a different enum for window roles. +enum UAUiWindowRole { + U_MAIN_ROLE = 1, + U_DASH_ROLE, + U_INDICATOR_ROLE, + U_NOTIFICATIONS_ROLE, + U_GREETER_ROLE, + U_LAUNCHER_ROLE, + U_ON_SCREEN_KEYBOARD_ROLE, + U_SHUTDOWN_DIALOG_ROLE, +}; + +struct MirSpecDeleter +{ + void operator()(MirSurfaceSpec *spec) { mir_surface_spec_release(spec); } +}; + +using Spec = std::unique_ptr; + +EGLNativeWindowType nativeWindowFor(MirSurface *surf) +{ + auto stream = mir_surface_get_buffer_stream(surf); + return reinterpret_cast(mir_buffer_stream_get_egl_native_window(stream)); +} + MirSurfaceState qtWindowStateToMirSurfaceState(Qt::WindowState state) { switch (state) { case Qt::WindowNoState: return mir_surface_state_restored; - case Qt::WindowFullScreen: return mir_surface_state_fullscreen; - case Qt::WindowMaximized: return mir_surface_state_maximized; - case Qt::WindowMinimized: return mir_surface_state_minimized; - default: LOG("Unexpected Qt::WindowState: %d", state); return mir_surface_state_restored; @@ -86,117 +107,137 @@ const char *qtWindowStateToStr(Qt::WindowState state) switch (state) { case Qt::WindowNoState: return "NoState"; - case Qt::WindowFullScreen: return "FullScreen"; - case Qt::WindowMaximized: return "Maximized"; - case Qt::WindowMinimized: return "Minimized"; - default: return "!?"; } } #endif -} // anonymous namespace - -class QMirClientWindowPrivate +WId makeId() { -public: - void createEGLSurface(EGLNativeWindowType nativeWindow); - void destroyEGLSurface(); - int panelHeight(); - - QMirClientScreen* screen; - EGLSurface eglSurface; - WId id; - QMirClientInput* input; - Qt::WindowState state; - MirConnection *connection; - MirSurface* surface; - QSize bufferSize; - QMutex mutex; - QSharedPointer clipboard; -}; - -static void eventCallback(MirSurface* surface, const MirEvent *event, void* context) -{ - (void) surface; - DASSERT(context != NULL); - QMirClientWindow* platformWindow = static_cast(context); - platformWindow->priv()->input->postEvent(platformWindow, event); + static int id = 1; + return id++; } -static void surfaceCreateCallback(MirSurface* surface, void* context) +MirPixelFormat defaultPixelFormatFor(MirConnection *connection) { - DASSERT(context != NULL); - QMirClientWindow* platformWindow = static_cast(context); - platformWindow->priv()->surface = surface; - - mir_surface_set_event_handler(surface, eventCallback, context); + MirPixelFormat format; + unsigned int nformats; + mir_connection_get_available_surface_formats(connection, &format, 1, &nformats); + return format; } -QMirClientWindow::QMirClientWindow(QWindow* w, QSharedPointer clipboard, QMirClientScreen* screen, - QMirClientInput* input, MirConnection* connection) - : QObject(nullptr), QPlatformWindow(w) +UAUiWindowRole roleFor(QWindow *window) { - DASSERT(screen != NULL); + QVariant roleVariant = window->property("role"); + if (!roleVariant.isValid()) + return U_MAIN_ROLE; - d = new QMirClientWindowPrivate; - d->screen = screen; - d->eglSurface = EGL_NO_SURFACE; - d->input = input; - d->state = window()->windowState(); - d->connection = connection; - d->clipboard = clipboard; + uint role = roleVariant.toUInt(); + if (role < U_MAIN_ROLE || role > U_SHUTDOWN_DIALOG_ROLE) + return U_MAIN_ROLE; - static int id = 1; - d->id = id++; - - // Use client geometry if set explicitly, use available screen geometry otherwise. - QPlatformWindow::setGeometry(window()->geometry().isValid() && window()->geometry() != screen->geometry() ? - window()->geometry() : screen->availableGeometry()); - createWindow(); - DLOG("QMirClientWindow::QMirClientWindow (this=%p, w=%p, screen=%p, input=%p)", this, w, screen, input); + return static_cast(role); } -QMirClientWindow::~QMirClientWindow() +QMirClientWindow *transientParentFor(QWindow *window) { - DLOG("QMirClientWindow::~QMirClientWindow"); - d->destroyEGLSurface(); - - mir_surface_release_sync(d->surface); - - delete d; + QWindow *parent = window->transientParent(); + return parent ? static_cast(parent->handle()) : nullptr; } -void QMirClientWindowPrivate::createEGLSurface(EGLNativeWindowType nativeWindow) +Spec makeSurfaceSpec(QWindow *window, QMirClientInput *input, MirConnection *connection) { - DLOG("QMirClientWindowPrivate::createEGLSurface (this=%p, nativeWindow=%p)", - this, reinterpret_cast(nativeWindow)); - - eglSurface = eglCreateWindowSurface(screen->eglDisplay(), screen->eglConfig(), - nativeWindow, nullptr); + const auto geom = window->geometry(); + const int width = geom.width() > 0 ? geom.width() : 1; + const int height = geom.height() > 0 ? geom.height() : 1; + const auto pixelFormat = defaultPixelFormatFor(connection); + + if (U_ON_SCREEN_KEYBOARD_ROLE == roleFor(window)) { + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating input method surface (width=%d, height=%d", window, width, height); + return Spec{mir_connection_create_spec_for_input_method(connection, width, height, pixelFormat)}; + } + + const Qt::WindowType type = window->type(); + if (type == Qt::Popup) { + auto parent = transientParentFor(window); + if (parent == nullptr) { + //NOTE: We cannot have a parentless popup - + //try using the last surface to receive input as that will most likely be + //the one that caused this popup to be created + parent = input->lastFocusedWindow(); + } + if (parent) { + auto pos = geom.topLeft(); + pos -= parent->geometry().topLeft(); + MirRectangle location{pos.x(), pos.y(), 0, 0}; + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating menu surface(width:%d, height:%d)", window, width, height); + return Spec{mir_connection_create_spec_for_menu( + connection, width, height, pixelFormat, parent->mirSurface(), + &location, mir_edge_attachment_any)}; + } else { + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - cannot create a menu without a parent!", window); + } + } else if (type == Qt::Dialog) { + auto parent = transientParentFor(window); + if (parent) { + // Modal dialog + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating modal dialog (width=%d, height=%d", window, width, height); + return Spec{mir_connection_create_spec_for_modal_dialog(connection, width, height, pixelFormat, parent->mirSurface())}; + } else { + // TODO: do Qt parentless dialogs have the same semantics as mir? + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating parentless dialog (width=%d, height=%d)", window, width, height); + return Spec{mir_connection_create_spec_for_dialog(connection, width, height, pixelFormat)}; + } + } + DLOG("[ubuntumirclient QPA] makeSurfaceSpec(window=%p) - creating normal surface(type=0x%x, width=%d, height=%d)", window, type, width, height); + return Spec{mir_connection_create_spec_for_normal_surface(connection, width, height, pixelFormat)}; +} - DASSERT(eglSurface != EGL_NO_SURFACE); +void setSizingConstraints(MirSurfaceSpec *spec, const QSize& minSize, const QSize& maxSize, const QSize& increment) +{ + mir_surface_spec_set_min_width(spec, minSize.width()); + mir_surface_spec_set_min_height(spec, minSize.height()); + if (maxSize.width() >= minSize.width()) { + mir_surface_spec_set_max_width(spec, maxSize.width()); + } + if (maxSize.height() >= minSize.height()) { + mir_surface_spec_set_max_height(spec, maxSize.height()); + } + if (increment.width() > 0) { + mir_surface_spec_set_width_increment(spec, increment.width()); + } + if (increment.height() > 0) { + mir_surface_spec_set_height_increment(spec, increment.height()); + } } -void QMirClientWindowPrivate::destroyEGLSurface() +MirSurface *createMirSurface(QWindow *window, QMirClientScreen *screen, QMirClientInput *input, MirConnection *connection) { - DLOG("QMirClientWindowPrivate::destroyEGLSurface (this=%p)", this); - if (eglSurface != EGL_NO_SURFACE) { - eglDestroySurface(screen->eglDisplay(), eglSurface); - eglSurface = EGL_NO_SURFACE; + auto spec = makeSurfaceSpec(window, input, connection); + const auto title = window->title().toUtf8(); + mir_surface_spec_set_name(spec.get(), title.constData()); + + setSizingConstraints(spec.get(), window->minimumSize(), window->maximumSize(), window->sizeIncrement()); + + if (window->windowState() == Qt::WindowFullScreen) { + mir_surface_spec_set_fullscreen_on_output(spec.get(), screen->mirOutputId()); } + + auto surface = mir_surface_create_sync(spec.get()); + Q_ASSERT(mir_surface_is_valid(surface)); + return surface; } // FIXME - in order to work around https://bugs.launchpad.net/mir/+bug/1346633 -// we need to guess the panel height (3GU + 2DP) -int QMirClientWindowPrivate::panelHeight() +// we need to guess the panel height (3GU) +int panelHeight() { if (qEnvironmentVariableIsSet("QT_MIRCLIENT_IGNORE_PANEL")) return 0; @@ -210,245 +251,412 @@ int QMirClientWindowPrivate::panelHeight() gridUnit = defaultGridUnit; } } - qreal densityPixelRatio = static_cast(gridUnit) / defaultGridUnit; - return gridUnit * 3 + qFloor(densityPixelRatio) * 2; + return gridUnit * 3; } -namespace +} //namespace + +class QMirClientSurface { -static MirPixelFormat -mir_choose_default_pixel_format(MirConnection *connection) +public: + QMirClientSurface(QMirClientWindow *platformWindow, QMirClientScreen *screen, QMirClientInput *input, MirConnection *connection) + : mWindow(platformWindow->window()) + , mPlatformWindow(platformWindow) + , mInput(input) + , mConnection(connection) + , mMirSurface(createMirSurface(mWindow, screen, input, connection)) + , mEglDisplay(screen->eglDisplay()) + , mEglSurface(eglCreateWindowSurface(mEglDisplay, screen->eglConfig(), nativeWindowFor(mMirSurface), nullptr)) + , mVisible(false) + , mNeedsRepaint(false) + , mParented(mWindow->transientParent() || mWindow->parent()) + , mWindowState(mWindow->windowState()) + + { + mir_surface_set_event_handler(mMirSurface, surfaceEventCallback, this); + + // Window manager can give us a final size different from what we asked for + // so let's check what we ended up getting + MirSurfaceParameters parameters; + mir_surface_get_parameters(mMirSurface, ¶meters); + + auto geom = mWindow->geometry(); + geom.setWidth(parameters.width); + geom.setHeight(parameters.height); + if (mWindowState == Qt::WindowFullScreen) { + geom.setY(0); + } else { + geom.setY(panelHeight()); + } + + // Assume that the buffer size matches the surface size at creation time + mBufferSize = geom.size(); + platformWindow->QPlatformWindow::setGeometry(geom); + QWindowSystemInterface::handleGeometryChange(mWindow, geom); + + DLOG("[ubuntumirclient QPA] created surface at (%d, %d) with size (%d, %d), title '%s', role: '%d'\n", + geom.x(), geom.y(), geom.width(), geom.height(), mWindow->title().toUtf8().constData(), roleFor(mWindow)); + } + + ~QMirClientSurface() + { + if (mEglSurface != EGL_NO_SURFACE) + eglDestroySurface(mEglDisplay, mEglSurface); + if (mMirSurface) + mir_surface_release_sync(mMirSurface); + } + + QMirClientSurface(QMirClientSurface const&) = delete; + QMirClientSurface& operator=(QMirClientSurface const&) = delete; + + void resize(const QSize& newSize); + void setState(Qt::WindowState newState); + void setVisible(bool state); + void updateTitle(const QString& title); + void setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment); + + void onSwapBuffersDone(); + void handleSurfaceResized(int width, int height); + int needsRepaint() const; + + EGLSurface eglSurface() const { return mEglSurface; } + MirSurface *mirSurface() const { return mMirSurface; } + +private: + static void surfaceEventCallback(MirSurface* surface, const MirEvent *event, void* context); + void postEvent(const MirEvent *event); + void updateSurface(); + + QWindow * const mWindow; + QMirClientWindow * const mPlatformWindow; + QMirClientInput * const mInput; + MirConnection * const mConnection; + + MirSurface * const mMirSurface; + const EGLDisplay mEglDisplay; + const EGLSurface mEglSurface; + + bool mVisible; + bool mNeedsRepaint; + bool mParented; + Qt::WindowState mWindowState; + QSize mBufferSize; + + QMutex mTargetSizeMutex; + QSize mTargetSize; +}; + +void QMirClientSurface::resize(const QSize& size) { - MirPixelFormat format[mir_pixel_formats]; - unsigned int nformats; + DLOG("[ubuntumirclient QPA] resize(window=%p, width=%d, height=%d)", mWindow, size.width(), size.height()); + + if (mWindowState == Qt::WindowFullScreen || mWindowState == Qt::WindowMaximized) { + DLOG("[ubuntumirclient QPA] resize(window=%p) - not resizing, window is maximized or fullscreen", mWindow); + return; + } - mir_connection_get_available_surface_formats(connection, - format, mir_pixel_formats, &nformats); + if (size.isEmpty()) { + DLOG("[ubuntumirclient QPA] resize(window=%p) - not resizing, size is empty", mWindow); + return; + } - return format[0]; + Spec spec{mir_connection_create_spec_for_changes(mConnection)}; + mir_surface_spec_set_width(spec.get(), size.width()); + mir_surface_spec_set_height(spec.get(), size.height()); + mir_surface_apply_spec(mMirSurface, spec.get()); } + +void QMirClientSurface::setState(Qt::WindowState newState) +{ + mir_wait_for(mir_surface_set_state(mMirSurface, qtWindowStateToMirSurfaceState(newState))); + mWindowState = newState; } -void QMirClientWindow::createWindow() +void QMirClientSurface::setVisible(bool visible) { - DLOG("QMirClientWindow::createWindow (this=%p)", this); + if (mVisible == visible) + return; - // FIXME: remove this remnant of an old platform-api enum - needs ubuntu-keyboard update - const int SCREEN_KEYBOARD_ROLE = 7; - // Get surface role and flags. - QVariant roleVariant = window()->property("role"); - int role = roleVariant.isValid() ? roleVariant.toUInt() : 1; // 1 is the default role for apps. - QVariant opaqueVariant = window()->property("opaque"); - uint flags = opaqueVariant.isValid() ? - opaqueVariant.toUInt() ? static_cast(IS_OPAQUE_FLAG) : 0 : 0; + mVisible = visible; - // FIXME(loicm) Opaque flag is forced for now for non-system sessions (applications) for - // performance reasons. - flags |= static_cast(IS_OPAQUE_FLAG); + if (mVisible) + updateSurface(); + + // TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized. + // Will have to change qtmir and unity8 for that. + const auto newState = visible ? qtWindowStateToMirSurfaceState(mWindowState) : mir_surface_state_minimized; + mir_wait_for(mir_surface_set_state(mMirSurface, newState)); +} + +void QMirClientSurface::updateTitle(const QString& newTitle) +{ + const auto title = newTitle.toUtf8(); + Spec spec{mir_connection_create_spec_for_changes(mConnection)}; + mir_surface_spec_set_name(spec.get(), title.constData()); + mir_surface_apply_spec(mMirSurface, spec.get()); +} - const QByteArray title = (!window()->title().isNull()) ? window()->title().toUtf8() : "Window 1"; // legacy title - const int panelHeight = d->panelHeight(); +void QMirClientSurface::setSizingConstraints(const QSize& minSize, const QSize& maxSize, const QSize& increment) +{ + Spec spec{mir_connection_create_spec_for_changes(mConnection)}; + ::setSizingConstraints(spec.get(), minSize, maxSize, increment); + mir_surface_apply_spec(mMirSurface, spec.get()); +} + +void QMirClientSurface::handleSurfaceResized(int width, int height) +{ + QMutexLocker lock(&mTargetSizeMutex); + + // mir's resize event is mainly a signal that we need to redraw our content. We use the + // width/height as identifiers to figure out if this is the latest surface resize event + // that has posted, discarding any old ones. This avoids issuing too many redraw events. + // see TODO in postEvent as the ideal way we should handle this. + // The actual buffer size may or may have not changed at this point, so let the rendering + // thread drive the window geometry updates. + mNeedsRepaint = mTargetSize.width() == width && mTargetSize.height() == height; +} + +int QMirClientSurface::needsRepaint() const +{ + if (mNeedsRepaint) { + if (mTargetSize != mBufferSize) { + //If the buffer hasn't changed yet, we need at least two redraws, + //once to get the new buffer size and propagate the geometry changes + //and the second to redraw the content at the new size + return 2; + } else { + // The buffer size has already been updated so we only need one redraw + // to render at the new size + return 1; + } + } + return 0; +} +void QMirClientSurface::onSwapBuffersDone() +{ #if !defined(QT_NO_DEBUG) - LOG("panelHeight: '%d'", panelHeight); - LOG("role: '%d'", role); - LOG("flags: '%s'", (flags & static_cast(1)) ? "Opaque" : "NotOpaque"); - LOG("title: '%s'", title.constData()); + static int sFrameNumber = 0; + ++sFrameNumber; #endif - // Get surface geometry. - QRect geometry; - if (d->state == Qt::WindowFullScreen) { - printf("QMirClientWindow - fullscreen geometry\n"); - geometry = screen()->geometry(); - } else if (d->state == Qt::WindowMaximized) { - printf("QMirClientWindow - maximized geometry\n"); - geometry = screen()->availableGeometry(); - /* - * FIXME: Autopilot relies on being able to convert coordinates relative of the window - * into absolute screen coordinates. Mir does not allow this, see bug lp:1346633 - * Until there's a correct way to perform this transformation agreed, this horrible hack - * guesses the transformation heuristically. - * - * Assumption: this method only used on phone devices! - */ - geometry.setY(panelHeight); - } else { - printf("QMirClientWindow - regular geometry\n"); - geometry = this->geometry(); - geometry.setY(panelHeight); - } + EGLint eglSurfaceWidth = -1; + EGLint eglSurfaceHeight = -1; + eglQuerySurface(mEglDisplay, mEglSurface, EGL_WIDTH, &eglSurfaceWidth); + eglQuerySurface(mEglDisplay, mEglSurface, EGL_HEIGHT, &eglSurfaceHeight); - DLOG("[ubuntumirclient QPA] creating surface at (%d, %d) with size (%d, %d) with title '%s'\n", - geometry.x(), geometry.y(), geometry.width(), geometry.height(), title.data()); + const bool validSize = eglSurfaceWidth > 0 && eglSurfaceHeight > 0; - MirSurfaceSpec *spec; - if (role == SCREEN_KEYBOARD_ROLE) - { - spec = mir_connection_create_spec_for_input_method(d->connection, geometry.width(), - geometry.height(), mir_choose_default_pixel_format(d->connection)); - } - else - { - spec = mir_connection_create_spec_for_normal_surface(d->connection, geometry.width(), - geometry.height(), mir_choose_default_pixel_format(d->connection)); - } - mir_surface_spec_set_name(spec, title.data()); + if (validSize && (mBufferSize.width() != eglSurfaceWidth || mBufferSize.height() != eglSurfaceHeight)) { - // Create platform window - mir_wait_for(mir_surface_create(spec, surfaceCreateCallback, this)); - mir_surface_spec_release(spec); + DLOG("[ubuntumirclient QPA] onSwapBuffersDone(window=%p) [%d] - size changed (%d, %d) => (%d, %d)", + mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height(), eglSurfaceWidth, eglSurfaceHeight); - DASSERT(d->surface != NULL); - d->createEGLSurface((EGLNativeWindowType)mir_buffer_stream_get_egl_native_window(mir_surface_get_buffer_stream(d->surface))); + mBufferSize.rwidth() = eglSurfaceWidth; + mBufferSize.rheight() = eglSurfaceHeight; - if (d->state == Qt::WindowFullScreen) { - // TODO: We could set this on creation once surface spec supports it (mps already up) - mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_fullscreen)); + QRect newGeometry = mPlatformWindow->geometry(); + newGeometry.setSize(mBufferSize); + + mPlatformWindow->QPlatformWindow::setGeometry(newGeometry); + QWindowSystemInterface::handleGeometryChange(mWindow, newGeometry); + } else { +#if 0 + DLOG("[ubuntumirclient QPA] onSwapBuffersDone(window=%p) [%d] - buffer size (%d,%d)", + mWindow, sFrameNumber, mBufferSize.width(), mBufferSize.height()); +#endif } +} - // Window manager can give us a final size different from what we asked for - // so let's check what we ended up getting - { - MirSurfaceParameters parameters; - mir_surface_get_parameters(d->surface, ¶meters); +void QMirClientSurface::surfaceEventCallback(MirSurface *surface, const MirEvent *event, void* context) +{ + Q_UNUSED(surface); + Q_ASSERT(context != nullptr); - geometry.setWidth(parameters.width); - geometry.setHeight(parameters.height); - } + auto s = static_cast(context); + s->postEvent(event); +} - DLOG("[ubuntumirclient QPA] created surface has size (%d, %d)", - geometry.width(), geometry.height()); +void QMirClientSurface::postEvent(const MirEvent *event) +{ + if (mir_event_type_resize == mir_event_get_type(event)) { + // TODO: The current event queue just accumulates all resize events; + // It would be nicer if we could update just one event if that event has not been dispatched. + // As a workaround, we use the width/height as an identifier of this latest event + // so the event handler (handleSurfaceResized) can discard/ignore old ones. + const auto resizeEvent = mir_event_get_resize_event(event); + const auto width = mir_resize_event_get_width(resizeEvent); + const auto height = mir_resize_event_get_height(resizeEvent); + DLOG("[ubuntumirclient QPA] resizeEvent(window=%p, width=%d, height=%d)", mWindow, width, height); + + QMutexLocker lock(&mTargetSizeMutex); + mTargetSize.rwidth() = width; + mTargetSize.rheight() = height; + } - // Assume that the buffer size matches the surface size at creation time - d->bufferSize = geometry.size(); + mInput->postEvent(mPlatformWindow, event); +} - // Tell Qt about the geometry. - QWindowSystemInterface::handleGeometryChange(window(), geometry); - QPlatformWindow::setGeometry(geometry); +void QMirClientSurface::updateSurface() +{ + DLOG("[ubuntumirclient QPA] updateSurface(window=%p)", mWindow); + + if (!mParented && mWindow->type() == Qt::Dialog) { + // The dialog may have been parented after creation time + // so morph it into a modal dialog + auto parent = transientParentFor(mWindow); + if (parent) { + DLOG("[ubuntumirclient QPA] updateSurface(window=%p) dialog now parented", mWindow); + mParented = true; + Spec spec{mir_connection_create_spec_for_changes(mConnection)}; + mir_surface_spec_set_parent(spec.get(), parent->mirSurface()); + mir_surface_apply_spec(mMirSurface, spec.get()); + } + } } -void QMirClientWindow::moveResize(const QRect& rect) +QMirClientWindow::QMirClientWindow(QWindow *w, const QSharedPointer &clipboard, QMirClientScreen *screen, + QMirClientInput *input, MirConnection *connection) + : QObject(nullptr) + , QPlatformWindow(w) + , mId(makeId()) + , mClipboard(clipboard) + , mSurface(new QMirClientSurface{this, screen, input, connection}) { - (void) rect; - // TODO: Not yet supported by mir. + DLOG("[ubuntumirclient QPA] QMirClientWindow(window=%p, screen=%p, input=%p, surf=%p)", w, screen, input, mSurface.get()); } -void QMirClientWindow::handleSurfaceResize(int width, int height) +QMirClientWindow::~QMirClientWindow() { - QMutexLocker(&d->mutex); - LOG("QMirClientWindow::handleSurfaceResize(width=%d, height=%d)", width, height); + DLOG("[ubuntumirclient QPA] ~QMirClientWindow(window=%p)", this); +} - // The current buffer size hasn't actually changed. so just render on it and swap - // buffers in the hope that the next buffer will match the surface size advertised - // in this event. - // But since this event is processed by a thread different from the one that swaps - // buffers, you can never know if this information is already outdated as there's - // no synchronicity whatsoever between the processing of resize events and the - // consumption of buffers. - if (d->bufferSize.width() != width || d->bufferSize.height() != height) { - QWindowSystemInterface::handleExposeEvent(window(), geometry()); - QWindowSystemInterface::flushWindowSystemEvents(); +void QMirClientWindow::handleSurfaceResized(int width, int height) +{ + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p, width=%d, height=%d)", window(), width, height); + + mSurface->handleSurfaceResized(width, height); + + // This resize event could have occurred just after the last buffer swap for this window. + // This means the client may still be holding a buffer with the older size. The first redraw call + // will then render at the old size. After swapping the client now will get a new buffer with the + // updated size but it still needs re-rendering so another redraw may be needed. + // A mir API to drop the currently held buffer would help here, so that we wouldn't have to redraw twice + auto const numRepaints = mSurface->needsRepaint(); + DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p) redraw %d times", window(), numRepaints); + for (int i = 0; i < numRepaints; i++) { + DLOG("[ubuntumirclient QPA] handleSurfaceResize(window=%p) repainting width=%d, height=%d", window(), geometry().size().width(), geometry().size().height()); + QWindowSystemInterface::handleExposeEvent(window(), QRect(QPoint(), geometry().size())); } } -void QMirClientWindow::handleSurfaceFocusChange(bool focused) +void QMirClientWindow::handleSurfaceFocused() { - LOG("QMirClientWindow::handleSurfaceFocusChange(focused=%s)", focused ? "true" : "false"); - QWindow *activatedWindow = focused ? window() : nullptr; + DLOG("[ubuntumirclient QPA] handleSurfaceFocused(window=%p)", window()); - // System clipboard contents might have changed while this window was unfocused and wihtout + // System clipboard contents might have changed while this window was unfocused and without // this process getting notified about it because it might have been suspended (due to // application lifecycle policies), thus unable to listen to any changes notified through // D-Bus. // Therefore let's ensure we are up to date with the system clipboard now that we are getting // focused again. - if (focused) { - d->clipboard->requestDBusClipboardContents(); - } - - QWindowSystemInterface::handleWindowActivated(activatedWindow, Qt::ActiveWindowFocusReason); + mClipboard->requestDBusClipboardContents(); } void QMirClientWindow::setWindowState(Qt::WindowState state) { - QMutexLocker(&d->mutex); - DLOG("QMirClientWindow::setWindowState (this=%p, %s)", this, qtWindowStateToStr(state)); + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] setWindowState(window=%p, %s)", this, qtWindowStateToStr(state)); + mSurface->setState(state); - if (state == d->state) - return; + updatePanelHeightHack(state); +} - // TODO: Perhaps we should check if the states are applied? - mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(state))); - d->state = state; +/* + FIXME: Mir does not let clients know the position of their windows in the virtual + desktop space. So we have this ugly hack that assumes a phone situation where the + window is always on the top-left corner, right below the indicators panel if not + in fullscreen. + */ +void QMirClientWindow::updatePanelHeightHack(Qt::WindowState state) +{ + if (state == Qt::WindowFullScreen && geometry().y() != 0) { + QRect newGeometry = geometry(); + newGeometry.setY(0); + QPlatformWindow::setGeometry(newGeometry); + QWindowSystemInterface::handleGeometryChange(window(), newGeometry); + } else if (geometry().y() == 0) { + QRect newGeometry = geometry(); + newGeometry.setY(panelHeight()); + QPlatformWindow::setGeometry(newGeometry); + QWindowSystemInterface::handleGeometryChange(window(), newGeometry); + } } void QMirClientWindow::setGeometry(const QRect& rect) { - DLOG("QMirClientWindow::setGeometry (this=%p)", this); + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] setGeometry (window=%p, x=%d, y=%d, width=%d, height=%d)", + window(), rect.x(), rect.y(), rect.width(), rect.height()); - bool doMoveResize; + //NOTE: mir surfaces cannot be moved by the client so ignore the topLeft coordinates + const auto newSize = rect.size(); + auto newGeometry = geometry(); + newGeometry.setSize(newSize); + QPlatformWindow::setGeometry(newGeometry); - { - QMutexLocker(&d->mutex); - QPlatformWindow::setGeometry(rect); - doMoveResize = d->state != Qt::WindowFullScreen && d->state != Qt::WindowMaximized; - } - - if (doMoveResize) { - moveResize(rect); - } + mSurface->resize(newSize); } void QMirClientWindow::setVisible(bool visible) { - QMutexLocker(&d->mutex); - DLOG("QMirClientWindow::setVisible (this=%p, visible=%s)", this, visible ? "true" : "false"); + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] setVisible (window=%p, visible=%s)", window(), visible ? "true" : "false"); - if (visible) { - mir_wait_for(mir_surface_set_state(d->surface, qtWindowStateToMirSurfaceState(d->state))); + mSurface->setVisible(visible); + const QRect& exposeRect = visible ? QRect(QPoint(), geometry().size()) : QRect(); - QWindowSystemInterface::handleExposeEvent(window(), QRect()); - QWindowSystemInterface::flushWindowSystemEvents(); - } else { - // TODO: Use the new mir_surface_state_hidden state instead of mir_surface_state_minimized. - // Will have to change qtmir and unity8 for that. - mir_wait_for(mir_surface_set_state(d->surface, mir_surface_state_minimized)); - } + lock.unlock(); + QWindowSystemInterface::handleExposeEvent(window(), exposeRect); + QWindowSystemInterface::flushWindowSystemEvents(); } -void* QMirClientWindow::eglSurface() const +void QMirClientWindow::setWindowTitle(const QString& title) { - return d->eglSurface; + QMutexLocker lock(&mMutex); + DLOG("[ubuntumirclient QPA] setWindowTitle(window=%p) title=%s)", window(), title.toUtf8().constData()); + mSurface->updateTitle(title); } -WId QMirClientWindow::winId() const +void QMirClientWindow::propagateSizeHints() { - return d->id; + QMutexLocker lock(&mMutex); + const auto win = window(); + DLOG("[ubuntumirclient QPA] propagateSizeHints(window=%p) min(%d,%d), max(%d,%d) increment(%d, %d)", + win, win->minimumSize().width(), win->minimumSize().height(), + win->maximumSize().width(), win->maximumSize().height(), + win->sizeIncrement().width(), win->sizeIncrement().height()); + mSurface->setSizingConstraints(win->minimumSize(), win->maximumSize(), win->sizeIncrement()); } -void QMirClientWindow::onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight) +void* QMirClientWindow::eglSurface() const { - QMutexLocker(&d->mutex); - - bool sizeKnown = newBufferWidth > 0 && newBufferHeight > 0; - - if (sizeKnown && (d->bufferSize.width() != newBufferWidth || - d->bufferSize.height() != newBufferHeight)) { - - DLOG("QMirClientWindow::onBuffersSwapped_threadSafe - buffer size changed from (%d,%d) to (%d,%d)", - d->bufferSize.width(), d->bufferSize.height(), newBufferWidth, newBufferHeight); - - d->bufferSize.rwidth() = newBufferWidth; - d->bufferSize.rheight() = newBufferHeight; + return mSurface->eglSurface(); +} - QRect newGeometry; +MirSurface *QMirClientWindow::mirSurface() const +{ + return mSurface->mirSurface(); +} - newGeometry = geometry(); - newGeometry.setWidth(d->bufferSize.width()); - newGeometry.setHeight(d->bufferSize.height()); +WId QMirClientWindow::winId() const +{ + return mId; +} - QPlatformWindow::setGeometry(newGeometry); - QWindowSystemInterface::handleGeometryChange(window(), newGeometry, QRect()); - } +void QMirClientWindow::onSwapBuffersDone() +{ + QMutexLocker lock(&mMutex); + mSurface->onSwapBuffersDone(); } diff --git a/src/plugins/platforms/mirclient/qmirclientwindow.h b/src/plugins/platforms/mirclient/qmirclientwindow.h index f342669544..4ec7879949 100644 --- a/src/plugins/platforms/mirclient/qmirclientwindow.h +++ b/src/plugins/platforms/mirclient/qmirclientwindow.h @@ -40,20 +40,23 @@ #include #include +#include -#include +#include class QMirClientClipboard; class QMirClientInput; class QMirClientScreen; -class QMirClientWindowPrivate; +class QMirClientSurface; +struct MirConnection; +struct MirSurface; class QMirClientWindow : public QObject, public QPlatformWindow { Q_OBJECT public: - QMirClientWindow(QWindow *w, QSharedPointer clipboard, QMirClientScreen *screen, - QMirClientInput *input, MirConnection *mir_connection); + QMirClientWindow(QWindow *w, const QSharedPointer &clipboard, QMirClientScreen *screen, + QMirClientInput *input, MirConnection *mirConnection); virtual ~QMirClientWindow(); // QPlatformWindow methods. @@ -61,20 +64,22 @@ public: void setGeometry(const QRect&) override; void setWindowState(Qt::WindowState state) override; void setVisible(bool visible) override; + void setWindowTitle(const QString &title) override; + void propagateSizeHints() override; // New methods. - void* eglSurface() const; - void handleSurfaceResize(int width, int height); - void handleSurfaceFocusChange(bool focused); - void onBuffersSwapped_threadSafe(int newBufferWidth, int newBufferHeight); - - QMirClientWindowPrivate* priv() { return d; } + void *eglSurface() const; + MirSurface *mirSurface() const; + void handleSurfaceResized(int width, int height); + void handleSurfaceFocused(); + void onSwapBuffersDone(); private: - void createWindow(); - void moveResize(const QRect& rect); - - QMirClientWindowPrivate *d; + void updatePanelHeightHack(Qt::WindowState); + mutable QMutex mMutex; + const WId mId; + const QSharedPointer mClipboard; + std::unique_ptr mSurface; }; #endif // QMIRCLIENTWINDOW_H -- cgit v1.2.3 From 52436965285de2525acd648c6ba5a21d4479c1e4 Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Wed, 13 Jan 2016 14:25:24 +0000 Subject: Haiku: Fix compilation of corelib Change-Id: I8f962ac7ee85af50a573a451f54931d6c0dd67eb Reviewed-by: Augustin Cavalier Reviewed-by: Thiago Macieira --- src/corelib/tools/qsimd.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qsimd.cpp b/src/corelib/tools/qsimd.cpp index 3e4fdfaaf1..f07eb098f2 100644 --- a/src/corelib/tools/qsimd.cpp +++ b/src/corelib/tools/qsimd.cpp @@ -636,7 +636,7 @@ int ffsll(quint64 i) #endif } #endif -#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) +#elif defined(Q_OS_ANDROID) || defined(Q_OS_QNX) || defined(Q_OS_OSX) || defined(Q_OS_HAIKU) # define ffsll __builtin_ffsll #endif -- cgit v1.2.3 From 294111e25a4e3639a83a87f70ed33ac0b3985f33 Mon Sep 17 00:00:00 2001 From: Alex Trotsenko Date: Sat, 28 Nov 2015 15:27:43 +0200 Subject: QHttpSocketEngine: ensure pending EOF triggers a notification When the remote peer closed the connection, a read notification needs to always be emitted, otherwise the higher layer does not get the disconnected signal. From the other side, underlying QAbstractSocket object could temporarily disable notifications from the engine at any time. To avoid possible blocking of the socket, take a pending EOF into account when the read notifications are re-enabled. Change-Id: Iac9d4e2f790530be3500baf5a2000f1f63df5cc2 Reviewed-by: Ulf Hermann --- src/network/socket/qhttpsocketengine.cpp | 5 ++- .../qhttpsocketengine/tst_qhttpsocketengine.cpp | 47 ++++++++++++++++++++++ 2 files changed, 51 insertions(+), 1 deletion(-) diff --git a/src/network/socket/qhttpsocketengine.cpp b/src/network/socket/qhttpsocketengine.cpp index 92ca76b560..a744688f29 100644 --- a/src/network/socket/qhttpsocketengine.cpp +++ b/src/network/socket/qhttpsocketengine.cpp @@ -439,8 +439,11 @@ void QHttpSocketEngine::setReadNotificationEnabled(bool enable) d->readNotificationEnabled = enable; if (enable) { // Enabling read notification can trigger a notification. - if (bytesAvailable()) + if (bytesAvailable()) { slotSocketReadNotification(); + } else if (d->socket && d->socket->state() == QAbstractSocket::UnconnectedState) { + emitReadNotification(); + } } } diff --git a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp index 179cdb76bc..f6662b6712 100644 --- a/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp +++ b/tests/auto/network/socket/qhttpsocketengine/tst_qhttpsocketengine.cpp @@ -72,6 +72,7 @@ private slots: void downloadBigFile(); // void tcpLoopbackPerformance(); void passwordAuth(); + void ensureEofTriggersNotification(); protected slots: void tcpSocketNonBlocking_hostFound(); @@ -739,5 +740,51 @@ void tst_QHttpSocketEngine::passwordAuth() //---------------------------------------------------------------------------------- +void tst_QHttpSocketEngine::ensureEofTriggersNotification() +{ + QList serverData; + // Set the handshake and server response data + serverData << "HTTP/1.0 200 Connection established\r\n\r\n" << "0"; + MiniHttpServer server(serverData); + + QTcpSocket socket; + connect(&socket, SIGNAL(connected()), SLOT(exitLoopSlot())); + socket.setProxy(QNetworkProxy(QNetworkProxy::HttpProxy, server.serverAddress().toString(), + server.serverPort())); + socket.connectToHost("0.1.2.3", 12345); + + QTestEventLoop::instance().enterLoop(5); + if (QTestEventLoop::instance().timeout()) + QFAIL("Connect timed out"); + + QCOMPARE(socket.state(), QTcpSocket::ConnectedState); + // Disable read notification on server response + socket.setReadBufferSize(1); + socket.putChar(0); + + // Wait for the response + connect(&socket, SIGNAL(readyRead()), SLOT(exitLoopSlot())); + QTestEventLoop::instance().enterLoop(5); + if (QTestEventLoop::instance().timeout()) + QFAIL("Read timed out"); + + QCOMPARE(socket.state(), QTcpSocket::ConnectedState); + QCOMPARE(socket.bytesAvailable(), 1); + // Trigger a read notification + socket.readAll(); + // Check for pending EOF at input + QCOMPARE(socket.bytesAvailable(), 0); + QCOMPARE(socket.state(), QTcpSocket::ConnectedState); + + // Try to read EOF + connect(&socket, SIGNAL(disconnected()), SLOT(exitLoopSlot())); + QTestEventLoop::instance().enterLoop(5); + if (QTestEventLoop::instance().timeout()) + QFAIL("Disconnect timed out"); + + // Check that it's closed + QCOMPARE(socket.state(), QTcpSocket::UnconnectedState); +} + QTEST_MAIN(tst_QHttpSocketEngine) #include "tst_qhttpsocketengine.moc" -- cgit v1.2.3 From bc81a28554a256563e7df8860d17f10a63e45a2b Mon Sep 17 00:00:00 2001 From: Frederik Gladhorn Date: Fri, 8 Jan 2016 16:22:12 +0100 Subject: Passing parameters to convertLineOffset by pointer instead of reference MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is aligned with our coding style and it should have been this way from the start. Change-Id: I23a00eb220dd9f17d9239c811b556885a2c0186a Reviewed-by: Fredrik de Vibe Reviewed-by: Jan Arve Sæther --- .../platforms/cocoa/qcocoaaccessibilityelement.mm | 24 +++++++++++----------- 1 file changed, 12 insertions(+), 12 deletions(-) diff --git a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm index b55393c7dc..608a7583c0 100644 --- a/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm +++ b/src/plugins/platforms/cocoa/qcocoaaccessibilityelement.mm @@ -44,11 +44,11 @@ QT_USE_NAMESPACE #ifndef QT_NO_ACCESSIBILITY -static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &offset, NSUInteger *start = 0, NSUInteger *end = 0) +static void convertLineOffset(QAccessibleTextInterface *text, int *line, int *offset, NSUInteger *start = 0, NSUInteger *end = 0) { - Q_ASSERT(line == -1 || offset == -1); - Q_ASSERT(line != -1 || offset != -1); - Q_ASSERT(offset <= text->characterCount()); + Q_ASSERT(*line == -1 || *offset == -1); + Q_ASSERT(*line != -1 || *offset != -1); + Q_ASSERT(*offset <= text->characterCount()); int curLine = -1; int curStart = 0, curEnd = 0; @@ -75,14 +75,14 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of if (nextEnd == curEnd) ++curEnd; } - } while ((line == -1 || curLine < line) && (offset == -1 || (curEnd <= offset)) && curEnd <= text->characterCount()); + } while ((*line == -1 || curLine < *line) && (*offset == -1 || (curEnd <= *offset)) && curEnd <= text->characterCount()); curEnd = qMin(curEnd, text->characterCount()); - if (line == -1) - line = curLine; - if (offset == -1) - offset = curStart; + if (*line == -1) + *line = curLine; + if (*offset == -1) + *offset = curStart; Q_ASSERT(curStart >= 0); Q_ASSERT(curEnd >= 0); @@ -338,7 +338,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of if (QAccessibleTextInterface *text = iface->textInterface()) { int line = -1; int position = text->cursorPosition(); - convertLineOffset(text, line, position); + convertLineOffset(text, &line, &position); return [NSNumber numberWithInt: line]; } return nil; @@ -397,7 +397,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of if (index < 0 || index > iface->textInterface()->characterCount()) return nil; int line = -1; - convertLineOffset(iface->textInterface(), line, index); + convertLineOffset(iface->textInterface(), &line, &index); return [NSNumber numberWithInt:line]; } if ([attribute isEqualToString: NSAccessibilityRangeForLineParameterizedAttribute]) { @@ -407,7 +407,7 @@ static void convertLineOffset(QAccessibleTextInterface *text, int &line, int &of int lineOffset = -1; NSUInteger startOffset = 0; NSUInteger endOffset = 0; - convertLineOffset(iface->textInterface(), line, lineOffset, &startOffset, &endOffset); + convertLineOffset(iface->textInterface(), &line, &lineOffset, &startOffset, &endOffset); return [NSValue valueWithRange:NSMakeRange(startOffset, endOffset - startOffset)]; } if ([attribute isEqualToString: NSAccessibilityBoundsForRangeParameterizedAttribute]) { -- cgit v1.2.3 From fd6cf5c875d794d23e513c8e7d6ebabc91dae790 Mon Sep 17 00:00:00 2001 From: Laszlo Agocs Date: Sat, 16 Jan 2016 19:59:23 +0100 Subject: Avoid checking the fb status in every bind On some drivers (e.g. NVIDIA, tested on Windows) the status check is apparently expensive. A simple FBO test app rendering into the FBO on every frame (and thus calling bind()) shows a 19-21% CPU usage. With the patch this gets reduced to 0.8-1%. The check is fairly useless too - whenever creating attachments, the status is checked, so d->valid is up-to-date. Task-number: QTBUG-50496 Change-Id: Ie9f0db34e5c2bc1a1141c734ca0b318419013c0d Reviewed-by: Allan Sandfeld Jensen --- src/gui/opengl/qopenglframebufferobject.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/gui/opengl/qopenglframebufferobject.cpp b/src/gui/opengl/qopenglframebufferobject.cpp index e0ef7c52a5..5184283a31 100644 --- a/src/gui/opengl/qopenglframebufferobject.cpp +++ b/src/gui/opengl/qopenglframebufferobject.cpp @@ -1077,8 +1077,6 @@ bool QOpenGLFramebufferObject::bind() } } - d->valid = d->checkFramebufferStatus(current); - return d->valid; } -- cgit v1.2.3 From 50073521649e3818d87920751ab95acd2c2dfd15 Mon Sep 17 00:00:00 2001 From: Giuseppe D'Angelo Date: Mon, 18 Jan 2016 12:38:36 +0100 Subject: QOrderedMutexLocker: use std::less to prevent undefined behavior operator< between pointers is undefined unless the two pointers point in the same array, which is not what QOrderedMutexLocker does. Change-Id: Ia6594900cfa807a73f20e157ce896b4321a3d746 Reviewed-by: Marc Mutz --- src/corelib/thread/qorderedmutexlocker_p.h | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/corelib/thread/qorderedmutexlocker_p.h b/src/corelib/thread/qorderedmutexlocker_p.h index c73a790820..54887342e7 100644 --- a/src/corelib/thread/qorderedmutexlocker_p.h +++ b/src/corelib/thread/qorderedmutexlocker_p.h @@ -47,6 +47,8 @@ #include +#include + QT_BEGIN_NAMESPACE /* @@ -57,8 +59,8 @@ class QOrderedMutexLocker { public: QOrderedMutexLocker(QMutex *m1, QMutex *m2) - : mtx1((m1 == m2) ? m1 : (m1 < m2 ? m1 : m2)), - mtx2((m1 == m2) ? 0 : (m1 < m2 ? m2 : m1)), + : mtx1((m1 == m2) ? m1 : (std::less()(m1, m2) ? m1 : m2)), + mtx2((m1 == m2) ? 0 : (std::less()(m1, m2) ? m2 : m1)), locked(false) { relock(); -- cgit v1.2.3 From f634ce3b9a38b163a6ef4d57d6bd61745d5248c9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morten=20Johan=20S=C3=B8rvig?= Date: Fri, 15 Jan 2016 15:17:54 +0100 Subject: QFocusFrame: Don't crash on null d->widget. This can happen with a suitably complex use case (See QTBUG-50263) Change-Id: Ie8fa7b5872a902e802fda5795ade3369399ddb54 Task-number: QTBUG-50263 Reviewed-by: Timur Pocheptsov --- src/widgets/widgets/qfocusframe.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/widgets/widgets/qfocusframe.cpp b/src/widgets/widgets/qfocusframe.cpp index 5a403fa669..bf8cb30ef7 100644 --- a/src/widgets/widgets/qfocusframe.cpp +++ b/src/widgets/widgets/qfocusframe.cpp @@ -250,6 +250,10 @@ void QFocusFrame::paintEvent(QPaintEvent *) { Q_D(QFocusFrame); + + if (!d->widget) + return; + QStylePainter p(this); QStyleOption option; initStyleOption(&option); -- cgit v1.2.3 From 99e25dd7d8bfcb184852110c5f882b89cfb889df Mon Sep 17 00:00:00 2001 From: Stephen Kelly Date: Mon, 18 Jan 2016 10:55:49 +0100 Subject: CMake: Don't attempt gui-tests if Qt is built with -no-gui Change-Id: I5f327fa1b0c7827535a4b00ca7d0d4281b1eec7b Reviewed-by: Simon Hausmann --- mkspecs/features/ctest_testcase_common.prf | 1 + tests/auto/cmake/CMakeLists.txt | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/mkspecs/features/ctest_testcase_common.prf b/mkspecs/features/ctest_testcase_common.prf index bdf40541ec..7183ade4df 100644 --- a/mkspecs/features/ctest_testcase_common.prf +++ b/mkspecs/features/ctest_testcase_common.prf @@ -56,6 +56,7 @@ mingw:isEmpty(CROSS_COMPILE):CMAKE_GENERATOR = -G \"MinGW Makefiles\" BUILD_DIR = $$replace($$list($$OUT_PWD/build), /, $$QMAKE_DIR_SEP) +!qtHaveModule(gui): CMAKE_MODULE_DEFINES += -DNO_GUI=True !qtHaveModule(widgets): CMAKE_MODULE_DEFINES += -DNO_WIDGETS=True !qtHaveModule(dbus): CMAKE_MODULE_DEFINES += -DNO_DBUS=True diff --git a/tests/auto/cmake/CMakeLists.txt b/tests/auto/cmake/CMakeLists.txt index 3a607983f9..5248f75a84 100644 --- a/tests/auto/cmake/CMakeLists.txt +++ b/tests/auto/cmake/CMakeLists.txt @@ -50,7 +50,9 @@ include("${_Qt5CTestMacros}") if(NOT ${CMAKE_VERSION} VERSION_LESS 2.8.9) # Requires INCLUDE_DIRECTORIES target property in CMake 2.8.8 # and POSITION_INDEPENDENT_CODE target property in 2.8.9 - expect_pass(test_use_modules_function) + if (NOT NO_GUI) + expect_pass(test_use_modules_function) + endif() expect_pass(test_umbrella_config) else() message("CMake version older than 2.8.9 (Found ${CMAKE_VERSION}). Not running test \"test_use_modules_function\" or \"test_umbrella_config\"") -- cgit v1.2.3 From e8ad49d6cba6521f20b1b08bf65d92fc81c158e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Sat, 16 Jan 2016 00:57:54 +0100 Subject: xcb: Fallback to Xlib screen when glXGetCurrentDisplay() returns NULL Change-Id: Ie25b3fac4c0224f847c77c0515894a9df84077a2 Reviewed-by: Laszlo Agocs --- .../platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp | 9 ++++++--- .../platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp | 8 +++++--- 2 files changed, 11 insertions(+), 6 deletions(-) diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp index 3412f3f3fc..22e68e3db7 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qglxintegration.cpp @@ -645,9 +645,12 @@ void QGLXContext::queryDummyContext() QScopedPointer surface; Display *display = glXGetCurrentDisplay(); - const char *glxvendor = 0; - if (display) - glxvendor = glXGetClientString(display, GLX_VENDOR); + if (!display) { + // FIXME: Since Qt 5.6 we don't need to check whether primary screen is NULL + if (QScreen *screen = QGuiApplication::primaryScreen()) + display = DISPLAY_FROM_XCB(static_cast(screen->handle())); + } + const char *glxvendor = glXGetClientString(display, GLX_VENDOR); if (glxvendor && !strcmp(glxvendor, "ATI")) { QWindow *window = new QWindow; window->resize(64, 64); diff --git a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp index cd4949af5c..a3a8aa259b 100644 --- a/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp +++ b/src/plugins/platforms/xcb/gl_integrations/xcb_glx/qxcbglxintegration.cpp @@ -196,9 +196,11 @@ QPlatformOffscreenSurface *QXcbGlxIntegration::createPlatformOffscreenSurface(QO if (!vendorChecked) { vendorChecked = true; Display *display = glXGetCurrentDisplay(); - const char *glxvendor = 0; - if (display) - glxvendor = glXGetClientString(display, GLX_VENDOR); +#ifdef XCB_USE_XLIB + if (!display) + display = static_cast(m_connection->xlib_display()); +#endif + const char *glxvendor = glXGetClientString(display, GLX_VENDOR); if (glxvendor && !strcmp(glxvendor, "ATI")) glxPbufferUsable = false; } -- cgit v1.2.3 From 9eba208445ad3c6f8efeadc1e6c8befad4478d8f Mon Sep 17 00:00:00 2001 From: Alexander Volkov Date: Mon, 18 Jan 2016 17:30:49 +0300 Subject: Center QPrintPropertiesDialog on top of its parent Remove QPrintPropertiesDialog::showEvent(). It just accepts QShowEvent, it makes no sense. At the same time this method overrides QDialog::showEvent(), which centers dialogs. Change-Id: I11510feb4a946f347c19d6ac59874b4cb931020e Reviewed-by: Friedemann Kleint --- src/printsupport/dialogs/qprintdialog_unix.cpp | 8 -------- 1 file changed, 8 deletions(-) diff --git a/src/printsupport/dialogs/qprintdialog_unix.cpp b/src/printsupport/dialogs/qprintdialog_unix.cpp index 9633032a0f..b96d8dfd22 100644 --- a/src/printsupport/dialogs/qprintdialog_unix.cpp +++ b/src/printsupport/dialogs/qprintdialog_unix.cpp @@ -118,9 +118,6 @@ public: void applyPrinterProperties(QPrinter *p); void setupPrinter() const; -protected: - void showEvent(QShowEvent* event) Q_DECL_OVERRIDE; - private: friend class QUnixPrintWidgetPrivate; Ui::QPrintPropertiesWidget widget; @@ -274,11 +271,6 @@ void QPrintPropertiesDialog::selectPrinter(QPrinter::OutputFormat outputFormat, widget.pageSetup->selectPrinter(outputFormat, printerName); } -void QPrintPropertiesDialog::showEvent(QShowEvent* event) -{ - event->accept(); -} - //////////////////////////////////////////////////////////////////////////////// //////////////////////////////////////////////////////////////////////////////// -- cgit v1.2.3 From c60e06e087e3c7919ba7adb26f9cf44007238061 Mon Sep 17 00:00:00 2001 From: Joerg Bornemann Date: Fri, 15 Jan 2016 10:43:37 +0100 Subject: Support precompiled header files without file extension in VS projects Having a precompiled header file without file extension (or without common file extension) led to an incorrectly generated Visual Studio project file. The custom build step for automatically generating the corresponding source file was missing. Remove the file extension check that apparently was yet another feeble attempt of runtime optimization. Task-number: QTBUG-50442 Change-Id: I0552f94be12cbb70e2f32c242c7364699979bd81 Reviewed-by: Karsten Heimrich Reviewed-by: Oswald Buddenhagen --- qmake/generators/win32/msvc_objectmodel.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/qmake/generators/win32/msvc_objectmodel.cpp b/qmake/generators/win32/msvc_objectmodel.cpp index 18457ac5ad..f26dbbc40b 100644 --- a/qmake/generators/win32/msvc_objectmodel.cpp +++ b/qmake/generators/win32/msvc_objectmodel.cpp @@ -2196,7 +2196,7 @@ void VCFilter::modifyPCHstage(QString str) break; } } - bool isHFile = Option::hasFileExtension(str, Option::h_ext) && (str == Project->precompH); + const bool isHFile = (str == Project->precompH); bool isCPPFile = pchThroughSourceFile && (str == Project->precompCPP); if(!isCFile && !isHFile && !isCPPFile) -- cgit v1.2.3 From a87dfdb19683cd106aa81d4053c255251a5e37a0 Mon Sep 17 00:00:00 2001 From: Tobias Koenig Date: Tue, 14 Jul 2015 12:44:17 +0200 Subject: WinCE: Build accessibility support on WinCE7 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Build the QPlatformAccessibility support on WinCE7, so that QtQuickControls, which depend on the availability of QPlatformAccessibility, can be used on WinCE7 as well. Change-Id: Ice7370b891a2963483bbfe1af8b219717541e64b Reviewed-by: Björn Breitmeyer Reviewed-by: Jan Arve Sæther Reviewed-by: Frederik Gladhorn --- .../platforms/windows/accessible/accessible.pri | 17 ++++++----- .../windows/accessible/qwindowsaccessibility.cpp | 34 +++++++++++++++------- 2 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/plugins/platforms/windows/accessible/accessible.pri b/src/plugins/platforms/windows/accessible/accessible.pri index e26c6614e2..0774d907f2 100644 --- a/src/plugins/platforms/windows/accessible/accessible.pri +++ b/src/plugins/platforms/windows/accessible/accessible.pri @@ -1,17 +1,20 @@ SOURCES += \ - $$PWD/qwindowsmsaaaccessible.cpp \ $$PWD/qwindowsaccessibility.cpp \ $$PWD/comutils.cpp HEADERS += \ - $$PWD/qwindowsmsaaaccessible.h \ $$PWD/qwindowsaccessibility.h \ $$PWD/comutils.h -!mingw: { - SOURCES += $$PWD/iaccessible2.cpp - HEADERS += $$PWD/iaccessible2.h - include(../../../../3rdparty/iaccessible2/iaccessible2.pri) +!wince: { + SOURCES += $$PWD/qwindowsmsaaaccessible.cpp + HEADERS += $$PWD/qwindowsmsaaaccessible.h + + !mingw: { + SOURCES += $$PWD/iaccessible2.cpp + HEADERS += $$PWD/iaccessible2.h + include(../../../../3rdparty/iaccessible2/iaccessible2.pri) + } } -mingw: LIBS *= -luuid \ No newline at end of file +mingw: LIBS *= -luuid diff --git a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp index 7015424f47..0437290dcb 100644 --- a/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp +++ b/src/plugins/platforms/windows/accessible/qwindowsaccessibility.cpp @@ -50,10 +50,12 @@ #include #include "qwindowsaccessibility.h" -#ifdef Q_CC_MINGW -# include "qwindowsmsaaaccessible.h" -#else -# include "iaccessible2.h" +#if !defined(Q_OS_WINCE) +# ifdef Q_CC_MINGW +# include "qwindowsmsaaaccessible.h" +# else +# include "iaccessible2.h" +# endif #endif #include "comutils.h" @@ -68,8 +70,9 @@ #if !defined(WINABLEAPI) # if defined(Q_OS_WINCE) # include +# else +# include # endif -# include #endif #include @@ -193,6 +196,11 @@ QWindow *QWindowsAccessibility::windowHelper(const QAccessibleInterface *iface) */ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) { +#if defined(Q_OS_WINCE) + Q_UNUSED(acc); + + return 0; +#else if (!acc) return 0; @@ -200,14 +208,15 @@ IAccessible *QWindowsAccessibility::wrap(QAccessibleInterface *acc) if (!QAccessible::uniqueId(acc)) QAccessible::registerAccessibleInterface(acc); -#ifdef Q_CC_MINGW +# ifdef Q_CC_MINGW QWindowsMsaaAccessible *wacc = new QWindowsMsaaAccessible(acc); -#else +# else QWindowsIA2Accessible *wacc = new QWindowsIA2Accessible(acc); -#endif +# endif IAccessible *iacc = 0; wacc->QueryInterface(IID_IAccessible, (void**)&iacc); return iacc; +#endif // defined(Q_OS_WINCE) } /* @@ -230,6 +239,7 @@ void QWindowsAccessibility::cleanup() bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, WPARAM wParam, LPARAM lParam, LRESULT *lResult) { +#if !defined(Q_OS_WINCE) if (static_cast(lParam) == static_cast(UiaRootObjectId)) { /* For UI Automation */ } else if ((DWORD)lParam == DWORD(OBJID_CLIENT)) { @@ -248,9 +258,7 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W if (!oleaccChecked) { oleaccChecked = true; -#if !defined(Q_OS_WINCE) ptrLresultFromObject = (PtrLresultFromObject)QSystemLibrary::resolve(QLatin1String("oleacc"), "LresultFromObject"); -#endif } if (ptrLresultFromObject) { @@ -269,6 +277,12 @@ bool QWindowsAccessibility::handleAccessibleObjectFromWindowRequest(HWND hwnd, W } } } +#else + Q_UNUSED(hwnd); + Q_UNUSED(wParam); + Q_UNUSED(lParam); + Q_UNUSED(lResult); +#endif // !defined(Q_OS_WINCE) return false; } -- cgit v1.2.3 From 465e93aa95d99f799300867b07f81bdd5162c9f1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?B=C5=82a=C5=BCej=20Szczygie=C5=82?= Date: Mon, 11 Jan 2016 15:25:12 +0100 Subject: QtWidgets: Improve native and top-level OpenGL widget performance Since 7c6625b105511191f739d07dc658094ff6f682ac native OpenGL widgets are able to render, but performance is very low. It also slows down rendering for top-level OpenGL widgets. Render-to-texture widgets prevent triggering unnecessary backingstore painting when only the OpenGL content changes. This patch makes possible to use that feature for native and top-level widgets by calling "markDirtyOnScreen()" function only when necessary. This patch also prevents native and top-level OpenGL widgets from flickering during resizing. Task-number: QTBUG-50381 Task-number: QTBUG-49620 Change-Id: I0c16ea644fb869a00772fd74e1709611e627bff3 Reviewed-by: Laszlo Agocs --- src/widgets/kernel/qwidgetbackingstore.cpp | 26 +++++++++++++++----------- 1 file changed, 15 insertions(+), 11 deletions(-) diff --git a/src/widgets/kernel/qwidgetbackingstore.cpp b/src/widgets/kernel/qwidgetbackingstore.cpp index 3f7f9291b6..d9d1c887c1 100644 --- a/src/widgets/kernel/qwidgetbackingstore.cpp +++ b/src/widgets/kernel/qwidgetbackingstore.cpp @@ -1079,7 +1079,8 @@ void QWidgetBackingStore::sync(QWidget *exposedWidget, const QRegion &exposedReg // Nothing to repaint. if (!isDirty() && store->size().isValid()) { - qt_flush(exposedWidget, exposedRegion, store, tlw, tlwOffset, widgetTexturesFor(tlw, tlw), this); + QPlatformTextureList *tl = widgetTexturesFor(tlw, exposedWidget); + qt_flush(exposedWidget, tl ? QRegion() : exposedRegion, store, tlw, tlwOffset, tl, this); return; } @@ -1250,9 +1251,17 @@ void QWidgetBackingStore::doSync() for (int i = 0; i < paintPending.count(); ++i) { QWidget *w = paintPending[i]; w->d_func()->sendPaintEvent(w->rect()); - QWidget *npw = w->nativeParentWidget(); - if (w->internalWinId() || (npw && npw != tlw)) - markDirtyOnScreen(w->rect(), w, w->mapTo(tlw, QPoint())); + if (w != tlw) { + QWidget *npw = w->nativeParentWidget(); + if (w->internalWinId() || (npw && npw != tlw)) { + if (!w->internalWinId()) + w = npw; + QWidgetPrivate *wPrivate = w->d_func(); + if (!wPrivate->needsFlush) + wPrivate->needsFlush = new QRegion; + appendDirtyOnScreenWidget(w); + } + } } // We might have newly exposed areas on the screen if this function was @@ -1277,13 +1286,8 @@ void QWidgetBackingStore::doSync() } } } - for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) { - QWidget *w = dirtyRenderToTextureWidgets.at(i); - resetWidget(w); - QWidget *npw = w->nativeParentWidget(); - if (w->internalWinId() || (npw && npw != tlw)) - markDirtyOnScreen(w->rect(), w, w->mapTo(tlw, QPoint())); - } + for (int i = 0; i < dirtyRenderToTextureWidgets.count(); ++i) + resetWidget(dirtyRenderToTextureWidgets.at(i)); dirtyRenderToTextureWidgets.clear(); #endif -- cgit v1.2.3 From 30bff91c3920fdf92d81d42983e31e8d0766969f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tor=20Arne=20Vestb=C3=B8?= Date: Fri, 15 Jan 2016 14:15:51 +0100 Subject: OS X: Ensure system tray icon is prepared even when menu bar is hidden On OS X 10.11 (El Capitan) the system menu bar can be automatically hidden, in which case the menu bar height is reported to be 0 when using the menuBarHeight API. This resulted in failing to prepare an image for the system tray icon item, making the tray item "invisible". Instead we now use the [[NSStatusBar systemStatusBar] thickness] API, which returns the correct height regardless of the menu bar being hidden or not. Task-number: QTBUG-48960 Change-Id: I208fb8df13754964a6f254cadfbff06dd56c6bab Reviewed-by: Markus Goetz (Woboq GmbH) Reviewed-by: Jake Petroules --- src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm index a3ffb5be66..8152c57ffd 100644 --- a/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm +++ b/src/plugins/platforms/cocoa/qcocoasystemtrayicon.mm @@ -198,7 +198,7 @@ void QCocoaSystemTrayIcon::updateIcon(const QIcon &icon) // current OS X versions is 22 points. Provide some future-proofing // by deriving the icon height from the menu height. const int padding = 4; - const int menuHeight = [[[NSApplication sharedApplication] mainMenu] menuBarHeight]; + const int menuHeight = [[NSStatusBar systemStatusBar] thickness]; const int maxImageHeight = menuHeight - padding; // Select pixmap based on the device pixel height. Ideally we would use -- cgit v1.2.3 From b9bd83c9c2992a156583f5e211eed9adb7f23d6b Mon Sep 17 00:00:00 2001 From: Eskil Abrahamsen Blomfeldt Date: Mon, 18 Jan 2016 15:04:06 +0100 Subject: Fix transformed text with DirectWrite engine This is a port of f54c5d9133d7aa7636988db36fa6cc51d26434b6 from Qt 4.8 which was lost in the transition to Qt 5. It makes sure we use the correct bounding box for the transformed glyph by getting from DirectWrite itself. [ChangeLog][Windows] Fixed transformed text when using the DirectWrite font engine. Task-number: QTBUG-50009 Change-Id: I416ab64253165b878af6b9837348134fede8092e Reviewed-by: Friedemann Kleint Reviewed-by: Lars Knoll Reviewed-by: Simon Hausmann --- .../windows/qwindowsfontenginedirectwrite.cpp | 145 ++++++++++++++------- 1 file changed, 98 insertions(+), 47 deletions(-) diff --git a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp index a50ee60975..bb4f4b1abd 100644 --- a/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp +++ b/src/plugins/platforms/windows/qwindowsfontenginedirectwrite.cpp @@ -520,13 +520,8 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, int margin, const QTransform &xform) { - glyph_metrics_t metrics = QFontEngine::boundingBox(t, xform); - // This needs to be kept in sync with alphaMapBoundingBox - int width = (metrics.width + margin * 2).ceil().toInt() ; - int height = (metrics.height + margin * 2).ceil().toInt(); - UINT16 glyphIndex = t; - FLOAT glyphAdvance = metrics.xoff.toReal(); + FLOAT glyphAdvance = 0; DWRITE_GLYPH_OFFSET glyphOffset; glyphOffset.advanceOffset = 0; @@ -542,12 +537,9 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, glyphRun.bidiLevel = 0; glyphRun.glyphOffsets = &glyphOffset; - QFixed x = margin - metrics.x.floor() + subPixelPosition; - QFixed y = margin - metrics.y.floor(); - DWRITE_MATRIX transform; - transform.dx = x.toReal(); - transform.dy = y.toReal(); + transform.dx = subPixelPosition.toReal(); + transform.dy = 0; transform.m11 = xform.m11(); transform.m12 = xform.m12(); transform.m21 = xform.m21(); @@ -571,46 +563,56 @@ QImage QWindowsFontEngineDirectWrite::imageForGlyph(glyph_t t, if (SUCCEEDED(hr)) { RECT rect; - rect.left = 0; - rect.top = 0; - rect.right = width; - rect.bottom = height; + glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); - int size = width * height * 3; - BYTE *alphaValues = new BYTE[size]; - memset(alphaValues, 0, size); + rect.left -= margin; + rect.top -= margin; + rect.right += margin; + rect.bottom += margin; - hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, - &rect, - alphaValues, - size); + const int width = rect.right - rect.left; + const int height = rect.bottom - rect.top; - if (SUCCEEDED(hr)) { - QImage img(width, height, QImage::Format_RGB32); - img.fill(0xffffffff); + const int size = width * height * 3; + if (size > 0) { + BYTE *alphaValues = new BYTE[size]; + memset(alphaValues, 0, size); - for (int y=0; y(img.scanLine(y)); - BYTE *src = alphaValues + width * 3 * y; + hr = glyphAnalysis->CreateAlphaTexture(DWRITE_TEXTURE_CLEARTYPE_3x1, + &rect, + alphaValues, + size); - for (int x=0; x(img.scanLine(y)); + BYTE *src = alphaValues + width * 3 * y; + + for (int x=0; xRelease(); + delete[] alphaValues; + glyphAnalysis->Release(); + + return img; + } else { + delete[] alphaValues; + glyphAnalysis->Release(); - return img; + qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__); + } } else { - delete[] alphaValues; glyphAnalysis->Release(); - - qErrnoWarning("%s: CreateAlphaTexture failed", __FUNCTION__); + qWarning("%s: Glyph has no bounds", __FUNCTION__); } } else { @@ -724,16 +726,65 @@ QString QWindowsFontEngineDirectWrite::fontNameSubstitute(const QString &familyN return QSettings(QLatin1String(keyC), QSettings::NativeFormat).value(familyName, familyName).toString(); } -glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, QFixed pos, const QTransform &matrix, GlyphFormat format) +glyph_metrics_t QWindowsFontEngineDirectWrite::alphaMapBoundingBox(glyph_t glyph, + QFixed subPixelPosition, + const QTransform &matrix, + GlyphFormat format) { - Q_UNUSED(pos); Q_UNUSED(format); + glyph_metrics_t bbox = QFontEngine::boundingBox(glyph, matrix); // To get transformed advance + + UINT16 glyphIndex = glyph; + FLOAT glyphAdvance = 0; + + DWRITE_GLYPH_OFFSET glyphOffset; + glyphOffset.advanceOffset = 0; + glyphOffset.ascenderOffset = 0; + + DWRITE_GLYPH_RUN glyphRun; + glyphRun.fontFace = m_directWriteFontFace; + glyphRun.fontEmSize = fontDef.pixelSize; + glyphRun.glyphCount = 1; + glyphRun.glyphIndices = &glyphIndex; + glyphRun.glyphAdvances = &glyphAdvance; + glyphRun.isSideways = false; + glyphRun.bidiLevel = 0; + glyphRun.glyphOffsets = &glyphOffset; + + DWRITE_MATRIX transform; + transform.dx = subPixelPosition.toReal(); + transform.dy = 0; + transform.m11 = matrix.m11(); + transform.m12 = matrix.m12(); + transform.m21 = matrix.m21(); + transform.m22 = matrix.m22(); + + IDWriteGlyphRunAnalysis *glyphAnalysis = NULL; + HRESULT hr = m_fontEngineData->directWriteFactory->CreateGlyphRunAnalysis( + &glyphRun, + 1.0f, + &transform, + DWRITE_RENDERING_MODE_CLEARTYPE_NATURAL_SYMMETRIC, + DWRITE_MEASURING_MODE_NATURAL, + 0.0, 0.0, + &glyphAnalysis + ); - int margin = glyphMargin(QFontEngine::Format_A32); - glyph_metrics_t gm = QFontEngine::boundingBox(glyph, matrix); - gm.width += margin * 2; - gm.height += margin * 2; - return gm; + if (SUCCEEDED(hr)) { + RECT rect; + glyphAnalysis->GetAlphaTextureBounds(DWRITE_TEXTURE_CLEARTYPE_3x1, &rect); + glyphAnalysis->Release(); + + int margin = glyphMargin(QFontEngine::Format_A32); + + return glyph_metrics_t(rect.left, + rect.top, + rect.right - rect.left + margin * 2, + rect.bottom - rect.top + margin * 2, + bbox.xoff, bbox.yoff); + } else { + return glyph_metrics_t(); + } } QT_END_NAMESPACE -- cgit v1.2.3 From 3d82b74c3a2b52ef4239fcb7abd9b54d8cb69805 Mon Sep 17 00:00:00 2001 From: Topi Reinio Date: Thu, 10 Dec 2015 12:44:11 +0100 Subject: Doc: Fix return type of QWeakPointer assignment operators Imprementation of QWeakPointer assign operators have return types that are references. However, in qsharedpointer.h where separate declarations are held for documentation purposes, the reference qualifiers were missing. This led to incorrect documentation being generated. Task-number: QTBUG-49862 Change-Id: I32727762826feb15a3f4f22446e51d2df16e605f Reviewed-by: Timur Pocheptsov --- src/corelib/tools/qsharedpointer.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qsharedpointer.h b/src/corelib/tools/qsharedpointer.h index 279ec36a28..af42d06991 100644 --- a/src/corelib/tools/qsharedpointer.h +++ b/src/corelib/tools/qsharedpointer.h @@ -108,11 +108,11 @@ public: ~QWeakPointer(); - QWeakPointer operator=(const QWeakPointer &other); - QWeakPointer operator=(const QSharedPointer &other); + QWeakPointer &operator=(const QWeakPointer &other); + QWeakPointer &operator=(const QSharedPointer &other); QWeakPointer(const QObject *other); - QWeakPointer operator=(const QObject *other); + QWeakPointer &operator=(const QObject *other); void swap(QWeakPointer &other); -- cgit v1.2.3 From b530ca770f54165cd2766ccebb7269ba45bccb51 Mon Sep 17 00:00:00 2001 From: Timur Pocheptsov Date: Thu, 7 Jan 2016 09:03:09 +0100 Subject: tst_qtextcocumentlayout::blockVisibility - make the test more robust MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit The test inserts strings "0" ... "9" into the text document, takes the half of resulting document's size, makes half of lines invisible and compares sizes. On OS X 10.11 after inserting "4" the width changes, so making "4" invisible also reduces the width and QCOMPARE(currentSize, previosHalfSize) fails. Instead of digits, insert the same string "A" 10 times. Change-Id: Ie88a0442703f98949cea9bcdb694cecee59695f3 Task-number: QTBUG-49848 Reviewed-by: Morten Johan Sørvig --- tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp b/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp index f59f542a2b..6a14928219 100644 --- a/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp +++ b/tests/auto/gui/text/qtextdocumentlayout/tst_qtextdocumentlayout.cpp @@ -319,7 +319,7 @@ void tst_QTextDocumentLayout::blockVisibility() for (int i = 0; i < 10; ++i) { if (!doc->isEmpty()) cursor.insertBlock(); - cursor.insertText(QString::number(i)); + cursor.insertText("A"); } qreal margin = doc->documentMargin(); -- cgit v1.2.3 From 8dad3bf2121e3ad5e405665fefa28c4d53192bf7 Mon Sep 17 00:00:00 2001 From: Kevin Funk Date: Thu, 14 Jan 2016 23:33:28 +0100 Subject: Fix toDisplayString(QUrl::PreferLocalFile) on Win When using QUrl::PreferLocalFile we do want to strip the leading slash, as toLocalFile() would do as well. Behavior change by means of an example: QUrl url(QUrl::fromLocalFile("C:/file.txt") url.toLocalFile() --> "C:/file.txt" Before: url.toDisplayString(QUrl::PreferLocalFile) --> "/C:/file.txt" After: url.toDisplayString(QUrl::PreferLocalFile) --> "C:/file.txt" Task-number: QTBUG-41729 Change-Id: I7d425541f6077ebcf3fcf46feeb7e0f03a0d7fe2 Reviewed-by: Dominik Haumann Reviewed-by: Thiago Macieira --- src/corelib/io/qurl.cpp | 53 +++++++++++++++++++-------------- tests/auto/corelib/io/qurl/tst_qurl.cpp | 25 ++++++++++++++++ 2 files changed, 55 insertions(+), 23 deletions(-) diff --git a/src/corelib/io/qurl.cpp b/src/corelib/io/qurl.cpp index 775a870a27..b51119c7ad 100644 --- a/src/corelib/io/qurl.cpp +++ b/src/corelib/io/qurl.cpp @@ -556,6 +556,7 @@ public: inline bool hasFragment() const { return sectionIsPresent & Fragment; } inline bool isLocalFile() const { return flags & IsLocalFile; } + QString toLocalFile(QUrl::FormattingOptions options) const; QString mergePaths(const QString &relativePath) const; @@ -1460,6 +1461,33 @@ inline void QUrlPrivate::parse(const QString &url, QUrl::ParsingMode parsingMode validateComponent(Fragment, url, hash + 1, len); } +QString QUrlPrivate::toLocalFile(QUrl::FormattingOptions options) const +{ + QString tmp; + QString ourPath; + appendPath(ourPath, options, QUrlPrivate::Path); + + // magic for shared drive on windows + if (!host.isEmpty()) { + tmp = QStringLiteral("//") + host; +#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only. + if (scheme == webDavScheme()) + tmp += webDavSslTag(); +#endif + if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/'))) + tmp += QLatin1Char('/'); + tmp += ourPath; + } else { + tmp = ourPath; +#ifdef Q_OS_WIN + // magic for drives on windows + if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) + tmp.remove(0, 1); +#endif + } + return tmp; +} + /* From http://www.ietf.org/rfc/rfc3986.txt, 5.2.3: Merge paths @@ -3257,7 +3285,7 @@ QString QUrl::toString(FormattingOptions options) const && (!d->hasQuery() || options.testFlag(QUrl::RemoveQuery)) && (!d->hasFragment() || options.testFlag(QUrl::RemoveFragment)) && isLocalFile()) { - return path(options); + return d->toLocalFile(options); } QString url; @@ -3820,28 +3848,7 @@ QString QUrl::toLocalFile() const if (!isLocalFile()) return QString(); - QString tmp; - QString ourPath = path(QUrl::FullyDecoded); - - // magic for shared drive on windows - if (!d->host.isEmpty()) { - tmp = QStringLiteral("//") + host(); -#ifdef Q_OS_WIN // QTBUG-42346, WebDAV is visible as local file on Windows only. - if (scheme() == webDavScheme()) - tmp += webDavSslTag(); -#endif - if (!ourPath.isEmpty() && !ourPath.startsWith(QLatin1Char('/'))) - tmp += QLatin1Char('/'); - tmp += ourPath; - } else { - tmp = ourPath; -#ifdef Q_OS_WIN - // magic for drives on windows - if (ourPath.length() > 2 && ourPath.at(0) == QLatin1Char('/') && ourPath.at(2) == QLatin1Char(':')) - tmp.remove(0, 1); -#endif - } - return tmp; + return d->toLocalFile(QUrl::FullyDecoded); } /*! diff --git a/tests/auto/corelib/io/qurl/tst_qurl.cpp b/tests/auto/corelib/io/qurl/tst_qurl.cpp index 031a35b380..519b05f492 100644 --- a/tests/auto/corelib/io/qurl/tst_qurl.cpp +++ b/tests/auto/corelib/io/qurl/tst_qurl.cpp @@ -69,6 +69,8 @@ private slots: void resolving(); void toString_data(); void toString(); + void toString_PreferLocalFile_data(); + void toString_PreferLocalFile(); void toString_constructed_data(); void toString_constructed(); void toAndFromStringList_data(); @@ -1050,6 +1052,29 @@ void tst_QUrl::toString() QCOMPARE(url.adjusted(opt).toString(), string); } +void tst_QUrl::toString_PreferLocalFile_data() +{ + QTest::addColumn("url"); + QTest::addColumn("string"); + +#ifdef Q_OS_WIN + QTest::newRow("win-drive") << QUrl(QString::fromLatin1("file:///c:/windows/regedit.exe")) + << QString::fromLatin1("c:/windows/regedit.exe"); + QTest::newRow("win-share") << QUrl(QString::fromLatin1("//Anarki/homes")) + << QString::fromLatin1("//anarki/homes"); +#else + QTest::newRow("unix-path") << QUrl(QString::fromLatin1("file:///tmp")) + << QString::fromLatin1("/tmp"); +#endif +} + +void tst_QUrl::toString_PreferLocalFile() +{ + QFETCH(QUrl, url); + QFETCH(QString, string); + + QCOMPARE(url.toString(QUrl::PreferLocalFile), string); +} void tst_QUrl::toAndFromStringList_data() { -- cgit v1.2.3 From 191858abe8cd2681f8f4e9de47819829bf1eaebb Mon Sep 17 00:00:00 2001 From: Friedemann Kleint Date: Tue, 19 Jan 2016 13:18:35 +0100 Subject: QMainWindowLayout::unplug(): Prevent unplugging when the widget is not a window. Task-number: QTBUG-50490 Change-Id: Icf02e2316bbad0794bd5ac6dccd857bfb28a498b Reviewed-by: Olivier Goffart (Woboq GmbH) --- src/widgets/widgets/qmainwindowlayout.cpp | 23 ++++++++++++----------- 1 file changed, 12 insertions(+), 11 deletions(-) diff --git a/src/widgets/widgets/qmainwindowlayout.cpp b/src/widgets/widgets/qmainwindowlayout.cpp index 54e956c4cf..1bb8496505 100644 --- a/src/widgets/widgets/qmainwindowlayout.cpp +++ b/src/widgets/widgets/qmainwindowlayout.cpp @@ -2252,17 +2252,18 @@ void QMainWindowLayout::setCentralWidget(QWidget *widget) QLayoutItem *QMainWindowLayout::unplug(QWidget *widget, bool group) { #if !defined(QT_NO_DOCKWIDGET) && !defined(QT_NO_TABBAR) - QDockWidgetGroupWindow *floatingParent = qobject_cast(widget->parentWidget()); - if (group && floatingParent && !widget->isWindow()) { - // We are just dragging a floating window as it, not need to do anything, we just have to - // look up the corresponding QWidgetItem* if it exists - QList tabbedWindowPath = layoutState.indexOf(widget->parentWidget()); - return tabbedWindowPath.isEmpty() ? 0 : layoutState.item(tabbedWindowPath); - } else if (floatingParent) { - // We are unplugging a dock widget from a floating window. - if (QDockWidget *dw = qobject_cast(widget)) { - dw->d_func()->unplug(widget->geometry()); - return 0; + if (!widget->isWindow() && qobject_cast(widget->parentWidget())) { + if (group) { + // We are just dragging a floating window as it, not need to do anything, we just have to + // look up the corresponding QWidgetItem* if it exists + QList tabbedWindowPath = layoutState.indexOf(widget->parentWidget()); + return tabbedWindowPath.isEmpty() ? 0 : layoutState.item(tabbedWindowPath); + } else { + // We are unplugging a dock widget from a floating window. + if (QDockWidget *dw = qobject_cast(widget)) { + dw->d_func()->unplug(widget->geometry()); + return 0; + } } } #endif -- cgit v1.2.3 From 722df6e0a2c640f09903f9b4f3b686c5c70e82d9 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Thu, 5 Nov 2015 15:13:48 +0100 Subject: Nomenclature corrections relating to CET. There are several European time zones; the only one relevant to the tests here is CET. They won't work with WET, GMT or EET. So name them and related variables for CET, not for Europe. CET's summer-time isn't called CST; and the (existing) spring forward test works only in CET/CEST, not elsewhere in Europe. Change-Id: I55c7544bf792de7495700b749b935ec534831d8b Reviewed-by: Thiago Macieira --- .../auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 74 +++++++++++----------- 1 file changed, 37 insertions(+), 37 deletions(-) diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index 228ce73c6b..d8934c1604 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -155,7 +155,7 @@ private slots: private: enum { LocalTimeIsUtc = 0, LocalTimeAheadOfUtc = 1, LocalTimeBehindUtc = -1} localTimeType; - bool europeanTimeZone; + bool zoneIsCET; QDate defDate() const { return QDate(1900, 1, 1); } QTime defTime() const { return QTime(0, 0, 0); } QDateTime defDateTime() const { return QDateTime(defDate(), defTime()); } @@ -173,7 +173,7 @@ tst_QDateTime::tst_QDateTime() { uint x1 = QDateTime(QDate(1990, 1, 1), QTime()).toTime_t(); uint x2 = QDateTime(QDate(1990, 6, 1), QTime()).toTime_t(); - europeanTimeZone = (x1 == 631148400 && x2 == 644191200); + zoneIsCET = (x1 == 631148400 && x2 == 644191200); QDateTime dt1 = QDateTime::fromTime_t(0); QDateTime dt2 = QDateTime::fromTime_t(181 * 86400); // six months later, Jul 1 @@ -201,7 +201,7 @@ void tst_QDateTime::initTestCase() break; case LocalTimeAheadOfUtc: typemsg1 = "ahead of"; - typemsg2 = europeanTimeZone ? "and is" : "but isn't"; + typemsg2 = zoneIsCET ? "and is" : "but isn't"; break; } @@ -245,7 +245,7 @@ void tst_QDateTime::ctor() QCOMPARE(dt3.timeSpec(), Qt::UTC); QVERIFY(dt1 == dt2); - if (europeanTimeZone) { + if (zoneIsCET) { QVERIFY(dt1 != dt3); QVERIFY(dt1 < dt3); QVERIFY(dt1.addSecs(3600).toUTC() == dt3); @@ -492,7 +492,7 @@ void tst_QDateTime::setTime_t() dt1.setTime_t(123456); QCOMPARE(dt1, QDateTime(QDate(1970, 1, 2), QTime(10, 17, 36), Qt::UTC)); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime dt2; dt2.setTime_t(123456); QCOMPARE(dt2, QDateTime(QDate(1970, 1, 2), QTime(11, 17, 36), Qt::LocalTime)); @@ -500,7 +500,7 @@ void tst_QDateTime::setTime_t() dt1.setTime_t((uint)(quint32)-123456); QCOMPARE(dt1, QDateTime(QDate(2106, 2, 5), QTime(20, 10, 40), Qt::UTC)); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime dt2; dt2.setTime_t((uint)(quint32)-123456); QCOMPARE(dt2, QDateTime(QDate(2106, 2, 5), QTime(21, 10, 40), Qt::LocalTime)); @@ -508,7 +508,7 @@ void tst_QDateTime::setTime_t() dt1.setTime_t(1214567890); QCOMPARE(dt1, QDateTime(QDate(2008, 6, 27), QTime(11, 58, 10), Qt::UTC)); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime dt2; dt2.setTime_t(1214567890); QCOMPARE(dt2, QDateTime(QDate(2008, 6, 27), QTime(13, 58, 10), Qt::LocalTime)); @@ -516,7 +516,7 @@ void tst_QDateTime::setTime_t() dt1.setTime_t(0x7FFFFFFF); QCOMPARE(dt1, QDateTime(QDate(2038, 1, 19), QTime(3, 14, 7), Qt::UTC)); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime dt2; dt2.setTime_t(0x7FFFFFFF); QCOMPARE(dt2, QDateTime(QDate(2038, 1, 19), QTime(4, 14, 7), Qt::LocalTime)); @@ -533,7 +533,7 @@ void tst_QDateTime::setMSecsSinceEpoch_data() { QTest::addColumn("msecs"); QTest::addColumn("utc"); - QTest::addColumn("european"); + QTest::addColumn("cet"); QTest::newRow("zero") << Q_INT64_C(0) @@ -584,7 +584,7 @@ void tst_QDateTime::setMSecsSinceEpoch() { QFETCH(qint64, msecs); QFETCH(QDateTime, utc); - QFETCH(QDateTime, european); + QFETCH(QDateTime, cet); QDateTime dt; dt.setTimeSpec(Qt::UTC); @@ -595,8 +595,8 @@ void tst_QDateTime::setMSecsSinceEpoch() QCOMPARE(dt.time(), utc.time()); QCOMPARE(dt.timeSpec(), Qt::UTC); - if (europeanTimeZone) { - QCOMPARE(dt.toLocalTime(), european); + if (zoneIsCET) { + QCOMPARE(dt.toLocalTime(), cet); // Test converting from LocalTime to UTC back to LocalTime. QDateTime localDt; @@ -613,13 +613,13 @@ void tst_QDateTime::setMSecsSinceEpoch() QDateTime dt2; dt2.setTimeZone(europe); dt2.setMSecsSinceEpoch(msecs); - QCOMPARE(dt2.date(), european.date()); + QCOMPARE(dt2.date(), cet.date()); // don't compare the time if the date is too early or too late: prior // to 1916, timezones in Europe were not standardised and some OS APIs // have hard limits. Let's restrict it to the 32-bit Unix range if (dt2.date().year() >= 1970 && dt2.date().year() <= 2037) - QCOMPARE(dt2.time(), european.time()); + QCOMPARE(dt2.time(), cet.time()); QCOMPARE(dt2.timeSpec(), Qt::TimeZone); QCOMPARE(dt2.timeZone(), europe); } @@ -643,7 +643,7 @@ void tst_QDateTime::fromMSecsSinceEpoch() { QFETCH(qint64, msecs); QFETCH(QDateTime, utc); - QFETCH(QDateTime, european); + QFETCH(QDateTime, cet); QDateTime dtLocal = QDateTime::fromMSecsSinceEpoch(msecs, Qt::LocalTime); QDateTime dtUtc = QDateTime::fromMSecsSinceEpoch(msecs, Qt::UTC); @@ -665,10 +665,10 @@ void tst_QDateTime::fromMSecsSinceEpoch() if (msecs != std::numeric_limits::max()) QCOMPARE(dtOffset.time(), utc.time().addMSecs(60*60*1000)); - if (europeanTimeZone) { - QCOMPARE(dtLocal.toLocalTime(), european); - QCOMPARE(dtUtc.toLocalTime(), european); - QCOMPARE(dtOffset.toLocalTime(), european); + if (zoneIsCET) { + QCOMPARE(dtLocal.toLocalTime(), cet); + QCOMPARE(dtUtc.toLocalTime(), cet); + QCOMPARE(dtOffset.toLocalTime(), cet); } else { QSKIP("You must test using Central European (CET/CEST) time zone, e.g. TZ=Europe/Oslo"); } @@ -793,7 +793,7 @@ void tst_QDateTime::toString_rfcDate_data() QTest::addColumn("dt"); QTest::addColumn("formatted"); - if (europeanTimeZone) { + if (zoneIsCET) { QTest::newRow("localtime") << QDateTime(QDate(1978, 11, 9), QTime(13, 28, 34)) << QString("09 Nov 1978 13:28:34 +0100"); @@ -1050,7 +1050,7 @@ void tst_QDateTime::addSecs_data() QTest::newRow("utc9") << QDateTime(QDate(4000, 1, 1), standardTime, Qt::UTC) << 0 << QDateTime(QDate(4000, 1, 1), standardTime, Qt::UTC); - if (europeanTimeZone) { + if (zoneIsCET) { QTest::newRow("cet0") << QDateTime(QDate(2004, 1, 1), standardTime, Qt::LocalTime) << 86400 << QDateTime(QDate(2004, 1, 2), standardTime, Qt::LocalTime); QTest::newRow("cet1") << QDateTime(QDate(2004, 1, 1), standardTime, Qt::LocalTime) << (86400 * 185) @@ -1162,7 +1162,7 @@ void tst_QDateTime::toTimeSpec_data() << QDateTime(QDate(-271821, 4, 20), QTime(23, 0, 0), Qt::UTC) << QDateTime(QDate(-271821, 4, 21), QTime(0, 0, 0), Qt::LocalTime); - if (europeanTimeZone) { + if (zoneIsCET) { QTest::newRow("summer1") << QDateTime(QDate(2004, 6, 30), utcTime, Qt::UTC) << QDateTime(QDate(2004, 6, 30), localDaylightTime, Qt::LocalTime); QTest::newRow("summer2") << QDateTime(QDate(1760, 6, 30), utcTime, Qt::UTC) @@ -1185,7 +1185,7 @@ void tst_QDateTime::toTimeSpec_data() void tst_QDateTime::toTimeSpec() { - if (europeanTimeZone) { + if (zoneIsCET) { QFETCH(QDateTime, fromUtc); QFETCH(QDateTime, fromLocal); @@ -1240,7 +1240,7 @@ void tst_QDateTime::toTimeSpec() QCOMPARE(localToOffset.time(), fromUtc.time()); QCOMPARE(localToOffset.timeSpec(), Qt::UTC); } else { - QSKIP("Not tested with timezone other than Central European (CET/CST)"); + QSKIP("Not tested with timezone other than Central European (CET/CEST)"); } } @@ -1251,7 +1251,7 @@ void tst_QDateTime::toLocalTime_data() void tst_QDateTime::toLocalTime() { - if (europeanTimeZone) { + if (zoneIsCET) { QFETCH(QDateTime, fromUtc); QFETCH(QDateTime, fromLocal); @@ -1262,7 +1262,7 @@ void tst_QDateTime::toLocalTime() QCOMPARE(fromUtc.toLocalTime(), fromLocal); QCOMPARE(fromUtc.toLocalTime(), fromLocal.toLocalTime()); } else { - QSKIP("Not tested with timezone other than Central European (CET/CST)"); + QSKIP("Not tested with timezone other than Central European (CET/CEST)"); } } @@ -1273,7 +1273,7 @@ void tst_QDateTime::toUTC_data() void tst_QDateTime::toUTC() { - if (europeanTimeZone) { + if (zoneIsCET) { QFETCH(QDateTime, fromUtc); QFETCH(QDateTime, fromLocal); @@ -1284,7 +1284,7 @@ void tst_QDateTime::toUTC() QCOMPARE(fromLocal.toUTC(), fromUtc); QCOMPARE(fromUtc.toUTC(), fromLocal.toUTC()); } else { - QSKIP("Not tested with timezone other than Central European (CET/CST)"); + QSKIP("Not tested with timezone other than Central European (CET/CEST)"); } QDateTime dt = QDateTime::currentDateTime(); @@ -1614,9 +1614,9 @@ void tst_QDateTime::springForward_data() QTest::addColumn("step"); // days to step; +ve from before, -ve from after QTest::addColumn("adjust"); // minutes ahead of UTC on day stepped from - if (europeanTimeZone) { - QTest::newRow("Europe from day before") << QDate(2015, 3, 29) << QTime(2, 30, 0) << 1 << 60; - QTest::newRow("Europe from day after") << QDate(2015, 3, 29) << QTime(2, 30, 0) << -1 << 120; + if (zoneIsCET) { + QTest::newRow("CET from day before") << QDate(2015, 3, 29) << QTime(2, 30, 0) << 1 << 60; + QTest::newRow("CET from day after") << QDate(2015, 3, 29) << QTime(2, 30, 0) << -1 << 120; // } else if (otherZone) { } else { QSKIP("No spring forward test data for this TZ"); @@ -1687,7 +1687,7 @@ void tst_QDateTime::operator_eqeq_data() QTest::newRow("invalid == invalid") << invalidDateTime() << invalidDateTime() << true << false; QTest::newRow("invalid == valid #1") << invalidDateTime() << dateTime1 << false << false; - if (europeanTimeZone) { + if (zoneIsCET) { QTest::newRow("data14") << QDateTime(QDate(2004, 1, 2), QTime(2, 2, 3), Qt::LocalTime) << QDateTime(QDate(2004, 1, 2), QTime(1, 2, 3), Qt::UTC) << true << true; } @@ -1719,7 +1719,7 @@ void tst_QDateTime::operator_eqeq() if (equal) QVERIFY(qHash(dt1) == qHash(dt2)); - if (checkEuro && europeanTimeZone) { + if (checkEuro && zoneIsCET) { QVERIFY(dt1.toUTC() == dt2); QVERIFY(dt1 == dt2.toLocalTime()); } @@ -2233,7 +2233,7 @@ void tst_QDateTime::offsetFromUtc() QCOMPARE(dt2.offsetFromUtc(), 0); // LocalTime should vary - if (europeanTimeZone) { + if (zoneIsCET) { // Time definitely in Standard Time so 1 hour ahead QDateTime dt3(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::LocalTime); QCOMPARE(dt3.offsetFromUtc(), 1 * 60 * 60); @@ -2358,7 +2358,7 @@ void tst_QDateTime::timeZoneAbbreviation() QCOMPARE(dt3.timeZoneAbbreviation(), QString("UTC")); // LocalTime should vary - if (europeanTimeZone) { + if (zoneIsCET) { // Time definitely in Standard Time QDateTime dt4(QDate(2013, 1, 1), QTime(0, 0, 0), Qt::LocalTime); #ifdef Q_OS_WIN @@ -2482,7 +2482,7 @@ void tst_QDateTime::isDaylightTime() const QDateTime offset2(QDate(2012, 6, 1), QTime(0, 0, 0), Qt::OffsetFromUTC, 1 * 60 * 60); QVERIFY(!offset2.isDaylightTime()); - if (europeanTimeZone) { + if (zoneIsCET) { QDateTime cet1(QDate(2012, 1, 1), QTime(0, 0, 0)); QVERIFY(!cet1.isDaylightTime()); QDateTime cet2(QDate(2012, 6, 1), QTime(0, 0, 0)); @@ -2494,7 +2494,7 @@ void tst_QDateTime::isDaylightTime() const void tst_QDateTime::daylightTransitions() const { - if (europeanTimeZone) { + if (zoneIsCET) { // CET transitions occur at 01:00:00 UTC on last Sunday in March and October // 2011-03-27 02:00:00 CET became 03:00:00 CEST at msecs = 1301187600000 // 2011-10-30 03:00:00 CEST became 02:00:00 CET at msecs = 1319936400000 -- cgit v1.2.3 From f7d9e34b96926cca9918608c23ead84bd0286db9 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Tue, 12 Jan 2016 15:16:25 +0100 Subject: Be fussier about setting tst_QDateTime's globals. Time zones change on the whim of politicians. Consequently, we can seem to be in CET/CEST or on UTC (because we tested sample dates when our zone coincided) when we aren't (i.e. we're in a materially different zone at the time probed by some particular test). Make the initialization of the globals that test this more robust against governmental meddling and document the unfixable problem with Algeria: a DST transition *on the epoch*. Change-Id: I17c5c81d339b80af12f4ffab367e28052dd6c2fa Reviewed-by: Thiago Macieira --- .../auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 77 ++++++++++++++++++---- 1 file changed, 63 insertions(+), 14 deletions(-) diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index d8934c1604..e4572d7c2c 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -171,21 +171,70 @@ Q_DECLARE_METATYPE(Qt::DateFormat) tst_QDateTime::tst_QDateTime() { - uint x1 = QDateTime(QDate(1990, 1, 1), QTime()).toTime_t(); - uint x2 = QDateTime(QDate(1990, 6, 1), QTime()).toTime_t(); - zoneIsCET = (x1 == 631148400 && x2 == 644191200); - - QDateTime dt1 = QDateTime::fromTime_t(0); - QDateTime dt2 = QDateTime::fromTime_t(181 * 86400); // six months later, Jul 1 - if (dt1.date().year() < 1970 || dt2.date().month() < 7) { - localTimeType = LocalTimeBehindUtc; - } else if (dt1.time().hour() > 0 || dt1.date().day() > 1) { - localTimeType = LocalTimeAheadOfUtc; - } else if (dt2.time().hour() > 0 || dt2.date().day() > 1) { - localTimeType = LocalTimeAheadOfUtc; - } else { - localTimeType = LocalTimeIsUtc; + /* + Due to some jurisdictions changing their zones and rules, it's possible + for a non-CET zone to accidentally match CET at a few tested moments but + be different a few years later or earlier. This would lead to tests + failing if run in the partially-aliasing zone (e.g. Algeria, Lybia). So + test thoroughly; ideally at every mid-winter or mid-summer in whose + half-year any test below assumes zoneIsCET means what it says. (Tests at + or near a DST transition implicate both of the half-years that meet + there.) Years outside the 1970--2038 range, however, are likely not + properly handled by the TZ-database; and QDateTime explicitly handles them + differently, so don't probe them here. + */ + const uint day = 24 * 3600; // in seconds + zoneIsCET = (QDateTime(QDate(2038, 1, 19), QTime(4, 14, 7)).toTime_t() == 0x7fffffff + // Entries a year apart robustly differ by multiples of day. + && QDateTime(QDate(2015, 7, 1), QTime()).toTime_t() == 1435701600 + && QDateTime(QDate(2015, 1, 1), QTime()).toTime_t() == 1420066800 + && QDateTime(QDate(2013, 7, 1), QTime()).toTime_t() == 1372629600 + && QDateTime(QDate(2013, 1, 1), QTime()).toTime_t() == 1356994800 + && QDateTime(QDate(2012, 7, 1), QTime()).toTime_t() == 1341093600 + && QDateTime(QDate(2012, 1, 1), QTime()).toTime_t() == 1325372400 + && QDateTime(QDate(2008, 7, 1), QTime()).toTime_t() == 1214863200 + && QDateTime(QDate(2004, 1, 1), QTime()).toTime_t() == 1072911600 + && QDateTime(QDate(2000, 1, 1), QTime()).toTime_t() == 946681200 + && QDateTime(QDate(1990, 7, 1), QTime()).toTime_t() == 646783200 + && QDateTime(QDate(1990, 1, 1), QTime()).toTime_t() == 631148400 + && QDateTime(QDate(1979, 1, 1), QTime()).toTime_t() == 283993200 + // .toTime_t() returns -1 for everything before this: + && QDateTime(QDate(1970, 1, 1), QTime(1, 0, 0)).toTime_t() == 0); + // Use .toMSecsSinceEpoch() if you really need to test anything earlier. + + /* + Again, rule changes can cause a TZ to look like UTC at some sample dates + but deviate at some date relevant to a test using localTimeType. These + tests mostly use years outside the 1970--2038 range for which TZ data is + credible, so we can't helpfully be exhaustive. So scan a sample of years' + starts and middles. + */ + const int sampled = 3; + // UTC starts of months in 2004, 2038 and 1970: + uint jans[sampled] = { 12418 * day, 24837 * day, 0 }; + uint juls[sampled] = { 12600 * day, 25018 * day, 181 * day }; + localTimeType = LocalTimeIsUtc; + for (int i = sampled; i-- > 0; ) { + QDateTime jan = QDateTime::fromTime_t(jans[i]); + QDateTime jul = QDateTime::fromTime_t(juls[i]); + if (jan.date().year() < 1970 || jul.date().month() < 7) { + localTimeType = LocalTimeBehindUtc; + break; + } else if (jan.time().hour() > 0 || jul.time().hour() > 0 + || jan.date().day() > 1 || jul.date().day() > 1) { + localTimeType = LocalTimeAheadOfUtc; + break; + } } + /* + Even so, TZ=Africa/Algiers will fail fromMSecsSinceEpoch(-1) because it + switched from WET without DST (i.e. UTC) in the late 1960s to WET with DST + for all of 1970 - so they had a DST transition *on the epoch*. They've + since switched to CET with no DST, making life simple; but our tests for + mistakes around the epoch can't tell the difference between what Algeria + really did and the symptoms we can believe a bug might produce: there's + not much we can do about that, that wouldn't hide real bugs. + */ } void tst_QDateTime::initTestCase() -- cgit v1.2.3 From 1967accb64a110a1c84d8f37d413bcd36ab579a1 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Fri, 6 Nov 2015 14:55:11 +0100 Subject: Expand springForward_data() to cover a few more time-zones. The important one is EET, for the benefit of our CI system; but other European zones and the USA's coastal zones likely have enough hackers in them to make this worth checking. Change-Id: Idcc703bce29808e1a0a6279680cc8d3cbed38dac Reviewed-by: Thiago Macieira --- .../auto/corelib/tools/qdatetime/tst_qdatetime.cpp | 38 ++++++++++++++++++++-- 1 file changed, 35 insertions(+), 3 deletions(-) diff --git a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp index e4572d7c2c..6d88b24eda 100644 --- a/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp +++ b/tests/auto/corelib/tools/qdatetime/tst_qdatetime.cpp @@ -1663,12 +1663,44 @@ void tst_QDateTime::springForward_data() QTest::addColumn("step"); // days to step; +ve from before, -ve from after QTest::addColumn("adjust"); // minutes ahead of UTC on day stepped from - if (zoneIsCET) { + /* + Zone tests compare a summer and winter moment's time_t to known values. + This could in principle be flawed (two DST-using zones in the same + hemisphere with the same DST and standard times but different transition + times) but no actual example is known where this is a problem. Please + document any such conflicts, if discovered. + + See http://www.timeanddate.com/time/zones/ for data on more candidates to + test. + */ + + uint winter = QDateTime(QDate(2015, 1, 1), QTime()).toTime_t(); + uint summer = QDateTime(QDate(2015, 7, 1), QTime()).toTime_t(); + + if (winter == 1420066800 && summer == 1435701600) { QTest::newRow("CET from day before") << QDate(2015, 3, 29) << QTime(2, 30, 0) << 1 << 60; QTest::newRow("CET from day after") << QDate(2015, 3, 29) << QTime(2, 30, 0) << -1 << 120; - // } else if (otherZone) { + } else if (winter == 1420063200 && summer == 1435698000) { + // e.g. Finland, where our CI runs ... + QTest::newRow("EET from day before") << QDate(2015, 3, 29) << QTime(3, 30, 0) << 1 << 120; + QTest::newRow("EET from day after") << QDate(2015, 3, 29) << QTime(3, 30, 0) << -1 << 180; + } else if (winter == 1420070400 && summer == 1435705200) { + // Western European Time, WET/WEST; a.k.a. GMT/BST + QTest::newRow("WET from day before") << QDate(2015, 3, 29) << QTime(1, 30, 0) << 1 << 0; + QTest::newRow("WET from day after") << QDate(2015, 3, 29) << QTime(1, 30, 0) << -1 << 60; + } else if (winter == 1420099200 && summer == 1435734000) { + // Western USA, Canada: Pacific Time (e.g. US/Pacific) + QTest::newRow("PT from day before") << QDate(2015, 3, 8) << QTime(2, 30, 0) << 1 << -480; + QTest::newRow("PT from day after") << QDate(2015, 3, 8) << QTime(2, 30, 0) << -1 << -420; + } else if (winter == 1420088400 && summer == 1435723200) { + // Eastern USA, Canada: Eastern Time (e.g. US/Eastern) + QTest::newRow("ET from day before") << QDate(2015, 3, 8) << QTime(2, 30, 0) << 1 << -300; + QTest::newRow("ET from day after") << QDate(2015, 3, 8) << QTime(2, 30, 0) << -1 << -240; } else { - QSKIP("No spring forward test data for this TZ"); + // Includes the numbers you need to test for your zone, as above: + QString msg(QString::fromLatin1("No spring forward test data for this TZ (%1, %2)" + ).arg(winter).arg(summer)); + QSKIP(qPrintable(msg)); } } -- cgit v1.2.3 From d8c0bd4207d5f63d3f47353f8d9c9e6963a24355 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 18 Jan 2016 12:52:12 +0100 Subject: Make it clearer what's happening with a fall-through. An if () {...}'s close-brace was hiding on the end of a break; line, an idiom used in several places for braces that existed to contain a case (for the sake of local declarations). This made it hard to see that there was an if() whose else was the resulting (commented) fall-through. So put that close-brace on the comment's line and make the comment clearly indicate it's an else. Change-Id: Ie7e7c7063bef96536d6231297b083fc384f2363e Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetimeparser.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index eaa695ef27..0832cd0eed 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -765,8 +765,8 @@ int QDateTimeParser::parseSection(const QDateTime ¤tValue, int sectionInde } else { state = Intermediate; } - break; } - // fall through + break; + } // else: fall through case DaySection: case YearSection: case YearSection2Digits: -- cgit v1.2.3 From aa196457da54d007dc443e81f200a62f10f7b915 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 18 Jan 2016 12:42:49 +0100 Subject: Avoid dereferencing before the start of a string. A check for a backslash before a quote neglected to pretest that the quote wasn't the first character in its string. Change-Id: Ib5226836d1111e37bed984938f7c667be59eb1c5 Reviewed-by: Thiago Macieira --- src/corelib/tools/qdatetimeparser.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index 0832cd0eed..99a324a728 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -382,7 +382,7 @@ bool QDateTimeParser::parseFormat(const QString &newFormat) ++add; if (status != quote) { status = quote; - } else if (newFormat.at(i - 1) != slash) { + } else if (i > 0 && newFormat.at(i - 1) != slash) { status = zero; } } else if (status != quote) { -- cgit v1.2.3 From 57e024cc81c55b8c442db9f719f19aebb321ef37 Mon Sep 17 00:00:00 2001 From: Edward Welbourne Date: Mon, 18 Jan 2016 12:45:11 +0100 Subject: Avoid shadowing a name (and use the outer variable an extra time) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit QDateTimeParser::parseFormat()'s top-level scope has a const int max; this was shadowed by a short-lived max in an inner scope; and the outer scope's max could be re-used one more time after that to save re-evaluating the same unchanged expression it held. Change-Id: I9f07452bb0b4e5ff4bcf6396d42d1419de6276fa Reviewed-by: Thiago Macieira Reviewed-by: Jędrzej Nowacki --- src/corelib/tools/qdatetimeparser.cpp | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index 99a324a728..3cf926ca8f 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -494,15 +494,15 @@ bool QDateTimeParser::parseFormat(const QString &newFormat) } if ((newDisplay & (AmPmSection|Hour12Section)) == Hour12Section) { - const int max = newSectionNodes.size(); - for (int i=0; i Date: Mon, 18 Jan 2016 12:58:31 +0100 Subject: Make some initializers be declarations. MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This shortens an earlier over-long line of declarations and makes visible that these are declare-and-initialize. Change-Id: I39fa9613196c34f7e2b2da04da729324d7f83a55 Reviewed-by: Marc Mutz Reviewed-by: Thiago Macieira Reviewed-by: Jędrzej Nowacki --- src/corelib/tools/qdatetimeparser.cpp | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/src/corelib/tools/qdatetimeparser.cpp b/src/corelib/tools/qdatetimeparser.cpp index 3cf926ca8f..9ca2e1ffc0 100644 --- a/src/corelib/tools/qdatetimeparser.cpp +++ b/src/corelib/tools/qdatetimeparser.cpp @@ -889,17 +889,17 @@ QDateTimeParser::StateNode QDateTimeParser::parse(QString &input, int &cursorPos QDTPDEBUG << "parse" << input; { - int year, month, day, hour12, hour, minute, second, msec, ampm, dayofweek, year2digits; + int year, month, day; currentValue.date().getDate(&year, &month, &day); - year2digits = year % 100; - hour = currentValue.time().hour(); - hour12 = -1; - minute = currentValue.time().minute(); - second = currentValue.time().second(); - msec = currentValue.time().msec(); - dayofweek = currentValue.date().dayOfWeek(); - - ampm = -1; + int year2digits = year % 100; + int hour = currentValue.time().hour(); + int hour12 = -1; + int minute = currentValue.time().minute(); + int second = currentValue.time().second(); + int msec = currentValue.time().msec(); + int dayofweek = currentValue.date().dayOfWeek(); + + int ampm = -1; Sections isSet = NoSection; int num; State tmpstate; -- cgit v1.2.3