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

Change-Id: Ibee5acec72a1a1769d4bc5f23f56c7dc8d4cf3cb
This commit is contained in:
Qt Forward Merge Bot 2020-03-11 01:00:56 +01:00 committed by Sona Kurazyan
commit 865afac250
131 changed files with 6139 additions and 1172 deletions

View File

@ -56,29 +56,28 @@
#include <math.h> #include <math.h>
//! [0] //! [0]
const double DefaultCenterX = -0.637011f; const double DefaultCenterX = -0.637011;
const double DefaultCenterY = -0.0395159f; const double DefaultCenterY = -0.0395159;
const double DefaultScale = 0.00403897f; const double DefaultScale = 0.00403897;
const double ZoomInFactor = 0.8f; const double ZoomInFactor = 0.8;
const double ZoomOutFactor = 1 / ZoomInFactor; const double ZoomOutFactor = 1 / ZoomInFactor;
const int ScrollStep = 20; const int ScrollStep = 20;
//! [0] //! [0]
//! [1] //! [1]
MandelbrotWidget::MandelbrotWidget(QWidget *parent) MandelbrotWidget::MandelbrotWidget(QWidget *parent) :
: QWidget(parent) QWidget(parent),
centerX(DefaultCenterX),
centerY(DefaultCenterY),
pixmapScale(DefaultScale),
curScale(DefaultScale)
{ {
centerX = DefaultCenterX;
centerY = DefaultCenterY;
pixmapScale = DefaultScale;
curScale = DefaultScale;
connect(&thread, &RenderThread::renderedImage, connect(&thread, &RenderThread::renderedImage,
this, &MandelbrotWidget::updatePixmap); this, &MandelbrotWidget::updatePixmap);
setWindowTitle(tr("Mandelbrot")); setWindowTitle(tr("Mandelbrot"));
#ifndef QT_NO_CURSOR #if QT_CONFIG(cursor)
setCursor(Qt::CrossCursor); setCursor(Qt::CrossCursor);
#endif #endif
resize(550, 400); resize(550, 400);
@ -102,7 +101,7 @@ void MandelbrotWidget::paintEvent(QPaintEvent * /* event */)
//! [4] //! [4]
//! [5] //! [5]
if (curScale == pixmapScale) { if (qFuzzyCompare(curScale, pixmapScale)) {
//! [5] //! [6] //! [5] //! [6]
painter.drawPixmap(pixmapOffset, pixmap); painter.drawPixmap(pixmapOffset, pixmap);
//! [6] //! [7] //! [6] //! [7]
@ -176,8 +175,8 @@ void MandelbrotWidget::keyPressEvent(QKeyEvent *event)
//! [12] //! [12]
void MandelbrotWidget::wheelEvent(QWheelEvent *event) void MandelbrotWidget::wheelEvent(QWheelEvent *event)
{ {
int numDegrees = event->angleDelta().y() / 8; const int numDegrees = event->angleDelta().y() / 8;
double numSteps = numDegrees / 15.0f; const double numSteps = numDegrees / double(15);
zoom(pow(ZoomInFactor, numSteps)); zoom(pow(ZoomInFactor, numSteps));
} }
//! [12] //! [12]

View File

@ -57,9 +57,6 @@
RenderThread::RenderThread(QObject *parent) RenderThread::RenderThread(QObject *parent)
: QThread(parent) : QThread(parent)
{ {
restart = false;
abort = false;
for (int i = 0; i < ColormapSize; ++i) for (int i = 0; i < ColormapSize; ++i)
colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize)); colormap[i] = rgbFromWaveLength(380.0 + (i * 400.0 / ColormapSize));
} }
@ -102,10 +99,10 @@ void RenderThread::run()
{ {
forever { forever {
mutex.lock(); mutex.lock();
QSize resultSize = this->resultSize; const QSize resultSize = this->resultSize;
double scaleFactor = this->scaleFactor; const double scaleFactor = this->scaleFactor;
double centerX = this->centerX; const double centerX = this->centerX;
double centerY = this->centerY; const double centerY = this->centerY;
mutex.unlock(); mutex.unlock();
//! [3] //! [3]
@ -128,20 +125,20 @@ void RenderThread::run()
if (abort) if (abort)
return; return;
uint *scanLine = auto scanLine =
reinterpret_cast<uint *>(image.scanLine(y + halfHeight)); reinterpret_cast<uint *>(image.scanLine(y + halfHeight));
double ay = centerY + (y * scaleFactor); const double ay = centerY + (y * scaleFactor);
for (int x = -halfWidth; x < halfWidth; ++x) { for (int x = -halfWidth; x < halfWidth; ++x) {
double ax = centerX + (x * scaleFactor); const double ax = centerX + (x * scaleFactor);
double a1 = ax; double a1 = ax;
double b1 = ay; double b1 = ay;
int numIterations = 0; int numIterations = 0;
do { do {
++numIterations; ++numIterations;
double a2 = (a1 * a1) - (b1 * b1) + ax; const double a2 = (a1 * a1) - (b1 * b1) + ax;
double b2 = (2 * a1 * b1) + ay; const double b2 = (2 * a1 * b1) + ay;
if ((a2 * a2) + (b2 * b2) > Limit) if ((a2 * a2) + (b2 * b2) > Limit)
break; break;
@ -187,9 +184,9 @@ void RenderThread::run()
//! [10] //! [10]
uint RenderThread::rgbFromWaveLength(double wave) uint RenderThread::rgbFromWaveLength(double wave)
{ {
double r = 0.0; double r = 0;
double g = 0.0; double g = 0;
double b = 0.0; double b = 0;
if (wave >= 380.0 && wave <= 440.0) { if (wave >= 380.0 && wave <= 440.0) {
r = -1.0 * (wave - 440.0) / (440.0 - 380.0); r = -1.0 * (wave - 440.0) / (440.0 - 380.0);

View File

@ -78,7 +78,7 @@ protected:
void run() override; void run() override;
private: private:
uint rgbFromWaveLength(double wave); static uint rgbFromWaveLength(double wave);
QMutex mutex; QMutex mutex;
QWaitCondition condition; QWaitCondition condition;
@ -86,8 +86,8 @@ private:
double centerY; double centerY;
double scaleFactor; double scaleFactor;
QSize resultSize; QSize resultSize;
bool restart; bool restart = false;
bool abort; bool abort = false;
enum { ColormapSize = 512 }; enum { ColormapSize = 512 };
uint colormap[ColormapSize]; uint colormap[ColormapSize];

View File

@ -54,6 +54,7 @@
#include <QOpenGLContext> #include <QOpenGLContext>
#include <QOpenGLPaintDevice> #include <QOpenGLPaintDevice>
#include <QPainter> #include <QPainter>
#include <QPainterPath>
#include <QScreen> #include <QScreen>
#include <QTimer> #include <QTimer>

View File

@ -51,6 +51,7 @@
#include <QOpenGLWindow> #include <QOpenGLWindow>
#include <QScreen> #include <QScreen>
#include <QPainter> #include <QPainter>
#include <QPainterPath>
#include <QGuiApplication> #include <QGuiApplication>
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QStaticText> #include <QStaticText>

View File

@ -50,6 +50,7 @@
#include <QRasterWindow> #include <QRasterWindow>
#include <QPainter> #include <QPainter>
#include <QPainterPath>
#include <QGuiApplication> #include <QGuiApplication>
#include <QMatrix4x4> #include <QMatrix4x4>
#include <QTimer> #include <QTimer>

View File

@ -437,6 +437,9 @@
\snippet drilldown/imageitem.h 0 \snippet drilldown/imageitem.h 0
We declare a \c Type enum value for our custom item and reimplement
\l{QGreaphicsItem::}{type()}. This is done so we can safely use
qgraphicsitem_cast().
In addition, we implement a public \c id() function to be able to In addition, we implement a public \c id() function to be able to
identify the associated location and a public \c adjust() function identify the associated location and a public \c adjust() function
that can be called to ensure that the image item is given the that can be called to ensure that the image item is given the

View File

@ -60,8 +60,11 @@ class ImageItem : public QObject, public QGraphicsPixmapItem
Q_OBJECT Q_OBJECT
public: public:
enum { Type = UserType + 1 };
ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent = nullptr); ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent = nullptr);
int type() const override { return Type; }
void adjust(); void adjust();
int id() const; int id() const;

View File

@ -51,6 +51,7 @@
#include "renderarea.h" #include "renderarea.h"
#include <QPainter> #include <QPainter>
#include <QPainterPath>
//! [0] //! [0]
RenderArea::RenderArea(QWidget *parent) RenderArea::RenderArea(QWidget *parent)

View File

@ -52,6 +52,7 @@
#include <QComboBox> #include <QComboBox>
#include <QPainter> #include <QPainter>
#include <QPainterPath>
#include <QPushButton> #include <QPushButton>
#include <QStyleFactory> #include <QStyleFactory>

View File

@ -43,6 +43,9 @@ isEmpty(ALL_ANDROID_ABIS): ALL_ANDROID_ABIS = arm64-v8a armeabi-v7a x86_64 x86
CONFIG += $$ANDROID_PLATFORM CONFIG += $$ANDROID_PLATFORM
ANDROID_MIN_SDK_VERSION = $$replace(ANDROID_PLATFORM, "android-", "")
ANDROID_TARGET_SDK_VERSION = 28
NDK_LLVM_PATH = $$NDK_ROOT/toolchains/llvm/prebuilt/$$NDK_HOST NDK_LLVM_PATH = $$NDK_ROOT/toolchains/llvm/prebuilt/$$NDK_HOST
QMAKE_CC = $$NDK_LLVM_PATH/bin/clang QMAKE_CC = $$NDK_LLVM_PATH/bin/clang
QMAKE_CXX = $$NDK_LLVM_PATH/bin/clang++ QMAKE_CXX = $$NDK_LLVM_PATH/bin/clang++

View File

@ -53,6 +53,12 @@ contains(TEMPLATE, ".*app"):!build_pass:!android-embedded {
!isEmpty(ANDROID_VERSION_CODE): \ !isEmpty(ANDROID_VERSION_CODE): \
FILE_CONTENT += " \"android-version-code\": $$emitString($$ANDROID_VERSION_CODE)," FILE_CONTENT += " \"android-version-code\": $$emitString($$ANDROID_VERSION_CODE),"
!isEmpty(ANDROID_MIN_SDK_VERSION): \
FILE_CONTENT += " \"android-min-sdk-version\": $$emitString($$ANDROID_MIN_SDK_VERSION),"
!isEmpty(ANDROID_TARGET_SDK_VERSION): \
FILE_CONTENT += " \"android-target-sdk-version\": $$emitString($$ANDROID_TARGET_SDK_VERSION),"
!isEmpty(ANDROID_EXTRA_LIBS): \ !isEmpty(ANDROID_EXTRA_LIBS): \
FILE_CONTENT += " \"android-extra-libs\": $$emitString($$join(ANDROID_EXTRA_LIBS, ","))," FILE_CONTENT += " \"android-extra-libs\": $$emitString($$join(ANDROID_EXTRA_LIBS, ",")),"

View File

@ -1111,6 +1111,15 @@
\row \li designer \li The target is a plugin for \QD. \row \li designer \li The target is a plugin for \QD.
\row \li no_lflags_merge \li Ensures that the list of libraries stored in the \row \li no_lflags_merge \li Ensures that the list of libraries stored in the
\c LIBS variable is not reduced to a list of unique values before it is used. \c LIBS variable is not reduced to a list of unique values before it is used.
\row \li metatypes \li Create a \c {<name>_metatypes.json} file for the
current project. \c {<name>} is the all lowercase base name of
\l TARGET.
\row \li qmltypes \li Automatically register QML types defined in C++.
For more information, see \l {Defining QML Types from C++}.
Also, create a \c {<template>.qmltypes} file for the current
project. \c <template> will be \c plugins (plural, for historical
reasons) if \c plugin is set, or the value of \l TEMPLATE otherwise.
\c qmltypes implies \c metatypes.
\endtable \endtable
These options define specific features on Windows only: These options define specific features on Windows only:
@ -2579,6 +2588,32 @@
For more information, see \l {Expressing Supported iOS Versions}. For more information, see \l {Expressing Supported iOS Versions}.
\section1 QML_IMPORT_MAJOR_VERSION
Specifies the major version to be used for automatically generated QML type
registrations. For more information, see \l {Defining QML Types from C++}.
\section1 QML_IMPORT_MINOR_VERSION
When automatically registering QML types defined in C++, register an
additional version of the module using this minor version. Generally,
minor versions to be registered are inferred from the meta objects.
You can use this variable if the meta objects have not changed and you
still want to import a QML module with a newer minor version number. For
example, \c MyModule metaobjects are at \c 1.1 level, but you want to import
the module as \c 1.3.
\section1 QML_IMPORT_VERSION
Specifies \l QML_IMPORT_MAJOR_VERSION and \l QML_IMPORT_MINOR_VERSION as a
\c {<major>.<minor>} version string.
\section1 QML_IMPORT_NAME
Specifies the module name to be used for automatically generated QML type
registrations. For more information, see \l {Defining QML Types from C++}.
\section1 QT \section1 QT
Specifies the \l{All Modules}{Qt modules} that are used by your project. For Specifies the \l{All Modules}{Qt modules} that are used by your project. For

View File

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

View File

@ -1,7 +1,5 @@
<?xml version='1.0' encoding='utf-8'?> <?xml version='1.0' encoding='utf-8'?>
<manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto"> <manifest package="org.qtproject.example" xmlns:android="http://schemas.android.com/apk/res/android" android:versionName="-- %%INSERT_VERSION_NAME%% --" android:versionCode="-- %%INSERT_VERSION_CODE%% --" android:installLocation="auto">
<uses-sdk android:minSdkVersion="23" android:targetSdkVersion="28"/>
<!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application. <!-- The following comment will be replaced upon deployment with default permissions based on the dependencies of the application.
Remove the comment if you do not require these default permissions. --> Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS --> <!-- %%INSERT_PERMISSIONS -->

View File

@ -5,7 +5,7 @@ buildscript {
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:3.5.0' classpath 'com.android.tools.build:gradle:3.6.0'
} }
} }
@ -59,4 +59,10 @@ android {
aaptOptions { aaptOptions {
noCompress 'rcc' noCompress 'rcc'
} }
defaultConfig {
resConfig "en"
minSdkVersion = qtMinSdkVersion
targetSdkVersion = qtTargetSdkVersion
}
} }

View File

@ -18,6 +18,8 @@ if (NOT ${PROJECT_NAME}-MultiAbiBuild)
option(ANDROID_BUILD_ABI_${abi} "Enable the build for Android ${abi}" ${abi_initial_value}) option(ANDROID_BUILD_ABI_${abi} "Enable the build for Android ${abi}" ${abi_initial_value})
endif() endif()
endforeach() endforeach()
option(ANDROID_MIN_SDK_VERSION "Android minimum SDK version" "21")
option(ANDROID_TARGET_SDK_VERSION "Android target SDK version" "28")
# Make sure to delete the "android-build" directory, which contains all the # Make sure to delete the "android-build" directory, which contains all the
# build artefacts, and also the androiddeployqt/gradle artefacts # build artefacts, and also the androiddeployqt/gradle artefacts
@ -101,6 +103,9 @@ if (NOT ${PROJECT_NAME}-MultiAbiBuild)
generate_json_variable(ANDROID_VERSION_NAME "android-version-name") generate_json_variable(ANDROID_VERSION_NAME "android-version-name")
generate_json_variable_list(ANDROID_EXTRA_LIBS "android-extra-libs") generate_json_variable_list(ANDROID_EXTRA_LIBS "android-extra-libs")
generate_json_variable_list(QML_IMPORT_PATH "qml-import-paths") generate_json_variable_list(QML_IMPORT_PATH "qml-import-paths")
generate_json_variable_list(ANDROID_MIN_SDK_VERSION "android-min-sdk-version")
generate_json_variable_list(ANDROID_TARGET_SDK_VERSION "android-target-sdk-version")
configure_file( configure_file(
"${CMAKE_BINARY_DIR}/android_deployment_settings.json.in" "${CMAKE_BINARY_DIR}/android_deployment_settings.json.in"

View File

@ -34,7 +34,7 @@
QMetaTypeId2 QObjectData QObjectUserData QMapNodeBase QMapNode QMapDataBase QMetaTypeId2 QObjectData QObjectUserData QMapNodeBase QMapNode QMapDataBase
QMapData QHashData QHashNode QArrayDataPointer QTextStreamManipulator QMapData QHashData QHashNode QArrayDataPointer QTextStreamManipulator
QContiguousCacheData QContiguousCacheTypedData QNoDebug QUrlTwoFlags QContiguousCacheData QContiguousCacheTypedData QNoDebug QUrlTwoFlags
QCborValueRef qfloat16 QDeferredDeleteEvent QSpecialInteger QLittleEndianStorageType QCborValueRef QDeferredDeleteEvent QSpecialInteger QLittleEndianStorageType
QBigEndianStorageType QFactoryInterface QFutureWatcherBase QJsonValuePtr QBigEndianStorageType QFactoryInterface QFutureWatcherBase QJsonValuePtr
QJsonValueRefPtr QAbstractConcatenable QStringBuilderCommon QJsonValueRefPtr QAbstractConcatenable QStringBuilderCommon
QTextCodec::ConverterState QThreadStorageData QTextStreamManipulator) QTextCodec::ConverterState QThreadStorageData QTextStreamManipulator)

View File

@ -179,6 +179,17 @@
rcc -compress 2 -compress-algo zlib myresources.qrc rcc -compress 2 -compress-algo zlib myresources.qrc
\endcode \endcode
It is also possible to use \c threshold, \c compress, and \c compress-algo
as attributes in a .qrc \c file tag.
\code
<qresource>
<file compress="1" compress-algo="zstd">data.txt</file>
</qresource>
\endcode
The above will select the \c zstd algorithm with compression level 1.
\c rcc supports the following compression algorithms and compression \c rcc supports the following compression algorithms and compression
levels: levels:
@ -196,10 +207,10 @@
library to choose an implementation-defined default. library to choose an implementation-defined default.
\li \c{zlib}: use the \l{https://zlib.net}{zlib} library to compress \li \c{zlib}: use the \l{https://zlib.net}{zlib} library to compress
contents. Valid compression levels range from 1 to 9, with 1the least contents. Valid compression levels range from 1 to 9, with 1 applying
compression (least CPU time) and 9 the most compression (most CPU time). the least compression (least CPU time) and 9 the most compression (most
The special value 0 means "no compression" and should not be used. The CPU time). The special value 0 means "no compression" and should not be
default is implementation-defined, but usually is level 6. used. The default is implementation-defined, but usually is level 6.
\li \c{none}: no compression. This is the same as the \c{-no-compress} \li \c{none}: no compression. This is the same as the \c{-no-compress}
option. option.

View File

@ -45,18 +45,20 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/*! /*!
\headerfile <QFloat16> \class qfloat16
\title 16-bit Floating Point Support \keyword 16-bit Floating Point Support
\ingroup funclists \ingroup funclists
\brief The <QFloat16> header file provides 16-bit floating point support. \inmodule QtCore
\inheaderfile QFloat16
\brief Provides 16-bit floating point support.
This header file provides support for half-precision (16-bit) floating The \c qfloat16 class provides support for half-precision (16-bit) floating
point data with the class \c qfloat16. It is fully compliant with IEEE point data. It is fully compliant with IEEE 754 as a storage type. This
754 as a storage type. This implies that any arithmetic operation on a implies that any arithmetic operation on a \c qfloat16 instance results in
\c qfloat16 instance results in the value first being converted to a the value first being converted to a \c float. This conversion to and from
\c float. This conversion to and from \c float is performed by hardware \c float is performed by hardware when possible, but on processors that do
when possible, but on processors that do not natively support half-precision, not natively support half-precision, the conversion is performed through a
the conversion is performed through a sequence of lookup table operations. sequence of lookup table operations.
\c qfloat16 should be treated as if it were a POD (plain old data) type. \c qfloat16 should be treated as if it were a POD (plain old data) type.
Consequently, none of the supported operations need any elaboration beyond Consequently, none of the supported operations need any elaboration beyond
@ -68,7 +70,7 @@ QT_BEGIN_NAMESPACE
/*! /*!
\macro QT_NO_FLOAT16_OPERATORS \macro QT_NO_FLOAT16_OPERATORS
\relates <QFloat16> \relates qfloat16
\since 5.12.4 \since 5.12.4
Defining this macro disables the arithmetic operators for qfloat16. Defining this macro disables the arithmetic operators for qfloat16.
@ -81,7 +83,7 @@ QT_BEGIN_NAMESPACE
/*! /*!
\fn bool qIsInf(qfloat16 f) \fn bool qIsInf(qfloat16 f)
\relates <QFloat16> \relates qfloat16
Returns true if the \c qfloat16 \a {f} is equivalent to infinity. Returns true if the \c qfloat16 \a {f} is equivalent to infinity.
@ -90,7 +92,7 @@ QT_BEGIN_NAMESPACE
/*! /*!
\fn bool qIsNaN(qfloat16 f) \fn bool qIsNaN(qfloat16 f)
\relates <QFloat16> \relates qfloat16
Returns true if the \c qfloat16 \a {f} is not a number (NaN). Returns true if the \c qfloat16 \a {f} is not a number (NaN).
@ -99,7 +101,7 @@ QT_BEGIN_NAMESPACE
/*! /*!
\fn bool qIsFinite(qfloat16 f) \fn bool qIsFinite(qfloat16 f)
\relates <QFloat16> \relates qfloat16
Returns true if the \c qfloat16 \a {f} is a finite number. Returns true if the \c qfloat16 \a {f} is a finite number.
@ -130,7 +132,7 @@ QT_BEGIN_NAMESPACE
\since 5.14 \since 5.14
\fn bool qfloat16::isNormal() const noexcept \fn bool qfloat16::isNormal() const noexcept
Tests whether this \c qfloat16 value is finite and in normal form. Returns \c true if this \c qfloat16 value is finite and in normal form.
\sa qFpClassify() \sa qFpClassify()
*/ */
@ -167,7 +169,7 @@ int qfloat16::fpClassify() const noexcept
} }
/*! \fn int qRound(qfloat16 value) /*! \fn int qRound(qfloat16 value)
\relates <QFloat16> \relates qfloat16
Rounds \a value to the nearest integer. Rounds \a value to the nearest integer.
@ -175,7 +177,7 @@ int qfloat16::fpClassify() const noexcept
*/ */
/*! \fn qint64 qRound64(qfloat16 value) /*! \fn qint64 qRound64(qfloat16 value)
\relates <QFloat16> \relates qfloat16
Rounds \a value to the nearest 64-bit integer. Rounds \a value to the nearest 64-bit integer.
@ -183,7 +185,7 @@ int qfloat16::fpClassify() const noexcept
*/ */
/*! \fn bool qFuzzyCompare(qfloat16 p1, qfloat16 p2) /*! \fn bool qFuzzyCompare(qfloat16 p1, qfloat16 p2)
\relates <QFloat16> \relates qfloat16
Compares the floating point value \a p1 and \a p2 and Compares the floating point value \a p1 and \a p2 and
returns \c true if they are considered equal, otherwise \c false. returns \c true if they are considered equal, otherwise \c false.
@ -256,7 +258,7 @@ static void qFloatFromFloat16_fast(float *, const quint16 *, qsizetype) noexcept
#endif #endif
/*! /*!
\since 5.11 \since 5.11
\relates <QFloat16> \relates qfloat16
Converts \a len floats from \a in to qfloat16 and stores them in \a out. Converts \a len floats from \a in to qfloat16 and stores them in \a out.
Both \a in and \a out must have \a len allocated entries. Both \a in and \a out must have \a len allocated entries.
@ -272,7 +274,7 @@ Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len
/*! /*!
\since 5.11 \since 5.11
\relates <QFloat16> \relates qfloat16
Converts \a len qfloat16 from \a in to floats and stores them in \a out. Converts \a len qfloat16 from \a in to floats and stores them in \a out.
Both \a in and \a out must have \a len allocated entries. Both \a in and \a out must have \a len allocated entries.

View File

@ -75,7 +75,7 @@ QLoggingRule::QLoggingRule() :
\internal \internal
Constructs a logging rule. Constructs a logging rule.
*/ */
QLoggingRule::QLoggingRule(const QStringRef &pattern, bool enabled) : QLoggingRule::QLoggingRule(QStringView pattern, bool enabled) :
messageType(-1), messageType(-1),
enabled(enabled) enabled(enabled)
{ {
@ -87,7 +87,7 @@ QLoggingRule::QLoggingRule(const QStringRef &pattern, bool enabled) :
Return value 1 means filter passed, 0 means filter doesn't influence this Return value 1 means filter passed, 0 means filter doesn't influence this
category, -1 means category doesn't pass this filter. category, -1 means category doesn't pass this filter.
*/ */
int QLoggingRule::pass(const QString &cat, QtMsgType msgType) const int QLoggingRule::pass(QLatin1String cat, QtMsgType msgType) const
{ {
// check message type // check message type
if (messageType > -1 && messageType != msgType) if (messageType > -1 && messageType != msgType)
@ -113,7 +113,7 @@ int QLoggingRule::pass(const QString &cat, QtMsgType msgType) const
return (enabled ? 1 : -1); return (enabled ? 1 : -1);
} else if (flags == RightFilter) { } else if (flags == RightFilter) {
// matches right // matches right
if (idx == (cat.count() - category.count())) if (idx == (cat.size() - category.count()))
return (enabled ? 1 : -1); return (enabled ? 1 : -1);
} }
} }
@ -129,26 +129,22 @@ int QLoggingRule::pass(const QString &cat, QtMsgType msgType) const
*.io.warning RightFilter, QtWarningMsg *.io.warning RightFilter, QtWarningMsg
*.core.* MidFilter *.core.* MidFilter
*/ */
void QLoggingRule::parse(const QStringRef &pattern) void QLoggingRule::parse(QStringView pattern)
{ {
QStringRef p; QStringView p;
// strip trailing ".messagetype" // strip trailing ".messagetype"
if (pattern.endsWith(QLatin1String(".debug"))) { if (pattern.endsWith(QLatin1String(".debug"))) {
p = QStringRef(pattern.string(), pattern.position(), p = pattern.chopped(6); // strlen(".debug")
pattern.length() - 6); // strlen(".debug")
messageType = QtDebugMsg; messageType = QtDebugMsg;
} else if (pattern.endsWith(QLatin1String(".info"))) { } else if (pattern.endsWith(QLatin1String(".info"))) {
p = QStringRef(pattern.string(), pattern.position(), p = pattern.chopped(5); // strlen(".info")
pattern.length() - 5); // strlen(".info")
messageType = QtInfoMsg; messageType = QtInfoMsg;
} else if (pattern.endsWith(QLatin1String(".warning"))) { } else if (pattern.endsWith(QLatin1String(".warning"))) {
p = QStringRef(pattern.string(), pattern.position(), p = pattern.chopped(8); // strlen(".warning")
pattern.length() - 8); // strlen(".warning")
messageType = QtWarningMsg; messageType = QtWarningMsg;
} else if (pattern.endsWith(QLatin1String(".critical"))) { } else if (pattern.endsWith(QLatin1String(".critical"))) {
p = QStringRef(pattern.string(), pattern.position(), p = pattern.chopped(9); // strlen(".critical")
pattern.length() - 9); // strlen(".critical")
messageType = QtCriticalMsg; messageType = QtCriticalMsg;
} else { } else {
p = pattern; p = pattern;
@ -159,11 +155,11 @@ void QLoggingRule::parse(const QStringRef &pattern)
} else { } else {
if (p.endsWith(QLatin1Char('*'))) { if (p.endsWith(QLatin1Char('*'))) {
flags |= LeftFilter; flags |= LeftFilter;
p = QStringRef(p.string(), p.position(), p.length() - 1); p = p.chopped(1);
} }
if (p.startsWith(QLatin1Char('*'))) { if (p.startsWith(QLatin1Char('*'))) {
flags |= RightFilter; flags |= RightFilter;
p = QStringRef(p.string(), p.position() + 1, p.length() - 1); p = p.mid(1);
} }
if (p.contains(QLatin1Char('*'))) // '*' only supported at start/end if (p.contains(QLatin1Char('*'))) // '*' only supported at start/end
flags = PatternFlags(); flags = PatternFlags();
@ -208,7 +204,7 @@ void QLoggingSettingsParser::setContent(QTextStream &stream)
_rules.clear(); _rules.clear();
QString line; QString line;
while (stream.readLineInto(&line)) while (stream.readLineInto(&line))
parseNextLine(QStringRef(&line)); parseNextLine(qToStringViewIgnoringNull(line));
} }
/*! /*!
@ -216,7 +212,7 @@ void QLoggingSettingsParser::setContent(QTextStream &stream)
Parses one line of the configuation file Parses one line of the configuation file
*/ */
void QLoggingSettingsParser::parseNextLine(QStringRef line) void QLoggingSettingsParser::parseNextLine(QStringView line)
{ {
// Remove whitespace at start and end of line: // Remove whitespace at start and end of line:
line = line.trimmed(); line = line.trimmed();
@ -227,7 +223,7 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line)
if (line.startsWith(QLatin1Char('[')) && line.endsWith(QLatin1Char(']'))) { if (line.startsWith(QLatin1Char('[')) && line.endsWith(QLatin1Char(']'))) {
// new section // new section
auto sectionName = line.mid(1, line.size() - 2).trimmed(); auto sectionName = line.mid(1).chopped(1).trimmed();
m_inRulesSection = sectionName.compare(QLatin1String("rules"), Qt::CaseInsensitive) == 0; m_inRulesSection = sectionName.compare(QLatin1String("rules"), Qt::CaseInsensitive) == 0;
return; return;
} }
@ -240,9 +236,9 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line)
#if QT_CONFIG(settings) #if QT_CONFIG(settings)
QString tmp; QString tmp;
QSettingsPrivate::iniUnescapedKey(key.toUtf8(), 0, key.length(), tmp); QSettingsPrivate::iniUnescapedKey(key.toUtf8(), 0, key.length(), tmp);
QStringRef pattern = QStringRef(&tmp, 0, tmp.length()); QStringView pattern = qToStringViewIgnoringNull(tmp);
#else #else
QStringRef pattern = key; QStringView pattern = key;
#endif #endif
const auto valueStr = line.mid(equalPos + 1).trimmed(); const auto valueStr = line.mid(equalPos + 1).trimmed();
int value = -1; int value = -1;
@ -252,7 +248,7 @@ void QLoggingSettingsParser::parseNextLine(QStringRef line)
value = 0; value = 0;
QLoggingRule rule(pattern, (value == 1)); QLoggingRule rule(pattern, (value == 1));
if (rule.flags != 0 && (value != -1)) if (rule.flags != 0 && (value != -1))
_rules.append(rule); _rules.append(std::move(rule));
else else
warnMsg("Ignoring malformed logging rule: '%s'", line.toUtf8().constData()); warnMsg("Ignoring malformed logging rule: '%s'", line.toUtf8().constData());
} else { } else {
@ -460,7 +456,7 @@ void QLoggingRegistry::defaultCategoryFilter(QLoggingCategory *cat)
debug = false; debug = false;
} }
QString categoryName = QLatin1String(cat->categoryName()); const auto categoryName = QLatin1String(cat->categoryName());
for (const auto &ruleSet : reg->ruleSets) { for (const auto &ruleSet : reg->ruleSets) {
for (const auto &rule : ruleSet) { for (const auto &rule : ruleSet) {

View File

@ -67,8 +67,8 @@ class Q_AUTOTEST_EXPORT QLoggingRule
{ {
public: public:
QLoggingRule(); QLoggingRule();
QLoggingRule(const QStringRef &pattern, bool enabled); QLoggingRule(QStringView pattern, bool enabled);
int pass(const QString &categoryName, QtMsgType type) const; int pass(QLatin1String categoryName, QtMsgType type) const;
enum PatternFlag { enum PatternFlag {
FullText = 0x1, FullText = 0x1,
@ -84,7 +84,7 @@ public:
bool enabled; bool enabled;
private: private:
void parse(const QStringRef &pattern); void parse(QStringView pattern);
}; };
Q_DECLARE_OPERATORS_FOR_FLAGS(QLoggingRule::PatternFlags) Q_DECLARE_OPERATORS_FOR_FLAGS(QLoggingRule::PatternFlags)
@ -101,7 +101,7 @@ public:
QVector<QLoggingRule> rules() const { return _rules; } QVector<QLoggingRule> rules() const { return _rules; }
private: private:
void parseNextLine(QStringRef line); void parseNextLine(QStringView line);
private: private:
bool m_inRulesSection = false; bool m_inRulesSection = false;

View File

@ -2475,12 +2475,11 @@ int QProcess::execute(const QString &program, const QStringList &arguments)
*/ */
int QProcess::execute(const QString &command) int QProcess::execute(const QString &command)
{ {
QProcess process; QStringList args = splitCommand(command);
process.setProcessChannelMode(ForwardedChannels); if (args.isEmpty())
process.start(command);
if (!process.waitForFinished(-1) || process.error() == FailedToStart)
return -2; return -2;
return process.exitStatus() == QProcess::NormalExit ? process.exitCode() : -1; QString program = args.takeFirst();
return execute(program, args);
} }
/*! /*!

View File

@ -732,7 +732,7 @@ const uchar *QResource::data() const
\note If the data was compressed, this function will decompress every time \note If the data was compressed, this function will decompress every time
it is called. The result is not cached between calls. it is called. The result is not cached between calls.
\sa uncompressedData(), size(), isCompressed(), isFile() \sa uncompressedSize(), size(), isCompressed(), isFile()
*/ */
QByteArray QResource::uncompressedData() const QByteArray QResource::uncompressedData() const

View File

@ -337,7 +337,7 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\value QPolygon QPolygon \value QPolygon QPolygon
\value QPolygonF QPolygonF \value QPolygonF QPolygonF
\value QColor QColor \value QColor QColor
\value QColorSpace QColorSpace \value QColorSpace QColorSpace (introduced in Qt 5.15)
\value QSizeF QSizeF \value QSizeF QSizeF
\value QRectF QRectF \value QRectF QRectF
\value QLine QLine \value QLine QLine
@ -383,7 +383,7 @@ Q_GLOBAL_STATIC(QMetaTypeCustomRegistry, customTypeRegistry)
\value QCborMap QCborMap \value QCborMap QCborMap
\value QCborSimpleType QCborSimpleType \value QCborSimpleType QCborSimpleType
\value QModelIndex QModelIndex \value QModelIndex QModelIndex
\value QPersistentModelIndex QPersistentModelIndex (since 5.5) \value QPersistentModelIndex QPersistentModelIndex (introduced in Qt 5.5)
\value QUuid QUuid \value QUuid QUuid
\value QByteArrayList QByteArrayList \value QByteArrayList QByteArrayList

View File

@ -26,9 +26,12 @@ qtConfig(mimetype) {
qtConfig(mimetype-database) { qtConfig(mimetype-database) {
outpath = .rcc outpath = .rcc
android {
outpath = $$outpath/$${QT_ARCH}
}
debug_and_release { debug_and_release {
CONFIG(debug, debug|release): outpath = .rcc/debug CONFIG(debug, debug|release): outpath = $$outpath/debug
else: outpath = .rcc/release else: outpath = $$outpath/release
} }
mimedb.depends = $$PWD/mime/generate.pl mimedb.depends = $$PWD/mime/generate.pl

View File

@ -219,8 +219,8 @@ public:
int count(const char *a) const; int count(const char *a) const;
int count(const QByteArray &a) const; int count(const QByteArray &a) const;
inline int compare(const char *c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline int compare(const char *c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
inline int compare(const QByteArray &a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const; inline int compare(const QByteArray &a, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
Q_REQUIRED_RESULT QByteArray left(int len) const; Q_REQUIRED_RESULT QByteArray left(int len) const;
Q_REQUIRED_RESULT QByteArray right(int len) const; Q_REQUIRED_RESULT QByteArray right(int len) const;
@ -555,12 +555,12 @@ inline bool QByteArray::contains(const QByteArray &a) const
{ return indexOf(a) != -1; } { return indexOf(a) != -1; }
inline bool QByteArray::contains(char c) const inline bool QByteArray::contains(char c) const
{ return indexOf(c) != -1; } { return indexOf(c) != -1; }
inline int QByteArray::compare(const char *c, Qt::CaseSensitivity cs) const inline int QByteArray::compare(const char *c, Qt::CaseSensitivity cs) const noexcept
{ {
return cs == Qt::CaseSensitive ? qstrcmp(*this, c) : return cs == Qt::CaseSensitive ? qstrcmp(*this, c) :
qstrnicmp(data(), size(), c, -1); qstrnicmp(data(), size(), c, -1);
} }
inline int QByteArray::compare(const QByteArray &a, Qt::CaseSensitivity cs) const inline int QByteArray::compare(const QByteArray &a, Qt::CaseSensitivity cs) const noexcept
{ {
return cs == Qt::CaseSensitive ? qstrcmp(*this, a) : return cs == Qt::CaseSensitive ? qstrcmp(*this, a) :
qstrnicmp(data(), size(), a.data(), a.size()); qstrnicmp(data(), size(), a.data(), a.size());

View File

@ -6154,6 +6154,16 @@ QString& QString::fill(QChar ch, int size)
sensitivity setting \a cs. sensitivity setting \a cs.
*/ */
/*!
\fn int QString::compare(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\since 5.14
\overload compare()
Performs a comparison of this with \a ch, using the case
sensitivity setting \a cs.
*/
#if QT_STRINGVIEW_LEVEL < 2 #if QT_STRINGVIEW_LEVEL < 2
/*! /*!
\overload compare() \overload compare()
@ -9575,6 +9585,23 @@ QString &QString::setRawData(const QChar *unicode, int size)
\sa front(), at(), operator[]() \sa front(), at(), operator[]()
*/ */
/*!
\fn int QLatin1String::compare(QStringView str, Qt::CaseSensitivity cs) const
\fn int QLatin1String::compare(QLatin1String l1, Qt::CaseSensitivity cs) const
\fn int QLatin1String::compare(QChar ch) const
\fn int QLatin1String::compare(QChar ch, Qt::CaseSensitivity cs) const
\since 5.14
Returns an integer that compares to zero as this Latin-1 string compares to the
string-view \a str, Latin-1 string \a l1, or character \a ch, respectively.
If \a cs is Qt::CaseSensitive (the default), the comparison is case sensitive;
otherwise the comparison is case-insensitive.
\sa operator==(), operator<(), operator>()
*/
/*! /*!
\fn bool QLatin1String::startsWith(QStringView str, Qt::CaseSensitivity cs) const \fn bool QLatin1String::startsWith(QStringView str, Qt::CaseSensitivity cs) const
\since 5.10 \since 5.10
@ -10941,6 +10968,19 @@ QStringRef QStringRef::appendTo(QString *string) const
Equivalent to \c {compare(*this, other, cs)}. Equivalent to \c {compare(*this, other, cs)}.
*/ */
/*!
\overload
\fn int QStringRef::compare(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const
\since 5.14
Compares this string with \a ch and returns an
integer less than, equal to, or greater than zero if this string
is less than, equal to, or greater than \a ch, interpreted as a string of length one.
If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
otherwise the comparison is case insensitive.
*/
/*! /*!
\overload \overload
\fn int QStringRef::compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const \fn int QStringRef::compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const

View File

@ -110,6 +110,15 @@ public:
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char front() const { return at(0); } Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char front() const { return at(0); }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char back() const { return at(size() - 1); } Q_REQUIRED_RESULT Q_DECL_CONSTEXPR QLatin1Char back() const { return at(size() - 1); }
Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::compareStrings(*this, other, cs); }
Q_REQUIRED_RESULT int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::compareStrings(*this, other, cs); }
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR int compare(QChar c) const noexcept
{ return isEmpty() || front() == c ? size() - 1 : uchar(m_data[0]) - c.unicode() ; }
Q_REQUIRED_RESULT int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); } { return QtPrivate::startsWith(*this, s, cs); }
Q_REQUIRED_RESULT bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept Q_REQUIRED_RESULT bool startsWith(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
@ -232,6 +241,8 @@ Q_DECL_CONSTEXPR bool QtPrivate::isLatin1(QLatin1String) noexcept
// //
// QStringView members that require QLatin1String: // QStringView members that require QLatin1String:
// //
int QStringView::compare(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::compareStrings(*this, s, cs); }
bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept bool QStringView::startsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); } { return QtPrivate::startsWith(*this, s, cs); }
bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
@ -729,6 +740,8 @@ public:
#endif #endif
int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
inline int compare(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; inline int compare(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
int compare(QChar ch, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return compare(QStringView{&ch, 1}, cs); }
static inline int compare(const QString &s1, const QString &s2, static inline int compare(const QString &s1, const QString &s2,
Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept Qt::CaseSensitivity cs = Qt::CaseSensitive) noexcept
@ -1615,6 +1628,8 @@ public:
int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; int compare(const QString &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; int compare(const QStringRef &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
int compare(QChar c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
int compare(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept; int compare(QLatin1String s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII) #if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
int compare(const QByteArray &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const int compare(const QByteArray &s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const

View File

@ -692,15 +692,29 @@ QT_BEGIN_NAMESPACE
*/ */
/*! /*!
\fn int QStringView::compare(QStringView other, Qt::CaseSensitivity cs) const \fn int QStringView::compare(QStringView str, Qt::CaseSensitivity cs) const
\since 5.12 \since 5.12
Compares this string-view with the \a other string-view and returns an Returns an integer that compares to zero as this string-view compares to the
integer less than, equal to, or greater than zero if this string-view string-view \a str.
is less than, equal to, or greater than the other string-view.
If \a cs is Qt::CaseSensitive, the comparison is case sensitive; If \a cs is Qt::CaseSensitive (the default), the comparison is case sensitive;
otherwise the comparison is case insensitive. otherwise the comparison is case-insensitive.
\sa operator==(), operator<(), operator>()
*/
/*!
\fn int QStringView::compare(QLatin1String l1, Qt::CaseSensitivity cs) const
\fn int QStringView::compare(QChar ch) const
\fn int QStringView::compare(QChar ch, Qt::CaseSensitivity cs) const
\since 5.14
Returns an integer that compares to zero as this string-view compares to the
Latin-1 string \a l1, or character \a ch, respectively.
If \a cs is Qt::CaseSensitive (the default), the comparison is case sensitive;
otherwise the comparison is case-insensitive.
\sa operator==(), operator<(), operator>() \sa operator==(), operator<(), operator>()
*/ */

View File

@ -257,6 +257,11 @@ public:
Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::compareStrings(*this, other, cs); } { return QtPrivate::compareStrings(*this, other, cs); }
Q_REQUIRED_RESULT inline int compare(QLatin1String other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept;
Q_REQUIRED_RESULT Q_DECL_CONSTEXPR int compare(QChar c) const noexcept
{ return empty() || front() == c ? size() - 1 : *utf16() - c.unicode() ; }
Q_REQUIRED_RESULT int compare(QChar c, Qt::CaseSensitivity cs) const noexcept
{ return QtPrivate::compareStrings(*this, QStringView(&c, 1), cs); }
Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept Q_REQUIRED_RESULT bool startsWith(QStringView s, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ return QtPrivate::startsWith(*this, s, cs); } { return QtPrivate::startsWith(*this, s, cs); }

View File

@ -49,9 +49,8 @@
****************************************************************************/ ****************************************************************************/
//! [0] //! [0]
QPixmap* pp;
QPixmap p; QPixmap p;
if ((pp=QPixmapCache::find("my_big_image", pm))) { if (QPixmap *pp = QPixmapCache::find("my_big_image"))) {
p = *pp; p = *pp;
} else { } else {
p.load("bigimage.png"); p.load("bigimage.png");

View File

@ -68,6 +68,11 @@
#include <private/qimage_p.h> #include <private/qimage_p.h>
#include <private/qfont_p.h> #include <private/qfont_p.h>
#if QT_CONFIG(thread)
#include "qsemaphore.h"
#include "qthreadpool.h"
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
static inline bool isLocked(QImageData *data) static inline bool isLocked(QImageData *data)
@ -4861,18 +4866,43 @@ void QImage::applyColorTransform(const QColorTransform &transform)
Q_UNREACHABLE(); Q_UNREACHABLE();
} }
std::function<void(int,int)> transformSegment;
if (depth() > 32) { if (depth() > 32) {
for (int i = 0; i < height(); ++i) { transformSegment = [&](int yStart, int yEnd) {
QRgba64 *scanline = reinterpret_cast<QRgba64 *>(scanLine(i)); for (int y = yStart; y < yEnd; ++y) {
transform.d->apply(scanline, scanline, width(), flags); QRgba64 *scanline = reinterpret_cast<QRgba64 *>(scanLine(y));
} transform.d->apply(scanline, scanline, width(), flags);
}
};
} else { } else {
for (int i = 0; i < height(); ++i) { transformSegment = [&](int yStart, int yEnd) {
QRgb *scanline = reinterpret_cast<QRgb *>(scanLine(i)); for (int y = yStart; y < yEnd; ++y) {
transform.d->apply(scanline, scanline, width(), flags); QRgb *scanline = reinterpret_cast<QRgb *>(scanLine(y));
} transform.d->apply(scanline, scanline, width(), flags);
}
};
} }
#if QT_CONFIG(thread)
int segments = sizeInBytes() / (1<<16);
segments = std::min(segments, height());
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (height() - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
transformSegment(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
} else
#endif
transformSegment(0, height());
if (oldFormat != format()) if (oldFormat != format())
*this = std::move(*this).convertToFormat(oldFormat); *this = std::move(*this).convertToFormat(oldFormat);
} }

View File

@ -43,7 +43,12 @@
#include <private/qendian_p.h> #include <private/qendian_p.h>
#include <private/qsimd_p.h> #include <private/qsimd_p.h>
#include <private/qimage_p.h> #include <private/qimage_p.h>
#include <qendian.h> #include <qendian.h>
#if QT_CONFIG(thread)
#include <qsemaphore.h>
#include <qthreadpool.h>
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -159,12 +164,8 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
// Cannot be used with indexed formats. // Cannot be used with indexed formats.
Q_ASSERT(dest->format > QImage::Format_Indexed8); Q_ASSERT(dest->format > QImage::Format_Indexed8);
Q_ASSERT(src->format > QImage::Format_Indexed8); Q_ASSERT(src->format > QImage::Format_Indexed8);
uint buf[BufferSize];
uint *buffer = buf;
const QPixelLayout *srcLayout = &qPixelLayouts[src->format]; const QPixelLayout *srcLayout = &qPixelLayouts[src->format];
const QPixelLayout *destLayout = &qPixelLayouts[dest->format]; const QPixelLayout *destLayout = &qPixelLayouts[dest->format];
const uchar *srcData = src->data;
uchar *destData = dest->data;
FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM; FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM; ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
@ -197,59 +198,110 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
else else
store = destLayout->storeFromRGB32; store = destLayout->storeFromRGB32;
} }
QDitherInfo dither;
QDitherInfo *ditherPtr = nullptr;
if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
ditherPtr = &dither;
for (int y = 0; y < src->height; ++y) { auto convertSegment = [=](int yStart, int yEnd) {
dither.y = y; uint buf[BufferSize];
int x = 0; uint *buffer = buf;
while (x < src->width) { const uchar *srcData = src->data + src->bytes_per_line * yStart;
dither.x = x; uchar *destData = dest->data + dest->bytes_per_line * yStart;
int l = src->width - x; QDitherInfo dither;
if (destLayout->bpp == QPixelLayout::BPP32) QDitherInfo *ditherPtr = nullptr;
buffer = reinterpret_cast<uint *>(destData) + x; if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
else ditherPtr = &dither;
l = qMin(l, BufferSize); for (int y = yStart; y < yEnd; ++y) {
const uint *ptr = fetch(buffer, srcData, x, l, nullptr, ditherPtr); dither.y = y;
store(destData, ptr, x, l, nullptr, ditherPtr); int x = 0;
x += l; while (x < src->width) {
dither.x = x;
int l = src->width - x;
if (destLayout->bpp == QPixelLayout::BPP32)
buffer = reinterpret_cast<uint *>(destData) + x;
else
l = qMin(l, BufferSize);
const uint *ptr = fetch(buffer, srcData, x, l, 0, ditherPtr);
store(destData, ptr, x, l, 0, ditherPtr);
x += l;
}
srcData += src->bytes_per_line;
destData += dest->bytes_per_line;
} }
srcData += src->bytes_per_line; };
destData += dest->bytes_per_line;
#if QT_CONFIG(thread)
int segments = src->nbytes / (1<<16);
segments = std::min(segments, src->height);
if (segments <= 1)
return convertSegment(0, src->height);
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (src->height - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
convertSegment(y, y + yn);
semaphore.release(1);
});
y += yn;
} }
semaphore.acquire(segments);
#else
convertSegment(0, src->height);
#endif
} }
void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags) void convert_generic_to_rgb64(QImageData *dest, const QImageData *src, Qt::ImageConversionFlags)
{ {
Q_ASSERT(dest->format > QImage::Format_Indexed8); Q_ASSERT(dest->format > QImage::Format_Indexed8);
Q_ASSERT(src->format > QImage::Format_Indexed8); Q_ASSERT(src->format > QImage::Format_Indexed8);
QRgba64 buf[BufferSize];
QRgba64 *buffer = buf;
const QPixelLayout *srcLayout = &qPixelLayouts[src->format]; const QPixelLayout *srcLayout = &qPixelLayouts[src->format];
const QPixelLayout *destLayout = &qPixelLayouts[dest->format]; const QPixelLayout *destLayout = &qPixelLayouts[dest->format];
const uchar *srcData = src->data;
uchar *destData = dest->data;
const FetchAndConvertPixelsFunc64 fetch = srcLayout->fetchToRGBA64PM; const FetchAndConvertPixelsFunc64 fetch = srcLayout->fetchToRGBA64PM;
const ConvertAndStorePixelsFunc64 store = qStoreFromRGBA64PM[dest->format]; const ConvertAndStorePixelsFunc64 store = qStoreFromRGBA64PM[dest->format];
for (int y = 0; y < src->height; ++y) { auto convertSegment = [=](int yStart, int yEnd) {
int x = 0; QRgba64 buf[BufferSize];
while (x < src->width) { QRgba64 *buffer = buf;
int l = src->width - x; const uchar *srcData = src->data + yStart * src->bytes_per_line;
if (destLayout->bpp == QPixelLayout::BPP64) uchar *destData = dest->data + yStart * dest->bytes_per_line;
buffer = reinterpret_cast<QRgba64 *>(destData) + x; for (int y = yStart; y < yEnd; ++y) {
else int x = 0;
l = qMin(l, BufferSize); while (x < src->width) {
const QRgba64 *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr); int l = src->width - x;
store(destData, ptr, x, l, nullptr, nullptr); if (destLayout->bpp == QPixelLayout::BPP64)
x += l; buffer = reinterpret_cast<QRgba64 *>(destData) + x;
else
l = qMin(l, BufferSize);
const QRgba64 *ptr = fetch(buffer, srcData, x, l, nullptr, nullptr);
store(destData, ptr, x, l, nullptr, nullptr);
x += l;
}
srcData += src->bytes_per_line;
destData += dest->bytes_per_line;
} }
srcData += src->bytes_per_line; };
destData += dest->bytes_per_line; #if QT_CONFIG(thread)
int segments = src->nbytes / (1<<16);
segments = std::min(segments, src->height);
if (segments <= 1)
return convertSegment(0, src->height);
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (src->height - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
convertSegment(y, y + yn);
semaphore.release(1);
});
y += yn;
} }
semaphore.acquire(segments);
#else
convertSegment(0, src->height);
#endif
} }
bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags flags) bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::ImageConversionFlags flags)
@ -270,11 +322,6 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
&& qt_highColorPrecision(dst_format, !srcLayout->hasAlphaChannel)) && qt_highColorPrecision(dst_format, !srcLayout->hasAlphaChannel))
return false; return false;
uint buf[BufferSize];
uint *buffer = buf;
uchar *srcData = data->data;
uchar *destData = data->data;
QImageData::ImageSizeParameters params = { data->bytes_per_line, data->nbytes }; QImageData::ImageSizeParameters params = { data->bytes_per_line, data->nbytes };
if (data->depth != destDepth) { if (data->depth != destDepth) {
params = QImageData::calculateImageParameters(data->width, data->height, destDepth); params = QImageData::calculateImageParameters(data->width, data->height, destDepth);
@ -313,28 +360,52 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
else else
store = destLayout->storeFromRGB32; store = destLayout->storeFromRGB32;
} }
QDitherInfo dither;
QDitherInfo *ditherPtr = nullptr;
if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
ditherPtr = &dither;
for (int y = 0; y < data->height; ++y) { auto convertSegment = [=](int yStart, int yEnd) {
dither.y = y; uint buf[BufferSize];
int x = 0; uint *buffer = buf;
while (x < data->width) { uchar *srcData = data->data + data->bytes_per_line * yStart;
dither.x = x; uchar *destData = srcData;
int l = data->width - x; QDitherInfo dither;
if (srcLayout->bpp == QPixelLayout::BPP32) QDitherInfo *ditherPtr = nullptr;
buffer = reinterpret_cast<uint *>(srcData) + x; if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
else ditherPtr = &dither;
l = qMin(l, BufferSize); for (int y = yStart; y < yEnd; ++y) {
const uint *ptr = fetch(buffer, srcData, x, l, nullptr, ditherPtr); dither.y = y;
store(destData, ptr, x, l, nullptr, ditherPtr); int x = 0;
x += l; while (x < data->width) {
dither.x = x;
int l = data->width - x;
if (srcLayout->bpp == QPixelLayout::BPP32)
buffer = reinterpret_cast<uint *>(srcData) + x;
else
l = qMin(l, BufferSize);
const uint *ptr = fetch(buffer, srcData, x, l, nullptr, ditherPtr);
store(destData, ptr, x, l, nullptr, ditherPtr);
x += l;
}
srcData += data->bytes_per_line;
destData += params.bytesPerLine;
} }
srcData += data->bytes_per_line; };
destData += params.bytesPerLine; #if QT_CONFIG(thread)
} int segments = data->nbytes / (1<<16);
segments = std::min(segments, data->height);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (data->height - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
convertSegment(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
} else
#endif
convertSegment(0, data->height);
if (params.totalSize != data->nbytes) { if (params.totalSize != data->nbytes) {
Q_ASSERT(params.totalSize < data->nbytes); Q_ASSERT(params.totalSize < data->nbytes);
void *newData = realloc(data->data, params.totalSize); void *newData = realloc(data->data, params.totalSize);

View File

@ -43,6 +43,11 @@
#include "qcolor.h" #include "qcolor.h"
#include "qrgba64_p.h" #include "qrgba64_p.h"
#if QT_CONFIG(thread)
#include "qsemaphore.h"
#include "qthreadpool.h"
#endif
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
/* /*
@ -239,6 +244,8 @@ static QImageScaleInfo* QImageScale::qimageCalcScaleInfo(const QImage &img,
isi = new QImageScaleInfo; isi = new QImageScaleInfo;
if (!isi) if (!isi)
return nullptr; return nullptr;
isi->sh = sh;
isi->sw = sw;
isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1); isi->xup_yup = (qAbs(dw) >= sw) + ((qAbs(dh) >= sh) << 1);
@ -303,33 +310,54 @@ static void qt_qimageScaleAARGBA_up_xy(QImageScaleInfo *isi, unsigned int *dest,
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
/* go through every scanline in the output buffer */ /* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
/* calculate the source line we'll scan from */ for (int y = yStart; y < yEnd; ++y) {
const unsigned int *sptr = ypoints[y]; /* calculate the source line we'll scan from */
unsigned int *dptr = dest + (y * dow); const unsigned int *sptr = ypoints[y];
const int yap = yapoints[y]; unsigned int *dptr = dest + (y * dow);
if (yap > 0) { const int yap = yapoints[y];
for (int x = 0; x < dw; x++) { if (yap > 0) {
const unsigned int *pix = sptr + xpoints[x]; for (int x = 0; x < dw; x++) {
const int xap = xapoints[x]; const unsigned int *pix = sptr + xpoints[x];
if (xap > 0) const int xap = xapoints[x];
*dptr = interpolate_4_pixels(pix, pix + sow, xap, yap); if (xap > 0)
else *dptr = interpolate_4_pixels(pix, pix + sow, xap, yap);
*dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - yap, pix[sow], yap); else
dptr++; *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - yap, pix[sow], yap);
} dptr++;
} else { }
for (int x = 0; x < dw; x++) { } else {
const unsigned int *pix = sptr + xpoints[x]; for (int x = 0; x < dw; x++) {
const int xap = xapoints[x]; const unsigned int *pix = sptr + xpoints[x];
if (xap > 0) const int xap = xapoints[x];
*dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap); if (xap > 0)
else *dptr = INTERPOLATE_PIXEL_256(pix[0], 256 - xap, pix[1], xap);
*dptr = pix[0]; else
dptr++; *dptr = pix[0];
dptr++;
}
} }
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
/* scale by area sampling - with alpha */ /* scale by area sampling - with alpha */
@ -411,33 +439,54 @@ static void qt_qimageScaleAARGBA_up_x_down_y(QImageScaleInfo *isi, unsigned int
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
/* go through every scanline in the output buffer */ /* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = yapoints[y] >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = yapoints[y] & 0xffff; int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
unsigned int *dptr = dest + (y * dow); unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
int r, g, b, a; int r, g, b, a;
qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, r, g, b, a); qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, r, g, b, a);
int xap = xapoints[x]; int xap = xapoints[x];
if (xap > 0) { if (xap > 0) {
int rr, gg, bb, aa; int rr, gg, bb, aa;
qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa); qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
r = r * (256 - xap); r = r * (256 - xap);
g = g * (256 - xap); g = g * (256 - xap);
b = b * (256 - xap); b = b * (256 - xap);
a = a * (256 - xap); a = a * (256 - xap);
r = (r + (rr * xap)) >> 8; r = (r + (rr * xap)) >> 8;
g = (g + (gg * xap)) >> 8; g = (g + (gg * xap)) >> 8;
b = (b + (bb * xap)) >> 8; b = (b + (bb * xap)) >> 8;
a = (a + (aa * xap)) >> 8; a = (a + (aa * xap)) >> 8;
}
*dptr++ = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
} }
*dptr++ = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest, static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
@ -449,34 +498,55 @@ static void qt_qimageScaleAARGBA_down_x_up_y(QImageScaleInfo *isi, unsigned int
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
/* go through every scanline in the output buffer */ /* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
unsigned int *dptr = dest + (y * dow); for (int y = yStart; y < yEnd; ++y) {
for (int x = 0; x < dw; x++) { unsigned int *dptr = dest + (y * dow);
int Cx = xapoints[x] >> 16; for (int x = 0; x < dw; x++) {
int xap = xapoints[x] & 0xffff; int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
int r, g, b, a; int r, g, b, a;
qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, r, g, b, a); qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, r, g, b, a);
int yap = yapoints[y]; int yap = yapoints[y];
if (yap > 0) { if (yap > 0) {
int rr, gg, bb, aa; int rr, gg, bb, aa;
qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa); qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
r = r * (256 - yap); r = r * (256 - yap);
g = g * (256 - yap); g = g * (256 - yap);
b = b * (256 - yap); b = b * (256 - yap);
a = a * (256 - yap); a = a * (256 - yap);
r = (r + (rr * yap)) >> 8; r = (r + (rr * yap)) >> 8;
g = (g + (gg * yap)) >> 8; g = (g + (gg * yap)) >> 8;
b = (b + (bb * yap)) >> 8; b = (b + (bb * yap)) >> 8;
a = (a + (aa * yap)) >> 8; a = (a + (aa * yap)) >> 8;
}
*dptr = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
dptr++;
} }
*dptr = qRgba(r >> 14, g >> 14, b >> 14, a >> 14);
dptr++;
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest, static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *dest,
@ -487,45 +557,66 @@ static void qt_qimageScaleAARGBA_down_xy(QImageScaleInfo *isi, unsigned int *des
int *xapoints = isi->xapoints; int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = (yapoints[y]) >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = (yapoints[y]) & 0xffff; int Cy = (yapoints[y]) >> 16;
int yap = (yapoints[y]) & 0xffff;
unsigned int *dptr = dest + (y * dow); unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
int Cx = xapoints[x] >> 16; int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff; int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
int rx, gx, bx, ax; int rx, gx, bx, ax;
qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax); qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
int r = ((rx>>4) * yap); int r = ((rx>>4) * yap);
int g = ((gx>>4) * yap); int g = ((gx>>4) * yap);
int b = ((bx>>4) * yap); int b = ((bx>>4) * yap);
int a = ((ax>>4) * yap); int a = ((ax>>4) * yap);
int j; int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) { for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += ((rx>>4) * Cy);
g += ((gx>>4) * Cy);
b += ((bx>>4) * Cy);
a += ((ax>>4) * Cy);
}
sptr += sow; sptr += sow;
qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax); qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += ((rx>>4) * Cy);
g += ((gx>>4) * Cy); r += ((rx>>4) * j);
b += ((bx>>4) * Cy); g += ((gx>>4) * j);
a += ((ax>>4) * Cy); b += ((bx>>4) * j);
a += ((ax>>4) * j);
*dptr = qRgba(r >> 24, g >> 24, b >> 24, a >> 24);
dptr++;
} }
sptr += sow;
qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += ((rx>>4) * j);
g += ((gx>>4) * j);
b += ((bx>>4) * j);
a += ((ax>>4) * j);
*dptr = qRgba(r >> 24, g >> 24, b >> 24, a >> 24);
dptr++;
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
#if QT_CONFIG(raster_64bit) #if QT_CONFIG(raster_64bit)
@ -546,32 +637,53 @@ static void qt_qimageScaleRgba64_up_xy(QImageScaleInfo *isi, QRgba64 *dest,
int *xapoints = isi->xapoints; int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
const QRgba64 *sptr = ypoints[y]; for (int y = yStart; y < yEnd; ++y) {
QRgba64 *dptr = dest + (y * dow); const QRgba64 *sptr = ypoints[y];
const int yap = yapoints[y]; QRgba64 *dptr = dest + (y * dow);
if (yap > 0) { const int yap = yapoints[y];
for (int x = 0; x < dw; x++) { if (yap > 0) {
const QRgba64 *pix = sptr + xpoints[x]; for (int x = 0; x < dw; x++) {
const int xap = xapoints[x]; const QRgba64 *pix = sptr + xpoints[x];
if (xap > 0) const int xap = xapoints[x];
*dptr = interpolate_4_pixels_rgb64(pix, pix + sow, xap * 256, yap * 256); if (xap > 0)
else *dptr = interpolate_4_pixels_rgb64(pix, pix + sow, xap * 256, yap * 256);
*dptr = interpolate256(pix[0], 256 - yap, pix[sow], yap); else
dptr++; *dptr = interpolate256(pix[0], 256 - yap, pix[sow], yap);
} dptr++;
} else { }
for (int x = 0; x < dw; x++) { } else {
const QRgba64 *pix = sptr + xpoints[x]; for (int x = 0; x < dw; x++) {
const int xap = xapoints[x]; const QRgba64 *pix = sptr + xpoints[x];
if (xap > 0) const int xap = xapoints[x];
*dptr = interpolate256(pix[0], 256 - xap, pix[1], xap); if (xap > 0)
else *dptr = interpolate256(pix[0], 256 - xap, pix[1], xap);
*dptr = pix[0]; else
dptr++; *dptr = pix[0];
dptr++;
}
} }
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
void qt_qimageScaleRgba64(QImageScaleInfo *isi, QRgba64 *dest, void qt_qimageScaleRgba64(QImageScaleInfo *isi, QRgba64 *dest,
@ -616,33 +728,54 @@ static void qt_qimageScaleRgba64_up_x_down_y(QImageScaleInfo *isi, QRgba64 *dest
int *xapoints = isi->xapoints; int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = (yapoints[y]) >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = (yapoints[y]) & 0xffff; int Cy = (yapoints[y]) >> 16;
int yap = (yapoints[y]) & 0xffff;
QRgba64 *dptr = dest + (y * dow); QRgba64 *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
const QRgba64 *sptr = ypoints[y] + xpoints[x]; const QRgba64 *sptr = ypoints[y] + xpoints[x];
qint64 r, g, b, a; qint64 r, g, b, a;
qt_qimageScaleRgba64_helper(sptr, yap, Cy, sow, r, g, b, a); qt_qimageScaleRgba64_helper(sptr, yap, Cy, sow, r, g, b, a);
int xap = xapoints[x]; int xap = xapoints[x];
if (xap > 0) { if (xap > 0) {
qint64 rr, gg, bb, aa; qint64 rr, gg, bb, aa;
qt_qimageScaleRgba64_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa); qt_qimageScaleRgba64_helper(sptr + 1, yap, Cy, sow, rr, gg, bb, aa);
r = r * (256 - xap); r = r * (256 - xap);
g = g * (256 - xap); g = g * (256 - xap);
b = b * (256 - xap); b = b * (256 - xap);
a = a * (256 - xap); a = a * (256 - xap);
r = (r + (rr * xap)) >> 8; r = (r + (rr * xap)) >> 8;
g = (g + (gg * xap)) >> 8; g = (g + (gg * xap)) >> 8;
b = (b + (bb * xap)) >> 8; b = (b + (bb * xap)) >> 8;
a = (a + (aa * xap)) >> 8; a = (a + (aa * xap)) >> 8;
}
*dptr++ = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
} }
*dptr++ = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
static void qt_qimageScaleRgba64_down_x_up_y(QImageScaleInfo *isi, QRgba64 *dest, static void qt_qimageScaleRgba64_down_x_up_y(QImageScaleInfo *isi, QRgba64 *dest,
@ -653,34 +786,55 @@ static void qt_qimageScaleRgba64_down_x_up_y(QImageScaleInfo *isi, QRgba64 *dest
int *xapoints = isi->xapoints; int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
QRgba64 *dptr = dest + (y * dow); for (int y = yStart; y < yEnd; ++y) {
for (int x = 0; x < dw; x++) { QRgba64 *dptr = dest + (y * dow);
int Cx = xapoints[x] >> 16; for (int x = 0; x < dw; x++) {
int xap = xapoints[x] & 0xffff; int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const QRgba64 *sptr = ypoints[y] + xpoints[x]; const QRgba64 *sptr = ypoints[y] + xpoints[x];
qint64 r, g, b, a; qint64 r, g, b, a;
qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, r, g, b, a); qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, r, g, b, a);
int yap = yapoints[y]; int yap = yapoints[y];
if (yap > 0) { if (yap > 0) {
qint64 rr, gg, bb, aa; qint64 rr, gg, bb, aa;
qt_qimageScaleRgba64_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa); qt_qimageScaleRgba64_helper(sptr + sow, xap, Cx, 1, rr, gg, bb, aa);
r = r * (256 - yap); r = r * (256 - yap);
g = g * (256 - yap); g = g * (256 - yap);
b = b * (256 - yap); b = b * (256 - yap);
a = a * (256 - yap); a = a * (256 - yap);
r = (r + (rr * yap)) >> 8; r = (r + (rr * yap)) >> 8;
g = (g + (gg * yap)) >> 8; g = (g + (gg * yap)) >> 8;
b = (b + (bb * yap)) >> 8; b = (b + (bb * yap)) >> 8;
a = (a + (aa * yap)) >> 8; a = (a + (aa * yap)) >> 8;
}
*dptr = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
dptr++;
} }
*dptr = qRgba64(r >> 14, g >> 14, b >> 14, a >> 14);
dptr++;
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest, static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
@ -691,43 +845,64 @@ static void qt_qimageScaleRgba64_down_xy(QImageScaleInfo *isi, QRgba64 *dest,
int *xapoints = isi->xapoints; int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = (yapoints[y]) >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = (yapoints[y]) & 0xffff; int Cy = (yapoints[y]) >> 16;
int yap = (yapoints[y]) & 0xffff;
QRgba64 *dptr = dest + (y * dow); QRgba64 *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
int Cx = xapoints[x] >> 16; int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff; int xap = xapoints[x] & 0xffff;
const QRgba64 *sptr = ypoints[y] + xpoints[x]; const QRgba64 *sptr = ypoints[y] + xpoints[x];
qint64 rx, gx, bx, ax; qint64 rx, gx, bx, ax;
qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax); qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
qint64 r = rx * yap; qint64 r = rx * yap;
qint64 g = gx * yap; qint64 g = gx * yap;
qint64 b = bx * yap; qint64 b = bx * yap;
qint64 a = ax * yap; qint64 a = ax * yap;
int j; int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) { for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += rx * Cy;
g += gx * Cy;
b += bx * Cy;
a += ax * Cy;
}
sptr += sow; sptr += sow;
qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax); qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += rx * Cy; r += rx * j;
g += gx * Cy; g += gx * j;
b += bx * Cy; b += bx * j;
a += ax * Cy; a += ax * j;
}
sptr += sow;
qt_qimageScaleRgba64_helper(sptr, xap, Cx, 1, rx, gx, bx, ax);
r += rx * j;
g += gx * j;
b += bx * j;
a += ax * j;
*dptr = qRgba64(r >> 28, g >> 28, b >> 28, a >> 28); *dptr = qRgba64(r >> 28, g >> 28, b >> 28, a >> 28);
dptr++; dptr++;
}
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
#endif #endif
@ -817,31 +992,52 @@ static void qt_qimageScaleAARGB_up_x_down_y(QImageScaleInfo *isi, unsigned int *
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
/* go through every scanline in the output buffer */ /* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = yapoints[y] >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = yapoints[y] & 0xffff; int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
unsigned int *dptr = dest + (y * dow); unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
int r, g, b; int r, g, b;
qt_qimageScaleAARGB_helper(sptr, yap, Cy, sow, r, g, b); qt_qimageScaleAARGB_helper(sptr, yap, Cy, sow, r, g, b);
int xap = xapoints[x]; int xap = xapoints[x];
if (xap > 0) { if (xap > 0) {
int rr, bb, gg; int rr, bb, gg;
qt_qimageScaleAARGB_helper(sptr + 1, yap, Cy, sow, rr, gg, bb); qt_qimageScaleAARGB_helper(sptr + 1, yap, Cy, sow, rr, gg, bb);
r = r * (256 - xap); r = r * (256 - xap);
g = g * (256 - xap); g = g * (256 - xap);
b = b * (256 - xap); b = b * (256 - xap);
r = (r + (rr * xap)) >> 8; r = (r + (rr * xap)) >> 8;
g = (g + (gg * xap)) >> 8; g = (g + (gg * xap)) >> 8;
b = (b + (bb * xap)) >> 8; b = (b + (bb * xap)) >> 8;
}
*dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
} }
*dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest, static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *dest,
@ -853,31 +1049,52 @@ static void qt_qimageScaleAARGB_down_x_up_y(QImageScaleInfo *isi, unsigned int *
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
/* go through every scanline in the output buffer */ /* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
unsigned int *dptr = dest + (y * dow); for (int y = yStart; y < yEnd; ++y) {
for (int x = 0; x < dw; x++) { unsigned int *dptr = dest + (y * dow);
int Cx = xapoints[x] >> 16; for (int x = 0; x < dw; x++) {
int xap = xapoints[x] & 0xffff; int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
int r, g, b; int r, g, b;
qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, r, g, b); qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, r, g, b);
int yap = yapoints[y]; int yap = yapoints[y];
if (yap > 0) { if (yap > 0) {
int rr, bb, gg; int rr, bb, gg;
qt_qimageScaleAARGB_helper(sptr + sow, xap, Cx, 1, rr, gg, bb); qt_qimageScaleAARGB_helper(sptr + sow, xap, Cx, 1, rr, gg, bb);
r = r * (256 - yap); r = r * (256 - yap);
g = g * (256 - yap); g = g * (256 - yap);
b = b * (256 - yap); b = b * (256 - yap);
r = (r + (rr * yap)) >> 8; r = (r + (rr * yap)) >> 8;
g = (g + (gg * yap)) >> 8; g = (g + (gg * yap)) >> 8;
b = (b + (bb * yap)) >> 8; b = (b + (bb * yap)) >> 8;
}
*dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
} }
*dptr++ = qRgb(r >> 14, g >> 14, b >> 14);
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest, static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest,
@ -888,43 +1105,64 @@ static void qt_qimageScaleAARGB_down_xy(QImageScaleInfo *isi, unsigned int *dest
int *xapoints = isi->xapoints; int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = yapoints[y] >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = yapoints[y] & 0xffff; int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
unsigned int *dptr = dest + (y * dow); unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
int Cx = xapoints[x] >> 16; int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff; int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
int rx, gx, bx; int rx, gx, bx;
qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx); qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
int r = (rx >> 4) * yap; int r = (rx >> 4) * yap;
int g = (gx >> 4) * yap; int g = (gx >> 4) * yap;
int b = (bx >> 4) * yap; int b = (bx >> 4) * yap;
int j; int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) { for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
r += (rx >> 4) * Cy;
g += (gx >> 4) * Cy;
b += (bx >> 4) * Cy;
}
sptr += sow; sptr += sow;
qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx); qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
r += (rx >> 4) * Cy; r += (rx >> 4) * j;
g += (gx >> 4) * Cy; g += (gx >> 4) * j;
b += (bx >> 4) * Cy; b += (bx >> 4) * j;
*dptr = qRgb(r >> 24, g >> 24, b >> 24);
dptr++;
} }
sptr += sow;
qt_qimageScaleAARGB_helper(sptr, xap, Cx, 1, rx, gx, bx);
r += (rx >> 4) * j;
g += (gx >> 4) * j;
b += (bx >> 4) * j;
*dptr = qRgb(r >> 24, g >> 24, b >> 24);
dptr++;
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
QImage qSmoothScaleImage(const QImage &src, int dw, int dh) QImage qSmoothScaleImage(const QImage &src, int dw, int dh)

View File

@ -41,6 +41,11 @@
#include "qimage.h" #include "qimage.h"
#include <private/qsimd_p.h> #include <private/qsimd_p.h>
#if QT_CONFIG(thread)
#include "qsemaphore.h"
#include "qthreadpool.h"
#endif
#if defined(__ARM_NEON__) #if defined(__ARM_NEON__)
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -76,33 +81,54 @@ void qt_qimageScaleAARGBA_up_x_down_y_neon(QImageScaleInfo *isi, unsigned int *d
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
/* go through every scanline in the output buffer */ /* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = yapoints[y] >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = yapoints[y] & 0xffff; int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
unsigned int *dptr = dest + (y * dow); unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow); uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow);
int xap = xapoints[x]; int xap = xapoints[x];
if (xap > 0) { if (xap > 0) {
uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow); uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow);
vx = vmulq_n_u32(vx, 256 - xap); vx = vmulq_n_u32(vx, 256 - xap);
vr = vmulq_n_u32(vr, xap); vr = vmulq_n_u32(vr, xap);
vx = vaddq_u32(vx, vr); vx = vaddq_u32(vx, vr);
vx = vshrq_n_u32(vx, 8); vx = vshrq_n_u32(vx, 8);
}
vx = vshrq_n_u32(vx, 14);
const uint16x4_t vx16 = vmovn_u32(vx);
const uint8x8_t vx8 = vmovn_u16(vcombine_u16(vx16, vx16));
*dptr = vget_lane_u32(vreinterpret_u32_u8(vx8), 0);
if (RGB)
*dptr |= 0xff000000;
dptr++;
} }
vx = vshrq_n_u32(vx, 14);
const uint16x4_t vx16 = vmovn_u32(vx);
const uint8x8_t vx8 = vmovn_u16(vcombine_u16(vx16, vx16));
*dptr = vget_lane_u32(vreinterpret_u32_u8(vx8), 0);
if (RGB)
*dptr |= 0xff000000;
dptr++;
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
template<bool RGB> template<bool RGB>
@ -115,33 +141,54 @@ void qt_qimageScaleAARGBA_down_x_up_y_neon(QImageScaleInfo *isi, unsigned int *d
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
/* go through every scanline in the output buffer */ /* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
unsigned int *dptr = dest + (y * dow); for (int y = yStart; y < yEnd; ++y) {
for (int x = 0; x < dw; x++) { unsigned int *dptr = dest + (y * dow);
int Cx = xapoints[x] >> 16; for (int x = 0; x < dw; x++) {
int xap = xapoints[x] & 0xffff; int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1); uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
int yap = yapoints[y]; int yap = yapoints[y];
if (yap > 0) { if (yap > 0) {
uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1); uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1);
vx = vmulq_n_u32(vx, 256 - yap); vx = vmulq_n_u32(vx, 256 - yap);
vr = vmulq_n_u32(vr, yap); vr = vmulq_n_u32(vr, yap);
vx = vaddq_u32(vx, vr); vx = vaddq_u32(vx, vr);
vx = vshrq_n_u32(vx, 8); vx = vshrq_n_u32(vx, 8);
}
vx = vshrq_n_u32(vx, 14);
const uint16x4_t vx16 = vmovn_u32(vx);
const uint8x8_t vx8 = vmovn_u16(vcombine_u16(vx16, vx16));
*dptr = vget_lane_u32(vreinterpret_u32_u8(vx8), 0);
if (RGB)
*dptr |= 0xff000000;
dptr++;
} }
vx = vshrq_n_u32(vx, 14);
const uint16x4_t vx16 = vmovn_u32(vx);
const uint8x8_t vx8 = vmovn_u16(vcombine_u16(vx16, vx16));
*dptr = vget_lane_u32(vreinterpret_u32_u8(vx8), 0);
if (RGB)
*dptr |= 0xff000000;
dptr++;
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
template<bool RGB> template<bool RGB>
@ -153,43 +200,64 @@ void qt_qimageScaleAARGBA_down_xy_neon(QImageScaleInfo *isi, unsigned int *dest,
int *xapoints = isi->xapoints; int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = yapoints[y] >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = yapoints[y] & 0xffff; int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
unsigned int *dptr = dest + (y * dow); unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
const int Cx = xapoints[x] >> 16; const int Cx = xapoints[x] >> 16;
const int xap = xapoints[x] & 0xffff; const int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1); uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
vx = vshrq_n_u32(vx, 4); vx = vshrq_n_u32(vx, 4);
uint32x4_t vr = vmulq_n_u32(vx, yap); uint32x4_t vr = vmulq_n_u32(vx, yap);
int j; int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) { for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
vx = vshrq_n_u32(vx, 4);
vx = vmulq_n_u32(vx, Cy);
vr = vaddq_u32(vr, vx);
}
sptr += sow; sptr += sow;
vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1); vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
vx = vshrq_n_u32(vx, 4); vx = vshrq_n_u32(vx, 4);
vx = vmulq_n_u32(vx, Cy); vx = vmulq_n_u32(vx, j);
vr = vaddq_u32(vr, vx); vr = vaddq_u32(vr, vx);
}
sptr += sow;
vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
vx = vshrq_n_u32(vx, 4);
vx = vmulq_n_u32(vx, j);
vr = vaddq_u32(vr, vx);
vx = vshrq_n_u32(vr, 24); vx = vshrq_n_u32(vr, 24);
const uint16x4_t vx16 = vmovn_u32(vx); const uint16x4_t vx16 = vmovn_u32(vx);
const uint8x8_t vx8 = vmovn_u16(vcombine_u16(vx16, vx16)); const uint8x8_t vx8 = vmovn_u16(vcombine_u16(vx16, vx16));
*dptr = vget_lane_u32(vreinterpret_u32_u8(vx8), 0); *dptr = vget_lane_u32(vreinterpret_u32_u8(vx8), 0);
if (RGB) if (RGB)
*dptr |= 0xff000000; *dptr |= 0xff000000;
dptr++; dptr++;
}
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
template void qt_qimageScaleAARGBA_up_x_down_y_neon<false>(QImageScaleInfo *isi, unsigned int *dest, template void qt_qimageScaleAARGBA_up_x_down_y_neon<false>(QImageScaleInfo *isi, unsigned int *dest,

View File

@ -66,6 +66,8 @@ namespace QImageScale {
int *xapoints{nullptr}; int *xapoints{nullptr};
int *yapoints{nullptr}; int *yapoints{nullptr};
int xup_yup{0}; int xup_yup{0};
int sh = 0;
int sw = 0;
}; };
} }

View File

@ -42,6 +42,11 @@
#include <private/qdrawhelper_x86_p.h> #include <private/qdrawhelper_x86_p.h>
#include <private/qsimd_p.h> #include <private/qsimd_p.h>
#if QT_CONFIG(thread)
#include "qsemaphore.h"
#include "qthreadpool.h"
#endif
#if defined(QT_COMPILER_SUPPORTS_SSE4_1) #if defined(QT_COMPILER_SUPPORTS_SSE4_1)
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
@ -70,44 +75,65 @@ void qt_qimageScaleAARGBA_up_x_down_y_sse4(QImageScaleInfo *isi, unsigned int *d
int dw, int dh, int dow, int sow) int dw, int dh, int dow, int sow)
{ {
const unsigned int **ypoints = isi->ypoints; const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints; const int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints; const int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints; const int *yapoints = isi->yapoints;
const __m128i v256 = _mm_set1_epi32(256); const __m128i v256 = _mm_set1_epi32(256);
/* go through every scanline in the output buffer */ /* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = yapoints[y] >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = yapoints[y] & 0xffff; const int Cy = yapoints[y] >> 16;
const __m128i vCy = _mm_set1_epi32(Cy); const int yap = yapoints[y] & 0xffff;
const __m128i vyap = _mm_set1_epi32(yap); const __m128i vCy = _mm_set1_epi32(Cy);
const __m128i vyap = _mm_set1_epi32(yap);
unsigned int *dptr = dest + (y * dow); unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
__m128i vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, vyap, vCy); __m128i vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, vyap, vCy);
int xap = xapoints[x]; const int xap = xapoints[x];
if (xap > 0) { if (xap > 0) {
const __m128i vxap = _mm_set1_epi32(xap); const __m128i vxap = _mm_set1_epi32(xap);
const __m128i vinvxap = _mm_sub_epi32(v256, vxap); const __m128i vinvxap = _mm_sub_epi32(v256, vxap);
__m128i vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, vyap, vCy); __m128i vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, vyap, vCy);
vx = _mm_mullo_epi32(vx, vinvxap); vx = _mm_mullo_epi32(vx, vinvxap);
vr = _mm_mullo_epi32(vr, vxap); vr = _mm_mullo_epi32(vr, vxap);
vx = _mm_add_epi32(vx, vr); vx = _mm_add_epi32(vx, vr);
vx = _mm_srli_epi32(vx, 8); vx = _mm_srli_epi32(vx, 8);
}
vx = _mm_srli_epi32(vx, 14);
vx = _mm_packus_epi32(vx, vx);
vx = _mm_packus_epi16(vx, vx);
*dptr = _mm_cvtsi128_si32(vx);
if (RGB)
*dptr |= 0xff000000;
dptr++;
} }
vx = _mm_srli_epi32(vx, 14);
vx = _mm_packus_epi32(vx, _mm_setzero_si128());
vx = _mm_packus_epi16(vx, _mm_setzero_si128());
*dptr = _mm_cvtsi128_si32(vx);
if (RGB)
*dptr |= 0xff000000;
dptr++;
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
template<bool RGB> template<bool RGB>
@ -122,37 +148,58 @@ void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *d
const __m128i v256 = _mm_set1_epi32(256); const __m128i v256 = _mm_set1_epi32(256);
/* go through every scanline in the output buffer */ /* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
unsigned int *dptr = dest + (y * dow); for (int y = yStart; y < yEnd; ++y) {
for (int x = 0; x < dw; x++) { unsigned int *dptr = dest + (y * dow);
int Cx = xapoints[x] >> 16; for (int x = 0; x < dw; x++) {
int xap = xapoints[x] & 0xffff; int Cx = xapoints[x] >> 16;
const __m128i vCx = _mm_set1_epi32(Cx); int xap = xapoints[x] & 0xffff;
const __m128i vxap = _mm_set1_epi32(xap); const __m128i vCx = _mm_set1_epi32(Cx);
const __m128i vxap = _mm_set1_epi32(xap);
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
__m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx); __m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
int yap = yapoints[y]; int yap = yapoints[y];
if (yap > 0) { if (yap > 0) {
const __m128i vyap = _mm_set1_epi32(yap); const __m128i vyap = _mm_set1_epi32(yap);
const __m128i vinvyap = _mm_sub_epi32(v256, vyap); const __m128i vinvyap = _mm_sub_epi32(v256, vyap);
__m128i vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, vxap, vCx); __m128i vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, vxap, vCx);
vx = _mm_mullo_epi32(vx, vinvyap); vx = _mm_mullo_epi32(vx, vinvyap);
vr = _mm_mullo_epi32(vr, vyap); vr = _mm_mullo_epi32(vr, vyap);
vx = _mm_add_epi32(vx, vr); vx = _mm_add_epi32(vx, vr);
vx = _mm_srli_epi32(vx, 8); vx = _mm_srli_epi32(vx, 8);
}
vx = _mm_srli_epi32(vx, 14);
vx = _mm_packus_epi32(vx, vx);
vx = _mm_packus_epi16(vx, vx);
*dptr = _mm_cvtsi128_si32(vx);
if (RGB)
*dptr |= 0xff000000;
dptr++;
} }
vx = _mm_srli_epi32(vx, 14);
vx = _mm_packus_epi32(vx, _mm_setzero_si128());
vx = _mm_packus_epi16(vx, _mm_setzero_si128());
*dptr = _mm_cvtsi128_si32(vx);
if (RGB)
*dptr |= 0xff000000;
dptr++;
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
template<bool RGB> template<bool RGB>
@ -164,42 +211,63 @@ void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
int *xapoints = isi->xapoints; int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints; int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) { auto scaleSection = [&] (int yStart, int yEnd) {
int Cy = yapoints[y] >> 16; for (int y = yStart; y < yEnd; ++y) {
int yap = yapoints[y] & 0xffff; int Cy = yapoints[y] >> 16;
const __m128i vCy = _mm_set1_epi32(Cy); int yap = yapoints[y] & 0xffff;
const __m128i vyap = _mm_set1_epi32(yap); const __m128i vCy = _mm_set1_epi32(Cy);
const __m128i vyap = _mm_set1_epi32(yap);
unsigned int *dptr = dest + (y * dow); unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) { for (int x = 0; x < dw; x++) {
const int Cx = xapoints[x] >> 16; const int Cx = xapoints[x] >> 16;
const int xap = xapoints[x] & 0xffff; const int xap = xapoints[x] & 0xffff;
const __m128i vCx = _mm_set1_epi32(Cx); const __m128i vCx = _mm_set1_epi32(Cx);
const __m128i vxap = _mm_set1_epi32(xap); const __m128i vxap = _mm_set1_epi32(xap);
const unsigned int *sptr = ypoints[y] + xpoints[x]; const unsigned int *sptr = ypoints[y] + xpoints[x];
__m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx); __m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
__m128i vr = _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vyap); __m128i vr = _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vyap);
int j; int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) { for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
sptr += sow;
vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vCy));
}
sptr += sow; sptr += sow;
vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx); vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vCy)); vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), _mm_set1_epi32(j)));
}
sptr += sow;
vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
vr = _mm_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), _mm_set1_epi32(j)));
vr = _mm_srli_epi32(vr, 24); vr = _mm_srli_epi32(vr, 24);
vr = _mm_packus_epi32(vr, _mm_setzero_si128()); vr = _mm_packus_epi32(vr, _mm_setzero_si128());
vr = _mm_packus_epi16(vr, _mm_setzero_si128()); vr = _mm_packus_epi16(vr, _mm_setzero_si128());
*dptr = _mm_cvtsi128_si32(vr); *dptr = _mm_cvtsi128_si32(vr);
if (RGB) if (RGB)
*dptr |= 0xff000000; *dptr |= 0xff000000;
dptr++; dptr++;
}
} }
};
#if QT_CONFIG(thread)
int segments = (qsizetype(isi->sh) * isi->sw) / (1<<16);
segments = std::min(segments, dh);
if (segments > 1) {
QSemaphore semaphore;
int y = 0;
for (int i = 0; i < segments; ++i) {
int yn = (dh - y) / (segments - i);
QThreadPool::globalInstance()->start([&, y, yn]() {
scaleSection(y, y + yn);
semaphore.release(1);
});
y += yn;
}
semaphore.acquire(segments);
return;
} }
#endif
scaleSection(0, dh);
} }
template void qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(QImageScaleInfo *isi, unsigned int *dest, template void qt_qimageScaleAARGBA_up_x_down_y_sse4<false>(QImageScaleInfo *isi, unsigned int *dest,

View File

@ -1602,25 +1602,6 @@ QPainterPath QPainterPath::toReversed() const
return rev; return rev;
} }
/*!
\overload
Converts the path into a list of polygons without any transformation,
and returns the list.
This function creates one polygon for each subpath regardless of
intersecting subpaths (i.e. overlapping bounding rectangles). To
make sure that such overlapping subpaths are filled correctly, use
the toFillPolygons() function instead.
\sa toFillPolygons(), toFillPolygon(), {QPainterPath#QPainterPath
Conversion}{QPainterPath Conversion}
*/
QList<QPolygonF> QPainterPath::toSubpathPolygons() const
{
return toSubpathPolygons(QTransform());
}
/*! /*!
Converts the path into a list of polygons using the QTransform Converts the path into a list of polygons using the QTransform
\a matrix, and returns the list. \a matrix, and returns the list.
@ -1678,35 +1659,6 @@ QList<QPolygonF> QPainterPath::toSubpathPolygons(const QTransform &matrix) const
return flatCurves; return flatCurves;
} }
/*!
\overload
Converts the path into a list of polygons without any transformation,
and returns the list.
The function differs from the toFillPolygon() function in that it
creates several polygons. It is provided because it is usually
faster to draw several small polygons than to draw one large
polygon, even though the total number of points drawn is the same.
The toFillPolygons() function differs from the toSubpathPolygons()
function in that it create only polygon for subpaths that have
overlapping bounding rectangles.
Like the toFillPolygon() function, this function uses a rewinding
technique to make sure that overlapping subpaths can be filled
using the correct fill rule. Note that rewinding inserts addition
lines in the polygons so the outline of the fill polygon does not
match the outline of the path.
\sa toSubpathPolygons(), toFillPolygon(),
{QPainterPath#QPainterPath Conversion}{QPainterPath Conversion}
*/
QList<QPolygonF> QPainterPath::toFillPolygons() const
{
return toFillPolygons(QTransform());
}
/*! /*!
Converts the path into a list of polygons using the Converts the path into a list of polygons using the
QTransform \a matrix, and returns the list. QTransform \a matrix, and returns the list.
@ -2902,28 +2854,6 @@ void QPainterPathStroker::setDashOffset(qreal offset)
d_func()->dashOffset = offset; d_func()->dashOffset = offset;
} }
/*!
\overload
Converts the path into a polygon without any transformation,
and returns the polygon.
The polygon is created by first converting all subpaths to
polygons, then using a rewinding technique to make sure that
overlapping subpaths can be filled using the correct fill rule.
Note that rewinding inserts addition lines in the polygon so
the outline of the fill polygon does not match the outline of
the path.
\sa toSubpathPolygons(), toFillPolygons(),
{QPainterPath#QPainterPath Conversion}{QPainterPath Conversion}
*/
QPolygonF QPainterPath::toFillPolygon() const
{
return toFillPolygon(QTransform());
}
/*! /*!
Converts the path into a polygon using the QTransform Converts the path into a polygon using the QTransform
\a matrix, and returns the polygon. \a matrix, and returns the polygon.

View File

@ -41,6 +41,7 @@
#define QPAINTERPATH_H #define QPAINTERPATH_H
#include <QtGui/qtguiglobal.h> #include <QtGui/qtguiglobal.h>
#include <QtGui/qtransform.h>
#include <QtCore/qglobal.h> #include <QtCore/qglobal.h>
#include <QtCore/qrect.h> #include <QtCore/qrect.h>
#include <QtCore/qline.h> #include <QtCore/qline.h>
@ -176,12 +177,9 @@ public:
Q_REQUIRED_RESULT QPainterPath toReversed() const; Q_REQUIRED_RESULT QPainterPath toReversed() const;
QList<QPolygonF> toSubpathPolygons() const; QList<QPolygonF> toSubpathPolygons(const QTransform &matrix = QTransform()) const;
QList<QPolygonF> toSubpathPolygons(const QTransform &matrix) const; QList<QPolygonF> toFillPolygons(const QTransform &matrix = QTransform()) const;
QList<QPolygonF> toFillPolygons() const; QPolygonF toFillPolygon(const QTransform &matrix = QTransform()) const;
QList<QPolygonF> toFillPolygons(const QTransform &matrix) const;
QPolygonF toFillPolygon() const;
QPolygonF toFillPolygon(const QTransform &matrix) const;
int elementCount() const; int elementCount() const;
QPainterPath::Element elementAt(int i) const; QPainterPath::Element elementAt(int i) const;
@ -356,6 +354,8 @@ inline void QPainterPath::translate(const QPointF &offset)
inline QPainterPath QPainterPath::translated(const QPointF &offset) const inline QPainterPath QPainterPath::translated(const QPointF &offset) const
{ return translated(offset.x(), offset.y()); } { return translated(offset.x(), offset.y()); }
inline QPainterPath operator *(const QPainterPath &p, const QTransform &m)
{ return m.map(p); }
#ifndef QT_NO_DEBUG_STREAM #ifndef QT_NO_DEBUG_STREAM
Q_GUI_EXPORT QDebug operator<<(QDebug, const QPainterPath &); Q_GUI_EXPORT QDebug operator<<(QDebug, const QPainterPath &);

View File

@ -46,6 +46,8 @@
#include <private/qdatabuffer_p.h> #include <private/qdatabuffer_p.h>
#include <private/qdrawhelper_p.h> #include <private/qdrawhelper_p.h>
#include <QtGui/qpainterpath.h>
#include <algorithm> #include <algorithm>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -43,6 +43,8 @@
#include "private/qfontengine_p.h" #include "private/qfontengine_p.h"
#include "private/qnumeric_p.h" #include "private/qnumeric_p.h"
#include <QtGui/qpainterpath.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
// #define CACHE_DEBUG // #define CACHE_DEBUG

View File

@ -40,7 +40,6 @@
#define QTRANSFORM_H #define QTRANSFORM_H
#include <QtGui/qtguiglobal.h> #include <QtGui/qtguiglobal.h>
#include <QtGui/qpainterpath.h>
#include <QtGui/qpolygon.h> #include <QtGui/qpolygon.h>
#include <QtGui/qregion.h> #include <QtGui/qregion.h>
#include <QtGui/qwindowdefs.h> #include <QtGui/qwindowdefs.h>
@ -50,8 +49,8 @@
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE
class QVariant; class QVariant;
class QPainterPath;
class Q_GUI_EXPORT QTransform class Q_GUI_EXPORT QTransform
{ {
@ -406,8 +405,6 @@ inline QPolygonF operator *(const QPolygonF &a, const QTransform &m)
{ return m.map(a); } { return m.map(a); }
inline QRegion operator *(const QRegion &r, const QTransform &m) inline QRegion operator *(const QRegion &r, const QTransform &m)
{ return m.map(r); } { return m.map(r); }
inline QPainterPath operator *(const QPainterPath &p, const QTransform &m)
{ return m.map(p); }
inline QTransform operator *(const QTransform &a, qreal n) inline QTransform operator *(const QTransform &a, qreal n)
{ QTransform t(a); t *= n; return t; } { QTransform t(a); t *= n; return t; }

View File

@ -2885,16 +2885,57 @@ QRhiShaderResourceBinding QRhiShaderResourceBinding::uniformBufferWithDynamicOff
\return a shader resource binding for the given binding number, pipeline \return a shader resource binding for the given binding number, pipeline
stages, texture, and sampler specified by \a binding, \a stage, \a tex, stages, texture, and sampler specified by \a binding, \a stage, \a tex,
\a sampler. \a sampler.
\note This function is equivalent to calling sampledTextures() with a
\c count of 1.
\sa sampledTextures()
*/ */
QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture( QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler) int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler)
{ {
const TextureAndSampler texSampler = { tex, sampler };
return sampledTextures(binding, stage, 1, &texSampler);
}
/*!
\return a shader resource binding for the given binding number, pipeline
stages, and the array of texture-sampler pairs specified by \a binding, \a
stage, \a count, and \a texSamplers.
\note \a count must be at least 1, and not larger than 16.
\note When \a count is 1, this function is equivalent to sampledTexture().
This function is relevant when arrays of combined image samplers are
involved. For example, in GLSL \c{layout(binding = 5) uniform sampler2D
shadowMaps[8];} declares an array of combined image samplers. The
application is then expected provide a QRhiShaderResourceBinding for
binding point 5, set up by calling this function with \a count set to 8 and
a valid texture and sampler for each element of the array.
\warning All elements of the array must be specified. With the above
example, the only valid, portable approach is calling this function with a
\a count of 8. Additionally, all QRhiTexture and QRhiSampler instances must
be valid, meaning nullptr is not an accepted value. This is due to some of
the underlying APIs, such as, Vulkan, that require a valid image and
sampler object for each element in descriptor arrays. Applications are
advised to provide "dummy" samplers and textures if some array elements are
not relevant (due to not being accessed in the shader).
\sa sampledTexture()
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTextures(
int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers)
{
Q_ASSERT(count >= 1 && count <= Data::MAX_TEX_SAMPLER_ARRAY_SIZE);
QRhiShaderResourceBinding b; QRhiShaderResourceBinding b;
b.d.binding = binding; b.d.binding = binding;
b.d.stage = stage; b.d.stage = stage;
b.d.type = SampledTexture; b.d.type = SampledTexture;
b.d.u.stex.tex = tex; b.d.u.stex.count = count;
b.d.u.stex.sampler = sampler; for (int i = 0; i < count; ++i)
b.d.u.stex.texSamplers[i] = texSamplers[i];
return b; return b;
} }
@ -3084,10 +3125,14 @@ bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBind
} }
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
if (da->u.stex.tex != db->u.stex.tex if (da->u.stex.count != db->u.stex.count)
|| da->u.stex.sampler != db->u.stex.sampler)
{
return false; return false;
for (int i = 0; i < da->u.stex.count; ++i) {
if (da->u.stex.texSamplers[i].tex != db->u.stex.texSamplers[i].tex
|| da->u.stex.texSamplers[i].sampler != db->u.stex.texSamplers[i].sampler)
{
return false;
}
} }
break; break;
case QRhiShaderResourceBinding::ImageLoad: case QRhiShaderResourceBinding::ImageLoad:
@ -3162,10 +3207,13 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
<< ')'; << ')';
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
dbg.nospace() << " SampledTexture(" dbg.nospace() << " SampledTextures("
<< "texture=" << d->u.stex.tex << "count=" << d->u.stex.count;
<< " sampler=" << d->u.stex.sampler for (int i = 0; i < d->u.stex.count; ++i) {
<< ')'; dbg.nospace() << " texture=" << d->u.stex.texSamplers[i].tex
<< " sampler=" << d->u.stex.texSamplers[i].sampler;
}
dbg.nospace() << ')';
break; break;
case QRhiShaderResourceBinding::ImageLoad: case QRhiShaderResourceBinding::ImageLoad:
dbg.nospace() << " ImageLoad(" dbg.nospace() << " ImageLoad("

View File

@ -348,6 +348,12 @@ public:
static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler); static QRhiShaderResourceBinding sampledTexture(int binding, StageFlags stage, QRhiTexture *tex, QRhiSampler *sampler);
struct TextureAndSampler {
QRhiTexture *tex;
QRhiSampler *sampler;
};
static QRhiShaderResourceBinding sampledTextures(int binding, StageFlags stage, int count, const TextureAndSampler *texSamplers);
static QRhiShaderResourceBinding imageLoad(int binding, StageFlags stage, QRhiTexture *tex, int level); static QRhiShaderResourceBinding imageLoad(int binding, StageFlags stage, QRhiTexture *tex, int level);
static QRhiShaderResourceBinding imageStore(int binding, StageFlags stage, QRhiTexture *tex, int level); static QRhiShaderResourceBinding imageStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
static QRhiShaderResourceBinding imageLoadStore(int binding, StageFlags stage, QRhiTexture *tex, int level); static QRhiShaderResourceBinding imageLoadStore(int binding, StageFlags stage, QRhiTexture *tex, int level);
@ -370,9 +376,10 @@ public:
int maybeSize; int maybeSize;
bool hasDynamicOffset; bool hasDynamicOffset;
}; };
static const int MAX_TEX_SAMPLER_ARRAY_SIZE = 16;
struct SampledTextureData { struct SampledTextureData {
QRhiTexture *tex; int count;
QRhiSampler *sampler; TextureAndSampler texSamplers[MAX_TEX_SAMPLER_ARRAY_SIZE];
}; };
struct StorageImageData { struct StorageImageData {
QRhiTexture *tex; QRhiTexture *tex;

View File

@ -113,6 +113,10 @@ QT_BEGIN_NAMESPACE
#define DXGI_ADAPTER_FLAG_SOFTWARE 2 #define DXGI_ADAPTER_FLAG_SOFTWARE 2
#endif #endif
#ifndef D3D11_1_UAV_SLOT_COUNT
#define D3D11_1_UAV_SLOT_COUNT 64
#endif
QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice) QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice)
: ofr(this), : ofr(this),
deviceCurse(this) deviceCurse(this)
@ -627,18 +631,25 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
{ {
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex); const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler); if (bd.stex.count != data->count) {
if (texD->generation != bd.stex.texGeneration bd.stex.count = data->count;
|| texD->m_id != bd.stex.texId
|| samplerD->generation != bd.stex.samplerGeneration
|| samplerD->m_id != bd.stex.samplerId)
{
srbUpdate = true; srbUpdate = true;
bd.stex.texId = texD->m_id; }
bd.stex.texGeneration = texD->generation; for (int elem = 0; elem < data->count; ++elem) {
bd.stex.samplerId = samplerD->m_id; QD3D11Texture *texD = QRHI_RES(QD3D11Texture, data->texSamplers[elem].tex);
bd.stex.samplerGeneration = samplerD->generation; QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, data->texSamplers[elem].sampler);
if (texD->generation != bd.stex.d[elem].texGeneration
|| texD->m_id != bd.stex.d[elem].texId
|| samplerD->generation != bd.stex.d[elem].samplerGeneration
|| samplerD->m_id != bd.stex.d[elem].samplerId)
{
srbUpdate = true;
bd.stex.d[elem].texId = texD->m_id;
bd.stex.d[elem].texGeneration = texD->generation;
bd.stex.d[elem].samplerId = samplerD->m_id;
bd.stex.d[elem].samplerGeneration = samplerD->generation;
}
} }
} }
break; break;
@ -1894,31 +1905,38 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
{ {
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex); const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler); bd.stex.count = data->count;
bd.stex.texId = texD->m_id; const QPair<int, int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
bd.stex.texGeneration = texD->generation; const QPair<int, int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
bd.stex.samplerId = samplerD->m_id; const QPair<int, int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
bd.stex.samplerGeneration = samplerD->generation; // if SPIR-V binding b is mapped to tN and sN in HLSL, and it
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { // is an array, then it will use tN, tN+1, tN+2, ..., and sN,
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps); // sN+1, sN+2, ...
if (nativeBinding.first >= 0 && nativeBinding.second >= 0) { for (int elem = 0; elem < data->count; ++elem) {
res[RBM_VERTEX].textures.append({ nativeBinding.first, texD->srv }); QD3D11Texture *texD = QRHI_RES(QD3D11Texture, data->texSamplers[elem].tex);
res[RBM_VERTEX].samplers.append({ nativeBinding.second, samplerD->samplerState }); QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, data->texSamplers[elem].sampler);
bd.stex.d[elem].texId = texD->m_id;
bd.stex.d[elem].texGeneration = texD->generation;
bd.stex.d[elem].samplerId = samplerD->m_id;
bd.stex.d[elem].samplerGeneration = samplerD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
if (nativeBindingVert.first >= 0 && nativeBindingVert.second >= 0) {
res[RBM_VERTEX].textures.append({ nativeBindingVert.first + elem, texD->srv });
res[RBM_VERTEX].samplers.append({ nativeBindingVert.second + elem, samplerD->samplerState });
}
} }
} if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { if (nativeBindingFrag.first >= 0 && nativeBindingFrag.second >= 0) {
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps); res[RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
if (nativeBinding.first >= 0 && nativeBinding.second >= 0) { res[RBM_FRAGMENT].samplers.append({ nativeBindingFrag.second + elem, samplerD->samplerState });
res[RBM_FRAGMENT].textures.append({ nativeBinding.first, texD->srv }); }
res[RBM_FRAGMENT].samplers.append({ nativeBinding.second, samplerD->samplerState });
} }
} if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { if (nativeBindingComp.first >= 0 && nativeBindingComp.second >= 0) {
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps); res[RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
if (nativeBinding.first >= 0 && nativeBinding.second >= 0) { res[RBM_COMPUTE].samplers.append({ nativeBindingComp.second + elem, samplerD->samplerState });
res[RBM_COMPUTE].textures.append({ nativeBinding.first, texD->srv }); }
res[RBM_COMPUTE].samplers.append({ nativeBinding.second, samplerD->samplerState });
} }
} }
} }
@ -2077,102 +2095,156 @@ static void applyDynamicOffsets(QVarLengthArray<UINT, 4> *offsets,
} }
} }
static inline uint clampedResourceCount(uint startSlot, int countSlots, uint maxSlots, const char *resType)
{
if (startSlot + countSlots > maxSlots) {
qWarning("Not enough D3D11 %s slots to bind %d resources starting at slot %d, max slots is %d",
resType, countSlots, startSlot, maxSlots);
countSlots = maxSlots > startSlot ? maxSlots - startSlot : 0;
}
return countSlots;
}
void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD, void QRhiD3D11::bindShaderResources(QD3D11ShaderResourceBindings *srbD,
const uint *dynOfsPairs, int dynOfsPairCount, const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange) bool offsetOnlyChange)
{ {
if (!offsetOnlyChange) { if (!offsetOnlyChange) {
for (const auto &batch : srbD->vssamplers.batches) for (const auto &batch : srbD->vssamplers.batches) {
context->VSSetSamplers(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData()); const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "VS sampler");
if (count)
context->VSSetSamplers(batch.startBinding, count, batch.resources.constData());
}
for (const auto &batch : srbD->vsshaderresources.batches) { for (const auto &batch : srbD->vsshaderresources.batches) {
context->VSSetShaderResources(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData()); const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
contextState.vsHighestActiveSrvBinding = qMax<int>(contextState.vsHighestActiveSrvBinding, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "VS SRV");
int(batch.startBinding) + batch.resources.count() - 1); if (count) {
context->VSSetShaderResources(batch.startBinding, count, batch.resources.constData());
contextState.vsHighestActiveSrvBinding = qMax(contextState.vsHighestActiveSrvBinding,
int(batch.startBinding + count) - 1);
}
} }
for (const auto &batch : srbD->fssamplers.batches) for (const auto &batch : srbD->fssamplers.batches) {
context->PSSetSamplers(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData()); const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "PS sampler");
if (count)
context->PSSetSamplers(batch.startBinding, count, batch.resources.constData());
}
for (const auto &batch : srbD->fsshaderresources.batches) { for (const auto &batch : srbD->fsshaderresources.batches) {
context->PSSetShaderResources(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData()); const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
contextState.fsHighestActiveSrvBinding = qMax<int>(contextState.fsHighestActiveSrvBinding, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "PS SRV");
int(batch.startBinding) + batch.resources.count() - 1); if (count) {
context->PSSetShaderResources(batch.startBinding, count, batch.resources.constData());
contextState.fsHighestActiveSrvBinding = qMax(contextState.fsHighestActiveSrvBinding,
int(batch.startBinding + count) - 1);
}
} }
for (const auto &batch : srbD->cssamplers.batches) for (const auto &batch : srbD->cssamplers.batches) {
context->CSSetSamplers(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData()); const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
D3D11_COMMONSHADER_SAMPLER_SLOT_COUNT, "CS sampler");
if (count)
context->CSSetSamplers(batch.startBinding, count, batch.resources.constData());
}
for (const auto &batch : srbD->csshaderresources.batches) { for (const auto &batch : srbD->csshaderresources.batches) {
context->CSSetShaderResources(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData()); const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
contextState.csHighestActiveSrvBinding = qMax<int>(contextState.csHighestActiveSrvBinding, D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "CS SRV");
int(batch.startBinding) + batch.resources.count() - 1); if (count) {
context->CSSetShaderResources(batch.startBinding, count, batch.resources.constData());
contextState.csHighestActiveSrvBinding = qMax(contextState.csHighestActiveSrvBinding,
int(batch.startBinding + count) - 1);
}
} }
} }
for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) { for (int i = 0, ie = srbD->vsubufs.batches.count(); i != ie; ++i) {
if (!dynOfsPairCount) { const uint count = clampedResourceCount(srbD->vsubufs.batches[i].startBinding,
context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding, srbD->vsubufs.batches[i].resources.count(),
UINT(srbD->vsubufs.batches[i].resources.count()), D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
srbD->vsubufs.batches[i].resources.constData(), "VS cbuf");
srbD->vsubufoffsets.batches[i].resources.constData(), if (count) {
srbD->vsubufsizes.batches[i].resources.constData()); if (!dynOfsPairCount) {
} else { context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
QVarLengthArray<UINT, 4> offsets; count,
applyDynamicOffsets(&offsets, i, &srbD->vsubufs, &srbD->vsubufoffsets, dynOfsPairs, dynOfsPairCount); srbD->vsubufs.batches[i].resources.constData(),
context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding, srbD->vsubufoffsets.batches[i].resources.constData(),
UINT(srbD->vsubufs.batches[i].resources.count()), srbD->vsubufsizes.batches[i].resources.constData());
srbD->vsubufs.batches[i].resources.constData(), } else {
offsets.constData(), QVarLengthArray<UINT, 4> offsets;
srbD->vsubufsizes.batches[i].resources.constData()); applyDynamicOffsets(&offsets, i, &srbD->vsubufs, &srbD->vsubufoffsets, dynOfsPairs, dynOfsPairCount);
context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
count,
srbD->vsubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->vsubufsizes.batches[i].resources.constData());
}
} }
} }
for (int i = 0, ie = srbD->fsubufs.batches.count(); i != ie; ++i) { for (int i = 0, ie = srbD->fsubufs.batches.count(); i != ie; ++i) {
if (!dynOfsPairCount) { const uint count = clampedResourceCount(srbD->fsubufs.batches[i].startBinding,
context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding, srbD->fsubufs.batches[i].resources.count(),
UINT(srbD->fsubufs.batches[i].resources.count()), D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
srbD->fsubufs.batches[i].resources.constData(), "PS cbuf");
srbD->fsubufoffsets.batches[i].resources.constData(), if (count) {
srbD->fsubufsizes.batches[i].resources.constData()); if (!dynOfsPairCount) {
} else { context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
QVarLengthArray<UINT, 4> offsets; count,
applyDynamicOffsets(&offsets, i, &srbD->fsubufs, &srbD->fsubufoffsets, dynOfsPairs, dynOfsPairCount); srbD->fsubufs.batches[i].resources.constData(),
context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding, srbD->fsubufoffsets.batches[i].resources.constData(),
UINT(srbD->fsubufs.batches[i].resources.count()), srbD->fsubufsizes.batches[i].resources.constData());
srbD->fsubufs.batches[i].resources.constData(), } else {
offsets.constData(), QVarLengthArray<UINT, 4> offsets;
srbD->fsubufsizes.batches[i].resources.constData()); applyDynamicOffsets(&offsets, i, &srbD->fsubufs, &srbD->fsubufoffsets, dynOfsPairs, dynOfsPairCount);
context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
count,
srbD->fsubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->fsubufsizes.batches[i].resources.constData());
}
} }
} }
for (int i = 0, ie = srbD->csubufs.batches.count(); i != ie; ++i) { for (int i = 0, ie = srbD->csubufs.batches.count(); i != ie; ++i) {
if (!dynOfsPairCount) { const uint count = clampedResourceCount(srbD->csubufs.batches[i].startBinding,
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding, srbD->csubufs.batches[i].resources.count(),
UINT(srbD->csubufs.batches[i].resources.count()), D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
srbD->csubufs.batches[i].resources.constData(), "CS cbuf");
srbD->csubufoffsets.batches[i].resources.constData(), if (count) {
srbD->csubufsizes.batches[i].resources.constData()); if (!dynOfsPairCount) {
} else { context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
QVarLengthArray<UINT, 4> offsets; count,
applyDynamicOffsets(&offsets, i, &srbD->csubufs, &srbD->csubufoffsets, dynOfsPairs, dynOfsPairCount); srbD->csubufs.batches[i].resources.constData(),
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding, srbD->csubufoffsets.batches[i].resources.constData(),
UINT(srbD->csubufs.batches[i].resources.count()), srbD->csubufsizes.batches[i].resources.constData());
srbD->csubufs.batches[i].resources.constData(), } else {
offsets.constData(), QVarLengthArray<UINT, 4> offsets;
srbD->csubufsizes.batches[i].resources.constData()); applyDynamicOffsets(&offsets, i, &srbD->csubufs, &srbD->csubufoffsets, dynOfsPairs, dynOfsPairCount);
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
count,
srbD->csubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->csubufsizes.batches[i].resources.constData());
}
} }
} }
for (int i = 0, ie = srbD->csUAVs.batches.count(); i != ie; ++i) { for (const auto &batch : srbD->csUAVs.batches) {
const uint startBinding = srbD->csUAVs.batches[i].startBinding; const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
const uint count = uint(srbD->csUAVs.batches[i].resources.count()); D3D11_1_UAV_SLOT_COUNT, "CS UAV");
context->CSSetUnorderedAccessViews(startBinding, if (count) {
count, context->CSSetUnorderedAccessViews(batch.startBinding,
srbD->csUAVs.batches[i].resources.constData(), count,
nullptr); batch.resources.constData(),
contextState.csHighestActiveUavBinding = qMax<int>(contextState.csHighestActiveUavBinding, nullptr);
int(startBinding + count - 1)); contextState.csHighestActiveUavBinding = qMax(contextState.csHighestActiveUavBinding,
int(batch.startBinding + count) - 1);
}
} }
} }
@ -3529,11 +3601,15 @@ static pD3DCompile resolveD3DCompile()
static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error, QShaderKey *usedShaderKey) static QByteArray compileHlslShaderSource(const QShader &shader, QShader::Variant shaderVariant, QString *error, QShaderKey *usedShaderKey)
{ {
QShaderCode dxbc = shader.shader({ QShader::DxbcShader, 50, shaderVariant }); QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
if (!dxbc.shader().isEmpty()) QShaderCode dxbc = shader.shader(key);
if (!dxbc.shader().isEmpty()) {
if (usedShaderKey)
*usedShaderKey = key;
return dxbc.shader(); return dxbc.shader();
}
const QShaderKey key = { QShader::HlslShader, 50, shaderVariant }; key = { QShader::HlslShader, 50, shaderVariant };
QShaderCode hlslSource = shader.shader(key); QShaderCode hlslSource = shader.shader(key);
if (hlslSource.shader().isEmpty()) { if (hlslSource.shader().isEmpty()) {
qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader; qWarning() << "No HLSL (shader model 5.0) code found in baked shader" << shader;

View File

@ -210,10 +210,13 @@ struct QD3D11ShaderResourceBindings : public QRhiShaderResourceBindings
uint generation; uint generation;
}; };
struct BoundSampledTextureData { struct BoundSampledTextureData {
quint64 texId; int count;
uint texGeneration; struct {
quint64 samplerId; quint64 texId;
uint samplerGeneration; uint texGeneration;
quint64 samplerId;
uint samplerGeneration;
} d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
}; };
struct BoundStorageImageData { struct BoundStorageImageData {
quint64 id; quint64 id;

View File

@ -917,10 +917,12 @@ void QRhiGles2::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
hasDynamicOffsetInSrb = true; hasDynamicOffsetInSrb = true;
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
trackedRegisterTexture(&passResTracker, for (int elem = 0; elem < b->u.stex.count; ++elem) {
QRHI_RES(QGles2Texture, b->u.stex.tex), trackedRegisterTexture(&passResTracker,
QRhiPassResourceTracker::TexSample, QRHI_RES(QGles2Texture, b->u.stex.texSamplers[elem].tex),
QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage)); QRhiPassResourceTracker::TexSample,
QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage));
}
break; break;
case QRhiShaderResourceBinding::ImageLoad: case QRhiShaderResourceBinding::ImageLoad:
case QRhiShaderResourceBinding::ImageStore: case QRhiShaderResourceBinding::ImageStore:
@ -2572,36 +2574,37 @@ void QRhiGles2::bindShaderResources(QRhiGraphicsPipeline *maybeGraphicsPs, QRhiC
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
{ {
QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.stex.tex);
QGles2Sampler *samplerD = QRHI_RES(QGles2Sampler, b->u.stex.sampler);
QVector<QGles2SamplerDescription> &samplers(maybeGraphicsPs ? QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->samplers QVector<QGles2SamplerDescription> &samplers(maybeGraphicsPs ? QRHI_RES(QGles2GraphicsPipeline, maybeGraphicsPs)->samplers
: QRHI_RES(QGles2ComputePipeline, maybeComputePs)->samplers); : QRHI_RES(QGles2ComputePipeline, maybeComputePs)->samplers);
for (int elem = 0; elem < b->u.stex.count; ++elem) {
QGles2Texture *texD = QRHI_RES(QGles2Texture, b->u.stex.texSamplers[elem].tex);
QGles2Sampler *samplerD = QRHI_RES(QGles2Sampler, b->u.stex.texSamplers[elem].sampler);
for (QGles2SamplerDescription &sampler : samplers) {
if (sampler.binding == b->binding) {
f->glActiveTexture(GL_TEXTURE0 + uint(texUnit));
f->glBindTexture(texD->target, texD->texture);
for (QGles2SamplerDescription &sampler : samplers) { if (texD->samplerState != samplerD->d) {
if (sampler.binding == b->binding) { f->glTexParameteri(texD->target, GL_TEXTURE_MIN_FILTER, GLint(samplerD->d.glminfilter));
f->glActiveTexture(GL_TEXTURE0 + uint(texUnit)); f->glTexParameteri(texD->target, GL_TEXTURE_MAG_FILTER, GLint(samplerD->d.glmagfilter));
f->glBindTexture(texD->target, texD->texture); f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_S, GLint(samplerD->d.glwraps));
f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_T, GLint(samplerD->d.glwrapt));
if (texD->samplerState != samplerD->d) { // 3D textures not supported by GLES 2.0 or by us atm...
f->glTexParameteri(texD->target, GL_TEXTURE_MIN_FILTER, GLint(samplerD->d.glminfilter)); //f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_R, samplerD->d.glwrapr);
f->glTexParameteri(texD->target, GL_TEXTURE_MAG_FILTER, GLint(samplerD->d.glmagfilter)); if (caps.textureCompareMode) {
f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_S, GLint(samplerD->d.glwraps)); if (samplerD->d.gltexcomparefunc != GL_NEVER) {
f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_T, GLint(samplerD->d.glwrapt)); f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
// 3D textures not supported by GLES 2.0 or by us atm... f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_FUNC, GLint(samplerD->d.gltexcomparefunc));
//f->glTexParameteri(texD->target, GL_TEXTURE_WRAP_R, samplerD->d.glwrapr); } else {
if (caps.textureCompareMode) { f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
if (samplerD->d.gltexcomparefunc != GL_NEVER) { }
f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE);
f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_FUNC, GLint(samplerD->d.gltexcomparefunc));
} else {
f->glTexParameteri(texD->target, GL_TEXTURE_COMPARE_MODE, GL_NONE);
} }
texD->samplerState = samplerD->d;
} }
texD->samplerState = samplerD->d;
}
f->glUniform1i(sampler.glslLocation, texUnit); f->glUniform1i(sampler.glslLocation + elem, texUnit);
++texUnit; ++texUnit;
}
} }
} }
} }

View File

@ -748,30 +748,33 @@ void QRhiMetal::enqueueShaderResourceBindings(QMetalShaderResourceBindings *srbD
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
{ {
QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.stex.tex); const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b->u.stex.sampler); for (int elem = 0; elem < data->count; ++elem) {
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) { QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.stex.texSamplers[elem].tex);
const int nativeBindingTexture = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture); QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b->u.stex.texSamplers[elem].sampler);
const int nativeBindingSampler = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Sampler); if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) { const int nativeBindingTexture = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Texture);
res[VERTEX].textures.append({ nativeBindingTexture, texD->d->tex }); const int nativeBindingSampler = mapBinding(b->binding, VERTEX, nativeResourceBindingMaps, BindingType::Sampler);
res[VERTEX].samplers.append({ nativeBindingSampler, samplerD->d->samplerState }); if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
res[VERTEX].textures.append({ nativeBindingTexture + elem, texD->d->tex });
res[VERTEX].samplers.append({ nativeBindingSampler + elem, samplerD->d->samplerState });
}
} }
} if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) { const int nativeBindingTexture = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture);
const int nativeBindingTexture = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Texture); const int nativeBindingSampler = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Sampler);
const int nativeBindingSampler = mapBinding(b->binding, FRAGMENT, nativeResourceBindingMaps, BindingType::Sampler); if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) { res[FRAGMENT].textures.append({ nativeBindingTexture + elem, texD->d->tex });
res[FRAGMENT].textures.append({ nativeBindingTexture, texD->d->tex }); res[FRAGMENT].samplers.append({ nativeBindingSampler + elem, samplerD->d->samplerState });
res[FRAGMENT].samplers.append({ nativeBindingSampler, samplerD->d->samplerState }); }
} }
} if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) { const int nativeBindingTexture = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture);
const int nativeBindingTexture = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Texture); const int nativeBindingSampler = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Sampler);
const int nativeBindingSampler = mapBinding(b->binding, COMPUTE, nativeResourceBindingMaps, BindingType::Sampler); if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) {
if (nativeBindingTexture >= 0 && nativeBindingSampler >= 0) { res[COMPUTE].textures.append({ nativeBindingTexture + elem, texD->d->tex });
res[COMPUTE].textures.append({ nativeBindingTexture, texD->d->tex }); res[COMPUTE].samplers.append({ nativeBindingSampler + elem, samplerD->d->samplerState });
res[COMPUTE].samplers.append({ nativeBindingSampler, samplerD->d->samplerState }); }
} }
} }
} }
@ -1020,21 +1023,28 @@ void QRhiMetal::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
{ {
QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.stex.tex); const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b->u.stex.sampler); if (bd.stex.count != data->count) {
if (texD->generation != bd.stex.texGeneration bd.stex.count = data->count;
|| texD->m_id != bd.stex.texId
|| samplerD->generation != bd.stex.samplerGeneration
|| samplerD->m_id != bd.stex.samplerId)
{
resNeedsRebind = true; resNeedsRebind = true;
bd.stex.texId = texD->m_id;
bd.stex.texGeneration = texD->generation;
bd.stex.samplerId = samplerD->m_id;
bd.stex.samplerGeneration = samplerD->generation;
} }
texD->lastActiveFrameSlot = currentFrameSlot; for (int elem = 0; elem < data->count; ++elem) {
samplerD->lastActiveFrameSlot = currentFrameSlot; QMetalTexture *texD = QRHI_RES(QMetalTexture, data->texSamplers[elem].tex);
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, data->texSamplers[elem].sampler);
if (texD->generation != bd.stex.d[elem].texGeneration
|| texD->m_id != bd.stex.d[elem].texId
|| samplerD->generation != bd.stex.d[elem].samplerGeneration
|| samplerD->m_id != bd.stex.d[elem].samplerId)
{
resNeedsRebind = true;
bd.stex.d[elem].texId = texD->m_id;
bd.stex.d[elem].texGeneration = texD->generation;
bd.stex.d[elem].samplerId = samplerD->m_id;
bd.stex.d[elem].samplerGeneration = samplerD->generation;
}
texD->lastActiveFrameSlot = currentFrameSlot;
samplerD->lastActiveFrameSlot = currentFrameSlot;
}
} }
break; break;
case QRhiShaderResourceBinding::ImageLoad: case QRhiShaderResourceBinding::ImageLoad:
@ -2981,12 +2991,16 @@ bool QMetalShaderResourceBindings::build()
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
{ {
QMetalTexture *texD = QRHI_RES(QMetalTexture, b->u.stex.tex); const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
QMetalSampler *samplerD = QRHI_RES(QMetalSampler, b->u.stex.sampler); bd.stex.count = data->count;
bd.stex.texId = texD->m_id; for (int elem = 0; elem < data->count; ++elem) {
bd.stex.texGeneration = texD->generation; QMetalTexture *texD = QRHI_RES(QMetalTexture, data->texSamplers[elem].tex);
bd.stex.samplerId = samplerD->m_id; QMetalSampler *samplerD = QRHI_RES(QMetalSampler, data->texSamplers[elem].sampler);
bd.stex.samplerGeneration = samplerD->generation; bd.stex.d[elem].texId = texD->m_id;
bd.stex.d[elem].texGeneration = texD->generation;
bd.stex.d[elem].samplerId = samplerD->m_id;
bd.stex.d[elem].samplerGeneration = samplerD->generation;
}
} }
break; break;
case QRhiShaderResourceBinding::ImageLoad: case QRhiShaderResourceBinding::ImageLoad:
@ -3241,8 +3255,12 @@ static inline MTLCullMode toMetalCullMode(QRhiGraphicsPipeline::CullMode c)
id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Variant shaderVariant, id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Variant shaderVariant,
QString *error, QByteArray *entryPoint, QShaderKey *activeKey) QString *error, QByteArray *entryPoint, QShaderKey *activeKey)
{ {
QShaderKey key = { QShader::MetalLibShader, 12, shaderVariant }; QShaderKey key = { QShader::MetalLibShader, 20, shaderVariant };
QShaderCode mtllib = shader.shader(key); QShaderCode mtllib = shader.shader(key);
if (mtllib.shader().isEmpty()) {
key.setSourceVersion(12);
mtllib = shader.shader(key);
}
if (!mtllib.shader().isEmpty()) { if (!mtllib.shader().isEmpty()) {
dispatch_data_t data = dispatch_data_create(mtllib.shader().constData(), dispatch_data_t data = dispatch_data_create(mtllib.shader().constData(),
size_t(mtllib.shader().size()), size_t(mtllib.shader().size()),
@ -3261,16 +3279,20 @@ id<MTLLibrary> QRhiMetalData::createMetalLib(const QShader &shader, QShader::Var
} }
} }
key = { QShader::MslShader, 12, shaderVariant }; key = { QShader::MslShader, 20, shaderVariant };
QShaderCode mslSource = shader.shader(key); QShaderCode mslSource = shader.shader(key);
if (mslSource.shader().isEmpty()) { if (mslSource.shader().isEmpty()) {
qWarning() << "No MSL 1.2 code found in baked shader" << shader; key.setSourceVersion(12);
mslSource = shader.shader(key);
}
if (mslSource.shader().isEmpty()) {
qWarning() << "No MSL 2.0 or 1.2 code found in baked shader" << shader;
return nil; return nil;
} }
NSString *src = [NSString stringWithUTF8String: mslSource.shader().constData()]; NSString *src = [NSString stringWithUTF8String: mslSource.shader().constData()];
MTLCompileOptions *opts = [[MTLCompileOptions alloc] init]; MTLCompileOptions *opts = [[MTLCompileOptions alloc] init];
opts.languageVersion = MTLLanguageVersion1_2; opts.languageVersion = key.sourceVersion() == 20 ? MTLLanguageVersion2_0 : MTLLanguageVersion1_2;
NSError *err = nil; NSError *err = nil;
id<MTLLibrary> lib = [dev newLibraryWithSource: src options: opts error: &err]; id<MTLLibrary> lib = [dev newLibraryWithSource: src options: opts error: &err];
[opts release]; [opts release];

View File

@ -197,10 +197,13 @@ struct QMetalShaderResourceBindings : public QRhiShaderResourceBindings
uint generation; uint generation;
}; };
struct BoundSampledTextureData { struct BoundSampledTextureData {
quint64 texId; int count;
uint texGeneration; struct {
quint64 samplerId; quint64 texId;
uint samplerGeneration; uint texGeneration;
quint64 samplerId;
uint samplerGeneration;
} d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
}; };
struct BoundStorageImageData { struct BoundStorageImageData {
quint64 id; quint64 id;

View File

@ -345,6 +345,15 @@ static bool qvk_debug_filter(VkDebugReportFlagsEXT flags, VkDebugReportObjectTyp
return true; return true;
} }
// In certain cases allocateDescriptorSet() will attempt to allocate from a
// pool that does not have enough descriptors of a certain type. This makes
// the validation layer shout. However, this is not an error since we will
// then move on to another pool. If there is a real error, a qWarning
// message is shown by allocateDescriptorSet(), so the validation warning
// does not have any value and is just noise.
if (strstr(pMessage, "VUID-VkDescriptorSetAllocateInfo-descriptorPool-00307"))
return true;
return false; return false;
} }
@ -2487,7 +2496,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb); QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb);
QVarLengthArray<VkDescriptorBufferInfo, 8> bufferInfos; QVarLengthArray<VkDescriptorBufferInfo, 8> bufferInfos;
QVarLengthArray<VkDescriptorImageInfo, 8> imageInfos; using ArrayOfImageDesc = QVarLengthArray<VkDescriptorImageInfo, 8>;
QVarLengthArray<ArrayOfImageDesc, 8> imageInfos;
QVarLengthArray<VkWriteDescriptorSet, 12> writeInfos; QVarLengthArray<VkWriteDescriptorSet, 12> writeInfos;
QVarLengthArray<QPair<int, int>, 12> infoIndices; QVarLengthArray<QPair<int, int>, 12> infoIndices;
@ -2530,17 +2540,22 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
{ {
QVkTexture *texD = QRHI_RES(QVkTexture, b->u.stex.tex); const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
QVkSampler *samplerD = QRHI_RES(QVkSampler, b->u.stex.sampler); writeInfo.descriptorCount = data->count; // arrays of combined image samplers are supported
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER; writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
bd.stex.texId = texD->m_id; ArrayOfImageDesc imageInfo(data->count);
bd.stex.texGeneration = texD->generation; for (int elem = 0; elem < data->count; ++elem) {
bd.stex.samplerId = samplerD->m_id; QVkTexture *texD = QRHI_RES(QVkTexture, data->texSamplers[elem].tex);
bd.stex.samplerGeneration = samplerD->generation; QVkSampler *samplerD = QRHI_RES(QVkSampler, data->texSamplers[elem].sampler);
VkDescriptorImageInfo imageInfo; bd.stex.d[elem].texId = texD->m_id;
imageInfo.sampler = samplerD->sampler; bd.stex.d[elem].texGeneration = texD->generation;
imageInfo.imageView = texD->imageView; bd.stex.d[elem].samplerId = samplerD->m_id;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL; bd.stex.d[elem].samplerGeneration = samplerD->generation;
imageInfo[elem].sampler = samplerD->sampler;
imageInfo[elem].imageView = texD->imageView;
imageInfo[elem].imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
}
bd.stex.count = data->count;
imageInfoIndex = imageInfos.count(); imageInfoIndex = imageInfos.count();
imageInfos.append(imageInfo); imageInfos.append(imageInfo);
} }
@ -2555,10 +2570,10 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE; writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
bd.simage.id = texD->m_id; bd.simage.id = texD->m_id;
bd.simage.generation = texD->generation; bd.simage.generation = texD->generation;
VkDescriptorImageInfo imageInfo; ArrayOfImageDesc imageInfo(1);
imageInfo.sampler = VK_NULL_HANDLE; imageInfo[0].sampler = VK_NULL_HANDLE;
imageInfo.imageView = view; imageInfo[0].imageView = view;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL; imageInfo[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
imageInfoIndex = imageInfos.count(); imageInfoIndex = imageInfos.count();
imageInfos.append(imageInfo); imageInfos.append(imageInfo);
} }
@ -2596,7 +2611,7 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
if (bufferInfoIndex >= 0) if (bufferInfoIndex >= 0)
writeInfos[i].pBufferInfo = &bufferInfos[bufferInfoIndex]; writeInfos[i].pBufferInfo = &bufferInfos[bufferInfoIndex];
else if (imageInfoIndex >= 0) else if (imageInfoIndex >= 0)
writeInfos[i].pImageInfo = &imageInfos[imageInfoIndex]; writeInfos[i].pImageInfo = imageInfos[imageInfoIndex].constData();
} }
df->vkUpdateDescriptorSets(dev, uint32_t(writeInfos.count()), writeInfos.constData(), 0, nullptr); df->vkUpdateDescriptorSets(dev, uint32_t(writeInfos.count()), writeInfos.constData(), 0, nullptr);
@ -4210,24 +4225,30 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
break; break;
case QRhiShaderResourceBinding::SampledTexture: case QRhiShaderResourceBinding::SampledTexture:
{ {
QVkTexture *texD = QRHI_RES(QVkTexture, b->u.stex.tex); const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
QVkSampler *samplerD = QRHI_RES(QVkSampler, b->u.stex.sampler); if (bd.stex.count != data->count) {
texD->lastActiveFrameSlot = currentFrameSlot; bd.stex.count = data->count;
samplerD->lastActiveFrameSlot = currentFrameSlot;
trackedRegisterTexture(&passResTracker, texD,
QRhiPassResourceTracker::TexSample,
QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage));
if (texD->generation != bd.stex.texGeneration
|| texD->m_id != bd.stex.texId
|| samplerD->generation != bd.stex.samplerGeneration
|| samplerD->m_id != bd.stex.samplerId)
{
rewriteDescSet = true; rewriteDescSet = true;
bd.stex.texId = texD->m_id; }
bd.stex.texGeneration = texD->generation; for (int elem = 0; elem < data->count; ++elem) {
bd.stex.samplerId = samplerD->m_id; QVkTexture *texD = QRHI_RES(QVkTexture, data->texSamplers[elem].tex);
bd.stex.samplerGeneration = samplerD->generation; QVkSampler *samplerD = QRHI_RES(QVkSampler, data->texSamplers[elem].sampler);
texD->lastActiveFrameSlot = currentFrameSlot;
samplerD->lastActiveFrameSlot = currentFrameSlot;
trackedRegisterTexture(&passResTracker, texD,
QRhiPassResourceTracker::TexSample,
QRhiPassResourceTracker::toPassTrackerTextureStage(b->stage));
if (texD->generation != bd.stex.d[elem].texGeneration
|| texD->m_id != bd.stex.d[elem].texId
|| samplerD->generation != bd.stex.d[elem].samplerGeneration
|| samplerD->m_id != bd.stex.d[elem].samplerId)
{
rewriteDescSet = true;
bd.stex.d[elem].texId = texD->m_id;
bd.stex.d[elem].texGeneration = texD->generation;
bd.stex.d[elem].samplerId = samplerD->m_id;
bd.stex.d[elem].samplerGeneration = samplerD->generation;
}
} }
} }
break; break;
@ -6065,7 +6086,10 @@ bool QVkShaderResourceBindings::build()
memset(&vkbinding, 0, sizeof(vkbinding)); memset(&vkbinding, 0, sizeof(vkbinding));
vkbinding.binding = uint32_t(b->binding); vkbinding.binding = uint32_t(b->binding);
vkbinding.descriptorType = toVkDescriptorType(b); vkbinding.descriptorType = toVkDescriptorType(b);
vkbinding.descriptorCount = 1; // no array support yet if (b->type == QRhiShaderResourceBinding::SampledTexture)
vkbinding.descriptorCount = b->u.stex.count;
else
vkbinding.descriptorCount = 1;
vkbinding.stageFlags = toVkShaderStageFlags(b->stage); vkbinding.stageFlags = toVkShaderStageFlags(b->stage);
vkbindings.append(vkbinding); vkbindings.append(vkbinding);
} }

View File

@ -254,10 +254,13 @@ struct QVkShaderResourceBindings : public QRhiShaderResourceBindings
uint generation; uint generation;
}; };
struct BoundSampledTextureData { struct BoundSampledTextureData {
quint64 texId; int count;
uint texGeneration; struct {
quint64 samplerId; quint64 texId;
uint samplerGeneration; uint texGeneration;
quint64 samplerId;
uint samplerGeneration;
} d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
}; };
struct BoundStorageImageData { struct BoundStorageImageData {
quint64 id; quint64 id;

View File

@ -51,6 +51,7 @@
#include <QtCore/qendian.h> #include <QtCore/qendian.h>
#include <QtCore/qfile.h> #include <QtCore/qfile.h>
#include <QtGui/qpainterpath.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -1602,7 +1602,7 @@ bool QVulkanWindow::event(QEvent *e)
\since 5.15 \since 5.15
*/ */
void QVulkanWindow::setQueueCreateInfoModifier(QueueCreateInfoModifier modifier) void QVulkanWindow::setQueueCreateInfoModifier(const QueueCreateInfoModifier &modifier)
{ {
Q_D(QVulkanWindow); Q_D(QVulkanWindow);
d->queueCreateInfoModifier = modifier; d->queueCreateInfoModifier = modifier;

View File

@ -106,7 +106,7 @@ public:
typedef std::function<void(const VkQueueFamilyProperties *, typedef std::function<void(const VkQueueFamilyProperties *,
uint32_t, uint32_t,
QVector<VkDeviceQueueCreateInfo> &)> QueueCreateInfoModifier; QVector<VkDeviceQueueCreateInfo> &)> QueueCreateInfoModifier;
void setQueueCreateInfoModifier(QueueCreateInfoModifier modifier); void setQueueCreateInfoModifier(const QueueCreateInfoModifier &modifier);
bool isValid() const; bool isValid() const;

View File

@ -253,6 +253,7 @@ static void ensureInitialized()
/*! /*!
\enum QNetworkAccessManager::NetworkAccessibility \enum QNetworkAccessManager::NetworkAccessibility
\obsolete
Indicates whether the network is accessible via this network access manager. Indicates whether the network is accessible via this network access manager.
@ -268,6 +269,7 @@ static void ensureInitialized()
/*! /*!
\property QNetworkAccessManager::networkAccessible \property QNetworkAccessManager::networkAccessible
\brief whether the network is currently accessible via this network access manager. \brief whether the network is currently accessible via this network access manager.
\obsolete
\since 4.7 \since 4.7

View File

@ -91,12 +91,15 @@ public:
}; };
#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section #ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
enum NetworkAccessibility { enum QT_DEPRECATED_VERSION_5_15 NetworkAccessibility {
UnknownAccessibility = -1, UnknownAccessibility = -1,
NotAccessible = 0, NotAccessible = 0,
Accessible = 1 Accessible = 1
}; };
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
Q_ENUM(NetworkAccessibility) Q_ENUM(NetworkAccessibility)
QT_WARNING_POP
#endif #endif
explicit QNetworkAccessManager(QObject *parent = nullptr); explicit QNetworkAccessManager(QObject *parent = nullptr);
@ -150,8 +153,11 @@ public:
QT_DEPRECATED_VERSION_5_15 QNetworkConfiguration configuration() const; QT_DEPRECATED_VERSION_5_15 QNetworkConfiguration configuration() const;
QT_DEPRECATED_VERSION_5_15 QNetworkConfiguration activeConfiguration() const; QT_DEPRECATED_VERSION_5_15 QNetworkConfiguration activeConfiguration() const;
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
QT_DEPRECATED_VERSION_5_15 void setNetworkAccessible(NetworkAccessibility accessible); QT_DEPRECATED_VERSION_5_15 void setNetworkAccessible(NetworkAccessibility accessible);
QT_DEPRECATED_VERSION_5_15 NetworkAccessibility networkAccessible() const; QT_DEPRECATED_VERSION_5_15 NetworkAccessibility networkAccessible() const;
QT_WARNING_POP
#endif #endif
#ifndef QT_NO_SSL #ifndef QT_NO_SSL
@ -187,7 +193,14 @@ Q_SIGNALS:
#ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section #ifndef QT_NO_BEARERMANAGEMENT // ### Qt6: Remove section
QT_DEPRECATED_VERSION_5_15 void networkSessionConnected(); QT_DEPRECATED_VERSION_5_15 void networkSessionConnected();
#ifndef Q_MOC_RUN // moc has trouble with the expansion of these macros
QT_WARNING_PUSH
QT_WARNING_DISABLE_DEPRECATED
#endif
QT_DEPRECATED_VERSION_5_15 void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible); QT_DEPRECATED_VERSION_5_15 void networkAccessibleChanged(QNetworkAccessManager::NetworkAccessibility accessible);
#ifndef Q_MOC_RUN // moc has trouble with the expansion of these macros
QT_WARNING_POP
#endif
#endif #endif
protected: protected:

View File

@ -27,7 +27,7 @@ qhp.QtNetwork.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtnetwork/qtnetwork.tags tagfile = ../../../doc/qtnetwork/qtnetwork.tags
depends += qtcore qtgui qtdoc qmake depends += qtcore qtgui qtdoc qmake qtcmake
headerdirs += .. headerdirs += ..

View File

@ -0,0 +1,12 @@
cmake_minimum_required(VERSION 3.1.0)
project(network_cppsnippets)
add_executable(mytarget
network/tcpwait.cpp
)
# ![0]
find_package(Qt5 COMPONENTS Network REQUIRED)
target_link_libraries(mytarget Qt5::Network)
# ![0]

View File

@ -1,3 +0,0 @@
#! [0]
QT += network
#! [0]

View File

@ -48,7 +48,7 @@
** **
****************************************************************************/ ****************************************************************************/
#include <QtGui> #include <QCoreApplication>
#include <QTcpSocket> #include <QTcpSocket>
int main(int argv, char **args) int main(int argv, char **args)

View File

@ -2,6 +2,8 @@ TEMPLATE = app
TARGET = network_cppsnippets TARGET = network_cppsnippets
# ![0]
QT += network QT += network
# ![0]
SOURCES += network/tcpwait.cpp SOURCES += network/tcpwait.cpp

View File

@ -31,6 +31,8 @@
\title Bearer Management \title Bearer Management
\brief An API to control the system's connectivity state. \brief An API to control the system's connectivity state.
\warning Bearer management is deprecated and will be removed in Qt 6.0.
Bearer Management controls the connectivity state of the system so that Bearer Management controls the connectivity state of the system so that
the user can start or stop interfaces or roam transparently between the user can start or stop interfaces or roam transparently between
access points. access points.

View File

@ -34,19 +34,16 @@
TCP/IP. Operations such as requests, cookies, and sending data over HTTP TCP/IP. Operations such as requests, cookies, and sending data over HTTP
are handled by various C++ classes. are handled by various C++ classes.
\section1 Getting Started \include module-use.qdocinc using qt module
\snippet CMakeLists.txt 0
To use Qt Network classes,add this directive into the C++ files: See also the \l{Build with CMake} overview.
\code
#include <QtNetwork>
\endcode
\if !defined(qtforpython) \section2 Building with qmake
To link against the Qt Network module, add this line to the project file:
\code Add \c network to the \c QT variable:
QT += network
\endcode \snippet snippets.pro 0
\endif
\section1 Articles and Guides \section1 Articles and Guides
@ -100,13 +97,6 @@
\qtvariable network \qtvariable network
\brief Provides classes to make network programming easier and portable. \brief Provides classes to make network programming easier and portable.
To include the definitions of the module's classes, use the Qt Network provides a set of APIs for programming applications that use
following directive: TCP/IP. See the \l{Qt Network} overview for more information.
\snippet code/doc_src_qtnetwork.cpp 1
To link against the module, add this line to your \l qmake \c
.pro file:
\snippet code/doc_src_qtnetwork.pro 0
*/ */

View File

@ -564,12 +564,12 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
int pos = -1; int pos = -1;
#if QT_CONFIG(regularexpression) #if QT_CONFIG(regularexpression)
if (syntax == Wildcard) if (syntax == PatternSyntax::Wildcard)
pos = pathPrefix.indexOf(QRegularExpression(QLatin1String("[*?[]"))); pos = pathPrefix.indexOf(QRegularExpression(QLatin1String("[*?[]")));
else if (syntax == RegExp) else if (syntax == PatternSyntax::RegularExpression)
pos = sourcePath.indexOf(QRegularExpression(QLatin1String("[\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]"))); pos = sourcePath.indexOf(QRegularExpression(QLatin1String("[\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]")));
#else #else
if (syntax == Wildcard || syntax == RegExp) if (syntax == PatternSyntax::Wildcard || syntax == PatternSyntax::RegExp)
qWarning("Regular expression support is disabled in this build. Only fixed string can be searched"); qWarning("Regular expression support is disabled in this build. Only fixed string can be searched");
return QList<QSslCertificate>(); return QList<QSslCertificate>();
#endif #endif
@ -606,7 +606,7 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
QList<QSslCertificate> certs; QList<QSslCertificate> certs;
#if QT_CONFIG(regularexpression) #if QT_CONFIG(regularexpression)
if (syntax == Wildcard) if (syntax == PatternSyntax::Wildcard)
sourcePath = QRegularExpression::wildcardToRegularExpression(sourcePath); sourcePath = QRegularExpression::wildcardToRegularExpression(sourcePath);
QRegularExpression pattern(QRegularExpression::anchoredPattern(sourcePath)); QRegularExpression pattern(QRegularExpression::anchoredPattern(sourcePath));

View File

@ -84,8 +84,8 @@ public:
EmailAddress EmailAddress
}; };
enum PatternSyntax { enum class PatternSyntax {
RegExp, RegularExpression,
Wildcard, Wildcard,
FixedString FixedString
}; };

View File

@ -130,8 +130,9 @@ public:
// Certificate Authority (CA) settings // Certificate Authority (CA) settings
QList<QSslCertificate> caCertificates() const; QList<QSslCertificate> caCertificates() const;
void setCaCertificates(const QList<QSslCertificate> &certificates); void setCaCertificates(const QList<QSslCertificate> &certificates);
bool addCaCertificates(const QString &path, QSsl::EncodingFormat format = QSsl::Pem, bool addCaCertificates(
QSslCertificate::PatternSyntax syntax = QSslCertificate::FixedString); const QString &path, QSsl::EncodingFormat format = QSsl::Pem,
QSslCertificate::PatternSyntax syntax = QSslCertificate::PatternSyntax::FixedString);
void addCaCertificate(const QSslCertificate &certificate); void addCaCertificate(const QSslCertificate &certificate);
void addCaCertificates(const QList<QSslCertificate> &certificates); void addCaCertificates(const QList<QSslCertificate> &certificates);

View File

@ -1306,7 +1306,8 @@ void QSslSocketBackendPrivate::transmit()
int totalRead = 0; int totalRead = 0;
bool hadIncompleteData = false; bool hadIncompleteData = false;
while (!readBufferMaxSize || buffer.size() < readBufferMaxSize) { while (!readBufferMaxSize || buffer.size() < readBufferMaxSize) {
if (missingData > plainSocket->bytesAvailable()) { if (missingData > plainSocket->bytesAvailable()
&& (!readBufferMaxSize || readBufferMaxSize >= missingData)) {
#ifdef QSSLSOCKET_DEBUG #ifdef QSSLSOCKET_DEBUG
qCDebug(lcSsl, "We're still missing %lld bytes, will check later.", missingData); qCDebug(lcSsl, "We're still missing %lld bytes, will check later.", missingData);
#endif #endif

View File

@ -48,6 +48,7 @@
#include <qscreen.h> #include <qscreen.h>
#include <qpa/qplatformscreen.h> #include <qpa/qplatformscreen.h>
#include <QtCore/QUuid> #include <QtCore/QUuid>
#include <QtGui/QPainterPath>
#ifndef QT_NO_FREETYPE #ifndef QT_NO_FREETYPE

View File

@ -45,6 +45,7 @@
#include <QtCore/qsettings.h> #include <QtCore/qsettings.h>
#endif #endif
#include <QtCore/qoperatingsystemversion.h> #include <QtCore/qoperatingsystemversion.h>
#include <QtGui/qpainterpath.h>
#include <private/qcoregraphics_p.h> #include <private/qcoregraphics_p.h>
#include <private/qimage_p.h> #include <private/qimage_p.h>

View File

@ -51,6 +51,7 @@
#include <QtGui/private/qguiapplication_p.h> #include <QtGui/private/qguiapplication_p.h>
#include <qpa/qplatformintegration.h> #include <qpa/qplatformintegration.h>
#include <QtGui/private/qhighdpiscaling_p.h> #include <QtGui/private/qhighdpiscaling_p.h>
#include <QtGui/qpainterpath.h>
#if defined(QT_USE_DIRECTWRITE2) #if defined(QT_USE_DIRECTWRITE2)
# include <dwrite_2.h> # include <dwrite_2.h>

View File

@ -166,7 +166,12 @@ static inline bool launch(const QString &launcher, const QUrl &url)
#if !QT_CONFIG(process) #if !QT_CONFIG(process)
const bool ok = ::system(qPrintable(command + QLatin1String(" &"))); const bool ok = ::system(qPrintable(command + QLatin1String(" &")));
#else #else
const bool ok = QProcess::startDetached(command); QStringList args = QProcess::splitCommand(command);
bool ok = false;
if (!args.isEmpty()) {
QString program = args.takeFirst();
ok = QProcess::startDetached(program, args);
}
#endif #endif
if (!ok) if (!ok)
qWarning("Launch failed (%s)", qPrintable(command)); qWarning("Launch failed (%s)", qPrintable(command));

View File

@ -53,6 +53,7 @@ QWindowsUiaWrapper::QWindowsUiaWrapper()
m_pUiaHostProviderFromHwnd = reinterpret_cast<PtrUiaHostProviderFromHwnd>(uiaLib.resolve("UiaHostProviderFromHwnd")); m_pUiaHostProviderFromHwnd = reinterpret_cast<PtrUiaHostProviderFromHwnd>(uiaLib.resolve("UiaHostProviderFromHwnd"));
m_pUiaRaiseAutomationPropertyChangedEvent = reinterpret_cast<PtrUiaRaiseAutomationPropertyChangedEvent>(uiaLib.resolve("UiaRaiseAutomationPropertyChangedEvent")); m_pUiaRaiseAutomationPropertyChangedEvent = reinterpret_cast<PtrUiaRaiseAutomationPropertyChangedEvent>(uiaLib.resolve("UiaRaiseAutomationPropertyChangedEvent"));
m_pUiaRaiseAutomationEvent = reinterpret_cast<PtrUiaRaiseAutomationEvent>(uiaLib.resolve("UiaRaiseAutomationEvent")); m_pUiaRaiseAutomationEvent = reinterpret_cast<PtrUiaRaiseAutomationEvent>(uiaLib.resolve("UiaRaiseAutomationEvent"));
m_pUiaRaiseNotificationEvent = reinterpret_cast<PtrUiaRaiseNotificationEvent>(uiaLib.resolve("UiaRaiseNotificationEvent"));
m_pUiaClientsAreListening = reinterpret_cast<PtrUiaClientsAreListening>(uiaLib.resolve("UiaClientsAreListening")); m_pUiaClientsAreListening = reinterpret_cast<PtrUiaClientsAreListening>(uiaLib.resolve("UiaClientsAreListening"));
} }
} }
@ -68,7 +69,7 @@ QWindowsUiaWrapper *QWindowsUiaWrapper::instance()
return &wrapper; return &wrapper;
} }
// True if all symbols resolved. // True if most symbols resolved (UiaRaiseNotificationEvent is optional).
BOOL QWindowsUiaWrapper::ready() BOOL QWindowsUiaWrapper::ready()
{ {
return m_pUiaReturnRawElementProvider return m_pUiaReturnRawElementProvider
@ -113,5 +114,12 @@ HRESULT QWindowsUiaWrapper::raiseAutomationEvent(IRawElementProviderSimple *pPro
return m_pUiaRaiseAutomationEvent(pProvider, id); return m_pUiaRaiseAutomationEvent(pProvider, id);
} }
HRESULT QWindowsUiaWrapper::raiseNotificationEvent(IRawElementProviderSimple *provider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId)
{
if (!m_pUiaRaiseNotificationEvent)
return UIA_E_NOTSUPPORTED;
return m_pUiaRaiseNotificationEvent(provider, notificationKind, notificationProcessing, displayString, activityId);
}
QT_END_NAMESPACE QT_END_NAMESPACE

View File

@ -80,17 +80,20 @@ public:
HRESULT hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider); HRESULT hostProviderFromHwnd(HWND hwnd, IRawElementProviderSimple **ppProvider);
HRESULT raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue); HRESULT raiseAutomationPropertyChangedEvent(IRawElementProviderSimple *pProvider, PROPERTYID id, VARIANT oldValue, VARIANT newValue);
HRESULT raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id); HRESULT raiseAutomationEvent(IRawElementProviderSimple *pProvider, EVENTID id);
HRESULT raiseNotificationEvent(IRawElementProviderSimple *provider, NotificationKind notificationKind, NotificationProcessing notificationProcessing, BSTR displayString, BSTR activityId);
private: private:
typedef LRESULT (WINAPI *PtrUiaReturnRawElementProvider)(HWND, WPARAM, LPARAM, IRawElementProviderSimple *); typedef LRESULT (WINAPI *PtrUiaReturnRawElementProvider)(HWND, WPARAM, LPARAM, IRawElementProviderSimple *);
typedef HRESULT (WINAPI *PtrUiaHostProviderFromHwnd)(HWND, IRawElementProviderSimple **); typedef HRESULT (WINAPI *PtrUiaHostProviderFromHwnd)(HWND, IRawElementProviderSimple **);
typedef HRESULT (WINAPI *PtrUiaRaiseAutomationPropertyChangedEvent)(IRawElementProviderSimple *, PROPERTYID, VARIANT, VARIANT); typedef HRESULT (WINAPI *PtrUiaRaiseAutomationPropertyChangedEvent)(IRawElementProviderSimple *, PROPERTYID, VARIANT, VARIANT);
typedef HRESULT (WINAPI *PtrUiaRaiseAutomationEvent)(IRawElementProviderSimple *, EVENTID); typedef HRESULT (WINAPI *PtrUiaRaiseAutomationEvent)(IRawElementProviderSimple *, EVENTID);
typedef HRESULT (WINAPI *PtrUiaRaiseNotificationEvent)(IRawElementProviderSimple *, NotificationKind, NotificationProcessing, BSTR, BSTR);
typedef BOOL (WINAPI *PtrUiaClientsAreListening)(); typedef BOOL (WINAPI *PtrUiaClientsAreListening)();
PtrUiaReturnRawElementProvider m_pUiaReturnRawElementProvider = nullptr; PtrUiaReturnRawElementProvider m_pUiaReturnRawElementProvider = nullptr;
PtrUiaHostProviderFromHwnd m_pUiaHostProviderFromHwnd = nullptr; PtrUiaHostProviderFromHwnd m_pUiaHostProviderFromHwnd = nullptr;
PtrUiaRaiseAutomationPropertyChangedEvent m_pUiaRaiseAutomationPropertyChangedEvent = nullptr; PtrUiaRaiseAutomationPropertyChangedEvent m_pUiaRaiseAutomationPropertyChangedEvent = nullptr;
PtrUiaRaiseAutomationEvent m_pUiaRaiseAutomationEvent = nullptr; PtrUiaRaiseAutomationEvent m_pUiaRaiseAutomationEvent = nullptr;
PtrUiaRaiseNotificationEvent m_pUiaRaiseNotificationEvent = nullptr;
PtrUiaClientsAreListening m_pUiaClientsAreListening = nullptr; PtrUiaClientsAreListening m_pUiaClientsAreListening = nullptr;
}; };

View File

@ -162,6 +162,22 @@ enum ExpandCollapseState {
ExpandCollapseState_LeafNode = 3 ExpandCollapseState_LeafNode = 3
}; };
enum NotificationKind {
NotificationKind_ItemAdded = 0,
NotificationKind_ItemRemoved = 1,
NotificationKind_ActionCompleted = 2,
NotificationKind_ActionAborted = 3,
NotificationKind_Other = 4
};
enum NotificationProcessing {
NotificationProcessing_ImportantAll = 0,
NotificationProcessing_ImportantMostRecent = 1,
NotificationProcessing_All = 2,
NotificationProcessing_MostRecent = 3,
NotificationProcessing_CurrentThenMostRecent = 4
};
struct UiaRect { struct UiaRect {
double left; double left;
double top; double top;

View File

@ -1632,6 +1632,7 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
nsWindow.restorable = NO; nsWindow.restorable = NO;
nsWindow.level = windowLevel(flags); nsWindow.level = windowLevel(flags);
nsWindow.tabbingMode = NSWindowTabbingModeDisallowed;
if (shouldBePanel) { if (shouldBePanel) {
// Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set // Qt::Tool windows hide on app deactivation, unless Qt::WA_MacAlwaysShowToolWindow is set

View File

@ -166,11 +166,27 @@ void QWindowsUiaMainProvider::notifyValueChange(QAccessibleValueChangeEvent *eve
} }
if (event->value().type() == QVariant::String) { if (event->value().type() == QVariant::String) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
// Notifies changes in string values.
VARIANT oldVal, newVal; // Tries to notify the change using UiaRaiseNotificationEvent(), which is only available on
clearVariant(&oldVal); // Windows 10 version 1709 or newer. Otherwise uses UiaRaiseAutomationPropertyChangedEvent().
setVariantString(event->value().toString(), &newVal);
QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal); BSTR displayString = bStrFromQString(event->value().toString());
BSTR activityId = bStrFromQString(QString());
HRESULT hr = QWindowsUiaWrapper::instance()->raiseNotificationEvent(provider, NotificationKind_Other,
NotificationProcessing_ImportantMostRecent,
displayString, activityId);
::SysFreeString(displayString);
::SysFreeString(activityId);
if (hr == static_cast<HRESULT>(UIA_E_NOTSUPPORTED)) {
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantString(event->value().toString(), &newVal);
QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
::SysFreeString(newVal.bstrVal);
}
} }
} else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) { } else if (QAccessibleValueInterface *valueInterface = accessible->valueInterface()) {
if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) { if (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {

View File

@ -397,7 +397,15 @@ bool QWinRTFileDialogHelper::show(Qt::WindowFlags windowFlags, Qt::WindowModalit
RETURN_FALSE_IF_FAILED_WITH_ARGS("Failed to set default file extension \"%s\"", qPrintable(suffix)); RETURN_FALSE_IF_FAILED_WITH_ARGS("Failed to set default file extension \"%s\"", qPrintable(suffix));
} }
const QString suggestedName = QFileInfo(d->saveFileName.toLocalFile()).fileName(); QString suggestedName = QFileInfo(d->saveFileName.toLocalFile()).fileName();
if (suggestedName.isEmpty() && dialogOptions->initiallySelectedFiles().size() > 0)
suggestedName = QFileInfo(dialogOptions->initiallySelectedFiles().first().toLocalFile())
.fileName();
if (suggestedName.isEmpty()) {
const auto fileInfo = QFileInfo(dialogOptions->initialDirectory().toLocalFile());
if (!fileInfo.isDir())
suggestedName = fileInfo.fileName();
}
if (!suggestedName.isEmpty()) { if (!suggestedName.isEmpty()) {
HStringReference nativeSuggestedName(reinterpret_cast<const wchar_t *>(suggestedName.utf16()), HStringReference nativeSuggestedName(reinterpret_cast<const wchar_t *>(suggestedName.utf16()),
uint(suggestedName.length())); uint(suggestedName.length()));

View File

@ -2379,7 +2379,7 @@ QStringList QODBCDriver::tables(QSql::TableType type) const
} }
while (r == SQL_SUCCESS) { while (r == SQL_SUCCESS) {
QString fieldVal = qGetStringData(hStmt, 2, -1, false); QString fieldVal = qGetStringData(hStmt, 2, -1, d->unicode);
tl.append(fieldVal); tl.append(fieldVal);
if (d->hasSQLFetchScroll) if (d->hasSQLFetchScroll)

View File

@ -56,6 +56,7 @@
#include <QtCore/private/qcore_mac_p.h> #include <QtCore/private/qcore_mac_p.h>
#include <QtGui/qpainterpath.h>
#include <QtGui/private/qcoregraphics_p.h> #include <QtGui/private/qcoregraphics_p.h>
#include <QtGui/qpa/qplatformfontdatabase.h> #include <QtGui/qpa/qplatformfontdatabase.h>
#include <QtGui/qpa/qplatformtheme.h> #include <QtGui/qpa/qplatformtheme.h>

View File

@ -42,6 +42,7 @@
#include "qprintdialog.h" #include "qprintdialog.h"
#include "qabstractprintdialog_p.h" #include "qabstractprintdialog_p.h"
#include <QtCore/qtemporarydir.h>
#include <QtCore/private/qcore_mac_p.h> #include <QtCore/private/qcore_mac_p.h>
#include <QtWidgets/private/qapplication_p.h> #include <QtWidgets/private/qapplication_p.h>
#include <QtPrintSupport/qprinter.h> #include <QtPrintSupport/qprinter.h>
@ -127,21 +128,36 @@ QT_USE_NAMESPACE
PMDestinationType dest; PMDestinationType dest;
PMSessionGetDestinationType(session, settings, &dest); PMSessionGetDestinationType(session, settings, &dest);
if (dest == kPMDestinationFile) { if (dest == kPMDestinationFile) {
// QTBUG-38820
// If user selected Print to File, leave OSX to generate the PDF,
// otherwise setting PdfFormat would prevent us showing dialog again.
// TODO Restore this when QTBUG-36112 is fixed.
/*
QCFType<CFURLRef> file; QCFType<CFURLRef> file;
PMSessionCopyDestinationLocation(session, settings, &file); PMSessionCopyDestinationLocation(session, settings, &file);
UInt8 localFile[2048]; // Assuming there's a POSIX file system here. UInt8 localFile[2048]; // Assuming there's a POSIX file system here.
CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile)); CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile));
printer->setOutputFileName(QString::fromUtf8(reinterpret_cast<const char *>(localFile))); auto outputFile = QFileInfo(QString::fromUtf8(reinterpret_cast<const char *>(localFile)));
*/ if (outputFile.suffix() == QLatin1String("pdf"))
} else { printer->setOutputFileName(outputFile.absoluteFilePath());
else
qWarning() << "Can not print to file type" << outputFile.suffix();
} else if (dest == kPMDestinationPreview) {
static QTemporaryDir printPreviews;
auto documentName = printer->docName();
if (documentName.isEmpty())
documentName = QGuiApplication::applicationDisplayName();
auto fileName = printPreviews.filePath(QString(QLatin1String("%1.pdf")).arg(documentName));
printer->setOutputFileName(fileName);
// Ideally we would have a callback when the PDF engine is done writing
// to the file, and open Preview in response to that. Lacking that, we
// use the quick and dirty assumption that the the print operation will
// happen synchronously after the dialog is accepted, so we can defer
// the opening of the file to the next runloop pass.
dispatch_async(dispatch_get_main_queue(), ^{
[NSWorkspace.sharedWorkspace openFile:fileName.toNSString()];
});
} else if (dest == kPMDestinationProcessPDF) {
qWarning("Printing workflows are not supported");
} else if (dest == kPMDestinationPrinter) {
PMPrinter macPrinter; PMPrinter macPrinter;
PMSessionGetCurrentPrinter(session, &macPrinter); PMSessionGetCurrentPrinter(session, &macPrinter);
QString printerId = QString::fromCFString(PMPrinterGetID(macPrinter)); QString printerId = QString::fromCFString(PMPrinterGetID(macPrinter)).trimmed();
if (printer->printerName() != printerId) if (printer->printerName() != printerId)
printer->setPrinterName(printerId); printer->setPrinterName(printerId);
} }
@ -199,14 +215,18 @@ void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
{ {
Q_Q(QPrintDialog); Q_Q(QPrintDialog);
// get the NSPrintInfo from the print engine in the platform plugin if (printer->outputFormat() == QPrinter::NativeFormat) {
void *voidp = 0; // get the NSPrintInfo from the print engine in the platform plugin
(void) QMetaObject::invokeMethod(qApp->platformNativeInterface(), void *voidp = 0;
"NSPrintInfoForPrintEngine", (void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
Q_RETURN_ARG(void *, voidp), "NSPrintInfoForPrintEngine",
Q_ARG(QPrintEngine *, printer->printEngine())); Q_RETURN_ARG(void *, voidp),
printInfo = static_cast<NSPrintInfo *>(voidp); Q_ARG(QPrintEngine *, printer->printEngine()));
[printInfo retain]; printInfo = static_cast<NSPrintInfo *>(voidp);
[printInfo retain];
} else {
printInfo = [NSPrintInfo.sharedPrintInfo retain];
}
// It seems the only way that PM lets you use all is if the minimum // It seems the only way that PM lets you use all is if the minimum
// for the page range is 1. This _kind of_ makes sense if you think about // for the page range is 1. This _kind of_ makes sense if you think about
@ -269,31 +289,15 @@ void QPrintDialogPrivate::closeCocoaPrintPanel()
printPanel = 0; printPanel = 0;
} }
static bool warnIfNotNative(QPrinter *printer)
{
if (printer->outputFormat() != QPrinter::NativeFormat) {
qWarning("QPrintDialog: Cannot be used on non-native printers");
return false;
}
return true;
}
QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent) QPrintDialog::QPrintDialog(QPrinter *printer, QWidget *parent)
: QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent) : QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)
{ {
Q_D(QPrintDialog);
if (!warnIfNotNative(d->printer))
return;
setAttribute(Qt::WA_DontShowOnScreen); setAttribute(Qt::WA_DontShowOnScreen);
} }
QPrintDialog::QPrintDialog(QWidget *parent) QPrintDialog::QPrintDialog(QWidget *parent)
: QAbstractPrintDialog(*(new QPrintDialogPrivate), 0, parent) : QAbstractPrintDialog(*(new QPrintDialogPrivate), 0, parent)
{ {
Q_D(QPrintDialog);
if (!warnIfNotNative(d->printer))
return;
setAttribute(Qt::WA_DontShowOnScreen); setAttribute(Qt::WA_DontShowOnScreen);
} }
@ -304,8 +308,6 @@ QPrintDialog::~QPrintDialog()
int QPrintDialog::exec() int QPrintDialog::exec()
{ {
Q_D(QPrintDialog); Q_D(QPrintDialog);
if (!warnIfNotNative(d->printer))
return QDialog::Rejected;
QDialog::setVisible(true); QDialog::setVisible(true);

View File

@ -170,6 +170,8 @@ struct Options
// Versioning // Versioning
QString versionName; QString versionName;
QString versionCode; QString versionCode;
QByteArray minSdkVersion{"21"};
QByteArray targetSdkVersion{"28"};
// lib c++ path // lib c++ path
QString stdCppPath; QString stdCppPath;
@ -859,6 +861,18 @@ bool readInputFile(Options *options)
options->versionCode = QStringLiteral("1"); options->versionCode = QStringLiteral("1");
} }
{
const QJsonValue ver = jsonObject.value(QLatin1String("android-min-sdk-version"));
if (!ver.isUndefined())
options->minSdkVersion = ver.toString().toUtf8();
}
{
const QJsonValue ver = jsonObject.value(QLatin1String("android-target-sdk-version"));
if (!ver.isUndefined())
options->targetSdkVersion = ver.toString().toUtf8();
}
{ {
const QJsonObject targetArchitectures = jsonObject.value(QLatin1String("architectures")).toObject(); const QJsonObject targetArchitectures = jsonObject.value(QLatin1String("architectures")).toObject();
if (targetArchitectures.isEmpty()) { if (targetArchitectures.isEmpty()) {
@ -2319,6 +2333,8 @@ bool buildAndroidProject(const Options &options)
gradleProperties["buildDir"] = "build"; gradleProperties["buildDir"] = "build";
gradleProperties["qt5AndroidDir"] = (options.qtInstallDirectory + QLatin1String("/src/android/java")).toUtf8(); gradleProperties["qt5AndroidDir"] = (options.qtInstallDirectory + QLatin1String("/src/android/java")).toUtf8();
gradleProperties["androidCompileSdkVersion"] = options.androidPlatform.split(QLatin1Char('-')).last().toLocal8Bit(); gradleProperties["androidCompileSdkVersion"] = options.androidPlatform.split(QLatin1Char('-')).last().toLocal8Bit();
gradleProperties["qtMinSdkVersion"] = options.minSdkVersion;
gradleProperties["qtTargetSdkVersion"] = options.targetSdkVersion;
if (gradleProperties["androidBuildToolsVersion"].isEmpty()) if (gradleProperties["androidBuildToolsVersion"].isEmpty())
gradleProperties["androidBuildToolsVersion"] = options.sdkBuildToolsVersion.toLocal8Bit(); gradleProperties["androidBuildToolsVersion"] = options.sdkBuildToolsVersion.toLocal8Bit();

View File

@ -233,6 +233,7 @@
#include <QtWidgets/qgraphicswidget.h> #include <QtWidgets/qgraphicswidget.h>
#include <QtGui/qpaintengine.h> #include <QtGui/qpaintengine.h>
#include <QtGui/qpainter.h> #include <QtGui/qpainter.h>
#include <QtGui/qpainterpath.h>
#include <QtGui/qpixmapcache.h> #include <QtGui/qpixmapcache.h>
#include <QtGui/qpolygon.h> #include <QtGui/qpolygon.h>
#include <QtGui/qtouchdevice.h> #include <QtGui/qtouchdevice.h>

View File

@ -60,6 +60,7 @@
#include "qgraphicswidget.h" #include "qgraphicswidget.h"
#include "qgraphicssceneindex_p.h" #include "qgraphicssceneindex_p.h"
#include "qgraphicsscenebsptreeindex_p.h" #include "qgraphicsscenebsptreeindex_p.h"
#include <QtGui/qpainterpath.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -293,6 +293,7 @@ static const int QGRAPHICSVIEW_PREALLOC_STYLE_OPTIONS = 503; // largest prime <
#include <QtWidgets/qlayout.h> #include <QtWidgets/qlayout.h>
#include <QtGui/qtransform.h> #include <QtGui/qtransform.h>
#include <QtGui/qpainter.h> #include <QtGui/qpainter.h>
#include <QtGui/qpainterpath.h>
#include <QtWidgets/qscrollbar.h> #include <QtWidgets/qscrollbar.h>
#include <QtWidgets/qstyleoption.h> #include <QtWidgets/qstyleoption.h>

View File

@ -59,6 +59,7 @@
#include <QtWidgets/qgraphicsview.h> #include <QtWidgets/qgraphicsview.h>
#include <QtWidgets/qgraphicsproxywidget.h> #include <QtWidgets/qgraphicsproxywidget.h>
#include <QtGui/qpalette.h> #include <QtGui/qpalette.h>
#include <QtGui/qpainterpath.h>
#include <QtWidgets/qstyleoption.h> #include <QtWidgets/qstyleoption.h>
#include <qdebug.h> #include <qdebug.h>

View File

@ -6125,7 +6125,7 @@ QIcon QCommonStyle::standardIcon(StandardPixmap standardIcon, const QStyleOption
const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size.width()); const QString cacheKey = QLatin1String("qt_mac_constructQIconFromIconRef") + QString::number(standardIcon) + QString::number(size.width());
if (standardIcon >= QStyle::SP_CustomBase) { if (standardIcon >= QStyle::SP_CustomBase) {
mainIcon = theme->standardPixmap(sp, QSizeF(size)); mainIcon = theme->standardPixmap(sp, QSizeF(size));
} else if (QPixmapCache::find(cacheKey, mainIcon) == false) { } else if (QPixmapCache::find(cacheKey, &mainIcon) == false) {
mainIcon = theme->standardPixmap(sp, QSizeF(size)); mainIcon = theme->standardPixmap(sp, QSizeF(size));
QPixmapCache::insert(cacheKey, mainIcon); QPixmapCache::insert(cacheKey, mainIcon);
} }

View File

@ -52,6 +52,7 @@
#include <qabstractbutton.h> #include <qabstractbutton.h>
#endif #endif
#include <qpainter.h> #include <qpainter.h>
#include <qpainterpath.h>
#include <qdir.h> #include <qdir.h>
#include <qstyleoption.h> #include <qstyleoption.h>
#include <qapplication.h> #include <qapplication.h>

View File

@ -118,6 +118,7 @@
#include <QtWidgets/qtoolbar.h> #include <QtWidgets/qtoolbar.h>
#endif #endif
#include <QtGui/qpainterpath.h>
#include <QtGui/qscreen.h> #include <QtGui/qscreen.h>
QT_BEGIN_NAMESPACE QT_BEGIN_NAMESPACE

View File

@ -78,6 +78,7 @@
#endif #endif
#include <private/qmath_p.h> #include <private/qmath_p.h>
#include <qmath.h> #include <qmath.h>
#include <QtGui/qpainterpath.h>
#include <QtGui/qscreen.h> #include <QtGui/qscreen.h>
#include <QtGui/qwindow.h> #include <QtGui/qwindow.h>
#include <qpa/qplatformtheme.h> #include <qpa/qplatformtheme.h>

View File

@ -158,10 +158,13 @@ private slots:
QFETCH(QtMsgType, msgType); QFETCH(QtMsgType, msgType);
QFETCH(LoggingRuleState, result); QFETCH(LoggingRuleState, result);
QLoggingRule rule(QStringRef(&pattern), true); const auto categoryL1 = category.toLatin1();
const auto categoryL1S = QLatin1String(categoryL1);
QLoggingRule rule(pattern, true);
LoggingRuleState state = Invalid; LoggingRuleState state = Invalid;
if (rule.flags != 0) { if (rule.flags != 0) {
switch (rule.pass(category, msgType)) { switch (rule.pass(categoryL1S, msgType)) {
case -1: QFAIL("Shoudn't happen, we set pattern to true"); break; case -1: QFAIL("Shoudn't happen, we set pattern to true"); break;
case 0: state = NoMatch; break; case 0: state = NoMatch; break;
case 1: state = Match; break; case 1: state = Match; break;

View File

@ -28,12 +28,13 @@
#include <QtTest/QtTest> #include <QtTest/QtTest>
#include <QtGui/QBitmap> #include <QtGui/QBitmap>
#include <QtGui/QPalette>
#include <QtGui/QPixmap>
#include <QtGui/QPicture>
#include <QtGui/QTextLength>
#include <QtGui/QPainter> #include <QtGui/QPainter>
#include <QtGui/QPainterPath>
#include <QtGui/QPalette>
#include <QtGui/QPen> #include <QtGui/QPen>
#include <QtGui/QPicture>
#include <QtGui/QPixmap>
#include <QtGui/QTextLength>
class tst_QDataStream : public QObject class tst_QDataStream : public QObject
{ {

View File

@ -73,6 +73,8 @@ QStringList toQStringList(const Iterable &i) {
MAKE_ALL(QByteArray, QChar) MAKE_ALL(QByteArray, QChar)
MAKE_ALL(QByteArray, QLatin1String) MAKE_ALL(QByteArray, QLatin1String)
MAKE_ALL(QByteArray, char16_t)
MAKE_ALL(char16_t, QByteArray)
MAKE_ALL(const char*, QChar) MAKE_ALL(const char*, QChar)
@ -100,6 +102,11 @@ static QByteArray rowName(const QByteArray &data)
return result; return result;
} }
# define QVERIFY_NOEXCEPT(expr) do { \
if (!has_nothrow_compare<LHS, RHS>::value) \
QEXPECT_FAIL("", "Qt is missing a nothrow utf8-utf16 comparator", Continue); \
QVERIFY(noexcept(expr)); } while (0)
class tst_QStringApiSymmetry : public QObject class tst_QStringApiSymmetry : public QObject
{ {
Q_OBJECT Q_OBJECT
@ -113,9 +120,11 @@ class tst_QStringApiSymmetry : public QObject
void compare_impl() const; void compare_impl() const;
private Q_SLOTS: private Q_SLOTS:
// test all combinations of {QChar, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*} // test all combinations of {QChar, char16_t, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*}
void compare_QChar_QChar_data() { compare_data(false); } void compare_QChar_QChar_data() { compare_data(false); }
void compare_QChar_QChar() { compare_impl<QChar, QChar>(); } void compare_QChar_QChar() { compare_impl<QChar, QChar>(); }
void compare_QChar_char16_t_data() { compare_data(false); }
void compare_QChar_char16_t() { compare_impl<QChar, char16_t>(); }
void compare_QChar_QStringRef_data() { compare_data(false); } void compare_QChar_QStringRef_data() { compare_data(false); }
void compare_QChar_QStringRef() { compare_impl<QChar, QStringRef>(); } void compare_QChar_QStringRef() { compare_impl<QChar, QStringRef>(); }
void compare_QChar_QString_data() { compare_data(false); } void compare_QChar_QString_data() { compare_data(false); }
@ -129,8 +138,27 @@ private Q_SLOTS:
void compare_QChar_const_char_star_data() { compare_data(false); } void compare_QChar_const_char_star_data() { compare_data(false); }
void compare_QChar_const_char_star() { compare_impl<QChar, const char *>(); } void compare_QChar_const_char_star() { compare_impl<QChar, const char *>(); }
void compare_char16_t_QChar_data() { compare_data(false); }
void compare_char16_t_QChar() { compare_impl<char16_t, QChar>(); }
//void compare_char16_t_char16_t_data() { compare_data(false); }
//void compare_char16_t_char16_t() { compare_impl<char16_t, char16_t>(); }
void compare_char16_t_QStringRef_data() { compare_data(false); }
void compare_char16_t_QStringRef() { compare_impl<char16_t, QStringRef>(); }
void compare_char16_t_QString_data() { compare_data(false); }
void compare_char16_t_QString() { compare_impl<char16_t, QString>(); }
void compare_char16_t_QStringView_data() { compare_data(false); }
void compare_char16_t_QStringView() { compare_impl<char16_t, QStringView>(); }
void compare_char16_t_QLatin1String_data() { compare_data(false); }
void compare_char16_t_QLatin1String() { compare_impl<char16_t, QLatin1String>(); }
void compare_char16_t_QByteArray_data() { compare_data(false); }
void compare_char16_t_QByteArray() { compare_impl<char16_t, QByteArray>(); }
//void compare_char16_t_const_char_star_data() { compare_data(false); }
//void compare_char16_t_const_char_star() { compare_impl<char16_t, const char *>(); }
void compare_QStringRef_QChar_data() { compare_data(false); } void compare_QStringRef_QChar_data() { compare_data(false); }
void compare_QStringRef_QChar() { compare_impl<QStringRef, QChar>(); } void compare_QStringRef_QChar() { compare_impl<QStringRef, QChar>(); }
void compare_QStringRef_char16_t_data() { compare_data(false); }
void compare_QStringRef_char16_t() { compare_impl<QStringRef, char16_t>(); }
void compare_QStringRef_QStringRef_data() { compare_data(); } void compare_QStringRef_QStringRef_data() { compare_data(); }
void compare_QStringRef_QStringRef() { compare_impl<QStringRef, QStringRef>(); } void compare_QStringRef_QStringRef() { compare_impl<QStringRef, QStringRef>(); }
void compare_QStringRef_QString_data() { compare_data(); } void compare_QStringRef_QString_data() { compare_data(); }
@ -146,6 +174,8 @@ private Q_SLOTS:
void compare_QString_QChar_data() { compare_data(false); } void compare_QString_QChar_data() { compare_data(false); }
void compare_QString_QChar() { compare_impl<QString, QChar>(); } void compare_QString_QChar() { compare_impl<QString, QChar>(); }
void compare_QString_char16_t_data() { compare_data(false); }
void compare_QString_char16_t() { compare_impl<QString, char16_t>(); }
void compare_QString_QStringRef_data() { compare_data(); } void compare_QString_QStringRef_data() { compare_data(); }
void compare_QString_QStringRef() { compare_impl<QString, QStringRef>(); } void compare_QString_QStringRef() { compare_impl<QString, QStringRef>(); }
void compare_QString_QString_data() { compare_data(); } void compare_QString_QString_data() { compare_data(); }
@ -161,6 +191,8 @@ private Q_SLOTS:
void compare_QStringView_QChar_data() { compare_data(false); } void compare_QStringView_QChar_data() { compare_data(false); }
void compare_QStringView_QChar() { compare_impl<QStringView, QChar>(); } void compare_QStringView_QChar() { compare_impl<QStringView, QChar>(); }
void compare_QStringView_char16_t_data() { compare_data(false); }
void compare_QStringView_char16_t() { compare_impl<QStringView, char16_t>(); }
void compare_QStringView_QStringRef_data() { compare_data(); } void compare_QStringView_QStringRef_data() { compare_data(); }
void compare_QStringView_QStringRef() { compare_impl<QStringView, QStringRef>(); } void compare_QStringView_QStringRef() { compare_impl<QStringView, QStringRef>(); }
void compare_QStringView_QString_data() { compare_data(); } void compare_QStringView_QString_data() { compare_data(); }
@ -178,6 +210,8 @@ private Q_SLOTS:
void compare_QLatin1String_QChar_data() { compare_data(false); } void compare_QLatin1String_QChar_data() { compare_data(false); }
void compare_QLatin1String_QChar() { compare_impl<QLatin1String, QChar>(); } void compare_QLatin1String_QChar() { compare_impl<QLatin1String, QChar>(); }
void compare_QLatin1String_char16_t_data() { compare_data(false); }
void compare_QLatin1String_char16_t() { compare_impl<QLatin1String, char16_t>(); }
void compare_QLatin1String_QStringRef_data() { compare_data(); } void compare_QLatin1String_QStringRef_data() { compare_data(); }
void compare_QLatin1String_QStringRef() { compare_impl<QLatin1String, QStringRef>(); } void compare_QLatin1String_QStringRef() { compare_impl<QLatin1String, QStringRef>(); }
void compare_QLatin1String_QString_data() { compare_data(); } void compare_QLatin1String_QString_data() { compare_data(); }
@ -193,6 +227,8 @@ private Q_SLOTS:
void compare_QByteArray_QChar_data() { compare_data(false); } void compare_QByteArray_QChar_data() { compare_data(false); }
void compare_QByteArray_QChar() { compare_impl<QByteArray, QChar>(); } void compare_QByteArray_QChar() { compare_impl<QByteArray, QChar>(); }
void compare_QByteArray_char16_t_data() { compare_data(false); }
void compare_QByteArray_char16_t() { compare_impl<QByteArray, char16_t>(); }
void compare_QByteArray_QStringRef_data() { compare_data(); } void compare_QByteArray_QStringRef_data() { compare_data(); }
void compare_QByteArray_QStringRef() { compare_impl<QByteArray, QStringRef>(); } void compare_QByteArray_QStringRef() { compare_impl<QByteArray, QStringRef>(); }
void compare_QByteArray_QString_data() { compare_data(); } void compare_QByteArray_QString_data() { compare_data(); }
@ -206,6 +242,8 @@ private Q_SLOTS:
void compare_const_char_star_QChar_data() { compare_data(false); } void compare_const_char_star_QChar_data() { compare_data(false); }
void compare_const_char_star_QChar() { compare_impl<const char *, QChar>(); } void compare_const_char_star_QChar() { compare_impl<const char *, QChar>(); }
//void compare_const_char_star_char16_t_data() { compare_data(false); }
//void compare_const_char_star_char16_t() { compare_impl<const char *, char16_t>(); }
void compare_const_char_star_QStringRef_data() { compare_data(); } void compare_const_char_star_QStringRef_data() { compare_data(); }
void compare_const_char_star_QStringRef() { compare_impl<const char *, QStringRef>(); } void compare_const_char_star_QStringRef() { compare_impl<const char *, QStringRef>(); }
void compare_const_char_star_QString_data() { compare_data(); } void compare_const_char_star_QString_data() { compare_data(); }
@ -223,10 +261,12 @@ private:
void member_compare_impl() const; void member_compare_impl() const;
private Q_SLOTS: private Q_SLOTS:
// test all combinations of {QChar, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*} // test all combinations of {QChar, char16_t, QStringRef, QString, QStringView, QLatin1String, QByteArray, const char*}
#ifdef NOT_YET_IMPLEMENTED // probably never will be - what's the point of QChar::compare(QStringView)? #ifdef NOT_YET_IMPLEMENTED // probably never will be - what's the point of QChar::compare(QStringView)?
void member_compare_QChar_QChar_data() { member_compare_data(false); } void member_compare_QChar_QChar_data() { member_compare_data(false); }
void member_compare_QChar_QChar() { member_compare_impl<QChar, QChar>(); } void member_compare_QChar_QChar() { member_compare_impl<QChar, QChar>(); }
void member_compare_QChar_char16_t_data() { member_compare_data(false); }
void member_compare_QChar_char16_t() { member_compare_impl<QChar, char16_t>(); }
void member_compare_QChar_QStringRef_data() { member_compare_data(false); } void member_compare_QChar_QStringRef_data() { member_compare_data(false); }
void member_compare_QChar_QStringRef() { member_compare_impl<QChar, QStringRef>(); } void member_compare_QChar_QStringRef() { member_compare_impl<QChar, QStringRef>(); }
void member_compare_QChar_QString_data() { member_compare_data(false); } void member_compare_QChar_QString_data() { member_compare_data(false); }
@ -241,8 +281,12 @@ private Q_SLOTS:
void member_compare_QChar_const_char_star() { member_compare_impl<QChar, const char *>(); } void member_compare_QChar_const_char_star() { member_compare_impl<QChar, const char *>(); }
#endif #endif
// void member_compare_char16_t_XXX() - not possible
void member_compare_QStringRef_QChar_data() { member_compare_data(false); } void member_compare_QStringRef_QChar_data() { member_compare_data(false); }
void member_compare_QStringRef_QChar() { member_compare_impl<QStringRef, QChar>(); } void member_compare_QStringRef_QChar() { member_compare_impl<QStringRef, QChar>(); }
void member_compare_QStringRef_char16_t_data() { member_compare_data(false); }
void member_compare_QStringRef_char16_t() { member_compare_impl<QStringRef, char16_t>(); }
void member_compare_QStringRef_QStringRef_data() { member_compare_data(); } void member_compare_QStringRef_QStringRef_data() { member_compare_data(); }
void member_compare_QStringRef_QStringRef() { member_compare_impl<QStringRef, QStringRef>(); } void member_compare_QStringRef_QStringRef() { member_compare_impl<QStringRef, QStringRef>(); }
void member_compare_QStringRef_QString_data() { member_compare_data(); } void member_compare_QStringRef_QString_data() { member_compare_data(); }
@ -262,6 +306,8 @@ private Q_SLOTS:
void member_compare_QString_QChar_data() { member_compare_data(false); } void member_compare_QString_QChar_data() { member_compare_data(false); }
void member_compare_QString_QChar() { member_compare_impl<QString, QChar>(); } void member_compare_QString_QChar() { member_compare_impl<QString, QChar>(); }
void member_compare_QString_char16_t_data() { member_compare_data(false); }
void member_compare_QString_char16_t() { member_compare_impl<QString, char16_t>(); }
void member_compare_QString_QStringRef_data() { member_compare_data(); } void member_compare_QString_QStringRef_data() { member_compare_data(); }
void member_compare_QString_QStringRef() { member_compare_impl<QString, QStringRef>(); } void member_compare_QString_QStringRef() { member_compare_impl<QString, QStringRef>(); }
void member_compare_QString_QString_data() { member_compare_data(); } void member_compare_QString_QString_data() { member_compare_data(); }
@ -275,26 +321,29 @@ private Q_SLOTS:
void member_compare_QString_const_char_star_data() { member_compare_data(); } void member_compare_QString_const_char_star_data() { member_compare_data(); }
void member_compare_QString_const_char_star() { member_compare_impl<QString, const char *>(); } void member_compare_QString_const_char_star() { member_compare_impl<QString, const char *>(); }
#ifdef NOT_YET_IMPLEMENTED // QChar doesn't implicitly convert to QStringView
void member_compare_QStringView_QChar_data() { member_compare_data(false); } void member_compare_QStringView_QChar_data() { member_compare_data(false); }
void member_compare_QStringView_QChar() { member_compare_impl<QStringView, QChar>(); } void member_compare_QStringView_QChar() { member_compare_impl<QStringView, QChar>(); }
#endif void member_compare_QStringView_char16_t_data() { member_compare_data(false); }
void member_compare_QStringView_char16_t() { member_compare_impl<QStringView, char16_t>(); }
void member_compare_QStringView_QStringRef_data() { member_compare_data(); } void member_compare_QStringView_QStringRef_data() { member_compare_data(); }
void member_compare_QStringView_QStringRef() { member_compare_impl<QStringView, QStringRef>(); } void member_compare_QStringView_QStringRef() { member_compare_impl<QStringView, QStringRef>(); }
void member_compare_QStringView_QString_data() { member_compare_data(); } void member_compare_QStringView_QString_data() { member_compare_data(); }
void member_compare_QStringView_QString() { member_compare_impl<QStringView, QString>(); } void member_compare_QStringView_QString() { member_compare_impl<QStringView, QString>(); }
void member_compare_QStringView_QStringView_data() { member_compare_data(); } void member_compare_QStringView_QStringView_data() { member_compare_data(); }
void member_compare_QStringView_QStringView() { member_compare_impl<QStringView, QStringView>(); } void member_compare_QStringView_QStringView() { member_compare_impl<QStringView, QStringView>(); }
#ifdef NOT_YET_IMPLEMENTED
void member_compare_QStringView_QLatin1String_data() { member_compare_data(); } void member_compare_QStringView_QLatin1String_data() { member_compare_data(); }
void member_compare_QStringView_QLatin1String() { member_compare_impl<QStringView, QLatin1String>(); } void member_compare_QStringView_QLatin1String() { member_compare_impl<QStringView, QLatin1String>(); }
#ifdef NOT_YET_IMPLEMENTED
void member_compare_QStringView_QByteArray_data() { member_compare_data(); } void member_compare_QStringView_QByteArray_data() { member_compare_data(); }
void member_compare_QStringView_QByteArray() { member_compare_impl<QStringView, QByteArray>(); } void member_compare_QStringView_QByteArray() { member_compare_impl<QStringView, QByteArray>(); }
void member_compare_QStringView_const_char_star_data() { member_compare_data(); } void member_compare_QStringView_const_char_star_data() { member_compare_data(); }
void member_compare_QStringView_const_char_star() { member_compare_impl<QStringView, const char *>(); } void member_compare_QStringView_const_char_star() { member_compare_impl<QStringView, const char *>(); }
#endif
void member_compare_QLatin1String_QChar_data() { member_compare_data(false); } void member_compare_QLatin1String_QChar_data() { member_compare_data(false); }
void member_compare_QLatin1String_QChar() { member_compare_impl<QLatin1String, QChar>(); } void member_compare_QLatin1String_QChar() { member_compare_impl<QLatin1String, QChar>(); }
void member_compare_QLatin1String_char16_t_data() { member_compare_data(false); }
void member_compare_QLatin1String_char16_t() { member_compare_impl<QLatin1String, char16_t>(); }
void member_compare_QLatin1String_QStringRef_data() { member_compare_data(); } void member_compare_QLatin1String_QStringRef_data() { member_compare_data(); }
void member_compare_QLatin1String_QStringRef() { member_compare_impl<QLatin1String, QStringRef>(); } void member_compare_QLatin1String_QStringRef() { member_compare_impl<QLatin1String, QStringRef>(); }
void member_compare_QLatin1String_QString_data() { member_compare_data(); } void member_compare_QLatin1String_QString_data() { member_compare_data(); }
@ -303,6 +352,7 @@ private Q_SLOTS:
void member_compare_QLatin1String_QStringView() { member_compare_impl<QLatin1String, QStringView>(); } void member_compare_QLatin1String_QStringView() { member_compare_impl<QLatin1String, QStringView>(); }
void member_compare_QLatin1String_QLatin1String_data() { member_compare_data(); } void member_compare_QLatin1String_QLatin1String_data() { member_compare_data(); }
void member_compare_QLatin1String_QLatin1String() { member_compare_impl<QLatin1String, QLatin1String>(); } void member_compare_QLatin1String_QLatin1String() { member_compare_impl<QLatin1String, QLatin1String>(); }
#ifdef NOT_YET_IMPLEMENTED
void member_compare_QLatin1String_QByteArray_data() { member_compare_data(); } void member_compare_QLatin1String_QByteArray_data() { member_compare_data(); }
void member_compare_QLatin1String_QByteArray() { member_compare_impl<QLatin1String, QByteArray>(); } void member_compare_QLatin1String_QByteArray() { member_compare_impl<QLatin1String, QByteArray>(); }
void member_compare_QLatin1String_const_char_star_data() { member_compare_data(); } void member_compare_QLatin1String_const_char_star_data() { member_compare_data(); }
@ -310,6 +360,8 @@ private Q_SLOTS:
void member_compare_QByteArray_QChar_data() { member_compare_data(false); } void member_compare_QByteArray_QChar_data() { member_compare_data(false); }
void member_compare_QByteArray_QChar() { member_compare_impl<QByteArray, QChar>(); } void member_compare_QByteArray_QChar() { member_compare_impl<QByteArray, QChar>(); }
void member_compare_QByteArray_char16_t_data() { member_compare_data(false); }
void member_compare_QByteArray_char16_t() { member_compare_impl<QByteArray, char16_t>(); }
void member_compare_QByteArray_QStringRef_data() { member_compare_data(); } void member_compare_QByteArray_QStringRef_data() { member_compare_data(); }
void member_compare_QByteArray_QStringRef() { member_compare_impl<QByteArray, QStringRef>(); } void member_compare_QByteArray_QStringRef() { member_compare_impl<QByteArray, QStringRef>(); }
void member_compare_QByteArray_QString_data() { member_compare_data(); } void member_compare_QByteArray_QString_data() { member_compare_data(); }
@ -330,7 +382,7 @@ private:
template <typename Haystack, typename Needle> void endsWith_impl() const; template <typename Haystack, typename Needle> void endsWith_impl() const;
private Q_SLOTS: private Q_SLOTS:
// test all combinations of {QString, QStringRef, QStringView, QLatin1String} x {QString, QStringRef, QStringView, QLatin1String, QChar}: // test all combinations of {QString, QStringRef, QStringView, QLatin1String} x {QString, QStringRef, QStringView, QLatin1String, QChar, char16_t}:
void startsWith_QString_QString_data() { startsWith_data(); } void startsWith_QString_QString_data() { startsWith_data(); }
void startsWith_QString_QString() { startsWith_impl<QString, QString>(); } void startsWith_QString_QString() { startsWith_impl<QString, QString>(); }
void startsWith_QString_QStringRef_data() { startsWith_data(); } void startsWith_QString_QStringRef_data() { startsWith_data(); }
@ -341,6 +393,8 @@ private Q_SLOTS:
void startsWith_QString_QLatin1String() { startsWith_impl<QString, QLatin1String>(); } void startsWith_QString_QLatin1String() { startsWith_impl<QString, QLatin1String>(); }
void startsWith_QString_QChar_data() { startsWith_data(false); } void startsWith_QString_QChar_data() { startsWith_data(false); }
void startsWith_QString_QChar() { startsWith_impl<QString, QChar>(); } void startsWith_QString_QChar() { startsWith_impl<QString, QChar>(); }
void startsWith_QString_char16_t_data() { startsWith_data(false); }
void startsWith_QString_char16_t() { startsWith_impl<QString, char16_t>(); }
void startsWith_QStringRef_QString_data() { startsWith_data(); } void startsWith_QStringRef_QString_data() { startsWith_data(); }
void startsWith_QStringRef_QString() { startsWith_impl<QStringRef, QString>(); } void startsWith_QStringRef_QString() { startsWith_impl<QStringRef, QString>(); }
@ -352,6 +406,8 @@ private Q_SLOTS:
void startsWith_QStringRef_QLatin1String() { startsWith_impl<QStringRef, QLatin1String>(); } void startsWith_QStringRef_QLatin1String() { startsWith_impl<QStringRef, QLatin1String>(); }
void startsWith_QStringRef_QChar_data() { startsWith_data(false); } void startsWith_QStringRef_QChar_data() { startsWith_data(false); }
void startsWith_QStringRef_QChar() { startsWith_impl<QStringRef, QChar>(); } void startsWith_QStringRef_QChar() { startsWith_impl<QStringRef, QChar>(); }
void startsWith_QStringRef_char16_t_data() { startsWith_data(false); }
void startsWith_QStringRef_char16_t() { startsWith_impl<QStringRef, char16_t>(); }
void startsWith_QStringView_QString_data() { startsWith_data(); } void startsWith_QStringView_QString_data() { startsWith_data(); }
void startsWith_QStringView_QString() { startsWith_impl<QStringView, QString>(); } void startsWith_QStringView_QString() { startsWith_impl<QStringView, QString>(); }
@ -363,6 +419,8 @@ private Q_SLOTS:
void startsWith_QStringView_QLatin1String() { startsWith_impl<QStringView, QLatin1String>(); } void startsWith_QStringView_QLatin1String() { startsWith_impl<QStringView, QLatin1String>(); }
void startsWith_QStringView_QChar_data() { startsWith_data(false); } void startsWith_QStringView_QChar_data() { startsWith_data(false); }
void startsWith_QStringView_QChar() { startsWith_impl<QStringView, QChar>(); } void startsWith_QStringView_QChar() { startsWith_impl<QStringView, QChar>(); }
void startsWith_QStringView_char16_t_data() { startsWith_data(false); }
void startsWith_QStringView_char16_t() { startsWith_impl<QStringView, char16_t>(); }
void startsWith_QLatin1String_QString_data() { startsWith_data(); } void startsWith_QLatin1String_QString_data() { startsWith_data(); }
void startsWith_QLatin1String_QString() { startsWith_impl<QLatin1String, QString>(); } void startsWith_QLatin1String_QString() { startsWith_impl<QLatin1String, QString>(); }
@ -374,6 +432,8 @@ private Q_SLOTS:
void startsWith_QLatin1String_QLatin1String() { startsWith_impl<QLatin1String, QLatin1String>(); } void startsWith_QLatin1String_QLatin1String() { startsWith_impl<QLatin1String, QLatin1String>(); }
void startsWith_QLatin1String_QChar_data() { startsWith_data(false); } void startsWith_QLatin1String_QChar_data() { startsWith_data(false); }
void startsWith_QLatin1String_QChar() { startsWith_impl<QLatin1String, QChar>(); } void startsWith_QLatin1String_QChar() { startsWith_impl<QLatin1String, QChar>(); }
void startsWith_QLatin1String_char16_t_data() { startsWith_data(false); }
void startsWith_QLatin1String_char16_t() { startsWith_impl<QLatin1String, char16_t>(); }
void endsWith_QString_QString_data() { endsWith_data(); } void endsWith_QString_QString_data() { endsWith_data(); }
void endsWith_QString_QString() { endsWith_impl<QString, QString>(); } void endsWith_QString_QString() { endsWith_impl<QString, QString>(); }
@ -385,6 +445,8 @@ private Q_SLOTS:
void endsWith_QString_QLatin1String() { endsWith_impl<QString, QLatin1String>(); } void endsWith_QString_QLatin1String() { endsWith_impl<QString, QLatin1String>(); }
void endsWith_QString_QChar_data() { endsWith_data(false); } void endsWith_QString_QChar_data() { endsWith_data(false); }
void endsWith_QString_QChar() { endsWith_impl<QString, QChar>(); } void endsWith_QString_QChar() { endsWith_impl<QString, QChar>(); }
void endsWith_QString_char16_t_data() { endsWith_data(false); }
void endsWith_QString_char16_t() { endsWith_impl<QString, char16_t>(); }
void endsWith_QStringRef_QString_data() { endsWith_data(); } void endsWith_QStringRef_QString_data() { endsWith_data(); }
void endsWith_QStringRef_QString() { endsWith_impl<QStringRef, QString>(); } void endsWith_QStringRef_QString() { endsWith_impl<QStringRef, QString>(); }
@ -396,6 +458,8 @@ private Q_SLOTS:
void endsWith_QStringRef_QLatin1String() { endsWith_impl<QStringRef, QLatin1String>(); } void endsWith_QStringRef_QLatin1String() { endsWith_impl<QStringRef, QLatin1String>(); }
void endsWith_QStringRef_QChar_data() { endsWith_data(false); } void endsWith_QStringRef_QChar_data() { endsWith_data(false); }
void endsWith_QStringRef_QChar() { endsWith_impl<QStringRef, QChar>(); } void endsWith_QStringRef_QChar() { endsWith_impl<QStringRef, QChar>(); }
void endsWith_QStringRef_char16_t_data() { endsWith_data(false); }
void endsWith_QStringRef_char16_t() { endsWith_impl<QStringRef, char16_t>(); }
void endsWith_QStringView_QString_data() { endsWith_data(); } void endsWith_QStringView_QString_data() { endsWith_data(); }
void endsWith_QStringView_QString() { endsWith_impl<QStringView, QString>(); } void endsWith_QStringView_QString() { endsWith_impl<QStringView, QString>(); }
@ -407,6 +471,8 @@ private Q_SLOTS:
void endsWith_QStringView_QLatin1String() { endsWith_impl<QStringView, QLatin1String>(); } void endsWith_QStringView_QLatin1String() { endsWith_impl<QStringView, QLatin1String>(); }
void endsWith_QStringView_QChar_data() { endsWith_data(false); } void endsWith_QStringView_QChar_data() { endsWith_data(false); }
void endsWith_QStringView_QChar() { endsWith_impl<QStringView, QChar>(); } void endsWith_QStringView_QChar() { endsWith_impl<QStringView, QChar>(); }
void endsWith_QStringView_char16_t_data() { endsWith_data(false); }
void endsWith_QStringView_char16_t() { endsWith_impl<QStringView, char16_t>(); }
void endsWith_QLatin1String_QString_data() { endsWith_data(); } void endsWith_QLatin1String_QString_data() { endsWith_data(); }
void endsWith_QLatin1String_QString() { endsWith_impl<QLatin1String, QString>(); } void endsWith_QLatin1String_QString() { endsWith_impl<QLatin1String, QString>(); }
@ -418,6 +484,8 @@ private Q_SLOTS:
void endsWith_QLatin1String_QLatin1String() { endsWith_impl<QLatin1String, QLatin1String>(); } void endsWith_QLatin1String_QLatin1String() { endsWith_impl<QLatin1String, QLatin1String>(); }
void endsWith_QLatin1String_QChar_data() { endsWith_data(false); } void endsWith_QLatin1String_QChar_data() { endsWith_data(false); }
void endsWith_QLatin1String_QChar() { endsWith_impl<QLatin1String, QChar>(); } void endsWith_QLatin1String_QChar() { endsWith_impl<QLatin1String, QChar>(); }
void endsWith_QLatin1String_char16_t_data() { endsWith_data(false); }
void endsWith_QLatin1String_char16_t() { endsWith_impl<QLatin1String, char16_t>(); }
private: private:
void split_data(bool rhsHasVariableLength = true); void split_data(bool rhsHasVariableLength = true);
@ -566,9 +634,10 @@ private Q_SLOTS:
private: private:
template <typename Haystack, typename Needle> void indexOf_impl() const; template <typename Haystack, typename Needle> void indexOf_impl() const;
void indexOf_data(); void indexOf_data(bool rhsHasVariableLength = true);
private Q_SLOTS: private Q_SLOTS:
// test all combinations of {QString, QLatin1String, QStringRef, QStringView} x {QString, QLatin1String, QStringRef, QStringView, QChar, char16_t}:
void indexOf_QString_QString_data() { indexOf_data(); } void indexOf_QString_QString_data() { indexOf_data(); }
void indexOf_QString_QString() { indexOf_impl<QString, QString>(); } void indexOf_QString_QString() { indexOf_impl<QString, QString>(); }
void indexOf_QString_QLatin1String_data() { indexOf_data(); } void indexOf_QString_QLatin1String_data() { indexOf_data(); }
@ -577,6 +646,10 @@ private Q_SLOTS:
void indexOf_QString_QStringRef() { indexOf_impl<QString, QStringRef>(); } void indexOf_QString_QStringRef() { indexOf_impl<QString, QStringRef>(); }
void indexOf_QString_QStringView_data() { indexOf_data(); } void indexOf_QString_QStringView_data() { indexOf_data(); }
void indexOf_QString_QStringView() { indexOf_impl<QString, QStringView>(); } void indexOf_QString_QStringView() { indexOf_impl<QString, QStringView>(); }
void indexOf_QString_QChar_data() { indexOf_data(false); }
void indexOf_QString_QChar() { indexOf_impl<QString, QChar>(); }
void indexOf_QString_char16_t_data() { indexOf_data(false); }
void indexOf_QString_char16_t() { indexOf_impl<QString, char16_t>(); }
void indexOf_QLatin1String_QString_data() { indexOf_data(); } void indexOf_QLatin1String_QString_data() { indexOf_data(); }
void indexOf_QLatin1String_QString() { indexOf_impl<QLatin1String, QString>(); } void indexOf_QLatin1String_QString() { indexOf_impl<QLatin1String, QString>(); }
@ -586,6 +659,10 @@ private Q_SLOTS:
void indexOf_QLatin1String_QStringRef() { indexOf_impl<QLatin1String, QStringRef>(); } void indexOf_QLatin1String_QStringRef() { indexOf_impl<QLatin1String, QStringRef>(); }
void indexOf_QLatin1String_QStringView_data() { indexOf_data(); } void indexOf_QLatin1String_QStringView_data() { indexOf_data(); }
void indexOf_QLatin1String_QStringView() { indexOf_impl<QLatin1String, QStringView>(); } void indexOf_QLatin1String_QStringView() { indexOf_impl<QLatin1String, QStringView>(); }
void indexOf_QLatin1String_QChar_data() { indexOf_data(false); }
void indexOf_QLatin1String_QChar() { indexOf_impl<QLatin1String, QChar>(); }
void indexOf_QLatin1String_char16_t_data() { indexOf_data(false); }
void indexOf_QLatin1String_char16_t() { indexOf_impl<QLatin1String, char16_t>(); }
void indexOf_QStringRef_QString_data() { indexOf_data(); } void indexOf_QStringRef_QString_data() { indexOf_data(); }
void indexOf_QStringRef_QString() { indexOf_impl<QStringRef, QString>(); } void indexOf_QStringRef_QString() { indexOf_impl<QStringRef, QString>(); }
@ -595,6 +672,10 @@ private Q_SLOTS:
void indexOf_QStringRef_QStringRef() { indexOf_impl<QStringRef, QStringRef>(); } void indexOf_QStringRef_QStringRef() { indexOf_impl<QStringRef, QStringRef>(); }
void indexOf_QStringRef_QStringView_data() { indexOf_data(); } void indexOf_QStringRef_QStringView_data() { indexOf_data(); }
void indexOf_QStringRef_QStringView() { indexOf_impl<QStringRef, QStringView>(); } void indexOf_QStringRef_QStringView() { indexOf_impl<QStringRef, QStringView>(); }
void indexOf_QStringRef_QChar_data() { indexOf_data(false); }
void indexOf_QStringRef_QChar() { indexOf_impl<QStringRef, QChar>(); }
void indexOf_QStringRef_char16_t_data() { indexOf_data(false); }
void indexOf_QStringRef_char16_t() { indexOf_impl<QStringRef, char16_t>(); }
void indexOf_QStringView_QString_data() { indexOf_data(); } void indexOf_QStringView_QString_data() { indexOf_data(); }
void indexOf_QStringView_QString() { indexOf_impl<QStringView, QString>(); } void indexOf_QStringView_QString() { indexOf_impl<QStringView, QString>(); }
@ -604,12 +685,17 @@ private Q_SLOTS:
void indexOf_QStringView_QStringRef() { indexOf_impl<QStringView, QStringRef>(); } void indexOf_QStringView_QStringRef() { indexOf_impl<QStringView, QStringRef>(); }
void indexOf_QStringView_QStringView_data() { indexOf_data(); } void indexOf_QStringView_QStringView_data() { indexOf_data(); }
void indexOf_QStringView_QStringView() { indexOf_impl<QStringView, QStringView>(); } void indexOf_QStringView_QStringView() { indexOf_impl<QStringView, QStringView>(); }
void indexOf_QStringView_QChar_data() { indexOf_data(false); }
void indexOf_QStringView_QChar() { indexOf_impl<QStringView, QChar>(); }
void indexOf_QStringView_char16_t_data() { indexOf_data(false); }
void indexOf_QStringView_char16_t() { indexOf_impl<QStringView, char16_t>(); }
private: private:
template <typename Haystack, typename Needle> void contains_impl() const; template <typename Haystack, typename Needle> void contains_impl() const;
void contains_data(); void contains_data(bool rhsHasVariableLength = true);
private Q_SLOTS: private Q_SLOTS:
// test all combinations of {QString, QLatin1String, QStringRef, QStringView} x {QString, QLatin1String, QStringRef, QStringView, QChar, char16_t}:
void contains_QString_QString_data() { contains_data(); } void contains_QString_QString_data() { contains_data(); }
void contains_QString_QString() { contains_impl<QString, QString>(); } void contains_QString_QString() { contains_impl<QString, QString>(); }
void contains_QString_QLatin1String_data() { contains_data(); } void contains_QString_QLatin1String_data() { contains_data(); }
@ -618,6 +704,10 @@ private Q_SLOTS:
void contains_QString_QStringRef() { contains_impl<QString, QStringRef>(); } void contains_QString_QStringRef() { contains_impl<QString, QStringRef>(); }
void contains_QString_QStringView_data() { contains_data(); } void contains_QString_QStringView_data() { contains_data(); }
void contains_QString_QStringView() { contains_impl<QString, QStringView>(); } void contains_QString_QStringView() { contains_impl<QString, QStringView>(); }
void contains_QString_QChar_data() { contains_data(false); }
void contains_QString_QChar() { contains_impl<QString, QChar>(); }
void contains_QString_char16_t_data() { contains_data(false); }
void contains_QString_char16_t() { contains_impl<QString, char16_t>(); }
void contains_QLatin1String_QString_data() { contains_data(); } void contains_QLatin1String_QString_data() { contains_data(); }
void contains_QLatin1String_QString() { contains_impl<QLatin1String, QString>(); } void contains_QLatin1String_QString() { contains_impl<QLatin1String, QString>(); }
@ -627,6 +717,10 @@ private Q_SLOTS:
void contains_QLatin1String_QStringRef() { contains_impl<QLatin1String, QStringRef>(); } void contains_QLatin1String_QStringRef() { contains_impl<QLatin1String, QStringRef>(); }
void contains_QLatin1String_QStringView_data() { contains_data(); } void contains_QLatin1String_QStringView_data() { contains_data(); }
void contains_QLatin1String_QStringView() { contains_impl<QLatin1String, QStringView>(); } void contains_QLatin1String_QStringView() { contains_impl<QLatin1String, QStringView>(); }
void contains_QLatin1String_QChar_data() { contains_data(false); }
void contains_QLatin1String_QChar() { contains_impl<QLatin1String, QChar>(); }
void contains_QLatin1String_char16_t_data() { contains_data(false); }
void contains_QLatin1String_char16_t() { contains_impl<QLatin1String, char16_t>(); }
void contains_QStringRef_QString_data() { contains_data(); } void contains_QStringRef_QString_data() { contains_data(); }
void contains_QStringRef_QString() { contains_impl<QStringRef, QString>(); } void contains_QStringRef_QString() { contains_impl<QStringRef, QString>(); }
@ -636,6 +730,10 @@ private Q_SLOTS:
void contains_QStringRef_QStringRef() { contains_impl<QStringRef, QStringRef>(); } void contains_QStringRef_QStringRef() { contains_impl<QStringRef, QStringRef>(); }
void contains_QStringRef_QStringView_data() { contains_data(); } void contains_QStringRef_QStringView_data() { contains_data(); }
void contains_QStringRef_QStringView() { contains_impl<QStringRef, QStringView>(); } void contains_QStringRef_QStringView() { contains_impl<QStringRef, QStringView>(); }
void contains_QStringRef_QChar_data() { contains_data(false); }
void contains_QStringRef_QChar() { contains_impl<QStringRef, QChar>(); }
void contains_QStringRef_char16_t_data() { contains_data(false); }
void contains_QStringRef_char16_t() { contains_impl<QStringRef, char16_t>(); }
void contains_QStringView_QString_data() { contains_data(); } void contains_QStringView_QString_data() { contains_data(); }
void contains_QStringView_QString() { contains_impl<QStringView, QString>(); } void contains_QStringView_QString() { contains_impl<QStringView, QString>(); }
@ -645,12 +743,17 @@ private Q_SLOTS:
void contains_QStringView_QStringRef() { contains_impl<QStringView, QStringRef>(); } void contains_QStringView_QStringRef() { contains_impl<QStringView, QStringRef>(); }
void contains_QStringView_QStringView_data() { contains_data(); } void contains_QStringView_QStringView_data() { contains_data(); }
void contains_QStringView_QStringView() { contains_impl<QStringView, QStringView>(); } void contains_QStringView_QStringView() { contains_impl<QStringView, QStringView>(); }
void contains_QStringView_QChar_data() { contains_data(false); }
void contains_QStringView_QChar() { contains_impl<QStringView, QChar>(); }
void contains_QStringView_char16_t_data() { contains_data(false); }
void contains_QStringView_char16_t() { contains_impl<QStringView, char16_t>(); }
private: private:
template <typename Haystack, typename Needle> void lastIndexOf_impl() const; template <typename Haystack, typename Needle> void lastIndexOf_impl() const;
void lastIndexOf_data(); void lastIndexOf_data(bool rhsHasVariableLength = true);
private Q_SLOTS: private Q_SLOTS:
// test all combinations of {QString, QLatin1String, QStringRef, QStringView} x {QString, QLatin1String, QStringRef, QStringView, QChar, char16_t}:
void lastIndexOf_QString_QString_data() { lastIndexOf_data(); } void lastIndexOf_QString_QString_data() { lastIndexOf_data(); }
void lastIndexOf_QString_QString() { lastIndexOf_impl<QString, QString>(); } void lastIndexOf_QString_QString() { lastIndexOf_impl<QString, QString>(); }
void lastIndexOf_QString_QLatin1String_data() { lastIndexOf_data(); } void lastIndexOf_QString_QLatin1String_data() { lastIndexOf_data(); }
@ -659,6 +762,10 @@ private Q_SLOTS:
void lastIndexOf_QString_QStringRef() { lastIndexOf_impl<QString, QStringRef>(); } void lastIndexOf_QString_QStringRef() { lastIndexOf_impl<QString, QStringRef>(); }
void lastIndexOf_QString_QStringView_data() { lastIndexOf_data(); } void lastIndexOf_QString_QStringView_data() { lastIndexOf_data(); }
void lastIndexOf_QString_QStringView() { lastIndexOf_impl<QString, QStringView>(); } void lastIndexOf_QString_QStringView() { lastIndexOf_impl<QString, QStringView>(); }
void lastIndexOf_QString_QChar_data() { lastIndexOf_data(false); }
void lastIndexOf_QString_QChar() { lastIndexOf_impl<QString, QChar>(); }
void lastIndexOf_QString_char16_t_data() { lastIndexOf_data(false); }
void lastIndexOf_QString_char16_t() { lastIndexOf_impl<QString, char16_t>(); }
void lastIndexOf_QLatin1String_QString_data() { lastIndexOf_data(); } void lastIndexOf_QLatin1String_QString_data() { lastIndexOf_data(); }
void lastIndexOf_QLatin1String_QString() { lastIndexOf_impl<QLatin1String, QString>(); } void lastIndexOf_QLatin1String_QString() { lastIndexOf_impl<QLatin1String, QString>(); }
@ -668,6 +775,10 @@ private Q_SLOTS:
void lastIndexOf_QLatin1String_QStringRef() { lastIndexOf_impl<QLatin1String, QStringRef>(); } void lastIndexOf_QLatin1String_QStringRef() { lastIndexOf_impl<QLatin1String, QStringRef>(); }
void lastIndexOf_QLatin1String_QStringView_data() { lastIndexOf_data(); } void lastIndexOf_QLatin1String_QStringView_data() { lastIndexOf_data(); }
void lastIndexOf_QLatin1String_QStringView() { lastIndexOf_impl<QLatin1String, QStringView>(); } void lastIndexOf_QLatin1String_QStringView() { lastIndexOf_impl<QLatin1String, QStringView>(); }
void lastIndexOf_QLatin1String_QChar_data() { lastIndexOf_data(false); }
void lastIndexOf_QLatin1String_QChar() { lastIndexOf_impl<QLatin1String, QChar>(); }
void lastIndexOf_QLatin1String_char16_t_data() { lastIndexOf_data(false); }
void lastIndexOf_QLatin1String_char16_t() { lastIndexOf_impl<QLatin1String, char16_t>(); }
void lastIndexOf_QStringRef_QString_data() { lastIndexOf_data(); } void lastIndexOf_QStringRef_QString_data() { lastIndexOf_data(); }
void lastIndexOf_QStringRef_QString() { lastIndexOf_impl<QStringRef, QString>(); } void lastIndexOf_QStringRef_QString() { lastIndexOf_impl<QStringRef, QString>(); }
@ -677,6 +788,10 @@ private Q_SLOTS:
void lastIndexOf_QStringRef_QStringRef() { lastIndexOf_impl<QStringRef, QStringRef>(); } void lastIndexOf_QStringRef_QStringRef() { lastIndexOf_impl<QStringRef, QStringRef>(); }
void lastIndexOf_QStringRef_QStringView_data() { lastIndexOf_data(); } void lastIndexOf_QStringRef_QStringView_data() { lastIndexOf_data(); }
void lastIndexOf_QStringRef_QStringView() { lastIndexOf_impl<QStringRef, QStringView>(); } void lastIndexOf_QStringRef_QStringView() { lastIndexOf_impl<QStringRef, QStringView>(); }
void lastIndexOf_QStringRef_QChar_data() { lastIndexOf_data(false); }
void lastIndexOf_QStringRef_QChar() { lastIndexOf_impl<QStringRef, QChar>(); }
void lastIndexOf_QStringRef_char16_t_data() { lastIndexOf_data(false); }
void lastIndexOf_QStringRef_char16_t() { lastIndexOf_impl<QStringRef, char16_t>(); }
void lastIndexOf_QStringView_QString_data() { lastIndexOf_data(); } void lastIndexOf_QStringView_QString_data() { lastIndexOf_data(); }
void lastIndexOf_QStringView_QString() { lastIndexOf_impl<QStringView, QString>(); } void lastIndexOf_QStringView_QString() { lastIndexOf_impl<QStringView, QString>(); }
@ -686,6 +801,10 @@ private Q_SLOTS:
void lastIndexOf_QStringView_QStringRef() { lastIndexOf_impl<QStringView, QStringRef>(); } void lastIndexOf_QStringView_QStringRef() { lastIndexOf_impl<QStringView, QStringRef>(); }
void lastIndexOf_QStringView_QStringView_data() { lastIndexOf_data(); } void lastIndexOf_QStringView_QStringView_data() { lastIndexOf_data(); }
void lastIndexOf_QStringView_QStringView() { lastIndexOf_impl<QStringView, QStringView>(); } void lastIndexOf_QStringView_QStringView() { lastIndexOf_impl<QStringView, QStringView>(); }
void lastIndexOf_QStringView_QChar_data() { lastIndexOf_data(false); }
void lastIndexOf_QStringView_QChar() { lastIndexOf_impl<QStringView, QChar>(); }
void lastIndexOf_QStringView_char16_t_data() { lastIndexOf_data(false); }
void lastIndexOf_QStringView_char16_t() { lastIndexOf_impl<QStringView, char16_t>(); }
}; };
void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty) void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
@ -725,6 +844,8 @@ void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
ROW("0", ""); ROW("0", "");
ROW("0", "1"); ROW("0", "1");
ROW("0", "0"); ROW("0", "0");
ROW("10", "0");
ROW("01", "1");
ROW("\xE4", "\xE4"); // ä <> ä ROW("\xE4", "\xE4"); // ä <> ä
ROW("\xE4", "\xC4"); // ä <> Ä ROW("\xE4", "\xC4"); // ä <> Ä
#undef ROW #undef ROW
@ -741,6 +862,7 @@ template <typename String> String detached(String s)
template <class Str> Str make(const QStringRef &sf, QLatin1String l1, const QByteArray &u8); template <class Str> Str make(const QStringRef &sf, QLatin1String l1, const QByteArray &u8);
template <> QChar make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.isEmpty() ? QChar() : sf.at(0); } template <> QChar make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.isEmpty() ? QChar() : sf.at(0); }
template <> char16_t make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.isEmpty() ? char16_t() : char16_t{sf.at(0).unicode()}; }
template <> QStringRef make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf; } template <> QStringRef make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf; }
template <> QString make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.toString(); } template <> QString make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.toString(); }
template <> QStringView make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf; } template <> QStringView make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf; }
@ -783,15 +905,6 @@ void tst_QStringApiSymmetry::compare_impl() const
const auto lhs = make<LHS>(lhsUnicode, lhsLatin1, lhsU8); const auto lhs = make<LHS>(lhsUnicode, lhsLatin1, lhsU8);
const auto rhs = make<RHS>(rhsUnicode, rhsLatin1, rhsU8); const auto rhs = make<RHS>(rhsUnicode, rhsLatin1, rhsU8);
#ifdef Q_COMPILER_NOEXCEPT
# define QVERIFY_NOEXCEPT(expr) do { \
if (has_nothrow_compare<LHS, RHS>::value) {} else \
QEXPECT_FAIL("", "Qt is missing a nothrow utf8-utf16 comparator", Continue); \
QVERIFY(noexcept(expr)); } while (0)
#else
# define QVERIFY_NOEXCEPT(expr)
#endif
#define CHECK(op) \ #define CHECK(op) \
QVERIFY_NOEXCEPT(lhs op rhs); \ QVERIFY_NOEXCEPT(lhs op rhs); \
do { if (caseSensitiveCompareResult op 0) { \ do { if (caseSensitiveCompareResult op 0) { \
@ -825,15 +938,6 @@ void tst_QStringApiSymmetry::member_compare_impl() const
const auto lhs = make<LHS>(lhsUnicode, lhsLatin1, lhsU8); const auto lhs = make<LHS>(lhsUnicode, lhsLatin1, lhsU8);
const auto rhs = make<RHS>(rhsUnicode, rhsLatin1, rhsU8); const auto rhs = make<RHS>(rhsUnicode, rhsLatin1, rhsU8);
#define QVERIFY_NOEXCEPT(expr) do { \
if (has_nothrow_compare<LHS, RHS>::value) {} else \
QEXPECT_FAIL("", "Qt is missing a nothrow utf8-utf16 comparator", Continue); \
QVERIFY(noexcept(expr)); } while (0)
if (std::is_same<LHS, QByteArray>::value || // needs to simply be marked as noexcept
((std::is_same<LHS, QString>::value || std::is_same<LHS, QStringRef>::value)
&& std::is_same<RHS, QChar>::value)) // implict QChar -> QString conversion kills noexcept
QEXPECT_FAIL("", "known issues, will be fixed before 5.14 release", Continue);
QVERIFY_NOEXCEPT(lhs.compare(rhs, Qt::CaseSensitive)); QVERIFY_NOEXCEPT(lhs.compare(rhs, Qt::CaseSensitive));
QCOMPARE(sign(lhs.compare(rhs)), caseSensitiveCompareResult); QCOMPARE(sign(lhs.compare(rhs)), caseSensitiveCompareResult);
@ -1646,7 +1750,7 @@ void tst_QStringApiSymmetry::toUcs4_impl()
QCOMPARE(unicode.isEmpty(), ucs4.isEmpty()); QCOMPARE(unicode.isEmpty(), ucs4.isEmpty());
} }
void tst_QStringApiSymmetry::indexOf_data() void tst_QStringApiSymmetry::indexOf_data(bool rhsHasVariableLength)
{ {
QTest::addColumn<QString>("haystackU16"); QTest::addColumn<QString>("haystackU16");
QTest::addColumn<QLatin1String>("haystackL1"); QTest::addColumn<QLatin1String>("haystackL1");
@ -1659,18 +1763,20 @@ void tst_QStringApiSymmetry::indexOf_data()
constexpr qsizetype zeroPos = 0; constexpr qsizetype zeroPos = 0;
constexpr qsizetype minus1Pos = -1; constexpr qsizetype minus1Pos = -1;
QTest::addRow("haystack: null, needle: null") << null << QLatin1String() if (rhsHasVariableLength) {
QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
<< null << QLatin1String() << zeroPos << zeroPos << zeroPos; << null << QLatin1String() << zeroPos << zeroPos << zeroPos;
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
<< null << QLatin1String() << zeroPos << zeroPos << zeroPos; << null << QLatin1String() << zeroPos << zeroPos << zeroPos;
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
<< null << QLatin1String() << zeroPos << zeroPos << zeroPos; << null << QLatin1String() << zeroPos << zeroPos << zeroPos;
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
<< empty << QLatin1String("") << zeroPos << zeroPos << zeroPos; << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
<< empty << QLatin1String("") << zeroPos << zeroPos << zeroPos; << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
<< empty << QLatin1String("") << zeroPos << zeroPos << zeroPos; << empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
}
QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("") QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
<< a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos; << a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos;
QTest::addRow("haystack: null, needle: a") << null << QLatin1String() QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
@ -1702,17 +1808,19 @@ void tst_QStringApiSymmetry::indexOf_data()
ROW(ABC, b, 1, -1, 1); ROW(ABC, b, 1, -1, 1);
ROW(ABC, B, 2, -1, -1); ROW(ABC, B, 2, -1, -1);
ROW(aBc, bc, 0, -1, 1); if (rhsHasVariableLength) {
ROW(aBc, Bc, 0, 1, 1); ROW(aBc, bc, 0, -1, 1);
ROW(aBc, bC, 0, -1, 1); ROW(aBc, Bc, 0, 1, 1);
ROW(aBc, BC, 0, -1, 1); ROW(aBc, bC, 0, -1, 1);
ROW(aBc, BC, 0, -1, 1);
ROW(AbC, bc, 0, -1, 1); ROW(AbC, bc, 0, -1, 1);
ROW(AbC, Bc, 0, -1, 1); ROW(AbC, Bc, 0, -1, 1);
ROW(AbC, bC, 0, 1, 1); ROW(AbC, bC, 0, 1, 1);
ROW(AbC, BC, 0, -1, 1); ROW(AbC, BC, 0, -1, 1);
ROW(AbC, BC, 1, -1, 1); ROW(AbC, BC, 1, -1, 1);
ROW(AbC, BC, 2, -1, -1); ROW(AbC, BC, 2, -1, -1);
}
#undef ROW #undef ROW
} }
@ -1739,13 +1847,6 @@ void tst_QStringApiSymmetry::indexOf_impl() const
QCOMPARE(haystack.indexOf(needle, startpos), size_type(resultCS)); QCOMPARE(haystack.indexOf(needle, startpos), size_type(resultCS));
QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS)); QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS));
QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS)); QCOMPARE(haystack.indexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS));
if (needle.size() == 1)
{
QCOMPARE(haystack.indexOf(needle[0], startpos), size_type(resultCS));
QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS));
QCOMPARE(haystack.indexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS));
}
} }
static QString ABCDEFGHIEfGEFG = QStringLiteral("ABCDEFGHIEfGEFG"); static QString ABCDEFGHIEfGEFG = QStringLiteral("ABCDEFGHIEfGEFG");
@ -1755,7 +1856,7 @@ static QString asd = QStringLiteral("asd");
static QString asdf = QStringLiteral("asdf"); static QString asdf = QStringLiteral("asdf");
static QString Z = QStringLiteral("Z"); static QString Z = QStringLiteral("Z");
void tst_QStringApiSymmetry::contains_data() void tst_QStringApiSymmetry::contains_data(bool rhsHasVariableLength)
{ {
QTest::addColumn<QString>("haystackU16"); QTest::addColumn<QString>("haystackU16");
QTest::addColumn<QLatin1String>("haystackL1"); QTest::addColumn<QLatin1String>("haystackL1");
@ -1764,18 +1865,20 @@ void tst_QStringApiSymmetry::contains_data()
QTest::addColumn<bool>("resultCS"); QTest::addColumn<bool>("resultCS");
QTest::addColumn<bool>("resultCIS"); QTest::addColumn<bool>("resultCIS");
QTest::addRow("haystack: null, needle: null") << null << QLatin1String() if (rhsHasVariableLength) {
QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
<< null << QLatin1String() << true << true; << null << QLatin1String() << true << true;
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
<< null << QLatin1String() << true << true; << null << QLatin1String() << true << true;
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
<< null << QLatin1String() << true << true; << null << QLatin1String() << true << true;
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
<< empty << QLatin1String("") << true << true; << empty << QLatin1String("") << true << true;
QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
<< empty << QLatin1String("") << true << true;; << empty << QLatin1String("") << true << true;;
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
<< empty << QLatin1String("") << true << true; << empty << QLatin1String("") << true << true;
}
QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("") QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
<< a << QLatin1String("a") << false << false; << a << QLatin1String("a") << false << false;
QTest::addRow("haystack: null, needle: a") << null << QLatin1String() QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
@ -1789,8 +1892,10 @@ void tst_QStringApiSymmetry::contains_data()
ROW(ABCDEFGHIEfGEFG, A, true, true); ROW(ABCDEFGHIEfGEFG, A, true, true);
ROW(ABCDEFGHIEfGEFG, a, false, true); ROW(ABCDEFGHIEfGEFG, a, false, true);
ROW(ABCDEFGHIEfGEFG, Z, false, false); ROW(ABCDEFGHIEfGEFG, Z, false, false);
ROW(ABCDEFGHIEfGEFG, EFG, true, true); if (rhsHasVariableLength) {
ROW(ABCDEFGHIEfGEFG, efg, false, true); ROW(ABCDEFGHIEfGEFG, EFG, true, true);
ROW(ABCDEFGHIEfGEFG, efg, false, true);
}
ROW(ABCDEFGHIEfGEFG, E, true, true); ROW(ABCDEFGHIEfGEFG, E, true, true);
ROW(ABCDEFGHIEfGEFG, e, false, true); ROW(ABCDEFGHIEfGEFG, e, false, true);
#undef ROW #undef ROW
@ -1815,16 +1920,9 @@ void tst_QStringApiSymmetry::contains_impl() const
QCOMPARE(haystack.contains(needle), resultCS); QCOMPARE(haystack.contains(needle), resultCS);
QCOMPARE(haystack.contains(needle, Qt::CaseSensitive), resultCS); QCOMPARE(haystack.contains(needle, Qt::CaseSensitive), resultCS);
QCOMPARE(haystack.contains(needle, Qt::CaseInsensitive), resultCIS); QCOMPARE(haystack.contains(needle, Qt::CaseInsensitive), resultCIS);
if (needle.size() == 1)
{
QCOMPARE(haystack.contains(needle[0]), resultCS);
QCOMPARE(haystack.contains(needle[0], Qt::CaseSensitive), resultCS);
QCOMPARE(haystack.contains(needle[0], Qt::CaseInsensitive), resultCIS);
}
} }
void tst_QStringApiSymmetry::lastIndexOf_data() void tst_QStringApiSymmetry::lastIndexOf_data(bool rhsHasVariableLength)
{ {
QTest::addColumn<QString>("haystackU16"); QTest::addColumn<QString>("haystackU16");
QTest::addColumn<QLatin1String>("haystackL1"); QTest::addColumn<QLatin1String>("haystackL1");
@ -1837,38 +1935,43 @@ void tst_QStringApiSymmetry::lastIndexOf_data()
constexpr qsizetype zeroPos = 0; constexpr qsizetype zeroPos = 0;
constexpr qsizetype minus1Pos = -1; constexpr qsizetype minus1Pos = -1;
QTest::addRow("haystack: null, needle: null") << null << QLatin1String() if (rhsHasVariableLength) {
QTest::addRow("haystack: null, needle: null") << null << QLatin1String()
<< null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos; << null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos;
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("") QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
<< null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos; << null << QLatin1String() << minus1Pos << minus1Pos << minus1Pos;
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
<< null << QLatin1String() << minus1Pos << zeroPos << zeroPos; << null << QLatin1String() << minus1Pos << zeroPos << zeroPos;
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String() QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
<< empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos; << empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos;
QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
<< empty << QLatin1String("") << minus1Pos << zeroPos << zeroPos; << empty << QLatin1String("") << minus1Pos << zeroPos << zeroPos;
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("") QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
<< empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos; << empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos;
}
QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("") QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
<< a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos; << a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos;
QTest::addRow("haystack: null, needle: a") << null << QLatin1String() QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
<< a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos; << a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos;
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") if (rhsHasVariableLength) {
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
<< null << QLatin1String() << qsizetype(1) << qsizetype(1) << qsizetype(1); << null << QLatin1String() << qsizetype(1) << qsizetype(1) << qsizetype(1);
QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
<< empty << QLatin1String("") << qsizetype(1) << qsizetype(1) << qsizetype(1); << empty << QLatin1String("") << qsizetype(1) << qsizetype(1) << qsizetype(1);
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a") QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
<< null << QLatin1String() << qsizetype(2) << minus1Pos << minus1Pos; << null << QLatin1String() << qsizetype(2) << minus1Pos << minus1Pos;
QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a") QTest::addRow("haystack: a, needle: empty") << a << QLatin1String("a")
<< empty << QLatin1String("") << qsizetype(2) << minus1Pos << minus1Pos; << empty << QLatin1String("") << qsizetype(2) << minus1Pos << minus1Pos;
}
#define ROW(h, n, st, cs, cis) \ #define ROW(h, n, st, cs, cis) \
QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \ QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \
<< n << QLatin1String(#n) \ << n << QLatin1String(#n) \
<< qsizetype(st) << qsizetype(cs) << qsizetype(cis) << qsizetype(st) << qsizetype(cs) << qsizetype(cis)
ROW(asd, asdf, -1, -1, -1); if (rhsHasVariableLength)
ROW(asd, asdf, -1, -1, -1);
ROW(ABCDEFGHIEfGEFG, G, -1, 14, 14); ROW(ABCDEFGHIEfGEFG, G, -1, 14, 14);
ROW(ABCDEFGHIEfGEFG, g, -1, -1, 14); ROW(ABCDEFGHIEfGEFG, g, -1, -1, 14);
@ -1895,13 +1998,15 @@ void tst_QStringApiSymmetry::lastIndexOf_data()
ROW(ABCDEFGHIEfGEFG, A, -15, 0, 0); ROW(ABCDEFGHIEfGEFG, A, -15, 0, 0);
ROW(ABCDEFGHIEfGEFG, a, -15, -1, 0); ROW(ABCDEFGHIEfGEFG, a, -15, -1, 0);
ROW(ABCDEFGHIEfGEFG, efg, 0, -1, -1); if (rhsHasVariableLength) {
ROW(ABCDEFGHIEfGEFG, efg, 15, -1, -1); ROW(ABCDEFGHIEfGEFG, efg, 0, -1, -1);
ROW(ABCDEFGHIEfGEFG, efg, -15, -1, -1); ROW(ABCDEFGHIEfGEFG, efg, 15, -1, -1);
ROW(ABCDEFGHIEfGEFG, efg, 14, -1, 12); ROW(ABCDEFGHIEfGEFG, efg, -15, -1, -1);
ROW(ABCDEFGHIEfGEFG, efg, 12, -1, 12); ROW(ABCDEFGHIEfGEFG, efg, 14, -1, 12);
ROW(ABCDEFGHIEfGEFG, efg, -12, -1, -1); ROW(ABCDEFGHIEfGEFG, efg, 12, -1, 12);
ROW(ABCDEFGHIEfGEFG, efg, 11, -1, 9); ROW(ABCDEFGHIEfGEFG, efg, -12, -1, -1);
ROW(ABCDEFGHIEfGEFG, efg, 11, -1, 9);
}
#undef ROW #undef ROW
} }
@ -1928,12 +2033,6 @@ void tst_QStringApiSymmetry::lastIndexOf_impl() const
QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS)); QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseSensitive), size_type(resultCS));
QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS)); QCOMPARE(haystack.lastIndexOf(needle, startpos, Qt::CaseInsensitive), size_type(resultCIS));
if (needle.size() == 1)
{
QCOMPARE(haystack.lastIndexOf(needle[0], startpos), size_type(resultCS));
QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseSensitive), size_type(resultCS));
QCOMPARE(haystack.lastIndexOf(needle[0], startpos, Qt::CaseInsensitive), size_type(resultCIS));
}
} }
QTEST_APPLESS_MAIN(tst_QStringApiSymmetry) QTEST_APPLESS_MAIN(tst_QStringApiSymmetry)

File diff suppressed because it is too large Load Diff

View File

@ -46,6 +46,7 @@
#include <private/qdrawhelper_p.h> #include <private/qdrawhelper_p.h>
#include <qpainter.h> #include <qpainter.h>
#include <qpainterpath.h>
#include <qqueue.h> #include <qqueue.h>
#include <qscreen.h> #include <qscreen.h>

View File

@ -32,6 +32,7 @@
#include <qbitmap.h> #include <qbitmap.h>
#include <qpainter.h> #include <qpainter.h>
#include <qpainterpath.h>
#include <qpolygon.h> #include <qpolygon.h>
class tst_QRegion : public QObject class tst_QRegion : public QObject

View File

@ -28,11 +28,11 @@
#include <QtTest/QtTest> #include <QtTest/QtTest>
#include "qtransform.h" #include <qpainterpath.h>
#include <qpolygon.h> #include <qpolygon.h>
#include <qtransform.h>
#include <qdebug.h> #include <qdebug.h>
class tst_QTransform : public QObject class tst_QTransform : public QObject
{ {
Q_OBJECT Q_OBJECT

View File

@ -36,6 +36,7 @@
#include <QtGui/QOpenGLFunctions> #include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLFunctions_4_2_Core> #include <QtGui/QOpenGLFunctions_4_2_Core>
#include <QtGui/QPainter> #include <QtGui/QPainter>
#include <QtGui/QPainterPath>
#include <QtGui/QScreen> #include <QtGui/QScreen>
#include <QtGui/QWindow> #include <QtGui/QWindow>
#include <QtGui/QOffscreenSurface> #include <QtGui/QOffscreenSurface>

View File

@ -44,5 +44,6 @@ qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simple.vert.qsb simple.vert
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simple.frag.qsb simple.frag qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simple.frag.qsb simple.frag
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simpletextured.vert.qsb simpletextured.vert qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simpletextured.vert.qsb simpletextured.vert
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simpletextured.frag.qsb simpletextured.frag qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o simpletextured.frag.qsb simpletextured.frag
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 20 -o simpletextured_array.frag.qsb simpletextured_array.frag
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured.vert.qsb textured.vert qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured.vert.qsb textured.vert
qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured.frag.qsb textured.frag qsb --glsl "150,120,100 es" --hlsl 50 -c --msl 12 -o textured.frag.qsb textured.frag

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