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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -437,6 +437,9 @@
\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
identify the associated location and a public \c adjust() function
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
public:
enum { Type = UserType + 1 };
ImageItem(int id, const QPixmap &pixmap, QGraphicsItem *parent = nullptr);
int type() const override { return Type; }
void adjust();
int id() const;

View File

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

View File

@ -52,6 +52,7 @@
#include <QComboBox>
#include <QPainter>
#include <QPainterPath>
#include <QPushButton>
#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
ANDROID_MIN_SDK_VERSION = $$replace(ANDROID_PLATFORM, "android-", "")
ANDROID_TARGET_SDK_VERSION = 28
NDK_LLVM_PATH = $$NDK_ROOT/toolchains/llvm/prebuilt/$$NDK_HOST
QMAKE_CC = $$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): \
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): \
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 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.
\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
These options define specific features on Windows only:
@ -2579,6 +2588,32 @@
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
Specifies the \l{All Modules}{Qt modules} that are used by your project. For

View File

@ -1,5 +1,5 @@
distributionBase=GRADLE_USER_HOME
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
zipStorePath=wrapper/dists

View File

@ -1,7 +1,5 @@
<?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">
<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.
Remove the comment if you do not require these default permissions. -->
<!-- %%INSERT_PERMISSIONS -->

View File

@ -5,7 +5,7 @@ buildscript {
}
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 {
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})
endif()
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
# 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_list(ANDROID_EXTRA_LIBS "android-extra-libs")
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(
"${CMAKE_BINARY_DIR}/android_deployment_settings.json.in"

View File

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

View File

@ -179,6 +179,17 @@
rcc -compress 2 -compress-algo zlib myresources.qrc
\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
levels:
@ -196,10 +207,10 @@
library to choose an implementation-defined default.
\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
compression (least CPU time) and 9 the most compression (most CPU time).
The special value 0 means "no compression" and should not be used. The
default is implementation-defined, but usually is level 6.
contents. Valid compression levels range from 1 to 9, with 1 applying
the least compression (least CPU time) and 9 the most compression (most
CPU time). The special value 0 means "no compression" and should not be
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}
option.

View File

@ -45,18 +45,20 @@
QT_BEGIN_NAMESPACE
/*!
\headerfile <QFloat16>
\title 16-bit Floating Point Support
\class qfloat16
\keyword 16-bit Floating Point Support
\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
point data with the class \c qfloat16. It is fully compliant with IEEE
754 as a storage type. This implies that any arithmetic operation on a
\c qfloat16 instance results in the value first being converted to a
\c float. This conversion to and from \c float is performed by hardware
when possible, but on processors that do not natively support half-precision,
the conversion is performed through a sequence of lookup table operations.
The \c qfloat16 class provides support for half-precision (16-bit) floating
point data. It is fully compliant with IEEE 754 as a storage type. This
implies that any arithmetic operation on a \c qfloat16 instance results in
the value first being converted to a \c float. This conversion to and from
\c float is performed by hardware when possible, but on processors that do
not natively support half-precision, the conversion is performed through a
sequence of lookup table operations.
\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
@ -68,7 +70,7 @@ QT_BEGIN_NAMESPACE
/*!
\macro QT_NO_FLOAT16_OPERATORS
\relates <QFloat16>
\relates qfloat16
\since 5.12.4
Defining this macro disables the arithmetic operators for qfloat16.
@ -81,7 +83,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn bool qIsInf(qfloat16 f)
\relates <QFloat16>
\relates qfloat16
Returns true if the \c qfloat16 \a {f} is equivalent to infinity.
@ -90,7 +92,7 @@ QT_BEGIN_NAMESPACE
/*!
\fn bool qIsNaN(qfloat16 f)
\relates <QFloat16>
\relates qfloat16
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)
\relates <QFloat16>
\relates qfloat16
Returns true if the \c qfloat16 \a {f} is a finite number.
@ -130,7 +132,7 @@ QT_BEGIN_NAMESPACE
\since 5.14
\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()
*/
@ -167,7 +169,7 @@ int qfloat16::fpClassify() const noexcept
}
/*! \fn int qRound(qfloat16 value)
\relates <QFloat16>
\relates qfloat16
Rounds \a value to the nearest integer.
@ -175,7 +177,7 @@ int qfloat16::fpClassify() const noexcept
*/
/*! \fn qint64 qRound64(qfloat16 value)
\relates <QFloat16>
\relates qfloat16
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)
\relates <QFloat16>
\relates qfloat16
Compares the floating point value \a p1 and \a p2 and
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
/*!
\since 5.11
\relates <QFloat16>
\relates qfloat16
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.
@ -272,7 +274,7 @@ Q_CORE_EXPORT void qFloatToFloat16(qfloat16 *out, const float *in, qsizetype len
/*!
\since 5.11
\relates <QFloat16>
\relates qfloat16
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.

View File

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

View File

@ -67,8 +67,8 @@ class Q_AUTOTEST_EXPORT QLoggingRule
{
public:
QLoggingRule();
QLoggingRule(const QStringRef &pattern, bool enabled);
int pass(const QString &categoryName, QtMsgType type) const;
QLoggingRule(QStringView pattern, bool enabled);
int pass(QLatin1String categoryName, QtMsgType type) const;
enum PatternFlag {
FullText = 0x1,
@ -84,7 +84,7 @@ public:
bool enabled;
private:
void parse(const QStringRef &pattern);
void parse(QStringView pattern);
};
Q_DECLARE_OPERATORS_FOR_FLAGS(QLoggingRule::PatternFlags)
@ -101,7 +101,7 @@ public:
QVector<QLoggingRule> rules() const { return _rules; }
private:
void parseNextLine(QStringRef line);
void parseNextLine(QStringView line);
private:
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)
{
QProcess process;
process.setProcessChannelMode(ForwardedChannels);
process.start(command);
if (!process.waitForFinished(-1) || process.error() == FailedToStart)
QStringList args = splitCommand(command);
if (args.isEmpty())
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
it is called. The result is not cached between calls.
\sa uncompressedData(), size(), isCompressed(), isFile()
\sa uncompressedSize(), size(), isCompressed(), isFile()
*/
QByteArray QResource::uncompressedData() const

View File

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

View File

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

View File

@ -219,8 +219,8 @@ public:
int count(const char *a) const;
int count(const QByteArray &a) const;
inline int compare(const char *c, Qt::CaseSensitivity cs = Qt::CaseSensitive) const;
inline int compare(const QByteArray &a, 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 noexcept;
Q_REQUIRED_RESULT QByteArray left(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; }
inline bool QByteArray::contains(char c) const
{ 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) :
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) :
qstrnicmp(data(), size(), a.data(), a.size());

View File

@ -6154,6 +6154,16 @@ QString& QString::fill(QChar ch, int size)
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
/*!
\overload compare()
@ -9575,6 +9585,23 @@ QString &QString::setRawData(const QChar *unicode, int size)
\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
\since 5.10
@ -10941,6 +10968,19 @@ QStringRef QStringRef::appendTo(QString *string) const
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
\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 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
{ return QtPrivate::startsWith(*this, s, cs); }
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:
//
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
{ return QtPrivate::startsWith(*this, s, cs); }
bool QStringView::endsWith(QLatin1String s, Qt::CaseSensitivity cs) const noexcept
@ -729,6 +740,8 @@ public:
#endif
int compare(QLatin1String other, 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,
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 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;
#if !defined(QT_NO_CAST_FROM_ASCII) && !defined(QT_RESTRICTED_CAST_FROM_ASCII)
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
Compares this string-view with the \a other string-view and returns an
integer less than, equal to, or greater than zero if this string-view
is less than, equal to, or greater than the other string-view.
Returns an integer that compares to zero as this string-view compares to the
string-view \a str.
If \a cs is Qt::CaseSensitive, the comparison is case sensitive;
otherwise the comparison is case insensitive.
If \a cs is Qt::CaseSensitive (the default), the comparison is case sensitive;
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>()
*/

View File

@ -257,6 +257,11 @@ public:
Q_REQUIRED_RESULT int compare(QStringView other, Qt::CaseSensitivity cs = Qt::CaseSensitive) const noexcept
{ 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
{ return QtPrivate::startsWith(*this, s, cs); }

View File

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

View File

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

View File

@ -43,7 +43,12 @@
#include <private/qendian_p.h>
#include <private/qsimd_p.h>
#include <private/qimage_p.h>
#include <qendian.h>
#if QT_CONFIG(thread)
#include <qsemaphore.h>
#include <qthreadpool.h>
#endif
QT_BEGIN_NAMESPACE
@ -159,12 +164,8 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
// Cannot be used with indexed formats.
Q_ASSERT(dest->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 *destLayout = &qPixelLayouts[dest->format];
const uchar *srcData = src->data;
uchar *destData = dest->data;
FetchAndConvertPixelsFunc fetch = srcLayout->fetchToARGB32PM;
ConvertAndStorePixelsFunc store = destLayout->storeFromARGB32PM;
@ -197,59 +198,110 @@ void convert_generic(QImageData *dest, const QImageData *src, Qt::ImageConversio
else
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) {
dither.y = y;
int x = 0;
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, nullptr, ditherPtr);
store(destData, ptr, x, l, nullptr, ditherPtr);
x += l;
auto convertSegment = [=](int yStart, int yEnd) {
uint buf[BufferSize];
uint *buffer = buf;
const uchar *srcData = src->data + src->bytes_per_line * yStart;
uchar *destData = dest->data + dest->bytes_per_line * yStart;
QDitherInfo dither;
QDitherInfo *ditherPtr = nullptr;
if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
ditherPtr = &dither;
for (int y = yStart; y < yEnd; ++y) {
dither.y = y;
int x = 0;
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)
{
Q_ASSERT(dest->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 *destLayout = &qPixelLayouts[dest->format];
const uchar *srcData = src->data;
uchar *destData = dest->data;
const FetchAndConvertPixelsFunc64 fetch = srcLayout->fetchToRGBA64PM;
const ConvertAndStorePixelsFunc64 store = qStoreFromRGBA64PM[dest->format];
for (int y = 0; y < src->height; ++y) {
int x = 0;
while (x < src->width) {
int l = src->width - x;
if (destLayout->bpp == QPixelLayout::BPP64)
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;
auto convertSegment = [=](int yStart, int yEnd) {
QRgba64 buf[BufferSize];
QRgba64 *buffer = buf;
const uchar *srcData = src->data + yStart * src->bytes_per_line;
uchar *destData = dest->data + yStart * dest->bytes_per_line;
for (int y = yStart; y < yEnd; ++y) {
int x = 0;
while (x < src->width) {
int l = src->width - x;
if (destLayout->bpp == QPixelLayout::BPP64)
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)
@ -270,11 +322,6 @@ bool convert_generic_inplace(QImageData *data, QImage::Format dst_format, Qt::Im
&& qt_highColorPrecision(dst_format, !srcLayout->hasAlphaChannel))
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 };
if (data->depth != 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
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) {
dither.y = y;
int x = 0;
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;
auto convertSegment = [=](int yStart, int yEnd) {
uint buf[BufferSize];
uint *buffer = buf;
uchar *srcData = data->data + data->bytes_per_line * yStart;
uchar *destData = srcData;
QDitherInfo dither;
QDitherInfo *ditherPtr = nullptr;
if ((flags & Qt::PreferDither) && (flags & Qt::Dither_Mask) != Qt::ThresholdDither)
ditherPtr = &dither;
for (int y = yStart; y < yEnd; ++y) {
dither.y = y;
int x = 0;
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) {
Q_ASSERT(params.totalSize < data->nbytes);
void *newData = realloc(data->data, params.totalSize);

View File

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

View File

@ -41,6 +41,11 @@
#include "qimage.h"
#include <private/qsimd_p.h>
#if QT_CONFIG(thread)
#include "qsemaphore.h"
#include "qthreadpool.h"
#endif
#if defined(__ARM_NEON__)
QT_BEGIN_NAMESPACE
@ -76,33 +81,54 @@ void qt_qimageScaleAARGBA_up_x_down_y_neon(QImageScaleInfo *isi, unsigned int *d
int *yapoints = isi->yapoints;
/* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) {
int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
auto scaleSection = [&] (int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
const unsigned int *sptr = ypoints[y] + xpoints[x];
uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow);
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
const unsigned int *sptr = ypoints[y] + xpoints[x];
uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow);
int xap = xapoints[x];
if (xap > 0) {
uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow);
int xap = xapoints[x];
if (xap > 0) {
uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow);
vx = vmulq_n_u32(vx, 256 - xap);
vr = vmulq_n_u32(vr, xap);
vx = vaddq_u32(vx, vr);
vx = vshrq_n_u32(vx, 8);
vx = vmulq_n_u32(vx, 256 - xap);
vr = vmulq_n_u32(vr, xap);
vx = vaddq_u32(vx, vr);
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>
@ -115,33 +141,54 @@ void qt_qimageScaleAARGBA_down_x_up_y_neon(QImageScaleInfo *isi, unsigned int *d
int *yapoints = isi->yapoints;
/* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) {
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
auto scaleSection = [&] (int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[y] + xpoints[x];
uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
const unsigned int *sptr = ypoints[y] + xpoints[x];
uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
int yap = yapoints[y];
if (yap > 0) {
uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1);
int yap = yapoints[y];
if (yap > 0) {
uint32x4_t vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1);
vx = vmulq_n_u32(vx, 256 - yap);
vr = vmulq_n_u32(vr, yap);
vx = vaddq_u32(vx, vr);
vx = vshrq_n_u32(vx, 8);
vx = vmulq_n_u32(vx, 256 - yap);
vr = vmulq_n_u32(vr, yap);
vx = vaddq_u32(vx, vr);
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>
@ -153,43 +200,64 @@ void qt_qimageScaleAARGBA_down_xy_neon(QImageScaleInfo *isi, unsigned int *dest,
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) {
int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
auto scaleSection = [&] (int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
const int Cx = xapoints[x] >> 16;
const int xap = xapoints[x] & 0xffff;
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
const int Cx = xapoints[x] >> 16;
const int xap = xapoints[x] & 0xffff;
const unsigned int *sptr = ypoints[y] + xpoints[x];
uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
vx = vshrq_n_u32(vx, 4);
uint32x4_t vr = vmulq_n_u32(vx, yap);
const unsigned int *sptr = ypoints[y] + xpoints[x];
uint32x4_t vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
vx = vshrq_n_u32(vx, 4);
uint32x4_t vr = vmulq_n_u32(vx, yap);
int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
int j;
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;
vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1);
vx = vshrq_n_u32(vx, 4);
vx = vmulq_n_u32(vx, Cy);
vx = vmulq_n_u32(vx, j);
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);
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(vr, 24);
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 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 *yapoints{nullptr};
int xup_yup{0};
int sh = 0;
int sw = 0;
};
}

View File

@ -42,6 +42,11 @@
#include <private/qdrawhelper_x86_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)
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)
{
const unsigned int **ypoints = isi->ypoints;
int *xpoints = isi->xpoints;
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
const int *xpoints = isi->xpoints;
const int *xapoints = isi->xapoints;
const int *yapoints = isi->yapoints;
const __m128i v256 = _mm_set1_epi32(256);
/* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) {
int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
const __m128i vCy = _mm_set1_epi32(Cy);
const __m128i vyap = _mm_set1_epi32(yap);
auto scaleSection = [&] (int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
const int Cy = yapoints[y] >> 16;
const int yap = yapoints[y] & 0xffff;
const __m128i vCy = _mm_set1_epi32(Cy);
const __m128i vyap = _mm_set1_epi32(yap);
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
const unsigned int *sptr = ypoints[y] + xpoints[x];
__m128i vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, vyap, vCy);
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
const unsigned int *sptr = ypoints[y] + xpoints[x];
__m128i vx = qt_qimageScaleAARGBA_helper(sptr, yap, Cy, sow, vyap, vCy);
int xap = xapoints[x];
if (xap > 0) {
const __m128i vxap = _mm_set1_epi32(xap);
const __m128i vinvxap = _mm_sub_epi32(v256, vxap);
__m128i vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, vyap, vCy);
const int xap = xapoints[x];
if (xap > 0) {
const __m128i vxap = _mm_set1_epi32(xap);
const __m128i vinvxap = _mm_sub_epi32(v256, vxap);
__m128i vr = qt_qimageScaleAARGBA_helper(sptr + 1, yap, Cy, sow, vyap, vCy);
vx = _mm_mullo_epi32(vx, vinvxap);
vr = _mm_mullo_epi32(vr, vxap);
vx = _mm_add_epi32(vx, vr);
vx = _mm_srli_epi32(vx, 8);
vx = _mm_mullo_epi32(vx, vinvxap);
vr = _mm_mullo_epi32(vr, vxap);
vx = _mm_add_epi32(vx, vr);
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>
@ -122,37 +148,58 @@ void qt_qimageScaleAARGBA_down_x_up_y_sse4(QImageScaleInfo *isi, unsigned int *d
const __m128i v256 = _mm_set1_epi32(256);
/* go through every scanline in the output buffer */
for (int y = 0; y < dh; y++) {
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const __m128i vCx = _mm_set1_epi32(Cx);
const __m128i vxap = _mm_set1_epi32(xap);
auto scaleSection = [&] (int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
int Cx = xapoints[x] >> 16;
int xap = xapoints[x] & 0xffff;
const __m128i vCx = _mm_set1_epi32(Cx);
const __m128i vxap = _mm_set1_epi32(xap);
const unsigned int *sptr = ypoints[y] + xpoints[x];
__m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
const unsigned int *sptr = ypoints[y] + xpoints[x];
__m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
int yap = yapoints[y];
if (yap > 0) {
const __m128i vyap = _mm_set1_epi32(yap);
const __m128i vinvyap = _mm_sub_epi32(v256, vyap);
__m128i vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, vxap, vCx);
int yap = yapoints[y];
if (yap > 0) {
const __m128i vyap = _mm_set1_epi32(yap);
const __m128i vinvyap = _mm_sub_epi32(v256, vyap);
__m128i vr = qt_qimageScaleAARGBA_helper(sptr + sow, xap, Cx, 1, vxap, vCx);
vx = _mm_mullo_epi32(vx, vinvyap);
vr = _mm_mullo_epi32(vr, vyap);
vx = _mm_add_epi32(vx, vr);
vx = _mm_srli_epi32(vx, 8);
vx = _mm_mullo_epi32(vx, vinvyap);
vr = _mm_mullo_epi32(vr, vyap);
vx = _mm_add_epi32(vx, vr);
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>
@ -164,42 +211,63 @@ void qt_qimageScaleAARGBA_down_xy_sse4(QImageScaleInfo *isi, unsigned int *dest,
int *xapoints = isi->xapoints;
int *yapoints = isi->yapoints;
for (int y = 0; y < dh; y++) {
int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
const __m128i vCy = _mm_set1_epi32(Cy);
const __m128i vyap = _mm_set1_epi32(yap);
auto scaleSection = [&] (int yStart, int yEnd) {
for (int y = yStart; y < yEnd; ++y) {
int Cy = yapoints[y] >> 16;
int yap = yapoints[y] & 0xffff;
const __m128i vCy = _mm_set1_epi32(Cy);
const __m128i vyap = _mm_set1_epi32(yap);
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
const int Cx = xapoints[x] >> 16;
const int xap = xapoints[x] & 0xffff;
const __m128i vCx = _mm_set1_epi32(Cx);
const __m128i vxap = _mm_set1_epi32(xap);
unsigned int *dptr = dest + (y * dow);
for (int x = 0; x < dw; x++) {
const int Cx = xapoints[x] >> 16;
const int xap = xapoints[x] & 0xffff;
const __m128i vCx = _mm_set1_epi32(Cx);
const __m128i vxap = _mm_set1_epi32(xap);
const unsigned int *sptr = ypoints[y] + xpoints[x];
__m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
__m128i vr = _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vyap);
const unsigned int *sptr = ypoints[y] + xpoints[x];
__m128i vx = qt_qimageScaleAARGBA_helper(sptr, xap, Cx, 1, vxap, vCx);
__m128i vr = _mm_mullo_epi32(_mm_srli_epi32(vx, 4), vyap);
int j;
for (j = (1 << 14) - yap; j > Cy; j -= Cy) {
int j;
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;
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;
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_add_epi32(vr, _mm_mullo_epi32(_mm_srli_epi32(vx, 4), _mm_set1_epi32(j)));
vr = _mm_srli_epi32(vr, 24);
vr = _mm_packus_epi32(vr, _mm_setzero_si128());
vr = _mm_packus_epi16(vr, _mm_setzero_si128());
*dptr = _mm_cvtsi128_si32(vr);
if (RGB)
*dptr |= 0xff000000;
dptr++;
vr = _mm_srli_epi32(vr, 24);
vr = _mm_packus_epi32(vr, _mm_setzero_si128());
vr = _mm_packus_epi16(vr, _mm_setzero_si128());
*dptr = _mm_cvtsi128_si32(vr);
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 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;
}
/*!
\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
\a matrix, and returns the list.
@ -1678,35 +1659,6 @@ QList<QPolygonF> QPainterPath::toSubpathPolygons(const QTransform &matrix) const
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
QTransform \a matrix, and returns the list.
@ -2902,28 +2854,6 @@ void QPainterPathStroker::setDashOffset(qreal 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
\a matrix, and returns the polygon.

View File

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

View File

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

View File

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

View File

@ -40,7 +40,6 @@
#define QTRANSFORM_H
#include <QtGui/qtguiglobal.h>
#include <QtGui/qpainterpath.h>
#include <QtGui/qpolygon.h>
#include <QtGui/qregion.h>
#include <QtGui/qwindowdefs.h>
@ -50,8 +49,8 @@
QT_BEGIN_NAMESPACE
class QVariant;
class QPainterPath;
class Q_GUI_EXPORT QTransform
{
@ -406,8 +405,6 @@ inline QPolygonF operator *(const QPolygonF &a, const QTransform &m)
{ return m.map(a); }
inline QRegion operator *(const QRegion &r, const QTransform &m)
{ 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)
{ 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
stages, texture, and sampler specified by \a binding, \a stage, \a tex,
\a sampler.
\note This function is equivalent to calling sampledTextures() with a
\c count of 1.
\sa sampledTextures()
*/
QRhiShaderResourceBinding QRhiShaderResourceBinding::sampledTexture(
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;
b.d.binding = binding;
b.d.stage = stage;
b.d.type = SampledTexture;
b.d.u.stex.tex = tex;
b.d.u.stex.sampler = sampler;
b.d.u.stex.count = count;
for (int i = 0; i < count; ++i)
b.d.u.stex.texSamplers[i] = texSamplers[i];
return b;
}
@ -3084,10 +3125,14 @@ bool operator==(const QRhiShaderResourceBinding &a, const QRhiShaderResourceBind
}
break;
case QRhiShaderResourceBinding::SampledTexture:
if (da->u.stex.tex != db->u.stex.tex
|| da->u.stex.sampler != db->u.stex.sampler)
{
if (da->u.stex.count != db->u.stex.count)
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;
case QRhiShaderResourceBinding::ImageLoad:
@ -3162,10 +3207,13 @@ QDebug operator<<(QDebug dbg, const QRhiShaderResourceBinding &b)
<< ')';
break;
case QRhiShaderResourceBinding::SampledTexture:
dbg.nospace() << " SampledTexture("
<< "texture=" << d->u.stex.tex
<< " sampler=" << d->u.stex.sampler
<< ')';
dbg.nospace() << " SampledTextures("
<< "count=" << d->u.stex.count;
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;
case QRhiShaderResourceBinding::ImageLoad:
dbg.nospace() << " ImageLoad("

View File

@ -348,6 +348,12 @@ public:
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 imageStore(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;
bool hasDynamicOffset;
};
static const int MAX_TEX_SAMPLER_ARRAY_SIZE = 16;
struct SampledTextureData {
QRhiTexture *tex;
QRhiSampler *sampler;
int count;
TextureAndSampler texSamplers[MAX_TEX_SAMPLER_ARRAY_SIZE];
};
struct StorageImageData {
QRhiTexture *tex;

View File

@ -113,6 +113,10 @@ QT_BEGIN_NAMESPACE
#define DXGI_ADAPTER_FLAG_SOFTWARE 2
#endif
#ifndef D3D11_1_UAV_SLOT_COUNT
#define D3D11_1_UAV_SLOT_COUNT 64
#endif
QRhiD3D11::QRhiD3D11(QRhiD3D11InitParams *params, QRhiD3D11NativeHandles *importDevice)
: ofr(this),
deviceCurse(this)
@ -627,18 +631,25 @@ void QRhiD3D11::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBind
break;
case QRhiShaderResourceBinding::SampledTexture:
{
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
if (texD->generation != bd.stex.texGeneration
|| texD->m_id != bd.stex.texId
|| samplerD->generation != bd.stex.samplerGeneration
|| samplerD->m_id != bd.stex.samplerId)
{
const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
if (bd.stex.count != data->count) {
bd.stex.count = data->count;
srbUpdate = true;
bd.stex.texId = texD->m_id;
bd.stex.texGeneration = texD->generation;
bd.stex.samplerId = samplerD->m_id;
bd.stex.samplerGeneration = samplerD->generation;
}
for (int elem = 0; elem < data->count; ++elem) {
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, data->texSamplers[elem].tex);
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;
@ -1894,31 +1905,38 @@ void QRhiD3D11::updateShaderResourceBindings(QD3D11ShaderResourceBindings *srbD,
break;
case QRhiShaderResourceBinding::SampledTexture:
{
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, b->u.stex.tex);
QD3D11Sampler *samplerD = QRHI_RES(QD3D11Sampler, b->u.stex.sampler);
bd.stex.texId = texD->m_id;
bd.stex.texGeneration = texD->generation;
bd.stex.samplerId = samplerD->m_id;
bd.stex.samplerGeneration = samplerD->generation;
if (b->stage.testFlag(QRhiShaderResourceBinding::VertexStage)) {
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
res[RBM_VERTEX].textures.append({ nativeBinding.first, texD->srv });
res[RBM_VERTEX].samplers.append({ nativeBinding.second, samplerD->samplerState });
const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
bd.stex.count = data->count;
const QPair<int, int> nativeBindingVert = mapBinding(b->binding, RBM_VERTEX, nativeResourceBindingMaps);
const QPair<int, int> nativeBindingFrag = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
const QPair<int, int> nativeBindingComp = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
// if SPIR-V binding b is mapped to tN and sN in HLSL, and it
// is an array, then it will use tN, tN+1, tN+2, ..., and sN,
// sN+1, sN+2, ...
for (int elem = 0; elem < data->count; ++elem) {
QD3D11Texture *texD = QRHI_RES(QD3D11Texture, data->texSamplers[elem].tex);
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)) {
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_FRAGMENT, nativeResourceBindingMaps);
if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
res[RBM_FRAGMENT].textures.append({ nativeBinding.first, texD->srv });
res[RBM_FRAGMENT].samplers.append({ nativeBinding.second, samplerD->samplerState });
if (b->stage.testFlag(QRhiShaderResourceBinding::FragmentStage)) {
if (nativeBindingFrag.first >= 0 && nativeBindingFrag.second >= 0) {
res[RBM_FRAGMENT].textures.append({ nativeBindingFrag.first + elem, texD->srv });
res[RBM_FRAGMENT].samplers.append({ nativeBindingFrag.second + elem, samplerD->samplerState });
}
}
}
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
QPair<int, int> nativeBinding = mapBinding(b->binding, RBM_COMPUTE, nativeResourceBindingMaps);
if (nativeBinding.first >= 0 && nativeBinding.second >= 0) {
res[RBM_COMPUTE].textures.append({ nativeBinding.first, texD->srv });
res[RBM_COMPUTE].samplers.append({ nativeBinding.second, samplerD->samplerState });
if (b->stage.testFlag(QRhiShaderResourceBinding::ComputeStage)) {
if (nativeBindingComp.first >= 0 && nativeBindingComp.second >= 0) {
res[RBM_COMPUTE].textures.append({ nativeBindingComp.first + elem, texD->srv });
res[RBM_COMPUTE].samplers.append({ nativeBindingComp.second + elem, 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,
const uint *dynOfsPairs, int dynOfsPairCount,
bool offsetOnlyChange)
{
if (!offsetOnlyChange) {
for (const auto &batch : srbD->vssamplers.batches)
context->VSSetSamplers(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
for (const auto &batch : srbD->vssamplers.batches) {
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) {
context->VSSetShaderResources(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
contextState.vsHighestActiveSrvBinding = qMax<int>(contextState.vsHighestActiveSrvBinding,
int(batch.startBinding) + batch.resources.count() - 1);
const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "VS SRV");
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)
context->PSSetSamplers(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
for (const auto &batch : srbD->fssamplers.batches) {
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) {
context->PSSetShaderResources(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
contextState.fsHighestActiveSrvBinding = qMax<int>(contextState.fsHighestActiveSrvBinding,
int(batch.startBinding) + batch.resources.count() - 1);
const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "PS SRV");
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)
context->CSSetSamplers(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
for (const auto &batch : srbD->cssamplers.batches) {
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) {
context->CSSetShaderResources(batch.startBinding, UINT(batch.resources.count()), batch.resources.constData());
contextState.csHighestActiveSrvBinding = qMax<int>(contextState.csHighestActiveSrvBinding,
int(batch.startBinding) + batch.resources.count() - 1);
const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
D3D11_COMMONSHADER_INPUT_RESOURCE_SLOT_COUNT, "CS SRV");
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) {
if (!dynOfsPairCount) {
context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
UINT(srbD->vsubufs.batches[i].resources.count()),
srbD->vsubufs.batches[i].resources.constData(),
srbD->vsubufoffsets.batches[i].resources.constData(),
srbD->vsubufsizes.batches[i].resources.constData());
} else {
QVarLengthArray<UINT, 4> offsets;
applyDynamicOffsets(&offsets, i, &srbD->vsubufs, &srbD->vsubufoffsets, dynOfsPairs, dynOfsPairCount);
context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
UINT(srbD->vsubufs.batches[i].resources.count()),
srbD->vsubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->vsubufsizes.batches[i].resources.constData());
const uint count = clampedResourceCount(srbD->vsubufs.batches[i].startBinding,
srbD->vsubufs.batches[i].resources.count(),
D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
"VS cbuf");
if (count) {
if (!dynOfsPairCount) {
context->VSSetConstantBuffers1(srbD->vsubufs.batches[i].startBinding,
count,
srbD->vsubufs.batches[i].resources.constData(),
srbD->vsubufoffsets.batches[i].resources.constData(),
srbD->vsubufsizes.batches[i].resources.constData());
} else {
QVarLengthArray<UINT, 4> offsets;
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) {
if (!dynOfsPairCount) {
context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
UINT(srbD->fsubufs.batches[i].resources.count()),
srbD->fsubufs.batches[i].resources.constData(),
srbD->fsubufoffsets.batches[i].resources.constData(),
srbD->fsubufsizes.batches[i].resources.constData());
} else {
QVarLengthArray<UINT, 4> offsets;
applyDynamicOffsets(&offsets, i, &srbD->fsubufs, &srbD->fsubufoffsets, dynOfsPairs, dynOfsPairCount);
context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
UINT(srbD->fsubufs.batches[i].resources.count()),
srbD->fsubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->fsubufsizes.batches[i].resources.constData());
const uint count = clampedResourceCount(srbD->fsubufs.batches[i].startBinding,
srbD->fsubufs.batches[i].resources.count(),
D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
"PS cbuf");
if (count) {
if (!dynOfsPairCount) {
context->PSSetConstantBuffers1(srbD->fsubufs.batches[i].startBinding,
count,
srbD->fsubufs.batches[i].resources.constData(),
srbD->fsubufoffsets.batches[i].resources.constData(),
srbD->fsubufsizes.batches[i].resources.constData());
} else {
QVarLengthArray<UINT, 4> offsets;
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) {
if (!dynOfsPairCount) {
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
UINT(srbD->csubufs.batches[i].resources.count()),
srbD->csubufs.batches[i].resources.constData(),
srbD->csubufoffsets.batches[i].resources.constData(),
srbD->csubufsizes.batches[i].resources.constData());
} else {
QVarLengthArray<UINT, 4> offsets;
applyDynamicOffsets(&offsets, i, &srbD->csubufs, &srbD->csubufoffsets, dynOfsPairs, dynOfsPairCount);
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
UINT(srbD->csubufs.batches[i].resources.count()),
srbD->csubufs.batches[i].resources.constData(),
offsets.constData(),
srbD->csubufsizes.batches[i].resources.constData());
const uint count = clampedResourceCount(srbD->csubufs.batches[i].startBinding,
srbD->csubufs.batches[i].resources.count(),
D3D11_COMMONSHADER_CONSTANT_BUFFER_API_SLOT_COUNT,
"CS cbuf");
if (count) {
if (!dynOfsPairCount) {
context->CSSetConstantBuffers1(srbD->csubufs.batches[i].startBinding,
count,
srbD->csubufs.batches[i].resources.constData(),
srbD->csubufoffsets.batches[i].resources.constData(),
srbD->csubufsizes.batches[i].resources.constData());
} else {
QVarLengthArray<UINT, 4> offsets;
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) {
const uint startBinding = srbD->csUAVs.batches[i].startBinding;
const uint count = uint(srbD->csUAVs.batches[i].resources.count());
context->CSSetUnorderedAccessViews(startBinding,
count,
srbD->csUAVs.batches[i].resources.constData(),
nullptr);
contextState.csHighestActiveUavBinding = qMax<int>(contextState.csHighestActiveUavBinding,
int(startBinding + count - 1));
for (const auto &batch : srbD->csUAVs.batches) {
const uint count = clampedResourceCount(batch.startBinding, batch.resources.count(),
D3D11_1_UAV_SLOT_COUNT, "CS UAV");
if (count) {
context->CSSetUnorderedAccessViews(batch.startBinding,
count,
batch.resources.constData(),
nullptr);
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)
{
QShaderCode dxbc = shader.shader({ QShader::DxbcShader, 50, shaderVariant });
if (!dxbc.shader().isEmpty())
QShaderKey key = { QShader::DxbcShader, 50, shaderVariant };
QShaderCode dxbc = shader.shader(key);
if (!dxbc.shader().isEmpty()) {
if (usedShaderKey)
*usedShaderKey = key;
return dxbc.shader();
}
const QShaderKey key = { QShader::HlslShader, 50, shaderVariant };
key = { QShader::HlslShader, 50, shaderVariant };
QShaderCode hlslSource = shader.shader(key);
if (hlslSource.shader().isEmpty()) {
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;
};
struct BoundSampledTextureData {
quint64 texId;
uint texGeneration;
quint64 samplerId;
uint samplerGeneration;
int count;
struct {
quint64 texId;
uint texGeneration;
quint64 samplerId;
uint samplerGeneration;
} d[QRhiShaderResourceBinding::Data::MAX_TEX_SAMPLER_ARRAY_SIZE];
};
struct BoundStorageImageData {
quint64 id;

View File

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

View File

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

View File

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

View File

@ -345,6 +345,15 @@ static bool qvk_debug_filter(VkDebugReportFlagsEXT flags, VkDebugReportObjectTyp
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;
}
@ -2487,7 +2496,8 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
QVkShaderResourceBindings *srbD = QRHI_RES(QVkShaderResourceBindings, srb);
QVarLengthArray<VkDescriptorBufferInfo, 8> bufferInfos;
QVarLengthArray<VkDescriptorImageInfo, 8> imageInfos;
using ArrayOfImageDesc = QVarLengthArray<VkDescriptorImageInfo, 8>;
QVarLengthArray<ArrayOfImageDesc, 8> imageInfos;
QVarLengthArray<VkWriteDescriptorSet, 12> writeInfos;
QVarLengthArray<QPair<int, int>, 12> infoIndices;
@ -2530,17 +2540,22 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
break;
case QRhiShaderResourceBinding::SampledTexture:
{
QVkTexture *texD = QRHI_RES(QVkTexture, b->u.stex.tex);
QVkSampler *samplerD = QRHI_RES(QVkSampler, b->u.stex.sampler);
const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
writeInfo.descriptorCount = data->count; // arrays of combined image samplers are supported
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER;
bd.stex.texId = texD->m_id;
bd.stex.texGeneration = texD->generation;
bd.stex.samplerId = samplerD->m_id;
bd.stex.samplerGeneration = samplerD->generation;
VkDescriptorImageInfo imageInfo;
imageInfo.sampler = samplerD->sampler;
imageInfo.imageView = texD->imageView;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
ArrayOfImageDesc imageInfo(data->count);
for (int elem = 0; elem < data->count; ++elem) {
QVkTexture *texD = QRHI_RES(QVkTexture, data->texSamplers[elem].tex);
QVkSampler *samplerD = QRHI_RES(QVkSampler, 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;
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();
imageInfos.append(imageInfo);
}
@ -2555,10 +2570,10 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
writeInfo.descriptorType = VK_DESCRIPTOR_TYPE_STORAGE_IMAGE;
bd.simage.id = texD->m_id;
bd.simage.generation = texD->generation;
VkDescriptorImageInfo imageInfo;
imageInfo.sampler = VK_NULL_HANDLE;
imageInfo.imageView = view;
imageInfo.imageLayout = VK_IMAGE_LAYOUT_GENERAL;
ArrayOfImageDesc imageInfo(1);
imageInfo[0].sampler = VK_NULL_HANDLE;
imageInfo[0].imageView = view;
imageInfo[0].imageLayout = VK_IMAGE_LAYOUT_GENERAL;
imageInfoIndex = imageInfos.count();
imageInfos.append(imageInfo);
}
@ -2596,7 +2611,7 @@ void QRhiVulkan::updateShaderResourceBindings(QRhiShaderResourceBindings *srb, i
if (bufferInfoIndex >= 0)
writeInfos[i].pBufferInfo = &bufferInfos[bufferInfoIndex];
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);
@ -4210,24 +4225,30 @@ void QRhiVulkan::setShaderResources(QRhiCommandBuffer *cb, QRhiShaderResourceBin
break;
case QRhiShaderResourceBinding::SampledTexture:
{
QVkTexture *texD = QRHI_RES(QVkTexture, b->u.stex.tex);
QVkSampler *samplerD = QRHI_RES(QVkSampler, b->u.stex.sampler);
texD->lastActiveFrameSlot = currentFrameSlot;
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)
{
const QRhiShaderResourceBinding::Data::SampledTextureData *data = &b->u.stex;
if (bd.stex.count != data->count) {
bd.stex.count = data->count;
rewriteDescSet = true;
bd.stex.texId = texD->m_id;
bd.stex.texGeneration = texD->generation;
bd.stex.samplerId = samplerD->m_id;
bd.stex.samplerGeneration = samplerD->generation;
}
for (int elem = 0; elem < data->count; ++elem) {
QVkTexture *texD = QRHI_RES(QVkTexture, data->texSamplers[elem].tex);
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;
@ -6065,7 +6086,10 @@ bool QVkShaderResourceBindings::build()
memset(&vkbinding, 0, sizeof(vkbinding));
vkbinding.binding = uint32_t(b->binding);
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);
vkbindings.append(vkbinding);
}

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -27,7 +27,7 @@ qhp.QtNetwork.subprojects.classes.sortPages = true
tagfile = ../../../doc/qtnetwork/qtnetwork.tags
depends += qtcore qtgui qtdoc qmake
depends += qtcore qtgui qtdoc qmake qtcmake
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>
int main(int argv, char **args)

View File

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

View File

@ -31,6 +31,8 @@
\title Bearer Management
\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
the user can start or stop interfaces or roam transparently between
access points.

View File

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

View File

@ -564,12 +564,12 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
int pos = -1;
#if QT_CONFIG(regularexpression)
if (syntax == Wildcard)
if (syntax == PatternSyntax::Wildcard)
pos = pathPrefix.indexOf(QRegularExpression(QLatin1String("[*?[]")));
else if (syntax == RegExp)
else if (syntax == PatternSyntax::RegularExpression)
pos = sourcePath.indexOf(QRegularExpression(QLatin1String("[\\$\\(\\)\\*\\+\\.\\?\\[\\]\\^\\{\\}\\|]")));
#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");
return QList<QSslCertificate>();
#endif
@ -606,7 +606,7 @@ QList<QSslCertificate> QSslCertificate::fromPath(const QString &path,
QList<QSslCertificate> certs;
#if QT_CONFIG(regularexpression)
if (syntax == Wildcard)
if (syntax == PatternSyntax::Wildcard)
sourcePath = QRegularExpression::wildcardToRegularExpression(sourcePath);
QRegularExpression pattern(QRegularExpression::anchoredPattern(sourcePath));

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -166,7 +166,12 @@ static inline bool launch(const QString &launcher, const QUrl &url)
#if !QT_CONFIG(process)
const bool ok = ::system(qPrintable(command + QLatin1String(" &")));
#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
if (!ok)
qWarning("Launch failed (%s)", qPrintable(command));

View File

@ -53,6 +53,7 @@ QWindowsUiaWrapper::QWindowsUiaWrapper()
m_pUiaHostProviderFromHwnd = reinterpret_cast<PtrUiaHostProviderFromHwnd>(uiaLib.resolve("UiaHostProviderFromHwnd"));
m_pUiaRaiseAutomationPropertyChangedEvent = reinterpret_cast<PtrUiaRaiseAutomationPropertyChangedEvent>(uiaLib.resolve("UiaRaiseAutomationPropertyChangedEvent"));
m_pUiaRaiseAutomationEvent = reinterpret_cast<PtrUiaRaiseAutomationEvent>(uiaLib.resolve("UiaRaiseAutomationEvent"));
m_pUiaRaiseNotificationEvent = reinterpret_cast<PtrUiaRaiseNotificationEvent>(uiaLib.resolve("UiaRaiseNotificationEvent"));
m_pUiaClientsAreListening = reinterpret_cast<PtrUiaClientsAreListening>(uiaLib.resolve("UiaClientsAreListening"));
}
}
@ -68,7 +69,7 @@ QWindowsUiaWrapper *QWindowsUiaWrapper::instance()
return &wrapper;
}
// True if all symbols resolved.
// True if most symbols resolved (UiaRaiseNotificationEvent is optional).
BOOL QWindowsUiaWrapper::ready()
{
return m_pUiaReturnRawElementProvider
@ -113,5 +114,12 @@ HRESULT QWindowsUiaWrapper::raiseAutomationEvent(IRawElementProviderSimple *pPro
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

View File

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

View File

@ -162,6 +162,22 @@ enum ExpandCollapseState {
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 {
double left;
double top;

View File

@ -1632,6 +1632,7 @@ QCocoaNSWindow *QCocoaWindow::createNSWindow(bool shouldBePanel)
nsWindow.restorable = NO;
nsWindow.level = windowLevel(flags);
nsWindow.tabbingMode = NSWindowTabbingModeDisallowed;
if (shouldBePanel) {
// 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 (QWindowsUiaMainProvider *provider = providerForAccessible(accessible)) {
// Notifies changes in string values.
VARIANT oldVal, newVal;
clearVariant(&oldVal);
setVariantString(event->value().toString(), &newVal);
QWindowsUiaWrapper::instance()->raiseAutomationPropertyChangedEvent(provider, UIA_ValueValuePropertyId, oldVal, newVal);
// Tries to notify the change using UiaRaiseNotificationEvent(), which is only available on
// Windows 10 version 1709 or newer. Otherwise uses UiaRaiseAutomationPropertyChangedEvent().
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()) {
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));
}
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()) {
HStringReference nativeSuggestedName(reinterpret_cast<const wchar_t *>(suggestedName.utf16()),
uint(suggestedName.length()));

View File

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

View File

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

View File

@ -42,6 +42,7 @@
#include "qprintdialog.h"
#include "qabstractprintdialog_p.h"
#include <QtCore/qtemporarydir.h>
#include <QtCore/private/qcore_mac_p.h>
#include <QtWidgets/private/qapplication_p.h>
#include <QtPrintSupport/qprinter.h>
@ -127,21 +128,36 @@ QT_USE_NAMESPACE
PMDestinationType dest;
PMSessionGetDestinationType(session, settings, &dest);
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;
PMSessionCopyDestinationLocation(session, settings, &file);
UInt8 localFile[2048]; // Assuming there's a POSIX file system here.
CFURLGetFileSystemRepresentation(file, true, localFile, sizeof(localFile));
printer->setOutputFileName(QString::fromUtf8(reinterpret_cast<const char *>(localFile)));
*/
} else {
auto outputFile = QFileInfo(QString::fromUtf8(reinterpret_cast<const char *>(localFile)));
if (outputFile.suffix() == QLatin1String("pdf"))
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;
PMSessionGetCurrentPrinter(session, &macPrinter);
QString printerId = QString::fromCFString(PMPrinterGetID(macPrinter));
QString printerId = QString::fromCFString(PMPrinterGetID(macPrinter)).trimmed();
if (printer->printerName() != printerId)
printer->setPrinterName(printerId);
}
@ -199,14 +215,18 @@ void QPrintDialogPrivate::openCocoaPrintPanel(Qt::WindowModality modality)
{
Q_Q(QPrintDialog);
// get the NSPrintInfo from the print engine in the platform plugin
void *voidp = 0;
(void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
"NSPrintInfoForPrintEngine",
Q_RETURN_ARG(void *, voidp),
Q_ARG(QPrintEngine *, printer->printEngine()));
printInfo = static_cast<NSPrintInfo *>(voidp);
[printInfo retain];
if (printer->outputFormat() == QPrinter::NativeFormat) {
// get the NSPrintInfo from the print engine in the platform plugin
void *voidp = 0;
(void) QMetaObject::invokeMethod(qApp->platformNativeInterface(),
"NSPrintInfoForPrintEngine",
Q_RETURN_ARG(void *, voidp),
Q_ARG(QPrintEngine *, printer->printEngine()));
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
// for the page range is 1. This _kind of_ makes sense if you think about
@ -269,31 +289,15 @@ void QPrintDialogPrivate::closeCocoaPrintPanel()
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)
: QAbstractPrintDialog(*(new QPrintDialogPrivate), printer, parent)
{
Q_D(QPrintDialog);
if (!warnIfNotNative(d->printer))
return;
setAttribute(Qt::WA_DontShowOnScreen);
}
QPrintDialog::QPrintDialog(QWidget *parent)
: QAbstractPrintDialog(*(new QPrintDialogPrivate), 0, parent)
{
Q_D(QPrintDialog);
if (!warnIfNotNative(d->printer))
return;
setAttribute(Qt::WA_DontShowOnScreen);
}
@ -304,8 +308,6 @@ QPrintDialog::~QPrintDialog()
int QPrintDialog::exec()
{
Q_D(QPrintDialog);
if (!warnIfNotNative(d->printer))
return QDialog::Rejected;
QDialog::setVisible(true);

View File

@ -170,6 +170,8 @@ struct Options
// Versioning
QString versionName;
QString versionCode;
QByteArray minSdkVersion{"21"};
QByteArray targetSdkVersion{"28"};
// lib c++ path
QString stdCppPath;
@ -859,6 +861,18 @@ bool readInputFile(Options *options)
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();
if (targetArchitectures.isEmpty()) {
@ -2319,6 +2333,8 @@ bool buildAndroidProject(const Options &options)
gradleProperties["buildDir"] = "build";
gradleProperties["qt5AndroidDir"] = (options.qtInstallDirectory + QLatin1String("/src/android/java")).toUtf8();
gradleProperties["androidCompileSdkVersion"] = options.androidPlatform.split(QLatin1Char('-')).last().toLocal8Bit();
gradleProperties["qtMinSdkVersion"] = options.minSdkVersion;
gradleProperties["qtTargetSdkVersion"] = options.targetSdkVersion;
if (gradleProperties["androidBuildToolsVersion"].isEmpty())
gradleProperties["androidBuildToolsVersion"] = options.sdkBuildToolsVersion.toLocal8Bit();

View File

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

View File

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

View File

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

View File

@ -59,6 +59,7 @@
#include <QtWidgets/qgraphicsview.h>
#include <QtWidgets/qgraphicsproxywidget.h>
#include <QtGui/qpalette.h>
#include <QtGui/qpainterpath.h>
#include <QtWidgets/qstyleoption.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());
if (standardIcon >= QStyle::SP_CustomBase) {
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));
QPixmapCache::insert(cacheKey, mainIcon);
}

View File

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

View File

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

View File

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

View File

@ -158,10 +158,13 @@ private slots:
QFETCH(QtMsgType, msgType);
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;
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 0: state = NoMatch; break;
case 1: state = Match; break;

View File

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

View File

@ -73,6 +73,8 @@ QStringList toQStringList(const Iterable &i) {
MAKE_ALL(QByteArray, QChar)
MAKE_ALL(QByteArray, QLatin1String)
MAKE_ALL(QByteArray, char16_t)
MAKE_ALL(char16_t, QByteArray)
MAKE_ALL(const char*, QChar)
@ -100,6 +102,11 @@ static QByteArray rowName(const QByteArray &data)
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
{
Q_OBJECT
@ -113,9 +120,11 @@ class tst_QStringApiSymmetry : public QObject
void compare_impl() const;
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() { 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() { compare_impl<QChar, QStringRef>(); }
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() { 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() { 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() { compare_impl<QStringRef, QStringRef>(); }
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() { 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() { compare_impl<QString, QStringRef>(); }
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() { 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() { compare_impl<QStringView, QStringRef>(); }
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() { 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() { compare_impl<QLatin1String, QStringRef>(); }
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() { 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() { compare_impl<QByteArray, QStringRef>(); }
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() { 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() { compare_impl<const char *, QStringRef>(); }
void compare_const_char_star_QString_data() { compare_data(); }
@ -223,10 +261,12 @@ private:
void member_compare_impl() const;
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)?
void member_compare_QChar_QChar_data() { member_compare_data(false); }
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() { member_compare_impl<QChar, QStringRef>(); }
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 *>(); }
#endif
// void member_compare_char16_t_XXX() - not possible
void member_compare_QStringRef_QChar_data() { member_compare_data(false); }
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() { member_compare_impl<QStringRef, QStringRef>(); }
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() { 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() { member_compare_impl<QString, QStringRef>(); }
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() { 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() { 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() { member_compare_impl<QStringView, QStringRef>(); }
void member_compare_QStringView_QString_data() { member_compare_data(); }
void member_compare_QStringView_QString() { member_compare_impl<QStringView, QString>(); }
void member_compare_QStringView_QStringView_data() { member_compare_data(); }
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() { member_compare_impl<QStringView, QLatin1String>(); }
#ifdef NOT_YET_IMPLEMENTED
void member_compare_QStringView_QByteArray_data() { member_compare_data(); }
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() { member_compare_impl<QStringView, const char *>(); }
#endif
void member_compare_QLatin1String_QChar_data() { member_compare_data(false); }
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() { member_compare_impl<QLatin1String, QStringRef>(); }
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_QLatin1String_data() { member_compare_data(); }
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() { member_compare_impl<QLatin1String, QByteArray>(); }
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() { 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() { member_compare_impl<QByteArray, QStringRef>(); }
void member_compare_QByteArray_QString_data() { member_compare_data(); }
@ -330,7 +382,7 @@ private:
template <typename Haystack, typename Needle> void endsWith_impl() const;
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() { startsWith_impl<QString, QString>(); }
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_QChar_data() { startsWith_data(false); }
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() { startsWith_impl<QStringRef, QString>(); }
@ -352,6 +406,8 @@ private Q_SLOTS:
void startsWith_QStringRef_QLatin1String() { startsWith_impl<QStringRef, QLatin1String>(); }
void startsWith_QStringRef_QChar_data() { startsWith_data(false); }
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() { startsWith_impl<QStringView, QString>(); }
@ -363,6 +419,8 @@ private Q_SLOTS:
void startsWith_QStringView_QLatin1String() { startsWith_impl<QStringView, QLatin1String>(); }
void startsWith_QStringView_QChar_data() { startsWith_data(false); }
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() { startsWith_impl<QLatin1String, QString>(); }
@ -374,6 +432,8 @@ private Q_SLOTS:
void startsWith_QLatin1String_QLatin1String() { startsWith_impl<QLatin1String, QLatin1String>(); }
void startsWith_QLatin1String_QChar_data() { startsWith_data(false); }
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() { endsWith_impl<QString, QString>(); }
@ -385,6 +445,8 @@ private Q_SLOTS:
void endsWith_QString_QLatin1String() { endsWith_impl<QString, QLatin1String>(); }
void endsWith_QString_QChar_data() { endsWith_data(false); }
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() { endsWith_impl<QStringRef, QString>(); }
@ -396,6 +458,8 @@ private Q_SLOTS:
void endsWith_QStringRef_QLatin1String() { endsWith_impl<QStringRef, QLatin1String>(); }
void endsWith_QStringRef_QChar_data() { endsWith_data(false); }
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() { endsWith_impl<QStringView, QString>(); }
@ -407,6 +471,8 @@ private Q_SLOTS:
void endsWith_QStringView_QLatin1String() { endsWith_impl<QStringView, QLatin1String>(); }
void endsWith_QStringView_QChar_data() { endsWith_data(false); }
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() { endsWith_impl<QLatin1String, QString>(); }
@ -418,6 +484,8 @@ private Q_SLOTS:
void endsWith_QLatin1String_QLatin1String() { endsWith_impl<QLatin1String, QLatin1String>(); }
void endsWith_QLatin1String_QChar_data() { endsWith_data(false); }
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:
void split_data(bool rhsHasVariableLength = true);
@ -566,9 +634,10 @@ private Q_SLOTS:
private:
template <typename Haystack, typename Needle> void indexOf_impl() const;
void indexOf_data();
void indexOf_data(bool rhsHasVariableLength = true);
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() { indexOf_impl<QString, QString>(); }
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_QStringView_data() { indexOf_data(); }
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() { indexOf_impl<QLatin1String, QString>(); }
@ -586,6 +659,10 @@ private Q_SLOTS:
void indexOf_QLatin1String_QStringRef() { indexOf_impl<QLatin1String, QStringRef>(); }
void indexOf_QLatin1String_QStringView_data() { indexOf_data(); }
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() { indexOf_impl<QStringRef, QString>(); }
@ -595,6 +672,10 @@ private Q_SLOTS:
void indexOf_QStringRef_QStringRef() { indexOf_impl<QStringRef, QStringRef>(); }
void indexOf_QStringRef_QStringView_data() { indexOf_data(); }
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() { indexOf_impl<QStringView, QString>(); }
@ -604,12 +685,17 @@ private Q_SLOTS:
void indexOf_QStringView_QStringRef() { indexOf_impl<QStringView, QStringRef>(); }
void indexOf_QStringView_QStringView_data() { indexOf_data(); }
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:
template <typename Haystack, typename Needle> void contains_impl() const;
void contains_data();
void contains_data(bool rhsHasVariableLength = true);
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() { contains_impl<QString, QString>(); }
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_QStringView_data() { contains_data(); }
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() { contains_impl<QLatin1String, QString>(); }
@ -627,6 +717,10 @@ private Q_SLOTS:
void contains_QLatin1String_QStringRef() { contains_impl<QLatin1String, QStringRef>(); }
void contains_QLatin1String_QStringView_data() { contains_data(); }
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() { contains_impl<QStringRef, QString>(); }
@ -636,6 +730,10 @@ private Q_SLOTS:
void contains_QStringRef_QStringRef() { contains_impl<QStringRef, QStringRef>(); }
void contains_QStringRef_QStringView_data() { contains_data(); }
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() { contains_impl<QStringView, QString>(); }
@ -645,12 +743,17 @@ private Q_SLOTS:
void contains_QStringView_QStringRef() { contains_impl<QStringView, QStringRef>(); }
void contains_QStringView_QStringView_data() { contains_data(); }
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:
template <typename Haystack, typename Needle> void lastIndexOf_impl() const;
void lastIndexOf_data();
void lastIndexOf_data(bool rhsHasVariableLength = true);
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() { lastIndexOf_impl<QString, QString>(); }
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_QStringView_data() { lastIndexOf_data(); }
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() { lastIndexOf_impl<QLatin1String, QString>(); }
@ -668,6 +775,10 @@ private Q_SLOTS:
void lastIndexOf_QLatin1String_QStringRef() { lastIndexOf_impl<QLatin1String, QStringRef>(); }
void lastIndexOf_QLatin1String_QStringView_data() { lastIndexOf_data(); }
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() { lastIndexOf_impl<QStringRef, QString>(); }
@ -677,6 +788,10 @@ private Q_SLOTS:
void lastIndexOf_QStringRef_QStringRef() { lastIndexOf_impl<QStringRef, QStringRef>(); }
void lastIndexOf_QStringRef_QStringView_data() { lastIndexOf_data(); }
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() { lastIndexOf_impl<QStringView, QString>(); }
@ -686,6 +801,10 @@ private Q_SLOTS:
void lastIndexOf_QStringView_QStringRef() { lastIndexOf_impl<QStringView, QStringRef>(); }
void lastIndexOf_QStringView_QStringView_data() { lastIndexOf_data(); }
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)
@ -725,6 +844,8 @@ void tst_QStringApiSymmetry::compare_data(bool hasConceptOfNullAndEmpty)
ROW("0", "");
ROW("0", "1");
ROW("0", "0");
ROW("10", "0");
ROW("01", "1");
ROW("\xE4", "\xE4"); // ä <> ä
ROW("\xE4", "\xC4"); // ä <> Ä
#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 <> 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 <> QString make(const QStringRef &sf, QLatin1String, const QByteArray &) { return sf.toString(); }
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 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) \
QVERIFY_NOEXCEPT(lhs op rhs); \
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 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));
QCOMPARE(sign(lhs.compare(rhs)), caseSensitiveCompareResult);
@ -1646,7 +1750,7 @@ void tst_QStringApiSymmetry::toUcs4_impl()
QCOMPARE(unicode.isEmpty(), ucs4.isEmpty());
}
void tst_QStringApiSymmetry::indexOf_data()
void tst_QStringApiSymmetry::indexOf_data(bool rhsHasVariableLength)
{
QTest::addColumn<QString>("haystackU16");
QTest::addColumn<QLatin1String>("haystackL1");
@ -1659,18 +1763,20 @@ void tst_QStringApiSymmetry::indexOf_data()
constexpr qsizetype zeroPos = 0;
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;
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
<< 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;
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
<< 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;
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
<< empty << QLatin1String("") << zeroPos << zeroPos << zeroPos;
}
QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
<< a << QLatin1String("a") << zeroPos << minus1Pos << minus1Pos;
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, 2, -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);
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, 1, -1, 1);
ROW(AbC, BC, 2, -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, 2, -1, -1);
}
#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, Qt::CaseSensitive), size_type(resultCS));
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");
@ -1755,7 +1856,7 @@ static QString asd = QStringLiteral("asd");
static QString asdf = QStringLiteral("asdf");
static QString Z = QStringLiteral("Z");
void tst_QStringApiSymmetry::contains_data()
void tst_QStringApiSymmetry::contains_data(bool rhsHasVariableLength)
{
QTest::addColumn<QString>("haystackU16");
QTest::addColumn<QLatin1String>("haystackL1");
@ -1764,18 +1865,20 @@ void tst_QStringApiSymmetry::contains_data()
QTest::addColumn<bool>("resultCS");
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;
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
<< 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;
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
<< 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;;
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
<< empty << QLatin1String("") << true << true;
}
QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
<< a << QLatin1String("a") << false << false;
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, false, true);
ROW(ABCDEFGHIEfGEFG, Z, false, false);
ROW(ABCDEFGHIEfGEFG, EFG, true, true);
ROW(ABCDEFGHIEfGEFG, efg, false, true);
if (rhsHasVariableLength) {
ROW(ABCDEFGHIEfGEFG, EFG, true, true);
ROW(ABCDEFGHIEfGEFG, efg, false, true);
}
ROW(ABCDEFGHIEfGEFG, E, true, true);
ROW(ABCDEFGHIEfGEFG, e, false, true);
#undef ROW
@ -1815,16 +1920,9 @@ void tst_QStringApiSymmetry::contains_impl() const
QCOMPARE(haystack.contains(needle), resultCS);
QCOMPARE(haystack.contains(needle, Qt::CaseSensitive), resultCS);
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<QLatin1String>("haystackL1");
@ -1837,38 +1935,43 @@ void tst_QStringApiSymmetry::lastIndexOf_data()
constexpr qsizetype zeroPos = 0;
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;
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
QTest::addRow("haystack: empty, needle: null") << empty << QLatin1String("")
<< 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;
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
QTest::addRow("haystack: null, needle: empty") << null << QLatin1String()
<< 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;
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
QTest::addRow("haystack: empty, needle: empty") << empty << QLatin1String("")
<< empty << QLatin1String("") << minus1Pos << minus1Pos << minus1Pos;
}
QTest::addRow("haystack: empty, needle: a") << empty << QLatin1String("")
<< a << QLatin1String("a") << minus1Pos << minus1Pos << minus1Pos;
QTest::addRow("haystack: null, needle: a") << null << QLatin1String()
<< 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);
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);
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
QTest::addRow("haystack: a, needle: null") << a << QLatin1String("a")
<< 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;
}
#define ROW(h, n, st, cs, cis) \
QTest::addRow("haystack: %s, needle: %s", #h, #n) << h << QLatin1String(#h) \
<< n << QLatin1String(#n) \
<< 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, -1, 14);
@ -1895,13 +1998,15 @@ void tst_QStringApiSymmetry::lastIndexOf_data()
ROW(ABCDEFGHIEfGEFG, A, -15, 0, 0);
ROW(ABCDEFGHIEfGEFG, a, -15, -1, 0);
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, 12, -1, 12);
ROW(ABCDEFGHIEfGEFG, efg, -12, -1, -1);
ROW(ABCDEFGHIEfGEFG, efg, 11, -1, 9);
if (rhsHasVariableLength) {
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, 12, -1, 12);
ROW(ABCDEFGHIEfGEFG, efg, -12, -1, -1);
ROW(ABCDEFGHIEfGEFG, efg, 11, -1, 9);
}
#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::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)

File diff suppressed because it is too large Load Diff

View File

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

View File

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

View File

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

View File

@ -36,6 +36,7 @@
#include <QtGui/QOpenGLFunctions>
#include <QtGui/QOpenGLFunctions_4_2_Core>
#include <QtGui/QPainter>
#include <QtGui/QPainterPath>
#include <QtGui/QScreen>
#include <QtGui/QWindow>
#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 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 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.frag.qsb textured.frag

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