Merge remote-tracking branch 'origin/5.14' into 5.15
Conflicts: src/corelib/plugin/qlibrary.cpp src/corelib/plugin/qlibrary_unix.cpp src/corelib/plugin/qpluginloader.cpp Change-Id: I866feaaa2a4936ee5389679724c8471a5b4b583d
This commit is contained in:
commit
116d68f105
@ -50,8 +50,12 @@
|
|||||||
|
|
||||||
#include "printview.h"
|
#include "printview.h"
|
||||||
|
|
||||||
#ifndef QT_NO_PRINTER
|
#if defined(QT_PRINTSUPPORT_LIB)
|
||||||
#include <QPrinter>
|
# include <QtPrintSupport/qtprintsupportglobal.h>
|
||||||
|
|
||||||
|
# if QT_CONFIG(printer)
|
||||||
|
# include <QPrinter>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
PrintView::PrintView()
|
PrintView::PrintView()
|
||||||
@ -62,9 +66,11 @@ PrintView::PrintView()
|
|||||||
|
|
||||||
void PrintView::print(QPrinter *printer)
|
void PrintView::print(QPrinter *printer)
|
||||||
{
|
{
|
||||||
#ifndef QT_NO_PRINTER
|
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
|
||||||
resize(printer->width(), printer->height());
|
resize(printer->width(), printer->height());
|
||||||
render(printer);
|
render(printer);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(printer)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -638,7 +638,7 @@ QString encode_pos(int row, int col)
|
|||||||
|
|
||||||
void SpreadSheet::print()
|
void SpreadSheet::print()
|
||||||
{
|
{
|
||||||
#if QT_CONFIG(printpreviewdialog)
|
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog)
|
||||||
QPrinter printer(QPrinter::ScreenResolution);
|
QPrinter printer(QPrinter::ScreenResolution);
|
||||||
QPrintPreviewDialog dlg(&printer);
|
QPrintPreviewDialog dlg(&printer);
|
||||||
PrintView view;
|
PrintView view;
|
||||||
|
@ -197,7 +197,7 @@ void TextEdit::setupFileActions()
|
|||||||
a->setPriority(QAction::LowPriority);
|
a->setPriority(QAction::LowPriority);
|
||||||
menu->addSeparator();
|
menu->addSeparator();
|
||||||
|
|
||||||
#ifndef QT_NO_PRINTER
|
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
|
||||||
const QIcon printIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png"));
|
const QIcon printIcon = QIcon::fromTheme("document-print", QIcon(rsrcPath + "/fileprint.png"));
|
||||||
a = menu->addAction(printIcon, tr("&Print..."), this, &TextEdit::filePrint);
|
a = menu->addAction(printIcon, tr("&Print..."), this, &TextEdit::filePrint);
|
||||||
a->setPriority(QAction::LowPriority);
|
a->setPriority(QAction::LowPriority);
|
||||||
@ -559,7 +559,7 @@ void TextEdit::filePrint()
|
|||||||
|
|
||||||
void TextEdit::filePrintPreview()
|
void TextEdit::filePrintPreview()
|
||||||
{
|
{
|
||||||
#if QT_CONFIG(printpreviewdialog)
|
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printpreviewdialog)
|
||||||
QPrinter printer(QPrinter::HighResolution);
|
QPrinter printer(QPrinter::HighResolution);
|
||||||
QPrintPreviewDialog preview(&printer, this);
|
QPrintPreviewDialog preview(&printer, this);
|
||||||
connect(&preview, &QPrintPreviewDialog::paintRequested, this, &TextEdit::printPreview);
|
connect(&preview, &QPrintPreviewDialog::paintRequested, this, &TextEdit::printPreview);
|
||||||
@ -569,17 +569,17 @@ void TextEdit::filePrintPreview()
|
|||||||
|
|
||||||
void TextEdit::printPreview(QPrinter *printer)
|
void TextEdit::printPreview(QPrinter *printer)
|
||||||
{
|
{
|
||||||
#ifdef QT_NO_PRINTER
|
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
|
||||||
Q_UNUSED(printer);
|
|
||||||
#else
|
|
||||||
textEdit->print(printer);
|
textEdit->print(printer);
|
||||||
|
#else
|
||||||
|
Q_UNUSED(printer)
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
void TextEdit::filePrintPdf()
|
void TextEdit::filePrintPdf()
|
||||||
{
|
{
|
||||||
#ifndef QT_NO_PRINTER
|
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
|
||||||
//! [0]
|
//! [0]
|
||||||
QFileDialog fileDialog(this, tr("Export PDF"));
|
QFileDialog fileDialog(this, tr("Export PDF"));
|
||||||
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
|
fileDialog.setAcceptMode(QFileDialog::AcceptSave);
|
||||||
|
@ -1,6 +1,8 @@
|
|||||||
TEMPLATE = app
|
TEMPLATE = app
|
||||||
TARGET = notepad
|
TARGET = notepad
|
||||||
|
|
||||||
|
QT += widgets
|
||||||
|
|
||||||
qtHaveModule(printsupport): QT += printsupport
|
qtHaveModule(printsupport): QT += printsupport
|
||||||
requires(qtConfig(fontdialog))
|
requires(qtConfig(fontdialog))
|
||||||
|
|
||||||
|
@ -69,10 +69,11 @@
|
|||||||
#include <QStatusBar>
|
#include <QStatusBar>
|
||||||
|
|
||||||
#if defined(QT_PRINTSUPPORT_LIB)
|
#if defined(QT_PRINTSUPPORT_LIB)
|
||||||
#include <QtPrintSupport/qtprintsupportglobal.h>
|
# include <QtPrintSupport/qtprintsupportglobal.h>
|
||||||
#if QT_CONFIG(printdialog)
|
|
||||||
#include <QPrintDialog>
|
# if QT_CONFIG(printdialog)
|
||||||
#endif
|
# include <QPrintDialog>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
//! [0]
|
//! [0]
|
||||||
|
@ -53,8 +53,12 @@
|
|||||||
|
|
||||||
#include <QMainWindow>
|
#include <QMainWindow>
|
||||||
#include <QImage>
|
#include <QImage>
|
||||||
#ifndef QT_NO_PRINTER
|
#if defined(QT_PRINTSUPPORT_LIB)
|
||||||
#include <QPrinter>
|
# include <QtPrintSupport/qtprintsupportglobal.h>
|
||||||
|
|
||||||
|
# if QT_CONFIG(printer)
|
||||||
|
# include <QPrinter>
|
||||||
|
# endif
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
@ -100,7 +104,7 @@ private:
|
|||||||
QScrollArea *scrollArea;
|
QScrollArea *scrollArea;
|
||||||
double scaleFactor = 1;
|
double scaleFactor = 1;
|
||||||
|
|
||||||
#ifndef QT_NO_PRINTER
|
#if defined(QT_PRINTSUPPORT_LIB) && QT_CONFIG(printer)
|
||||||
QPrinter printer;
|
QPrinter printer;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
@ -1949,8 +1949,9 @@ void QSortFilterProxyModelPrivate::_q_sourceColumnsMoved(
|
|||||||
example.)
|
example.)
|
||||||
|
|
||||||
If you are working with large amounts of filtering and have to invoke
|
If you are working with large amounts of filtering and have to invoke
|
||||||
invalidateFilter() repeatedly, using reset() may be more efficient,
|
invalidateFilter() repeatedly, using beginResetModel() / endResetModel() may
|
||||||
depending on the implementation of your model. However, reset() returns the
|
be more efficient, depending on the implementation of your model. However,
|
||||||
|
beginResetModel() / endResetModel() returns the
|
||||||
proxy model to its original state, losing selection information, and will
|
proxy model to its original state, losing selection information, and will
|
||||||
cause the proxy model to be repopulated.
|
cause the proxy model to be repopulated.
|
||||||
|
|
||||||
|
@ -615,7 +615,8 @@ QMetaTypeComparatorRegistry;
|
|||||||
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
|
typedef QMetaTypeFunctionRegistry<QtPrivate::AbstractDebugStreamFunction,int>
|
||||||
QMetaTypeDebugStreamRegistry;
|
QMetaTypeDebugStreamRegistry;
|
||||||
|
|
||||||
Q_STATIC_ASSERT(std::is_pod<QMetaTypeInterface>::value);
|
Q_STATIC_ASSERT(std::is_trivial<QMetaTypeInterface>::value);
|
||||||
|
Q_STATIC_ASSERT(std::is_standard_layout<QMetaTypeInterface>::value);
|
||||||
|
|
||||||
Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
|
Q_DECLARE_TYPEINFO(QCustomTypeInfo, Q_MOVABLE_TYPE);
|
||||||
Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
|
Q_GLOBAL_STATIC(QVector<QCustomTypeInfo>, customTypes)
|
||||||
|
@ -389,16 +389,11 @@ QObject *QFactoryLoader::instance(int index) const
|
|||||||
QMutexLocker lock(&d->mutex);
|
QMutexLocker lock(&d->mutex);
|
||||||
if (index < d->libraryList.size()) {
|
if (index < d->libraryList.size()) {
|
||||||
QLibraryPrivate *library = d->libraryList.at(index);
|
QLibraryPrivate *library = d->libraryList.at(index);
|
||||||
if (library->instance || library->loadPlugin()) {
|
if (QObject *obj = library->pluginInstance()) {
|
||||||
if (!library->inst)
|
|
||||||
library->inst = library->instance();
|
|
||||||
QObject *obj = library->inst.data();
|
|
||||||
if (obj) {
|
|
||||||
if (!obj->parent())
|
if (!obj->parent())
|
||||||
obj->moveToThread(QCoreApplicationPrivate::mainThread());
|
obj->moveToThread(QCoreApplicationPrivate::mainThread());
|
||||||
return obj;
|
return obj;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
index -= d->libraryList.size();
|
index -= d->libraryList.size();
|
||||||
|
@ -407,7 +407,7 @@ inline void QLibraryStore::cleanup()
|
|||||||
QLibraryPrivate *lib = it.value();
|
QLibraryPrivate *lib = it.value();
|
||||||
if (lib->libraryRefCount.loadRelaxed() == 1) {
|
if (lib->libraryRefCount.loadRelaxed() == 1) {
|
||||||
if (lib->libraryUnloadCount.loadRelaxed() > 0) {
|
if (lib->libraryUnloadCount.loadRelaxed() > 0) {
|
||||||
Q_ASSERT(lib->pHnd);
|
Q_ASSERT(lib->pHnd.loadRelaxed());
|
||||||
lib->libraryUnloadCount.storeRelaxed(1);
|
lib->libraryUnloadCount.storeRelaxed(1);
|
||||||
#ifdef __GLIBC__
|
#ifdef __GLIBC__
|
||||||
// glibc has a bug in unloading from global destructors
|
// glibc has a bug in unloading from global destructors
|
||||||
@ -498,8 +498,7 @@ inline void QLibraryStore::releaseLibrary(QLibraryPrivate *lib)
|
|||||||
}
|
}
|
||||||
|
|
||||||
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
|
QLibraryPrivate::QLibraryPrivate(const QString &canonicalFileName, const QString &version, QLibrary::LoadHints loadHints)
|
||||||
: pHnd(nullptr), fileName(canonicalFileName), fullVersion(version), instance(nullptr),
|
: fileName(canonicalFileName), fullVersion(version), pluginState(MightBeAPlugin)
|
||||||
libraryRefCount(0), libraryUnloadCount(0), pluginState(MightBeAPlugin)
|
|
||||||
{
|
{
|
||||||
loadHintsInt.storeRelaxed(loadHints);
|
loadHintsInt.storeRelaxed(loadHints);
|
||||||
if (canonicalFileName.isEmpty())
|
if (canonicalFileName.isEmpty())
|
||||||
@ -519,7 +518,7 @@ QLibraryPrivate::~QLibraryPrivate()
|
|||||||
void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
|
void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
|
||||||
{
|
{
|
||||||
// if the library is already loaded, we can't change the load hints
|
// if the library is already loaded, we can't change the load hints
|
||||||
if (pHnd)
|
if (pHnd.loadRelaxed())
|
||||||
return;
|
return;
|
||||||
|
|
||||||
loadHintsInt.storeRelaxed(lh);
|
loadHintsInt.storeRelaxed(lh);
|
||||||
@ -527,7 +526,7 @@ void QLibraryPrivate::mergeLoadHints(QLibrary::LoadHints lh)
|
|||||||
|
|
||||||
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
|
QFunctionPointer QLibraryPrivate::resolve(const char *symbol)
|
||||||
{
|
{
|
||||||
if (!pHnd)
|
if (!pHnd.loadRelaxed())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
return resolve_sys(symbol);
|
return resolve_sys(symbol);
|
||||||
}
|
}
|
||||||
@ -539,9 +538,36 @@ void QLibraryPrivate::setLoadHints(QLibrary::LoadHints lh)
|
|||||||
mergeLoadHints(lh);
|
mergeLoadHints(lh);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
QObject *QLibraryPrivate::pluginInstance()
|
||||||
|
{
|
||||||
|
// first, check if the instance is cached and hasn't been deleted
|
||||||
|
QObject *obj = (QMutexLocker(&mutex), inst.data());
|
||||||
|
if (obj)
|
||||||
|
return obj;
|
||||||
|
|
||||||
|
// We need to call the plugin's factory function. Is that cached?
|
||||||
|
// skip increasing the reference count (why? -Thiago)
|
||||||
|
QtPluginInstanceFunction factory = instanceFactory.loadAcquire();
|
||||||
|
if (!factory)
|
||||||
|
factory = loadPlugin();
|
||||||
|
|
||||||
|
if (!factory)
|
||||||
|
return nullptr;
|
||||||
|
|
||||||
|
obj = factory();
|
||||||
|
|
||||||
|
// cache again
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
|
if (inst)
|
||||||
|
obj = inst;
|
||||||
|
else
|
||||||
|
inst = obj;
|
||||||
|
return obj;
|
||||||
|
}
|
||||||
|
|
||||||
bool QLibraryPrivate::load()
|
bool QLibraryPrivate::load()
|
||||||
{
|
{
|
||||||
if (pHnd) {
|
if (pHnd.loadRelaxed()) {
|
||||||
libraryUnloadCount.ref();
|
libraryUnloadCount.ref();
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
@ -550,7 +576,9 @@ bool QLibraryPrivate::load()
|
|||||||
|
|
||||||
Q_TRACE(QLibraryPrivate_load_entry, fileName);
|
Q_TRACE(QLibraryPrivate_load_entry, fileName);
|
||||||
|
|
||||||
|
mutex.lock();
|
||||||
bool ret = load_sys();
|
bool ret = load_sys();
|
||||||
|
mutex.unlock();
|
||||||
if (qt_debug_component()) {
|
if (qt_debug_component()) {
|
||||||
if (ret) {
|
if (ret) {
|
||||||
qDebug() << "loaded library" << fileName;
|
qDebug() << "loaded library" << fileName;
|
||||||
@ -573,9 +601,10 @@ bool QLibraryPrivate::load()
|
|||||||
|
|
||||||
bool QLibraryPrivate::unload(UnloadFlag flag)
|
bool QLibraryPrivate::unload(UnloadFlag flag)
|
||||||
{
|
{
|
||||||
if (!pHnd)
|
if (!pHnd.loadRelaxed())
|
||||||
return false;
|
return false;
|
||||||
if (libraryUnloadCount.loadRelaxed() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
|
if (libraryUnloadCount.loadRelaxed() > 0 && !libraryUnloadCount.deref()) { // only unload if ALL QLibrary instance wanted to
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
delete inst.data();
|
delete inst.data();
|
||||||
if (flag == NoUnloadSys || unload_sys()) {
|
if (flag == NoUnloadSys || unload_sys()) {
|
||||||
if (qt_debug_component())
|
if (qt_debug_component())
|
||||||
@ -584,12 +613,13 @@ bool QLibraryPrivate::unload(UnloadFlag flag)
|
|||||||
//when the library is unloaded, we release the reference on it so that 'this'
|
//when the library is unloaded, we release the reference on it so that 'this'
|
||||||
//can get deleted
|
//can get deleted
|
||||||
libraryRefCount.deref();
|
libraryRefCount.deref();
|
||||||
pHnd = nullptr;
|
pHnd.storeRelaxed(nullptr);
|
||||||
instance = nullptr;
|
instanceFactory.storeRelaxed(nullptr);
|
||||||
|
return true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return (pHnd == nullptr);
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void QLibraryPrivate::release()
|
void QLibraryPrivate::release()
|
||||||
@ -597,22 +627,23 @@ void QLibraryPrivate::release()
|
|||||||
QLibraryStore::releaseLibrary(this);
|
QLibraryStore::releaseLibrary(this);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QLibraryPrivate::loadPlugin()
|
QtPluginInstanceFunction QLibraryPrivate::loadPlugin()
|
||||||
{
|
{
|
||||||
if (instance) {
|
if (auto ptr = instanceFactory.loadAcquire()) {
|
||||||
libraryUnloadCount.ref();
|
libraryUnloadCount.ref();
|
||||||
return true;
|
return ptr;
|
||||||
}
|
}
|
||||||
if (pluginState == IsNotAPlugin)
|
if (pluginState == IsNotAPlugin)
|
||||||
return false;
|
return nullptr;
|
||||||
if (load()) {
|
if (load()) {
|
||||||
instance = (QtPluginInstanceFunction)resolve("qt_plugin_instance");
|
auto ptr = reinterpret_cast<QtPluginInstanceFunction>(resolve("qt_plugin_instance"));
|
||||||
return instance;
|
instanceFactory.storeRelease(ptr); // two threads may store the same value
|
||||||
|
return ptr;
|
||||||
}
|
}
|
||||||
if (qt_debug_component())
|
if (qt_debug_component())
|
||||||
qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
|
qWarning() << "QLibraryPrivate::loadPlugin failed on" << fileName << ":" << errorString;
|
||||||
pluginState = IsNotAPlugin;
|
pluginState = IsNotAPlugin;
|
||||||
return false;
|
return nullptr;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -719,6 +750,7 @@ bool QLibraryPrivate::isPlugin()
|
|||||||
|
|
||||||
void QLibraryPrivate::updatePluginState()
|
void QLibraryPrivate::updatePluginState()
|
||||||
{
|
{
|
||||||
|
QMutexLocker locker(&mutex);
|
||||||
errorString.clear();
|
errorString.clear();
|
||||||
if (pluginState != MightBeAPlugin)
|
if (pluginState != MightBeAPlugin)
|
||||||
return;
|
return;
|
||||||
@ -739,7 +771,7 @@ void QLibraryPrivate::updatePluginState()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!pHnd) {
|
if (!pHnd.loadRelaxed()) {
|
||||||
// scan for the plugin metadata without loading
|
// scan for the plugin metadata without loading
|
||||||
success = findPatternUnloaded(fileName, this);
|
success = findPatternUnloaded(fileName, this);
|
||||||
} else {
|
} else {
|
||||||
@ -803,7 +835,7 @@ bool QLibrary::load()
|
|||||||
if (!d)
|
if (!d)
|
||||||
return false;
|
return false;
|
||||||
if (did_load)
|
if (did_load)
|
||||||
return d->pHnd;
|
return d->pHnd.loadRelaxed();
|
||||||
did_load = true;
|
did_load = true;
|
||||||
return d->load();
|
return d->load();
|
||||||
}
|
}
|
||||||
@ -839,7 +871,7 @@ bool QLibrary::unload()
|
|||||||
*/
|
*/
|
||||||
bool QLibrary::isLoaded() const
|
bool QLibrary::isLoaded() const
|
||||||
{
|
{
|
||||||
return d && d->pHnd;
|
return d && d->pHnd.loadRelaxed();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
@ -950,8 +982,10 @@ void QLibrary::setFileName(const QString &fileName)
|
|||||||
|
|
||||||
QString QLibrary::fileName() const
|
QString QLibrary::fileName() const
|
||||||
{
|
{
|
||||||
if (d)
|
if (d) {
|
||||||
|
QMutexLocker locker(&d->mutex);
|
||||||
return d->qualifiedFileName.isEmpty() ? d->fileName : d->qualifiedFileName;
|
return d->qualifiedFileName.isEmpty() ? d->fileName : d->qualifiedFileName;
|
||||||
|
}
|
||||||
return QString();
|
return QString();
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1092,7 +1126,12 @@ QFunctionPointer QLibrary::resolve(const QString &fileName, const QString &versi
|
|||||||
*/
|
*/
|
||||||
QString QLibrary::errorString() const
|
QString QLibrary::errorString() const
|
||||||
{
|
{
|
||||||
return (!d || d->errorString.isEmpty()) ? tr("Unknown error") : d->errorString;
|
QString str;
|
||||||
|
if (d) {
|
||||||
|
QMutexLocker locker(&d->mutex);
|
||||||
|
str = d->errorString;
|
||||||
|
}
|
||||||
|
return str.isEmpty() ? tr("Unknown error") : str;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
|
@ -54,10 +54,10 @@
|
|||||||
|
|
||||||
#include <QtCore/private/qglobal_p.h>
|
#include <QtCore/private/qglobal_p.h>
|
||||||
#include "QtCore/qlibrary.h"
|
#include "QtCore/qlibrary.h"
|
||||||
|
#include "QtCore/qmutex.h"
|
||||||
#include "QtCore/qpointer.h"
|
#include "QtCore/qpointer.h"
|
||||||
#include "QtCore/qstringlist.h"
|
#include "QtCore/qstringlist.h"
|
||||||
#include "QtCore/qplugin.h"
|
#include "QtCore/qplugin.h"
|
||||||
#include "QtCore/qsharedpointer.h"
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
# include "QtCore/qt_windows.h"
|
# include "QtCore/qt_windows.h"
|
||||||
#endif
|
#endif
|
||||||
@ -72,21 +72,18 @@ class QLibraryStore;
|
|||||||
class QLibraryPrivate
|
class QLibraryPrivate
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
HINSTANCE
|
using Handle = HINSTANCE;
|
||||||
#else
|
#else
|
||||||
void *
|
using Handle = void *;
|
||||||
#endif
|
#endif
|
||||||
pHnd;
|
|
||||||
|
|
||||||
enum UnloadFlag { UnloadSys, NoUnloadSys };
|
enum UnloadFlag { UnloadSys, NoUnloadSys };
|
||||||
|
|
||||||
QString fileName, qualifiedFileName;
|
const QString fileName;
|
||||||
QString fullVersion;
|
const QString fullVersion;
|
||||||
|
|
||||||
bool load();
|
bool load();
|
||||||
bool loadPlugin(); // loads and resolves instance
|
QtPluginInstanceFunction loadPlugin(); // loads and resolves instance
|
||||||
bool unload(UnloadFlag flag = UnloadSys);
|
bool unload(UnloadFlag flag = UnloadSys);
|
||||||
void release();
|
void release();
|
||||||
QFunctionPointer resolve(const char *);
|
QFunctionPointer resolve(const char *);
|
||||||
@ -94,17 +91,22 @@ public:
|
|||||||
QLibrary::LoadHints loadHints() const
|
QLibrary::LoadHints loadHints() const
|
||||||
{ return QLibrary::LoadHints(loadHintsInt.loadRelaxed()); }
|
{ return QLibrary::LoadHints(loadHintsInt.loadRelaxed()); }
|
||||||
void setLoadHints(QLibrary::LoadHints lh);
|
void setLoadHints(QLibrary::LoadHints lh);
|
||||||
|
QObject *pluginInstance();
|
||||||
|
|
||||||
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
|
static QLibraryPrivate *findOrCreate(const QString &fileName, const QString &version = QString(),
|
||||||
QLibrary::LoadHints loadHints = { });
|
QLibrary::LoadHints loadHints = { });
|
||||||
static QStringList suffixes_sys(const QString &fullVersion);
|
static QStringList suffixes_sys(const QString &fullVersion);
|
||||||
static QStringList prefixes_sys();
|
static QStringList prefixes_sys();
|
||||||
|
|
||||||
QPointer<QObject> inst;
|
QAtomicPointer<std::remove_pointer<QtPluginInstanceFunction>::type> instanceFactory;
|
||||||
QtPluginInstanceFunction instance;
|
QAtomicPointer<std::remove_pointer<Handle>::type> pHnd;
|
||||||
QJsonObject metaData;
|
|
||||||
|
|
||||||
|
// the mutex protects the fields below
|
||||||
|
QMutex mutex;
|
||||||
|
QPointer<QObject> inst; // used by QFactoryLoader
|
||||||
|
QJsonObject metaData;
|
||||||
QString errorString;
|
QString errorString;
|
||||||
|
QString qualifiedFileName;
|
||||||
|
|
||||||
void updatePluginState();
|
void updatePluginState();
|
||||||
bool isPlugin();
|
bool isPlugin();
|
||||||
|
@ -214,8 +214,9 @@ bool QLibraryPrivate::load_sys()
|
|||||||
#endif
|
#endif
|
||||||
|
|
||||||
bool retry = true;
|
bool retry = true;
|
||||||
for(int prefix = 0; retry && !pHnd && prefix < prefixes.size(); prefix++) {
|
Handle hnd = nullptr;
|
||||||
for(int suffix = 0; retry && !pHnd && suffix < suffixes.size(); suffix++) {
|
for (int prefix = 0; retry && !hnd && prefix < prefixes.size(); prefix++) {
|
||||||
|
for (int suffix = 0; retry && !hnd && suffix < suffixes.size(); suffix++) {
|
||||||
if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix)))
|
if (!prefixes.at(prefix).isEmpty() && name.startsWith(prefixes.at(prefix)))
|
||||||
continue;
|
continue;
|
||||||
if (path.isEmpty() && prefixes.at(prefix).contains(QLatin1Char('/')))
|
if (path.isEmpty() && prefixes.at(prefix).contains(QLatin1Char('/')))
|
||||||
@ -232,7 +233,7 @@ bool QLibraryPrivate::load_sys()
|
|||||||
attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix);
|
attempt = path + prefixes.at(prefix) + name + suffixes.at(suffix);
|
||||||
}
|
}
|
||||||
|
|
||||||
pHnd = dlopen(QFile::encodeName(attempt), dlFlags);
|
hnd = dlopen(QFile::encodeName(attempt), dlFlags);
|
||||||
#ifdef Q_OS_ANDROID
|
#ifdef Q_OS_ANDROID
|
||||||
if (!pHnd) {
|
if (!pHnd) {
|
||||||
auto attemptFromBundle = attempt;
|
auto attemptFromBundle = attempt;
|
||||||
@ -248,7 +249,7 @@ bool QLibraryPrivate::load_sys()
|
|||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
if (!pHnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) {
|
if (!hnd && fileName.startsWith(QLatin1Char('/')) && QFile::exists(attempt)) {
|
||||||
// We only want to continue if dlopen failed due to that the shared library did not exist.
|
// We only want to continue if dlopen failed due to that the shared library did not exist.
|
||||||
// However, we are only able to apply this check for absolute filenames (since they are
|
// However, we are only able to apply this check for absolute filenames (since they are
|
||||||
// not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...)
|
// not influenced by the content of LD_LIBRARY_PATH, /etc/ld.so.cache, DT_RPATH etc...)
|
||||||
@ -259,7 +260,7 @@ bool QLibraryPrivate::load_sys()
|
|||||||
}
|
}
|
||||||
|
|
||||||
#ifdef Q_OS_MAC
|
#ifdef Q_OS_MAC
|
||||||
if (!pHnd) {
|
if (!hnd) {
|
||||||
QByteArray utf8Bundle = fileName.toUtf8();
|
QByteArray utf8Bundle = fileName.toUtf8();
|
||||||
QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true);
|
QCFType<CFURLRef> bundleUrl = CFURLCreateFromFileSystemRepresentation(NULL, reinterpret_cast<const UInt8*>(utf8Bundle.data()), utf8Bundle.length(), true);
|
||||||
QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl);
|
QCFType<CFBundleRef> bundle = CFBundleCreate(NULL, bundleUrl);
|
||||||
@ -268,23 +269,24 @@ bool QLibraryPrivate::load_sys()
|
|||||||
char executableFile[FILENAME_MAX];
|
char executableFile[FILENAME_MAX];
|
||||||
CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX);
|
CFURLGetFileSystemRepresentation(url, true, reinterpret_cast<UInt8*>(executableFile), FILENAME_MAX);
|
||||||
attempt = QString::fromUtf8(executableFile);
|
attempt = QString::fromUtf8(executableFile);
|
||||||
pHnd = dlopen(QFile::encodeName(attempt), dlFlags);
|
hnd = dlopen(QFile::encodeName(attempt), dlFlags);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
if (!pHnd) {
|
if (!hnd) {
|
||||||
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName, qdlerror());
|
errorString = QLibrary::tr("Cannot load library %1: %2").arg(fileName, qdlerror());
|
||||||
}
|
}
|
||||||
if (pHnd) {
|
if (hnd) {
|
||||||
qualifiedFileName = attempt;
|
qualifiedFileName = attempt;
|
||||||
errorString.clear();
|
errorString.clear();
|
||||||
}
|
}
|
||||||
return (pHnd != nullptr);
|
pHnd.storeRelaxed(hnd);
|
||||||
|
return (hnd != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QLibraryPrivate::unload_sys()
|
bool QLibraryPrivate::unload_sys()
|
||||||
{
|
{
|
||||||
if (dlclose(pHnd)) {
|
if (dlclose(pHnd.loadAcquire())) {
|
||||||
#if defined (Q_OS_QNX) // Workaround until fixed in QNX; fixes crash in
|
#if defined (Q_OS_QNX) // Workaround until fixed in QNX; fixes crash in
|
||||||
char *error = dlerror(); // QtDeclarative auto test "qqmlenginecleanup" for instance
|
char *error = dlerror(); // QtDeclarative auto test "qqmlenginecleanup" for instance
|
||||||
if (!qstrcmp(error, "Shared objects still referenced")) // On QNX that's only "informative"
|
if (!qstrcmp(error, "Shared objects still referenced")) // On QNX that's only "informative"
|
||||||
@ -316,13 +318,7 @@ Q_CORE_EXPORT QFunctionPointer qt_mac_resolve_sys(void *handle, const char *symb
|
|||||||
|
|
||||||
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
|
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
|
||||||
{
|
{
|
||||||
QFunctionPointer address = QFunctionPointer(dlsym(pHnd, symbol));
|
QFunctionPointer address = QFunctionPointer(dlsym(pHnd.loadAcquire(), symbol));
|
||||||
if (!address) {
|
|
||||||
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
|
|
||||||
QString::fromLatin1(symbol), fileName, qdlerror());
|
|
||||||
} else {
|
|
||||||
errorString.clear();
|
|
||||||
}
|
|
||||||
return address;
|
return address;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -95,26 +95,27 @@ bool QLibraryPrivate::load_sys()
|
|||||||
attempts.prepend(QDir::rootPath() + fileName);
|
attempts.prepend(QDir::rootPath() + fileName);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
Handle hnd = nullptr;
|
||||||
for (const QString &attempt : qAsConst(attempts)) {
|
for (const QString &attempt : qAsConst(attempts)) {
|
||||||
#ifndef Q_OS_WINRT
|
#ifndef Q_OS_WINRT
|
||||||
pHnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
|
hnd = LoadLibrary(reinterpret_cast<const wchar_t*>(QDir::toNativeSeparators(attempt).utf16()));
|
||||||
#else // Q_OS_WINRT
|
#else // Q_OS_WINRT
|
||||||
QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt));
|
QString path = QDir::toNativeSeparators(QDir::current().relativeFilePath(attempt));
|
||||||
pHnd = LoadPackagedLibrary(reinterpret_cast<LPCWSTR>(path.utf16()), 0);
|
hnd = LoadPackagedLibrary(reinterpret_cast<LPCWSTR>(path.utf16()), 0);
|
||||||
if (pHnd)
|
if (hnd)
|
||||||
qualifiedFileName = attempt;
|
qualifiedFileName = attempt;
|
||||||
#endif // !Q_OS_WINRT
|
#endif // !Q_OS_WINRT
|
||||||
|
|
||||||
// If we have a handle or the last error is something other than "unable
|
// If we have a handle or the last error is something other than "unable
|
||||||
// to find the module", then bail out
|
// to find the module", then bail out
|
||||||
if (pHnd || ::GetLastError() != ERROR_MOD_NOT_FOUND)
|
if (hnd || ::GetLastError() != ERROR_MOD_NOT_FOUND)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifndef Q_OS_WINRT
|
#ifndef Q_OS_WINRT
|
||||||
SetErrorMode(oldmode);
|
SetErrorMode(oldmode);
|
||||||
#endif
|
#endif
|
||||||
if (!pHnd) {
|
if (!hnd) {
|
||||||
errorString = QLibrary::tr("Cannot load library %1: %2").arg(
|
errorString = QLibrary::tr("Cannot load library %1: %2").arg(
|
||||||
QDir::toNativeSeparators(fileName), qt_error_string());
|
QDir::toNativeSeparators(fileName), qt_error_string());
|
||||||
} else {
|
} else {
|
||||||
@ -123,7 +124,7 @@ bool QLibraryPrivate::load_sys()
|
|||||||
|
|
||||||
#ifndef Q_OS_WINRT
|
#ifndef Q_OS_WINRT
|
||||||
wchar_t buffer[MAX_PATH];
|
wchar_t buffer[MAX_PATH];
|
||||||
::GetModuleFileName(pHnd, buffer, MAX_PATH);
|
::GetModuleFileName(hnd, buffer, MAX_PATH);
|
||||||
|
|
||||||
QString moduleFileName = QString::fromWCharArray(buffer);
|
QString moduleFileName = QString::fromWCharArray(buffer);
|
||||||
moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(QLatin1Char('\\')));
|
moduleFileName.remove(0, 1 + moduleFileName.lastIndexOf(QLatin1Char('\\')));
|
||||||
@ -138,19 +139,20 @@ bool QLibraryPrivate::load_sys()
|
|||||||
HMODULE hmod;
|
HMODULE hmod;
|
||||||
bool ok = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN |
|
bool ok = GetModuleHandleEx(GET_MODULE_HANDLE_EX_FLAG_PIN |
|
||||||
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
GET_MODULE_HANDLE_EX_FLAG_FROM_ADDRESS,
|
||||||
reinterpret_cast<const wchar_t *>(pHnd),
|
reinterpret_cast<const wchar_t *>(hnd),
|
||||||
&hmod);
|
&hmod);
|
||||||
Q_ASSERT(!ok || hmod == pHnd);
|
Q_ASSERT(!ok || hmod == hnd);
|
||||||
Q_UNUSED(ok);
|
Q_UNUSED(ok);
|
||||||
}
|
}
|
||||||
#endif // !Q_OS_WINRT
|
#endif // !Q_OS_WINRT
|
||||||
}
|
}
|
||||||
return (pHnd != 0);
|
pHnd.storeRelaxed(hnd);
|
||||||
|
return (pHnd != nullptr);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool QLibraryPrivate::unload_sys()
|
bool QLibraryPrivate::unload_sys()
|
||||||
{
|
{
|
||||||
if (!FreeLibrary(pHnd)) {
|
if (!FreeLibrary(pHnd.loadAcquire())) {
|
||||||
errorString = QLibrary::tr("Cannot unload library %1: %2").arg(
|
errorString = QLibrary::tr("Cannot unload library %1: %2").arg(
|
||||||
QDir::toNativeSeparators(fileName), qt_error_string());
|
QDir::toNativeSeparators(fileName), qt_error_string());
|
||||||
return false;
|
return false;
|
||||||
@ -161,13 +163,7 @@ bool QLibraryPrivate::unload_sys()
|
|||||||
|
|
||||||
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
|
QFunctionPointer QLibraryPrivate::resolve_sys(const char* symbol)
|
||||||
{
|
{
|
||||||
FARPROC address = GetProcAddress(pHnd, symbol);
|
FARPROC address = GetProcAddress(pHnd.loadAcquire(), symbol);
|
||||||
if (!address) {
|
|
||||||
errorString = QLibrary::tr("Cannot resolve symbol \"%1\" in %2: %3").arg(
|
|
||||||
QString::fromLatin1(symbol), QDir::toNativeSeparators(fileName), qt_error_string());
|
|
||||||
} else {
|
|
||||||
errorString.clear();
|
|
||||||
}
|
|
||||||
return QFunctionPointer(address);
|
return QFunctionPointer(address);
|
||||||
}
|
}
|
||||||
QT_END_NAMESPACE
|
QT_END_NAMESPACE
|
||||||
|
@ -196,9 +196,7 @@ QObject *QPluginLoader::instance()
|
|||||||
{
|
{
|
||||||
if (!isLoaded() && !load())
|
if (!isLoaded() && !load())
|
||||||
return nullptr;
|
return nullptr;
|
||||||
if (!d->inst && d->instance)
|
return d->pluginInstance();
|
||||||
d->inst = d->instance();
|
|
||||||
return d->inst.data();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*!
|
/*!
|
||||||
@ -233,7 +231,7 @@ bool QPluginLoader::load()
|
|||||||
if (!d || d->fileName.isEmpty())
|
if (!d || d->fileName.isEmpty())
|
||||||
return false;
|
return false;
|
||||||
if (did_load)
|
if (did_load)
|
||||||
return d->pHnd && d->instance;
|
return d->pHnd && d->instanceFactory.loadAcquire();
|
||||||
if (!d->isPlugin())
|
if (!d->isPlugin())
|
||||||
return false;
|
return false;
|
||||||
did_load = true;
|
did_load = true;
|
||||||
@ -275,7 +273,7 @@ bool QPluginLoader::unload()
|
|||||||
*/
|
*/
|
||||||
bool QPluginLoader::isLoaded() const
|
bool QPluginLoader::isLoaded() const
|
||||||
{
|
{
|
||||||
return d && d->pHnd && d->instance;
|
return d && d->pHnd && d->instanceFactory.loadRelaxed();
|
||||||
}
|
}
|
||||||
|
|
||||||
#if defined(QT_SHARED)
|
#if defined(QT_SHARED)
|
||||||
|
@ -115,7 +115,8 @@ struct ByteData
|
|||||||
QStringView asStringView() const{ return QStringView(utf16(), len / 2); }
|
QStringView asStringView() const{ return QStringView(utf16(), len / 2); }
|
||||||
QString asQStringRaw() const { return QString::fromRawData(utf16(), len / 2); }
|
QString asQStringRaw() const { return QString::fromRawData(utf16(), len / 2); }
|
||||||
};
|
};
|
||||||
Q_STATIC_ASSERT(std::is_pod<ByteData>::value);
|
Q_STATIC_ASSERT(std::is_trivial<ByteData>::value);
|
||||||
|
Q_STATIC_ASSERT(std::is_standard_layout<ByteData>::value);
|
||||||
} // namespace QtCbor
|
} // namespace QtCbor
|
||||||
|
|
||||||
Q_DECLARE_TYPEINFO(QtCbor::Element, Q_PRIMITIVE_TYPE);
|
Q_DECLARE_TYPEINFO(QtCbor::Element, Q_PRIMITIVE_TYPE);
|
||||||
|
@ -1667,7 +1667,8 @@ namespace {
|
|||||||
QFontEngine *previousGlyphFontEngine;
|
QFontEngine *previousGlyphFontEngine;
|
||||||
|
|
||||||
QFixed minw;
|
QFixed minw;
|
||||||
QFixed softHyphenWidth;
|
QFixed currentSoftHyphenWidth;
|
||||||
|
QFixed commitedSoftHyphenWidth;
|
||||||
QFixed rightBearing;
|
QFixed rightBearing;
|
||||||
QFixed minimumRightBearing;
|
QFixed minimumRightBearing;
|
||||||
|
|
||||||
@ -1681,7 +1682,7 @@ namespace {
|
|||||||
|
|
||||||
QFixed calculateNewWidth(const QScriptLine &line) const {
|
QFixed calculateNewWidth(const QScriptLine &line) const {
|
||||||
return line.textWidth + tmpData.textWidth + spaceData.textWidth
|
return line.textWidth + tmpData.textWidth + spaceData.textWidth
|
||||||
+ softHyphenWidth + negativeRightBearing();
|
+ (line.textWidth > 0 ? currentSoftHyphenWidth : QFixed()) + negativeRightBearing();
|
||||||
}
|
}
|
||||||
|
|
||||||
inline glyph_t currentGlyph() const
|
inline glyph_t currentGlyph() const
|
||||||
@ -1755,6 +1756,7 @@ inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
|
|||||||
if (line.length && !manualWrap && (newWidth > line.width || glyphCount > maxGlyphs))
|
if (line.length && !manualWrap && (newWidth > line.width || glyphCount > maxGlyphs))
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
|
const QFixed oldTextWidth = line.textWidth;
|
||||||
minw = qMax(minw, tmpData.textWidth);
|
minw = qMax(minw, tmpData.textWidth);
|
||||||
line += tmpData;
|
line += tmpData;
|
||||||
line.textWidth += spaceData.textWidth;
|
line.textWidth += spaceData.textWidth;
|
||||||
@ -1765,6 +1767,11 @@ inline bool LineBreakHelper::checkFullOtherwiseExtend(QScriptLine &line)
|
|||||||
spaceData.textWidth = 0;
|
spaceData.textWidth = 0;
|
||||||
spaceData.length = 0;
|
spaceData.length = 0;
|
||||||
|
|
||||||
|
if (oldTextWidth != line.textWidth || currentSoftHyphenWidth > 0) {
|
||||||
|
commitedSoftHyphenWidth = currentSoftHyphenWidth;
|
||||||
|
currentSoftHyphenWidth = 0;
|
||||||
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1837,7 +1844,6 @@ void QTextLine::layout_helper(int maxGlyphs)
|
|||||||
|
|
||||||
while (newItem < eng->layoutData->items.size()) {
|
while (newItem < eng->layoutData->items.size()) {
|
||||||
lbh.resetRightBearing();
|
lbh.resetRightBearing();
|
||||||
lbh.softHyphenWidth = 0;
|
|
||||||
if (newItem != item) {
|
if (newItem != item) {
|
||||||
item = newItem;
|
item = newItem;
|
||||||
const QScriptItem ¤t = eng->layoutData->items.at(item);
|
const QScriptItem ¤t = eng->layoutData->items.at(item);
|
||||||
@ -1975,9 +1981,9 @@ void QTextLine::layout_helper(int maxGlyphs)
|
|||||||
} while (lbh.currentPosition < end);
|
} while (lbh.currentPosition < end);
|
||||||
lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw);
|
lbh.minw = qMax(lbh.tmpData.textWidth, lbh.minw);
|
||||||
|
|
||||||
if (lbh.currentPosition > 0 && lbh.currentPosition < end
|
if (lbh.currentPosition > 0 && lbh.currentPosition <= end
|
||||||
&& attributes[lbh.currentPosition].lineBreak
|
&& (lbh.currentPosition == end || attributes[lbh.currentPosition].lineBreak)
|
||||||
&& eng->layoutData->string.at(lbh.currentPosition - 1).unicode() == QChar::SoftHyphen) {
|
&& eng->layoutData->string.at(lbh.currentPosition - 1) == QChar::SoftHyphen) {
|
||||||
// if we are splitting up a word because of
|
// if we are splitting up a word because of
|
||||||
// a soft hyphen then we ...
|
// a soft hyphen then we ...
|
||||||
//
|
//
|
||||||
@ -1994,10 +2000,7 @@ void QTextLine::layout_helper(int maxGlyphs)
|
|||||||
// want the soft-hyphen to slip into the next line
|
// want the soft-hyphen to slip into the next line
|
||||||
// and thus become invisible again.
|
// and thus become invisible again.
|
||||||
//
|
//
|
||||||
if (line.length)
|
lbh.currentSoftHyphenWidth = lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
|
||||||
lbh.softHyphenWidth = lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
|
|
||||||
else if (breakany)
|
|
||||||
lbh.tmpData.textWidth += lbh.glyphs.advances[lbh.logClusters[lbh.currentPosition - 1]];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (sb_or_ws|breakany) {
|
if (sb_or_ws|breakany) {
|
||||||
@ -2023,6 +2026,7 @@ void QTextLine::layout_helper(int maxGlyphs)
|
|||||||
lbh.calculateRightBearing();
|
lbh.calculateRightBearing();
|
||||||
|
|
||||||
if (lbh.checkFullOtherwiseExtend(line)) {
|
if (lbh.checkFullOtherwiseExtend(line)) {
|
||||||
|
|
||||||
// We are too wide to accept the next glyph with its bearing, so we restore the
|
// We are too wide to accept the next glyph with its bearing, so we restore the
|
||||||
// right bearing to that of the previous glyph (the one that was already accepted),
|
// right bearing to that of the previous glyph (the one that was already accepted),
|
||||||
// so that the bearing can be be applied to the final width of the text below.
|
// so that the bearing can be be applied to the final width of the text below.
|
||||||
@ -2031,9 +2035,7 @@ void QTextLine::layout_helper(int maxGlyphs)
|
|||||||
else
|
else
|
||||||
lbh.calculateRightBearingForPreviousGlyph();
|
lbh.calculateRightBearingForPreviousGlyph();
|
||||||
|
|
||||||
if (!breakany) {
|
line.textWidth += lbh.commitedSoftHyphenWidth;
|
||||||
line.textWidth += lbh.softHyphenWidth;
|
|
||||||
}
|
|
||||||
|
|
||||||
goto found;
|
goto found;
|
||||||
}
|
}
|
||||||
@ -2045,6 +2047,7 @@ void QTextLine::layout_helper(int maxGlyphs)
|
|||||||
}
|
}
|
||||||
LB_DEBUG("reached end of line");
|
LB_DEBUG("reached end of line");
|
||||||
lbh.checkFullOtherwiseExtend(line);
|
lbh.checkFullOtherwiseExtend(line);
|
||||||
|
line.textWidth += lbh.commitedSoftHyphenWidth;
|
||||||
found:
|
found:
|
||||||
line.textAdvance = line.textWidth;
|
line.textAdvance = line.textWidth;
|
||||||
|
|
||||||
|
@ -56,6 +56,7 @@
|
|||||||
#include <QtGui/qpalette.h>
|
#include <QtGui/qpalette.h>
|
||||||
#include <QtGui/qtextdocument.h>
|
#include <QtGui/qtextdocument.h>
|
||||||
#include <QtGui/qtextlist.h>
|
#include <QtGui/qtextlist.h>
|
||||||
|
#include <QtCore/qpointer.h>
|
||||||
#include <QtCore/qstack.h>
|
#include <QtCore/qstack.h>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
@ -46,7 +46,11 @@
|
|||||||
#include <QSocketNotifier>
|
#include <QSocketNotifier>
|
||||||
#include <QLoggingCategory>
|
#include <QLoggingCategory>
|
||||||
|
|
||||||
|
#ifdef Q_OS_FREEBSD
|
||||||
|
#include <dev/evdev/input.h>
|
||||||
|
#else
|
||||||
#include <linux/input.h>
|
#include <linux/input.h>
|
||||||
|
#endif
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
|
@ -122,6 +122,7 @@ static const char *xcb_atomnames = {
|
|||||||
"_NET_WM_STATE_MODAL\0"
|
"_NET_WM_STATE_MODAL\0"
|
||||||
"_NET_WM_STATE_STAYS_ON_TOP\0"
|
"_NET_WM_STATE_STAYS_ON_TOP\0"
|
||||||
"_NET_WM_STATE_DEMANDS_ATTENTION\0"
|
"_NET_WM_STATE_DEMANDS_ATTENTION\0"
|
||||||
|
"_NET_WM_STATE_HIDDEN\0"
|
||||||
|
|
||||||
"_NET_WM_USER_TIME\0"
|
"_NET_WM_USER_TIME\0"
|
||||||
"_NET_WM_USER_TIME_WINDOW\0"
|
"_NET_WM_USER_TIME_WINDOW\0"
|
||||||
|
@ -123,6 +123,7 @@ public:
|
|||||||
_NET_WM_STATE_MODAL,
|
_NET_WM_STATE_MODAL,
|
||||||
_NET_WM_STATE_STAYS_ON_TOP,
|
_NET_WM_STATE_STAYS_ON_TOP,
|
||||||
_NET_WM_STATE_DEMANDS_ATTENTION,
|
_NET_WM_STATE_DEMANDS_ATTENTION,
|
||||||
|
_NET_WM_STATE_HIDDEN,
|
||||||
|
|
||||||
_NET_WM_USER_TIME,
|
_NET_WM_USER_TIME,
|
||||||
_NET_WM_USER_TIME_WINDOW,
|
_NET_WM_USER_TIME_WINDOW,
|
||||||
|
@ -903,6 +903,8 @@ QXcbWindow::NetWmStates QXcbWindow::netWmStates()
|
|||||||
result |= NetWmStateStaysOnTop;
|
result |= NetWmStateStaysOnTop;
|
||||||
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
|
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_DEMANDS_ATTENTION)))
|
||||||
result |= NetWmStateDemandsAttention;
|
result |= NetWmStateDemandsAttention;
|
||||||
|
if (statesEnd != std::find(states, statesEnd, atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
|
||||||
|
result |= NetWmStateHidden;
|
||||||
} else {
|
} else {
|
||||||
qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window);
|
qCDebug(lcQpaXcb, "getting net wm state (%x), empty\n", m_window);
|
||||||
}
|
}
|
||||||
@ -1074,6 +1076,9 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
|
|||||||
states |= NetWmStateBelow;
|
states |= NetWmStateBelow;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (window()->windowStates() & Qt::WindowMinimized)
|
||||||
|
states |= NetWmStateHidden;
|
||||||
|
|
||||||
if (window()->windowStates() & Qt::WindowFullScreen)
|
if (window()->windowStates() & Qt::WindowFullScreen)
|
||||||
states |= NetWmStateFullScreen;
|
states |= NetWmStateFullScreen;
|
||||||
|
|
||||||
@ -1107,6 +1112,8 @@ void QXcbWindow::setNetWmStateOnUnmappedWindow()
|
|||||||
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
|
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_ABOVE));
|
||||||
if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
|
if (states & NetWmStateBelow && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_BELOW)))
|
||||||
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
|
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_BELOW));
|
||||||
|
if (states & NetWmStateHidden && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_HIDDEN)))
|
||||||
|
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_HIDDEN));
|
||||||
if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
|
if (states & NetWmStateFullScreen && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN)))
|
||||||
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
|
atoms.push_back(atom(QXcbAtom::_NET_WM_STATE_FULLSCREEN));
|
||||||
if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
|
if (states & NetWmStateMaximizedHorz && !atoms.contains(atom(QXcbAtom::_NET_WM_STATE_MAXIMIZED_HORZ)))
|
||||||
@ -2204,10 +2211,16 @@ void QXcbWindow::handlePropertyNotifyEvent(const xcb_property_notify_event_t *ev
|
|||||||
|| (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized));
|
|| (data[0] == XCB_ICCCM_WM_STATE_WITHDRAWN && m_minimized));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (m_minimized)
|
|
||||||
newState = Qt::WindowMinimized;
|
|
||||||
|
|
||||||
const NetWmStates states = netWmStates();
|
const NetWmStates states = netWmStates();
|
||||||
|
// _NET_WM_STATE_HIDDEN should be set by the Window Manager to indicate that a window would
|
||||||
|
// not be visible on the screen if its desktop/viewport were active and its coordinates were
|
||||||
|
// within the screen bounds. The canonical example is that minimized windows should be in
|
||||||
|
// the _NET_WM_STATE_HIDDEN state.
|
||||||
|
if (m_minimized && (!connection()->wmSupport()->isSupportedByWM(NetWmStateHidden)
|
||||||
|
|| states.testFlag(NetWmStateHidden)))
|
||||||
|
newState = Qt::WindowMinimized;
|
||||||
|
|
||||||
if (states & NetWmStateFullScreen)
|
if (states & NetWmStateFullScreen)
|
||||||
newState |= Qt::WindowFullScreen;
|
newState |= Qt::WindowFullScreen;
|
||||||
if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))
|
if ((states & NetWmStateMaximizedHorz) && (states & NetWmStateMaximizedVert))
|
||||||
|
@ -68,7 +68,8 @@ public:
|
|||||||
NetWmStateMaximizedVert = 0x10,
|
NetWmStateMaximizedVert = 0x10,
|
||||||
NetWmStateModal = 0x20,
|
NetWmStateModal = 0x20,
|
||||||
NetWmStateStaysOnTop = 0x40,
|
NetWmStateStaysOnTop = 0x40,
|
||||||
NetWmStateDemandsAttention = 0x80
|
NetWmStateDemandsAttention = 0x80,
|
||||||
|
NetWmStateHidden = 0x100
|
||||||
};
|
};
|
||||||
|
|
||||||
Q_DECLARE_FLAGS(NetWmStates, NetWmState)
|
Q_DECLARE_FLAGS(NetWmStates, NetWmState)
|
||||||
|
@ -546,12 +546,19 @@ void WriteInitialization::acceptUI(DomUI *node)
|
|||||||
|
|
||||||
m_output << m_option.indent << language::endFunctionDefinition("setupUi");
|
m_output << m_option.indent << language::endFunctionDefinition("setupUi");
|
||||||
|
|
||||||
if (!m_mainFormUsedInRetranslateUi && language::language() == Language::Cpp) {
|
if (!m_mainFormUsedInRetranslateUi) {
|
||||||
|
if (language::language() == Language::Cpp) {
|
||||||
// Mark varName as unused to avoid compiler warnings.
|
// Mark varName as unused to avoid compiler warnings.
|
||||||
m_refreshInitialization += m_indent;
|
m_refreshInitialization += m_indent;
|
||||||
m_refreshInitialization += QLatin1String("(void)");
|
m_refreshInitialization += QLatin1String("(void)");
|
||||||
m_refreshInitialization += varName ;
|
m_refreshInitialization += varName ;
|
||||||
m_refreshInitialization += language::eol;
|
m_refreshInitialization += language::eol;
|
||||||
|
} else if (language::language() == Language::Python) {
|
||||||
|
// output a 'pass' to have an empty function
|
||||||
|
m_refreshInitialization += m_indent;
|
||||||
|
m_refreshInitialization += QLatin1String("pass");
|
||||||
|
m_refreshInitialization += language::eol;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
m_output << m_option.indent
|
m_output << m_option.indent
|
||||||
|
@ -65,6 +65,7 @@
|
|||||||
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
#include <limits>
|
||||||
|
|
||||||
QT_BEGIN_NAMESPACE
|
QT_BEGIN_NAMESPACE
|
||||||
|
|
||||||
@ -4364,7 +4365,7 @@ void QDomElement::setAttribute(const QString& name, float value)
|
|||||||
if (!impl)
|
if (!impl)
|
||||||
return;
|
return;
|
||||||
QString x;
|
QString x;
|
||||||
x.setNum(value);
|
x.setNum(value, 'g', 8);
|
||||||
IMPL->setAttribute(name, x);
|
IMPL->setAttribute(name, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4378,7 +4379,7 @@ void QDomElement::setAttribute(const QString& name, double value)
|
|||||||
if (!impl)
|
if (!impl)
|
||||||
return;
|
return;
|
||||||
QString x;
|
QString x;
|
||||||
x.setNum(value);
|
x.setNum(value, 'g', 17);
|
||||||
IMPL->setAttribute(name, x);
|
IMPL->setAttribute(name, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -4547,7 +4548,7 @@ void QDomElement::setAttributeNS(const QString nsURI, const QString& qName, doub
|
|||||||
if (!impl)
|
if (!impl)
|
||||||
return;
|
return;
|
||||||
QString x;
|
QString x;
|
||||||
x.setNum(value);
|
x.setNum(value, 'g', 17);
|
||||||
IMPL->setAttributeNS(nsURI, qName, x);
|
IMPL->setAttributeNS(nsURI, qName, x);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,3 +0,0 @@
|
|||||||
[elapsed]
|
|
||||||
macos
|
|
||||||
windows-10
|
|
@ -368,7 +368,7 @@ void tst_QLibrary::errorString_data()
|
|||||||
|
|
||||||
QTest::newRow("bad load()") << (int)Load << QString("nosuchlib") << false << QString("Cannot load library nosuchlib: .*");
|
QTest::newRow("bad load()") << (int)Load << QString("nosuchlib") << false << QString("Cannot load library nosuchlib: .*");
|
||||||
QTest::newRow("call errorString() on QLibrary with no d-pointer (crashtest)") << (int)(Load | DontSetFileName) << QString() << false << QString("Unknown error");
|
QTest::newRow("call errorString() on QLibrary with no d-pointer (crashtest)") << (int)(Load | DontSetFileName) << QString() << false << QString("Unknown error");
|
||||||
QTest::newRow("bad resolve") << (int)Resolve << appDir + "/mylib" << false << QString("Cannot resolve symbol \"nosuchsymbol\" in \\S+: .*");
|
QTest::newRow("bad resolve") << (int)Resolve << appDir + "/mylib" << false << QString("Unknown error");
|
||||||
QTest::newRow("good resolve") << (int)Resolve << appDir + "/mylib" << true << QString("Unknown error");
|
QTest::newRow("good resolve") << (int)Resolve << appDir + "/mylib" << true << QString("Unknown error");
|
||||||
|
|
||||||
#ifdef Q_OS_WIN
|
#ifdef Q_OS_WIN
|
||||||
|
@ -62,6 +62,7 @@ private slots:
|
|||||||
void lineBreaking();
|
void lineBreaking();
|
||||||
#ifdef QT_BUILD_INTERNAL
|
#ifdef QT_BUILD_INTERNAL
|
||||||
void simpleBoundingRect();
|
void simpleBoundingRect();
|
||||||
|
void threeLineBoundingRect_data();
|
||||||
void threeLineBoundingRect();
|
void threeLineBoundingRect();
|
||||||
void boundingRectWithLongLineAndNoWrap();
|
void boundingRectWithLongLineAndNoWrap();
|
||||||
void forcedBreaks();
|
void forcedBreaks();
|
||||||
@ -140,6 +141,7 @@ private slots:
|
|||||||
void showLineAndParagraphSeparatorsCrash();
|
void showLineAndParagraphSeparatorsCrash();
|
||||||
void koreanWordWrap();
|
void koreanWordWrap();
|
||||||
void tooManyDirectionalCharctersCrash_qtbug77819();
|
void tooManyDirectionalCharctersCrash_qtbug77819();
|
||||||
|
void softHyphens();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
QFont testFont;
|
QFont testFont;
|
||||||
@ -315,18 +317,49 @@ void tst_QTextLayout::simpleBoundingRect()
|
|||||||
QCOMPARE(layout.boundingRect(), QRectF(0, 0, width, QFontMetrics(testFont).height()));
|
QCOMPARE(layout.boundingRect(), QRectF(0, 0, width, QFontMetrics(testFont).height()));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QTextLayout::threeLineBoundingRect_data()
|
||||||
|
{
|
||||||
|
QTest::addColumn<QChar>("wordBoundary1");
|
||||||
|
QTest::addColumn<QChar>("wordBoundary2");
|
||||||
|
QTest::newRow("2x' '") << QChar(' ') << QChar(' ');
|
||||||
|
QTest::newRow("2x'\\n'") << QChar('\n') << QChar('\n');
|
||||||
|
QTest::newRow("' ' + '\\n'") << QChar(' ') << QChar('\n');
|
||||||
|
QTest::newRow("'\\n' + ' '") << QChar('\n') << QChar(' ');
|
||||||
|
QTest::newRow("2x'\\t'") << QChar('\t') << QChar('\t');
|
||||||
|
QTest::newRow("2xsoft hyphen") << QChar(0xad) << QChar(0xad);
|
||||||
|
QTest::newRow("2x'-'") << QChar('-') << QChar('-');
|
||||||
|
QTest::newRow("2x'/'") << QChar('/') << QChar('/');
|
||||||
|
QTest::newRow("soft hyphen + ' '") << QChar(0xad) << QChar(' ');
|
||||||
|
QTest::newRow("soft hyphen + '\\n'") << QChar(0xad) << QChar('\n');
|
||||||
|
QTest::newRow("soft hyphen + '-'") << QChar(0xad) << QChar('-');
|
||||||
|
QTest::newRow("' ' + soft hyphen") << QChar(' ') << QChar(0xad);
|
||||||
|
QTest::newRow("'\\n' + soft hyphen") << QChar('\n') << QChar(0xad);
|
||||||
|
QTest::newRow("'-' + soft hyphen") << QChar('-') << QChar(0xad);
|
||||||
|
}
|
||||||
|
|
||||||
void tst_QTextLayout::threeLineBoundingRect()
|
void tst_QTextLayout::threeLineBoundingRect()
|
||||||
{
|
{
|
||||||
/* stricter check. break text into three lines */
|
/* stricter check. break text into three lines */
|
||||||
|
QFETCH(QChar, wordBoundary1);
|
||||||
|
QFETCH(QChar, wordBoundary2);
|
||||||
|
|
||||||
QString firstWord("hello");
|
QString firstWord("hello");
|
||||||
QString secondWord("world");
|
QString secondWord("test");
|
||||||
QString thirdWord("test");
|
QString thirdWord("world");
|
||||||
QString text(firstWord + ' ' + secondWord + ' ' + thirdWord);
|
QString text(firstWord + wordBoundary1 + secondWord + wordBoundary2 + thirdWord);
|
||||||
|
|
||||||
const int firstLineWidth = firstWord.length() * testFont.pixelSize();
|
int firstLineWidth = firstWord.length() * testFont.pixelSize();
|
||||||
const int secondLineWidth = secondWord.length() * testFont.pixelSize();
|
int secondLineWidth = secondWord.length() * testFont.pixelSize();
|
||||||
const int thirdLineWidth = thirdWord.length() * testFont.pixelSize();
|
int thirdLineWidth = thirdWord.length() * testFont.pixelSize();
|
||||||
|
// Trailing spaces do not count to line width:
|
||||||
|
if (!wordBoundary1.isSpace())
|
||||||
|
firstLineWidth += testFont.pixelSize();
|
||||||
|
if (!wordBoundary2.isSpace())
|
||||||
|
secondLineWidth += testFont.pixelSize();
|
||||||
|
// But trailing spaces do count to line length:
|
||||||
|
const int firstLineLength = firstWord.length() + 1;
|
||||||
|
const int secondLineLength = secondWord.length() + 1;
|
||||||
|
const int thirdLineLength = thirdWord.length();
|
||||||
|
|
||||||
const int longestLine = qMax(firstLineWidth, qMax(secondLineWidth, thirdLineWidth));
|
const int longestLine = qMax(firstLineWidth, qMax(secondLineWidth, thirdLineWidth));
|
||||||
|
|
||||||
@ -339,8 +372,7 @@ void tst_QTextLayout::threeLineBoundingRect()
|
|||||||
line.setLineWidth(firstLineWidth);
|
line.setLineWidth(firstLineWidth);
|
||||||
line.setPosition(QPoint(0, y));
|
line.setPosition(QPoint(0, y));
|
||||||
QCOMPARE(line.textStart(), pos);
|
QCOMPARE(line.textStart(), pos);
|
||||||
// + 1 for trailing space
|
QCOMPARE(line.textLength(), firstLineLength);
|
||||||
QCOMPARE(line.textLength(), firstWord.length() + 1);
|
|
||||||
QCOMPARE(qRound(line.naturalTextWidth()), firstLineWidth);
|
QCOMPARE(qRound(line.naturalTextWidth()), firstLineWidth);
|
||||||
|
|
||||||
pos += line.textLength();
|
pos += line.textLength();
|
||||||
@ -349,9 +381,8 @@ void tst_QTextLayout::threeLineBoundingRect()
|
|||||||
line = layout.createLine();
|
line = layout.createLine();
|
||||||
line.setLineWidth(secondLineWidth);
|
line.setLineWidth(secondLineWidth);
|
||||||
line.setPosition(QPoint(0, y));
|
line.setPosition(QPoint(0, y));
|
||||||
// + 1 for trailing space
|
|
||||||
QCOMPARE(line.textStart(), pos);
|
QCOMPARE(line.textStart(), pos);
|
||||||
QCOMPARE(line.textLength(), secondWord.length() + 1);
|
QCOMPARE(line.textLength(), secondLineLength);
|
||||||
QCOMPARE(qRound(line.naturalTextWidth()), secondLineWidth);
|
QCOMPARE(qRound(line.naturalTextWidth()), secondLineWidth);
|
||||||
|
|
||||||
pos += line.textLength();
|
pos += line.textLength();
|
||||||
@ -360,9 +391,8 @@ void tst_QTextLayout::threeLineBoundingRect()
|
|||||||
line = layout.createLine();
|
line = layout.createLine();
|
||||||
line.setLineWidth(secondLineWidth);
|
line.setLineWidth(secondLineWidth);
|
||||||
line.setPosition(QPoint(0, y));
|
line.setPosition(QPoint(0, y));
|
||||||
// no trailing space here!
|
|
||||||
QCOMPARE(line.textStart(), pos);
|
QCOMPARE(line.textStart(), pos);
|
||||||
QCOMPARE(line.textLength(), thirdWord.length());
|
QCOMPARE(line.textLength(), thirdLineLength);
|
||||||
QCOMPARE(qRound(line.naturalTextWidth()), thirdLineWidth);
|
QCOMPARE(qRound(line.naturalTextWidth()), thirdLineWidth);
|
||||||
y += qRound(line.ascent() + line.descent());
|
y += qRound(line.ascent() + line.descent());
|
||||||
|
|
||||||
@ -2352,5 +2382,111 @@ void tst_QTextLayout::tooManyDirectionalCharctersCrash_qtbug77819()
|
|||||||
tl.endLayout();
|
tl.endLayout();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void tst_QTextLayout::softHyphens()
|
||||||
|
{
|
||||||
|
QString text = QStringLiteral("xxxx\u00ad") + QStringLiteral("xxxx\u00ad");
|
||||||
|
|
||||||
|
QFont font;
|
||||||
|
font.setPixelSize(14);
|
||||||
|
font.setHintingPreference(QFont::PreferNoHinting);
|
||||||
|
const float xAdvance = QFontMetricsF(font).horizontalAdvance(QChar('x'));
|
||||||
|
const float shyAdvance = QFontMetricsF(font).horizontalAdvance(QChar::SoftHyphen);
|
||||||
|
if (xAdvance < (shyAdvance + 1.0f))
|
||||||
|
QSKIP("Default font not suitable for this test.");
|
||||||
|
QTextLayout layout(text, font);
|
||||||
|
QTextOption option;
|
||||||
|
option.setWrapMode(QTextOption::WrapAtWordBoundaryOrAnywhere);
|
||||||
|
layout.setTextOption(option);
|
||||||
|
|
||||||
|
// Loose fit
|
||||||
|
// xxxx- |
|
||||||
|
// xxxx- |
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
int y = 0;
|
||||||
|
layout.beginLayout();
|
||||||
|
QTextLine line = layout.createLine();
|
||||||
|
line.setLineWidth(qCeil(5 * xAdvance) + 1);
|
||||||
|
line.setPosition(QPoint(0, y));
|
||||||
|
QCOMPARE(line.textStart(), pos);
|
||||||
|
QCOMPARE(line.textLength(), 5);
|
||||||
|
QVERIFY(qAbs(line.naturalTextWidth() - (4 * xAdvance + shyAdvance)) <= 1);
|
||||||
|
|
||||||
|
pos += line.textLength();
|
||||||
|
y += qRound(line.ascent() + line.descent());
|
||||||
|
|
||||||
|
line = layout.createLine();
|
||||||
|
line.setLineWidth(qCeil(5 * xAdvance) + 1);
|
||||||
|
line.setPosition(QPoint(0, y));
|
||||||
|
QCOMPARE(line.textStart(), pos);
|
||||||
|
QCOMPARE(line.textLength(), 5);
|
||||||
|
QVERIFY(qAbs(line.naturalTextWidth() - (4 * xAdvance + shyAdvance)) <= 1);
|
||||||
|
layout.endLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Tight fit
|
||||||
|
// xxxx-|
|
||||||
|
// xxxx-|
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
int y = 0;
|
||||||
|
layout.beginLayout();
|
||||||
|
QTextLine line = layout.createLine();
|
||||||
|
line.setLineWidth(qCeil(4 * xAdvance + shyAdvance) + 1);
|
||||||
|
line.setPosition(QPoint(0, y));
|
||||||
|
QCOMPARE(line.textStart(), pos);
|
||||||
|
QCOMPARE(line.textLength(), 5);
|
||||||
|
QVERIFY(qAbs(line.naturalTextWidth() - (4 * xAdvance + shyAdvance)) <= 1);
|
||||||
|
|
||||||
|
pos += line.textLength();
|
||||||
|
y += qRound(line.ascent() + line.descent());
|
||||||
|
|
||||||
|
line = layout.createLine();
|
||||||
|
line.setLineWidth(qCeil(4 * xAdvance + shyAdvance) + 1);
|
||||||
|
line.setPosition(QPoint(0, y));
|
||||||
|
QCOMPARE(line.textStart(), pos);
|
||||||
|
QCOMPARE(line.textLength(), 5);
|
||||||
|
QVERIFY(qAbs(line.naturalTextWidth() - (4 * xAdvance + shyAdvance)) <= 1);
|
||||||
|
layout.endLayout();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Very tight fit
|
||||||
|
// xxxx|
|
||||||
|
// xxxx|
|
||||||
|
// - |
|
||||||
|
{
|
||||||
|
int pos = 0;
|
||||||
|
int y = 0;
|
||||||
|
layout.beginLayout();
|
||||||
|
QTextLine line = layout.createLine();
|
||||||
|
line.setLineWidth(qCeil(4 * xAdvance) + 2);
|
||||||
|
line.setPosition(QPoint(0, y));
|
||||||
|
QCOMPARE(line.textStart(), pos);
|
||||||
|
QCOMPARE(line.textLength(), 4);
|
||||||
|
QVERIFY(qAbs(line.naturalTextWidth() - 4 * xAdvance) <= 1);
|
||||||
|
|
||||||
|
pos += line.textLength();
|
||||||
|
y += qRound(line.ascent() + line.descent());
|
||||||
|
|
||||||
|
line = layout.createLine();
|
||||||
|
line.setLineWidth(qCeil(4 * xAdvance) + 2);
|
||||||
|
line.setPosition(QPoint(0, y));
|
||||||
|
QCOMPARE(line.textStart(), pos);
|
||||||
|
QCOMPARE(line.textLength(), 5);
|
||||||
|
QVERIFY(qAbs(line.naturalTextWidth() - 4 * xAdvance) <= 1);
|
||||||
|
|
||||||
|
pos += line.textLength();
|
||||||
|
y += qRound(line.ascent() + line.descent());
|
||||||
|
|
||||||
|
line = layout.createLine();
|
||||||
|
line.setLineWidth(qCeil(4 * xAdvance) + 2);
|
||||||
|
line.setPosition(QPoint(0, y));
|
||||||
|
QCOMPARE(line.textStart(), pos);
|
||||||
|
QCOMPARE(line.textLength(), 1);
|
||||||
|
QVERIFY(qAbs(line.naturalTextWidth() - shyAdvance) <= 1);
|
||||||
|
layout.endLayout();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
QTEST_MAIN(tst_QTextLayout)
|
QTEST_MAIN(tst_QTextLayout)
|
||||||
#include "tst_qtextlayout.moc"
|
#include "tst_qtextlayout.moc"
|
||||||
|
@ -2,7 +2,3 @@
|
|||||||
# QTBUG-66345
|
# QTBUG-66345
|
||||||
opensuse-42.3
|
opensuse-42.3
|
||||||
ubuntu-16.04
|
ubuntu-16.04
|
||||||
[setWindowState]
|
|
||||||
ubuntu-18.04
|
|
||||||
rhel-7.6
|
|
||||||
|
|
||||||
|
@ -38,6 +38,7 @@
|
|||||||
#include <QtTest/QtTest>
|
#include <QtTest/QtTest>
|
||||||
#include <QtXml>
|
#include <QtXml>
|
||||||
#include <QVariant>
|
#include <QVariant>
|
||||||
|
#include <cmath>
|
||||||
|
|
||||||
QT_FORWARD_DECLARE_CLASS(QDomDocument)
|
QT_FORWARD_DECLARE_CLASS(QDomDocument)
|
||||||
QT_FORWARD_DECLARE_CLASS(QDomNode)
|
QT_FORWARD_DECLARE_CLASS(QDomNode)
|
||||||
@ -419,7 +420,9 @@ void tst_QDom::setGetAttributes()
|
|||||||
const int intVal = std::numeric_limits<int>::min();
|
const int intVal = std::numeric_limits<int>::min();
|
||||||
const uint uintVal = std::numeric_limits<uint>::max();
|
const uint uintVal = std::numeric_limits<uint>::max();
|
||||||
const float floatVal = 0.1234f;
|
const float floatVal = 0.1234f;
|
||||||
const double doubleVal = 0.1234;
|
const double doubleVal1 = 1./6.;
|
||||||
|
const double doubleVal2 = std::nextafter(doubleVal1, 1.);
|
||||||
|
const double doubleVal3 = std::nextafter(doubleVal2, 1.);
|
||||||
|
|
||||||
rootNode.setAttribute("qstringVal", qstringVal);
|
rootNode.setAttribute("qstringVal", qstringVal);
|
||||||
rootNode.setAttribute("qlonglongVal", qlonglongVal);
|
rootNode.setAttribute("qlonglongVal", qlonglongVal);
|
||||||
@ -427,7 +430,9 @@ void tst_QDom::setGetAttributes()
|
|||||||
rootNode.setAttribute("intVal", intVal);
|
rootNode.setAttribute("intVal", intVal);
|
||||||
rootNode.setAttribute("uintVal", uintVal);
|
rootNode.setAttribute("uintVal", uintVal);
|
||||||
rootNode.setAttribute("floatVal", floatVal);
|
rootNode.setAttribute("floatVal", floatVal);
|
||||||
rootNode.setAttribute("doubleVal", doubleVal);
|
rootNode.setAttribute("doubleVal1", doubleVal1);
|
||||||
|
rootNode.setAttribute("doubleVal2", doubleVal2);
|
||||||
|
rootNode.setAttribute("doubleVal3", doubleVal3);
|
||||||
|
|
||||||
QDomElement nsNode = doc.createElement("NS");
|
QDomElement nsNode = doc.createElement("NS");
|
||||||
rootNode.appendChild(nsNode);
|
rootNode.appendChild(nsNode);
|
||||||
@ -437,7 +442,9 @@ void tst_QDom::setGetAttributes()
|
|||||||
nsNode.setAttributeNS("namespace", "intVal", intVal);
|
nsNode.setAttributeNS("namespace", "intVal", intVal);
|
||||||
nsNode.setAttributeNS("namespace", "uintVal", uintVal);
|
nsNode.setAttributeNS("namespace", "uintVal", uintVal);
|
||||||
nsNode.setAttributeNS("namespace", "floatVal", floatVal); // not available atm
|
nsNode.setAttributeNS("namespace", "floatVal", floatVal); // not available atm
|
||||||
nsNode.setAttributeNS("namespace", "doubleVal", doubleVal);
|
nsNode.setAttributeNS("namespace", "doubleVal1", doubleVal1);
|
||||||
|
nsNode.setAttributeNS("namespace", "doubleVal2", doubleVal2);
|
||||||
|
nsNode.setAttributeNS("namespace", "doubleVal3", doubleVal3);
|
||||||
|
|
||||||
bool bOk;
|
bool bOk;
|
||||||
QCOMPARE(rootNode.attribute("qstringVal"), qstringVal);
|
QCOMPARE(rootNode.attribute("qstringVal"), qstringVal);
|
||||||
@ -451,8 +458,10 @@ void tst_QDom::setGetAttributes()
|
|||||||
QVERIFY(bOk);
|
QVERIFY(bOk);
|
||||||
QCOMPARE(rootNode.attribute("floatVal").toFloat(&bOk), floatVal);
|
QCOMPARE(rootNode.attribute("floatVal").toFloat(&bOk), floatVal);
|
||||||
QVERIFY(bOk);
|
QVERIFY(bOk);
|
||||||
QCOMPARE(rootNode.attribute("doubleVal").toDouble(&bOk), doubleVal);
|
|
||||||
QVERIFY(bOk);
|
QVERIFY(rootNode.attribute("doubleVal1").toDouble(&bOk) == doubleVal1 && bOk);
|
||||||
|
QVERIFY(rootNode.attribute("doubleVal2").toDouble(&bOk) == doubleVal2 && bOk);
|
||||||
|
QVERIFY(rootNode.attribute("doubleVal3").toDouble(&bOk) == doubleVal3 && bOk);
|
||||||
|
|
||||||
QCOMPARE(nsNode.attributeNS("namespace", "qstringVal"), qstringVal);
|
QCOMPARE(nsNode.attributeNS("namespace", "qstringVal"), qstringVal);
|
||||||
QCOMPARE(nsNode.attributeNS("namespace", "qlonglongVal").toLongLong(&bOk), qlonglongVal);
|
QCOMPARE(nsNode.attributeNS("namespace", "qlonglongVal").toLongLong(&bOk), qlonglongVal);
|
||||||
@ -465,8 +474,9 @@ void tst_QDom::setGetAttributes()
|
|||||||
QVERIFY(bOk);
|
QVERIFY(bOk);
|
||||||
QCOMPARE(nsNode.attributeNS("namespace", "floatVal").toFloat(&bOk), floatVal);
|
QCOMPARE(nsNode.attributeNS("namespace", "floatVal").toFloat(&bOk), floatVal);
|
||||||
QVERIFY(bOk);
|
QVERIFY(bOk);
|
||||||
QCOMPARE(nsNode.attributeNS("namespace", "doubleVal").toDouble(&bOk), doubleVal);
|
QVERIFY(nsNode.attributeNS("namespace", "doubleVal1").toDouble(&bOk) == doubleVal1 && bOk);
|
||||||
QVERIFY(bOk);
|
QVERIFY(nsNode.attributeNS("namespace", "doubleVal2").toDouble(&bOk) == doubleVal2 && bOk);
|
||||||
|
QVERIFY(nsNode.attributeNS("namespace", "doubleVal3").toDouble(&bOk) == doubleVal3 && bOk);
|
||||||
|
|
||||||
QLocale::setDefault(oldLocale);
|
QLocale::setDefault(oldLocale);
|
||||||
}
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user