Merge remote-tracking branch 'origin/dev' into 5.14

Conflicts:
	src/widgets/kernel/qwidget.cpp
	src/widgets/kernel/qwidget_p.h
	src/widgets/kernel/qwidgetrepaintmanager.cpp
	src/widgets/kernel/qwidgetwindow.cpp
	tests/auto/widgets/kernel/qwidget/tst_qwidget.cpp

Change-Id: Ifae457d0427be8e2465e474b055722e11b3b1e5c
This commit is contained in:
Liang Qi 2019-08-27 09:45:52 +02:00
commit 0f1f7fb97f
203 changed files with 4698 additions and 2878 deletions

View File

@ -3,9 +3,6 @@ targetinfofile ~= s/pro$/target.txt/
win32 {
ext = .exe
} else:android {
file_prefix = lib
ext = .so
} else:wasm {
equals(WASM_OBJECT_FILES, 1): \
ext = .o

View File

@ -304,8 +304,8 @@
\snippet threads/mandelbrot/mandelbrotwidget.cpp 12
The wheel event handler is reimplemented to make the mouse wheel
control the zoom level. QWheelEvent::delta() returns the angle of
the wheel mouse movement, in eights of a degree. For most mice,
control the zoom level. QWheelEvent::angleDelta() returns the angle
of the wheel mouse movement, in eighths of a degree. For most mice,
one wheel step corresponds to 15 degrees. We find out how many
mouse steps we have and determine the resulting zoom factor.
For example, if we have two wheel steps in the positive direction

View File

@ -176,7 +176,7 @@ void MandelbrotWidget::keyPressEvent(QKeyEvent *event)
//! [12]
void MandelbrotWidget::wheelEvent(QWheelEvent *event)
{
int numDegrees = event->delta() / 8;
int numDegrees = event->angleDelta().y() / 8;
double numSteps = numDegrees / 15.0f;
zoom(pow(ZoomInFactor, numSteps));
}

View File

@ -68,7 +68,7 @@
void GraphicsView::wheelEvent(QWheelEvent *e)
{
if (e->modifiers() & Qt::ControlModifier) {
if (e->delta() > 0)
if (e->angleDelta().y() > 0)
view->zoomIn(6);
else
view->zoomOut(6);

View File

@ -190,7 +190,7 @@ void GraphWidget::timerEvent(QTimerEvent *event)
//! [5]
void GraphWidget::wheelEvent(QWheelEvent *event)
{
scaleView(pow((double)2, -event->delta() / 240.0));
scaleView(pow((double)2, -event->angleDelta().y() / 240.0));
}
//! [5]
#endif

View File

@ -260,7 +260,7 @@ void XFormView::timerEvent(QTimerEvent *e)
#if QT_CONFIG(wheelevent)
void XFormView::wheelEvent(QWheelEvent *e)
{
m_scale += e->delta() / qreal(600);
m_scale += e->angleDelta().y() / qreal(600);
m_scale = qMax(qreal(0.1), qMin(qreal(4), m_scale));
emit scaleChanged(int(m_scale*1000));
}

View File

@ -93,15 +93,16 @@ void ButtonTester::mouseDoubleClickEvent(QMouseEvent *e)
void ButtonTester::wheelEvent (QWheelEvent *e)
{
QString result;
if (e->delta() > 0) {
if (e->orientation() == Qt::Vertical) {
const bool vertical = qAbs(e->angleDelta().y()) >= qAbs(e->angleDelta().x());
const int delta = vertical ? e->angleDelta().y() : e->angleDelta().x();
if (delta > 0) {
if (vertical) {
result = "Mouse Wheel Event: UP";
} else {
result = "Mouse Wheel Event: LEFT";
}
} else if (e->delta() < 0) {
if (e->orientation() == Qt::Vertical) {
} else if (delta < 0) {
if (vertical) {
result = "Mouse Wheel Event: DOWN";
} else {
result = "Mouse Wheel Event: RIGHT";

View File

@ -8,43 +8,102 @@ CONFIG += android_install unversioned_soname unversioned_libname
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/clang.conf)
include(../common/android-base-head.conf)
load(device_config)
# In early configure setup; nothing useful to be done here.
isEmpty(DEFAULT_ANDROID_NDK_ROOT): return()
NDK_ROOT = $$(ANDROID_NDK_ROOT)
isEmpty(NDK_ROOT): NDK_ROOT = $$DEFAULT_ANDROID_NDK_ROOT
!exists($$NDK_ROOT): error("You need to set the ANDROID_NDK_ROOT environment variable to point to your Android NDK.")
NDK_HOST = $$(ANDROID_NDK_HOST)
isEmpty(NDK_HOST): NDK_HOST = $$DEFAULT_ANDROID_NDK_HOST
ANDROID_PLATFORM = $$(ANDROID_NDK_PLATFORM)
isEmpty(ANDROID_PLATFORM): ANDROID_PLATFORM = $$DEFAULT_ANDROID_PLATFORM
ANDROID_SDK_ROOT = $$(ANDROID_SDK_ROOT)
isEmpty(ANDROID_SDK_ROOT): ANDROID_SDK_ROOT = $$DEFAULT_ANDROID_SDK_ROOT
ANDROID_SDK_BUILD_TOOLS_REVISION = $$(ANDROID_BUILD_TOOLS_REVISION)
isEmpty(ANDROID_SDK_BUILD_TOOLS_REVISION) {
SDK_BUILD_TOOLS_REVISIONS = $$files($$ANDROID_SDK_ROOT/build-tools/*)
for (REVISION, SDK_BUILD_TOOLS_REVISIONS) {
BASENAME = $$basename(REVISION)
greaterThan(BASENAME, $$ANDROID_SDK_BUILD_TOOLS_REVISION): ANDROID_SDK_BUILD_TOOLS_REVISION = $$BASENAME
}
}
ALL_ANDROID_ABIS = arm64-v8a armeabi-v7a x86_64 x86
CONFIG += $$ANDROID_PLATFORM
QMAKE_PCH_OUTPUT_EXT = .gch
QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE}
QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE
NDK_LLVM_PATH = $$NDK_ROOT/toolchains/llvm/prebuilt/$$NDK_HOST
QMAKE_CC = $$NDK_LLVM_PATH/bin/clang
QMAKE_CXX = $$NDK_LLVM_PATH/bin/clang++
QMAKE_LINK = $$QMAKE_CXX
equals(ANDROID_TARGET_ARCH, armeabi-v7a): \
QMAKE_CFLAGS += -target armv7-none-linux-androideabi
else: equals(ANDROID_TARGET_ARCH, armeabi): \
QMAKE_CFLAGS += -target armv5te-none-linux-androideabi
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): \
QMAKE_CFLAGS += -target aarch64-none-linux-android
else: equals(ANDROID_TARGET_ARCH, x86): \
QMAKE_CFLAGS += -target i686-none-linux-android -mstackrealign
else: equals(ANDROID_TARGET_ARCH, x86_64): \
QMAKE_CFLAGS += -target x86_64-none-linux-android
QMAKE_CFLAGS_OPTIMIZE = -Oz
QMAKE_CFLAGS_OPTIMIZE_FULL = -Oz
QMAKE_CFLAGS += -gcc-toolchain $$NDK_TOOLCHAIN_PATH -fno-limit-debug-info
QMAKE_CFLAGS_WARN_ON = -Wall -W
QMAKE_CFLAGS_WARN_OFF =
QMAKE_CFLAGS_SHLIB = -fPIC
QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
QMAKE_CFLAGS_THREAD = -D_REENTRANT
QMAKE_CFLAGS_HIDESYMS = -fvisibility=hidden
QMAKE_CFLAGS_NEON = -mfpu=neon
QMAKE_LINK = $$QMAKE_CXX $$QMAKE_CFLAGS -Wl,--exclude-libs,libgcc.a -Wl,--exclude-libs,libatomic.a -nostdlib++
equals(ANDROID_TARGET_ARCH, armeabi-v7a): QMAKE_LINK += -Wl,--exclude-libs,libunwind.a
QMAKE_LFLAGS_APP = -Wl,--no-undefined -Wl,-z,noexecstack -shared
QMAKE_LFLAGS_SHLIB = -Wl,--no-undefined -Wl,-z,noexecstack -shared
QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB
QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined
QMAKE_LFLAGS_RPATH = -Wl,-rpath=
QMAKE_LFLAGS_RPATHLINK = -Wl,-rpath-link=
QMAKE_CFLAGS += -DANDROID_HAS_WSTRING --sysroot=$$NDK_ROOT/sysroot \
-isystem $$NDK_ROOT/sysroot/usr/include/$$NDK_TOOLS_PREFIX \
-isystem $$NDK_ROOT/sources/cxx-stl/llvm-libc++/include \
-isystem $$NDK_ROOT/sources/android/support/include \
-isystem $$NDK_ROOT/sources/cxx-stl/llvm-libc++abi/include
ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/llvm-libc++/libs/$$ANDROID_TARGET_ARCH
ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++_shared.so
QMAKE_LIBS_X11 =
QMAKE_LIBS_THREAD =
QMAKE_LIBS_OPENGL =
QMAKE_INCDIR_POST =
QMAKE_INCDIR_X11 =
QMAKE_LIBDIR_X11 =
QMAKE_INCDIR_OPENGL =
QMAKE_LIBDIR_OPENGL =
ANDROID_USE_LLVM = true
exists($$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++.so): \
ANDROID_CXX_STL_LIBS = -lc++
else: \
ANDROID_CXX_STL_LIBS = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libc++.so.$$replace(ANDROID_PLATFORM, "android-", "")
armeabi-v7a.sdk = armeabi-v7a
armeabi-v7a.target = armeabi-v7a
armeabi-v7a.dir_affix = armeabi-v7a
armeabi-v7a.CONFIG = armeabi-v7a
armeabi-v7a.deployment_identifier = armeabi-v7a
include(../common/android-base-tail.conf)
arm64-v8a.sdk = arm64-v8a
arm64-v8a.target = arm64-v8a
arm64-v8a.dir_affix = arm64-v8a
arm64-v8a.CONFIG = arm64-v8a
arm64-v8a.deployment_identifier = arm64-v8a
x86.sdk = x86
x86.target = x86
x86.dir_affix = x86
x86.CONFIG = x86
x86.deployment_identifier = x86
x86_64.sdk = x86_64
x86_64.target = x86_64
x86_64.dir_affix = x86_64
x86_64.CONFIG = x86_64
x86_64.deployment_identifier = x86_64
load(qt_config)

View File

@ -1,35 +0,0 @@
# qmake configuration for building with android-g++
MAKEFILE_GENERATOR = UNIX
QMAKE_PLATFORM = android
QMAKE_COMPILER = gcc
CONFIG += android_install unversioned_soname unversioned_libname plugin_with_soname android_deployment_settings
include(../common/linux.conf)
include(../common/gcc-base-unix.conf)
include(../common/android-base-head.conf)
QMAKE_CC = $${CROSS_COMPILE}gcc
QMAKE_CXX = $${CROSS_COMPILE}g++
QMAKE_LINK = $$QMAKE_CXX
ANDROID_SOURCES_CXX_STL_LIBDIR = $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/libs/$$ANDROID_TARGET_ARCH
ANDROID_STDCPP_PATH = $$ANDROID_SOURCES_CXX_STL_LIBDIR/libgnustl_shared.so
ANDROID_CXX_STL_LIBS = -lgnustl_shared -lgcc
ANDROID_USE_LLVM = false
exists($$NDK_ROOT/sysroot/usr/include): \
QMAKE_CFLAGS += --sysroot=$$NDK_ROOT/sysroot \
-isystem $$NDK_ROOT/sysroot/usr/include/$$NDK_TOOLS_PREFIX
else: QMAKE_CFLAGS += --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
QMAKE_CFLAGS += -isystem $$NDK_ROOT/sources/cxx-stl/gnu-libstdc++/$$NDK_TOOLCHAIN_VERSION/include \
-isystem $$ANDROID_SOURCES_CXX_STL_LIBDIR/include
equals(ANDROID_TARGET_ARCH, armeabi)|equals(ANDROID_TARGET_ARCH, armeabi-v7a): \
LIBGCC_PATH_FULL = $$system("$$QMAKE_CXX -mthumb-interwork -print-libgcc-file-name")
else: \
LIBGCC_PATH_FULL = $$system("$$QMAKE_CXX -print-libgcc-file-name")
ANDROID_SOURCES_CXX_STL_LIBDIR += $$dirname(LIBGCC_PATH_FULL)
include(../common/android-base-tail.conf)

View File

@ -1,177 +0,0 @@
/****************************************************************************
**
** Copyright (C) 2016 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the qmake spec of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QPLATFORMDEFS_H
#define QPLATFORMDEFS_H
// Get Qt defines/settings
#include "qglobal.h"
// Set any POSIX/XOPEN defines at the top of this file to turn on specific APIs
// 1) need to reset default environment if _BSD_SOURCE is defined
// 2) need to specify POSIX thread interfaces explicitly in glibc 2.0
// 3) it seems older glibc need this to include the X/Open stuff
#include <unistd.h>
// We are hot - unistd.h should have turned on the specific APIs we requested
#include <features.h>
#include <pthread.h>
#include <dirent.h>
#include <fcntl.h>
#include <grp.h>
#include <pwd.h>
#include <signal.h>
#include <dlfcn.h>
#include <sys/types.h>
#include <sys/ioctl.h>
#include <sys/ipc.h>
#include <sys/time.h>
#include <sys/socket.h>
#include <sys/stat.h>
#include <sys/wait.h>
#ifndef _GNU_SOURCE
# define _GNU_SOURCE
#endif
#ifdef QT_LARGEFILE_SUPPORT
#define QT_STATBUF struct stat64
#define QT_STATBUF4TSTAT struct stat64
#define QT_STAT ::stat64
#define QT_FSTAT ::fstat64
#define QT_LSTAT ::lstat64
#define QT_OPEN ::open64
#define QT_TRUNCATE ::truncate64
#define QT_FTRUNCATE ::ftruncate64
#define QT_LSEEK ::lseek64
#else
#define QT_STATBUF struct stat
#define QT_STATBUF4TSTAT struct stat
#define QT_STAT ::stat
#define QT_FSTAT ::fstat
#define QT_LSTAT ::lstat
#define QT_OPEN ::open
#define QT_TRUNCATE ::truncate
#define QT_FTRUNCATE ::ftruncate
#define QT_LSEEK ::lseek
#endif
#ifdef QT_LARGEFILE_SUPPORT
#define QT_FOPEN ::fopen64
#define QT_FSEEK ::fseeko64
#define QT_FTELL ::ftello64
#define QT_FGETPOS ::fgetpos64
#define QT_FSETPOS ::fsetpos64
#define QT_MMAP ::mmap64
#define QT_FPOS_T fpos64_t
#define QT_OFF_T off64_t
#else
#define QT_FOPEN ::fopen
#define QT_FSEEK ::fseek
#define QT_FTELL ::ftell
#define QT_FGETPOS ::fgetpos
#define QT_FSETPOS ::fsetpos
#define QT_MMAP ::mmap
#define QT_FPOS_T fpos_t
#define QT_OFF_T long
#endif
#define QT_STAT_REG S_IFREG
#define QT_STAT_DIR S_IFDIR
#define QT_STAT_MASK S_IFMT
#define QT_STAT_LNK S_IFLNK
#define QT_SOCKET_CONNECT ::connect
#define QT_SOCKET_BIND ::bind
#define QT_FILENO fileno
#define QT_CLOSE ::close
#define QT_READ ::read
#define QT_WRITE ::write
#define QT_ACCESS ::access
#define QT_GETCWD ::getcwd
#define QT_CHDIR ::chdir
#define QT_MKDIR ::mkdir
#define QT_RMDIR ::rmdir
#define QT_OPEN_LARGEFILE O_LARGEFILE
#define QT_OPEN_RDONLY O_RDONLY
#define QT_OPEN_WRONLY O_WRONLY
#define QT_OPEN_RDWR O_RDWR
#define QT_OPEN_CREAT O_CREAT
#define QT_OPEN_TRUNC O_TRUNC
#define QT_OPEN_APPEND O_APPEND
#define QT_OPEN_EXCL O_EXCL
// Directory iteration
#define QT_DIR DIR
#define QT_OPENDIR ::opendir
#define QT_CLOSEDIR ::closedir
#if defined(QT_LARGEFILE_SUPPORT) \
&& defined(QT_USE_XOPEN_LFS_EXTENSIONS) \
&& !defined(QT_NO_READDIR64)
#define QT_DIRENT struct dirent64
#define QT_READDIR ::readdir64
#define QT_READDIR_R ::readdir64_r
#else
#define QT_DIRENT struct dirent
#define QT_READDIR ::readdir
#define QT_READDIR_R ::readdir_r
#endif
#define QT_SOCKET_CONNECT ::connect
#define QT_SOCKET_BIND ::bind
#define QT_SIGNAL_RETTYPE void
#define QT_SIGNAL_ARGS int
#define QT_SIGNAL_IGNORE SIG_IGN
#define QT_SOCKLEN_T socklen_t
#if defined(_XOPEN_SOURCE) && (_XOPEN_SOURCE >= 500)
#define QT_SNPRINTF ::snprintf
#define QT_VSNPRINTF ::vsnprintf
#endif
#endif // QPLATFORMDEFS_H

View File

@ -1,72 +0,0 @@
load(device_config)
# In early configure setup; nothing useful to be done here.
isEmpty(DEFAULT_ANDROID_NDK_ROOT): return()
NDK_ROOT = $$(ANDROID_NDK_ROOT)
isEmpty(NDK_ROOT): NDK_ROOT = $$DEFAULT_ANDROID_NDK_ROOT
NDK_HOST = $$(ANDROID_NDK_HOST)
isEmpty(NDK_HOST): NDK_HOST = $$DEFAULT_ANDROID_NDK_HOST
ANDROID_PLATFORM = $$(ANDROID_NDK_PLATFORM)
isEmpty(ANDROID_PLATFORM): ANDROID_PLATFORM = $$DEFAULT_ANDROID_PLATFORM
ANDROID_TARGET_ARCH = $$(ANDROID_TARGET_ARCH)
isEmpty(ANDROID_TARGET_ARCH): ANDROID_TARGET_ARCH = $$DEFAULT_ANDROID_TARGET_ARCH
NDK_TOOLCHAIN_PREFIX = $$(ANDROID_NDK_TOOLCHAIN_PREFIX)
isEmpty(NDK_TOOLCHAIN_PREFIX) {
equals(ANDROID_TARGET_ARCH, x86): NDK_TOOLCHAIN_PREFIX = x86
else: equals(ANDROID_TARGET_ARCH, x86_64): NDK_TOOLCHAIN_PREFIX = x86_64
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): NDK_TOOLCHAIN_PREFIX = aarch64-linux-android
else: NDK_TOOLCHAIN_PREFIX = arm-linux-androideabi
}
NDK_TOOLS_PREFIX = $$(ANDROID_NDK_TOOLS_PREFIX)
isEmpty(NDK_TOOLS_PREFIX) {
equals(ANDROID_TARGET_ARCH, x86): NDK_TOOLS_PREFIX = i686-linux-android
else: equals(ANDROID_TARGET_ARCH, x86_64): NDK_TOOLS_PREFIX = x86_64-linux-android
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): NDK_TOOLS_PREFIX = aarch64-linux-android
else: NDK_TOOLS_PREFIX = arm-linux-androideabi
}
NDK_TOOLCHAIN_VERSION = $$(ANDROID_NDK_TOOLCHAIN_VERSION)
isEmpty(NDK_TOOLCHAIN_VERSION): NDK_TOOLCHAIN_VERSION = $$DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION
equals(ANDROID_TARGET_ARCH, x86): ANDROID_ARCHITECTURE = x86
else: equals(ANDROID_TARGET_ARCH, x86_64): ANDROID_ARCHITECTURE = x86_64
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): ANDROID_ARCHITECTURE = arm64
else: ANDROID_ARCHITECTURE = arm
!equals(NDK_TOOLCHAIN_VERSION, 4.4.3): ANDROID_CXXSTL_SUFFIX = -$$NDK_TOOLCHAIN_VERSION
NDK_TOOLCHAIN = $$NDK_TOOLCHAIN_PREFIX-$$NDK_TOOLCHAIN_VERSION
NDK_TOOLCHAIN_PATH = $$NDK_ROOT/toolchains/$$NDK_TOOLCHAIN/prebuilt/$$NDK_HOST
ANDROID_SDK_ROOT = $$(ANDROID_SDK_ROOT)
isEmpty(ANDROID_SDK_ROOT): ANDROID_SDK_ROOT = $$DEFAULT_ANDROID_SDK_ROOT
ANDROID_SDK_BUILD_TOOLS_REVISION = $$(ANDROID_BUILD_TOOLS_REVISION)
isEmpty(ANDROID_SDK_BUILD_TOOLS_REVISION) {
SDK_BUILD_TOOLS_REVISIONS = $$files($$ANDROID_SDK_ROOT/build-tools/*)
for (REVISION, SDK_BUILD_TOOLS_REVISIONS) {
BASENAME = $$basename(REVISION)
greaterThan(BASENAME, $$ANDROID_SDK_BUILD_TOOLS_REVISION): ANDROID_SDK_BUILD_TOOLS_REVISION = $$BASENAME
}
}
CONFIG += $$ANDROID_PLATFORM
QMAKE_CFLAGS = -D__ANDROID_API__=$$replace(ANDROID_PLATFORM, "android-", "")
ANDROID_PLATFORM_ROOT_PATH = $$NDK_ROOT/platforms/$$ANDROID_PLATFORM/arch-$$ANDROID_ARCHITECTURE/
CROSS_COMPILE = $$NDK_TOOLCHAIN_PATH/bin/$$NDK_TOOLS_PREFIX-
QMAKE_PCH_OUTPUT_EXT = .gch
QMAKE_CFLAGS_PRECOMPILE = -x c-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CFLAGS_USE_PRECOMPILE = -include ${QMAKE_PCH_OUTPUT_BASE}
QMAKE_CXXFLAGS_PRECOMPILE = -x c++-header -c ${QMAKE_PCH_INPUT} -o ${QMAKE_PCH_OUTPUT}
QMAKE_CXXFLAGS_USE_PRECOMPILE = $$QMAKE_CFLAGS_USE_PRECOMPILE

View File

@ -1,90 +0,0 @@
# In early configure setup; nothing useful to be done here.
isEmpty(DEFAULT_ANDROID_NDK_ROOT): return()
# -fstack-protector-strong offers good protection against stack smashing attacks.
# It is (currently) enabled only on Android because we know for sure that Andoroid compilers supports it
QMAKE_CFLAGS += -fstack-protector-strong -DANDROID
equals(ANDROID_TARGET_ARCH, armeabi-v7a): \
QMAKE_CFLAGS += -march=armv7-a -mfloat-abi=softfp -mfpu=vfp -fno-builtin-memmove
else: equals(ANDROID_TARGET_ARCH, armeabi): \
QMAKE_CFLAGS += -march=armv5te -mtune=xscale -msoft-float -fno-builtin-memmove
# -fno-builtin-memmove is used to workaround https://code.google.com/p/android/issues/detail?id=81692
QMAKE_CFLAGS_WARN_ON = -Wall -W
QMAKE_CFLAGS_WARN_OFF =
equals(ANDROID_TARGET_ARCH, armeabi-v7a) | equals(ANDROID_TARGET_ARCH, armeabi) {
CONFIG += optimize_size
QMAKE_CFLAGS_DEBUG = -g -marm -O0
equals(ANDROID_TARGET_ARCH, armeabi):if(equals(NDK_TOOLCHAIN_VERSION, 4.8)|equals(NDK_TOOLCHAIN_VERSION, 4.9)) {
DEFINES += QT_OS_ANDROID_GCC_48_WORKAROUND
} else {
QMAKE_CFLAGS_RELEASE += -mthumb
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -mthumb
}
}
QMAKE_CFLAGS_SHLIB = -fPIC
QMAKE_CFLAGS_YACC = -Wno-unused -Wno-parentheses
QMAKE_CFLAGS_THREAD = -D_REENTRANT
QMAKE_CFLAGS_HIDESYMS = -fvisibility=hidden
QMAKE_CFLAGS_NEON = -mfpu=neon
QMAKE_CFLAGS_GNUC99 = -std=gnu99
QMAKE_CFLAGS_GNUC11 = -std=gnu11
QMAKE_CXXFLAGS_CXX11 = -std=c++11
QMAKE_CXXFLAGS_CXX14 = -std=c++14
QMAKE_CXXFLAGS_CXX1Z = -std=c++1z
QMAKE_CXXFLAGS_GNUCXX11 = -std=gnu++11
QMAKE_CXXFLAGS_GNUCXX14 = -std=gnu++14
QMAKE_CXXFLAGS_GNUCXX1Z = -std=gnu++1z
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
QMAKE_CXXFLAGS_RELEASE += $$QMAKE_CFLAGS_RELEASE
QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO += $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_CXXFLAGS_DEBUG += $$QMAKE_CFLAGS_DEBUG
QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
QMAKE_CXXFLAGS_HIDESYMS = $$QMAKE_CFLAGS_HIDESYMS -fvisibility-inlines-hidden
# modifications to linux.conf
QMAKE_AR = $${CROSS_COMPILE}ar cqs
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $${CROSS_COMPILE}nm -P
QMAKE_STRIP =
#$${CROSS_COMPILE}strip
QMAKE_RANLIB = $${CROSS_COMPILE}ranlib
QMAKE_INCDIR_POST =
QMAKE_LIBDIR_POST = $$ANDROID_SOURCES_CXX_STL_LIBDIR
QMAKE_INCDIR_X11 =
QMAKE_LIBDIR_X11 =
QMAKE_INCDIR_OPENGL =
QMAKE_LIBDIR_OPENGL =
QMAKE_LINK_SHLIB = $$QMAKE_LINK
QMAKE_LFLAGS = --sysroot=$$ANDROID_PLATFORM_ROOT_PATH
equals(ANDROID_TARGET_ARCH, x86_64) QMAKE_LFLAGS += -L$$ANDROID_PLATFORM_ROOT_PATH/usr/lib64
QMAKE_LFLAGS_APP = -Wl,--no-undefined -Wl,-z,noexecstack -shared
QMAKE_LFLAGS_SHLIB = -Wl,--no-undefined -Wl,-z,noexecstack -shared
QMAKE_LFLAGS_PLUGIN = $$QMAKE_LFLAGS_SHLIB
QMAKE_LFLAGS_NOUNDEF = -Wl,--no-undefined
QMAKE_LFLAGS_RPATH = -Wl,-rpath=
QMAKE_LFLAGS_RPATHLINK = -Wl,-rpath-link=
QMAKE_LIBS_PRIVATE = $$ANDROID_CXX_STL_LIBS -llog -lz -lm -ldl -lc
QMAKE_LIBS_X11 =
QMAKE_LIBS_THREAD =
QMAKE_LIBS_EGL = -lEGL
QMAKE_LIBS_OPENGL =
QMAKE_LIBS_OPENGL_ES2 = -lGLESv2
!exists($$NDK_ROOT): error("You need to set the ANDROID_NDK_ROOT environment variable to point to your Android NDK.")
load(qt_config)

View File

@ -16,17 +16,22 @@ APK_PATH = $$shell_path($$OUT_PWD/android-build/$${TARGET}.apk)
}
QMAKE_EXTRA_TARGETS *= apk apk_install_target
contains(TEMPLATE, ".*app") {
!android_app {
!contains(TARGET, ".so"): TARGET = lib$${TARGET}.so
QMAKE_LFLAGS += -Wl,-soname,$$shell_quote($$TARGET)
build_pass {
contains(TEMPLATE, ".*app") {
!android_app {
!contains(TARGET, ".so") {
single_arch:TARGET = lib$${TARGET}.so
else:TARGET = lib$${TARGET}_$${QT_ARCH}.so
}
QMAKE_LFLAGS += -Wl,-soname,$$shell_quote($$TARGET)
android_install {
target.path=/libs/$$ANDROID_TARGET_ARCH/
INSTALLS *= target
android_install {
target.path=/libs/$$ANDROID_TARGET_ARCH/
INSTALLS *= target
}
}
} else: contains(TEMPLATE, "lib"):!static:!QTDIR_build:android_install {
target.path = /libs/$$ANDROID_TARGET_ARCH/
INSTALLS *= target
}
} else: contains(TEMPLATE, "lib"):!static:!QTDIR_build:android_install {
target.path = /libs/$$ANDROID_TARGET_ARCH/
INSTALLS *= target
}

View File

@ -17,32 +17,21 @@ contains(TEMPLATE, ".*app"):!build_pass:!android-embedded {
isEmpty(NDK_ROOT): NDK_ROOT = $$DEFAULT_ANDROID_NDK_ROOT
FILE_CONTENT += " \"ndk\": $$emitString($$NDK_ROOT),"
equals(ANDROID_USE_LLVM, true) {
FILE_CONTENT += " \"toolchain-prefix\": \"llvm\","
FILE_CONTENT += " \"tool-prefix\": \"llvm\","
} else {
NDK_TOOLCHAIN_PREFIX = $$(ANDROID_NDK_TOOLCHAIN_PREFIX)
isEmpty(NDK_TOOLCHAIN_PREFIX) {
equals(ANDROID_TARGET_ARCH, x86): NDK_TOOLCHAIN_PREFIX = x86
else: equals(ANDROID_TARGET_ARCH, x86_64): NDK_TOOLCHAIN_PREFIX = x86_64
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): NDK_TOOLCHAIN_PREFIX = aarch64-linux-android
else: NDK_TOOLCHAIN_PREFIX = arm-linux-androideabi
}
FILE_CONTENT += " \"toolchain-prefix\": $$emitString($$NDK_TOOLCHAIN_PREFIX),"
FILE_CONTENT += " \"tool-prefix\": $$emitString($$NDK_TOOLS_PREFIX),"
}
NDK_TOOLCHAIN_VERSION = $$(ANDROID_NDK_TOOLCHAIN_VERSION)
isEmpty(NDK_TOOLCHAIN_VERSION): NDK_TOOLCHAIN_VERSION = $$DEFAULT_ANDROID_NDK_TOOLCHAIN_VERSION
FILE_CONTENT += " \"toolchain-version\": $$emitString($$NDK_TOOLCHAIN_VERSION),"
FILE_CONTENT += " \"toolchain-prefix\": \"llvm\","
FILE_CONTENT += " \"tool-prefix\": \"llvm\","
NDK_HOST = $$(ANDROID_NDK_HOST)
isEmpty(NDK_HOST): NDK_HOST = $$DEFAULT_ANDROID_NDK_HOST
FILE_CONTENT += " \"ndk-host\": $$emitString($$NDK_HOST),"
ANDROID_TARGET_ARCH = $$(ANDROID_TARGET_ARCH)
isEmpty(ANDROID_TARGET_ARCH): ANDROID_TARGET_ARCH = $$DEFAULT_ANDROID_TARGET_ARCH
FILE_CONTENT += " \"target-architecture\": $$emitString($$ANDROID_TARGET_ARCH),"
for (arch, ANDROID_ABIS) {
equals(arch, x86): libs_arch = i686-linux-android
else: equals(arch, x86_64): libs_arch = x86_64-linux-android
else: equals(arch, arm64-v8a): libs_arch = aarch64-linux-android
else: libs_arch = arm-linux-androideabi
ARCHS += "$$emitString($$arch):$$emitString($$libs_arch)"
}
FILE_CONTENT += " \"architectures\": {$$join(ARCHS,", ")},"
# Explicitly set qt dependencies of application for deployment
!isEmpty(ANDROID_DEPLOYMENT_DEPENDENCIES): \
@ -74,9 +63,8 @@ contains(TEMPLATE, ".*app"):!build_pass:!android-embedded {
QML_ROOT_PATH = $$_PRO_FILE_PWD_
FILE_CONTENT += " \"qml-root-path\": $$emitString($$QML_ROOT_PATH),"
FILE_CONTENT += " \"stdcpp-path\": $$emitString($$ANDROID_STDCPP_PATH),"
FILE_CONTENT += " \"useLLVM\": $$ANDROID_USE_LLVM,"
FILE_CONTENT += " \"application-binary\": $$emitString($$absolute_path($$DESTDIR, $$OUT_PWD)/$$TARGET)"
FILE_CONTENT += ""
FILE_CONTENT += " \"application-binary\": $$emitString($$TARGET)"
FILE_CONTENT += "}"
isEmpty(ANDROID_DEPLOYMENT_SETTINGS_FILE): ANDROID_DEPLOYMENT_SETTINGS_FILE = $$OUT_PWD/android-$$TARGET-deployment-settings.json

View File

@ -0,0 +1,76 @@
load(default_pre)
build_pass:armeabi-v7a {
QT_ARCH = armeabi-v7a
} else:build_pass:arm64-v8a {
QT_ARCH = arm64-v8a
} else:build_pass:x86 {
QT_ARCH = x86
} else:build_pass:x86_64 {
QT_ARCH = x86_64
} else {
# default architecture
QT_ARCH = arm64-v8a
}
DEFAULT_ANDROID_TARGET_ARCH=$${QT_ARCH}
ANDROID_TARGET_ARCH = $$(ANDROID_TARGET_ARCH)
isEmpty(ANDROID_TARGET_ARCH): ANDROID_TARGET_ARCH = $$DEFAULT_ANDROID_TARGET_ARCH
# Follow https://android.googlesource.com/platform/ndk/+/ndk-release-r20/docs/BuildSystemMaintainers.md
equals(ANDROID_TARGET_ARCH, armeabi-v7a): \
QMAKE_CFLAGS = -target armv7a-linux-androideabi$$replace(ANDROID_PLATFORM, "android-", "")
else: equals(ANDROID_TARGET_ARCH, arm64-v8a): \
QMAKE_CFLAGS = -target aarch64-linux-android$$replace(ANDROID_PLATFORM, "android-", "")
else: equals(ANDROID_TARGET_ARCH, x86): \
QMAKE_CFLAGS = -target i686-linux-android$$replace(ANDROID_PLATFORM, "android-", "") -mstackrealign
else: equals(ANDROID_TARGET_ARCH, x86_64): \
QMAKE_CFLAGS = -target x86_64-linux-android$$replace(ANDROID_PLATFORM, "android-", "")
QMAKE_CFLAGS += -fno-limit-debug-info
QMAKE_LINK = $$QMAKE_CXX $$QMAKE_CFLAGS
ANDROID_STDCPP_PATH = $$NDK_LLVM_PATH/sysroot/usr/lib/
# -fstack-protector-strong offers good protection against stack smashing attacks.
# It is (currently) enabled only on Android because we know for sure that Android compilers supports it
QMAKE_CFLAGS += -fPIC -fstack-protector-strong -DANDROID
equals(ANDROID_TARGET_ARCH, armeabi-v7a) | equals(ANDROID_TARGET_ARCH, armeabi) {
CONFIG += optimize_size
QMAKE_CFLAGS_DEBUG = -g -marm -O0
QMAKE_CFLAGS_RELEASE += -mthumb
QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO += -mthumb
}
QMAKE_CXXFLAGS_RELEASE_WITH_DEBUGINFO = $$QMAKE_CFLAGS_RELEASE_WITH_DEBUGINFO
QMAKE_CXXFLAGS = $$QMAKE_CFLAGS
QMAKE_CXXFLAGS_WARN_ON = $$QMAKE_CFLAGS_WARN_ON
QMAKE_CXXFLAGS_WARN_OFF = $$QMAKE_CFLAGS_WARN_OFF
QMAKE_CXXFLAGS_RELEASE = $$QMAKE_CFLAGS_RELEASE
QMAKE_CXXFLAGS_DEBUG = $$QMAKE_CFLAGS_DEBUG
QMAKE_CXXFLAGS_SHLIB = $$QMAKE_CFLAGS_SHLIB
QMAKE_CXXFLAGS_YACC = $$QMAKE_CFLAGS_YACC
QMAKE_CXXFLAGS_THREAD = $$QMAKE_CFLAGS_THREAD
QMAKE_LIBS_EGL = -lEGL
QMAKE_LIBS_OPENGL_ES2 = -lGLESv2
# modifications to linux.conf
QMAKE_AR = $${CROSS_COMPILE}ar cqs
QMAKE_OBJCOPY = $${CROSS_COMPILE}objcopy
QMAKE_NM = $${CROSS_COMPILE}nm -P
QMAKE_STRIP =
#$${CROSS_COMPILE}strip
QMAKE_RANLIB = $${CROSS_COMPILE}ranlib
QMAKE_LINK_SHLIB = $$QMAKE_LINK
QMAKE_LFLAGS =
QMAKE_LIBS_PRIVATE = -llog -lz -lm -ldl -lc

View File

@ -0,0 +1,10 @@
load(resolve_config)
!host_build:!single_arch:!java:android {
isEmpty(ANDROID_ABIS): ANDROID_ABIS = $$ALL_ANDROID_ABIS
ALL_ABIS = $$join(ANDROID_ABIS, _and_)
CONFIG += $$ALL_ABIS build_all
addExclusiveBuildsProper($$ALL_ABIS, $$ANDROID_ABIS)
unset(ALL_ABIS)
}

View File

@ -1,4 +1,6 @@
load(qt_functions)
contains(TEMPLATE, subdirs) {
for(build, QMAKE_EXCLUSIVE_BUILDS) {
prepareRecursiveTarget($$build)

View File

@ -22,7 +22,11 @@ for(ever) {
!defined(QMAKE_LIBS_$$nu, var): \
error("Library '$$lower($$replace(nu, _, -))' is not defined.")
debug: \
android {
ABI_LIBS = $$eval(QMAKE_LIBS_$${nu}_$${QT_ARCH})
isEmpty(ABI_LIBS): ABI_LIBS = $$eval(QMAKE_LIBS_$${nu})
LIBS$${suffix} += $$ABI_LIBS
} else: debug: \
LIBS$${suffix} += $$eval(QMAKE_LIBS_$${nu}_DEBUG) $$eval(QMAKE_LIBS_$$nu)
else: \
LIBS$${suffix} += $$eval(QMAKE_LIBS_$${nu}_RELEASE) $$eval(QMAKE_LIBS_$$nu)

View File

@ -16,7 +16,7 @@
ANDROID_DEPENDS_DIR = $$MODULE_BASE_OUTDIR/lib/
DEPENDENCY_FILE = $$ANDROID_DEPENDS_DIR$$TARGET-android-dependencies.xml
!build_pass {
build_pass:!isEmpty(QT_ARCH): {
!isEmpty(MODULE_PLUGIN_TYPES) {
for(PLUGIN_TYPE, MODULE_PLUGIN_TYPES) {
ANDROID_BUNDLED_FILES += "plugins/$$PLUGIN_TYPE"
@ -46,6 +46,8 @@ DEPENDENCY_FILE = $$ANDROID_DEPENDS_DIR$$TARGET-android-dependencies.xml
EXTENDS = $$section(LIB_FILE, ":", 1, 1)
!isEmpty(EXTENDS): EXTENDS = "extends=\"$$EXTENDS\""
LIB_FILE = $$section(LIB_FILE, ":", 0, 0)
LIB_FILE = $$replace(LIB_FILE,".so", "_$${QT_ARCH}.so")
!isEmpty(EXTENDS): EXTENDS = $$replace(EXTENDS,".so", "_$${QT_ARCH}.so")
FILE_CONTENT += "<lib file=\"$$LIB_FILE\" $$EXTENDS />"
}
}
@ -54,12 +56,14 @@ DEPENDENCY_FILE = $$ANDROID_DEPENDS_DIR$$TARGET-android-dependencies.xml
for(REPLACEMENT, ANDROID_LIB_DEPENDENCY_REPLACEMENTS) {
REPLACEMENT_FILE = $$section(REPLACEMENT, ":", 0, 0)
LIB_FILE = $$section(REPLACEMENT, ":", 1, 1)
REPLACEMENT_FILE = $$replace(REPLACEMENT_FILE,".so", "_$${QT_ARCH}.so")
FILE_CONTENT += "<lib file=\"$$LIB_FILE\" replaces=\"$$REPLACEMENT_FILE\" />"
}
}
!isEmpty(ANDROID_BUNDLED_FILES) {
for (BUNDLED_FILE, ANDROID_BUNDLED_FILES) {
BUNDLED_FILE = $$replace(BUNDLED_FILE,".so", "_$${QT_ARCH}.so")
FILE_CONTENT += "<bundled file=\"$$BUNDLED_FILE\" />"
}
}

View File

@ -560,7 +560,7 @@ defineTest(qtConfResolveLibs) {
} else {
paths += $$lp
}
} else: contains(l, "^-l.*") {
} else: !android: contains(l, "^-l.*") {
lib = $$replace(l, "^-l", )
lcan =
integrity:contains(lib, "^.*\\.a") {

View File

@ -1,7 +1,8 @@
defineReplace(qtPlatformTargetSuffix) {
suffix =
CONFIG(debug, debug|release) {
android: return($${suffix}_$${QT_ARCH})
else: CONFIG(debug, debug|release) {
!debug_and_release|build_pass {
mac: return($${suffix}_debug)
win32: return($${suffix}d)

View File

@ -29,19 +29,19 @@ DLLDESTDIR = $$MODULE_BASE_OUTDIR/bin
THE_TARGET = $$qt5LibraryTarget($$TARGET)
!build_pass {
MODULE = $$replace(TARGET, ^qt, )
MODULE ~= s,-,_,
MODULE_PRI = $$MODULE_QMAKE_OUTDIR/mkspecs/modules/qt_ext_$${MODULE}.pri
ucmodule = $$upper($$MODULE)
MODULE = $$replace(TARGET, ^qt, )
MODULE ~= s,-,_,
MODULE_PRI = $$MODULE_QMAKE_OUTDIR/mkspecs/modules/qt_ext_$${MODULE}.pri
ucmodule = $$upper($$MODULE)
win32|CONFIG(static, static|shared) {
prefix = $$QMAKE_PREFIX_STATICLIB
suffix = $$QMAKE_EXTENSION_STATICLIB
} else {
prefix = $$QMAKE_PREFIX_SHLIB
suffix = $$QMAKE_EXTENSION_SHLIB
}
win32|CONFIG(static, static|shared) {
prefix = $$QMAKE_PREFIX_STATICLIB
suffix = $$QMAKE_EXTENSION_STATICLIB
} else {
prefix = $$QMAKE_PREFIX_SHLIB
suffix = $$QMAKE_EXTENSION_SHLIB
}
!build_pass {
CC_USES =
LD_USES =
for (use, QMAKE_USE) {
@ -58,7 +58,9 @@ THE_TARGET = $$qt5LibraryTarget($$TARGET)
"QMAKE_DEPENDS_$${ucmodule}_LD =$$join(LD_USES, " ", " ")" \
"QMAKE_INCDIR_$${ucmodule} = $$val_escape(MODULE_INCLUDEPATH)" \
"QMAKE_DEFINES_$${ucmodule} = $$val_escape(MODULE_DEFINES)"
debug_and_release {
android {
MODULE_PRI_CONT += "QMAKE_LIBS_$${ucmodule} ="
} else: debug_and_release {
win32: \
MODULE_DEBUG_LIBS = $$DESTDIR/$$prefix$${TARGET}d.$$suffix
else: darwin: \
@ -76,6 +78,11 @@ THE_TARGET = $$qt5LibraryTarget($$TARGET)
"QMAKE_LIBS_$${ucmodule} = $$val_escape(MODULE_LIBS)"
}
write_file($$MODULE_PRI, MODULE_PRI_CONT)|error()
} else: android {
ABI_TARGET = $$qt5LibraryTarget($$TARGET)
ABI_MODULE_LIBS = $$DESTDIR/$$prefix$${ABI_TARGET}.$$suffix
MODULE_PRI_CONT = "QMAKE_LIBS_$${ucmodule}_$${QT_ARCH} = $$val_escape(ABI_MODULE_LIBS)"
write_file($$MODULE_PRI, MODULE_PRI_CONT, append)|error()
}
TARGET = $$THE_TARGET

View File

@ -93,7 +93,7 @@ header_module {
DESTDIR = $$MODULE_BASE_OUTDIR/lib
DLLDESTDIR = $$MODULE_BASE_OUTDIR/bin
CONFIG += qmake_cache target_qt
CONFIG += target_qt
QMAKE_DOCS_TARGETDIR = qt$${MODULE}

View File

@ -51,13 +51,12 @@ defineReplace(qtGetExportsForModule) {
return($$result)
}
defineReplace(qtExportLibsForModule) {
defineReplace(qtExportDepsForModule) {
result =
for (lib, QT.$${1}.libraries) {
NAME = $$upper($$lib)
vars = \
QMAKE_DEPENDS_$${NAME}_CC QMAKE_DEPENDS_$${NAME}_LD \
QMAKE_LIBS_$$NAME QMAKE_LIBS_$${NAME}_DEBUG QMAKE_LIBS_$${NAME}_RELEASE \
QMAKE_DEFINES_$$NAME QMAKE_INCDIR_$$NAME
for (var, vars) {
expvar = $$var
@ -71,6 +70,24 @@ defineReplace(qtExportLibsForModule) {
return($$result)
}
defineReplace(qtExportLibsForModule) {
result =
for (lib, QT.$${1}.libraries) {
NAME = $$upper($$lib)
vars = \
QMAKE_LIBS_$$NAME QMAKE_LIBS_$${NAME}_DEBUG QMAKE_LIBS_$${NAME}_RELEASE
for (var, vars) {
expvar = $$var
expvar ~= s/^QMAKE_/QMAKE_EXPORT_/
defined($$expvar, var):equals($$expvar, -): next()
!defined($$expvar, var): expvar = $$var
defined($$expvar, var): \
result += "$$var$${2} = $$val_escape($$expvar)"
}
}
return($$result)
}
!build_pass {
# Create a module .pri file
@ -160,6 +177,7 @@ defineReplace(qtExportLibsForModule) {
"QT.$${MODULE}_private.module_config =$$join(module_build_type, " ", " ")" \
$$qtGetFeaturesForModule($${MODULE}_private) \
"" \
$$qtExportDepsForModule($${MODULE}_private) \
$$qtExportLibsForModule($${MODULE}_private)
write_file($$MODULE_PRIVATE_PRI, MODULE_PRIVATE_PRI_CONT)|error()
}
@ -220,7 +238,10 @@ defineReplace(qtExportLibsForModule) {
}
cache(QT_MODULES, transient)
} # !build_pass
} else:android:!no_private_module:!internal_module {
MODULE_PRIVATE_PRI_CONT = $$qtExportLibsForModule($${MODULE}_private, _$${QT_ARCH})
write_file($$MODULE_PRIVATE_PRI, MODULE_PRIVATE_PRI_CONT, append)|error()
}
# Schedule the regular .pri file for installation
CONFIG += qt_install_module

View File

@ -771,20 +771,6 @@ MakefileGenerator::init()
QMakeSourceFileInfo::setDependencyPaths(deplist);
debug_msg(1, "Dependency Directories: %s",
incDirs.join(QString(" :: ")).toLatin1().constData());
//cache info
if(project->isActiveConfig("qmake_cache")) {
QString cache_file;
if(!project->isEmpty("QMAKE_INTERNAL_CACHE_FILE")) {
cache_file = QDir::fromNativeSeparators(project->first("QMAKE_INTERNAL_CACHE_FILE").toQString());
} else {
cache_file = ".qmake.internal.cache";
if(project->isActiveConfig("build_pass"))
cache_file += ".BUILD." + project->first("BUILD_PASS");
}
if(cache_file.indexOf('/') == -1)
cache_file.prepend(Option::output_dir + '/');
QMakeSourceFileInfo::setCacheFile(cache_file);
}
//add to dependency engine
for(x = 0; x < compilers.count(); ++x) {

View File

@ -60,8 +60,6 @@ QT_BEGIN_NAMESPACE
inline bool qmake_endOfLine(const char &c) { return (c == '\r' || c == '\n'); }
#endif
//#define QMAKE_USE_CACHE
QMakeLocalFileName::QMakeLocalFileName(const QString &name) : is_null(name.isNull())
{
if(!name.isEmpty()) {
@ -265,19 +263,10 @@ QMakeSourceFileInfo::QMakeSourceFileInfo(const QString &cf)
//buffer
spare_buffer = nullptr;
spare_buffer_size = 0;
//cache
cachefile = cf;
if(!cachefile.isEmpty())
loadCache(cachefile);
}
QMakeSourceFileInfo::~QMakeSourceFileInfo()
{
//cache
if(!cachefile.isEmpty() /*&& files_changed*/)
saveCache(cachefile);
//buffer
if(spare_buffer) {
free(spare_buffer);
@ -290,12 +279,6 @@ QMakeSourceFileInfo::~QMakeSourceFileInfo()
delete includes;
}
void QMakeSourceFileInfo::setCacheFile(const QString &cf)
{
cachefile = cf;
loadCache(cachefile);
}
void QMakeSourceFileInfo::addSourceFiles(const ProStringList &l, uchar seek,
QMakeSourceFileInfo::SourceFileType type)
{
@ -1054,151 +1037,4 @@ bool QMakeSourceFileInfo::findMocs(SourceFile *file)
return true;
}
void QMakeSourceFileInfo::saveCache(const QString &cf)
{
#ifdef QMAKE_USE_CACHE
if(cf.isEmpty())
return;
QFile file(QMakeLocalFileName(cf).local());
if(file.open(QIODevice::WriteOnly)) {
QTextStream stream(&file);
stream << QMAKE_VERSION_STR << endl << endl; //version
{ //cache verification
QMap<QString, QStringList> verify = getCacheVerification();
stream << verify.count() << endl;
for(QMap<QString, QStringList>::iterator it = verify.begin();
it != verify.end(); ++it) {
stream << it.key() << endl << it.value().join(';') << endl;
}
stream << endl;
}
if(files->nodes) {
for(int file = 0; file < files->num_nodes; ++file) {
for(SourceFiles::SourceFileNode *node = files->nodes[file]; node; node = node->next) {
stream << node->file->file.local() << endl; //source
stream << node->file->type << endl; //type
//depends
stream << ";";
if(node->file->deps) {
for(int depend = 0; depend < node->file->deps->used_nodes; ++depend) {
if(depend)
stream << ";";
stream << node->file->deps->children[depend]->file.local();
}
}
stream << endl;
stream << node->file->mocable << endl; //mocable
stream << endl; //just for human readability
}
}
}
stream.flush();
file.close();
}
#else
Q_UNUSED(cf);
#endif
}
void QMakeSourceFileInfo::loadCache(const QString &cf)
{
if(cf.isEmpty())
return;
#ifdef QMAKE_USE_CACHE
QMakeLocalFileName cache_file(cf);
int fd = open(QMakeLocalFileName(cf).local().toLatin1(), O_RDONLY);
if(fd == -1)
return;
QFileInfo cache_fi = findFileInfo(cache_file);
if(!cache_fi.exists() || cache_fi.isDir())
return;
QFile file;
if (!file.open(fd, QIODevice::ReadOnly))
return;
QTextStream stream(&file);
if (stream.readLine() == QMAKE_VERSION_STR) { //version check
stream.skipWhiteSpace();
bool verified = true;
{ //cache verification
QMap<QString, QStringList> verify;
int len = stream.readLine().toInt();
for(int i = 0; i < len; ++i) {
QString var = stream.readLine();
QString val = stream.readLine();
verify.insert(var, val.split(';', QString::SkipEmptyParts));
}
verified = verifyCache(verify);
}
if(verified) {
stream.skipWhiteSpace();
if(!files)
files = new SourceFiles;
while(!stream.atEnd()) {
QString source = stream.readLine();
QString type = stream.readLine();
QString depends = stream.readLine();
QString mocable = stream.readLine();
stream.skipWhiteSpace();
QMakeLocalFileName fn(source);
QFileInfo fi = findFileInfo(fn);
SourceFile *file = files->lookupFile(fn);
if(!file) {
file = new SourceFile;
file->file = fn;
files->addFile(file);
file->type = (SourceFileType)type.toInt();
file->exists = fi.exists();
}
if(fi.exists() && fi.lastModified() < cache_fi.lastModified()) {
if(!file->dep_checked) { //get depends
if(!file->deps)
file->deps = new SourceDependChildren;
file->dep_checked = true;
QStringList depend_list = depends.split(";", QString::SkipEmptyParts);
for(int depend = 0; depend < depend_list.size(); ++depend) {
QMakeLocalFileName dep_fn(depend_list.at(depend));
QFileInfo dep_fi(findFileInfo(dep_fn));
SourceFile *dep = files->lookupFile(dep_fn);
if(!dep) {
dep = new SourceFile;
dep->file = dep_fn;
dep->exists = dep_fi.exists();
dep->type = QMakeSourceFileInfo::TYPE_UNKNOWN;
files->addFile(dep);
}
dep->included_count++;
file->deps->addChild(dep);
}
}
if(!file->moc_checked) { //get mocs
file->moc_checked = true;
file->mocable = mocable.toInt();
}
}
}
}
}
#endif
}
QMap<QString, QStringList> QMakeSourceFileInfo::getCacheVerification()
{
return QMap<QString, QStringList>();
}
bool QMakeSourceFileInfo::verifyCache(const QMap<QString, QStringList> &v)
{
return v == getCacheVerification();
}
QT_END_NAMESPACE

View File

@ -79,9 +79,6 @@ private:
bool findDeps(SourceFile *);
void dependTreeWalker(SourceFile *, SourceDependChildren *);
//cache
QString cachefile;
protected:
virtual QMakeLocalFileName fixPathForFile(const QMakeLocalFileName &, bool forOpen=false);
virtual QMakeLocalFileName findFileForDep(const QMakeLocalFileName &, const QMakeLocalFileName &);
@ -114,12 +111,6 @@ public:
bool mocable(const QString &file);
virtual QMap<QString, QStringList> getCacheVerification();
virtual bool verifyCache(const QMap<QString, QStringList> &);
void setCacheFile(const QString &cachefile); //auto caching
void loadCache(const QString &cf);
void saveCache(const QString &cf);
private:
DependencyMode dep_mode;
};

View File

@ -300,14 +300,17 @@ inline XmlOutput::xml_output valueTagT( const triState v)
return valueTag(v == _True ? "true" : "false");
}
static QString vcxCommandSeparator()
static QString commandLinesForOutput(QStringList commands)
{
// MSBuild puts the contents of the custom commands into a batch file and calls it.
// As we want every sub-command to be error-checked (as is done by makefile-based
// backends), we insert the checks ourselves, using the undocumented jump target.
static QString cmdSep =
QLatin1String("&#x000D;&#x000A;if errorlevel 1 goto VCEnd&#x000D;&#x000A;");
return cmdSep;
static QString errchk = QStringLiteral("if errorlevel 1 goto VCEnd");
for (int i = commands.count() - 2; i >= 0; --i) {
if (!commands.at(i).startsWith("rem", Qt::CaseInsensitive))
commands.insert(i + 1, errchk);
}
return commands.join('\n');
}
static QString unquote(const QString &value)
@ -1658,7 +1661,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCCustomBuildTool &tool)
{
xml << tag("Command")
<< attrTag("Condition", condition)
<< valueTag(tool.CommandLine.join(vcxCommandSeparator()));
<< valueTag(commandLinesForOutput(tool.CommandLine));
}
if ( !tool.Description.isEmpty() )
@ -1712,7 +1715,7 @@ void VCXProjectWriter::write(XmlOutput &xml, const VCEventTool &tool)
{
xml
<< tag(tool.EventName)
<< tag(_Command) << valueTag(tool.CommandLine.join(vcxCommandSeparator()))
<< tag(_Command) << valueTag(commandLinesForOutput(tool.CommandLine))
<< tag(_Message) << valueTag(tool.Description)
<< closetag(tool.EventName);
}

View File

@ -209,7 +209,9 @@ bool VcprojGenerator::writeProjectMakefile()
struct VcsolutionDepend {
QString uuid;
QString vcprojFile, orig_target, target;
QString vcprojFile;
QString projectName;
QString target;
Target targetType;
QStringList dependencies;
};
@ -433,7 +435,8 @@ ProStringList VcprojGenerator::collectDependencies(QMakeProject *proj, QHash<QSt
Option::qmake_mode = old_mode;
// We assume project filename is [QMAKE_PROJECT_NAME].vcproj
QString vcproj = tmp_vcproj.project->first("QMAKE_PROJECT_NAME") + project->first("VCPROJ_EXTENSION");
const ProString projectName = tmp_vcproj.project->first("QMAKE_PROJECT_NAME");
const QString vcproj = projectName + project->first("VCPROJ_EXTENSION");
QString vcprojDir = Option::output_dir;
// If file doesn't exsist, then maybe the users configuration
@ -445,14 +448,14 @@ ProStringList VcprojGenerator::collectDependencies(QMakeProject *proj, QHash<QSt
VcsolutionDepend *newDep = new VcsolutionDepend;
newDep->vcprojFile = vcprojDir + Option::dir_sep + vcproj;
newDep->orig_target = tmp_proj.first("QMAKE_ORIG_TARGET").toQString();
newDep->projectName = projectName.toQString();
newDep->target = tmp_proj.first("MSVCPROJ_TARGET").toQString().section(Option::dir_sep, -1);
newDep->targetType = tmp_vcproj.projectTarget;
newDep->uuid = tmp_proj.isEmpty("QMAKE_UUID") ? getProjectUUID(Option::fixPathToLocalOS(vcprojDir + QDir::separator() + vcproj)).toString().toUpper(): tmp_proj.first("QMAKE_UUID").toQString();
// We want to store it as the .lib name.
if (newDep->target.endsWith(".dll"))
newDep->target = newDep->target.left(newDep->target.length()-3) + "lib";
projGuids.insert(newDep->orig_target, newDep->target);
projGuids.insert(newDep->projectName, newDep->target);
if (tmpList.size()) {
const ProStringList depends = tmpList;
@ -591,7 +594,7 @@ void VcprojGenerator::writeSubDirs(QTextStream &t)
for (QList<VcsolutionDepend*>::Iterator it = solution_cleanup.begin(); it != solution_cleanup.end(); ++it) {
// ### quoting rules?
t << _slnProjectBeg << _slnMSVCvcprojGUID << _slnProjectMid
<< "\"" << (*it)->orig_target << "\", \"" << (*it)->vcprojFile
<< "\"" << (*it)->projectName << "\", \"" << (*it)->vcprojFile
<< "\", \"" << (*it)->uuid << "\"";
debug_msg(1, "Project %s has dependencies: %s", (*it)->target.toLatin1().constData(), (*it)->dependencies.join(" ").toLatin1().constData());
@ -937,6 +940,15 @@ void VcprojGenerator::initProject()
vcProject.SccProjectName = project->first("SCCPROJECTNAME").toQString();
vcProject.SccLocalPath = project->first("SCCLOCALPATH").toQString();
vcProject.flat_files = project->isActiveConfig("flat");
// Set up the full target path for target conflict checking.
const QChar slash = QLatin1Char('/');
QString destdir = QDir::fromNativeSeparators(var("DESTDIR"));
if (!destdir.endsWith(slash))
destdir.append(slash);
project->values("DEST_TARGET") = ProStringList(destdir
+ project->first("TARGET")
+ project->first("TARGET_EXT"));
}
void VcprojGenerator::initConfiguration()

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 Intel Corporation.
** Copyright (C) 2019 Intel Corporation.
** Copyright (C) 2015 Klarälvdalens Datakonsult AB, a KDAB Group company, info@kdab.com
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
@ -59,9 +59,6 @@
# define HAVE_PIPE2 1
# endif
#endif
#if defined(__FreeBSD__) && __FreeBSD__ >= 9
# include <sys/procdesc.h>
#endif
#if _POSIX_VERSION-0 >= 200809L || _XOPEN_VERSION-0 >= 500
# define HAVE_WAITID 1
@ -93,9 +90,11 @@
# endif
#endif
#ifndef FFD_ATOMIC_RELAXED
# include "forkfd_gcc.h"
#endif
#include "forkfd_atomic.h"
static int system_has_forkfd(void);
static int system_forkfd(int flags, pid_t *ppid, int *system);
static int system_forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage);
#define CHILDREN_IN_SMALL_ARRAY 16
#define CHILDREN_IN_BIG_ARRAY 256
@ -448,6 +447,37 @@ static void ignore_sigpipe()
#endif
}
#if defined(__GNUC__) && (!defined(__FreeBSD__) || __FreeBSD__ < 10)
__attribute((destructor, unused)) static void cleanup();
#endif
static void cleanup()
{
BigArray *array;
/* This function is not thread-safe!
* It must only be called when the process is shutting down.
* At shutdown, we expect no one to be calling forkfd(), so we don't
* need to be thread-safe with what is done there.
*
* But SIGCHLD might be delivered to any thread, including this one.
* There's no way to prevent that. The correct solution would be to
* cooperatively delete. We don't do that.
*/
if (ffd_atomic_load(&forkfd_status, FFD_ATOMIC_RELAXED) == 0)
return;
/* notify the handler that we're no longer in operation */
ffd_atomic_store(&forkfd_status, 0, FFD_ATOMIC_RELAXED);
/* free any arrays we might have */
array = ffd_atomic_load(&children.header.nextArray, FFD_ATOMIC_ACQUIRE);
while (array != NULL) {
BigArray *next = ffd_atomic_load(&array->header.nextArray, FFD_ATOMIC_ACQUIRE);
free(array);
array = next;
}
}
static void forkfd_initialize()
{
#if defined(HAVE_BROKEN_WAITID)
@ -489,44 +519,15 @@ static void forkfd_initialize()
ignore_sigpipe();
#endif
#ifndef __GNUC__
#ifdef __GNUC__
(void) cleanup; /* suppress unused static function warning */
#else
atexit(cleanup);
#endif
ffd_atomic_store(&forkfd_status, 1, FFD_ATOMIC_RELAXED);
}
#ifdef __GNUC__
__attribute((destructor, unused)) static void cleanup();
#endif
static void cleanup()
{
BigArray *array;
/* This function is not thread-safe!
* It must only be called when the process is shutting down.
* At shutdown, we expect no one to be calling forkfd(), so we don't
* need to be thread-safe with what is done there.
*
* But SIGCHLD might be delivered to any thread, including this one.
* There's no way to prevent that. The correct solution would be to
* cooperatively delete. We don't do that.
*/
if (ffd_atomic_load(&forkfd_status, FFD_ATOMIC_RELAXED) == 0)
return;
/* notify the handler that we're no longer in operation */
ffd_atomic_store(&forkfd_status, 0, FFD_ATOMIC_RELAXED);
/* free any arrays we might have */
array = ffd_atomic_load(&children.header.nextArray, FFD_ATOMIC_ACQUIRE);
while (array != NULL) {
BigArray *next = ffd_atomic_load(&array->header.nextArray, FFD_ATOMIC_ACQUIRE);
free(array);
array = next;
}
}
static int create_pipe(int filedes[], int flags)
{
int ret = -1;
@ -565,55 +566,6 @@ static int create_pipe(int filedes[], int flags)
return ret;
}
#if defined(FORKFD_NO_SPAWNFD) && defined(__FreeBSD__) && __FreeBSD__ >= 9
# if __FreeBSD__ == 9
/* PROCDESC is an optional feature in the kernel and wasn't enabled
* by default on FreeBSD 9. So we need to check for it at runtime. */
static ffd_atomic_int system_has_forkfd = FFD_ATOMIC_INIT(1);
# else
/* On FreeBSD 10, PROCDESC was enabled by default. On v11, it's not an option
* anymore and can't be disabled. */
static const int system_has_forkfd = 1;
# endif
static int system_forkfd(int flags, pid_t *ppid)
{
int ret;
pid_t pid;
pid = pdfork(&ret, PD_DAEMON);
if (__builtin_expect(pid == -1, 0)) {
# if __FreeBSD__ == 9
if (errno == ENOSYS) {
/* PROCDESC wasn't compiled into the kernel: don't try it again. */
ffd_atomic_store(&system_has_forkfd, 0, FFD_ATOMIC_RELAXED);
}
# endif
return -1;
}
if (pid == 0) {
/* child process */
return FFD_CHILD_PROCESS;
}
/* parent process */
if (flags & FFD_CLOEXEC)
fcntl(ret, F_SETFD, FD_CLOEXEC);
if (flags & FFD_NONBLOCK)
fcntl(ret, F_SETFL, fcntl(ret, F_GETFL) | O_NONBLOCK);
if (ppid)
*ppid = pid;
return ret;
}
#else
static const int system_has_forkfd = 0;
static int system_forkfd(int flags, pid_t *ppid)
{
(void)flags;
(void)ppid;
return -1;
}
#endif
#ifndef FORKFD_NO_FORKFD
/**
* @brief forkfd returns a file descriptor representing a child process
@ -661,11 +613,9 @@ int forkfd(int flags, pid_t *ppid)
int efd;
#endif
if (system_has_forkfd) {
ret = system_forkfd(flags, ppid);
if (system_has_forkfd)
return ret;
}
fd = system_forkfd(flags, ppid, &ret);
if (ret)
return fd;
(void) pthread_once(&forkfd_initialization, forkfd_initialize);
@ -790,7 +740,7 @@ int spawnfd(int flags, pid_t *ppid, const char *path, const posix_spawn_file_act
/* we can only do work if we have a way to start the child in stopped mode;
* otherwise, we have a major race condition. */
assert(!system_has_forkfd);
assert(!system_has_forkfd());
(void) pthread_once(&forkfd_initialization, forkfd_initialize);
@ -843,30 +793,13 @@ out:
#endif // _POSIX_SPAWN && !FORKFD_NO_SPAWNFD
int forkfd_wait(int ffd, forkfd_info *info, struct rusage *rusage)
int forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage)
{
struct pipe_payload payload;
int ret;
if (system_has_forkfd) {
#if defined(__FreeBSD__) && __FreeBSD__ >= 9
pid_t pid;
int status;
int options = WEXITED;
ret = pdgetpid(ffd, &pid);
if (ret == -1)
return ret;
ret = fcntl(ffd, F_GETFL);
if (ret == -1)
return ret;
options |= (ret & O_NONBLOCK) ? WNOHANG : 0;
ret = wait4(pid, &status, options, rusage);
if (ret != -1 && info)
convertStatusToForkfdInfo(status, info);
return ret == -1 ? -1 : 0;
#endif
}
if (system_has_forkfd())
return system_forkfd_wait(ffd, info, rusage);
ret = read(ffd, &payload, sizeof(payload));
if (ret == -1)
@ -886,3 +819,28 @@ int forkfd_close(int ffd)
{
return close(ffd);
}
#if defined(__FreeBSD__) && __FreeBSD__ >= 9
# include "forkfd_freebsd.c"
#else
int system_has_forkfd()
{
return 0;
}
int system_forkfd(int flags, pid_t *ppid, int *system)
{
(void)flags;
(void)ppid;
*system = 0;
return -1;
}
int system_forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage)
{
(void)ffd;
(void)info;
(void)rusage;
return -1;
}
#endif

View File

@ -1,6 +1,6 @@
/****************************************************************************
**
** Copyright (C) 2016 Intel Corporation.
** Copyright (C) 2019 Intel Corporation.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
@ -27,6 +27,7 @@
#include <fcntl.h>
#include <stdint.h>
#include <sys/wait.h>
#include <unistd.h> // to get the POSIX flags
#if _POSIX_SPAWN > 0
@ -48,7 +49,7 @@ struct forkfd_info {
};
int forkfd(int flags, pid_t *ppid);
int forkfd_wait(int ffd, forkfd_info *info, struct rusage *rusage);
int forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage);
int forkfd_close(int ffd);
#if _POSIX_SPAWN > 0

39
src/3rdparty/forkfd/forkfd_atomic.h vendored Normal file
View File

@ -0,0 +1,39 @@
/****************************************************************************
**
** Copyright (C) 2019 Intel Corporation.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#if !defined(FFD_ATOMIC_H) & !defined(FFD_ATOMIC_RELAXED)
#define FFD_ATOMIC_H
#if defined(__cplusplus) && __cplusplus >= 201103L
# include "forkfd_c11.h"
#elif defined(__STDC_VERSION__) && __STDC_VERSION__ >= 201112L
# include "forkfd_c11.h"
#elif defined(__GNUC__)
# include "forkfd_gcc.h"
#endif
#endif /* FFD_ATOMIC_h && FFD_ATOMIC_RELAXED */
#ifndef FFD_ATOMIC_RELAXED
# error "Could not determine atomics for this platform"
#endif

64
src/3rdparty/forkfd/forkfd_c11.h vendored Normal file
View File

@ -0,0 +1,64 @@
/****************************************************************************
**
** Copyright (C) 2019 Intel Corporation.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#ifndef FFD_ATOMIC_C11_H
#define FFD_ATOMIC_C11_H
/* atomics */
/* Using the C11 <stdatomic.h> header or C++11's <atomic>
*/
#if defined(__cplusplus)
# include <atomic>
# define ffd_atomic_pointer(type) std::atomic<type*>
# define FFD_ATOMIC_RELAXED std::memory_order_relaxed
# define FFD_ATOMIC_ACQUIRE std::memory_order_acquire
# define FFD_ATOMIC_RELEASE std::memory_order_release
// acq_rel & cst not necessary
typedef std::atomic_int ffd_atomic_int;
#else
# include <stdatomic.h>
# define ffd_atomic_pointer(type) _Atomic(type*)
# define FFD_ATOMIC_RELAXED memory_order_relaxed
# define FFD_ATOMIC_ACQUIRE memory_order_acquire
# define FFD_ATOMIC_RELEASE memory_order_release
// acq_rel & cst not necessary
typedef atomic_int ffd_atomic_int;
#endif
#define FFD_ATOMIC_INIT(val) ATOMIC_VAR_INIT(val)
#define ffd_atomic_load(ptr, order) \
atomic_load_explicit(ptr, order)
#define ffd_atomic_store(ptr, val, order) \
atomic_store_explicit(ptr, val, order)
#define ffd_atomic_exchange(ptr,val,order) \
atomic_exchange_explicit(ptr, val, order)
#define ffd_atomic_compare_exchange(ptr, expected, desired, order1, order2) \
atomic_compare_exchange_strong_explicit(ptr, expected, desired, order1, order2)
#define ffd_atomic_add_fetch(ptr, val, order) \
(atomic_fetch_add_explicit(ptr, val, order) + (val))
#endif

101
src/3rdparty/forkfd/forkfd_freebsd.c vendored Normal file
View File

@ -0,0 +1,101 @@
/****************************************************************************
**
** Copyright (C) 2019 Intel Corporation.
**
** Permission is hereby granted, free of charge, to any person obtaining a copy
** of this software and associated documentation files (the "Software"), to deal
** in the Software without restriction, including without limitation the rights
** to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
** copies of the Software, and to permit persons to whom the Software is
** furnished to do so, subject to the following conditions:
**
** The above copyright notice and this permission notice shall be included in
** all copies or substantial portions of the Software.
**
** THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
** IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
** FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
** AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
** LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
** OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
** THE SOFTWARE.
**
****************************************************************************/
#include "forkfd.h"
#include <sys/types.h>
#include <sys/procdesc.h>
#include "forkfd_atomic.h"
#if __FreeBSD__ >= 10
/* On FreeBSD 10, PROCDESC was enabled by default. On v11, it's not an option
* anymore and can't be disabled. */
static ffd_atomic_int system_forkfd_state = FFD_ATOMIC_INIT(1);
#else
static ffd_atomic_int system_forkfd_state = FFD_ATOMIC_INIT(0);
#endif
int system_has_forkfd()
{
return ffd_atomic_load(&system_forkfd_state, FFD_ATOMIC_RELAXED) > 0;
}
int system_forkfd(int flags, pid_t *ppid, int *system)
{
int ret;
pid_t pid;
int state = ffd_atomic_load(&system_forkfd_state, FFD_ATOMIC_RELAXED);
*system = 0;
if (state < 0)
return -1;
pid = pdfork(&ret, PD_DAEMON);
# if __FreeBSD__ == 9
if (state == 0 && pid != 0) {
/* Parent process: remember whether PROCDESC was compiled into the kernel */
state = (pid == -1 && errno == ENOSYS) ? -1 : 1;
ffd_atomic_store(&system_forkfd_state, state, FFD_ATOMIC_RELAXED);
}
if (state < 0)
return -1;
# endif
*system = 1;
if (__builtin_expect(pid == -1, 0))
return -1;
if (pid == 0) {
/* child process */
return FFD_CHILD_PROCESS;
}
/* parent process */
if (flags & FFD_CLOEXEC)
fcntl(ret, F_SETFD, FD_CLOEXEC);
if (flags & FFD_NONBLOCK)
fcntl(ret, F_SETFL, fcntl(ret, F_GETFL) | O_NONBLOCK);
if (ppid)
*ppid = pid;
return ret;
}
int system_forkfd_wait(int ffd, struct forkfd_info *info, struct rusage *rusage)
{
pid_t pid;
int status;
int options = WEXITED;
int ret = pdgetpid(ffd, &pid);
if (ret == -1)
return ret;
ret = fcntl(ffd, F_GETFL);
if (ret == -1)
return ret;
options |= (ret & O_NONBLOCK) ? WNOHANG : 0;
ret = wait4(pid, &status, options, rusage);
if (ret != -1 && info)
convertStatusToForkfdInfo(status, info);
return ret == -1 ? -1 : 0;
}

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-4.6-bin.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-5.5.1-bin.zip
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists

View File

@ -1,6 +1,7 @@
TARGET = QtAndroid
CONFIG += java
DESTDIR = $$[QT_INSTALL_PREFIX/get]/jar
PATHPREFIX = $$PWD/src/org/qtproject/qt5/android/

View File

@ -1,3 +1,5 @@
CONFIG += single_arch
CONFIG -= qt android_install
javaresources.files = \

View File

@ -1,5 +1,5 @@
/*
Copyright (c) 2016, BogDan Vatra <bogdan@kde.org>
Copyright (c) 2019, BogDan Vatra <bogdan@kde.org>
Contact: http://www.qt.io/licensing/
Commercial License Usage
@ -63,9 +63,12 @@ import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.lang.reflect.Array;
import java.lang.reflect.Method;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import dalvik.system.DexClassLoader;
@ -85,7 +88,6 @@ public abstract class QtLoader {
public static final String ENVIRONMENT_VARIABLES_KEY = "environment.variables";
public static final String APPLICATION_PARAMETERS_KEY = "application.parameters";
public static final String BUNDLED_LIBRARIES_KEY = "bundled.libraries";
public static final String QT_LIBS_RESOURCE_ID_KEY = "android.app.qt_libs_resource_id";
public static final String BUNDLED_IN_LIB_RESOURCE_ID_KEY = "android.app.bundled_in_lib_resource_id";
public static final String BUNDLED_IN_ASSETS_RESOURCE_ID_KEY = "android.app.bundled_in_assets_resource_id";
public static final String MAIN_LIBRARY_KEY = "main.library";
@ -153,7 +155,7 @@ public abstract class QtLoader {
// this repository is used to push a new release, and should be used to test your application.
// * unstable - unstable repository, DO NOT use this repository in production,
// this repository is used to push Qt snapshots.
public String[] m_qtLibs = null; // required qt libs
public ArrayList<String> m_qtLibs = null; // required qt libs
public int m_displayDensity = -1;
private ContextWrapper m_context;
protected ComponentInfo m_contextInfo;
@ -191,6 +193,36 @@ public abstract class QtLoader {
}
// Implement in subclass
private final List<String> supportedAbis = Arrays.asList(Build.SUPPORTED_ABIS);
private String preferredAbi = null;
private ArrayList<String> prefferedAbiLibs(String []libs)
{
HashMap<String, ArrayList<String>> abisLibs = new HashMap<>();
for (String lib : libs) {
String[] archLib = lib.split(";", 2);
if (preferredAbi != null && !archLib[0].equals(preferredAbi))
continue;
if (!abisLibs.containsKey(archLib[0]))
abisLibs.put(archLib[0], new ArrayList<String>());
abisLibs.get(archLib[0]).add(archLib[1]);
}
if (preferredAbi != null) {
if (abisLibs.containsKey(preferredAbi)) {
return abisLibs.get(preferredAbi);
}
return new ArrayList<String>();
}
for (String abi: supportedAbis) {
if (abisLibs.containsKey(abi)) {
preferredAbi = abi;
return abisLibs.get(abi);
}
}
return new ArrayList<String>();
}
// this function is used to load and start the loader
private void loadApplication(Bundle loaderParams)
@ -218,12 +250,14 @@ public abstract class QtLoader {
// add all bundled Qt libs to loader params
ArrayList<String> libs = new ArrayList<String>();
if (m_contextInfo.metaData.containsKey("android.app.bundled_libs_resource_id"))
libs.addAll(Arrays.asList(m_context.getResources().getStringArray(m_contextInfo.metaData.getInt("android.app.bundled_libs_resource_id"))));
if (m_contextInfo.metaData.containsKey("android.app.bundled_libs_resource_id")) {
int resourceId = m_contextInfo.metaData.getInt("android.app.bundled_libs_resource_id");
libs.addAll(prefferedAbiLibs(m_context.getResources().getStringArray(resourceId)));
}
String libName = null;
if (m_contextInfo.metaData.containsKey("android.app.lib_name")) {
libName = m_contextInfo.metaData.getString("android.app.lib_name");
libName = m_contextInfo.metaData.getString("android.app.lib_name") + "_" + preferredAbi;
loaderParams.putString(MAIN_LIBRARY_KEY, libName); //main library contains main() function
}
@ -278,7 +312,7 @@ public abstract class QtLoader {
try {
if (m_service != null) {
Bundle parameters = new Bundle();
parameters.putStringArray(REQUIRED_MODULES_KEY, m_qtLibs);
parameters.putStringArray(REQUIRED_MODULES_KEY, (String[]) m_qtLibs.toArray());
parameters.putString(APPLICATION_TITLE_KEY, getTitle());
parameters.putInt(MINIMUM_MINISTRO_API_KEY, MINISTRO_API_LEVEL);
parameters.putInt(MINIMUM_QT_VERSION_KEY, QT_VERSION);
@ -464,7 +498,8 @@ public abstract class QtLoader {
// why can't we load the plugins directly from libs ?!?!
String key = BUNDLED_IN_LIB_RESOURCE_ID_KEY;
if (m_contextInfo.metaData.containsKey(key)) {
String[] list = m_context.getResources().getStringArray(m_contextInfo.metaData.getInt(key));
int resourceId = m_contextInfo.metaData.getInt(key);
ArrayList<String> list = prefferedAbiLibs(m_context.getResources().getStringArray(resourceId));
for (String bundledImportBinary : list) {
String[] split = bundledImportBinary.split(":");
@ -603,7 +638,7 @@ public abstract class QtLoader {
if (m_contextInfo.metaData.containsKey("android.app.qt_libs_resource_id")) {
int resourceId = m_contextInfo.metaData.getInt("android.app.qt_libs_resource_id");
m_qtLibs = m_context.getResources().getStringArray(resourceId);
m_qtLibs = prefferedAbiLibs(m_context.getResources().getStringArray(resourceId));
}
if (m_contextInfo.metaData.containsKey("android.app.use_local_qt_libs")
@ -617,6 +652,7 @@ public abstract class QtLoader {
apkDeployFromSystem = true;
String libsDir = null;
String bundledLibsDir = null;
if (apkDeployFromSystem) {
String systemLibsPrefix = SYSTEM_LIB_PATH;
if (m_contextInfo.metaData.containsKey("android.app.system_libs_prefix")) {
@ -633,8 +669,11 @@ public abstract class QtLoader {
} else {
String nativeLibraryPrefix = m_context.getApplicationInfo().nativeLibraryDir + "/";
File nativeLibraryDir = new File(nativeLibraryPrefix);
if (nativeLibraryDir.exists() && nativeLibraryDir.isDirectory() && nativeLibraryDir.list().length > 0)
if (nativeLibraryDir.exists() && nativeLibraryDir.isDirectory() && nativeLibraryDir.list().length > 0) {
libsDir = nativeLibraryPrefix;
bundledLibsDir = nativeLibraryPrefix;
}
}
if (apkDeployFromSystem && libsDir == null)
@ -643,8 +682,8 @@ public abstract class QtLoader {
if (m_qtLibs != null) {
String libPrefix = libsDir + "lib";
for (int i = 0; i < m_qtLibs.length; i++)
libraryList.add(libPrefix + m_qtLibs[i] + ".so");
for (String lib : m_qtLibs)
libraryList.add(libPrefix + lib + ".so");
}
if (m_contextInfo.metaData.containsKey("android.app.bundle_local_qt_libs")
@ -654,22 +693,26 @@ public abstract class QtLoader {
String pluginsPrefix = dataPath + "qt-reserved-files/";
if (libsDir == null)
throw new Exception("");
throw new Exception("Invalid libsDir");
cleanOldCacheIfNecessary(dataPath, pluginsPrefix);
extractBundledPluginsAndImports(pluginsPrefix, libsDir);
if (m_contextInfo.metaData.containsKey(BUNDLED_IN_LIB_RESOURCE_ID_KEY)) {
String[] extraLibs = m_contextInfo.metaData.getString("android.app.load_local_libs").split(":");
for (String lib : extraLibs) {
if (!lib.isEmpty())
libraryList.add(pluginsPrefix + lib);
int resourceId = m_contextInfo.metaData.getInt("android.app.load_local_libs_resource_id");
for (String libs : prefferedAbiLibs(m_context.getResources().getStringArray(resourceId))) {
for (String lib : libs.split(":")) {
if (!lib.isEmpty())
libraryList.add(libsDir + lib);
}
}
}
ENVIRONMENT_VARIABLES += "\tQML2_IMPORT_PATH=" + pluginsPrefix + "/qml"
+ "\tQML_IMPORT_PATH=" + pluginsPrefix + "/imports"
+ "\tQT_PLUGIN_PATH=" + pluginsPrefix + "/plugins";
if (bundledLibsDir != null)
ENVIRONMENT_VARIABLES += "\tQT_BUNDLED_LIBS_PATH=" + bundledLibsDir;
}
Bundle loaderParams = new Bundle();

View File

@ -12,7 +12,7 @@
<supports-screens android:largeScreens="true" android:normalScreens="true" android:anyDensity="true" android:smallScreens="true"/>
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --">
<application android:hardwareAccelerated="true" android:name="org.qtproject.qt5.android.bindings.QtApplication" android:label="-- %%INSERT_APP_NAME%% --" android:extractNativeLibs="true">
<activity android:configChanges="orientation|uiMode|screenLayout|screenSize|smallestScreenSize|layoutDirection|locale|fontScale|keyboard|keyboardHidden|navigation|mcc|mnc|density"
android:name="org.qtproject.qt5.android.bindings.QtActivity"
android:label="-- %%INSERT_APP_NAME%% --"
@ -36,10 +36,11 @@
<meta-data android:name="android.app.bundle_local_qt_libs" android:value="-- %%BUNDLE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.bundled_in_lib_resource_id" android:resource="@array/bundled_in_lib"/>
<meta-data android:name="android.app.bundled_in_assets_resource_id" android:resource="@array/bundled_in_assets"/>
<!-- Run with local libs -->
<meta-data android:name="android.app.use_local_qt_libs" android:value="-- %%USE_LOCAL_QT_LIBS%% --"/>
<meta-data android:name="android.app.libs_prefix" android:value="/data/local/tmp/qt/"/>
<meta-data android:name="android.app.load_local_libs" android:value="-- %%INSERT_LOCAL_LIBS%% --"/>
<meta-data android:name="android.app.load_local_libs_resource_id" android:resource="@array/load_local_libs"/>
<meta-data android:name="android.app.load_local_jars" android:value="-- %%INSERT_LOCAL_JARS%% --"/>
<meta-data android:name="android.app.static_init_classes" android:value="-- %%INSERT_INIT_CLASSES%% --"/>
<!-- Used to specify custom system library path to run with local system libs -->

View File

@ -5,7 +5,7 @@ buildscript {
}
dependencies {
classpath 'com.android.tools.build:gradle:3.2.0'
classpath 'com.android.tools.build:gradle:3.5.0'
}
}

View File

@ -1,7 +1,7 @@
<?xml version='1.0' encoding='utf-8'?>
<resources>
<array name="qt_sources">
<item>https://download.qt.io/ministro/android/qt5/qt-5.9</item>
<item>https://download.qt.io/ministro/android/qt5/qt-5.14</item>
</array>
<!-- The following is handled automatically by the deployment tool. It should
@ -12,12 +12,17 @@
</array>
<array name="qt_libs">
<!-- %%INSERT_QT_LIBS%% -->
<!-- %%INSERT_QT_LIBS%% -->
</array>
<array name="bundled_in_lib">
<!-- %%INSERT_BUNDLED_IN_LIB%% -->
</array>
<array name="load_local_libs">
<!-- %%INSERT_LOCAL_LIBS%% -->
</array>
<array name="bundled_in_assets">
<!-- %%INSERT_BUNDLED_IN_ASSETS%% -->
</array>

View File

@ -1,3 +1,5 @@
CONFIG += single_arch
CONFIG -= qt android_install
templates.files = \

View File

@ -42,8 +42,10 @@
#include "qtextcodec_p.h"
#include "qutfcodec_p.h"
#include "qlatincodec_p.h"
#if QT_CONFIG(codecs)
#include "qtsciicodec_p.h"
#include "qisciicodec_p.h"
#endif
#include "qsimplecodec_p.h"
#include "private/qcoreglobaldata_p.h"
#include "qdebug.h"

View File

@ -12,6 +12,7 @@ CONFIG += qt_tracepoints
CONFIG += $$MODULE_CONFIG
DEFINES += $$MODULE_DEFINES
android: DEFINES += LIBS_SUFFIX='\\"_$${QT_ARCH}.so\\"'
DEFINES += QT_NO_USING_NAMESPACE QT_NO_FOREACH
msvc:equals(QT_ARCH, i386): QMAKE_LFLAGS += /BASE:0x67000000

View File

@ -37,37 +37,12 @@
**
****************************************************************************/
// these might be defined via precompiled headers
#include <QtCore/qatomic.h>
#include <QtCore/qglobal.h>
#define FORKFD_NO_SPAWNFD
#if defined(QT_NO_DEBUG) && !defined(NDEBUG)
# define NDEBUG
#endif
typedef QT_PREPEND_NAMESPACE(QBasicAtomicInt) ffd_atomic_int;
#define ffd_atomic_pointer(type) QT_PREPEND_NAMESPACE(QBasicAtomicPointer<type>)
QT_BEGIN_NAMESPACE
#define FFD_ATOMIC_INIT(val) Q_BASIC_ATOMIC_INITIALIZER(val)
#define FFD_ATOMIC_RELAXED Relaxed
#define FFD_ATOMIC_ACQUIRE Acquire
#define FFD_ATOMIC_RELEASE Release
#define FFD_CONCAT(x, y) x ## y
#define ffd_atomic_load(ptr,order) (ptr)->FFD_CONCAT(load, order)()
#define ffd_atomic_store(ptr,val,order) (ptr)->FFD_CONCAT(store, order)(val)
#define ffd_atomic_exchange(ptr,val,order) (ptr)->FFD_CONCAT(fetchAndStore, order)(val)
#define ffd_atomic_compare_exchange(ptr,expected,desired,order1,order2) \
(ptr)->FFD_CONCAT(testAndSet, order1)(*expected, desired, *expected)
#define ffd_atomic_add_fetch(ptr,val,order) ((ptr)->FFD_CONCAT(fetchAndAdd, order)(val) + val)
QT_END_NAMESPACE
extern "C" {
#include <forkfd.h>
#include "../../3rdparty/forkfd/forkfd.c"
}

View File

@ -1898,10 +1898,17 @@ bool QAbstractItemModel::clearItemData(const QModelIndex &index)
*/
bool QAbstractItemModel::setItemData(const QModelIndex &index, const QMap<int, QVariant> &roles)
{
bool b = true;
for (QMap<int, QVariant>::ConstIterator it = roles.begin(); it != roles.end(); ++it)
b = b && setData(index, it.value(), it.key());
return b;
// ### Qt 6: Consider change the semantics of this function,
// or deprecating/removing it altogether.
//
// For instance, it should try setting *all* the data
// in \a roles, and not bail out at the first setData that returns
// false. It should also have a transactional approach.
for (auto it = roles.begin(), e = roles.end(); it != e; ++it) {
if (!setData(index, it.value(), it.key()))
return false;
}
return true;
}
/*!

View File

@ -524,28 +524,6 @@ inline void QMetaCallEvent::allocArgs()
d.args_ = static_cast<void **>(memory);
}
/*!
\internal
Only used by QtDeclarative - to be removed when migrated.
*/
QMetaCallEvent::QMetaCallEvent(ushort method_offset, ushort method_relative,
QObjectPrivate::StaticMetaCallFunction callFunction,
const QObject *sender, int signalId,
int nargs, int *types_, void **args_)
: QAbstractMetaCallEvent(sender, signalId),
d({nullptr, nullptr, callFunction, nargs, method_offset, method_relative}),
prealloc_()
{
allocArgs();
for (int arg = 0; arg < nargs; ++arg) {
types()[arg] = types_[arg];
args()[arg] = args_[arg];
}
free(types_);
free(args_);
}
/*!
\internal

View File

@ -509,12 +509,6 @@ private:
class Q_CORE_EXPORT QMetaCallEvent : public QAbstractMetaCallEvent
{
public:
// kept for compatibility until QtDeclarative has moved over
QMetaCallEvent(ushort method_offset, ushort method_relative,
QObjectPrivate::StaticMetaCallFunction callFunction,
const QObject *sender, int signalId,
int nargs, int *types, void **args);
// blocking queued with semaphore - args always owned by caller
QMetaCallEvent(ushort method_offset, ushort method_relative,
QObjectPrivate::StaticMetaCallFunction callFunction,

View File

@ -52,6 +52,10 @@
# include <private/qcore_mac_p.h>
#endif
#ifdef Q_OS_ANDROID
# include <private/qjnihelpers_p.h>
#endif
QT_BEGIN_NAMESPACE
static QString qdlerror()
@ -96,6 +100,9 @@ QStringList QLibraryPrivate::suffixes_sys(const QString& fullVersion)
suffixes << QLatin1String(".so.%1").arg(fullVersion);
} else {
suffixes << QLatin1String(".so");
# ifdef Q_OS_ANDROID
suffixes << QStringLiteral(LIBS_SUFFIX);
# endif
}
#endif
# ifdef Q_OS_MAC
@ -157,9 +164,12 @@ bool QLibraryPrivate::load_sys()
// Do not unload the library during dlclose(). Consequently, the
// library's specific static variables are not reinitialized if the
// library is reloaded with dlopen() at a later time.
#if defined(RTLD_NODELETE) && !defined(Q_OS_ANDROID)
#if defined(RTLD_NODELETE)
if (loadHints & QLibrary::PreventUnloadHint) {
dlFlags |= RTLD_NODELETE;
# ifdef Q_OS_ANDROID // RTLD_NODELETE flag is supported by Android 23+
if (QtAndroidPrivate::androidSdkVersion() > 22)
# endif
dlFlags |= RTLD_NODELETE;
}
#endif
@ -219,7 +229,14 @@ bool QLibraryPrivate::load_sys()
} else {
attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix);
}
pHnd = dlopen(QFile::encodeName(attempt), dlFlags);
#ifdef Q_OS_ANDROID
if (!pHnd) {
auto attemptFromBundle = attempt;
pHnd = dlopen(QFile::encodeName(attemptFromBundle.replace(QLatin1Char('/'), QLatin1Char('_'))), dlFlags);
}
#endif
if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) {
// We only want to continue if dlopen failed due to that the shared library did not exist.

View File

@ -915,7 +915,7 @@ void QCborContainerPrivate::replaceAt_complex(Element &e, const QCborValue &valu
// in qstring.cpp
void qt_to_latin1_unchecked(uchar *dst, const ushort *uc, qsizetype len);
Q_NEVER_INLINE void QCborContainerPrivate::appendAsciiString(const QString &s)
Q_NEVER_INLINE void QCborContainerPrivate::appendAsciiString(QStringView s)
{
qsizetype len = s.size();
QtCbor::Element e;
@ -926,7 +926,7 @@ Q_NEVER_INLINE void QCborContainerPrivate::appendAsciiString(const QString &s)
char *ptr = data.data() + e.value + sizeof(ByteData);
uchar *l = reinterpret_cast<uchar *>(ptr);
const ushort *uc = (const ushort *)s.unicode();
const ushort *uc = (const ushort *)s.utf16();
qt_to_latin1_unchecked(l, uc, len);
}
@ -1646,13 +1646,23 @@ QCborValue::QCborValue(const QByteArray &ba)
container->ref.storeRelaxed(1);
}
#if QT_STRINGVIEW_LEVEL < 2
/*!
Creates a QCborValue with string value \a s. The value can later be
retrieved using toString().
\sa toString(), isString(), isByteArray()
*/
QCborValue::QCborValue(const QString &s)
QCborValue::QCborValue(const QString &s) : QCborValue(qToStringViewIgnoringNull(s)) {}
#endif
/*!
Creates a QCborValue with string value \a s. The value can later be
retrieved using toString().
\sa toString(), isString(), isByteArray()
*/
QCborValue::QCborValue(QStringView s)
: n(0), container(new QCborContainerPrivate), t(String)
{
container->append(s);

View File

@ -143,7 +143,10 @@ public:
QCborValue(QCborSimpleType st) : t(type_helper(st)) {}
QCborValue(const QByteArray &ba);
#if QT_STRINGVIEW_LEVEL < 2
QCborValue(const QString &s);
#endif
QCborValue(QStringView s);
QCborValue(QLatin1String s);
#ifndef QT_NO_CAST_FROM_ASCII
QT_ASCII_CAST_WARN QCborValue(const char *s) : QCborValue(QString::fromUtf8(s)) {}

View File

@ -245,13 +245,21 @@ public:
appendByteData(s.latin1(), s.size(), QCborValue::String,
QtCbor::Element::StringIsAscii);
}
void appendAsciiString(const QString &s);
void appendAsciiString(QStringView s);
#if QT_STRINGVIEW_LEVEL < 2
void append(const QString &s)
{
append(qToStringViewIgnoringNull(s));
}
#endif
void append(QStringView s)
{
if (QtPrivate::isAscii(s))
appendAsciiString(s);
else
appendByteData(reinterpret_cast<const char *>(s.constData()), s.size() * 2,
appendByteData(reinterpret_cast<const char *>(s.utf16()), s.size() * 2,
QCborValue::String, QtCbor::Element::StringIsUtf16);
}
void append(const QCborValue &v)
@ -345,33 +353,41 @@ public:
return e;
}
bool stringEqualsElement(qsizetype idx, QLatin1String s) const
static int compareUtf8(const QtCbor::ByteData *b, const QLatin1String &s)
{
const auto &e = elements.at(idx);
if (e.type != QCborValue::String)
return false;
const QtCbor::ByteData *b = byteData(idx);
if (!b)
return s.isEmpty();
if (e.flags & QtCbor::Element::StringIsUtf16)
return QtPrivate::compareStrings(b->asStringView(), s) == 0;
return QUtf8::compareUtf8(b->byte(), b->len, s) == 0;
return QUtf8::compareUtf8(b->byte(), b->len, s);
}
bool stringEqualsElement(qsizetype idx, const QString &s) const
{
const auto &e = elements.at(idx);
if (e.type != QCborValue::String)
return false;
const QtCbor::ByteData *b = byteData(idx);
static int compareUtf8(const QtCbor::ByteData *b, QStringView s)
{
return QUtf8::compareUtf8(b->byte(), b->len, s.data(), s.size());
}
template<typename String>
int stringCompareElement(const QtCbor::Element &e, String s) const
{
if (e.type != QCborValue::String)
return int(e.type) - int(QCborValue::String);
const QtCbor::ByteData *b = byteData(e);
if (!b)
return s.isEmpty();
return s.isEmpty() ? 0 : -1;
if (e.flags & QtCbor::Element::StringIsUtf16)
return QtPrivate::compareStrings(b->asStringView(), s) == 0;
return QUtf8::compareUtf8(b->byte(), b->len, s.data(), s.size()) == 0;
return QtPrivate::compareStrings(b->asStringView(), s);
return compareUtf8(b, s);
}
template<typename String>
bool stringEqualsElement(const QtCbor::Element &e, String s) const
{
return stringCompareElement(e, s) == 0;
}
template<typename String>
bool stringEqualsElement(qsizetype idx, String s) const
{
return stringEqualsElement(elements.at(idx), s);
}
static int compareElement_helper(const QCborContainerPrivate *c1, QtCbor::Element e1,

View File

@ -57,15 +57,6 @@
#include <string>
#include <iterator>
#if defined(Q_OS_ANDROID) && !defined(ANDROID_HAS_WSTRING)
// std::wstring is disabled on android's glibc, as bionic lacks certain features
// that libstdc++ checks for (like mbcslen).
namespace std
{
typedef basic_string<wchar_t> wstring;
}
#endif
#include <stdarg.h>
#ifdef truncate

View File

@ -108,20 +108,8 @@ Q_STATIC_ASSERT(sizeof(pthread_t) <= sizeof(Qt::HANDLE));
enum { ThreadPriorityResetFlag = 0x80000000 };
#if defined(Q_OS_LINUX) && defined(__GLIBC__) && (defined(Q_CC_GNU) || defined(Q_CC_INTEL)) && !defined(QT_LINUXBASE)
/* LSB doesn't have __thread, https://lsbbugs.linuxfoundation.org/show_bug.cgi?id=993 */
#define HAVE_TLS
#endif
#if defined(Q_CC_XLC) || defined (Q_CC_SUN)
#define HAVE_TLS
#endif
#if defined(Q_OS_RTEMS)
#define HAVE_TLS
#endif
#ifdef HAVE_TLS
static __thread QThreadData *currentThreadData = 0;
#endif
static thread_local QThreadData *currentThreadData = 0;
static pthread_once_t current_thread_data_once = PTHREAD_ONCE_INIT;
static pthread_key_t current_thread_data_key;
@ -182,28 +170,19 @@ Q_DESTRUCTOR_FUNCTION(destroy_current_thread_data_key)
// Utility functions for getting, setting and clearing thread specific data.
static QThreadData *get_thread_data()
{
#ifdef HAVE_TLS
return currentThreadData;
#else
pthread_once(&current_thread_data_once, create_current_thread_data_key);
return reinterpret_cast<QThreadData *>(pthread_getspecific(current_thread_data_key));
#endif
}
static void set_thread_data(QThreadData *data)
{
#ifdef HAVE_TLS
currentThreadData = data;
#endif
pthread_once(&current_thread_data_once, create_current_thread_data_key);
pthread_setspecific(current_thread_data_key, data);
}
static void clear_thread_data()
{
#ifdef HAVE_TLS
currentThreadData = 0;
#endif
pthread_setspecific(current_thread_data_key, 0);
}

View File

@ -390,7 +390,25 @@ QSize QSize::scaled(const QSize &s, Qt::AspectRatioMode mode) const noexcept
\sa expandedTo(), scale()
*/
/*!
\fn QSize QSize::grownBy(QMargins margins) const
\fn QSizeF QSizeF::grownBy(QMarginsF margins) const
\since 5.14
Returns the size that results from growing this size by \a margins.
\sa shrunkBy()
*/
/*!
\fn QSize QSize::shrunkBy(QMargins margins) const
\fn QSizeF QSizeF::shrunkBy(QMarginsF margins) const
\since 5.14
Returns the size that results from shrinking this size by \a margins.
\sa grownBy()
*/
/*****************************************************************************
QSize stream functions

View File

@ -41,6 +41,7 @@
#define QSIZE_H
#include <QtCore/qnamespace.h>
#include <QtCore/qmargins.h>
#if defined(Q_OS_DARWIN) || defined(Q_QDOC)
struct CGSize;
@ -74,6 +75,11 @@ public:
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize expandedTo(const QSize &) const noexcept;
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSize boundedTo(const QSize &) const noexcept;
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QSize grownBy(QMargins m) const noexcept
{ return {width() + m.left() + m.right(), height() + m.top() + m.bottom()}; }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QSize shrunkBy(QMargins m) const noexcept
{ return {width() - m.left() - m.right(), height() - m.top() - m.bottom()}; }
Q_DECL_RELAXED_CONSTEXPR inline int &rwidth() noexcept;
Q_DECL_RELAXED_CONSTEXPR inline int &rheight() noexcept;
@ -238,6 +244,11 @@ public:
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF expandedTo(const QSizeF &) const noexcept;
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR inline QSizeF boundedTo(const QSizeF &) const noexcept;
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QSizeF grownBy(QMarginsF m) const noexcept
{ return {width() + m.left() + m.right(), height() + m.top() + m.bottom()}; }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QSizeF shrunkBy(QMarginsF m) const noexcept
{ return {width() - m.left() - m.right(), height() - m.top() - m.bottom()}; }
Q_DECL_RELAXED_CONSTEXPR inline qreal &rwidth() noexcept;
Q_DECL_RELAXED_CONSTEXPR inline qreal &rheight() noexcept;

View File

@ -67,3 +67,6 @@ navigation.cppclassespage = "Qt GUI C++ Classes"
# Ignore warnings about undocumented enum values for the QGradient presets
spurious += "Undocumented enum item '.*' in QGradient::Preset"
# \svgcolor {#ffdead}
macro.svgcolor.HTML = "<div style=\"padding:10px;color:#fff;background:\1;\"></div>"

View File

@ -0,0 +1,86 @@
\table
\header
\li Name
\li Hex
\li Color
\row
\li Color0
\li #000000
\li \svgcolor {#000000}
\row
\li Color1
\li #ffffff
\li \svgcolor {#ffffff}
\row
\li Black
\li #000000
\li \svgcolor {#000000}
\row
\li White
\li #ffffff
\li \svgcolor {#ffffff}
\row
\li DarkGray
\li #808080
\li \svgcolor {#808080}
\row
\li Gray
\li #a0a0a4
\li \svgcolor {#a0a0a4}
\row
\li LightGray
\li #c0c0c0
\li \svgcolor {#c0c0c0}
\row
\li Red
\li #ff0000
\li \svgcolor {#ff0000}
\row
\li Green
\li #00ff00
\li \svgcolor {#00ff00}
\row
\li Blue
\li #0000ff
\li \svgcolor {#0000ff}
\row
\li Cyan
\li #00ffff
\li \svgcolor {#00ffff}
\row
\li Magenta
\li #ff00ff
\li \svgcolor {#ff00ff}
\row
\li Yellow
\li #ffff00
\li \svgcolor {#ffff00}
\row
\li DarkRed
\li #800000
\li \svgcolor {#800000}
\row
\li DarkGreen
\li #008000
\li \svgcolor {#008000}
\row
\li DarkBlue
\li #000080
\li \svgcolor {#000080}
\row
\li DarkCyan
\li #008080
\li \svgcolor {#008080}
\row
\li DarkMagenta
\li #800080
\li \svgcolor {#800080}
\row
\li DarkYellow
\li #808000
\li \svgcolor {#808000}
\row
\li Transparent
\li #00000000
\li (transparent)
\endtable

View File

@ -0,0 +1,594 @@
\table
\header
\li Name
\li Hex
\li Color
\row
\li aliceblue
\li #f0f8ff
\li \svgcolor {#f0f8ff}
\row
\li antiquewhite
\li #faebd7
\li \svgcolor {#faebd7}
\row
\li aqua
\li #00ffff
\li \svgcolor {#00ffff}
\row
\li aquamarine
\li #7fffd4
\li \svgcolor {#7fffd4}
\row
\li azure
\li #f0ffff
\li \svgcolor {#f0ffff}
\row
\li beige
\li #f5f5dc
\li \svgcolor {#f5f5dc}
\row
\li bisque
\li #ffe4c4
\li \svgcolor {#ffe4c4}
\row
\li black
\li #000000
\li \svgcolor {#000000}
\row
\li blanchedalmond
\li #ffebcd
\li \svgcolor {#ffebcd}
\row
\li blue
\li #0000ff
\li \svgcolor {#0000ff}
\row
\li blueviolet
\li #8a2be2
\li \svgcolor {#8a2be2}
\row
\li brown
\li #a52a2a
\li \svgcolor {#a52a2a}
\row
\li burlywood
\li #deb887
\li \svgcolor {#deb887}
\row
\li cadetblue
\li #5f9ea0
\li \svgcolor {#5f9ea0}
\row
\li chartreuse
\li #7fff00
\li \svgcolor {#7fff00}
\row
\li chocolate
\li #d2691e
\li \svgcolor {#d2691e}
\row
\li coral
\li #ff7f50
\li \svgcolor {#ff7f50}
\row
\li cornflowerblue
\li #6495ed
\li \svgcolor {#6495ed}
\row
\li cornsilk
\li #fff8dc
\li \svgcolor {#fff8dc}
\row
\li crimson
\li #dc143c
\li \svgcolor {#dc143c}
\row
\li cyan
\li #00ffff
\li \svgcolor {#00ffff}
\row
\li darkblue
\li #00008b
\li \svgcolor {#00008b}
\row
\li darkcyan
\li #008b8b
\li \svgcolor {#008b8b}
\row
\li darkgoldenrod
\li #b8860b
\li \svgcolor {#b8860b}
\row
\li darkgray
\li #a9a9a9
\li \svgcolor {#a9a9a9}
\row
\li darkgreen
\li #006400
\li \svgcolor {#006400}
\row
\li darkgrey
\li #a9a9a9
\li \svgcolor {#a9a9a9}
\row
\li darkkhaki
\li #bdb76b
\li \svgcolor {#bdb76b}
\row
\li darkmagenta
\li #8b008b
\li \svgcolor {#8b008b}
\row
\li darkolivegreen
\li #556b2f
\li \svgcolor {#556b2f}
\row
\li darkorange
\li #ff8c00
\li \svgcolor {#ff8c00}
\row
\li darkorchid
\li #9932cc
\li \svgcolor {#9932cc}
\row
\li darkred
\li #8b0000
\li \svgcolor {#8b0000}
\row
\li darksalmon
\li #e9967a
\li \svgcolor {#e9967a}
\row
\li darkseagreen
\li #8fbc8f
\li \svgcolor {#8fbc8f}
\row
\li darkslateblue
\li #483d8b
\li \svgcolor {#483d8b}
\row
\li darkslategray
\li #2f4f4f
\li \svgcolor {#2f4f4f}
\row
\li darkslategrey
\li #2f4f4f
\li \svgcolor {#2f4f4f}
\row
\li darkturquoise
\li #00ced1
\li \svgcolor {#00ced1}
\row
\li darkviolet
\li #9400d3
\li \svgcolor {#9400d3}
\row
\li deeppink
\li #ff1493
\li \svgcolor {#ff1493}
\row
\li deepskyblue
\li #00bfff
\li \svgcolor {#00bfff}
\row
\li dimgray
\li #696969
\li \svgcolor {#696969}
\row
\li dimgrey
\li #696969
\li \svgcolor {#696969}
\row
\li dodgerblue
\li #1e90ff
\li \svgcolor {#1e90ff}
\row
\li firebrick
\li #b22222
\li \svgcolor {#b22222}
\row
\li floralwhite
\li #fffaf0
\li \svgcolor {#fffaf0}
\row
\li forestgreen
\li #228b22
\li \svgcolor {#228b22}
\row
\li fuchsia
\li #ff00ff
\li \svgcolor {#ff00ff}
\row
\li gainsboro
\li #dcdcdc
\li \svgcolor {#dcdcdc}
\row
\li ghostwhite
\li #f8f8ff
\li \svgcolor {#f8f8ff}
\row
\li gold
\li #ffd700
\li \svgcolor {#ffd700}
\row
\li goldenrod
\li #daa520
\li \svgcolor {#daa520}
\row
\li gray
\li #808080
\li \svgcolor {#808080}
\row
\li grey
\li #808080
\li \svgcolor {#808080}
\row
\li green
\li #008000
\li \svgcolor {#008000}
\row
\li greenyellow
\li #adff2f
\li \svgcolor {#adff2f}
\row
\li honeydew
\li #f0fff0
\li \svgcolor {#f0fff0}
\row
\li hotpink
\li #ff69b4
\li \svgcolor {#ff69b4}
\row
\li indianred
\li #cd5c5c
\li \svgcolor {#cd5c5c}
\row
\li indigo
\li #4b0082
\li \svgcolor {#4b0082}
\row
\li ivory
\li #fffff0
\li \svgcolor {#fffff0}
\row
\li khaki
\li #f0e68c
\li \svgcolor {#f0e68c}
\row
\li lavender
\li #e6e6fa
\li \svgcolor {#e6e6fa}
\row
\li lavenderblush
\li #fff0f5
\li \svgcolor {#fff0f5}
\row
\li lawngreen
\li #7cfc00
\li \svgcolor {#7cfc00}
\row
\li lemonchiffon
\li #fffacd
\li \svgcolor {#fffacd}
\row
\li lightblue
\li #add8e6
\li \svgcolor {#add8e6}
\row
\li lightcoral
\li #f08080
\li \svgcolor {#f08080}
\row
\li lightcyan
\li #e0ffff
\li \svgcolor {#e0ffff}
\row
\li lightgoldenrodyellow
\li #fafad2
\li \svgcolor {#fafad2}
\row
\li lightgray
\li #d3d3d3
\li \svgcolor {#d3d3d3}
\row
\li lightgreen
\li #90ee90
\li \svgcolor {#90ee90}
\row
\li lightgrey
\li #d3d3d3
\li \svgcolor {#d3d3d3}
\row
\li lightpink
\li #ffb6c1
\li \svgcolor {#ffb6c1}
\row
\li lightsalmon
\li #ffa07a
\li \svgcolor {#ffa07a}
\row
\li lightseagreen
\li #20b2aa
\li \svgcolor {#20b2aa}
\row
\li lightskyblue
\li #87cefa
\li \svgcolor {#87cefa}
\row
\li lightslategray
\li #778899
\li \svgcolor {#778899}
\row
\li lightslategrey
\li #778899
\li \svgcolor {#778899}
\row
\li lightsteelblue
\li #b0c4de
\li \svgcolor {#b0c4de}
\row
\li lightyellow
\li #ffffe0
\li \svgcolor {#ffffe0}
\row
\li lime
\li #00ff00
\li \svgcolor {#00ff00}
\row
\li limegreen
\li #32cd32
\li \svgcolor {#32cd32}
\row
\li linen
\li #faf0e6
\li \svgcolor {#faf0e6}
\row
\li magenta
\li #ff00ff
\li \svgcolor {#ff00ff}
\row
\li maroon
\li #800000
\li \svgcolor {#800000}
\row
\li mediumaquamarine
\li #66cdaa
\li \svgcolor {#66cdaa}
\row
\li mediumblue
\li #0000cd
\li \svgcolor {#0000cd}
\row
\li mediumorchid
\li #ba55d3
\li \svgcolor {#ba55d3}
\row
\li mediumpurple
\li #9370db
\li \svgcolor {#9370db}
\row
\li mediumseagreen
\li #3cb371
\li \svgcolor {#3cb371}
\row
\li mediumslateblue
\li #7b68ee
\li \svgcolor {#7b68ee}
\row
\li mediumspringgreen
\li #00fa9a
\li \svgcolor {#00fa9a}
\row
\li mediumturquoise
\li #48d1cc
\li \svgcolor {#48d1cc}
\row
\li mediumvioletred
\li #c71585
\li \svgcolor {#c71585}
\row
\li midnightblue
\li #191970
\li \svgcolor {#191970}
\row
\li mintcream
\li #f5fffa
\li \svgcolor {#f5fffa}
\row
\li mistyrose
\li #ffe4e1
\li \svgcolor {#ffe4e1}
\row
\li moccasin
\li #ffe4b5
\li \svgcolor {#ffe4b5}
\row
\li navajowhite
\li #ffdead
\li \svgcolor {#ffdead}
\row
\li navy
\li #000080
\li \svgcolor {#000080}
\row
\li oldlace
\li #fdf5e6
\li \svgcolor {#fdf5e6}
\row
\li olive
\li #808000
\li \svgcolor {#808000}
\row
\li olivedrab
\li #6b8e23
\li \svgcolor {#6b8e23}
\row
\li orange
\li #ffa500
\li \svgcolor {#ffa500}
\row
\li orangered
\li #ff4500
\li \svgcolor {#ff4500}
\row
\li orchid
\li #da70d6
\li \svgcolor {#da70d6}
\row
\li palegoldenrod
\li #eee8aa
\li \svgcolor {#eee8aa}
\row
\li palegreen
\li #98fb98
\li \svgcolor {#98fb98}
\row
\li paleturquoise
\li #afeeee
\li \svgcolor {#afeeee}
\row
\li palevioletred
\li #db7093
\li \svgcolor {#db7093}
\row
\li papayawhip
\li #ffefd5
\li \svgcolor {#ffefd5}
\row
\li peachpuff
\li #ffdab9
\li \svgcolor {#ffdab9}
\row
\li peru
\li #cd853f
\li \svgcolor {#cd853f}
\row
\li pink
\li #ffc0cb
\li \svgcolor {#ffc0cb}
\row
\li plum
\li #dda0dd
\li \svgcolor {#dda0dd}
\row
\li powderblue
\li #b0e0e6
\li \svgcolor {#b0e0e6}
\row
\li purple
\li #800080
\li \svgcolor {#800080}
\row
\li red
\li #ff0000
\li \svgcolor {#ff0000}
\row
\li rosybrown
\li #bc8f8f
\li \svgcolor {#bc8f8f}
\row
\li royalblue
\li #4169e1
\li \svgcolor {#4169e1}
\row
\li saddlebrown
\li #8b4513
\li \svgcolor {#8b4513}
\row
\li salmon
\li #fa8072
\li \svgcolor {#fa8072}
\row
\li sandybrown
\li #f4a460
\li \svgcolor {#f4a460}
\row
\li seagreen
\li #2e8b57
\li \svgcolor {#2e8b57}
\row
\li seashell
\li #fff5ee
\li \svgcolor {#fff5ee}
\row
\li sienna
\li #a0522d
\li \svgcolor {#a0522d}
\row
\li silver
\li #c0c0c0
\li \svgcolor {#c0c0c0}
\row
\li skyblue
\li #87ceeb
\li \svgcolor {#87ceeb}
\row
\li slateblue
\li #6a5acd
\li \svgcolor {#6a5acd}
\row
\li slategray
\li #708090
\li \svgcolor {#708090}
\row
\li slategrey
\li #708090
\li \svgcolor {#708090}
\row
\li snow
\li #fffafa
\li \svgcolor {#fffafa}
\row
\li springgreen
\li #00ff7f
\li \svgcolor {#00ff7f}
\row
\li steelblue
\li #4682b4
\li \svgcolor {#4682b4}
\row
\li tan
\li #d2b48c
\li \svgcolor {#d2b48c}
\row
\li teal
\li #008080
\li \svgcolor {#008080}
\row
\li thistle
\li #d8bfd8
\li \svgcolor {#d8bfd8}
\row
\li tomato
\li #ff6347
\li \svgcolor {#ff6347}
\row
\li turquoise
\li #40e0d0
\li \svgcolor {#40e0d0}
\row
\li violet
\li #ee82ee
\li \svgcolor {#ee82ee}
\row
\li wheat
\li #f5deb3
\li \svgcolor {#f5deb3}
\row
\li white
\li #ffffff
\li \svgcolor {#ffffff}
\row
\li whitesmoke
\li #f5f5f5
\li \svgcolor {#f5f5f5}
\row
\li yellow
\li #ffff00
\li \svgcolor {#ffff00}
\row
\li yellowgreen
\li #9acd32
\li \svgcolor {#9acd32}
\endtable

View File

@ -82,7 +82,18 @@ qtConfig(png) {
}
# SIMD
SSSE3_SOURCES += image/qimage_ssse3.cpp
NEON_SOURCES += image/qimage_neon.cpp
MIPS_DSPR2_SOURCES += image/qimage_mips_dspr2.cpp
MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S
!android {
SSSE3_SOURCES += image/qimage_ssse3.cpp
NEON_SOURCES += image/qimage_neon.cpp
MIPS_DSPR2_SOURCES += image/qimage_mips_dspr2.cpp
MIPS_DSPR2_ASM += image/qimage_mips_dspr2_asm.S
} else {
# see https://developer.android.com/ndk/guides/abis
arm64-v8a {
SOURCES += image/qimage_neon.cpp
}
x86 | x86_64 {
DEFINES += QT_COMPILER_SUPPORTS_SSE2 QT_COMPILER_SUPPORTS_SSE3 QT_COMPILER_SUPPORTS_SSSE3
SOURCES += image/qimage_ssse3.cpp
}
}

View File

@ -287,6 +287,7 @@ bool QImageData::checkForAlphaPixels() const
case QImage::Format_RGB555:
case QImage::Format_RGB666:
case QImage::Format_RGB888:
case QImage::Format_BGR888:
case QImage::Format_RGBX8888:
case QImage::Format_BGR30:
case QImage::Format_RGB30:
@ -720,6 +721,7 @@ bool QImageData::checkForAlphaPixels() const
\value Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16). (added in Qt 5.12)
\value Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
RGBA format (16-16-16-16). (added in Qt 5.12)
\value Format_BGR888 The image is stored using a 24-bit BGR format. (added in Qt 5.14)
\note Drawing into a QImage with QImage::Format_Indexed8 is not
supported.
@ -5550,6 +5552,19 @@ static Q_CONSTEXPR QPixelFormat pixelformats[] = {
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
/*INTERPRETATION*/ QPixelFormat::UnsignedShort,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
//QImage::Format_BGR888:
QPixelFormat(QPixelFormat::BGR,
/*RED*/ 8,
/*GREEN*/ 8,
/*BLUE*/ 8,
/*FOURTH*/ 0,
/*FIFTH*/ 0,
/*ALPHA*/ 0,
/*ALPHA USAGE*/ QPixelFormat::IgnoresAlpha,
/*ALPHA POSITION*/ QPixelFormat::AtBeginning,
/*PREMULTIPLIED*/ QPixelFormat::NotPremultiplied,
/*INTERPRETATION*/ QPixelFormat::UnsignedByte,
/*BYTE ORDER*/ QPixelFormat::CurrentSystemEndian),
};
Q_STATIC_ASSERT(sizeof(pixelformats) / sizeof(*pixelformats) == QImage::NImageFormats);

View File

@ -131,6 +131,7 @@ public:
Format_RGBA64,
Format_RGBA64_Premultiplied,
Format_Grayscale16,
Format_BGR888,
#ifndef Q_QDOC
NImageFormats
#endif

View File

@ -429,8 +429,8 @@ typedef void (QT_FASTCALL *Rgb888ToRgbConverter)(quint32 *dst, const uchar *src,
template <bool rgbx>
static void convert_RGB888_to_RGB(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_RGB888);
if (rgbx)
Q_ASSERT(src->format == QImage::Format_RGB888 || src->format == QImage::Format_BGR888);
if (rgbx ^ (src->format == QImage::Format_BGR888))
Q_ASSERT(dest->format == QImage::Format_RGBX8888 || dest->format == QImage::Format_RGBA8888 || dest->format == QImage::Format_RGBA8888_Premultiplied);
else
Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied);
@ -1421,6 +1421,69 @@ static void convert_RGBA64_to_gray16(QImageData *dest, const QImageData *src, Qt
}
}
static void convert_RGB888_to_BGR888(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_RGB888 || src->format == QImage::Format_BGR888);
Q_ASSERT(dest->format == QImage::Format_RGB888 || dest->format == QImage::Format_BGR888);
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);
const qsizetype sbpl = src->bytes_per_line;
const qsizetype dbpl = dest->bytes_per_line;
const uchar *src_data = src->data;
uchar *dest_data = dest->data;
for (int i = 0; i < src->height; ++i) {
int pixel = 0;
// Handle 4 pixels (12 bytes) at a time
for (; pixel + 3 < src->width; pixel += 4) {
const uchar *src = src_data + pixel * 3;
quint32 *dest_packed = (quint32 *) (dest_data + pixel * 3);
dest_packed[0] = (src[5] << 24) | (src[0] << 16) | (src[1] << 8) | (src[2] << 0);
dest_packed[1] = (src[7] << 24) | (src[8] << 16) | (src[3] << 8) | (src[4] << 0);
dest_packed[2] = (src[9] << 24) | (src[10] << 16) | (src[11] << 8) | (src[6] << 0);
}
// epilog: handle left over pixels
for (; pixel < src->width; ++pixel) {
dest_data[pixel * 3 + 0] = src_data[pixel * 3 + 2];
dest_data[pixel * 3 + 1] = src_data[pixel * 3 + 1];
dest_data[pixel * 3 + 2] = src_data[pixel * 3 + 0];
}
src_data += sbpl;
dest_data += dbpl;
}
}
static bool convert_RGB888_to_BGR888_inplace(QImageData *data, Qt::ImageConversionFlags)
{
Q_ASSERT(data->format == QImage::Format_RGB888 || data->format == QImage::Format_BGR888);
const qsizetype bpl = data->bytes_per_line;
uchar *line_data = data->data;
for (int i = 0; i < data->height; ++i) {
for (int j = 0; j < data->width; ++j)
qSwap(line_data[j * 3 + 0], line_data[j * 3 + 2]);
line_data += bpl;
}
switch (data->format) {
case QImage::Format_RGB888:
data->format = QImage::Format_BGR888;
break;
case QImage::Format_BGR888:
data->format = QImage::Format_RGB888;
break;
default:
Q_UNREACHABLE();
data->format = QImage::Format_Invalid;
return false;
}
return true;
}
static QVector<QRgb> fix_color_table(const QVector<QRgb> &ctbl, QImage::Format format)
{
QVector<QRgb> colorTable = ctbl;
@ -2265,7 +2328,7 @@ static bool convert_Grayscale8_to_Indexed8_inplace(QImageData *data, Qt::ImageCo
Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
{
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{
0,
@ -2286,7 +2349,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Mono
{
@ -2308,7 +2371,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_MonoLSB
{
@ -2333,7 +2396,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0, 0, 0, 0, 0,
convert_Indexed8_to_Alpha8,
convert_Indexed8_to_Grayscale8,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_Indexed8
{
@ -2361,7 +2424,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_RGB_to_RGB30<PixelOrderRGB, false>,
0,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_RGB32
{
@ -2391,7 +2454,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0, 0,
0,
convert_ARGB32_to_RGBA64<false>,
0, 0
0, 0, 0
}, // Format_ARGB32
{
@ -2416,7 +2479,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_ARGB_to_RGBA,
0, 0, 0, 0,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_ARGB32_Premultiplied
{
@ -2438,7 +2501,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB16
{
@ -2460,7 +2523,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8565_Premultiplied
{
@ -2482,7 +2545,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB666
{
@ -2504,7 +2567,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB6666_Premultiplied
{
@ -2526,7 +2589,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB555
{
@ -2548,7 +2611,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8555_Premultiplied
{
@ -2565,13 +2628,14 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0,
0, // self
0,
0,
convert_RGB888_to_RGB<true>,
convert_RGB888_to_RGB<true>,
convert_RGB888_to_RGB<true>,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
convert_RGB888_to_BGR888,
}, // Format_RGB888
{
@ -2593,7 +2657,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB444
{
@ -2614,7 +2678,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB4444_Premultiplied
{
0,
@ -2641,7 +2705,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_RGB_to_RGB30<PixelOrderRGB, true>,
0,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_RGBX8888
{
0,
@ -2670,7 +2734,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0, 0,
0,
convert_ARGB32_to_RGBA64<true>,
0, 0
0, 0, 0
}, // Format_RGBA8888
{
@ -2692,7 +2756,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGBA8888_Premultiplied
{
@ -2720,7 +2784,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_BGR30_to_RGB30,
convert_BGR30_to_RGB30,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_BGR30
{
0,
@ -2747,7 +2811,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_A2RGB30_PM_to_RGB30<true>,
convert_BGR30_to_RGB30,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_A2BGR30_Premultiplied
{
0,
@ -2773,7 +2837,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_BGR30_to_RGB30,
0,
convert_passthrough,
0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0
}, // Format_RGB30
{
0,
@ -2800,7 +2864,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_A2RGB30_PM_to_RGB30<false>,
0,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_A2RGB30_Premultiplied
{
0,
@ -2820,7 +2884,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Alpha8
{
0,
@ -2840,14 +2904,15 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Grayscale8
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // self
convert_passthrough,
convert_passthrough,
convert_RGBA64_to_gray16
convert_RGBA64_to_gray16,
0
}, // Format_RGBX64
{
0,
@ -2874,6 +2939,7 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_RGBA64_to_RGBx64,
0, // self
convert_RGBA64_to_RGBA64PM,
0,
0
}, // Format_RGBA64
{
@ -2901,7 +2967,8 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_RGBA64PM_to_RGBA64<true>,
convert_RGBA64PM_to_RGBA64<false>,
0, // self
convert_RGBA64_to_gray16
convert_RGBA64_to_gray16,
0
}, // Format_RGBA64_Premultiplied
{
0,
@ -2931,20 +2998,46 @@ Image_Converter qimage_converter_map[QImage::NImageFormats][QImage::NImageFormat
convert_gray16_to_RGBA64,
convert_gray16_to_RGBA64,
convert_gray16_to_RGBA64,
0 // self
0, // self
0
}, // Format_Grayscale16
{
0,
0,
0,
0,
0, 0, 0,
0,
0,
0,
0,
0,
0,
convert_RGB888_to_BGR888,
0,
0,
#if Q_BYTE_ORDER == Q_LITTLE_ENDIAN
convert_RGB888_to_RGB<false>,
convert_RGB888_to_RGB<false>,
convert_RGB888_to_RGB<false>,
#else
0, 0, 0,
#endif
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // self
}, // Format_BGR888
};
InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QImage::NImageFormats] =
{
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
},
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Mono
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_MonoLSB
{
0,
@ -2968,7 +3061,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, 0, 0, 0, 0,
convert_Indexed8_to_Alpha8_inplace,
convert_Indexed8_to_Grayscale8_inplace,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_Indexed8
{
0,
@ -2995,7 +3088,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_RGB_to_RGB30_inplace<PixelOrderRGB, false>,
0,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_RGB32
{
0,
@ -3022,7 +3115,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_RGB_to_RGB30_inplace<PixelOrderRGB, false>,
0,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_ARGB32
{
0,
@ -3046,34 +3139,35 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_ARGB_to_RGBA_inplace<QImage::Format_RGBA8888_Premultiplied>,
0, 0, 0, 0,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_ARGB32_Premultiplied
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB16
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8565_Premultiplied
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB666
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB6666_Premultiplied
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB555
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB8555_Premultiplied
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
convert_RGB888_to_BGR888_inplace
}, // Format_RGB888
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGB444
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_ARGB4444_Premultiplied
{
0,
@ -3100,7 +3194,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_RGB_to_RGB30_inplace<PixelOrderRGB, true>,
0,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_RGBX8888
{
0,
@ -3127,7 +3221,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_RGB_to_RGB30_inplace<PixelOrderRGB, true>,
0,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_RGBA8888
{
0,
@ -3149,7 +3243,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0,
0,
0,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_RGBA8888_Premultiplied
{
0,
@ -3176,7 +3270,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_BGR30_to_RGB30_inplace,
convert_BGR30_to_A2RGB30_inplace,
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_BGR30
{
0,
@ -3202,7 +3296,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, // self
convert_A2RGB30_PM_to_RGB30_inplace<true>,
convert_BGR30_to_RGB30_inplace,
0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0
}, // Format_A2BGR30_Premultiplied
{
0,
@ -3228,7 +3322,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_BGR30_to_A2RGB30_inplace,
0, // self
convert_passthrough_inplace<QImage::Format_A2RGB30_Premultiplied>,
0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0
}, // Format_RGB30
{
0,
@ -3255,7 +3349,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
convert_A2RGB30_PM_to_RGB30_inplace<false>,
0, // self
0, 0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_A2RGB30_Premultiplied
{
0,
@ -3280,7 +3374,7 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, 0, 0, 0,
0, // self
0,
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_Alpha8
{
0,
@ -3305,32 +3399,37 @@ InPlace_Image_Converter qimage_inplace_converter_map[QImage::NImageFormats][QIma
0, 0, 0, 0,
0,
0, // self
0, 0, 0, 0
0, 0, 0, 0, 0
}, // Format_Grayscale8
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
0, // self
convert_passthrough_inplace<QImage::Format_RGBA64>,
convert_passthrough_inplace<QImage::Format_RGBA64_Premultiplied>,
0
0, 0
}, // Format_RGBX64
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
convert_RGBA64_to_RGBx64_inplace,
0, // self
convert_RGBA64_to_RGBA64PM_inplace,
0
0, 0
}, // Format_RGBA64
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
convert_RGBA64PM_to_RGBA64_inplace<true>,
convert_RGBA64PM_to_RGBA64_inplace<false>,
0, // self
0
0, 0
}, // Format_RGBA64_Premultiplied
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_Grayscale16
{
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
convert_RGB888_to_BGR888_inplace,
0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
}, // Format_BGR888
};
static void qInitImageConversions()
@ -3341,6 +3440,9 @@ static void qInitImageConversions()
qimage_converter_map[QImage::Format_RGB888][QImage::Format_RGB32] = convert_RGB888_to_RGB32_ssse3;
qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32] = convert_RGB888_to_RGB32_ssse3;
qimage_converter_map[QImage::Format_RGB888][QImage::Format_ARGB32_Premultiplied] = convert_RGB888_to_RGB32_ssse3;
qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBX8888] = convert_RGB888_to_RGB32_ssse3;
qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBA8888] = convert_RGB888_to_RGB32_ssse3;
qimage_converter_map[QImage::Format_BGR888][QImage::Format_RGBA8888_Premultiplied] = convert_RGB888_to_RGB32_ssse3;
}
#endif

View File

@ -207,6 +207,7 @@ inline int qt_depthForFormat(QImage::Format format)
case QImage::Format_ARGB8565_Premultiplied:
case QImage::Format_ARGB8555_Premultiplied:
case QImage::Format_RGB888:
case QImage::Format_BGR888:
depth = 24;
break;
case QImage::Format_RGBX64:

View File

@ -121,8 +121,11 @@ Q_GUI_EXPORT void QT_FASTCALL qt_convert_rgb888_to_rgb32_ssse3(quint32 *dst, con
void convert_RGB888_to_RGB32_ssse3(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{
Q_ASSERT(src->format == QImage::Format_RGB888);
Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied);
Q_ASSERT(src->format == QImage::Format_RGB888 || src->format == QImage::Format_BGR888);
if (src->format == QImage::Format_BGR888)
Q_ASSERT(dest->format == QImage::Format_RGBX8888 || dest->format == QImage::Format_RGBA8888 || dest->format == QImage::Format_RGBA8888_Premultiplied);
else
Q_ASSERT(dest->format == QImage::Format_RGB32 || dest->format == QImage::Format_ARGB32 || dest->format == QImage::Format_ARGB32_Premultiplied);
Q_ASSERT(src->width == dest->width);
Q_ASSERT(src->height == dest->height);

View File

@ -281,6 +281,7 @@ Q_GUI_EXPORT HBITMAP qt_imageToWinHBITMAP(const QImage &imageIn, int hbitmapForm
}
break;
case QImage::Format_RGB888:
case QImage::Format_BGR888:
compression = BI_RGB;
bitCount = 24u;
break;
@ -368,7 +369,7 @@ static QImage::Format imageFromWinHBITMAP_Format(const BITMAPINFOHEADER &header,
? QImage::Format_RGB32 : QImage::Format_ARGB32_Premultiplied;
break;
case 24:
result = QImage::Format_RGB888;
result = QImage::Format_BGR888;
break;
case 16:
result = QImage::Format_RGB555;

View File

@ -1079,6 +1079,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i
if (color_type == PNG_COLOR_TYPE_RGB) {
switch (image.format()) {
case QImage::Format_RGB888:
case QImage::Format_BGR888:
break;
case QImage::Format_RGBX8888:
case QImage::Format_RGBX64:
@ -1131,6 +1132,7 @@ bool QPNGImageWriter::writeImage(const QImage& image, volatile int compression_i
case QImage::Format_RGB32:
case QImage::Format_ARGB32:
case QImage::Format_RGB888:
case QImage::Format_BGR888:
case QImage::Format_RGBX8888:
case QImage::Format_RGBA8888:
case QImage::Format_RGBX64:

View File

@ -534,13 +534,6 @@ Qt::MouseEventFlags QMouseEvent::flags() const
\sa button(), Qt::MouseButton
*/
/*!
\fn QPointF QMouseEvent::posF() const
\obsolete
Use localPos() instead.
*/
/*!
\class QHoverEvent
\ingroup events
@ -750,12 +743,14 @@ QHoverEvent::~QHoverEvent()
\l inverted always returns false.
*/
#if QT_DEPRECATED_SINCE(5, 15)
/*!
\fn Qt::Orientation QWheelEvent::orientation() const
\obsolete
Use angleDelta() instead.
*/
#endif
#if QT_CONFIG(wheelevent)
#if QT_DEPRECATED_SINCE(5, 15)
@ -936,6 +931,7 @@ QWheelEvent::~QWheelEvent()
\endlist
*/
#if QT_DEPRECATED_SINCE(5, 15)
/*!
\fn int QWheelEvent::delta() const
\obsolete
@ -999,6 +995,7 @@ QWheelEvent::~QWheelEvent()
This function has been deprecated, use globalPosition() instead.
*/
#endif
/*!
\fn Qt::ScrollPhase QWheelEvent::phase() const
@ -1101,16 +1098,6 @@ QKeyEvent::~QKeyEvent()
{
}
/*!
\fn QKeyEvent *QKeyEvent::createExtendedKeyEvent(Type type, int key, Qt::KeyboardModifiers modifiers, quint32 nativeScanCode, quint32 nativeVirtualKey, quint32 nativeModifiers, const QString& text, bool autorep, ushort count)
\internal
*/
/*!
\fn bool QKeyEvent::hasExtendedInfo() const
\internal
*/
/*!
\fn quint32 QKeyEvent::nativeScanCode() const
\since 4.2
@ -2539,7 +2526,7 @@ Qt::MouseButtons QTabletEvent::buttons() const
globalPos() can differ significantly from the current position
QCursor::pos().
\sa globalX(), globalY(), hiResGlobalPos()
\sa globalX(), globalY()
*/
/*!
@ -2583,15 +2570,6 @@ Qt::MouseButtons QTabletEvent::buttons() const
\sa pointerType()
*/
/*!
\fn const QPointF &QTabletEvent::hiResGlobalPos() const
The high precision coordinates delivered from the tablet expressed.
Sub pixeling information is in the fractional part of the QPointF.
\sa globalPos(), hiResGlobalX(), hiResGlobalY()
*/
/*!
\fn qreal &QTabletEvent::hiResGlobalX() const
@ -2674,10 +2652,10 @@ Qt::MouseButtons QTabletEvent::buttons() const
\sa Qt::NativeGestureType, QGestureEvent
*/
#if QT_DEPRECATED_SINCE(5, 10)
/*!
\deprecated The QTouchDevice parameter is now required
*/
#if QT_DEPRECATED_SINCE(5, 10)
QNativeGestureEvent::QNativeGestureEvent(Qt::NativeGestureType type, const QPointF &localPos, const QPointF &windowPos,
const QPointF &screenPos, qreal realValue, ulong sequenceId, quint64 intValue)
: QInputEvent(QEvent::NativeGesture), mGestureType(type),
@ -4290,18 +4268,6 @@ QWindowStateChangeEvent::~QWindowStateChangeEvent()
QGraphicsItem::acceptTouchEvents()
*/
/*! \enum QTouchEvent::DeviceType
\obsolete
This enum represents the type of device that generated a QTouchEvent.
This enum has been deprecated. Use QTouchDevice::DeviceType instead.
\omitvalue TouchPad
\omitvalue TouchScreen
\sa QTouchDevice::DeviceType, QTouchDevice::type(), QTouchEvent::device()
*/
/*!
Constructs a QTouchEvent with the given \a eventType, \a device, and
\a touchPoints. The \a touchPointStates and \a modifiers
@ -4341,16 +4307,6 @@ QTouchEvent::~QTouchEvent()
This is typically a QWidget or a QQuickItem. May be 0 when no specific target is available.
*/
/*! \fn QTouchEvent::DeviceType QTouchEvent::deviceType() const
\obsolete
Returns the touch device Type, which is of type \l {QTouchEvent::DeviceType} {DeviceType}.
This function has been deprecated. Use QTouchDevice::type() instead.
\sa QTouchDevice::type(), QTouchEvent::device()
*/
/*! \fn QTouchEvent::TouchPoint::TouchPoint(TouchPoint &&other)
Move-constructs a TouchPoint instance, making it point to the same

View File

@ -65,6 +65,10 @@
#define GL_RGBA16 0x805B
#endif
#ifndef GL_BGR
#define GL_BGR 0x80E0
#endif
#ifndef GL_BGRA
#define GL_BGRA 0x80E1
#endif
@ -202,6 +206,20 @@ qsizetype QOpenGLTextureUploader::textureImage(GLenum target, const QImage &imag
pixelType = GL_UNSIGNED_BYTE;
targetFormat = QImage::Format_RGB888;
break;
case QImage::Format_BGR888:
if (isOpenGL12orBetter) {
externalFormat = GL_BGR;
internalFormat = GL_RGB;
pixelType = GL_UNSIGNED_BYTE;
targetFormat = QImage::Format_BGR888;
} else if (funcs->hasOpenGLExtension(QOpenGLExtensions::TextureSwizzle)) {
funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_B, GL_RED);
funcs->glTexParameteri(target, GL_TEXTURE_SWIZZLE_R, GL_BLUE);
externalFormat = internalFormat = GL_RGB;
pixelType = GL_UNSIGNED_BYTE;
targetFormat = QImage::Format_BGR888;
}
break;
case QImage::Format_RGBX8888:
case QImage::Format_RGBA8888:
case QImage::Format_RGBA8888_Premultiplied:

View File

@ -135,23 +135,41 @@ gcc:equals(QT_GCC_MAJOR_VERSION, 5) {
NO_PCH_SOURCES += painting/qdrawhelper.cpp
}
SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \
painting/qimagescale_sse4.cpp
ARCH_HASWELL_SOURCES += painting/qdrawhelper_avx2.cpp
!android {
SSE2_SOURCES += painting/qdrawhelper_sse2.cpp
SSSE3_SOURCES += painting/qdrawhelper_ssse3.cpp
SSE4_1_SOURCES += painting/qdrawhelper_sse4.cpp \
painting/qimagescale_sse4.cpp
ARCH_HASWELL_SOURCES += painting/qdrawhelper_avx2.cpp
NEON_SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp
NEON_HEADERS += painting/qdrawhelper_neon_p.h
NEON_SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp
NEON_HEADERS += painting/qdrawhelper_neon_p.h
}
!uikit:!win32:contains(QT_ARCH, "arm"): CONFIG += no_clang_integrated_as
!uikit:!win32:!integrity:!contains(QT_ARCH, "arm64") {
!android:!uikit:!win32:!integrity:!contains(QT_ARCH, "arm64") {
NEON_ASM += ../3rdparty/pixman/pixman-arm-neon-asm.S painting/qdrawhelper_neon_asm.S
DEFINES += ENABLE_PIXMAN_DRAWHELPERS
}
MIPS_DSP_SOURCES += painting/qdrawhelper_mips_dsp.cpp
MIPS_DSP_HEADERS += painting/qdrawhelper_mips_dsp_p.h painting/qt_mips_asm_dsp_p.h
MIPS_DSP_ASM += painting/qdrawhelper_mips_dsp_asm.S
MIPS_DSPR2_ASM += painting/qdrawhelper_mips_dspr2_asm.S
!android {
MIPS_DSP_SOURCES += painting/qdrawhelper_mips_dsp.cpp
MIPS_DSP_HEADERS += painting/qdrawhelper_mips_dsp_p.h painting/qt_mips_asm_dsp_p.h
MIPS_DSP_ASM += painting/qdrawhelper_mips_dsp_asm.S
MIPS_DSPR2_ASM += painting/qdrawhelper_mips_dspr2_asm.S
} else {
# see https://developer.android.com/ndk/guides/abis
x86 | x86_64 {
DEFINES += QT_COMPILER_SUPPORTS_SSE2 QT_COMPILER_SUPPORTS_SSE3 QT_COMPILER_SUPPORTS_SSSE3
SOURCES += painting/qdrawhelper_sse2.cpp painting/qdrawhelper_ssse3.cpp
}
x86_64 {
DEFINES += QT_COMPILER_SUPPORTS_SSE4_1 QT_COMPILER_SUPPORTS_SSE4_2
SOURCES += painting/qdrawhelper_sse4.cpp painting/qimagescale_sse4.cpp
}
arm64-v8a {
SOURCES += painting/qdrawhelper_neon.cpp painting/qimagescale_neon.cpp
HEADERS += painting/qdrawhelper_neon_p.h
}
}
include($$PWD/../../3rdparty/zlib_dependency.pri)

View File

@ -47,6 +47,8 @@
#include <private/qnumeric_p.h>
#include <tuple> // for std::tie()
QT_BEGIN_NAMESPACE
//#define QDEBUG_BEZIER
@ -128,7 +130,7 @@ void QBezier::addToPolygon(QPolygonF *polygon, qreal bezier_flattening_threshold
--lvl;
} else {
// split, second half of the polygon goes lower into the stack
b->split(b+1, b);
std::tie(b[1], b[0]) = b->split();
lvl[1] = --lvl[0];
++b;
++lvl;
@ -166,7 +168,7 @@ void QBezier::addToPolygon(QDataBuffer<QPointF> &polygon, qreal bezier_flattenin
--lvl;
} else {
// split, second half of the polygon goes lower into the stack
b->split(b+1, b);
std::tie(b[1], b[0]) = b->split();
lvl[1] = --lvl[0];
++b;
++lvl;
@ -422,7 +424,7 @@ redo:
o += 2;
--b;
} else {
b->split(b+1, b);
std::tie(b[1], b[0]) = b->split();
++b;
}
}
@ -464,8 +466,6 @@ qreal QBezier::length(qreal error) const
void QBezier::addIfClose(qreal *length, qreal error) const
{
QBezier left, right; /* bez poly splits */
qreal len = qreal(0.0); /* arc length */
qreal chord; /* chord length */
@ -476,9 +476,9 @@ void QBezier::addIfClose(qreal *length, qreal error) const
chord = QLineF(QPointF(x1, y1),QPointF(x4, y4)).length();
if((len-chord) > error) {
split(&left, &right); /* split in two */
left.addIfClose(length, error); /* try left side */
right.addIfClose(length, error); /* try right side */
const auto halves = split(); /* split in two */
halves.first.addIfClose(length, error); /* try left side */
halves.second.addIfClose(length, error); /* try right side */
return;
}

View File

@ -107,7 +107,7 @@ public:
inline QLineF endTangent() const;
inline void parameterSplitLeft(qreal t, QBezier *left);
inline void split(QBezier *firstHalf, QBezier *secondHalf) const;
inline std::pair<QBezier, QBezier> split() const;
int shifted(QBezier *curveSegments, int maxSegmets,
qreal offset, float threshold) const;
@ -223,28 +223,21 @@ inline QPointF QBezier::secondDerivedAt(qreal t) const
a * y1 + b * y2 + c * y3 + d * y4);
}
inline void QBezier::split(QBezier *firstHalf, QBezier *secondHalf) const
std::pair<QBezier, QBezier> QBezier::split() const
{
Q_ASSERT(firstHalf);
Q_ASSERT(secondHalf);
const auto mid = [](QPointF lhs, QPointF rhs) { return (lhs + rhs) * .5; };
qreal c = (x2 + x3)*.5;
firstHalf->x2 = (x1 + x2)*.5;
secondHalf->x3 = (x3 + x4)*.5;
firstHalf->x1 = x1;
secondHalf->x4 = x4;
firstHalf->x3 = (firstHalf->x2 + c)*.5;
secondHalf->x2 = (secondHalf->x3 + c)*.5;
firstHalf->x4 = secondHalf->x1 = (firstHalf->x3 + secondHalf->x2)*.5;
const QPointF mid_12 = mid(pt1(), pt2());
const QPointF mid_23 = mid(pt2(), pt3());
const QPointF mid_34 = mid(pt3(), pt4());
const QPointF mid_12_23 = mid(mid_12, mid_23);
const QPointF mid_23_34 = mid(mid_23, mid_34);
const QPointF mid_12_23__23_34 = mid(mid_12_23, mid_23_34);
c = (y2 + y3)/2;
firstHalf->y2 = (y1 + y2)*.5;
secondHalf->y3 = (y3 + y4)*.5;
firstHalf->y1 = y1;
secondHalf->y4 = y4;
firstHalf->y3 = (firstHalf->y2 + c)*.5;
secondHalf->y2 = (secondHalf->y3 + c)*.5;
firstHalf->y4 = secondHalf->y1 = (firstHalf->y3 + secondHalf->y2)*.5;
return {
fromPoints(pt1(), mid_12, mid_12_23, mid_12_23__23_34),
fromPoints(mid_12_23__23_34, mid_23_34, mid_34, pt4()),
};
}
inline void QBezier::parameterSplitLeft(qreal t, QBezier *left)

View File

@ -147,6 +147,7 @@ static bool get_hex_rgb(const QChar *str, size_t len, QRgba64 *rgb)
#endif
#define rgb(r,g,b) (0xff000000 | (r << 16) | (g << 8) | b)
// keep this is in sync with QColorConstants
static const struct RGBData {
const char name[21];
uint value;
@ -475,25 +476,35 @@ static QStringList get_colornames()
\section1 Predefined Colors
There are 20 predefined QColors described by the Qt::GlobalColor enum,
including black, white, primary and secondary colors, darker versions
of these colors and three shades of gray. QColor also recognizes a
variety of color names; the static colorNames() function returns a
QStringList color names that QColor knows about.
There are 20 predefined QColor objects in the \c{QColorConstants}
namespace, including black, white, primary and secondary colors,
darker versions of these colors, and three shades of gray.
Furthermore, the \c{QColorConstants::Svg} namespace defines QColor
objects for the standard \l{https://www.w3.org/TR/SVG11/types.html#ColorKeywords}{SVG color keyword names}.
\image qt-colors.png Qt Colors
Additionally, the Qt::color0, Qt::color1 and Qt::transparent colors
are used for special purposes.
The \c{QColorConstants::Color0}, \c{QColorConstants::Color1} and
\c{QColorConstants::Transparent} colors are used for special
purposes.
Qt::color0 (zero pixel value) and Qt::color1 (non-zero pixel value)
are special colors for drawing in QBitmaps. Painting with Qt::color0
sets the bitmap bits to 0 (transparent; i.e., background), and painting
with Qt::color1 sets the bits to 1 (opaque; i.e., foreground).
\c{QColorConstants::Color0} (zero pixel value) and
\c{QColorConstants::Color1} (non-zero pixel value) are special
colors for drawing in QBitmaps. Painting with
\c{QColorConstants::Color0} sets the bitmap bits to 0 (transparent;
i.e., background), and painting with c{QColorConstants::Color1}
sets the bits to 1 (opaque; i.e., foreground).
Qt::transparent is used to indicate a transparent pixel. When painting
with this value, a pixel value will be used that is appropriate for the
underlying pixel format in use.
\c{QColorConstants::Transparent} is used to indicate a transparent
pixel. When painting with this value, a pixel value will be used
that is appropriate for the underlying pixel format in use.
For historical reasons, the 20 predefined colors are also available
in the Qt::GlobalColor enumeration.
Finally, QColor recognizes a variety of color names (as strings);
the static colorNames() function returns a QStringList color names
that QColor knows about.
\section1 The Extended RGB Color Model
@ -586,7 +597,7 @@ static QStringList get_colornames()
alpha-channel to feature \l {QColor#Alpha-Blended
Drawing}{alpha-blended drawing}.
\sa QPalette, QBrush
\sa QPalette, QBrush, QColorConstants
*/
#define QCOLOR_INT_RANGE_CHECK(fn, var) \
@ -886,7 +897,8 @@ QString QColor::name(NameFormat format) const
\li #AARRGGBB (Since 5.2)
\li #RRRGGGBBB
\li #RRRRGGGGBBBB
\li A name from the list of colors defined in the list of \l{http://www.w3.org/TR/SVG/types.html#ColorKeywords}{SVG color keyword names}
\li A name from the list of colors defined in the list of
\l{https://www.w3.org/TR/SVG11/types.html#ColorKeywords}{SVG color keyword names}
provided by the World Wide Web Consortium; for example, "steelblue" or "gainsboro".
These color names work on all platforms. Note that these color names are \e not the
same as defined by the Qt::GlobalColor enums, e.g. "green" and Qt::green does not
@ -3249,4 +3261,41 @@ const uint qt_inv_premul_factor[256] = {
\sa QColor::rgb(), QColor::rgba()
*/
/*!
\namespace QColorConstants
\inmodule QtGui
\brief The QColorConstants namespace contains QColor predefined constants.
These constants are usable everywhere a QColor object is expected:
\code
painter.setBrush(QColorConstants::Svg::lightblue);
\endcode
Their usage is much cheaper than e.g. passing a string to QColor's constructor,
as they don't require any parsing of the string, and always result in a valid
QColor object:
\badcode
object.setColor(QColor("lightblue")); // expensive
\endcode
\section1 Qt Colors
The following colors are defined in the \c{QColorConstants} namespace:
\include qt-colors.qdocinc
\section1 SVG Colors
The following table lists the available
\l {http://www.w3.org/TR/SVG/types.html#ColorKeywords}{SVG colors}.
They are available in the \c{QColorConstants::Svg} inner namespace.
\include svg-colors.qdocinc
\sa QColor, Qt::GlobalColor
*/
QT_END_NAMESPACE

View File

@ -309,6 +309,12 @@ private:
friend Q_GUI_EXPORT QDataStream &operator<<(QDataStream &, const QColor &);
friend Q_GUI_EXPORT QDataStream &operator>>(QDataStream &, QColor &);
#endif
#ifdef Q_COMPILER_UNIFORM_INIT
public: // can't give friendship to a namespace, so it needs to be public
Q_DECL_CONSTEXPR explicit QColor(Spec spec, ushort a1, ushort a2, ushort a3, ushort a4, ushort a5=0) noexcept
: cspec(spec), ct(a1, a2, a3, a4, a5) {}
#endif // Q_COMPILER_UNIFORM_INIT
};
Q_DECLARE_TYPEINFO(QColor, QT_VERSION >= QT_VERSION_CHECK(6,0,0) ? Q_MOVABLE_TYPE : Q_RELOCATABLE_TYPE);
@ -326,6 +332,187 @@ inline QColor::QColor(const QString& aname)
inline bool QColor::isValid() const noexcept
{ return cspec != Invalid; }
// define these namespaces even if the contents are ifdef'd out
namespace QColorConstants
{
namespace Svg {}
#if defined(Q_COMPILER_CONSTEXPR) & defined(Q_COMPILER_UNIFORM_INIT)
// Qt::GlobalColor names
constexpr Q_DECL_UNUSED QColor Color0 {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor Color1 {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor Black {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor White {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor DarkGray {QColor::Rgb, 0xff * 0x101, 0x80 * 0x101, 0x80 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor Gray {QColor::Rgb, 0xff * 0x101, 0xa0 * 0x101, 0xa0 * 0x101, 0xa4 * 0x101};
constexpr Q_DECL_UNUSED QColor LightGray {QColor::Rgb, 0xff * 0x101, 0xc0 * 0x101, 0xc0 * 0x101, 0xc0 * 0x101};
constexpr Q_DECL_UNUSED QColor Red {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor Green {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0xff * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor Blue {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor Cyan {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0xff * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor Magenta {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x00 * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor Yellow {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor DarkRed {QColor::Rgb, 0xff * 0x101, 0x80 * 0x101, 0x00 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor DarkGreen {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x80 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor DarkBlue {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor DarkCyan {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x80 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor DarkMagenta {QColor::Rgb, 0xff * 0x101, 0x80 * 0x101, 0x00 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor DarkYellow {QColor::Rgb, 0xff * 0x101, 0x80 * 0x101, 0x80 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor Transparent {QColor::Rgb, 0x00 * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0x00 * 0x101};
// SVG names supported by QColor (see qcolor.cpp).
namespace Svg {
constexpr Q_DECL_UNUSED QColor aliceblue {QColor::Rgb, 0xff * 0x101, 0xf0 * 0x101, 0xf8 * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor antiquewhite {QColor::Rgb, 0xff * 0x101, 0xfa * 0x101, 0xeb * 0x101, 0xd7 * 0x101};
constexpr Q_DECL_UNUSED QColor aqua {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0xff * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor aquamarine {QColor::Rgb, 0xff * 0x101, 0x7f * 0x101, 0xff * 0x101, 0xd4 * 0x101};
constexpr Q_DECL_UNUSED QColor azure {QColor::Rgb, 0xff * 0x101, 0xf0 * 0x101, 0xff * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor beige {QColor::Rgb, 0xff * 0x101, 0xf5 * 0x101, 0xf5 * 0x101, 0xdc * 0x101};
constexpr Q_DECL_UNUSED QColor bisque {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xe4 * 0x101, 0xc4 * 0x101};
constexpr Q_DECL_UNUSED QColor black {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor blanchedalmond {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xeb * 0x101, 0xcd * 0x101};
constexpr Q_DECL_UNUSED QColor blue {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor blueviolet {QColor::Rgb, 0xff * 0x101, 0x8a * 0x101, 0x2b * 0x101, 0xe2 * 0x101};
constexpr Q_DECL_UNUSED QColor brown {QColor::Rgb, 0xff * 0x101, 0xa5 * 0x101, 0x2a * 0x101, 0x2a * 0x101};
constexpr Q_DECL_UNUSED QColor burlywood {QColor::Rgb, 0xff * 0x101, 0xde * 0x101, 0xb8 * 0x101, 0x87 * 0x101};
constexpr Q_DECL_UNUSED QColor cadetblue {QColor::Rgb, 0xff * 0x101, 0x5f * 0x101, 0x9e * 0x101, 0xa0 * 0x101};
constexpr Q_DECL_UNUSED QColor chartreuse {QColor::Rgb, 0xff * 0x101, 0x7f * 0x101, 0xff * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor chocolate {QColor::Rgb, 0xff * 0x101, 0xd2 * 0x101, 0x69 * 0x101, 0x1e * 0x101};
constexpr Q_DECL_UNUSED QColor coral {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x7f * 0x101, 0x50 * 0x101};
constexpr Q_DECL_UNUSED QColor cornflowerblue {QColor::Rgb, 0xff * 0x101, 0x64 * 0x101, 0x95 * 0x101, 0xed * 0x101};
constexpr Q_DECL_UNUSED QColor cornsilk {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xf8 * 0x101, 0xdc * 0x101};
constexpr Q_DECL_UNUSED QColor crimson {QColor::Rgb, 0xff * 0x101, 0xdc * 0x101, 0x14 * 0x101, 0x3c * 0x101};
constexpr Q_DECL_UNUSED QColor cyan {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0xff * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor darkblue {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0x8b * 0x101};
constexpr Q_DECL_UNUSED QColor darkcyan {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x8b * 0x101, 0x8b * 0x101};
constexpr Q_DECL_UNUSED QColor darkgoldenrod {QColor::Rgb, 0xff * 0x101, 0xb8 * 0x101, 0x86 * 0x101, 0x0b * 0x101};
constexpr Q_DECL_UNUSED QColor darkgray {QColor::Rgb, 0xff * 0x101, 0xa9 * 0x101, 0xa9 * 0x101, 0xa9 * 0x101};
constexpr Q_DECL_UNUSED QColor darkgreen {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x64 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor darkgrey {QColor::Rgb, 0xff * 0x101, 0xa9 * 0x101, 0xa9 * 0x101, 0xa9 * 0x101};
constexpr Q_DECL_UNUSED QColor darkkhaki {QColor::Rgb, 0xff * 0x101, 0xbd * 0x101, 0xb7 * 0x101, 0x6b * 0x101};
constexpr Q_DECL_UNUSED QColor darkmagenta {QColor::Rgb, 0xff * 0x101, 0x8b * 0x101, 0x00 * 0x101, 0x8b * 0x101};
constexpr Q_DECL_UNUSED QColor darkolivegreen {QColor::Rgb, 0xff * 0x101, 0x55 * 0x101, 0x6b * 0x101, 0x2f * 0x101};
constexpr Q_DECL_UNUSED QColor darkorange {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x8c * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor darkorchid {QColor::Rgb, 0xff * 0x101, 0x99 * 0x101, 0x32 * 0x101, 0xcc * 0x101};
constexpr Q_DECL_UNUSED QColor darkred {QColor::Rgb, 0xff * 0x101, 0x8b * 0x101, 0x00 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor darksalmon {QColor::Rgb, 0xff * 0x101, 0xe9 * 0x101, 0x96 * 0x101, 0x7a * 0x101};
constexpr Q_DECL_UNUSED QColor darkseagreen {QColor::Rgb, 0xff * 0x101, 0x8f * 0x101, 0xbc * 0x101, 0x8f * 0x101};
constexpr Q_DECL_UNUSED QColor darkslateblue {QColor::Rgb, 0xff * 0x101, 0x48 * 0x101, 0x3d * 0x101, 0x8b * 0x101};
constexpr Q_DECL_UNUSED QColor darkslategray {QColor::Rgb, 0xff * 0x101, 0x2f * 0x101, 0x4f * 0x101, 0x4f * 0x101};
constexpr Q_DECL_UNUSED QColor darkslategrey {QColor::Rgb, 0xff * 0x101, 0x2f * 0x101, 0x4f * 0x101, 0x4f * 0x101};
constexpr Q_DECL_UNUSED QColor darkturquoise {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0xce * 0x101, 0xd1 * 0x101};
constexpr Q_DECL_UNUSED QColor darkviolet {QColor::Rgb, 0xff * 0x101, 0x94 * 0x101, 0x00 * 0x101, 0xd3 * 0x101};
constexpr Q_DECL_UNUSED QColor deeppink {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x14 * 0x101, 0x93 * 0x101};
constexpr Q_DECL_UNUSED QColor deepskyblue {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0xbf * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor dimgray {QColor::Rgb, 0xff * 0x101, 0x69 * 0x101, 0x69 * 0x101, 0x69 * 0x101};
constexpr Q_DECL_UNUSED QColor dimgrey {QColor::Rgb, 0xff * 0x101, 0x69 * 0x101, 0x69 * 0x101, 0x69 * 0x101};
constexpr Q_DECL_UNUSED QColor dodgerblue {QColor::Rgb, 0xff * 0x101, 0x1e * 0x101, 0x90 * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor firebrick {QColor::Rgb, 0xff * 0x101, 0xb2 * 0x101, 0x22 * 0x101, 0x22 * 0x101};
constexpr Q_DECL_UNUSED QColor floralwhite {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xfa * 0x101, 0xf0 * 0x101};
constexpr Q_DECL_UNUSED QColor forestgreen {QColor::Rgb, 0xff * 0x101, 0x22 * 0x101, 0x8b * 0x101, 0x22 * 0x101};
constexpr Q_DECL_UNUSED QColor fuchsia {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x00 * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor gainsboro {QColor::Rgb, 0xff * 0x101, 0xdc * 0x101, 0xdc * 0x101, 0xdc * 0x101};
constexpr Q_DECL_UNUSED QColor ghostwhite {QColor::Rgb, 0xff * 0x101, 0xf8 * 0x101, 0xf8 * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor gold {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xd7 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor goldenrod {QColor::Rgb, 0xff * 0x101, 0xda * 0x101, 0xa5 * 0x101, 0x20 * 0x101};
constexpr Q_DECL_UNUSED QColor gray {QColor::Rgb, 0xff * 0x101, 0x80 * 0x101, 0x80 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor green {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x80 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor greenyellow {QColor::Rgb, 0xff * 0x101, 0xad * 0x101, 0xff * 0x101, 0x2f * 0x101};
constexpr Q_DECL_UNUSED QColor grey {QColor::Rgb, 0xff * 0x101, 0x80 * 0x101, 0x80 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor honeydew {QColor::Rgb, 0xff * 0x101, 0xf0 * 0x101, 0xff * 0x101, 0xf0 * 0x101};
constexpr Q_DECL_UNUSED QColor hotpink {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x69 * 0x101, 0xb4 * 0x101};
constexpr Q_DECL_UNUSED QColor indianred {QColor::Rgb, 0xff * 0x101, 0xcd * 0x101, 0x5c * 0x101, 0x5c * 0x101};
constexpr Q_DECL_UNUSED QColor indigo {QColor::Rgb, 0xff * 0x101, 0x4b * 0x101, 0x00 * 0x101, 0x82 * 0x101};
constexpr Q_DECL_UNUSED QColor ivory {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101, 0xf0 * 0x101};
constexpr Q_DECL_UNUSED QColor khaki {QColor::Rgb, 0xff * 0x101, 0xf0 * 0x101, 0xe6 * 0x101, 0x8c * 0x101};
constexpr Q_DECL_UNUSED QColor lavender {QColor::Rgb, 0xff * 0x101, 0xe6 * 0x101, 0xe6 * 0x101, 0xfa * 0x101};
constexpr Q_DECL_UNUSED QColor lavenderblush {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xf0 * 0x101, 0xf5 * 0x101};
constexpr Q_DECL_UNUSED QColor lawngreen {QColor::Rgb, 0xff * 0x101, 0x7c * 0x101, 0xfc * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor lemonchiffon {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xfa * 0x101, 0xcd * 0x101};
constexpr Q_DECL_UNUSED QColor lightblue {QColor::Rgb, 0xff * 0x101, 0xad * 0x101, 0xd8 * 0x101, 0xe6 * 0x101};
constexpr Q_DECL_UNUSED QColor lightcoral {QColor::Rgb, 0xff * 0x101, 0xf0 * 0x101, 0x80 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor lightcyan {QColor::Rgb, 0xff * 0x101, 0xe0 * 0x101, 0xff * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor lightgoldenrodyellow {QColor::Rgb, 0xff * 0x101, 0xfa * 0x101, 0xfa * 0x101, 0xd2 * 0x101};
constexpr Q_DECL_UNUSED QColor lightgray {QColor::Rgb, 0xff * 0x101, 0xd3 * 0x101, 0xd3 * 0x101, 0xd3 * 0x101};
constexpr Q_DECL_UNUSED QColor lightgreen {QColor::Rgb, 0xff * 0x101, 0x90 * 0x101, 0xee * 0x101, 0x90 * 0x101};
constexpr Q_DECL_UNUSED QColor lightgrey {QColor::Rgb, 0xff * 0x101, 0xd3 * 0x101, 0xd3 * 0x101, 0xd3 * 0x101};
constexpr Q_DECL_UNUSED QColor lightpink {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xb6 * 0x101, 0xc1 * 0x101};
constexpr Q_DECL_UNUSED QColor lightsalmon {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xa0 * 0x101, 0x7a * 0x101};
constexpr Q_DECL_UNUSED QColor lightseagreen {QColor::Rgb, 0xff * 0x101, 0x20 * 0x101, 0xb2 * 0x101, 0xaa * 0x101};
constexpr Q_DECL_UNUSED QColor lightskyblue {QColor::Rgb, 0xff * 0x101, 0x87 * 0x101, 0xce * 0x101, 0xfa * 0x101};
constexpr Q_DECL_UNUSED QColor lightslategray {QColor::Rgb, 0xff * 0x101, 0x77 * 0x101, 0x88 * 0x101, 0x99 * 0x101};
constexpr Q_DECL_UNUSED QColor lightslategrey {QColor::Rgb, 0xff * 0x101, 0x77 * 0x101, 0x88 * 0x101, 0x99 * 0x101};
constexpr Q_DECL_UNUSED QColor lightsteelblue {QColor::Rgb, 0xff * 0x101, 0xb0 * 0x101, 0xc4 * 0x101, 0xde * 0x101};
constexpr Q_DECL_UNUSED QColor lightyellow {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101, 0xe0 * 0x101};
constexpr Q_DECL_UNUSED QColor lime {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0xff * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor limegreen {QColor::Rgb, 0xff * 0x101, 0x32 * 0x101, 0xcd * 0x101, 0x32 * 0x101};
constexpr Q_DECL_UNUSED QColor linen {QColor::Rgb, 0xff * 0x101, 0xfa * 0x101, 0xf0 * 0x101, 0xe6 * 0x101};
constexpr Q_DECL_UNUSED QColor magenta {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x00 * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor maroon {QColor::Rgb, 0xff * 0x101, 0x80 * 0x101, 0x00 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor mediumaquamarine {QColor::Rgb, 0xff * 0x101, 0x66 * 0x101, 0xcd * 0x101, 0xaa * 0x101};
constexpr Q_DECL_UNUSED QColor mediumblue {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0xcd * 0x101};
constexpr Q_DECL_UNUSED QColor mediumorchid {QColor::Rgb, 0xff * 0x101, 0xba * 0x101, 0x55 * 0x101, 0xd3 * 0x101};
constexpr Q_DECL_UNUSED QColor mediumpurple {QColor::Rgb, 0xff * 0x101, 0x93 * 0x101, 0x70 * 0x101, 0xdb * 0x101};
constexpr Q_DECL_UNUSED QColor mediumseagreen {QColor::Rgb, 0xff * 0x101, 0x3c * 0x101, 0xb3 * 0x101, 0x71 * 0x101};
constexpr Q_DECL_UNUSED QColor mediumslateblue {QColor::Rgb, 0xff * 0x101, 0x7b * 0x101, 0x68 * 0x101, 0xee * 0x101};
constexpr Q_DECL_UNUSED QColor mediumspringgreen {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0xfa * 0x101, 0x9a * 0x101};
constexpr Q_DECL_UNUSED QColor mediumturquoise {QColor::Rgb, 0xff * 0x101, 0x48 * 0x101, 0xd1 * 0x101, 0xcc * 0x101};
constexpr Q_DECL_UNUSED QColor mediumvioletred {QColor::Rgb, 0xff * 0x101, 0xc7 * 0x101, 0x15 * 0x101, 0x85 * 0x101};
constexpr Q_DECL_UNUSED QColor midnightblue {QColor::Rgb, 0xff * 0x101, 0x19 * 0x101, 0x19 * 0x101, 0x70 * 0x101};
constexpr Q_DECL_UNUSED QColor mintcream {QColor::Rgb, 0xff * 0x101, 0xf5 * 0x101, 0xff * 0x101, 0xfa * 0x101};
constexpr Q_DECL_UNUSED QColor mistyrose {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xe4 * 0x101, 0xe1 * 0x101};
constexpr Q_DECL_UNUSED QColor moccasin {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xe4 * 0x101, 0xb5 * 0x101};
constexpr Q_DECL_UNUSED QColor navajowhite {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xde * 0x101, 0xad * 0x101};
constexpr Q_DECL_UNUSED QColor navy {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor oldlace {QColor::Rgb, 0xff * 0x101, 0xfd * 0x101, 0xf5 * 0x101, 0xe6 * 0x101};
constexpr Q_DECL_UNUSED QColor olive {QColor::Rgb, 0xff * 0x101, 0x80 * 0x101, 0x80 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor olivedrab {QColor::Rgb, 0xff * 0x101, 0x6b * 0x101, 0x8e * 0x101, 0x23 * 0x101};
constexpr Q_DECL_UNUSED QColor orange {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xa5 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor orangered {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x45 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor orchid {QColor::Rgb, 0xff * 0x101, 0xda * 0x101, 0x70 * 0x101, 0xd6 * 0x101};
constexpr Q_DECL_UNUSED QColor palegoldenrod {QColor::Rgb, 0xff * 0x101, 0xee * 0x101, 0xe8 * 0x101, 0xaa * 0x101};
constexpr Q_DECL_UNUSED QColor palegreen {QColor::Rgb, 0xff * 0x101, 0x98 * 0x101, 0xfb * 0x101, 0x98 * 0x101};
constexpr Q_DECL_UNUSED QColor paleturquoise {QColor::Rgb, 0xff * 0x101, 0xaf * 0x101, 0xee * 0x101, 0xee * 0x101};
constexpr Q_DECL_UNUSED QColor palevioletred {QColor::Rgb, 0xff * 0x101, 0xdb * 0x101, 0x70 * 0x101, 0x93 * 0x101};
constexpr Q_DECL_UNUSED QColor papayawhip {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xef * 0x101, 0xd5 * 0x101};
constexpr Q_DECL_UNUSED QColor peachpuff {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xda * 0x101, 0xb9 * 0x101};
constexpr Q_DECL_UNUSED QColor peru {QColor::Rgb, 0xff * 0x101, 0xcd * 0x101, 0x85 * 0x101, 0x3f * 0x101};
constexpr Q_DECL_UNUSED QColor pink {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xc0 * 0x101, 0xcb * 0x101};
constexpr Q_DECL_UNUSED QColor plum {QColor::Rgb, 0xff * 0x101, 0xdd * 0x101, 0xa0 * 0x101, 0xdd * 0x101};
constexpr Q_DECL_UNUSED QColor powderblue {QColor::Rgb, 0xff * 0x101, 0xb0 * 0x101, 0xe0 * 0x101, 0xe6 * 0x101};
constexpr Q_DECL_UNUSED QColor purple {QColor::Rgb, 0xff * 0x101, 0x80 * 0x101, 0x00 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor red {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x00 * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor rosybrown {QColor::Rgb, 0xff * 0x101, 0xbc * 0x101, 0x8f * 0x101, 0x8f * 0x101};
constexpr Q_DECL_UNUSED QColor royalblue {QColor::Rgb, 0xff * 0x101, 0x41 * 0x101, 0x69 * 0x101, 0xe1 * 0x101};
constexpr Q_DECL_UNUSED QColor saddlebrown {QColor::Rgb, 0xff * 0x101, 0x8b * 0x101, 0x45 * 0x101, 0x13 * 0x101};
constexpr Q_DECL_UNUSED QColor salmon {QColor::Rgb, 0xff * 0x101, 0xfa * 0x101, 0x80 * 0x101, 0x72 * 0x101};
constexpr Q_DECL_UNUSED QColor sandybrown {QColor::Rgb, 0xff * 0x101, 0xf4 * 0x101, 0xa4 * 0x101, 0x60 * 0x101};
constexpr Q_DECL_UNUSED QColor seagreen {QColor::Rgb, 0xff * 0x101, 0x2e * 0x101, 0x8b * 0x101, 0x57 * 0x101};
constexpr Q_DECL_UNUSED QColor seashell {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xf5 * 0x101, 0xee * 0x101};
constexpr Q_DECL_UNUSED QColor sienna {QColor::Rgb, 0xff * 0x101, 0xa0 * 0x101, 0x52 * 0x101, 0x2d * 0x101};
constexpr Q_DECL_UNUSED QColor silver {QColor::Rgb, 0xff * 0x101, 0xc0 * 0x101, 0xc0 * 0x101, 0xc0 * 0x101};
constexpr Q_DECL_UNUSED QColor skyblue {QColor::Rgb, 0xff * 0x101, 0x87 * 0x101, 0xce * 0x101, 0xeb * 0x101};
constexpr Q_DECL_UNUSED QColor slateblue {QColor::Rgb, 0xff * 0x101, 0x6a * 0x101, 0x5a * 0x101, 0xcd * 0x101};
constexpr Q_DECL_UNUSED QColor slategray {QColor::Rgb, 0xff * 0x101, 0x70 * 0x101, 0x80 * 0x101, 0x90 * 0x101};
constexpr Q_DECL_UNUSED QColor slategrey {QColor::Rgb, 0xff * 0x101, 0x70 * 0x101, 0x80 * 0x101, 0x90 * 0x101};
constexpr Q_DECL_UNUSED QColor snow {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xfa * 0x101, 0xfa * 0x101};
constexpr Q_DECL_UNUSED QColor springgreen {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0xff * 0x101, 0x7f * 0x101};
constexpr Q_DECL_UNUSED QColor steelblue {QColor::Rgb, 0xff * 0x101, 0x46 * 0x101, 0x82 * 0x101, 0xb4 * 0x101};
constexpr Q_DECL_UNUSED QColor tan {QColor::Rgb, 0xff * 0x101, 0xd2 * 0x101, 0xb4 * 0x101, 0x8c * 0x101};
constexpr Q_DECL_UNUSED QColor teal {QColor::Rgb, 0xff * 0x101, 0x00 * 0x101, 0x80 * 0x101, 0x80 * 0x101};
constexpr Q_DECL_UNUSED QColor thistle {QColor::Rgb, 0xff * 0x101, 0xd8 * 0x101, 0xbf * 0x101, 0xd8 * 0x101};
constexpr Q_DECL_UNUSED QColor tomato {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0x63 * 0x101, 0x47 * 0x101};
constexpr Q_DECL_UNUSED QColor turquoise {QColor::Rgb, 0xff * 0x101, 0x40 * 0x101, 0xe0 * 0x101, 0xd0 * 0x101};
constexpr Q_DECL_UNUSED QColor violet {QColor::Rgb, 0xff * 0x101, 0xee * 0x101, 0x82 * 0x101, 0xee * 0x101};
constexpr Q_DECL_UNUSED QColor wheat {QColor::Rgb, 0xff * 0x101, 0xf5 * 0x101, 0xde * 0x101, 0xb3 * 0x101};
constexpr Q_DECL_UNUSED QColor white {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101};
constexpr Q_DECL_UNUSED QColor whitesmoke {QColor::Rgb, 0xff * 0x101, 0xf5 * 0x101, 0xf5 * 0x101, 0xf5 * 0x101};
constexpr Q_DECL_UNUSED QColor yellow {QColor::Rgb, 0xff * 0x101, 0xff * 0x101, 0xff * 0x101, 0x00 * 0x101};
constexpr Q_DECL_UNUSED QColor yellowgreen {QColor::Rgb, 0xff * 0x101, 0x9a * 0x101, 0xcd * 0x101, 0x32 * 0x101};
} // namespace Svg
#endif // Q_COMPILER_CONSTEXPR && Q_COMPILER_UNIFORM_INIT
} // namespace QColorLiterals
QT_END_NAMESPACE
#endif // QCOLOR_H

View File

@ -88,6 +88,7 @@ template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB444>() { return 4; }
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB555>() { return 5; }
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB666>() { return 6; }
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_RGB888>() { return 8; }
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_BGR888>() { return 8; }
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; }
template<> Q_DECL_CONSTEXPR uint redWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; }
@ -101,6 +102,7 @@ template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB444>() { return 8;
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB555>() { return 10; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB666>() { return 12; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_RGB888>() { return 16; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_BGR888>() { return 0; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB4444_Premultiplied>() { return 8; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8555_Premultiplied>() { return 18; }
template<> Q_DECL_CONSTEXPR uint redShift<QImage::Format_ARGB8565_Premultiplied>() { return 19; }
@ -119,6 +121,7 @@ template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB444>() { return 4;
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB555>() { return 5; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB666>() { return 6; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_RGB888>() { return 8; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_BGR888>() { return 8; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; }
template<> Q_DECL_CONSTEXPR uint greenWidth<QImage::Format_ARGB8565_Premultiplied>() { return 6; }
@ -132,6 +135,7 @@ template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB444>() { return 4;
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB555>() { return 5; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB666>() { return 6; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_RGB888>() { return 8; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_BGR888>() { return 8; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8555_Premultiplied>() { return 13; }
template<> Q_DECL_CONSTEXPR uint greenShift<QImage::Format_ARGB8565_Premultiplied>() { return 13; }
@ -150,6 +154,7 @@ template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB444>() { return 4;
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB555>() { return 5; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB666>() { return 6; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_RGB888>() { return 8; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_BGR888>() { return 8; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8555_Premultiplied>() { return 5; }
template<> Q_DECL_CONSTEXPR uint blueWidth<QImage::Format_ARGB8565_Premultiplied>() { return 5; }
@ -163,6 +168,7 @@ template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB444>() { return 0;
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB555>() { return 0; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB666>() { return 0; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_RGB888>() { return 0; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_BGR888>() { return 16; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB4444_Premultiplied>() { return 0; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8555_Premultiplied>() { return 8; }
template<> Q_DECL_CONSTEXPR uint blueShift<QImage::Format_ARGB8565_Premultiplied>() { return 8; }
@ -181,6 +187,7 @@ template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB444>() { return 0;
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB555>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB666>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_RGB888>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_BGR888>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB4444_Premultiplied>() { return 4; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8555_Premultiplied>() { return 8; }
template<> Q_DECL_CONSTEXPR uint alphaWidth<QImage::Format_ARGB8565_Premultiplied>() { return 8; }
@ -194,6 +201,7 @@ template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB444>() { return 0;
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB555>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB666>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_RGB888>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_BGR888>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB4444_Premultiplied>() { return 12; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8555_Premultiplied>() { return 0; }
template<> Q_DECL_CONSTEXPR uint alphaShift<QImage::Format_ARGB8565_Premultiplied>() { return 0; }
@ -214,6 +222,7 @@ template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB444>() { r
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB555>() { return QPixelLayout::BPP16; }
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB666>() { return QPixelLayout::BPP24; }
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_RGB888>() { return QPixelLayout::BPP24; }
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_BGR888>() { return QPixelLayout::BPP24; }
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB4444_Premultiplied>() { return QPixelLayout::BPP16; }
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8555_Premultiplied>() { return QPixelLayout::BPP24; }
template<> constexpr QPixelLayout::BPP bitsPerPixel<QImage::Format_ARGB8565_Premultiplied>() { return QPixelLayout::BPP24; }
@ -1528,7 +1537,8 @@ QPixelLayout qPixelLayouts[QImage::NImageFormats] = {
{ false, false, QPixelLayout::BPP16, nullptr,
convertGrayscale16ToRGB32, convertGrayscale16ToRGBA64,
fetchGrayscale16ToRGB32, fetchGrayscale16ToRGBA64,
storeGrayscale16FromARGB32PM, storeGrayscale16FromRGB32 } // Format_Grayscale16
storeGrayscale16FromARGB32PM, storeGrayscale16FromRGB32 }, // Format_Grayscale16
pixelLayoutRGB<QImage::Format_BGR888>(),
};
Q_STATIC_ASSERT(sizeof(qPixelLayouts) / sizeof(*qPixelLayouts) == QImage::NImageFormats);
@ -1643,7 +1653,8 @@ ConvertAndStorePixelsFunc64 qStoreFromRGBA64PM[QImage::NImageFormats] = {
storeRGBX64FromRGBA64PM,
storeRGBA64FromRGBA64PM,
storeRGBA64PMFromRGBA64PM,
storeGray16FromRGBA64PM
storeGray16FromRGBA64PM,
storeGenericFromRGBA64PM<QImage::Format_BGR888>,
};
/*
@ -1732,6 +1743,7 @@ static DestFetchProc destFetchProc[QImage::NImageFormats] =
destFetch, // Format_RGBA64
destFetch, // Format_RGBA64_Premultiplied
destFetch, // Format_Grayscale16
destFetch, // Format_BGR888
};
#if QT_CONFIG(raster_64bit)
@ -1782,6 +1794,7 @@ static DestFetchProc64 destFetchProc64[QImage::NImageFormats] =
destFetch64, // Format_RGBA64
destFetchRGB64, // Format_RGBA64_Premultiplied
destFetch64, // Format_Grayscale16
destFetch64, // Format_BGR888
};
#endif
@ -1922,6 +1935,7 @@ static DestStoreProc destStoreProc[QImage::NImageFormats] =
destStore, // Format_RGBA64
destStore, // Format_RGBA64_Premultiplied
destStore, // Format_Grayscale16
destStore, // Format_BGR888
};
#if QT_CONFIG(raster_64bit)
@ -1971,6 +1985,7 @@ static DestStoreProc64 destStoreProc64[QImage::NImageFormats] =
destStore64RGBA64, // Format_RGBA64
0, // Format_RGBA64_Premultiplied
destStore64, // Format_Grayscale16
destStore64, // Format_BGR888
};
#endif
@ -3922,6 +3937,7 @@ static SourceFetchProc sourceFetchUntransformed[QImage::NImageFormats] = {
fetchUntransformed, // RGBA64
fetchUntransformed, // RGBA64_Premultiplied
fetchUntransformed, // Grayscale16
fetchUntransformed, // BGR888
};
static const SourceFetchProc sourceFetchGeneric[NBlendTypes] = {
@ -6589,6 +6605,14 @@ DrawHelper qDrawHelper[QImage::NImageFormats] =
qt_alphargbblit_generic,
qt_rectfill_quint16
},
// Format_BGR888
{
blend_color_generic,
0,
qt_alphamapblit_generic,
qt_alphargbblit_generic,
qt_rectfill_quint24
},
};
#if !defined(__SSE2__)

View File

@ -1855,10 +1855,9 @@ static void qt_painterpath_isect_curve(const QBezier &bezier, const QPointF &pt,
}
// split curve and try again...
QBezier first_half, second_half;
bezier.split(&first_half, &second_half);
qt_painterpath_isect_curve(first_half, pt, winding, depth + 1);
qt_painterpath_isect_curve(second_half, pt, winding, depth + 1);
const auto halves = bezier.split();
qt_painterpath_isect_curve(halves.first, pt, winding, depth + 1);
qt_painterpath_isect_curve(halves.second, pt, winding, depth + 1);
}
}
@ -2013,10 +2012,9 @@ static bool qt_isect_curve_horizontal(const QBezier &bezier, qreal y, qreal x1,
if (depth == 32 || (bounds.width() < lower_bound && bounds.height() < lower_bound))
return true;
QBezier first_half, second_half;
bezier.split(&first_half, &second_half);
if (qt_isect_curve_horizontal(first_half, y, x1, x2, depth + 1)
|| qt_isect_curve_horizontal(second_half, y, x1, x2, depth + 1))
const auto halves = bezier.split();
if (qt_isect_curve_horizontal(halves.first, y, x1, x2, depth + 1)
|| qt_isect_curve_horizontal(halves.second, y, x1, x2, depth + 1))
return true;
}
return false;
@ -2032,10 +2030,9 @@ static bool qt_isect_curve_vertical(const QBezier &bezier, qreal x, qreal y1, qr
if (depth == 32 || (bounds.width() < lower_bound && bounds.height() < lower_bound))
return true;
QBezier first_half, second_half;
bezier.split(&first_half, &second_half);
if (qt_isect_curve_vertical(first_half, x, y1, y2, depth + 1)
|| qt_isect_curve_vertical(second_half, x, y1, y2, depth + 1))
const auto halves = bezier.split();
if (qt_isect_curve_vertical(halves.first, x, y1, y2, depth + 1)
|| qt_isect_curve_vertical(halves.second, x, y1, y2, depth + 1))
return true;
}
return false;

View File

@ -164,6 +164,43 @@ void openFile(const std::string &accept,
openFiles(accept, FileSelectMode::SingleFile, fileDialogClosedWithInt, acceptFile, fileDataReady);
}
void saveFile(const char *content, size_t size, const std::string &fileNameHint)
{
// Save a file by creating programatically clicking a download
// link to an object url to a Blob containing the file content.
// File content is copied once, so that the passed in content
// buffer can be released as soon as this function returns - we
// don't know for how long the browser will retain the TypedArray
// view used to create the Blob.
emscripten::val document = emscripten::val::global("document");
emscripten::val window = emscripten::val::global("window");
emscripten::val fileContentView = emscripten::val(emscripten::typed_memory_view(size, content));
emscripten::val fileContentCopy = emscripten::val::global("ArrayBuffer").new_(size);
emscripten::val fileContentCopyView = emscripten::val::global("Uint8Array").new_(fileContentCopy);
fileContentCopyView.call<void>("set", fileContentView);
emscripten::val contentArray = emscripten::val::array();
contentArray.call<void>("push", fileContentCopyView);
emscripten::val type = emscripten::val::object();
type.set("type","application/octet-stream");
emscripten::val contentBlob = emscripten::val::global("Blob").new_(contentArray, type);
emscripten::val contentUrl = window["URL"].call<emscripten::val>("createObjectURL", contentBlob);
emscripten::val contentLink = document.call<emscripten::val>("createElement", std::string("a"));
contentLink.set("href", contentUrl);
contentLink.set("download", fileNameHint);
contentLink.set("style", "display:none");
emscripten::val body = document["body"];
body.call<void>("appendChild", contentLink);
contentLink.call<void>("click");
body.call<void>("removeChild", contentLink);
window["URL"].call<emscripten::val>("revokeObjectURL", contentUrl);
}
} // namespace QWasmLocalFileAccess
QT_END_NAMESPACE

View File

@ -71,6 +71,8 @@ void openFile(const std::string &accept,
const std::function<char *(uint64_t size, const std::string name)> &acceptFile,
const std::function<void()> &fileDataReady);
void saveFile(const char *content, size_t size, const std::string &fileNameHint);
} // namespace QWasmLocalFileAccess
QT_END_NAMESPACE

View File

@ -92,6 +92,7 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "border-bottom-right-radius", BorderBottomRightRadius },
{ "border-bottom-style", BorderBottomStyle },
{ "border-bottom-width", BorderBottomWidth },
{ "border-collapse", BorderCollapse },
{ "border-color", BorderColor },
{ "border-image", BorderImage },
{ "border-left", BorderLeft },
@ -611,11 +612,7 @@ bool ValueExtractor::extractBorder(int *borders, QBrush *colors, BorderStyle *st
case BorderRightStyle: styles[RightEdge] = decl.styleValue(); break;
case BorderStyles: decl.styleValues(styles); break;
#ifndef QT_OS_ANDROID_GCC_48_WORKAROUND
case BorderTopLeftRadius: radii[0] = sizeValue(decl); break;
#else
case BorderTopLeftRadius: new(radii)QSize(sizeValue(decl)); break;
#endif
case BorderTopRightRadius: radii[1] = sizeValue(decl); break;
case BorderBottomLeftRadius: radii[2] = sizeValue(decl); break;
case BorderBottomRightRadius: radii[3] = sizeValue(decl); break;
@ -1732,6 +1729,14 @@ void Declaration::borderImageValue(QString *image, int *cuts,
*h = *v;
}
bool Declaration::borderCollapseValue() const
{
if (d->values.count() != 1)
return false;
else
return d->values.at(0).toString() == QLatin1String("collapse");
}
QIcon Declaration::iconValue() const
{
if (d->parsed.isValid())

View File

@ -122,6 +122,7 @@ enum Property {
BorderRight,
BorderTop,
BorderBottom,
BorderCollapse,
Padding,
PaddingLeft,
PaddingRight,
@ -478,6 +479,7 @@ struct Q_GUI_EXPORT Declaration
QIcon iconValue() const;
void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const;
bool borderCollapseValue() const;
};
QT_CSS_DECLARE_TYPEINFO(Declaration, Q_MOVABLE_TYPE)

View File

@ -180,14 +180,14 @@ Q_GUI_EXPORT int qt_defaultDpi()
}
QFontPrivate::QFontPrivate()
: engineData(0), dpi(qt_defaultDpi()), screen(0),
: engineData(0), dpi(qt_defaultDpi()),
underline(false), overline(false), strikeOut(false), kerning(true),
capital(0), letterSpacingIsAbsolute(false), scFont(0)
{
}
QFontPrivate::QFontPrivate(const QFontPrivate &other)
: request(other.request), engineData(0), dpi(other.dpi), screen(other.screen),
: request(other.request), engineData(0), dpi(other.dpi),
underline(other.underline), overline(other.overline),
strikeOut(other.strikeOut), kerning(other.kerning),
capital(other.capital), letterSpacingIsAbsolute(other.letterSpacingIsAbsolute),
@ -581,11 +581,9 @@ QFont::QFont(const QFont &font, const QPaintDevice *pd)
{
Q_ASSERT(pd);
const int dpi = pd->logicalDpiY();
const int screen = 0;
if (font.d->dpi != dpi || font.d->screen != screen ) {
if (font.d->dpi != dpi) {
d = new QFontPrivate(*font.d);
d->dpi = dpi;
d->screen = screen;
} else {
d = font.d;
}

View File

@ -185,7 +185,6 @@ public:
QFontDef request;
mutable QFontEngineData *engineData;
int dpi;
int screen;
uint underline : 1;
uint overline : 1;
@ -230,19 +229,17 @@ public:
void clear();
struct Key {
Key() : script(0), multi(0), screen(0) { }
Key(const QFontDef &d, uchar c, bool m = 0, uchar s = 0)
: def(d), script(c), multi(m), screen(s) { }
Key() : script(0), multi(0) { }
Key(const QFontDef &d, uchar c, bool m = 0)
: def(d), script(c), multi(m) { }
QFontDef def;
uchar script;
uchar multi: 1;
uchar screen: 7;
inline bool operator<(const Key &other) const
{
if (script != other.script) return script < other.script;
if (screen != other.screen) return screen < other.screen;
if (multi != other.multi) return multi < other.multi;
if (multi && def.fallBackFamilies.size() != other.def.fallBackFamilies.size())
return def.fallBackFamilies.size() < other.def.fallBackFamilies.size();
@ -251,7 +248,6 @@ public:
inline bool operator==(const Key &other) const
{
return script == other.script
&& screen == other.screen
&& multi == other.multi
&& (!multi || def.fallBackFamilies == other.def.fallBackFamilies)
&& def == other.def;

View File

@ -185,11 +185,9 @@ QFontMetrics::QFontMetrics(const QFont &font, const QPaintDevice *paintdevice)
#endif
{
const int dpi = paintdevice ? paintdevice->logicalDpiY() : qt_defaultDpi();
const int screen = 0;
if (font.d->dpi != dpi || font.d->screen != screen ) {
if (font.d->dpi != dpi) {
d = new QFontPrivate(*font.d);
d->dpi = dpi;
d->screen = screen;
} else {
d = font.d;
}
@ -1178,11 +1176,9 @@ QFontMetricsF::QFontMetricsF(const QFont &font, const QPaintDevice *paintdevice)
#endif
{
int dpi = paintdevice ? paintdevice->logicalDpiY() : qt_defaultDpi();
const int screen = 0;
if (font.d->dpi != dpi || font.d->screen != screen ) {
if (font.d->dpi != dpi) {
d = new QFontPrivate(*font.d);
d->dpi = dpi;
d->screen = screen;
} else {
d = font.d;
}

View File

@ -2593,51 +2593,43 @@ void QTextHtmlExporter::emitFloatStyle(QTextFrameFormat::Position pos, StyleMode
html += QLatin1Char('\"');
}
static QLatin1String richtextBorderStyleToHtmlBorderStyle(QTextFrameFormat::BorderStyle style)
{
switch (style) {
case QTextFrameFormat::BorderStyle_None:
return QLatin1String("none");
case QTextFrameFormat::BorderStyle_Dotted:
return QLatin1String("dotted");
case QTextFrameFormat::BorderStyle_Dashed:
return QLatin1String("dashed");
case QTextFrameFormat::BorderStyle_Solid:
return QLatin1String("solid");
case QTextFrameFormat::BorderStyle_Double:
return QLatin1String("double");
case QTextFrameFormat::BorderStyle_DotDash:
return QLatin1String("dot-dash");
case QTextFrameFormat::BorderStyle_DotDotDash:
return QLatin1String("dot-dot-dash");
case QTextFrameFormat::BorderStyle_Groove:
return QLatin1String("groove");
case QTextFrameFormat::BorderStyle_Ridge:
return QLatin1String("ridge");
case QTextFrameFormat::BorderStyle_Inset:
return QLatin1String("inset");
case QTextFrameFormat::BorderStyle_Outset:
return QLatin1String("outset");
default:
Q_UNREACHABLE();
};
return QLatin1String("");
}
void QTextHtmlExporter::emitBorderStyle(QTextFrameFormat::BorderStyle style)
{
Q_ASSERT(style <= QTextFrameFormat::BorderStyle_Outset);
html += QLatin1String(" border-style:");
switch (style) {
case QTextFrameFormat::BorderStyle_None:
html += QLatin1String("none");
break;
case QTextFrameFormat::BorderStyle_Dotted:
html += QLatin1String("dotted");
break;
case QTextFrameFormat::BorderStyle_Dashed:
html += QLatin1String("dashed");
break;
case QTextFrameFormat::BorderStyle_Solid:
html += QLatin1String("solid");
break;
case QTextFrameFormat::BorderStyle_Double:
html += QLatin1String("double");
break;
case QTextFrameFormat::BorderStyle_DotDash:
html += QLatin1String("dot-dash");
break;
case QTextFrameFormat::BorderStyle_DotDotDash:
html += QLatin1String("dot-dot-dash");
break;
case QTextFrameFormat::BorderStyle_Groove:
html += QLatin1String("groove");
break;
case QTextFrameFormat::BorderStyle_Ridge:
html += QLatin1String("ridge");
break;
case QTextFrameFormat::BorderStyle_Inset:
html += QLatin1String("inset");
break;
case QTextFrameFormat::BorderStyle_Outset:
html += QLatin1String("outset");
break;
default:
Q_ASSERT(false);
break;
};
html += richtextBorderStyleToHtmlBorderStyle(style);
html += QLatin1Char(';');
}
@ -3204,6 +3196,33 @@ void QTextHtmlExporter::emitTable(const QTextTable *table)
if (cellFormat.hasProperty(QTextFormat::TableCellBottomPadding))
styleString += QLatin1String(" padding-bottom:") + QString::number(cellFormat.bottomPadding()) + QLatin1Char(';');
if (cellFormat.hasProperty(QTextFormat::TableCellTopBorder))
styleString += QLatin1String(" border-top:") + QString::number(cellFormat.topBorder()) + QLatin1String("px;");
if (cellFormat.hasProperty(QTextFormat::TableCellRightBorder))
styleString += QLatin1String(" border-right:") + QString::number(cellFormat.rightBorder()) + QLatin1String("px;");
if (cellFormat.hasProperty(QTextFormat::TableCellBottomBorder))
styleString += QLatin1String(" border-bottom:") + QString::number(cellFormat.bottomBorder()) + QLatin1String("px;");
if (cellFormat.hasProperty(QTextFormat::TableCellLeftBorder))
styleString += QLatin1String(" border-left:") + QString::number(cellFormat.leftBorder()) + QLatin1String("px;");
if (cellFormat.hasProperty(QTextFormat::TableCellTopBorderBrush))
styleString += QLatin1String(" border-top-color:") + cellFormat.topBorderBrush().color().name() + QLatin1Char(';');
if (cellFormat.hasProperty(QTextFormat::TableCellRightBorderBrush))
styleString += QLatin1String(" border-right-color:") + cellFormat.rightBorderBrush().color().name() + QLatin1Char(';');
if (cellFormat.hasProperty(QTextFormat::TableCellBottomBorderBrush))
styleString += QLatin1String(" border-bottom-color:") + cellFormat.bottomBorderBrush().color().name() + QLatin1Char(';');
if (cellFormat.hasProperty(QTextFormat::TableCellLeftBorderBrush))
styleString += QLatin1String(" border-left-color:") + cellFormat.leftBorderBrush().color().name() + QLatin1Char(';');
if (cellFormat.hasProperty(QTextFormat::TableCellTopBorderStyle))
styleString += QLatin1String(" border-top-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.topBorderStyle()) + QLatin1Char(';');
if (cellFormat.hasProperty(QTextFormat::TableCellRightBorderStyle))
styleString += QLatin1String(" border-right-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.rightBorderStyle()) + QLatin1Char(';');
if (cellFormat.hasProperty(QTextFormat::TableCellBottomBorderStyle))
styleString += QLatin1String(" border-bottom-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.bottomBorderStyle()) + QLatin1Char(';');
if (cellFormat.hasProperty(QTextFormat::TableCellLeftBorderStyle))
styleString += QLatin1String(" border-left-style:") + richtextBorderStyleToHtmlBorderStyle(cellFormat.leftBorderStyle()) + QLatin1Char(';');
if (!styleString.isEmpty())
html += QLatin1String(" style=\"") + styleString + QLatin1Char('\"');
@ -3310,6 +3329,9 @@ void QTextHtmlExporter::emitFrameStyle(const QTextFrameFormat &format, FrameType
QString::number(format.leftMargin()),
QString::number(format.rightMargin()));
if (format.property(QTextFormat::TableBorderCollapse).toBool())
html += QLatin1String(" border-collapse:collapse;");
if (html.length() == originalHtmlLength) // nothing emitted?
html.chop(styleAttribute.size());
else

View File

@ -986,6 +986,7 @@ QTextHtmlImporter::Table QTextHtmlImporter::scanTable(int tableNodeIdx)
tableFmt.setColumns(table.columns);
tableFmt.setColumnWidthConstraints(columnWidths);
tableFmt.setHeaderRowCount(tableHeaderRowCount);
tableFmt.setBorderCollapse(node.borderCollapse);
fmt = tableFmt;
}
@ -1061,6 +1062,31 @@ QTextHtmlImporter::ProcessNodeResult QTextHtmlImporter::processBlockNode()
fmt.setLeftPadding(leftPadding(currentNodeIdx));
if (rightPadding(currentNodeIdx) >= 0)
fmt.setRightPadding(rightPadding(currentNodeIdx));
if (tableCellBorder(currentNodeIdx, QCss::TopEdge) > 0)
fmt.setTopBorder(tableCellBorder(currentNodeIdx, QCss::TopEdge));
if (tableCellBorder(currentNodeIdx, QCss::RightEdge) > 0)
fmt.setRightBorder(tableCellBorder(currentNodeIdx, QCss::RightEdge));
if (tableCellBorder(currentNodeIdx, QCss::BottomEdge) > 0)
fmt.setBottomBorder(tableCellBorder(currentNodeIdx, QCss::BottomEdge));
if (tableCellBorder(currentNodeIdx, QCss::LeftEdge) > 0)
fmt.setLeftBorder(tableCellBorder(currentNodeIdx, QCss::LeftEdge));
if (tableCellBorderStyle(currentNodeIdx, QCss::TopEdge) != QTextFrameFormat::BorderStyle_None)
fmt.setTopBorderStyle(tableCellBorderStyle(currentNodeIdx, QCss::TopEdge));
if (tableCellBorderStyle(currentNodeIdx, QCss::RightEdge) != QTextFrameFormat::BorderStyle_None)
fmt.setRightBorderStyle(tableCellBorderStyle(currentNodeIdx, QCss::RightEdge));
if (tableCellBorderStyle(currentNodeIdx, QCss::BottomEdge) != QTextFrameFormat::BorderStyle_None)
fmt.setBottomBorderStyle(tableCellBorderStyle(currentNodeIdx, QCss::BottomEdge));
if (tableCellBorderStyle(currentNodeIdx, QCss::LeftEdge) != QTextFrameFormat::BorderStyle_None)
fmt.setLeftBorderStyle(tableCellBorderStyle(currentNodeIdx, QCss::LeftEdge));
if (tableCellBorderBrush(currentNodeIdx, QCss::TopEdge) != Qt::NoBrush)
fmt.setTopBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::TopEdge));
if (tableCellBorderBrush(currentNodeIdx, QCss::RightEdge) != Qt::NoBrush)
fmt.setRightBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::RightEdge));
if (tableCellBorderBrush(currentNodeIdx, QCss::BottomEdge) != Qt::NoBrush)
fmt.setBottomBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::BottomEdge));
if (tableCellBorderBrush(currentNodeIdx, QCss::LeftEdge) != Qt::NoBrush)
fmt.setLeftBorderBrush(tableCellBorderBrush(currentNodeIdx, QCss::LeftEdge));
cell.setFormat(fmt);
cursor.setPosition(cell.firstPosition());

View File

@ -491,12 +491,19 @@ QTextHtmlParserNode::QTextHtmlParserNode()
listStyle(QTextListFormat::ListStyleUndefined), imageWidth(-1), imageHeight(-1), tableBorder(0),
tableCellRowSpan(1), tableCellColSpan(1), tableCellSpacing(2), tableCellPadding(0),
borderBrush(Qt::darkGray), borderStyle(QTextFrameFormat::BorderStyle_Outset),
borderCollapse(false),
userState(-1), cssListIndent(0), wsm(WhiteSpaceModeUndefined)
{
margin[QTextHtmlParser::MarginLeft] = 0;
margin[QTextHtmlParser::MarginRight] = 0;
margin[QTextHtmlParser::MarginTop] = 0;
margin[QTextHtmlParser::MarginBottom] = 0;
for (int i = 0; i < 4; ++i) {
tableCellBorderStyle[i] = QTextFrameFormat::BorderStyle_None;
tableCellBorder[i] = 0;
tableCellBorderBrush[i] = Qt::NoBrush;
}
}
void QTextHtmlParser::dumpHtml()
@ -1169,6 +1176,25 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
QCss::ValueExtractor extractor(declarations);
extractor.extractBox(margin, padding);
if (id == Html_td || id == Html_th) {
QCss::BorderStyle cssStyles[4];
int cssBorder[4];
QSize cssRadii[4]; // unused
for (int i = 0; i < 4; ++i) {
cssStyles[i] = QCss::BorderStyle_None;
cssBorder[i] = 0;
}
// this will parse (and cache) "border-width" as a list so the
// QCss::BorderWidth parsing below which expects a single value
// will not work as expected - which in this case does not matter
// because tableBorder is not relevant for cells.
extractor.extractBorder(cssBorder, tableCellBorderBrush, cssStyles, cssRadii);
for (int i = 0; i < 4; ++i) {
tableCellBorderStyle[i] = static_cast<QTextFrameFormat::BorderStyle>(cssStyles[i] - 1);
tableCellBorder[i] = static_cast<qreal>(cssBorder[i]);
}
}
for (int i = 0; i < declarations.count(); ++i) {
const QCss::Declaration &decl = declarations.at(i);
if (decl.d->values.isEmpty()) continue;
@ -1186,6 +1212,9 @@ void QTextHtmlParserNode::applyCssDeclarations(const QVector<QCss::Declaration>
case QCss::BorderWidth:
tableBorder = extractor.lengthValue(decl);
break;
case QCss::BorderCollapse:
borderCollapse = decl.borderCollapseValue();
break;
case QCss::Color: charFormat.setForeground(decl.colorValue()); break;
case QCss::Float:
cssFloat = QTextFrameFormat::InFlow;
@ -1654,6 +1683,11 @@ void QTextHtmlParser::applyAttributes(const QStringList &attributes)
if (!c.isValid())
qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
node->charFormat.setBackground(c);
} else if (key == QLatin1String("bordercolor")) {
QColor c; c.setNamedColor(value);
if (!c.isValid())
qWarning("QTextHtmlParser::applyAttributes: Unknown color name '%s'",value.toLatin1().constData());
node->borderBrush = c;
} else if (key == QLatin1String("background")) {
node->applyBackgroundImage(value, resourceProvider);
} else if (key == QLatin1String("cellspacing")) {

View File

@ -195,8 +195,12 @@ struct QTextHtmlParserNode {
int tableCellColSpan;
qreal tableCellSpacing;
qreal tableCellPadding;
qreal tableCellBorder[4];
QBrush tableCellBorderBrush[4];
QTextFrameFormat::BorderStyle tableCellBorderStyle[4];
QBrush borderBrush;
QTextFrameFormat::BorderStyle borderStyle;
bool borderCollapse;
int userState;
int cssListIndent;
@ -290,6 +294,10 @@ public:
inline int leftPadding(int i) const { return at(i).padding[MarginLeft]; }
inline int rightPadding(int i) const { return at(i).padding[MarginRight]; }
inline qreal tableCellBorder(int i, int edge) const { return at(i).tableCellBorder[edge]; }
inline QTextFrameFormat::BorderStyle tableCellBorderStyle(int i, int edge) const { return at(i).tableCellBorderStyle[edge]; }
inline QBrush tableCellBorderBrush(int i, int edge) const { return at(i).tableCellBorderBrush[edge]; }
void dumpHtml();
void parse(const QString &text, const QTextDocument *resourceProvider);

View File

@ -97,7 +97,8 @@ qtConfig(http) {
access/qhttpnetworkrequest.cpp \
access/qhttpprotocolhandler.cpp \
access/qhttpthreaddelegate.cpp \
access/qnetworkreplyhttpimpl.cpp
access/qnetworkreplyhttpimpl.cpp \
access/qhttp2configuration.cpp
HEADERS += \
access/qabstractprotocolhandler_p.h \
@ -111,7 +112,8 @@ qtConfig(http) {
access/qhttpnetworkrequest_p.h \
access/qhttpprotocolhandler_p.h \
access/qhttpthreaddelegate_p.h \
access/qnetworkreplyhttpimpl_p.h
access/qnetworkreplyhttpimpl_p.h \
access/qhttp2configuration.h
qtConfig(ssl) {
SOURCES += \

View File

@ -208,6 +208,11 @@ void Encoder::setMaxDynamicTableSize(quint32 size)
lookupTable.setMaxDynamicTableSize(size);
}
void Encoder::setCompressStrings(bool compress)
{
compressStrings = compress;
}
bool Encoder::encodeRequestPseudoHeaders(BitOStream &outputStream,
const HttpHeader &header)
{

View File

@ -83,6 +83,7 @@ public:
quint32 newSize);
void setMaxDynamicTableSize(quint32 size);
void setCompressStrings(bool compress);
private:
bool encodeRequestPseudoHeaders(BitOStream &outputStream,

View File

@ -305,7 +305,7 @@ FrameStatus FrameReader::read(QAbstractSocket &socket)
return status;
}
if (Http2PredefinedParameters::maxFrameSize < frame.payloadSize())
if (Http2PredefinedParameters::maxPayloadSize < frame.payloadSize())
return FrameStatus::sizeError;
frame.buffer.resize(frame.payloadSize() + frameHeaderSize);
@ -388,7 +388,7 @@ void FrameWriter::setPayloadSize(quint32 size)
auto &buffer = frame.buffer;
Q_ASSERT(buffer.size() >= frameHeaderSize);
Q_ASSERT(size < maxPayloadSize);
Q_ASSERT(size <= maxPayloadSize);
buffer[0] = size >> 16;
buffer[1] = size >> 8;

View File

@ -43,6 +43,8 @@
#include "private/qhttpnetworkrequest_p.h"
#include "private/qhttpnetworkreply_p.h"
#include <access/qhttp2configuration.h>
#include <QtCore/qbytearray.h>
#include <QtCore/qstring.h>
@ -62,88 +64,29 @@ const char Http2clientPreface[clientPrefaceLength] =
0x2e, 0x30, 0x0d, 0x0a, 0x0d, 0x0a,
0x53, 0x4d, 0x0d, 0x0a, 0x0d, 0x0a};
// TODO: (in 5.11) - remove it!
const char *http2ParametersPropertyName = "QT_HTTP2_PARAMETERS_PROPERTY";
ProtocolParameters::ProtocolParameters()
Frame configurationToSettingsFrame(const QHttp2Configuration &config)
{
settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID] = qtDefaultStreamReceiveWindowSize;
settingsFrameData[Settings::ENABLE_PUSH_ID] = 0;
// 6.5 SETTINGS
FrameWriter builder(FrameType::SETTINGS, FrameFlag::EMPTY, connectionStreamID);
// Server push:
builder.append(Settings::ENABLE_PUSH_ID);
builder.append(int(config.serverPushEnabled()));
// Stream receive window size:
builder.append(Settings::INITIAL_WINDOW_SIZE_ID);
builder.append(config.streamReceiveWindowSize());
if (config.maxFrameSize() != minPayloadLimit) {
builder.append(Settings::MAX_FRAME_SIZE_ID);
builder.append(config.maxFrameSize());
}
// TODO: In future, if the need is proven, we can
// also send decoding table size and header list size.
// For now, defaults suffice.
return builder.outboundFrame();
}
bool ProtocolParameters::validate() const
QByteArray settingsFrameToBase64(const Frame &frame)
{
// 0. Huffman/indexing: any values are valid and allowed.
// 1. Session receive window size (client side): HTTP/2 starts from the
// default value of 64Kb, if a client code tries to set lesser value,
// the delta would become negative, but this is not allowed.
if (maxSessionReceiveWindowSize < qint32(defaultSessionWindowSize)) {
qCWarning(QT_HTTP2, "Session receive window must be at least 65535 bytes");
return false;
}
// 2. HEADER_TABLE_SIZE: we do not validate HEADER_TABLE_SIZE, considering
// all values as valid. RFC 7540 and 7541 do not provide any lower/upper
// limits. If it's 0 - we do not index anything, if it's too huge - a user
// who provided such a value can potentially have a huge memory footprint,
// up to them to decide.
// 3. SETTINGS_ENABLE_PUSH: RFC 7540, 6.5.2, a value other than 0 or 1 will
// be treated by our peer as a PROTOCOL_ERROR.
if (settingsFrameData.contains(Settings::ENABLE_PUSH_ID)
&& settingsFrameData[Settings::ENABLE_PUSH_ID] > 1) {
qCWarning(QT_HTTP2, "SETTINGS_ENABLE_PUSH can be only 0 or 1");
return false;
}
// 4. SETTINGS_MAX_CONCURRENT_STREAMS : RFC 7540 recommends 100 as the lower
// limit, says nothing about the upper limit. The RFC allows 0, but this makes
// no sense to us at all: there is no way a user can change this later and
// we'll not be able to get any responses on such a connection.
if (settingsFrameData.contains(Settings::MAX_CONCURRENT_STREAMS_ID)
&& !settingsFrameData[Settings::MAX_CONCURRENT_STREAMS_ID]) {
qCWarning(QT_HTTP2, "MAX_CONCURRENT_STREAMS must be a positive number");
return false;
}
// 5. SETTINGS_INITIAL_WINDOW_SIZE.
if (settingsFrameData.contains(Settings::INITIAL_WINDOW_SIZE_ID)) {
const quint32 value = settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID];
// RFC 7540, 6.5.2 (the upper limit). The lower limit is our own - we send
// SETTINGS frame only once and will not be able to change this 0, thus
// we'll suspend all streams.
if (!value || value > quint32(maxSessionReceiveWindowSize)) {
qCWarning(QT_HTTP2, "INITIAL_WINDOW_SIZE must be in the range "
"(0, 2^31-1]");
return false;
}
}
// 6. SETTINGS_MAX_FRAME_SIZE: RFC 7540, 6.5.2, a value outside of the range
// [2^14-1, 2^24-1] will be treated by our peer as a PROTOCOL_ERROR.
if (settingsFrameData.contains(Settings::MAX_FRAME_SIZE_ID)) {
const quint32 value = settingsFrameData[Settings::INITIAL_WINDOW_SIZE_ID];
if (value < maxFrameSize || value > maxPayloadSize) {
qCWarning(QT_HTTP2, "MAX_FRAME_SIZE must be in the range [2^14, 2^24-1]");
return false;
}
}
// For SETTINGS_MAX_HEADER_LIST_SIZE RFC 7540 does not provide any specific
// numbers. It's clear, if a value is too small, no header can ever be sent
// by our peer at all. The default value is unlimited and we normally do not
// change this.
//
// Note: the size is calculated as the length of uncompressed (no HPACK)
// name + value + 32 bytes.
return true;
}
QByteArray ProtocolParameters::settingsFrameToBase64() const
{
Frame frame(settingsFrame());
// SETTINGS frame's payload consists of pairs:
// 2-byte-identifier | 4-byte-value == multiple of 6.
Q_ASSERT(frame.payloadSize() && !(frame.payloadSize() % 6));
@ -157,20 +100,7 @@ QByteArray ProtocolParameters::settingsFrameToBase64() const
return wrapper.toBase64(QByteArray::Base64UrlEncoding | QByteArray::OmitTrailingEquals);
}
Frame ProtocolParameters::settingsFrame() const
{
// 6.5 SETTINGS
FrameWriter builder(FrameType::SETTINGS, FrameFlag::EMPTY, connectionStreamID);
for (auto it = settingsFrameData.cbegin(), end = settingsFrameData.cend();
it != end; ++it) {
builder.append(it.key());
builder.append(it.value());
}
return builder.outboundFrame();
}
void ProtocolParameters::addProtocolUpgradeHeaders(QHttpNetworkRequest *request) const
void appendProtocolUpgradeHeaders(const QHttp2Configuration &config, QHttpNetworkRequest *request)
{
Q_ASSERT(request);
// RFC 2616, 14.10
@ -184,8 +114,10 @@ void ProtocolParameters::addProtocolUpgradeHeaders(QHttpNetworkRequest *request)
request->setHeaderField("Connection", value);
// This we just (re)write.
request->setHeaderField("Upgrade", "h2c");
const Frame frame(configurationToSettingsFrame(config));
// This we just (re)write.
request->setHeaderField("HTTP2-Settings", settingsFrameToBase64());
request->setHeaderField("HTTP2-Settings", settingsFrameToBase64(frame));
}
void qt_error(quint32 errorCode, QNetworkReply::NetworkError &error,

View File

@ -55,12 +55,14 @@
#include <QtCore/qloggingcategory.h>
#include <QtCore/qmetatype.h>
#include <QtCore/qglobal.h>
#include <QtCore/qmap.h>
// Different HTTP/2 constants/values as defined by RFC 7540.
QT_BEGIN_NAMESPACE
class QHttpNetworkRequest;
class QHttp2Configuration;
class QHttpNetworkReply;
class QByteArray;
class QString;
@ -118,13 +120,19 @@ enum Http2PredefinedParameters
connectionStreamID = 0, // HTTP/2, 5.1.1
frameHeaderSize = 9, // HTTP/2, 4.1
// It's our max frame size we send in SETTINGS frame,
// it's also the default one and we also use it to later
// validate incoming frames:
maxFrameSize = 16384, // HTTP/2 6.5.2
// The initial allowed payload size. We would use it as an
// upper limit for a frame payload we send, until our peer
// updates us with a larger SETTINGS_MAX_FRAME_SIZE.
// The initial maximum payload size that an HTTP/2 frame
// can contain is 16384. It's also the minimal size that
// can be advertised via 'SETTINGS' frames. A real frame
// can have a payload smaller than 16384.
minPayloadLimit = 16384, // HTTP/2 6.5.2
// The maximum allowed payload size.
maxPayloadSize = (1 << 24) - 1, // HTTP/2 6.5.2
defaultSessionWindowSize = 65535, // HTTP/2 6.5.2
maxPayloadSize = (1 << 24) - 1, // HTTP/2 6.5.2
// Using 1000 (rather arbitrarily), just to
// impose *some* upper limit:
maxPeerConcurrentStreams = 1000,
@ -145,48 +153,9 @@ const quint32 lastValidStreamID((quint32(1) << 31) - 1); // HTTP/2, 5.1.1
const qint32 maxSessionReceiveWindowSize((quint32(1) << 31) - 1);
const qint32 qtDefaultStreamReceiveWindowSize = maxSessionReceiveWindowSize / maxConcurrentStreams;
// The class ProtocolParameters allows client code to customize HTTP/2 protocol
// handler, if needed. Normally, we use our own default parameters (see below).
// In 5.10 we can also use setProperty/property on a QNAM object to pass the
// non-default values to the protocol handler. In 5.11 this will probably become
// a public API.
using RawSettings = QMap<Settings, quint32>;
struct Q_AUTOTEST_EXPORT ProtocolParameters
{
ProtocolParameters();
bool validate() const;
QByteArray settingsFrameToBase64() const;
struct Frame settingsFrame() const;
void addProtocolUpgradeHeaders(QHttpNetworkRequest *request) const;
// HPACK:
// TODO: for now we ignore them (fix it for 5.11, would require changes in HPACK)
bool useHuffman = true;
bool indexStrings = true;
// This parameter is not negotiated via SETTINGS frames, so we have it
// as a member and will convey it to our peer as a WINDOW_UPDATE frame.
// Note, some servers do not accept our WINDOW_UPDATE from the default
// 64 KB to the possible maximum. Let's use a half of it:
qint32 maxSessionReceiveWindowSize = Http2::maxSessionReceiveWindowSize / 2;
// This is our default SETTINGS frame:
//
// SETTINGS_INITIAL_WINDOW_SIZE: (2^31 - 1) / 100
// SETTINGS_ENABLE_PUSH: 0.
//
// Note, whenever we skip some value in our SETTINGS frame, our peer
// will assume the defaults recommended by RFC 7540, which in general
// are good enough, although we (and most browsers) prefer to work
// with larger window sizes.
RawSettings settingsFrameData;
};
// TODO: remove in 5.11
extern const Q_AUTOTEST_EXPORT char *http2ParametersPropertyName;
struct Frame configurationToSettingsFrame(const QHttp2Configuration &configuration);
QByteArray settingsFrameToBase64(const Frame &settingsFrame);
void appendProtocolUpgradeHeaders(const QHttp2Configuration &configuration, QHttpNetworkRequest *request);
extern const Q_AUTOTEST_EXPORT char Http2clientPreface[clientPrefaceLength];
@ -235,6 +204,5 @@ Q_DECLARE_LOGGING_CATEGORY(QT_HTTP2)
QT_END_NAMESPACE
Q_DECLARE_METATYPE(Http2::Settings)
Q_DECLARE_METATYPE(Http2::ProtocolParameters)
#endif

View File

@ -0,0 +1,312 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#include "qhttp2configuration.h"
#include "private/http2protocol_p.h"
#include "private/hpack_p.h"
#include "qdebug.h"
QT_BEGIN_NAMESPACE
/*!
\class QHttp2Configuration
\brief The QHttp2Configuration class controls HTTP/2 parameters and settings
\since 5.14
\reentrant
\inmodule QtNetwork
\ingroup network
\ingroup shared
QHttp2Configuration controls HTTP/2 parameters and settings that
QNetworkAccessManager will use to send requests and process responses
when the HTTP/2 protocol is enabled.
The HTTP/2 parameters that QHttp2Configuration currently supports include:
\list
\li The session window size for connection-level flow control.
Will be sent to a remote peer when needed as 'WINDOW_UPDATE'
frames on the stream with an identifier 0.
\li The stream receiving window size for stream-level flow control.
Sent as 'SETTINGS_INITIAL_WINDOW_SIZE' parameter in the initial
SETTINGS frame and, when needed, 'WINDOW_UPDATE' frames will be
sent on streams that QNetworkAccessManager opens.
\li The maximum frame size. This parameter limits the maximum payload
a frame coming from the remote peer can have. Sent by QNetworkAccessManager
as 'SETTINGS_MAX_FRAME_SIZE' parameter in the initial 'SETTINGS'
frame.
\li The server push. Allows to enable or disable server push. Sent
as 'SETTINGS_ENABLE_PUSH' parameter in the initial 'SETTINGS'
frame.
\endlist
The QHttp2Configuration class also controls if the header compression
algorithm (HPACK) is additionally using Huffman coding for string
compression.
\note The configuration must be set before the first request
was sent to a given host (and thus an HTTP/2 session established).
\note Details about flow control, server push and 'SETTINGS'
can be found in \l {https://httpwg.org/specs/rfc7540.html}{RFC 7540}.
Different modes and parameters of the HPACK compression algorithm
are described in \l {https://httpwg.org/specs/rfc7541.html}{RFC 7541}.
\sa QNetworkRequest::setHttp2Configuration(), QNetworkRequest::http2Configuration(), QNetworkAccessManager
*/
class QHttp2ConfigurationPrivate : public QSharedData
{
public:
unsigned sessionWindowSize = Http2::defaultSessionWindowSize;
// The size below is quite a limiting default value, QNetworkRequest
// by default sets a larger number, an application can change this using
// QNetworkRequest::setHttp2Configuration.
unsigned streamWindowSize = Http2::defaultSessionWindowSize;
unsigned maxFrameSize = Http2::minPayloadLimit; // Initial (default) value of 16Kb.
bool pushEnabled = false;
// TODO: for now those two below are noop.
bool huffmanCompressionEnabled = true;
};
/*!
Default constructs a QHttp2Configuration object.
Such a configuration has the following values:
\list
\li Server push is disabled
\li Huffman string compression is enabled
\li Window size for connection-level flow control is 65535 octets
\li Window size for stream-level flow control is 65535 octets
\li Frame size is 16384 octets
\endlist
*/
QHttp2Configuration::QHttp2Configuration()
: d(new QHttp2ConfigurationPrivate)
{
}
/*!
Copy-constructs this QHttp2Configuration.
*/
QHttp2Configuration::QHttp2Configuration(const QHttp2Configuration &) = default;
/*!
Move-constructs this QHttp2Configuration from \a other
*/
QHttp2Configuration::QHttp2Configuration(QHttp2Configuration &&other) noexcept
{
swap(other);
}
/*!
Copy-assigns to this QHttp2Configuration.
*/
QHttp2Configuration &QHttp2Configuration::operator=(const QHttp2Configuration &) = default;
/*!
Move-assigns to this QHttp2Configuration.
*/
QHttp2Configuration &QHttp2Configuration::operator=(QHttp2Configuration &&) noexcept = default;
/*!
Destructor.
*/
QHttp2Configuration::~QHttp2Configuration()
{
}
/*!
If \a enable is \c true, a remote server can potentially
use server push to send reponses in advance.
\sa serverPushEnabled
*/
void QHttp2Configuration::setServerPushEnabled(bool enable)
{
d->pushEnabled = enable;
}
/*!
Returns true if server push was enabled.
\note By default, QNetworkAccessManager disables server
push via the 'SETTINGS' frame.
\sa setServerPushEnabled
*/
bool QHttp2Configuration::serverPushEnabled() const
{
return d->pushEnabled;
}
/*!
If \a enable is \c true, HPACK compression will additionally
compress string using the Huffman coding. Enabled by default.
\note This parameter only affects 'HEADERS' frames that
QNetworkAccessManager is sending.
\sa huffmanCompressionEnabled
*/
void QHttp2Configuration::setHuffmanCompressionEnabled(bool enable)
{
d->huffmanCompressionEnabled = enable;
}
/*!
Returns \c true if the Huffman coding in HPACK is enabled.
\sa setHuffmanCompressionEnabled
*/
bool QHttp2Configuration::huffmanCompressionEnabled() const
{
return d->huffmanCompressionEnabled;
}
/*!
Sets the window size for connection-level flow control.
\a size cannot be 0 and must not exceed 2147483647 octets.
\sa sessionReceiveWindowSize
*/
bool QHttp2Configuration::setSessionReceiveWindowSize(unsigned size)
{
if (!size || size > Http2::maxSessionReceiveWindowSize) { // RFC-7540, 6.9
qCWarning(QT_HTTP2) << "Invalid session window size";
return false;
}
d->sessionWindowSize = size;
return true;
}
/*!
Returns the window size for connection-level flow control.
The default value QNetworkAccessManager will be using is
2147483647 octets.
*/
unsigned QHttp2Configuration::sessionReceiveWindowSize() const
{
return d->sessionWindowSize;
}
/*!
Sets the window size for stream-level flow control.
\a size cannot be 0 and must not exceed 2147483647 octets.
\sa streamReceiveWindowSize
*/
bool QHttp2Configuration::setStreamReceiveWindowSize(unsigned size)
{
if (!size || size > Http2::maxSessionReceiveWindowSize) { // RFC-7540, 6.9
qCWarning(QT_HTTP2) << "Invalid stream window size";
return false;
}
d->streamWindowSize = size;
return true;
}
/*!
Returns the window size for stream-level flow control.
The default value QNetworkAccessManager will be using is
21474836 octets.
*/
unsigned QHttp2Configuration::streamReceiveWindowSize() const
{
return d->streamWindowSize;
}
/*!
Sets the maximum frame size that QNetworkAccessManager
will advertise to the server when sending its initial SETTINGS frame.
\note While this \a size is required to be within a range between
16384 and 16777215 inclusive, the actual payload size in frames
that carry payload maybe be less than 16384.
*/
bool QHttp2Configuration::setMaxFrameSize(unsigned size)
{
if (size < Http2::minPayloadLimit || size > Http2::maxPayloadSize) {
qCWarning(QT_HTTP2) << "Maximum frame size to advertise is invalid";
return false;
}
d->maxFrameSize = size;
return true;
}
/*!
The maximum payload size that HTTP/2 frames can
have. The default (initial) value is 16384 octets.
*/
unsigned QHttp2Configuration::maxFrameSize() const
{
return d->maxFrameSize;
}
/*!
Swaps this configuration with the \a other configuration.
*/
void QHttp2Configuration::swap(QHttp2Configuration &other) noexcept
{
d.swap(other.d);
}
/*!
Returns \c true if \a lhs and \a rhs have the same set of HTTP/2
parameters.
*/
bool operator==(const QHttp2Configuration &lhs, const QHttp2Configuration &rhs)
{
if (lhs.d == rhs.d)
return true;
return lhs.d->pushEnabled == rhs.d->pushEnabled
&& lhs.d->huffmanCompressionEnabled == rhs.d->huffmanCompressionEnabled
&& lhs.d->sessionWindowSize == rhs.d->sessionWindowSize
&& lhs.d->streamWindowSize == rhs.d->streamWindowSize;
}
QT_END_NAMESPACE

View File

@ -0,0 +1,100 @@
/****************************************************************************
**
** Copyright (C) 2019 The Qt Company Ltd.
** Contact: https://www.qt.io/licensing/
**
** This file is part of the QtNetwork module of the Qt Toolkit.
**
** $QT_BEGIN_LICENSE:LGPL$
** 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 https://www.qt.io/terms-conditions. For further
** information use the contact form at https://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.LGPL3 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-3.0.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 (at your option) the GNU General
** Public license version 3 or any later version approved by the KDE Free
** Qt Foundation. The licenses are as published by the Free Software
** Foundation and appearing in the file LICENSE.GPL2 and LICENSE.GPL3
** included in the packaging of this file. Please review the following
** information to ensure the GNU General Public License requirements will
** be met: https://www.gnu.org/licenses/gpl-2.0.html and
** https://www.gnu.org/licenses/gpl-3.0.html.
**
** $QT_END_LICENSE$
**
****************************************************************************/
#ifndef QHTTP2CONFIGURATION_H
#define QHTTP2CONFIGURATION_H
#include <QtNetwork/qtnetworkglobal.h>
#include <QtCore/qshareddata.h>
#ifndef Q_CLANG_QDOC
QT_REQUIRE_CONFIG(http);
#endif
QT_BEGIN_NAMESPACE
class QHttp2ConfigurationPrivate;
class Q_NETWORK_EXPORT QHttp2Configuration
{
friend Q_NETWORK_EXPORT bool operator==(const QHttp2Configuration &lhs, const QHttp2Configuration &rhs);
public:
QHttp2Configuration();
QHttp2Configuration(const QHttp2Configuration &other);
QHttp2Configuration(QHttp2Configuration &&other) noexcept;
QHttp2Configuration &operator = (const QHttp2Configuration &other);
QHttp2Configuration &operator = (QHttp2Configuration &&other) noexcept;
~QHttp2Configuration();
void setServerPushEnabled(bool enable);
bool serverPushEnabled() const;
void setHuffmanCompressionEnabled(bool enable);
bool huffmanCompressionEnabled() const;
bool setSessionReceiveWindowSize(unsigned size);
unsigned sessionReceiveWindowSize() const;
bool setStreamReceiveWindowSize(unsigned size);
unsigned streamReceiveWindowSize() const;
bool setMaxFrameSize(unsigned size);
unsigned maxFrameSize() const;
void swap(QHttp2Configuration &other) noexcept;
private:
QSharedDataPointer<QHttp2ConfigurationPrivate> d;
};
Q_DECLARE_SHARED(QHttp2Configuration)
Q_NETWORK_EXPORT bool operator==(const QHttp2Configuration &lhs, const QHttp2Configuration &rhs);
inline bool operator!=(const QHttp2Configuration &lhs, const QHttp2Configuration &rhs)
{
return !(lhs == rhs);
}
QT_END_NAMESPACE
#endif // QHTTP2CONFIGURATION_H

View File

@ -40,6 +40,7 @@
#include "qhttpnetworkconnection_p.h"
#include "qhttp2protocolhandler_p.h"
#include "http2/http2frames_p.h"
#include "http2/bitstreams_p.h"
#include <private/qnoncontiguousbytedevice_p.h>
@ -51,6 +52,8 @@
#include <QtCore/qlist.h>
#include <QtCore/qurl.h>
#include <qhttp2configuration.h>
#ifndef QT_NO_NETWORKPROXY
#include <QtNetwork/qnetworkproxy.h>
#endif
@ -172,30 +175,11 @@ QHttp2ProtocolHandler::QHttp2ProtocolHandler(QHttpNetworkConnectionChannel *chan
Q_ASSERT(channel && m_connection);
continuedFrames.reserve(20);
const ProtocolParameters params(m_connection->http2Parameters());
Q_ASSERT(params.validate());
maxSessionReceiveWindowSize = params.maxSessionReceiveWindowSize;
const RawSettings &data = params.settingsFrameData;
for (auto param = data.cbegin(), end = data.cend(); param != end; ++param) {
switch (param.key()) {
case Settings::INITIAL_WINDOW_SIZE_ID:
streamInitialReceiveWindowSize = param.value();
break;
case Settings::ENABLE_PUSH_ID:
pushPromiseEnabled = param.value();
break;
case Settings::HEADER_TABLE_SIZE_ID:
case Settings::MAX_CONCURRENT_STREAMS_ID:
case Settings::MAX_FRAME_SIZE_ID:
case Settings::MAX_HEADER_LIST_SIZE_ID:
// These other settings are just recommendations to our peer. We
// only check they are not crazy in ProtocolParameters::validate().
default:
break;
}
}
const auto h2Config = m_connection->http2Parameters();
maxSessionReceiveWindowSize = h2Config.sessionReceiveWindowSize();
pushPromiseEnabled = h2Config.serverPushEnabled();
streamInitialReceiveWindowSize = h2Config.streamReceiveWindowSize();
encoder.setCompressStrings(h2Config.huffmanCompressionEnabled());
if (!channel->ssl && m_connection->connectionType() != QHttpNetworkConnection::ConnectionTypeHTTP2Direct) {
// We upgraded from HTTP/1.1 to HTTP/2. channel->request was already sent
@ -422,20 +406,17 @@ bool QHttp2ProtocolHandler::sendClientPreface()
return false;
// 6.5 SETTINGS
const ProtocolParameters params(m_connection->http2Parameters());
Q_ASSERT(params.validate());
frameWriter.setOutboundFrame(params.settingsFrame());
frameWriter.setOutboundFrame(Http2::configurationToSettingsFrame(m_connection->http2Parameters()));
Q_ASSERT(frameWriter.outboundFrame().payloadSize());
if (!frameWriter.write(*m_socket))
return false;
sessionReceiveWindowSize = maxSessionReceiveWindowSize;
// ProtocolParameters::validate does not allow maxSessionReceiveWindowSize
// to be smaller than defaultSessionWindowSize, so everything is OK here with
// 'delta':
// We only send WINDOW_UPDATE for the connection if the size differs from the
// default 64 KB:
const auto delta = maxSessionReceiveWindowSize - Http2::defaultSessionWindowSize;
if (!sendWINDOW_UPDATE(Http2::connectionStreamID, delta))
if (delta && !sendWINDOW_UPDATE(Http2::connectionStreamID, delta))
return false;
prefaceSent = true;
@ -1069,7 +1050,7 @@ bool QHttp2ProtocolHandler::acceptSetting(Http2::Settings identifier, quint32 ne
}
if (identifier == Settings::MAX_FRAME_SIZE_ID) {
if (newValue < Http2::maxFrameSize || newValue > Http2::maxPayloadSize) {
if (newValue < Http2::minPayloadLimit || newValue > Http2::maxPayloadSize) {
connectionError(PROTOCOL_ERROR, "SETTGINGS max frame size is out of range");
return false;
}

View File

@ -55,6 +55,8 @@
#include <private/qabstractprotocolhandler_p.h>
#include <private/qhttpnetworkrequest_p.h>
#include <access/qhttp2configuration.h>
#include <private/http2protocol_p.h>
#include <private/http2streams_p.h>
#include <private/http2frames_p.h>
@ -163,8 +165,9 @@ private:
static const std::deque<quint32>::size_type maxRecycledStreams;
std::deque<quint32> recycledStreams;
// Peer's max frame size.
quint32 maxFrameSize = Http2::maxFrameSize;
// Peer's max frame size (this min is the default value
// we start with, that can be updated by SETTINGS frame):
quint32 maxFrameSize = Http2::minPayloadLimit;
Http2::FrameReader frameReader;
Http2::Frame inboundFrame;
@ -176,28 +179,28 @@ private:
// Control flow:
// This is how many concurrent streams our peer expects from us:
// 100 is the default value, can be updated by the server's SETTINGS
// frame(s):
// This is how many concurrent streams our peer allows us, 100 is the
// initial value, can be updated by the server's SETTINGS frame(s):
quint32 maxConcurrentStreams = Http2::maxConcurrentStreams;
// While we allow sending SETTTINGS_MAX_CONCURRENT_STREAMS to limit our peer,
// it's just a hint and we do not actually enforce it (and we can continue
// sending requests and creating streams while maxConcurrentStreams allows).
// This is the max value, we set it in a ctor from Http2::ProtocolParameters,
// it does not change after that.
// This is our (client-side) maximum possible receive window size, we set
// it in a ctor from QHttp2Configuration, it does not change after that.
// The default is 64Kb:
qint32 maxSessionReceiveWindowSize = Http2::defaultSessionWindowSize;
// Our session receive window size, default is 64Kb. We'll update it from QNAM's
// Http2::ProtocolParameters. Signed integer since it can become negative
// Our session current receive window size, updated in a ctor from
// QHttp2Configuration. Signed integer since it can become negative
// (it's still a valid window size).
qint32 sessionReceiveWindowSize = Http2::defaultSessionWindowSize;
// Our per-stream receive window size, default is 64 Kb, will be updated
// from QNAM's Http2::ProtocolParameters. Again, signed - can become negative.
// from QHttp2Configuration. Again, signed - can become negative.
qint32 streamInitialReceiveWindowSize = Http2::defaultSessionWindowSize;
// These are our peer's receive window sizes, they will be updated by the
// peer's SETTINGS and WINDOW_UPDATE frames.
// peer's SETTINGS and WINDOW_UPDATE frames, defaults presumed to be 64Kb.
qint32 sessionSendWindowSize = Http2::defaultSessionWindowSize;
qint32 streamInitialSendWindowSize = Http2::defaultSessionWindowSize;

View File

@ -1456,21 +1456,16 @@ void QHttpNetworkConnection::setConnectionType(ConnectionType type)
d->connectionType = type;
}
Http2::ProtocolParameters QHttpNetworkConnection::http2Parameters() const
QHttp2Configuration QHttpNetworkConnection::http2Parameters() const
{
Q_D(const QHttpNetworkConnection);
return d->http2Parameters;
}
void QHttpNetworkConnection::setHttp2Parameters(const Http2::ProtocolParameters &params)
void QHttpNetworkConnection::setHttp2Parameters(const QHttp2Configuration &params)
{
Q_D(QHttpNetworkConnection);
if (params.validate()) {
d->http2Parameters = params;
} else {
qCWarning(QT_HTTP2)
<< "invalid HTTP/2 parameters, falling back to defaults instead";
}
d->http2Parameters = params;
}
// SSL support below

View File

@ -57,6 +57,8 @@
#include <QtNetwork/qabstractsocket.h>
#include <QtNetwork/qnetworksession.h>
#include <qhttp2configuration.h>
#include <private/qobject_p.h>
#include <qauthenticator.h>
#include <qnetworkproxy.h>
@ -142,8 +144,8 @@ public:
ConnectionType connectionType();
void setConnectionType(ConnectionType type);
Http2::ProtocolParameters http2Parameters() const;
void setHttp2Parameters(const Http2::ProtocolParameters &params);
QHttp2Configuration http2Parameters() const;
void setHttp2Parameters(const QHttp2Configuration &params);
#ifndef QT_NO_SSL
void setSslConfiguration(const QSslConfiguration &config);
@ -294,7 +296,7 @@ public:
QSharedPointer<QNetworkSession> networkSession;
#endif
Http2::ProtocolParameters http2Parameters;
QHttp2Configuration http2Parameters;
QString peerVerifyName;
// If network status monitoring is enabled, we activate connectionMonitor

View File

@ -40,6 +40,7 @@
#include "qhttpnetworkconnectionchannel_p.h"
#include "qhttpnetworkconnection_p.h"
#include "qhttp2configuration.h"
#include "private/qnoncontiguousbytedevice_p.h"
#include <qpair.h>
@ -48,6 +49,7 @@
#include <private/qhttp2protocolhandler_p.h>
#include <private/qhttpprotocolhandler_p.h>
#include <private/qspdyprotocolhandler_p.h>
#include <private/http2protocol_p.h>
#ifndef QT_NO_SSL
# include <private/qsslsocket_p.h>
@ -947,9 +949,7 @@ void QHttpNetworkConnectionChannel::_q_connected()
if (tryProtocolUpgrade) {
// Let's augment our request with some magic headers and try to
// switch to HTTP/2.
const Http2::ProtocolParameters params(connection->http2Parameters());
Q_ASSERT(params.validate());
params.addProtocolUpgradeHeaders(&request);
Http2::appendProtocolUpgradeHeaders(connection->http2Parameters(), &request);
}
sendRequest();
}

Some files were not shown because too many files have changed in this diff Show More