Merge remote-tracking branch 'origin/5.5' into dev
Change-Id: I04f9f2749f68c0cb5a427b8d84e43b44bb143e4d
This commit is contained in:
commit
4973786f0d
11
configure
vendored
11
configure
vendored
@ -561,21 +561,28 @@ fi
|
||||
# initalize variables
|
||||
#-------------------------------------------------------------------------------
|
||||
|
||||
SYSTEM_VARIABLES="RANLIB STRIP OBJDUMP LD CC CXX CFLAGS CXXFLAGS LDFLAGS"
|
||||
SYSTEM_VARIABLES="AR RANLIB STRIP OBJDUMP LD CC CXX CFLAGS CXXFLAGS LDFLAGS"
|
||||
for varname in $SYSTEM_VARIABLES; do
|
||||
qmakevarname="${varname}"
|
||||
qmakecmdargs=""
|
||||
# use LDFLAGS for autoconf compat, but qmake uses QMAKE_LFLAGS
|
||||
if [ "${varname}" = "LDFLAGS" ]; then
|
||||
qmakevarname="LFLAGS"
|
||||
elif [ "${varname}" = "LD" ]; then
|
||||
qmakevarname="LINK"
|
||||
elif [ "${varname}" = "AR" ]; then
|
||||
# QMAKE_AR needs to be set to "/path/to/ar cqs" but the
|
||||
# environment variable will be set to the command only so we
|
||||
# need to append " cqs" for autoconf compatibility
|
||||
qmakecmdargs=" cqs"
|
||||
fi
|
||||
cmd=`echo \
|
||||
'if [ -n "\$'${varname}'" ]; then
|
||||
QMakeVar set QMAKE_'${qmakevarname}' "\$'${varname}'"
|
||||
QMakeVar set QMAKE_'${qmakevarname}' "\$'${varname}${qmakecmdargs}'"
|
||||
fi'`
|
||||
eval "$cmd"
|
||||
done
|
||||
|
||||
# Use CC/CXX to run config.tests
|
||||
mkdir -p "$outpath/config.tests"
|
||||
rm -f "$outpath/config.tests/.qmake.cache"
|
||||
|
@ -4,10 +4,8 @@ CONFIG *= thread
|
||||
win32 {
|
||||
contains(QT_CONFIG, shared) {
|
||||
# this variable is read by qmake in qmake/generators/win32/msvc_vcproj.cpp
|
||||
# function VcprojGenerator::initDeploymentTool(), which contains some hardcoded
|
||||
# library names (the ones that were static in Qt 4)
|
||||
# it probably doesn't work anymore and should not be in this file
|
||||
QMAKE_QT_DLL = 1
|
||||
# function VcprojGenerator::initDeploymentTool()
|
||||
QMAKE_DLL_PATHS += $$[QT_INSTALL_BINS/get]
|
||||
}
|
||||
}
|
||||
CONFIG(release, debug|release):DEFINES += QT_NO_DEBUG
|
||||
|
@ -1267,31 +1267,43 @@ void VcprojGenerator::initDeploymentTool()
|
||||
if (targetPath.endsWith("/") || targetPath.endsWith("\\"))
|
||||
targetPath.chop(1);
|
||||
}
|
||||
|
||||
ProStringList dllPaths = project->values("QMAKE_DLL_PATHS");
|
||||
// Only deploy Qt libs for shared build
|
||||
if (!project->values("QMAKE_QT_DLL").isEmpty()) {
|
||||
if (!dllPaths.isEmpty()) {
|
||||
// FIXME: This code should actually resolve the libraries from all Qt modules.
|
||||
const QString &qtdir = project->propertyValue(ProKey("QT_INSTALL_LIBS/get")).toQString();
|
||||
ProStringList arg = project->values("QMAKE_LIBS") + project->values("QMAKE_LIBS_PRIVATE");
|
||||
for (ProStringList::ConstIterator it = arg.constBegin(); it != arg.constEnd(); ++it) {
|
||||
if (it->contains(qtdir)) {
|
||||
QString dllName = (*it).toQString();
|
||||
QString dllName = (*it).toQString();
|
||||
dllName.replace(QLatin1Char('\\'), QLatin1Char('/'));
|
||||
// LIBPATH isn't relevant for deployment
|
||||
if (dllName.startsWith(QLatin1String("/LIBPATH:")))
|
||||
continue;
|
||||
// We want to deploy .dlls not .libs
|
||||
if (dllName.endsWith(QLatin1String(".lib")))
|
||||
dllName.replace(dllName.length() - 3, 3, QLatin1String("dll"));
|
||||
// Use only the file name and check in Qt's install path and LIBPATHs to check for existence
|
||||
dllName.remove(0, dllName.lastIndexOf(QLatin1Char('/')) + 1);
|
||||
QFileInfo info;
|
||||
foreach (const ProString &dllPath, dllPaths) {
|
||||
QString absoluteDllFilePath = dllPath.toQString();
|
||||
if (!absoluteDllFilePath.endsWith(QLatin1Char('/')))
|
||||
absoluteDllFilePath += QLatin1Char('/');
|
||||
absoluteDllFilePath += dllName;
|
||||
info = QFileInfo(absoluteDllFilePath);
|
||||
if (info.exists())
|
||||
break;
|
||||
}
|
||||
|
||||
if (dllName.contains(QLatin1String("QAxContainer"))
|
||||
|| dllName.contains(QLatin1String("qtmain"))
|
||||
|| dllName.contains(QLatin1String("QtUiTools")))
|
||||
continue;
|
||||
dllName.replace(QLatin1String(".lib") , QLatin1String(".dll"));
|
||||
QFileInfo info(dllName);
|
||||
if (conf.WinRT) {
|
||||
QString absoluteFilePath(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||
vcProject.DeploymentFiles.addFile(absoluteFilePath);
|
||||
} else {
|
||||
conf.deployment.AdditionalFiles += info.fileName()
|
||||
+ "|" + QDir::toNativeSeparators(info.absolutePath())
|
||||
+ "|" + targetPath
|
||||
+ "|0;";
|
||||
}
|
||||
if (!info.exists())
|
||||
continue;
|
||||
if (conf.WinRT) {
|
||||
QString absoluteFilePath(QDir::toNativeSeparators(info.absoluteFilePath()));
|
||||
vcProject.DeploymentFiles.addFile(absoluteFilePath);
|
||||
} else {
|
||||
conf.deployment.AdditionalFiles += info.fileName()
|
||||
+ "|" + QDir::toNativeSeparators(info.absolutePath())
|
||||
+ "|" + targetPath
|
||||
+ "|0;";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -49,26 +49,35 @@
|
||||
applications:
|
||||
|
||||
\list
|
||||
\li \l {Concurrent Map and Map-Reduce}
|
||||
\list
|
||||
\li \l {QtConcurrent::map}{QtConcurrent::map()} applies a function
|
||||
to every item in a container, modifying the items in-place.
|
||||
\li \l {QtConcurrent::mapped}{QtConcurrent::mapped()} is like
|
||||
map(), except that it returns a new container with the
|
||||
modifications.
|
||||
\li \l {QtConcurrent::mappedReduced}{QtConcurrent::mappedReduced()}
|
||||
is like mapped(), except that the modified results are reduced
|
||||
or folded into a single result.
|
||||
\endlist
|
||||
|
||||
\li \l {QtConcurrent::map}{QtConcurrent::map()} applies a function to every item in a container,
|
||||
modifying the items in-place.
|
||||
\li \l {Concurrent Filter and Filter-Reduce}
|
||||
\list
|
||||
\li \l {QtConcurrent::filter}{QtConcurrent::filter()} removes all items
|
||||
from a container based on the result of a filter function.
|
||||
\li \l {QtConcurrent::filtered}{QtConcurrent::filtered()} is like
|
||||
filter(), except that it returns a new container with the filtered
|
||||
results.
|
||||
\li \l {QtConcurrent::filteredReduced}{QtConcurrent::filteredReduced()}
|
||||
is like filtered(), except that the filtered results are reduced or
|
||||
folded into a single result.
|
||||
\endlist
|
||||
|
||||
\li \l {QtConcurrent::mapped}{QtConcurrent::mapped()} is like map(), except that it returns a new
|
||||
container with the modifications.
|
||||
|
||||
\li \l {QtConcurrent::mappedReduced}{QtConcurrent::mappedReduced()} is like mapped(), except that the
|
||||
modified results are reduced or folded into a single result.
|
||||
|
||||
\li \l {QtConcurrent::filter}{QtConcurrent::filter()} removes all items from a container based on the
|
||||
result of a filter function.
|
||||
|
||||
\li \l {QtConcurrent::filtered}{QtConcurrent::filtered()} is like filter(), except that it returns a new
|
||||
container with the filtered results.
|
||||
|
||||
\li \l {QtConcurrent::filteredReduced}{QtConcurrent::filteredReduced()} is like filtered(), except that the
|
||||
filtered results are reduced or folded into a single result.
|
||||
|
||||
\li \l {QtConcurrent::run}{QtConcurrent::run()} runs a function in another thread.
|
||||
\li \l {Concurrent Run}
|
||||
\list
|
||||
\li \l {QtConcurrent::run}{QtConcurrent::run()} runs a function in
|
||||
another thread.
|
||||
\endlist
|
||||
|
||||
\li QFuture represents the result of an asynchronous computation.
|
||||
|
||||
|
@ -179,6 +179,8 @@
|
||||
Calls \a filterFunction once for each item in \a sequence. If
|
||||
\a filterFunction returns \c true, the item is kept in \a sequence;
|
||||
otherwise, the item is removed from \a sequence.
|
||||
|
||||
\sa {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -188,6 +190,8 @@
|
||||
new Sequence of kept items. If \a filterFunction returns \c true, a copy of
|
||||
the item is put in the new Sequence. Otherwise, the item will \e not
|
||||
appear in the new Sequence.
|
||||
|
||||
\sa {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -197,6 +201,8 @@
|
||||
returns a new Sequence of kept items. If \a filterFunction returns \c true, a
|
||||
copy of the item is put in the new Sequence. Otherwise, the item will
|
||||
\e not appear in the new Sequence.
|
||||
|
||||
\sa {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -213,6 +219,8 @@
|
||||
QtConcurrent::UnorderedReduce. If \a reduceOptions is
|
||||
QtConcurrent::OrderedReduce, \a reduceFunction is called in the order of
|
||||
the original sequence.
|
||||
|
||||
\sa {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -229,6 +237,8 @@
|
||||
QtConcurrent::UnorderedReduce. If \a reduceOptions is
|
||||
QtConcurrent::OrderedReduce, the \a reduceFunction is called in the order
|
||||
of the original sequence.
|
||||
|
||||
\sa {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -239,6 +249,8 @@
|
||||
otherwise, the item is removed from \a sequence.
|
||||
|
||||
\note This function will block until all items in the sequence have been processed.
|
||||
|
||||
\sa {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -251,7 +263,7 @@
|
||||
|
||||
\note This function will block until all items in the sequence have been processed.
|
||||
|
||||
\sa filtered()
|
||||
\sa filtered(), {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -265,7 +277,7 @@
|
||||
\note This function will block until the iterator reaches the end of the
|
||||
sequence being processed.
|
||||
|
||||
\sa filtered()
|
||||
\sa filtered(), {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -285,7 +297,7 @@
|
||||
|
||||
\note This function will block until all items in the sequence have been processed.
|
||||
|
||||
\sa filteredReduced()
|
||||
\sa filteredReduced(), {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -306,5 +318,5 @@
|
||||
\note This function will block until the iterator reaches the end of the
|
||||
sequence being processed.
|
||||
|
||||
\sa filteredReduced()
|
||||
\sa filteredReduced(), {Concurrent Filter and Filter-Reduce}
|
||||
*/
|
||||
|
@ -229,6 +229,8 @@
|
||||
Calls \a function once for each item in \a sequence. The \a function is
|
||||
passed a reference to the item, so that any modifications done to the item
|
||||
will appear in \a sequence.
|
||||
|
||||
\sa {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -237,6 +239,8 @@
|
||||
Calls \a function once for each item from \a begin to \a end. The
|
||||
\a function is passed a reference to the item, so that any modifications
|
||||
done to the item will appear in the sequence which the iterators belong to.
|
||||
|
||||
\sa {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -245,6 +249,8 @@
|
||||
Calls \a function once for each item in \a sequence and returns a future
|
||||
with each mapped item as a result. You can use QFuture::const_iterator or
|
||||
QFutureIterator to iterate through the results.
|
||||
|
||||
\sa {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -253,6 +259,8 @@
|
||||
Calls \a function once for each item from \a begin to \a end and returns a
|
||||
future with each mapped item as a result. You can use
|
||||
QFuture::const_iterator or QFutureIterator to iterate through the results.
|
||||
|
||||
\sa {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -266,6 +274,8 @@
|
||||
Note that while \a mapFunction is called concurrently, only one thread at a
|
||||
time will call \a reduceFunction. The order in which \a reduceFunction is
|
||||
called is determined by \a reduceOptions.
|
||||
|
||||
\sa {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -281,6 +291,8 @@
|
||||
\a reduceFunction is called is undefined.
|
||||
|
||||
\note QtConcurrent::OrderedReduce results in the ordered reduction.
|
||||
|
||||
\sa {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -292,7 +304,7 @@
|
||||
|
||||
\note This function will block until all items in the sequence have been processed.
|
||||
|
||||
\sa map()
|
||||
\sa map(), {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -305,7 +317,7 @@
|
||||
\note This function will block until the iterator reaches the end of the
|
||||
sequence being processed.
|
||||
|
||||
\sa map()
|
||||
\sa map(), {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -316,7 +328,7 @@
|
||||
|
||||
\note This function will block until all items in the sequence have been processed.
|
||||
|
||||
\sa mapped()
|
||||
\sa mapped(), {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -333,7 +345,7 @@
|
||||
\note This function will block until the iterator reaches the end of the
|
||||
sequence being processed.
|
||||
|
||||
\sa mapped()
|
||||
\sa mapped(), {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -348,7 +360,7 @@
|
||||
|
||||
\note This function will block until all items in the sequence have been processed.
|
||||
|
||||
\sa mapped()
|
||||
\sa mapped(), {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -364,5 +376,5 @@
|
||||
\note This function will block until the iterator reaches the end of the
|
||||
sequence being processed.
|
||||
|
||||
\sa blockingMappedReduced()
|
||||
\sa blockingMappedReduced(), {Concurrent Map and Map-Reduce}
|
||||
*/
|
||||
|
@ -143,6 +143,8 @@
|
||||
canceling, pausing, or progress reporting. The QFuture returned can only
|
||||
be used to query for the running/finished status and the return value of
|
||||
the function.
|
||||
|
||||
\sa {Concurrent Run}
|
||||
*/
|
||||
|
||||
/*!
|
||||
@ -160,4 +162,6 @@
|
||||
canceling, pausing, or progress reporting. The QFuture returned can only
|
||||
be used to query for the running/finished status and the return value of
|
||||
the function.
|
||||
|
||||
\sa {Concurrent Run}
|
||||
*/
|
||||
|
@ -299,18 +299,6 @@ static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environm
|
||||
if (environment.isEmpty())
|
||||
return 0;
|
||||
|
||||
// if LD_LIBRARY_PATH exists in the current environment, but
|
||||
// not in the environment list passed by the programmer, then
|
||||
// copy it over.
|
||||
#if defined(Q_OS_MAC)
|
||||
static const char libraryPath[] = "DYLD_LIBRARY_PATH";
|
||||
#else
|
||||
static const char libraryPath[] = "LD_LIBRARY_PATH";
|
||||
#endif
|
||||
const QByteArray envLibraryPath = qgetenv(libraryPath);
|
||||
bool needToAddLibraryPath = !envLibraryPath.isEmpty() &&
|
||||
!environment.contains(QProcessEnvironmentPrivate::Key(QByteArray(libraryPath)));
|
||||
|
||||
char **envp = new char *[environment.count() + 2];
|
||||
envp[environment.count()] = 0;
|
||||
envp[environment.count() + 1] = 0;
|
||||
@ -327,9 +315,6 @@ static char **_q_dupEnvironment(const QProcessEnvironmentPrivate::Hash &environm
|
||||
envp[(*envc)++] = ::strdup(key.constData());
|
||||
}
|
||||
|
||||
if (needToAddLibraryPath)
|
||||
envp[(*envc)++] = ::strdup(QByteArray(QByteArray(libraryPath) + '=' +
|
||||
envLibraryPath).constData());
|
||||
return envp;
|
||||
}
|
||||
|
||||
|
@ -215,7 +215,7 @@ bool QSaveFile::open(OpenMode mode)
|
||||
d->finalFileName = existingFile.filePath();
|
||||
}
|
||||
|
||||
d->fileEngine = new QTemporaryFileEngine(d->finalFileName);
|
||||
d->fileEngine = new QTemporaryFileEngine(d->finalFileName, 0666);
|
||||
// Same as in QFile: QIODevice provides the buffering, so there's no need to request it from the file engine.
|
||||
if (!d->fileEngine->open(mode | QIODevice::Unbuffered)) {
|
||||
QFileDevice::FileError err = d->fileEngine->error();
|
||||
|
@ -103,13 +103,14 @@ typedef int NativeFileHandle;
|
||||
\a path is used as a template when generating unique paths, \a pos
|
||||
identifies the position of the first character that will be replaced in the
|
||||
template and \a length the number of characters that may be substituted.
|
||||
\a mode specifies the file mode bits (not used on Windows).
|
||||
|
||||
Returns an open handle to the newly created file if successful, an invalid
|
||||
handle otherwise. In both cases, the string in \a path will be changed and
|
||||
contain the generated path name.
|
||||
*/
|
||||
static bool createFileFromTemplate(NativeFileHandle &file,
|
||||
QFileSystemEntry::NativePath &path, size_t pos, size_t length,
|
||||
QFileSystemEntry::NativePath &path, size_t pos, size_t length, quint32 mode,
|
||||
QSystemError &error)
|
||||
{
|
||||
Q_ASSERT(length != 0);
|
||||
@ -143,6 +144,8 @@ static bool createFileFromTemplate(NativeFileHandle &file,
|
||||
for (;;) {
|
||||
// Atomically create file and obtain handle
|
||||
#if defined(Q_OS_WIN)
|
||||
Q_UNUSED(mode);
|
||||
|
||||
# ifndef Q_OS_WINRT
|
||||
file = CreateFile((const wchar_t *)path.constData(),
|
||||
GENERIC_READ | GENERIC_WRITE,
|
||||
@ -175,7 +178,7 @@ static bool createFileFromTemplate(NativeFileHandle &file,
|
||||
#else // POSIX
|
||||
file = QT_OPEN(path.constData(),
|
||||
QT_OPEN_CREAT | O_EXCL | QT_OPEN_RDWR | QT_OPEN_LARGEFILE,
|
||||
0600);
|
||||
static_cast<mode_t>(mode));
|
||||
|
||||
if (file != -1)
|
||||
return true;
|
||||
@ -333,7 +336,7 @@ bool QTemporaryFileEngine::open(QIODevice::OpenMode openMode)
|
||||
NativeFileHandle &file = d->fd;
|
||||
#endif
|
||||
|
||||
if (!createFileFromTemplate(file, filename, phPos, phLength, error)) {
|
||||
if (!createFileFromTemplate(file, filename, phPos, phLength, fileMode, error)) {
|
||||
setError(QFile::OpenError, error.toString());
|
||||
return false;
|
||||
}
|
||||
@ -407,9 +410,9 @@ QAbstractFileEngine *QTemporaryFilePrivate::engine() const
|
||||
{
|
||||
if (!fileEngine) {
|
||||
if (fileName.isEmpty())
|
||||
fileEngine = new QTemporaryFileEngine(templateName);
|
||||
fileEngine = new QTemporaryFileEngine(templateName, 0600);
|
||||
else
|
||||
fileEngine = new QTemporaryFileEngine(fileName, false);
|
||||
fileEngine = new QTemporaryFileEngine(fileName, 0600, false);
|
||||
}
|
||||
return fileEngine;
|
||||
}
|
||||
|
@ -77,8 +77,13 @@ class QTemporaryFileEngine : public QFSFileEngine
|
||||
{
|
||||
Q_DECLARE_PRIVATE(QFSFileEngine)
|
||||
public:
|
||||
QTemporaryFileEngine(const QString &file, bool fileIsTemplate = true)
|
||||
: QFSFileEngine(), filePathIsTemplate(fileIsTemplate),
|
||||
|
||||
QTemporaryFileEngine(const QString &file,
|
||||
quint32 fileMode,
|
||||
bool fileIsTemplate = true) :
|
||||
QFSFileEngine(),
|
||||
fileMode(fileMode),
|
||||
filePathIsTemplate(fileIsTemplate),
|
||||
filePathWasTemplate(fileIsTemplate)
|
||||
{
|
||||
Q_D(QFSFileEngine);
|
||||
@ -100,6 +105,7 @@ public:
|
||||
bool renameOverwrite(const QString &newName);
|
||||
bool close();
|
||||
|
||||
quint32 fileMode;
|
||||
bool filePathIsTemplate;
|
||||
bool filePathWasTemplate;
|
||||
};
|
||||
|
@ -38,10 +38,8 @@
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#if defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && !defined(Q_CC_INTEL)
|
||||
#pragma GCC diagnostic push
|
||||
#pragma GCC diagnostic ignored "-Wmissing-field-initializers"
|
||||
#endif
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_GCC("-Wmissing-field-initializers")
|
||||
|
||||
const QArrayData QArrayData::shared_null[2] = {
|
||||
{ Q_REFCOUNT_INITIALIZE_STATIC, 0, 0, 0, sizeof(QArrayData) }, // shared null
|
||||
@ -52,9 +50,7 @@ static const QArrayData qt_array[3] = {
|
||||
{ { Q_BASIC_ATOMIC_INITIALIZER(0) }, 0, 0, 0, sizeof(QArrayData) }, // unsharable empty
|
||||
/* zero initialized terminator */};
|
||||
|
||||
#if defined (__GNUC__) && (__GNUC__ * 100 + __GNUC_MINOR__ >= 406) && !defined(Q_CC_INTEL)
|
||||
#pragma GCC diagnostic pop
|
||||
#endif
|
||||
QT_WARNING_POP
|
||||
|
||||
static const QArrayData &qt_array_empty = qt_array[0];
|
||||
static const QArrayData &qt_array_unsharable_empty = qt_array[1];
|
||||
|
@ -869,44 +869,62 @@ static inline char qToLower(char c)
|
||||
|
||||
/*! \fn QByteArray::iterator QByteArray::begin()
|
||||
|
||||
\internal
|
||||
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the first character in
|
||||
the byte-array.
|
||||
|
||||
\sa constBegin(), end()
|
||||
*/
|
||||
|
||||
/*! \fn QByteArray::const_iterator QByteArray::begin() const
|
||||
|
||||
\internal
|
||||
\overload begin()
|
||||
*/
|
||||
|
||||
/*! \fn QByteArray::const_iterator QByteArray::cbegin() const
|
||||
\since 5.0
|
||||
|
||||
\internal
|
||||
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character
|
||||
in the byte-array.
|
||||
|
||||
\sa begin(), cend()
|
||||
*/
|
||||
|
||||
/*! \fn QByteArray::const_iterator QByteArray::constBegin() const
|
||||
|
||||
\internal
|
||||
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the first character
|
||||
in the byte-array.
|
||||
|
||||
\sa begin(), constEnd()
|
||||
*/
|
||||
|
||||
/*! \fn QByteArray::iterator QByteArray::end()
|
||||
|
||||
\internal
|
||||
Returns an \l{STL-style iterators}{STL-style iterator} pointing to the imaginary character
|
||||
after the last character in the byte-array.
|
||||
|
||||
\sa begin(), constEnd()
|
||||
*/
|
||||
|
||||
/*! \fn QByteArray::const_iterator QByteArray::end() const
|
||||
|
||||
\internal
|
||||
\overload end()
|
||||
*/
|
||||
|
||||
/*! \fn QByteArray::const_iterator QByteArray::cend() const
|
||||
\since 5.0
|
||||
|
||||
\internal
|
||||
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
|
||||
character after the last character in the list.
|
||||
|
||||
\sa cbegin(), end()
|
||||
*/
|
||||
|
||||
/*! \fn QByteArray::const_iterator QByteArray::constEnd() const
|
||||
|
||||
\internal
|
||||
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
|
||||
character after the last character in the list.
|
||||
|
||||
\sa constBegin(), end()
|
||||
*/
|
||||
|
||||
/*! \fn void QByteArray::push_back(const QByteArray &other)
|
||||
|
@ -3237,7 +3237,6 @@ bool QDateTime::isDaylightTime() const
|
||||
|
||||
void QDateTime::setDate(const QDate &date)
|
||||
{
|
||||
detach();
|
||||
d->setDateTime(date, time());
|
||||
}
|
||||
|
||||
@ -3256,7 +3255,6 @@ void QDateTime::setDate(const QDate &date)
|
||||
|
||||
void QDateTime::setTime(const QTime &time)
|
||||
{
|
||||
detach();
|
||||
d->setDateTime(date(), time);
|
||||
}
|
||||
|
||||
@ -3278,7 +3276,7 @@ void QDateTime::setTime(const QTime &time)
|
||||
|
||||
void QDateTime::setTimeSpec(Qt::TimeSpec spec)
|
||||
{
|
||||
detach();
|
||||
QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
|
||||
d->setTimeSpec(spec, 0);
|
||||
d->checkValidDateTime();
|
||||
}
|
||||
@ -3300,7 +3298,7 @@ void QDateTime::setTimeSpec(Qt::TimeSpec spec)
|
||||
|
||||
void QDateTime::setOffsetFromUtc(int offsetSeconds)
|
||||
{
|
||||
detach();
|
||||
QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
|
||||
d->setTimeSpec(Qt::OffsetFromUTC, offsetSeconds);
|
||||
d->checkValidDateTime();
|
||||
}
|
||||
@ -3319,7 +3317,7 @@ void QDateTime::setOffsetFromUtc(int offsetSeconds)
|
||||
|
||||
void QDateTime::setTimeZone(const QTimeZone &toZone)
|
||||
{
|
||||
detach();
|
||||
QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
|
||||
d->m_spec = Qt::TimeZone;
|
||||
d->m_offsetFromUtc = 0;
|
||||
d->m_timeZone = toZone;
|
||||
@ -3395,7 +3393,7 @@ uint QDateTime::toTime_t() const
|
||||
*/
|
||||
void QDateTime::setMSecsSinceEpoch(qint64 msecs)
|
||||
{
|
||||
detach();
|
||||
QDateTimePrivate *d = this->d.data(); // detaches (and shadows d)
|
||||
|
||||
d->m_status = 0;
|
||||
switch (d->m_spec) {
|
||||
@ -3669,7 +3667,6 @@ QString QDateTime::toString(const QString& format) const
|
||||
QDateTime QDateTime::addDays(qint64 ndays) const
|
||||
{
|
||||
QDateTime dt(*this);
|
||||
dt.detach();
|
||||
QPair<QDate, QTime> p = d->getDateTime();
|
||||
QDate &date = p.first;
|
||||
QTime &time = p.second;
|
||||
@ -3705,7 +3702,6 @@ QDateTime QDateTime::addDays(qint64 ndays) const
|
||||
QDateTime QDateTime::addMonths(int nmonths) const
|
||||
{
|
||||
QDateTime dt(*this);
|
||||
dt.detach();
|
||||
QPair<QDate, QTime> p = d->getDateTime();
|
||||
QDate &date = p.first;
|
||||
QTime &time = p.second;
|
||||
@ -3741,7 +3737,6 @@ QDateTime QDateTime::addMonths(int nmonths) const
|
||||
QDateTime QDateTime::addYears(int nyears) const
|
||||
{
|
||||
QDateTime dt(*this);
|
||||
dt.detach();
|
||||
QPair<QDate, QTime> p = d->getDateTime();
|
||||
QDate &date = p.first;
|
||||
QTime &time = p.second;
|
||||
@ -3790,7 +3785,6 @@ QDateTime QDateTime::addMSecs(qint64 msecs) const
|
||||
return QDateTime();
|
||||
|
||||
QDateTime dt(*this);
|
||||
dt.detach();
|
||||
if (d->m_spec == Qt::LocalTime || d->m_spec == Qt::TimeZone)
|
||||
// Convert to real UTC first in case crosses daylight transition
|
||||
dt.setMSecsSinceEpoch(d->toMSecsSinceEpoch() + msecs);
|
||||
@ -4267,7 +4261,6 @@ QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs)
|
||||
QDateTime QDateTime::fromMSecsSinceEpoch(qint64 msecs, Qt::TimeSpec spec, int offsetSeconds)
|
||||
{
|
||||
QDateTime dt;
|
||||
dt.detach();
|
||||
dt.d->setTimeSpec(spec, offsetSeconds);
|
||||
dt.setMSecsSinceEpoch(msecs);
|
||||
return dt;
|
||||
@ -4687,14 +4680,6 @@ QDateTime QDateTime::fromString(const QString &string, const QString &format)
|
||||
\sa toTimeSpec()
|
||||
*/
|
||||
|
||||
/*!
|
||||
\internal
|
||||
*/
|
||||
void QDateTime::detach()
|
||||
{
|
||||
d.detach();
|
||||
}
|
||||
|
||||
/*****************************************************************************
|
||||
Date/time stream functions
|
||||
*****************************************************************************/
|
||||
@ -4846,8 +4831,6 @@ QDataStream &operator<<(QDataStream &out, const QDateTime &dateTime)
|
||||
|
||||
QDataStream &operator>>(QDataStream &in, QDateTime &dateTime)
|
||||
{
|
||||
dateTime.detach();
|
||||
|
||||
QDate dt;
|
||||
QTime tm;
|
||||
qint8 ts = 0;
|
||||
|
@ -321,7 +321,6 @@ public:
|
||||
|
||||
private:
|
||||
friend class QDateTimePrivate;
|
||||
void detach();
|
||||
|
||||
// ### Qt6: Using a private here has high impact on runtime
|
||||
// on users such as QFileInfo. In Qt 6, the data members
|
||||
|
@ -46,6 +46,11 @@ public:
|
||||
inline QQueue() {}
|
||||
inline ~QQueue() {}
|
||||
inline void swap(QQueue<T> &other) { QList<T>::swap(other); } // prevent QList<->QQueue swaps
|
||||
#ifndef Q_QDOC
|
||||
// bring in QList::swap(int, int). We cannot say using QList<T>::swap,
|
||||
// because we don't want to make swap(QList&) available.
|
||||
inline void swap(int i, int j) { QList<T>::swap(i, j); }
|
||||
#endif
|
||||
inline void enqueue(const T &t) { QList<T>::append(t); }
|
||||
inline T dequeue() { return QList<T>::takeFirst(); }
|
||||
inline T &head() { return QList<T>::first(); }
|
||||
|
@ -1291,7 +1291,7 @@ const QString::Null QString::null = { };
|
||||
\since 5.0
|
||||
|
||||
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
|
||||
item after the last item in the list.
|
||||
character after the last character in the list.
|
||||
|
||||
\sa cbegin(), end()
|
||||
*/
|
||||
@ -1299,7 +1299,7 @@ const QString::Null QString::null = { };
|
||||
/*! \fn QString::const_iterator QString::constEnd() const
|
||||
|
||||
Returns a const \l{STL-style iterators}{STL-style iterator} pointing to the imaginary
|
||||
item after the last item in the list.
|
||||
character after the last character in the list.
|
||||
|
||||
\sa constBegin(), end()
|
||||
*/
|
||||
|
@ -717,11 +717,41 @@ QQuaternion QQuaternion::fromAxes(const QVector3D &xAxis, const QVector3D &yAxis
|
||||
return QQuaternion::fromRotationMatrix(rot3x3);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.5
|
||||
|
||||
Constructs the quaternion using specified forward direction \a direction
|
||||
and upward direction \a up.
|
||||
If the upward direction was not specified or the forward and upward
|
||||
vectors are collinear, a new orthonormal upward direction will be generated.
|
||||
|
||||
\sa fromAxes(), rotationTo()
|
||||
*/
|
||||
QQuaternion QQuaternion::fromDirection(const QVector3D &direction, const QVector3D &up)
|
||||
{
|
||||
if (qFuzzyIsNull(direction.x()) && qFuzzyIsNull(direction.y()) && qFuzzyIsNull(direction.z()))
|
||||
return QQuaternion();
|
||||
|
||||
const QVector3D zAxis(direction.normalized());
|
||||
QVector3D xAxis(QVector3D::crossProduct(up, zAxis));
|
||||
if (qFuzzyIsNull(xAxis.lengthSquared())) {
|
||||
// collinear or invalid up vector; derive shortest arc to new direction
|
||||
return QQuaternion::rotationTo(QVector3D(0.0f, 0.0f, 1.0f), zAxis);
|
||||
}
|
||||
|
||||
xAxis.normalize();
|
||||
const QVector3D yAxis(QVector3D::crossProduct(zAxis, xAxis));
|
||||
|
||||
return QQuaternion::fromAxes(xAxis, yAxis, zAxis);
|
||||
}
|
||||
|
||||
/*!
|
||||
\since 5.5
|
||||
|
||||
Returns the shortest arc quaternion to rotate from the direction described by the vector \a from
|
||||
to the direction described by the vector \a to.
|
||||
|
||||
\sa fromDirection()
|
||||
*/
|
||||
QQuaternion QQuaternion::rotationTo(const QVector3D &from, const QVector3D &to)
|
||||
{
|
||||
|
@ -138,6 +138,8 @@ public:
|
||||
void getAxes(QVector3D *xAxis, QVector3D *yAxis, QVector3D *zAxis) const;
|
||||
static QQuaternion fromAxes(const QVector3D &xAxis, const QVector3D &yAxis, const QVector3D &zAxis);
|
||||
|
||||
static QQuaternion fromDirection(const QVector3D &direction, const QVector3D &up);
|
||||
|
||||
static QQuaternion rotationTo(const QVector3D &from, const QVector3D &to);
|
||||
#endif
|
||||
|
||||
|
@ -1484,8 +1484,10 @@ void QOpenGLFramebufferObject::blitFramebuffer(QOpenGLFramebufferObject *target,
|
||||
const int ty0 = targetRect.top();
|
||||
const int ty1 = targetRect.top() + targetRect.height();
|
||||
|
||||
extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : 0);
|
||||
extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : 0);
|
||||
const GLuint defaultFboId = ctx->defaultFramebufferObject();
|
||||
|
||||
extensions.glBindFramebuffer(GL_READ_FRAMEBUFFER, source ? source->handle() : defaultFboId);
|
||||
extensions.glBindFramebuffer(GL_DRAW_FRAMEBUFFER, target ? target->handle() : defaultFboId);
|
||||
|
||||
extensions.glBlitFramebuffer(sx0, sy0, sx1, sy1,
|
||||
tx0, ty0, tx1, ty1,
|
||||
|
@ -123,17 +123,6 @@ bool QTextureGlyphCache::populate(QFontEngine *fontEngine, int numGlyphs, const
|
||||
if (listItemCoordinates.contains(GlyphAndSubPixelPosition(glyph, subPixelPosition)))
|
||||
continue;
|
||||
|
||||
// This is a rather crude hack, but it works.
|
||||
// The FreeType font engine is not capable of getting precise metrics for the alphamap
|
||||
// without first rasterizing the glyph. If we force the glyph to be rasterized before
|
||||
// we ask for the alphaMapBoundingBox(), the glyph will be loaded, rasterized and its
|
||||
// proper metrics will be cached and used later.
|
||||
if (fontEngine->hasInternalCaching()) {
|
||||
QImage *locked = fontEngine->lockedAlphaMapForGlyph(glyph, subPixelPosition, m_format);
|
||||
if (locked && !locked->isNull())
|
||||
fontEngine->unlockAlphaMapForGlyph();
|
||||
}
|
||||
|
||||
glyph_metrics_t metrics = fontEngine->alphaMapBoundingBox(glyph, subPixelPosition, m_transform, m_format);
|
||||
|
||||
#ifdef CACHE_DEBUG
|
||||
|
@ -43,6 +43,7 @@
|
||||
|
||||
#include "qfile.h"
|
||||
#include "qfileinfo.h"
|
||||
#include <qscopedvaluerollback.h>
|
||||
#include "qthreadstorage.h"
|
||||
#include <qmath.h>
|
||||
|
||||
@ -800,6 +801,17 @@ int QFontEngineFT::loadFlags(QGlyphSet *set, GlyphFormat format, int flags,
|
||||
return load_flags;
|
||||
}
|
||||
|
||||
static inline bool areMetricsTooLarge(const QFontEngineFT::GlyphInfo &info)
|
||||
{
|
||||
// false if exceeds QFontEngineFT::Glyph metrics
|
||||
return (short)(info.linearAdvance) != info.linearAdvance
|
||||
|| (signed char)(info.xOff) != info.xOff
|
||||
|| (uchar)(info.width) != info.width
|
||||
|| (uchar)(info.height) != info.height
|
||||
|| (signed char)(info.x) != info.x
|
||||
|| (signed char)(info.y) != info.y;
|
||||
}
|
||||
|
||||
QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
QFixed subPixelPosition,
|
||||
GlyphFormat format,
|
||||
@ -807,13 +819,9 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
{
|
||||
// Q_ASSERT(freetype->lock == 1);
|
||||
|
||||
if (format == Format_None) {
|
||||
if (defaultFormat != Format_None) {
|
||||
format = defaultFormat;
|
||||
} else {
|
||||
format = Format_Mono;
|
||||
}
|
||||
}
|
||||
if (format == Format_None)
|
||||
format = defaultFormat != Format_None ? defaultFormat : Format_Mono;
|
||||
Q_ASSERT(format != Format_None);
|
||||
|
||||
Glyph *g = set ? set->getGlyph(glyph, subPixelPosition) : 0;
|
||||
if (g && g->format == format && (fetchMetricsOnly || g->data))
|
||||
@ -822,32 +830,28 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
if (!g && set && set->isGlyphMissing(glyph))
|
||||
return &emptyGlyph;
|
||||
|
||||
QFontEngineFT::GlyphInfo info;
|
||||
|
||||
Q_ASSERT(format != Format_None);
|
||||
FT_Face face = freetype->face;
|
||||
|
||||
FT_Matrix matrix = freetype->matrix;
|
||||
|
||||
FT_Vector v;
|
||||
v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.value());
|
||||
v.y = 0;
|
||||
FT_Set_Transform(face, &matrix, &v);
|
||||
|
||||
bool hsubpixel = false;
|
||||
int vfactor = 1;
|
||||
int load_flags = loadFlags(set, format, 0, hsubpixel, vfactor);
|
||||
|
||||
if (format != Format_Mono && !embeddedbitmap)
|
||||
load_flags |= FT_LOAD_NO_BITMAP;
|
||||
|
||||
FT_Matrix matrix = freetype->matrix;
|
||||
bool transform = matrix.xx != 0x10000
|
||||
|| matrix.yy != 0x10000
|
||||
|| matrix.xy != 0
|
||||
|| matrix.yx != 0;
|
||||
|
||||
if (transform)
|
||||
if (transform || (format != Format_Mono && !embeddedbitmap))
|
||||
load_flags |= FT_LOAD_NO_BITMAP;
|
||||
|
||||
FT_Face face = freetype->face;
|
||||
|
||||
FT_Vector v;
|
||||
v.x = format == Format_Mono ? 0 : FT_Pos(subPixelPosition.toReal() * 64);
|
||||
v.y = 0;
|
||||
FT_Set_Transform(face, &freetype->matrix, &v);
|
||||
|
||||
FT_Error err = FT_Load_Glyph(face, glyph, load_flags);
|
||||
if (err && (load_flags & FT_LOAD_NO_BITMAP)) {
|
||||
load_flags &= ~FT_LOAD_NO_BITMAP;
|
||||
@ -891,6 +895,8 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
FT_Matrix_Multiply(&m, &matrix);
|
||||
}
|
||||
|
||||
GlyphInfo info;
|
||||
info.linearAdvance = slot->linearHoriAdvance >> 10;
|
||||
info.xOff = TRUNC(ROUND(slot->advance.x));
|
||||
info.yOff = 0;
|
||||
|
||||
@ -899,27 +905,23 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
int right = CEIL(slot->metrics.horiBearingX + slot->metrics.width);
|
||||
int top = CEIL(slot->metrics.horiBearingY);
|
||||
int bottom = FLOOR(slot->metrics.horiBearingY - slot->metrics.height);
|
||||
int width = right-left;
|
||||
int height = top-bottom;
|
||||
info.x = TRUNC(left);
|
||||
info.y = TRUNC(top);
|
||||
info.width = TRUNC(right - left);
|
||||
info.height = TRUNC(top - bottom);
|
||||
|
||||
// If any of the metrics are too large to fit, don't cache them
|
||||
if (qAbs(info.xOff) >= 128
|
||||
|| qAbs(TRUNC(top)) >= 128
|
||||
|| TRUNC(width) >= 256
|
||||
|| TRUNC(height) >= 256
|
||||
|| qAbs(TRUNC(left)) >= 128
|
||||
|| qAbs(TRUNC(ROUND(slot->advance.x))) >= 128) {
|
||||
if (areMetricsTooLarge(info))
|
||||
return 0;
|
||||
}
|
||||
|
||||
g = new Glyph;
|
||||
g->data = 0;
|
||||
g->linearAdvance = slot->linearHoriAdvance >> 10;
|
||||
g->width = TRUNC(width);
|
||||
g->height = TRUNC(height);
|
||||
g->x = TRUNC(left);
|
||||
g->y = TRUNC(top);
|
||||
g->advance = TRUNC(ROUND(slot->advance.x));
|
||||
g->linearAdvance = info.linearAdvance;
|
||||
g->width = info.width;
|
||||
g->height = info.height;
|
||||
g->x = info.x;
|
||||
g->y = info.y;
|
||||
g->advance = info.xOff;
|
||||
g->format = format;
|
||||
|
||||
if (set)
|
||||
@ -948,7 +950,7 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
|
||||
info.height = slot->bitmap.rows / vfactor;
|
||||
info.width = hsubpixel ? slot->bitmap.width / 3 : slot->bitmap.width;
|
||||
info.x = -slot->bitmap_left;
|
||||
info.x = slot->bitmap_left;
|
||||
info.y = slot->bitmap_top;
|
||||
|
||||
glyph_buffer_size = info.width * info.height * 4;
|
||||
@ -1013,23 +1015,16 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
hpixels = hpixels*3 + 8;
|
||||
info.width = hpixels;
|
||||
info.height = TRUNC(top - bottom);
|
||||
info.x = -TRUNC(left);
|
||||
info.x = TRUNC(left);
|
||||
info.y = TRUNC(top);
|
||||
if (hsubpixel) {
|
||||
info.width /= 3;
|
||||
info.x += 1;
|
||||
info.x -= 1;
|
||||
}
|
||||
|
||||
bool large_glyph = (((short)(slot->linearHoriAdvance>>10) != slot->linearHoriAdvance>>10)
|
||||
|| ((uchar)(info.width) != info.width)
|
||||
|| ((uchar)(info.height) != info.height)
|
||||
|| ((signed char)(info.x) != info.x)
|
||||
|| ((signed char)(info.y) != info.y)
|
||||
|| ((signed char)(info.xOff) != info.xOff));
|
||||
|
||||
if (large_glyph) {
|
||||
// If any of the metrics are too large to fit, don't cache them
|
||||
if (areMetricsTooLarge(info))
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pitch = (format == Format_Mono ? ((info.width + 31) & ~31) >> 3 :
|
||||
(format == Format_A8 ? (info.width + 3) & ~3 : info.width * 4));
|
||||
@ -1142,10 +1137,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyph(QGlyphSet *set, uint glyph,
|
||||
g->data = 0;
|
||||
}
|
||||
|
||||
g->linearAdvance = slot->linearHoriAdvance >> 10;
|
||||
g->linearAdvance = info.linearAdvance;
|
||||
g->width = info.width;
|
||||
g->height = info.height;
|
||||
g->x = -info.x;
|
||||
g->x = info.x;
|
||||
g->y = info.y;
|
||||
g->advance = info.xOff;
|
||||
g->format = format;
|
||||
@ -1725,12 +1720,38 @@ glyph_metrics_t QFontEngineFT::alphaMapBoundingBox(glyph_t glyph, QFixed subPixe
|
||||
return overall;
|
||||
}
|
||||
|
||||
static inline QImage alphaMapFromGlyphData(QFontEngineFT::Glyph *glyph, QFontEngine::GlyphFormat glyphFormat)
|
||||
{
|
||||
if (glyph == Q_NULLPTR)
|
||||
return QImage();
|
||||
|
||||
QImage::Format format;
|
||||
int bytesPerLine;
|
||||
switch (glyphFormat) {
|
||||
case QFontEngine::Format_Mono:
|
||||
format = QImage::Format_Mono;
|
||||
bytesPerLine = ((glyph->width + 31) & ~31) >> 3;
|
||||
break;
|
||||
case QFontEngine::Format_A8:
|
||||
format = QImage::Format_Alpha8;
|
||||
bytesPerLine = (glyph->width + 3) & ~3;
|
||||
break;
|
||||
case QFontEngine::Format_A32:
|
||||
format = QImage::Format_ARGB32;
|
||||
bytesPerLine = glyph->width * 4;
|
||||
break;
|
||||
default:
|
||||
Q_UNREACHABLE();
|
||||
};
|
||||
|
||||
return QImage(static_cast<const uchar *>(glyph->data), glyph->width, glyph->height, bytesPerLine, format);
|
||||
}
|
||||
|
||||
QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixelPosition,
|
||||
QFontEngine::GlyphFormat neededFormat,
|
||||
const QTransform &t, QPoint *offset)
|
||||
{
|
||||
Q_ASSERT(currentlyLockedAlphaMap.isNull());
|
||||
lockFace();
|
||||
|
||||
if (isBitmapFont())
|
||||
neededFormat = Format_Mono;
|
||||
@ -1739,86 +1760,20 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe
|
||||
else if (neededFormat == Format_None)
|
||||
neededFormat = Format_A8;
|
||||
|
||||
QImage::Format format;
|
||||
switch (neededFormat) {
|
||||
case Format_Mono:
|
||||
format = QImage::Format_Mono;
|
||||
break;
|
||||
case Format_A8:
|
||||
format = QImage::Format_Alpha8;
|
||||
break;
|
||||
case Format_A32:
|
||||
format = QImage::Format_ARGB32;
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
format = QImage::Format_Invalid;
|
||||
};
|
||||
Glyph *glyph = loadGlyphFor(glyphIndex, subPixelPosition, neededFormat, t);
|
||||
|
||||
QFontEngineFT::Glyph *glyph;
|
||||
if (cacheEnabled) {
|
||||
QGlyphSet *gset = loadGlyphSet(t);
|
||||
QFontEngine::HintStyle hintStyle = default_hint_style;
|
||||
if (t.type() >= QTransform::TxScale) {
|
||||
// disable hinting if the glyphs are transformed
|
||||
default_hint_style = HintNone;
|
||||
}
|
||||
|
||||
if (gset) {
|
||||
FT_Matrix m = matrix;
|
||||
FT_Matrix_Multiply(&gset->transformationMatrix, &m);
|
||||
FT_Set_Transform(freetype->face, &m, 0);
|
||||
freetype->matrix = m;
|
||||
}
|
||||
|
||||
if (!gset || gset->outline_drawing || !(glyph = loadGlyph(gset, glyphIndex, subPixelPosition,
|
||||
neededFormat))) {
|
||||
default_hint_style = hintStyle;
|
||||
return QFontEngine::lockedAlphaMapForGlyph(glyphIndex, subPixelPosition, neededFormat, t,
|
||||
offset);
|
||||
}
|
||||
default_hint_style = hintStyle;
|
||||
} else {
|
||||
FT_Matrix m = matrix;
|
||||
FT_Matrix extra = QTransformToFTMatrix(t);
|
||||
FT_Matrix_Multiply(&extra, &m);
|
||||
FT_Set_Transform(freetype->face, &m, 0);
|
||||
freetype->matrix = m;
|
||||
glyph = loadGlyph(0, glyphIndex, subPixelPosition, neededFormat);
|
||||
}
|
||||
|
||||
if (glyph == 0 || glyph->data == 0 || glyph->width == 0 || glyph->height == 0) {
|
||||
if (!cacheEnabled && glyph != &emptyGlyph)
|
||||
delete glyph;
|
||||
unlockFace();
|
||||
return 0;
|
||||
}
|
||||
|
||||
int pitch;
|
||||
switch (neededFormat) {
|
||||
case Format_Mono:
|
||||
pitch = ((glyph->width + 31) & ~31) >> 3;
|
||||
break;
|
||||
case Format_A8:
|
||||
pitch = (glyph->width + 3) & ~3;
|
||||
break;
|
||||
case Format_A32:
|
||||
pitch = glyph->width * 4;
|
||||
break;
|
||||
default:
|
||||
Q_ASSERT(false);
|
||||
pitch = 0;
|
||||
};
|
||||
|
||||
if (offset != 0)
|
||||
if (offset != 0 && glyph != 0)
|
||||
*offset = QPoint(glyph->x, -glyph->y);
|
||||
|
||||
currentlyLockedAlphaMap = QImage(glyph->data, glyph->width, glyph->height, pitch, format);
|
||||
currentlyLockedAlphaMap = alphaMapFromGlyphData(glyph, neededFormat);
|
||||
|
||||
if (!cacheEnabled && glyph != &emptyGlyph) {
|
||||
currentlyLockedAlphaMap = currentlyLockedAlphaMap.copy();
|
||||
delete glyph;
|
||||
}
|
||||
Q_ASSERT(!currentlyLockedAlphaMap.isNull());
|
||||
|
||||
if (currentlyLockedAlphaMap.isNull())
|
||||
return QFontEngine::lockedAlphaMapForGlyph(glyphIndex, subPixelPosition, neededFormat, t, offset);
|
||||
|
||||
QImageData *data = currentlyLockedAlphaMap.data_ptr();
|
||||
data->is_locked = true;
|
||||
@ -1828,9 +1783,7 @@ QImage *QFontEngineFT::lockedAlphaMapForGlyph(glyph_t glyphIndex, QFixed subPixe
|
||||
|
||||
void QFontEngineFT::unlockAlphaMapForGlyph()
|
||||
{
|
||||
Q_ASSERT(!currentlyLockedAlphaMap.isNull());
|
||||
unlockFace();
|
||||
currentlyLockedAlphaMap = QImage();
|
||||
QFontEngine::unlockAlphaMapForGlyph();
|
||||
}
|
||||
|
||||
QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
|
||||
@ -1845,6 +1798,10 @@ QFontEngineFT::Glyph *QFontEngineFT::loadGlyphFor(glyph_t g,
|
||||
|
||||
Glyph *glyph = glyphSet != 0 ? glyphSet->getGlyph(g, subPixelPosition) : 0;
|
||||
if (!glyph || glyph->format != format || (!fetchBoundingBox && !glyph->data)) {
|
||||
QScopedValueRollback<HintStyle> saved_default_hint_style(default_hint_style);
|
||||
if (t.type() >= QTransform::TxScale)
|
||||
default_hint_style = HintNone; // disable hinting if the glyphs are transformed
|
||||
|
||||
lockFace();
|
||||
FT_Matrix m = this->matrix;
|
||||
FT_Matrix ftMatrix = glyphSet != 0 ? glyphSet->transformationMatrix : QTransformToFTMatrix(t);
|
||||
@ -1864,32 +1821,20 @@ QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition)
|
||||
|
||||
QImage QFontEngineFT::alphaMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
|
||||
{
|
||||
Glyph *glyph = loadGlyphFor(g, subPixelPosition, antialias ? Format_A8 : Format_Mono, t);
|
||||
if (!glyph || !glyph->data) {
|
||||
if (!cacheEnabled && glyph != &emptyGlyph)
|
||||
delete glyph;
|
||||
return QFontEngine::alphaMapForGlyph(g);
|
||||
}
|
||||
const GlyphFormat neededFormat = antialias ? Format_A8 : Format_Mono;
|
||||
|
||||
const int pitch = antialias ? (glyph->width + 3) & ~3 : ((glyph->width + 31)/32) * 4;
|
||||
Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t);
|
||||
|
||||
QImage img(glyph->width, glyph->height, antialias ? QImage::Format_Alpha8 : QImage::Format_Mono);
|
||||
if (!antialias) {
|
||||
QVector<QRgb> colors(2);
|
||||
colors[0] = qRgba(0, 0, 0, 0);
|
||||
colors[1] = qRgba(0, 0, 0, 255);
|
||||
img.setColorTable(colors);
|
||||
}
|
||||
Q_ASSERT(img.bytesPerLine() == pitch);
|
||||
if (glyph->width) {
|
||||
for (int y = 0; y < glyph->height; ++y)
|
||||
memcpy(img.scanLine(y), &glyph->data[y * pitch], pitch);
|
||||
}
|
||||
QImage img = alphaMapFromGlyphData(glyph, neededFormat);
|
||||
img = img.copy();
|
||||
|
||||
if (!cacheEnabled && glyph != &emptyGlyph)
|
||||
delete glyph;
|
||||
|
||||
return img;
|
||||
if (!img.isNull())
|
||||
return img;
|
||||
|
||||
return QFontEngine::alphaMapForGlyph(g);
|
||||
}
|
||||
|
||||
QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, const QTransform &t)
|
||||
@ -1897,20 +1842,20 @@ QImage QFontEngineFT::alphaRGBMapForGlyph(glyph_t g, QFixed subPixelPosition, co
|
||||
if (t.type() > QTransform::TxRotate)
|
||||
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
|
||||
|
||||
Glyph *glyph = loadGlyphFor(g, subPixelPosition, Format_A32, t);
|
||||
if (!glyph || !glyph->data) {
|
||||
if (!cacheEnabled && glyph != &emptyGlyph)
|
||||
delete glyph;
|
||||
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
|
||||
}
|
||||
const GlyphFormat neededFormat = Format_A32;
|
||||
|
||||
QImage img(glyph->width, glyph->height, QImage::Format_RGB32);
|
||||
memcpy(img.bits(), glyph->data, 4 * glyph->width * glyph->height);
|
||||
Glyph *glyph = loadGlyphFor(g, subPixelPosition, neededFormat, t);
|
||||
|
||||
QImage img = alphaMapFromGlyphData(glyph, neededFormat);
|
||||
img = img.copy();
|
||||
|
||||
if (!cacheEnabled && glyph != &emptyGlyph)
|
||||
delete glyph;
|
||||
|
||||
return img;
|
||||
if (!img.isNull())
|
||||
return img;
|
||||
|
||||
return QFontEngine::alphaRGBMapForGlyph(g, subPixelPosition, t);
|
||||
}
|
||||
|
||||
void QFontEngineFT::removeGlyphFromCache(glyph_t glyph)
|
||||
|
@ -143,6 +143,7 @@ public:
|
||||
};
|
||||
|
||||
struct GlyphInfo {
|
||||
int linearAdvance;
|
||||
unsigned short width;
|
||||
unsigned short height;
|
||||
short x;
|
||||
|
@ -1265,8 +1265,8 @@ bool QAbstractSocketPrivate::readFromSocket()
|
||||
bytesToRead = readBufferMaxSize - buffer.size();
|
||||
|
||||
#if defined(QABSTRACTSOCKET_DEBUG)
|
||||
qDebug("QAbstractSocketPrivate::readFromSocket() about to read %d bytes",
|
||||
int(bytesToRead));
|
||||
qDebug("QAbstractSocketPrivate::readFromSocket() about to read %lld bytes",
|
||||
bytesToRead);
|
||||
#endif
|
||||
|
||||
// Read from the socket, store data in the read buffer.
|
||||
@ -1277,10 +1277,10 @@ bool QAbstractSocketPrivate::readFromSocket()
|
||||
buffer.chop(bytesToRead);
|
||||
return true;
|
||||
}
|
||||
buffer.chop(int(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes)));
|
||||
buffer.chop(bytesToRead - (readBytes < 0 ? qint64(0) : readBytes));
|
||||
#if defined(QABSTRACTSOCKET_DEBUG)
|
||||
qDebug("QAbstractSocketPrivate::readFromSocket() got %d bytes, buffer size = %d",
|
||||
int(readBytes), buffer.size());
|
||||
qDebug("QAbstractSocketPrivate::readFromSocket() got %lld bytes, buffer size = %lld",
|
||||
readBytes, buffer.size());
|
||||
#endif
|
||||
|
||||
if (!socketEngine->isValid()) {
|
||||
@ -1726,7 +1726,7 @@ qint64 QAbstractSocket::bytesAvailable() const
|
||||
available += d->socketEngine->bytesAvailable();
|
||||
|
||||
#if defined(QABSTRACTSOCKET_DEBUG)
|
||||
qDebug("QAbstractSocket::bytesAvailable() == %llu", available);
|
||||
qDebug("QAbstractSocket::bytesAvailable() == %lld", available);
|
||||
#endif
|
||||
return available;
|
||||
}
|
||||
@ -1805,8 +1805,8 @@ bool QAbstractSocket::canReadLine() const
|
||||
{
|
||||
bool hasLine = d_func()->buffer.canReadLine();
|
||||
#if defined (QABSTRACTSOCKET_DEBUG)
|
||||
qDebug("QAbstractSocket::canReadLine() == %s, buffer size = %d, size = %d", hasLine ? "true" : "false",
|
||||
d_func()->buffer.size(), d_func()->buffer.size());
|
||||
qDebug("QAbstractSocket::canReadLine() == %s, buffer size = %lld, size = %lld",
|
||||
hasLine ? "true" : "false", d_func()->buffer.size(), d_func()->buffer.size());
|
||||
#endif
|
||||
return hasLine || QIODevice::canReadLine();
|
||||
}
|
||||
|
@ -303,8 +303,7 @@ namespace {
|
||||
, m_referenceCount(0)
|
||||
{
|
||||
}
|
||||
|
||||
~DirectWriteFontFileStream()
|
||||
virtual ~DirectWriteFontFileStream()
|
||||
{
|
||||
}
|
||||
|
||||
@ -355,7 +354,7 @@ namespace {
|
||||
OUT void **fragmentContext)
|
||||
{
|
||||
*fragmentContext = NULL;
|
||||
if (fragmentSize + fileOffset <= m_fontData.size()) {
|
||||
if (fileOffset + fragmentSize <= quint64(m_fontData.size())) {
|
||||
*fragmentStart = m_fontData.data() + fileOffset;
|
||||
return S_OK;
|
||||
} else {
|
||||
@ -384,8 +383,7 @@ namespace {
|
||||
{
|
||||
public:
|
||||
DirectWriteFontFileLoader() : m_referenceCount(0) {}
|
||||
|
||||
~DirectWriteFontFileLoader()
|
||||
virtual ~DirectWriteFontFileLoader()
|
||||
{
|
||||
}
|
||||
|
||||
@ -1104,18 +1102,14 @@ QFontEngine *QWindowsFontDatabase::fontEngine(const QByteArray &fontData, qreal
|
||||
GUID guid;
|
||||
CoCreateGuid(&guid);
|
||||
|
||||
#ifdef Q_CC_GNU
|
||||
# pragma GCC diagnostic push
|
||||
# pragma GCC diagnostic ignored "-Wstrict-aliasing"
|
||||
#endif
|
||||
QT_WARNING_PUSH
|
||||
QT_WARNING_DISABLE_GCC("-Wstrict-aliasing")
|
||||
QString uniqueFamilyName = QLatin1Char('f')
|
||||
+ QString::number(guid.Data1, 36) + QLatin1Char('-')
|
||||
+ QString::number(guid.Data2, 36) + QLatin1Char('-')
|
||||
+ QString::number(guid.Data3, 36) + QLatin1Char('-')
|
||||
+ QString::number(*reinterpret_cast<quint64 *>(guid.Data4), 36);
|
||||
#ifdef Q_CC_GNU
|
||||
# pragma GCC diagnostic pop
|
||||
#endif
|
||||
QT_WARNING_POP
|
||||
|
||||
QString actualFontName = font.changeFamilyName(uniqueFamilyName);
|
||||
if (actualFontName.isEmpty()) {
|
||||
|
@ -33,6 +33,10 @@
|
||||
|
||||
#ifndef QT_NO_DIRECTWRITE
|
||||
|
||||
#if WINVER < 0x0600
|
||||
# undef WINVER
|
||||
# define WINVER 0x0600
|
||||
#endif
|
||||
#if _WIN32_WINNT < 0x0600
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x0600
|
||||
@ -61,10 +65,14 @@ namespace {
|
||||
class GeometrySink: public IDWriteGeometrySink
|
||||
{
|
||||
public:
|
||||
GeometrySink(QPainterPath *path) : m_path(path), m_refCount(0)
|
||||
GeometrySink(QPainterPath *path)
|
||||
: m_refCount(0), m_path(path)
|
||||
{
|
||||
Q_ASSERT(m_path != 0);
|
||||
}
|
||||
virtual ~GeometrySink()
|
||||
{
|
||||
}
|
||||
|
||||
IFACEMETHOD_(void, AddBeziers)(const D2D1_BEZIER_SEGMENT *beziers, UINT bezierCount);
|
||||
IFACEMETHOD_(void, AddLines)(const D2D1_POINT_2F *points, UINT pointCount);
|
||||
|
@ -39,14 +39,12 @@
|
||||
# define DC_COLLATE 22
|
||||
#endif
|
||||
|
||||
#if defined (Q_CC_MINGW)
|
||||
# pragma GCC diagnostic ignored "-Wsign-compare"
|
||||
#endif
|
||||
|
||||
QT_BEGIN_NAMESPACE
|
||||
|
||||
#ifndef QT_NO_PRINTER
|
||||
|
||||
QT_WARNING_DISABLE_GCC("-Wsign-compare")
|
||||
|
||||
extern qreal qt_pointMultiplier(QPageLayout::Unit unit);
|
||||
|
||||
static inline uint qwcsnlen(const wchar_t *str, uint maxlen)
|
||||
|
@ -58,8 +58,9 @@
|
||||
- (NSString *)nameForLegacyLogging;
|
||||
@end
|
||||
|
||||
#pragma GCC diagnostic push // Ignore XCTestProbe deprecation
|
||||
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
|
||||
QT_WARNING_PUSH
|
||||
// Ignore XCTestProbe deprecation
|
||||
QT_WARNING_DISABLE_GCC("-Wdeprecated-declarations")
|
||||
|
||||
// ---------------------------------------------------------
|
||||
|
||||
@ -498,4 +499,4 @@ bool QXcodeTestLogger::isActive()
|
||||
return s_currentTestLogger;
|
||||
}
|
||||
|
||||
#pragma GCC diagnostic pop
|
||||
QT_WARNING_POP
|
||||
|
@ -149,7 +149,7 @@ QString Node::plainFullName(const Node* relative) const
|
||||
*/
|
||||
QString Node::fullName(const Node* relative) const
|
||||
{
|
||||
if (isDocumentNode())
|
||||
if ((isDocumentNode() || isGroup()) && !title().isEmpty())
|
||||
return title();
|
||||
return plainFullName(relative);
|
||||
}
|
||||
|
@ -2036,6 +2036,8 @@ void QTabBar::wheelEvent(QWheelEvent *event)
|
||||
int offset = event->delta() > 0 ? -1 : 1;
|
||||
d->setCurrentNextEnabledIndex(offset);
|
||||
QWidget::wheelEvent(event);
|
||||
#else
|
||||
Q_UNUSED(event)
|
||||
#endif
|
||||
}
|
||||
#endif //QT_NO_WHEELEVENT
|
||||
|
@ -119,6 +119,14 @@ void tst_QSaveFile::transactionalWrite()
|
||||
QFile reader(targetFile);
|
||||
QVERIFY(reader.open(QIODevice::ReadOnly));
|
||||
QCOMPARE(QString::fromLatin1(reader.readAll()), QString::fromLatin1("Hello"));
|
||||
|
||||
// check that permissions are the same as for QFile
|
||||
const QString otherFile = dir.path() + QString::fromLatin1("/otherfile");
|
||||
QFile::remove(otherFile);
|
||||
QFile other(otherFile);
|
||||
other.open(QIODevice::WriteOnly);
|
||||
other.close();
|
||||
QCOMPARE(QFile::permissions(targetFile), QFile::permissions(otherFile));
|
||||
}
|
||||
|
||||
void tst_QSaveFile::saveTwice()
|
||||
|
@ -141,6 +141,9 @@ private slots:
|
||||
void rotationTo_data();
|
||||
void rotationTo();
|
||||
|
||||
void fromDirection_data();
|
||||
void fromDirection();
|
||||
|
||||
void fromEulerAngles_data();
|
||||
void fromEulerAngles();
|
||||
|
||||
@ -989,6 +992,97 @@ void tst_QQuaternion::rotationTo()
|
||||
QVERIFY(myFuzzyCompare(vec2, from));
|
||||
}
|
||||
|
||||
static QByteArray testnameForAxis(const QVector3D &axis)
|
||||
{
|
||||
QByteArray testname;
|
||||
if (axis == QVector3D()) {
|
||||
testname = "null";
|
||||
} else {
|
||||
if (axis.x()) {
|
||||
testname += axis.x() < 0 ? "-" : "+";
|
||||
testname += "X";
|
||||
}
|
||||
if (axis.y()) {
|
||||
testname += axis.y() < 0 ? "-" : "+";
|
||||
testname += "Y";
|
||||
}
|
||||
if (axis.z()) {
|
||||
testname += axis.z() < 0 ? "-" : "+";
|
||||
testname += "Z";
|
||||
}
|
||||
}
|
||||
return testname;
|
||||
}
|
||||
|
||||
// Test quaternion convertion to and from orthonormal axes.
|
||||
void tst_QQuaternion::fromDirection_data()
|
||||
{
|
||||
QTest::addColumn<QVector3D>("direction");
|
||||
QTest::addColumn<QVector3D>("up");
|
||||
|
||||
QList<QQuaternion> orientations;
|
||||
orientations << QQuaternion();
|
||||
for (int angle = 45; angle <= 360; angle += 45) {
|
||||
orientations << QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), angle)
|
||||
<< QQuaternion::fromAxisAndAngle(QVector3D(0, 1, 0), angle)
|
||||
<< QQuaternion::fromAxisAndAngle(QVector3D(0, 0, 1), angle)
|
||||
<< QQuaternion::fromAxisAndAngle(QVector3D(1, 0, 0), angle)
|
||||
* QQuaternion::fromAxisAndAngle(QVector3D(0, 1, 0), angle)
|
||||
* QQuaternion::fromAxisAndAngle(QVector3D(0, 0, 1), angle);
|
||||
}
|
||||
|
||||
// othonormal up and dir
|
||||
foreach (const QQuaternion &q, orientations) {
|
||||
QVector3D xAxis, yAxis, zAxis;
|
||||
q.getAxes(&xAxis, &yAxis, &zAxis);
|
||||
|
||||
QTest::newRow("dir: " + testnameForAxis(zAxis) + ", up: " + testnameForAxis(yAxis))
|
||||
<< zAxis * 10.0f << yAxis * 10.0f;
|
||||
}
|
||||
|
||||
// collinear up and dir
|
||||
QTest::newRow("dir: +X, up: +X") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(10.0f, 0.0f, 0.0f);
|
||||
QTest::newRow("dir: +X, up: -X") << QVector3D(10.0f, 0.0f, 0.0f) << QVector3D(-10.0f, 0.0f, 0.0f);
|
||||
QTest::newRow("dir: +Y, up: +Y") << QVector3D(0.0f, 10.0f, 0.0f) << QVector3D(0.0f, 10.0f, 0.0f);
|
||||
QTest::newRow("dir: +Y, up: -Y") << QVector3D(0.0f, 10.0f, 0.0f) << QVector3D(0.0f, -10.0f, 0.0f);
|
||||
QTest::newRow("dir: +Z, up: +Z") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, 0.0f, 10.0f);
|
||||
QTest::newRow("dir: +Z, up: -Z") << QVector3D(0.0f, 0.0f, 10.0f) << QVector3D(0.0f, 0.0f, -10.0f);
|
||||
QTest::newRow("dir: +X+Y+Z, up: +X+Y+Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(10.0f, 10.0f, 10.0f);
|
||||
QTest::newRow("dir: +X+Y+Z, up: -X-Y-Z") << QVector3D(10.0f, 10.0f, 10.0f) << QVector3D(-10.0f, -10.0f, -10.0f);
|
||||
|
||||
// invalid up
|
||||
foreach (const QQuaternion &q, orientations) {
|
||||
QVector3D xAxis, yAxis, zAxis;
|
||||
q.getAxes(&xAxis, &yAxis, &zAxis);
|
||||
|
||||
QTest::newRow("dir: " + testnameForAxis(zAxis) + ", up: null")
|
||||
<< zAxis * 10.0f << QVector3D();
|
||||
}
|
||||
}
|
||||
void tst_QQuaternion::fromDirection()
|
||||
{
|
||||
QFETCH(QVector3D, direction);
|
||||
QFETCH(QVector3D, up);
|
||||
|
||||
QVector3D expextedZ(direction != QVector3D() ? direction.normalized() : QVector3D(0, 0, 1));
|
||||
QVector3D expextedY(up.normalized());
|
||||
|
||||
QQuaternion result = QQuaternion::fromDirection(direction, up);
|
||||
QVERIFY(myFuzzyCompare(result, result.normalized()));
|
||||
|
||||
QVector3D xAxis, yAxis, zAxis;
|
||||
result.getAxes(&xAxis, &yAxis, &zAxis);
|
||||
|
||||
QVERIFY(myFuzzyCompare(zAxis, expextedZ));
|
||||
|
||||
if (!qFuzzyIsNull(QVector3D::crossProduct(expextedZ, expextedY).lengthSquared())) {
|
||||
QVector3D expextedX(QVector3D::crossProduct(expextedY, expextedZ));
|
||||
|
||||
QVERIFY(myFuzzyCompare(yAxis, expextedY));
|
||||
QVERIFY(myFuzzyCompare(xAxis, expextedX));
|
||||
}
|
||||
}
|
||||
|
||||
// Test quaternion creation from an axis and an angle.
|
||||
void tst_QQuaternion::fromEulerAngles_data()
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user