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

Change-Id: I04f9f2749f68c0cb5a427b8d84e43b44bb143e4d
This commit is contained in:
Liang Qi 2015-04-08 21:24:25 +02:00
commit 4973786f0d
32 changed files with 437 additions and 314 deletions

11
configure vendored
View File

@ -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"

View File

@ -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

View File

@ -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;";
}
}
}

View File

@ -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.

View File

@ -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}
*/

View File

@ -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}
*/

View File

@ -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}
*/

View File

@ -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;
}

View File

@ -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();

View File

@ -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;
}

View File

@ -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;
};

View File

@ -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];

View File

@ -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)

View File

@ -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;

View File

@ -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

View File

@ -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(); }

View File

@ -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()
*/

View File

@ -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)
{

View File

@ -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

View File

@ -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,

View File

@ -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

View File

@ -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)

View File

@ -143,6 +143,7 @@ public:
};
struct GlyphInfo {
int linearAdvance;
unsigned short width;
unsigned short height;
short x;

View File

@ -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();
}

View File

@ -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()) {

View File

@ -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);

View File

@ -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)

View File

@ -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

View File

@ -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);
}

View File

@ -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

View File

@ -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()

View File

@ -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()
{