summaryrefslogtreecommitdiffstats
path: root/src/gui
diff options
context:
space:
mode:
Diffstat (limited to 'src/gui')
-rw-r--r--src/gui/CMakeLists.txt20
-rw-r--r--src/gui/accessible/linux/atspiadaptor.cpp75
-rw-r--r--src/gui/accessible/linux/atspiadaptor_p.h6
-rw-r--r--src/gui/accessible/qaccessible.cpp83
-rw-r--r--src/gui/accessible/qaccessible.h32
-rw-r--r--src/gui/accessible/qaccessible_base.h7
-rw-r--r--src/gui/accessible/qaccessiblebridge.cpp2
-rw-r--r--src/gui/accessible/qaccessiblebridge.h4
-rw-r--r--src/gui/compat/removed_api.cpp39
-rw-r--r--src/gui/configure.cmake2
-rw-r--r--src/gui/image/qicon.cpp28
-rw-r--r--src/gui/image/qicon_p.h20
-rw-r--r--src/gui/image/qiconengine.h1
-rw-r--r--src/gui/image/qimage.cpp96
-rw-r--r--src/gui/image/qmovie.cpp6
-rw-r--r--src/gui/image/qpixmap.cpp9
-rw-r--r--src/gui/kernel/qevent.h1
-rw-r--r--src/gui/kernel/qguiapplication.cpp50
-rw-r--r--src/gui/kernel/qguiapplication.h2
-rw-r--r--src/gui/kernel/qguiapplication_p.h4
-rw-r--r--src/gui/kernel/qguiapplication_platform.h30
-rw-r--r--src/gui/kernel/qguivariant.cpp2
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h4
-rw-r--r--src/gui/kernel/qopenglcontext.cpp3
-rw-r--r--src/gui/kernel/qplatformtheme.cpp5
-rw-r--r--src/gui/kernel/qplatformtheme.h1
-rw-r--r--src/gui/kernel/qplatformwindow.cpp9
-rw-r--r--src/gui/kernel/qstylehints.cpp91
-rw-r--r--src/gui/kernel/qstylehints.h10
-rw-r--r--src/gui/kernel/qstylehints_p.h3
-rw-r--r--src/gui/kernel/qwindow.cpp30
-rw-r--r--src/gui/kernel/qwindow_p.h12
-rw-r--r--src/gui/painting/qbackingstore.cpp29
-rw-r--r--src/gui/painting/qcolorspace.cpp8
-rw-r--r--src/gui/painting/qcolortransfertable_p.h54
-rw-r--r--src/gui/painting/qcolortransform.cpp116
-rw-r--r--src/gui/painting/qcolortransform_p.h6
-rw-r--r--src/gui/painting/qicc.cpp13
-rw-r--r--src/gui/painting/qpagelayout.cpp150
-rw-r--r--src/gui/painting/qpagelayout.h13
-rw-r--r--src/gui/painting/qpagesize.h2
-rw-r--r--src/gui/platform/ios/qiosnativeinterface.cpp26
-rw-r--r--src/gui/platform/unix/qgenericunixthemes.cpp266
-rw-r--r--src/gui/platform/windows/qwindowsnativeinterface.cpp10
-rw-r--r--src/gui/qt_cmdline.cmake3
-rw-r--r--src/gui/rhi/qrhigles2.cpp16
-rw-r--r--src/gui/rhi/qrhigles2_p.h6
-rw-r--r--src/gui/rhi/qrhimetal.mm35
-rw-r--r--src/gui/rhi/qrhivulkan.cpp24
-rw-r--r--src/gui/rhi/qrhivulkan_p.h4
-rw-r--r--src/gui/text/coretext/qfontengine_coretext.mm30
-rw-r--r--src/gui/text/coretext/qfontengine_coretext_p.h2
-rw-r--r--src/gui/text/freetype/qfontengine_ft.cpp11
-rw-r--r--src/gui/text/freetype/qfontengine_ft_p.h2
-rw-r--r--src/gui/text/qcssparser.cpp62
-rw-r--r--src/gui/text/qcssparser_p.h17
-rw-r--r--src/gui/text/qfont.cpp16
-rw-r--r--src/gui/text/qfont.h1
-rw-r--r--src/gui/text/qfontdatabase.cpp31
-rw-r--r--src/gui/text/qfontengine.cpp79
-rw-r--r--src/gui/text/qfontengine_p.h17
-rw-r--r--src/gui/text/qrawfont.cpp4
-rw-r--r--src/gui/text/qtextdocument.cpp65
-rw-r--r--src/gui/text/qtextdocument.h6
-rw-r--r--src/gui/text/qtextdocumentlayout.cpp8
-rw-r--r--src/gui/text/qtextengine.cpp23
-rw-r--r--src/gui/text/qtextengine_p.h1
-rw-r--r--src/gui/text/qtextformat.cpp40
-rw-r--r--src/gui/text/qtextformat.h8
-rw-r--r--src/gui/text/qtexthtmlparser.cpp62
-rw-r--r--src/gui/text/qtextimagehandler.cpp26
-rw-r--r--src/gui/text/unix/qfontconfigdatabase.cpp102
-rw-r--r--src/gui/text/windows/qwindowsfontengine.cpp16
-rw-r--r--src/gui/text/windows/qwindowsfontengine_p.h4
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite.cpp16
-rw-r--r--src/gui/text/windows/qwindowsfontenginedirectwrite_p.h4
-rw-r--r--src/gui/util/qdesktopservices.cpp42
-rw-r--r--src/gui/util/qgridlayoutengine.cpp4
78 files changed, 1592 insertions, 575 deletions
diff --git a/src/gui/CMakeLists.txt b/src/gui/CMakeLists.txt
index cef71318d8..aed66563a7 100644
--- a/src/gui/CMakeLists.txt
+++ b/src/gui/CMakeLists.txt
@@ -7,7 +7,9 @@ qt_find_package(WrapPNG PROVIDED_TARGETS WrapPNG::WrapPNG)
qt_find_package(WrapFreetype PROVIDED_TARGETS WrapFreetype::WrapFreetype)
if (QT_FEATURE_gui)
- if(WIN32)
+ if(QT_QPA_PLATFORMS)
+ list(GET QT_QPA_PLATFORMS 0 _default_platform)
+ elseif(WIN32)
set(_default_platform "windows")
elseif(ANDROID)
set(_default_platform "android")
@@ -30,6 +32,11 @@ if (QT_FEATURE_gui)
endif()
set(QT_QPA_DEFAULT_PLATFORM "${_default_platform}" CACHE STRING "QPA default platform")
+ if(NOT "${QT_QPA_DEFAULT_PLATFORM}" IN_LIST QT_QPA_PLATFORMS)
+ list(APPEND QT_QPA_PLATFORMS "${QT_QPA_DEFAULT_PLATFORM}")
+ set(QT_QPA_PLATFORMS "${QT_QPA_PLATFORMS}" CACHE STRING
+ "QPA platforms deployed by default" FORCE)
+ endif()
endif()
# Silence warnings in 3rdparty code
@@ -376,6 +383,11 @@ qt_internal_extend_target(Gui CONDITION MACOS
${FWAppKit}
)
+qt_internal_extend_target(Gui CONDITION UIKIT
+ SOURCES
+ platform/ios/qiosnativeinterface.cpp
+)
+
qt_internal_extend_target(Gui CONDITION WASM
SOURCES
platform/wasm/qwasmnativeinterface.cpp
@@ -402,6 +414,12 @@ qt_internal_extend_target(Gui CONDITION APPLE
${FWImageIO}
)
+qt_internal_extend_target(Gui CONDITION QNX
+ SOURCES
+ painting/qrasterbackingstore.cpp painting/qrasterbackingstore_p.h
+ painting/qrhibackingstore.cpp painting/qrhibackingstore_p.h
+)
+
qt_internal_extend_target(Gui CONDITION QT_FEATURE_animation
SOURCES
animation/qguivariantanimation.cpp
diff --git a/src/gui/accessible/linux/atspiadaptor.cpp b/src/gui/accessible/linux/atspiadaptor.cpp
index b3269a2a95..a83dec4e64 100644
--- a/src/gui/accessible/linux/atspiadaptor.cpp
+++ b/src/gui/accessible/linux/atspiadaptor.cpp
@@ -35,6 +35,13 @@
#define ATSPI_COORD_TYPE_PARENT 2
#endif
+// ATSPI_*_VERSION defines were added in libatspi 2.50,
+// as was the AtspiLive enum; define values here for older versions
+#if !defined(ATSPI_MAJOR_VERSION) || !defined(ATSPI_MINOR_VERSION) || ATSPI_MAJOR_VERSION < 2 || ATSPI_MINOR_VERSION < 50
+#define ATSPI_LIVE_POLITE 1
+#define ATSPI_LIVE_ASSERTIVE 2
+#endif
+
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
@@ -47,6 +54,7 @@ AtSpiAdaptor::AtSpiAdaptor(DBusConnection *connection, QObject *parent)
, sendFocus(0)
, sendObject(0)
, sendObject_active_descendant_changed(0)
+ , sendObject_announcement(0)
, sendObject_attributes_changed(0)
, sendObject_bounds_changed(0)
, sendObject_children_changed(0)
@@ -127,6 +135,7 @@ QString AtSpiAdaptor::introspect(const QString &path) const
" <interface name=\"org.a11y.atspi.Accessible\">\n"
" <property access=\"read\" type=\"s\" name=\"Name\"/>\n"
" <property access=\"read\" type=\"s\" name=\"Description\"/>\n"
+ " <property access=\"read\" type=\"s\" name=\"HelpText\"/>\n"
" <property access=\"read\" type=\"(so)\" name=\"Parent\">\n"
" <annotation value=\"QSpiObjectReference\" name=\"org.qtproject.QtDBus.QtTypeName\"/>\n"
" </property>\n"
@@ -678,6 +687,8 @@ void AtSpiAdaptor::setBitFlag(const QString &flag)
if (false) {
} else if (right.startsWith("ActiveDescendantChanged"_L1)) {
sendObject_active_descendant_changed = 1;
+ } else if (right.startsWith("Announcement"_L1)) {
+ sendObject_announcement = 1;
} else if (right.startsWith("AttributesChanged"_L1)) {
sendObject_attributes_changed = 1;
} else if (right.startsWith("BoundsChanged"_L1)) {
@@ -929,6 +940,26 @@ void AtSpiAdaptor::notifyStateChange(QAccessibleInterface *interface, const QStr
sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "StateChanged"_L1, stateArgs);
}
+void AtSpiAdaptor::sendAnnouncement(QAccessibleAnnouncementEvent *event)
+{
+ QAccessibleInterface *iface = event->accessibleInterface();
+ if (!iface) {
+ qCWarning(lcAccessibilityAtspi, "Announcement event has no accessible set.");
+ return;
+ }
+ if (!iface->isValid()) {
+ qCWarning(lcAccessibilityAtspi) << "Announcement event with invalid accessible: " << iface;
+ return;
+ }
+
+ const QString path = pathForInterface(iface);
+ const QString message = event->message();
+ const QAccessible::AnnouncementPriority prio = event->priority();
+ const int politeness = (prio == QAccessible::AnnouncementPriority::Assertive) ? ATSPI_LIVE_ASSERTIVE : ATSPI_LIVE_POLITE;
+
+ const QVariantList args = packDBusSignalArguments(QString(), politeness, 0, QVariant::fromValue(QDBusVariant(message)));
+ sendDBusSignal(path, ATSPI_DBUS_INTERFACE_EVENT_OBJECT ""_L1, "Announcement"_L1, args);
+}
/*!
This function gets called when Qt notifies about accessibility updates.
@@ -1003,6 +1034,14 @@ void AtSpiAdaptor::notify(QAccessibleEvent *event)
sendFocusChanged(event->accessibleInterface());
break;
}
+
+ case QAccessible::Announcement: {
+ if (sendObject || sendObject_announcement) {
+ QAccessibleAnnouncementEvent *announcementEvent = static_cast<QAccessibleAnnouncementEvent*>(event);
+ sendAnnouncement(announcementEvent);
+ }
+ break;
+ }
case QAccessible::TextInserted:
case QAccessible::TextRemoved:
case QAccessible::TextUpdated: {
@@ -1586,6 +1625,8 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
sendReply(connection, message, accessibleInterfaces(interface));
} else if (function == "GetDescription"_L1) {
sendReply(connection, message, QVariant::fromValue(QDBusVariant(interface->text(QAccessible::Description))));
+ } else if (function == "GetHelpText"_L1) {
+ sendReply(connection, message, QVariant::fromValue(QDBusVariant(interface->text(QAccessible::Help))));
} else if (function == "GetState"_L1) {
quint64 spiState = spiStatesFromQState(interface->state());
if (interface->tableInterface()) {
@@ -1606,7 +1647,7 @@ bool AtSpiAdaptor::accessibleInterface(QAccessibleInterface *interface, const QS
sendReply(connection, message,
QVariant::fromValue(spiStateSetFromSpiStates(spiState)));
} else if (function == "GetAttributes"_L1) {
- sendReply(connection, message, QVariant::fromValue(QSpiAttributeSet()));
+ sendReply(connection, message, QVariant::fromValue(getAttributes(interface)));
} else if (function == "GetRelationSet"_L1) {
sendReply(connection, message, QVariant::fromValue(relationSet(interface, connection)));
} else if (function == "GetApplication"_L1) {
@@ -2264,6 +2305,38 @@ namespace
}
}
+QSpiAttributeSet AtSpiAdaptor::getAttributes(QAccessibleInterface *interface) const
+{
+ QSpiAttributeSet set;
+ QAccessibleAttributesInterface *attributesIface = interface->attributesInterface();
+ if (!attributesIface)
+ return set;
+
+ const QList<QAccessible::Attribute> attrKeys = attributesIface->attributeKeys();
+ for (QAccessible::Attribute key : attrKeys) {
+ const QVariant value = attributesIface->attributeValue(key);
+ // see "Core Accessibility API Mappings" spec: https://www.w3.org/TR/core-aam-1.2/
+ switch (key) {
+ case QAccessible::Attribute::Custom:
+ {
+ // forward custom attributes to AT-SPI as-is
+ Q_ASSERT((value.canConvert<QHash<QString, QString>>()));
+ const QHash<QString, QString> attrMap = value.value<QHash<QString, QString>>();
+ for (auto [name, val] : attrMap.asKeyValueRange())
+ set.insert(name, val);
+ break;
+ }
+ case QAccessible::Attribute::Level:
+ Q_ASSERT(value.canConvert<int>());
+ set.insert(QStringLiteral("level"), QString::number(value.toInt()));
+ break;
+ default:
+ break;
+ }
+ }
+ return set;
+}
+
// FIXME all attribute methods below should share code
QVariantList AtSpiAdaptor::getAttributes(QAccessibleInterface *interface, int offset, bool includeDefaults) const
{
diff --git a/src/gui/accessible/linux/atspiadaptor_p.h b/src/gui/accessible/linux/atspiadaptor_p.h
index 3a890f3d7d..68a455e7cb 100644
--- a/src/gui/accessible/linux/atspiadaptor_p.h
+++ b/src/gui/accessible/linux/atspiadaptor_p.h
@@ -16,7 +16,7 @@
// We mean it.
//
-#include <atspi/atspi-constants.h>
+#include <atspi/atspi.h>
#include <QtGui/private/qtguiglobal_p.h>
#include <QtDBus/qdbusvirtualobject.h>
@@ -85,8 +85,11 @@ private:
void notifyStateChange(QAccessibleInterface *interface, const QString& state, int value);
+ void sendAnnouncement(QAccessibleAnnouncementEvent *event);
+
// accessible helper functions
AtspiRole getRole(QAccessibleInterface *interface) const;
+ QSpiAttributeSet getAttributes(QAccessibleInterface *) const;
QSpiRelationArray relationSet(QAccessibleInterface *interface, const QDBusConnection &connection) const;
QStringList accessibleInterfaces(QAccessibleInterface *interface) const;
@@ -130,6 +133,7 @@ private:
// all of object
uint sendObject : 1;
uint sendObject_active_descendant_changed : 1;
+ uint sendObject_announcement : 1;
uint sendObject_attributes_changed : 1;
uint sendObject_bounds_changed : 1;
uint sendObject_children_changed : 1;
diff --git a/src/gui/accessible/qaccessible.cpp b/src/gui/accessible/qaccessible.cpp
index 46bca16dad..eec779efb1 100644
--- a/src/gui/accessible/qaccessible.cpp
+++ b/src/gui/accessible/qaccessible.cpp
@@ -173,6 +173,7 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\value ActionChanged An action has been changed.
\value ActiveDescendantChanged
\value Alert A system alert (e.g., a message from a QMessageBox)
+ \value [since 6.8] Announcement The announcement of a message is requested.
\value AttributeChanged
\value ContextHelpEnd Context help (QWhatsThis) for an object is finished.
\value ContextHelpStart Context help (QWhatsThis) for an object is initiated.
@@ -449,6 +450,30 @@ Q_LOGGING_CATEGORY(lcAccessibilityCore, "qt.accessibility.core");
\sa QAccessibleAttributesInterface
*/
+/*! \enum QAccessible::AnnouncementPriority
+ This enum describes the priority for announcements used by the
+ \l QAccessibleAnnouncementEvent.
+ \since 6.8
+
+ With \a QAccessible::AnouncementPriority::Polite, assistive technologies
+ should announce the message at the next graceful opportunity such as at the
+ end of speaking the current sentence or when the user pauses typing.
+
+ When specifying \a QAccessible::AnouncementPriority::Assertive, assistive
+ technologies should notify the user immediately.
+
+ Because an interruption might disorient users or cause them to not complete
+ their current task, \a QAccessible::AnouncementPriority::Assertive should
+ not be used unless the interruption is imperative.
+
+ \value Polite The announcement has normal priority.
+ \value Assertive The announcement has high priority and should notify
+ the user immediately, even if that means interrupting the user's
+ current task.
+
+ \sa QAccessibleAnnouncementEvent
+*/
+
/*!
\enum QAccessible::InterfaceType
@@ -1778,9 +1803,58 @@ QAccessibleTextSelectionEvent::~QAccessibleTextSelectionEvent()
{
}
+/*!
+ \since 6.8
+ \class QAccessibleAnnouncementEvent
+ \ingroup accessibility
+ \inmodule QtGui
+
+ \brief The QAccessibleAnnouncementEvent is used to request the announcement
+ of a given message by assistive technologies.
+
+ This class is used with \l QAccessible::updateAccessibility().
+*/
+
+/*! \fn QAccessibleAnnouncementEvent::QAccessibleAnnouncementEvent(QObject *object, const QString &message)
+
+ Constructs a new QAccessibleAnnouncementEvent event for \a object
+ to request the announcement of \a message with priority \l QAccessible::AnnouncementPriority::Polite.
+
+ \l QAccessibleAnnouncementEvent::setPriority can be used to adjust the priority.
+*/
+
+/*! \fn QAccessibleAnnouncementEvent::QAccessibleAnnouncementEvent(QAccessibleInterface *iface, const QString &message)
+
+ Constructs a new QAccessibleAnnouncementEvent event for \a iface
+ to request the announcement of \a message with priority \l QAccessible::AnnouncementPriority::Polite.
+
+ \l QAccessibleAnnouncementEvent::setPriority can be used to adjust the priority.
+*/
+
+/*! \fn QString QAccessibleAnnouncementEvent::message() const
+
+ Returns the message.
+*/
+
+/*! \fn QAccessible::AnnouncementPriority QAccessibleAnnouncementEvent::priority() const
+
+ Returns the priority.
+*/
+
+/*! \fn void QAccessibleAnnouncementEvent::setPriority(QAccessible::AnnouncementPriority priority)
+
+ Sets the priority with which the announcement will be requested to \a priority.
+*/
/*!
+ \internal
+*/
+QAccessibleAnnouncementEvent::~QAccessibleAnnouncementEvent()
+{
+}
+
+/*!
Returns the QAccessibleInterface associated with the event.
*/
QAccessibleInterface *QAccessibleEvent::accessibleInterface() const
@@ -3118,7 +3192,7 @@ bool QAccessibleSelectionInterface::isSelected(QAccessibleInterface *childItem)
Attributes are key-value pairs. Values are stored in \l QVariant.
- The \a QAccessible::Attributes enumeration describes the available keys and
+ The \l QAccessible::Attribute enumeration describes the available keys and
documents which type to use for the value of each key.
While the text-specific attributes handled by \l QAccessibleTextInterface::attributes
@@ -3151,8 +3225,11 @@ QAccessibleAttributesInterface::~QAccessibleAttributesInterface()
Returns the value of the attribute \a key of this object.
- If the specificed attribute is not set for this object, an invalid
- \l QVariant is returned.
+ If the attribute is set for this object, a value of the type documented for the
+ given key in the documentation of the \l QAccessible::Attribute enumeration is
+ returned in the \l QVariant.
+
+ Otherwise, an invalid \l QVariant is returned.
*/
/*! \internal */
diff --git a/src/gui/accessible/qaccessible.h b/src/gui/accessible/qaccessible.h
index 0a92e76c73..3d8daa4b3c 100644
--- a/src/gui/accessible/qaccessible.h
+++ b/src/gui/accessible/qaccessible.h
@@ -316,6 +316,7 @@ public:
Q_ASSERT(m_type != QAccessible::TextRemoved);
Q_ASSERT(m_type != QAccessible::TextUpdated);
Q_ASSERT(m_type != QAccessible::TableModelChanged);
+ Q_ASSERT(m_type != QAccessible::Announcement);
}
inline QAccessibleEvent(QAccessibleInterface *iface, QAccessible::Event typ)
@@ -330,6 +331,7 @@ public:
Q_ASSERT(m_type != QAccessible::TextRemoved);
Q_ASSERT(m_type != QAccessible::TextUpdated);
Q_ASSERT(m_type != QAccessible::TableModelChanged);
+ Q_ASSERT(m_type != QAccessible::Announcement);
m_uniqueId = QAccessible::uniqueId(iface);
m_object = iface->object();
}
@@ -605,6 +607,36 @@ protected:
int m_lastColumn;
};
+class Q_GUI_EXPORT QAccessibleAnnouncementEvent : public QAccessibleEvent
+{
+public:
+ inline QAccessibleAnnouncementEvent(QObject *object, const QString &message)
+ : QAccessibleEvent(object, QAccessible::InvalidEvent)
+ , m_message(message)
+ , m_priority(QAccessible::AnnouncementPriority::Polite)
+ {
+ m_type = QAccessible::Announcement;
+ }
+
+ inline QAccessibleAnnouncementEvent(QAccessibleInterface *iface, const QString &message)
+ : QAccessibleEvent(iface, QAccessible::InvalidEvent)
+ , m_message(message)
+ , m_priority(QAccessible::AnnouncementPriority::Polite)
+ {
+ m_type = QAccessible::Announcement;
+ }
+
+ ~QAccessibleAnnouncementEvent();
+
+ QString message() const { return m_message; }
+ QAccessible::AnnouncementPriority priority() const { return m_priority; }
+ void setPriority(QAccessible::AnnouncementPriority priority) { m_priority = priority; };
+
+protected:
+ QString m_message;
+ QAccessible::AnnouncementPriority m_priority;
+};
+
#ifndef Q_QDOC
#define QAccessibleInterface_iid "org.qt-project.Qt.QAccessibleInterface"
Q_DECLARE_INTERFACE(QAccessibleInterface, QAccessibleInterface_iid)
diff --git a/src/gui/accessible/qaccessible_base.h b/src/gui/accessible/qaccessible_base.h
index 2d2b1de316..1ca3dadc36 100644
--- a/src/gui/accessible/qaccessible_base.h
+++ b/src/gui/accessible/qaccessible_base.h
@@ -101,6 +101,7 @@ public:
HelpChanged = 0x80A0,
DefaultActionChanged = 0x80B0,
AcceleratorChanged = 0x80C0,
+ Announcement = 0x80D0,
InvalidEvent
};
@@ -367,6 +368,12 @@ public:
Level,
};
+ enum class AnnouncementPriority {
+ Polite,
+ Assertive
+ };
+ Q_ENUM(AnnouncementPriority)
+
typedef QAccessibleInterface*(*InterfaceFactory)(const QString &key, QObject*);
typedef void(*UpdateHandler)(QAccessibleEvent *event);
typedef void(*RootObjectHandler)(QObject*);
diff --git a/src/gui/accessible/qaccessiblebridge.cpp b/src/gui/accessible/qaccessiblebridge.cpp
index a8b54b0c68..0651c516ea 100644
--- a/src/gui/accessible/qaccessiblebridge.cpp
+++ b/src/gui/accessible/qaccessiblebridge.cpp
@@ -33,6 +33,8 @@ QT_BEGIN_NAMESPACE
Destroys the accessibility bridge object.
*/
+QAccessibleBridge::~QAccessibleBridge()
+ = default;
/*!
\fn void QAccessibleBridge::setRootObject(QAccessibleInterface *object)
diff --git a/src/gui/accessible/qaccessiblebridge.h b/src/gui/accessible/qaccessiblebridge.h
index 4d817c8e58..753f59597a 100644
--- a/src/gui/accessible/qaccessiblebridge.h
+++ b/src/gui/accessible/qaccessiblebridge.h
@@ -16,10 +16,10 @@ QT_BEGIN_NAMESPACE
class QAccessibleInterface;
class QAccessibleEvent;
-class QAccessibleBridge
+class Q_GUI_EXPORT QAccessibleBridge
{
public:
- virtual ~QAccessibleBridge() {}
+ virtual ~QAccessibleBridge();
virtual void setRootObject(QAccessibleInterface *) = 0;
virtual void notifyAccessibilityUpdate(QAccessibleEvent *event) = 0;
};
diff --git a/src/gui/compat/removed_api.cpp b/src/gui/compat/removed_api.cpp
index a64580e9e1..a642c33c42 100644
--- a/src/gui/compat/removed_api.cpp
+++ b/src/gui/compat/removed_api.cpp
@@ -7,6 +7,17 @@
QT_USE_NAMESPACE
+#if QT_GUI_REMOVED_SINCE(6, 4)
+
+#include "qpagesize.h" // removed duplicate declaration of op==
+ // (still caused an symbol on some platforms)
+
+// #include "qotherheader.h"
+// // implement removed functions from qotherheader.h
+// order sections alphabetically
+
+#endif // QT_GUI_REMOVED_SINCE(6, 4)
+
#if QT_GUI_REMOVED_SINCE(6, 6)
#include "qpixmapcache.h" // inlined API
@@ -26,8 +37,34 @@ bool Qt::mightBeRichText(const QString& text)
return Qt::mightBeRichText(qToStringViewIgnoringNull(text));
}
+#endif // QT_GUI_REMOVED_SINCE(6, 7)
+
+#if QT_GUI_REMOVED_SINCE(6, 8)
+
+#include "qpagelayout.h"
+
+bool QPageLayout::setMargins(const QMarginsF &margins)
+{
+ return setMargins(margins, OutOfBoundsPolicy::Reject);
+}
+
+bool QPageLayout::setLeftMargin(qreal leftMargin)
+{
+ return setLeftMargin(leftMargin, OutOfBoundsPolicy::Reject);
+}
+
+bool QPageLayout::setRightMargin(qreal rightMargin)
+{
+ return setRightMargin(rightMargin, OutOfBoundsPolicy::Reject);
+}
+
+bool QPageLayout::setTopMargin(qreal topMargin)
+{
+ return setTopMargin(topMargin, OutOfBoundsPolicy::Reject);
+}
+
// #include "qotherheader.h"
// // implement removed functions from qotherheader.h
// order sections alphabetically
-#endif // QT_GUI_REMOVED_SINCE(6, 7)
+#endif // QT_GUI_REMOVED_SINCE(6, 8)
diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake
index e1d8efb292..da08863ac6 100644
--- a/src/gui/configure.cmake
+++ b/src/gui/configure.cmake
@@ -893,7 +893,7 @@ qt_feature("jpeg" PRIVATE
CONDITION QT_FEATURE_imageformatplugin
DISABLE INPUT_libjpeg STREQUAL 'no'
)
-qt_feature_definition("jpeg" "QT_NO_IMAGEFORMAT_JPEG" NEGATE)
+qt_feature_definition("jpeg" "QT_NO_IMAGEFORMAT_JPEG" NEGATE VALUE "1")
qt_feature("system-jpeg" PRIVATE
LABEL " Using system libjpeg"
CONDITION QT_FEATURE_jpeg AND JPEG_FOUND
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 086ac37a07..82e78409f2 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -160,15 +160,16 @@ static inline int area(const QSize &s) { return s.width() * s.height(); }
// the 2x pixmaps then.)
static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale, QPixmapIconEngineEntry *pa, QPixmapIconEngineEntry *pb)
{
-
+ const auto scaleA = pa->pixmap.devicePixelRatio();
+ const auto scaleB = pb->pixmap.devicePixelRatio();
// scale: we can only differentiate on scale if the scale differs
- if (pa->scale != pb->scale) {
+ if (scaleA != scaleB) {
// Score the pixmaps: 0 is an exact scale match, positive
// scores have more detail than requested, negative scores
// have less detail than requested.
- qreal ascore = pa->scale - scale;
- qreal bscore = pb->scale - scale;
+ qreal ascore = scaleA - scale;
+ qreal bscore = scaleB - scale;
// always prefer positive scores to prevent upscaling
if ((ascore < 0) != (bscore < 0))
@@ -201,13 +202,14 @@ static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale
QPixmapIconEngineEntry *QPixmapIconEngine::tryMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state)
{
QPixmapIconEngineEntry *pe = nullptr;
- for (int i = 0; i < pixmaps.size(); ++i)
- if (pixmaps.at(i).mode == mode && pixmaps.at(i).state == state) {
+ for (auto &entry : pixmaps) {
+ if (entry.mode == mode && entry.state == state) {
if (pe)
- pe = bestSizeScaleMatch(size, scale, &pixmaps[i], pe);
+ pe = bestSizeScaleMatch(size, scale, &entry, pe);
else
- pe = &pixmaps[i];
+ pe = &entry;
}
+ }
return pe;
}
@@ -278,7 +280,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc
pm = pe->pixmap;
if (pm.isNull()) {
- int idx = pixmaps.size();
+ auto idx = pixmaps.size();
while (--idx >= 0) {
if (pe == &pixmaps.at(idx)) {
pixmaps.remove(idx);
@@ -369,7 +371,7 @@ void QPixmapIconEngine::addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon
{
if (!pixmap.isNull()) {
QPixmapIconEngineEntry *pe = tryMatch(pixmap.size(), pixmap.devicePixelRatio(), mode, state);
- if (pe && pe->size == pixmap.size() && pe->scale == pixmap.devicePixelRatio()) {
+ if (pe && pe->size == pixmap.size() && pe->pixmap.devicePixelRatio() == pixmap.devicePixelRatio()) {
pe->pixmap = pixmap;
pe->fileName.clear();
} else {
@@ -387,7 +389,7 @@ static inline int origIcoDepth(const QImage &image)
static inline int findBySize(const QList<QImage> &images, const QSize &size)
{
- for (int i = 0; i < images.size(); ++i) {
+ for (qsizetype i = 0; i < images.size(); ++i) {
if (images.at(i).size() == size)
return i;
}
@@ -862,7 +864,9 @@ QPixmap QIcon::pixmap(const QSize &size, Mode mode, State state) const
\since 6.0
Returns a pixmap with the requested \a size, \a devicePixelRatio, \a mode, and \a
- state, generating one if necessary.
+ state, generating one with the given \a mode and \a state if necessary. The pixmap
+ might be smaller than requested, but never larger, unless the device-pixel ratio
+ of the returned pixmap is larger than 1.
\sa actualSize(), paint()
*/
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index c5bf120620..dfce2d5b53 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -49,24 +49,22 @@ public:
struct QPixmapIconEngineEntry
{
- QPixmapIconEngineEntry():scale(1), mode(QIcon::Normal), state(QIcon::Off){}
- QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
- :pixmap(pm), size(pm.size()), scale(pm.devicePixelRatio()), mode(m), state(s){}
- QPixmapIconEngineEntry(const QString &file, const QSize &sz = QSize(), QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off)
- :fileName(file), size(sz), scale(1), mode(m), state(s){}
- QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m = QIcon::Normal, QIcon::State s = QIcon::Off);
+ QPixmapIconEngineEntry() = default;
+ QPixmapIconEngineEntry(const QPixmap &pm, QIcon::Mode m, QIcon::State s)
+ : pixmap(pm), size(pm.size()), mode(m), state(s) {}
+ QPixmapIconEngineEntry(const QString &file, const QSize &sz, QIcon::Mode m, QIcon::State s)
+ : fileName(file), size(sz), mode(m), state(s) {}
+ QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m, QIcon::State s);
QPixmap pixmap;
QString fileName;
QSize size;
- qreal scale;
- QIcon::Mode mode;
- QIcon::State state;
- bool isNull() const {return (fileName.isEmpty() && pixmap.isNull()); }
+ QIcon::Mode mode = QIcon::Normal;
+ QIcon::State state = QIcon::Off;
};
Q_DECLARE_TYPEINFO(QPixmapIconEngineEntry, Q_RELOCATABLE_TYPE);
inline QPixmapIconEngineEntry::QPixmapIconEngineEntry(const QString &file, const QImage &image, QIcon::Mode m, QIcon::State s)
- : fileName(file), size(image.size()), scale(image.devicePixelRatio()), mode(m), state(s)
+ : fileName(file), size(image.size()), mode(m), state(s)
{
pixmap.convertFromImage(image);
}
diff --git a/src/gui/image/qiconengine.h b/src/gui/image/qiconengine.h
index 61411b0660..f5c5184608 100644
--- a/src/gui/image/qiconengine.h
+++ b/src/gui/image/qiconengine.h
@@ -18,6 +18,7 @@ public:
virtual ~QIconEngine();
virtual void paint(QPainter *painter, const QRect &rect, QIcon::Mode mode, QIcon::State state) = 0;
virtual QSize actualSize(const QSize &size, QIcon::Mode mode, QIcon::State state);
+ // ### Qt7: add qreal scale argument and remove scaledPixmap
virtual QPixmap pixmap(const QSize &size, QIcon::Mode mode, QIcon::State state);
virtual void addPixmap(const QPixmap &pixmap, QIcon::Mode mode, QIcon::State state);
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index a23bdfcadd..a24d7ccde7 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -713,39 +713,60 @@ bool QImageData::checkForAlphaPixels() const
The unused bits are always zero.
\value Format_ARGB4444_Premultiplied The image is stored using a
premultiplied 16-bit ARGB format (4-4-4-4).
- \value Format_RGBX8888 The image is stored using a 32-bit byte-ordered RGB(x) format (8-8-8-8).
- This is the same as the Format_RGBA8888 except alpha must always be 255. (added in Qt 5.2)
- \value Format_RGBA8888 The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8).
+ \value [since 5.2]
+ Format_RGBX8888 The image is stored using a 32-bit byte-ordered RGB(x) format (8-8-8-8).
+ This is the same as the Format_RGBA8888 except alpha must always be 255.
+ \value [since 5.2]
+ Format_RGBA8888 The image is stored using a 32-bit byte-ordered RGBA format (8-8-8-8).
Unlike ARGB32 this is a byte-ordered format, which means the 32bit
encoding differs between big endian and little endian architectures,
being respectively (0xRRGGBBAA) and (0xAABBGGRR). The order of the colors
- is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA. (added in Qt 5.2)
- \value Format_RGBA8888_Premultiplied The image is stored using a
- premultiplied 32-bit byte-ordered RGBA format (8-8-8-8). (added in Qt 5.2)
- \value Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10). (added in Qt 5.4)
- \value Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10). (added in Qt 5.4)
- \value Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10). (added in Qt 5.4)
- \value Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10). (added in Qt 5.4)
- \value Format_Alpha8 The image is stored using an 8-bit alpha only format. (added in Qt 5.5)
- \value Format_Grayscale8 The image is stored using an 8-bit grayscale format. (added in Qt 5.5)
- \value Format_Grayscale16 The image is stored using an 16-bit grayscale format. (added in Qt 5.13)
- \value Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
- This is the same as the Format_RGBA64 except alpha must always be 65535. (added in Qt 5.12)
- \value Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16). (added in Qt 5.12)
- \value Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
- RGBA format (16-16-16-16). (added in Qt 5.12)
- \value Format_BGR888 The image is stored using a 24-bit BGR format. (added in Qt 5.14)
- \value Format_RGBX16FPx4 The image is stored using a 4 16-bit halfword floating point RGBx format (16FP-16FP-16FP-16FP).
- This is the same as the Format_RGBA16FPx4 except alpha must always be 1.0. (added in Qt 6.2)
- \value Format_RGBA16FPx4 The image is stored using a 4 16-bit halfword floating point RGBA format (16FP-16FP-16FP-16FP). (added in Qt 6.2)
- \value Format_RGBA16FPx4_Premultiplied The image is stored using a premultiplied 4 16-bit halfword floating point
- RGBA format (16FP-16FP-16FP-16FP). (added in Qt 6.2)
- \value Format_RGBX32FPx4 The image is stored using a 4 32-bit floating point RGBx format (32FP-32FP-32FP-32FP).
- This is the same as the Format_RGBA32FPx4 except alpha must always be 1.0. (added in Qt 6.2)
- \value Format_RGBA32FPx4 The image is stored using a 4 32-bit floating point RGBA format (32FP-32FP-32FP-32FP). (added in Qt 6.2)
- \value Format_RGBA32FPx4_Premultiplied The image is stored using a premultiplied 4 32-bit floating point
- RGBA format (32FP-32FP-32FP-32FP). (added in Qt 6.2)
- \value Format_CMYK8888 The image is stored using a 32-bit byte-ordered CMYK format. (added in Qt 6.8)
+ is the same on any architecture if read as bytes 0xRR,0xGG,0xBB,0xAA.
+ \value [since 5.2]
+ Format_RGBA8888_Premultiplied The image is stored using a
+ premultiplied 32-bit byte-ordered RGBA format (8-8-8-8).
+ \value [since 5.4]
+ Format_BGR30 The image is stored using a 32-bit BGR format (x-10-10-10).
+ \value [since 5.4]
+ Format_A2BGR30_Premultiplied The image is stored using a 32-bit premultiplied ABGR format (2-10-10-10).
+ \value [since 5.4]
+ Format_RGB30 The image is stored using a 32-bit RGB format (x-10-10-10).
+ \value [since 5.4]
+ Format_A2RGB30_Premultiplied The image is stored using a 32-bit premultiplied ARGB format (2-10-10-10).
+ \value [since 5.5]
+ Format_Alpha8 The image is stored using an 8-bit alpha only format.
+ \value [since 5.5]
+ Format_Grayscale8 The image is stored using an 8-bit grayscale format.
+ \value [since 5.13]
+ Format_Grayscale16 The image is stored using an 16-bit grayscale format.
+ \value [since 5.12]
+ Format_RGBX64 The image is stored using a 64-bit halfword-ordered RGB(x) format (16-16-16-16).
+ This is the same as the Format_RGBA64 except alpha must always be 65535.
+ \value [since 5.12]
+ Format_RGBA64 The image is stored using a 64-bit halfword-ordered RGBA format (16-16-16-16).
+ \value [since 5.12]
+ Format_RGBA64_Premultiplied The image is stored using a premultiplied 64-bit halfword-ordered
+ RGBA format (16-16-16-16).
+ \value [since 5.14]
+ Format_BGR888 The image is stored using a 24-bit BGR format.
+ \value [since 6.2]
+ Format_RGBX16FPx4 The image is stored using a four 16-bit halfword floating point RGBx format (16FP-16FP-16FP-16FP).
+ This is the same as the Format_RGBA16FPx4 except alpha must always be 1.0.
+ \value [since 6.2]
+ Format_RGBA16FPx4 The image is stored using a four 16-bit halfword floating point RGBA format (16FP-16FP-16FP-16FP).
+ \value [since 6.2]
+ Format_RGBA16FPx4_Premultiplied The image is stored using a premultiplied four 16-bit halfword floating point
+ RGBA format (16FP-16FP-16FP-16FP).
+ \value [since 6.2]
+ Format_RGBX32FPx4 The image is stored using a four 32-bit floating point RGBx format (32FP-32FP-32FP-32FP).
+ This is the same as the Format_RGBA32FPx4 except alpha must always be 1.0.
+ \value [since 6.2]
+ Format_RGBA32FPx4 The image is stored using a four 32-bit floating point RGBA format (32FP-32FP-32FP-32FP).
+ \value [since 6.2]
+ Format_RGBA32FPx4_Premultiplied The image is stored using a premultiplied four 32-bit floating point
+ RGBA format (32FP-32FP-32FP-32FP).
+ \value [since 6.8]
+ Format_CMYK8888 The image is stored using a 32-bit byte-ordered CMYK format.
\note Drawing into a QImage with format QImage::Format_Indexed8 or QImage::Format_CMYK8888 is not
supported.
@@ -1072,7 +1093,6 @@ QImage &QImage::operator=(const QImage &image)
/*!
\fn void QImage::swap(QImage &other)
- \since 4.8
Swaps image \a other with this image. This operation is very
fast and never fails.
@@ -1151,9 +1171,10 @@ static void copyPhysicalMetadata(QImageData *dst, const QImageData *src)
static void copyMetadata(QImageData *dst, const QImageData *src)
{
- // Doesn't copy colortable and alpha_clut, or offset.
+ // Doesn't copy colortable and alpha_clut.
copyPhysicalMetadata(dst, src);
dst->text = src->text;
+ dst->offset = src->offset;
dst->colorSpace = src->colorSpace;
}
@@ -1218,7 +1239,6 @@ QImage Q_TRACE_INSTRUMENT(qtgui) QImage::copy(const QRect& r) const
} else
memcpy(image.bits(), bits(), d->nbytes);
image.d->colortable = d->colortable;
- image.d->offset = d->offset;
image.d->has_alpha_clut = d->has_alpha_clut;
copyMetadata(image.d, d);
return image;
@@ -1307,7 +1327,6 @@ QImage Q_TRACE_INSTRUMENT(qtgui) QImage::copy(const QRect& r) const
}
copyMetadata(image.d, d);
- image.d->offset = offset();
image.d->has_alpha_clut = d->has_alpha_clut;
return image;
}
@@ -1392,7 +1411,6 @@ int QImage::depth() const
}
/*!
- \since 4.6
\fn int QImage::colorCount() const
Returns the size of the color table for the image.
@@ -1656,7 +1674,6 @@ const uchar *QImage::scanLine(int i) const
shared pixel data, because the returned data is const.
\sa scanLine(), constBits()
- \since 4.7
*/
const uchar *QImage::constScanLine(int i) const
{
@@ -1712,7 +1729,6 @@ const uchar *QImage::bits() const
shared pixel data, because the returned data is const.
\sa bits(), constScanLine()
- \since 4.7
*/
const uchar *QImage::constBits() const
{
@@ -1819,7 +1835,6 @@ void QImage::fill(uint pixel)
/*!
\fn void QImage::fill(Qt::GlobalColor color)
\overload
- \since 4.8
Fills the image with the given \a color, described as a standard global
color.
@@ -1845,8 +1860,6 @@ void QImage::fill(Qt::GlobalColor color)
If the depth of the image is 8, the image will be filled with the
index corresponding the \a color in the color table if present; it
will otherwise be filled with 0.
-
- \since 4.8
*/
void QImage::fill(const QColor &color)
@@ -2103,7 +2116,6 @@ void QImage::invertPixels(InvertMode mode)
#endif
/*!
- \since 4.6
Resizes the color table to contain \a colorCount entries.
If the color table is expanded, all the extra colors will be set to
@@ -2207,7 +2219,6 @@ QImage QImage::convertToFormat_helper(Format format, Qt::ImageConversionFlags fl
QIMAGE_SANITYCHECK_MEMORY(image);
- image.d->offset = offset();
copyMetadata(image.d, d);
converter(image.d, d, flags);
@@ -4588,7 +4599,6 @@ bool QImage::hasAlphaChannel() const
}
/*!
- \since 4.7
Returns the number of bit planes in the image.
The number of bit planes is the number of bits of color and
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index 435f1dced9..0d13639d35 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -319,7 +319,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
// For an animated image format, QImageIOHandler::nextImageDelay() should
// provide the time to wait until showing the next frame; but multi-frame
// formats are not expected to provide this value, so use 1000 ms by default.
- const int nextFrameDelay = supportsAnimation ? reader->nextImageDelay() : 1000;
+ const auto nextFrameDelay = [&]() { return supportsAnimation ? reader->nextImageDelay() : 1000; };
if (cacheMode == QMovie::CacheNone) {
if (frameNumber != currentFrameNumber+1) {
@@ -363,7 +363,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
}
if (frameNumber > greatestFrameNumber)
greatestFrameNumber = frameNumber;
- return QFrameInfo(QPixmap::fromImage(std::move(anImage)), nextFrameDelay);
+ return QFrameInfo(QPixmap::fromImage(std::move(anImage)), nextFrameDelay());
} else if (frameNumber != 0) {
// We've read all frames now. Return an end marker
haveReadAll = true;
@@ -391,7 +391,7 @@ QFrameInfo QMoviePrivate::infoForFrame(int frameNumber)
return QFrameInfo(); // Invalid
}
greatestFrameNumber = i;
- QFrameInfo info(QPixmap::fromImage(std::move(anImage)), nextFrameDelay);
+ QFrameInfo info(QPixmap::fromImage(std::move(anImage)), nextFrameDelay());
// Cache it!
frameMap.insert(i, info);
if (i == frameNumber) {
diff --git a/src/gui/image/qpixmap.cpp b/src/gui/image/qpixmap.cpp
index 89b8d5303b..afef16f867 100644
--- a/src/gui/image/qpixmap.cpp
+++ b/src/gui/image/qpixmap.cpp
@@ -289,7 +289,6 @@ QPixmap QPixmap::copy(const QRect &rect) const
/*!
\fn QPixmap::scroll(int dx, int dy, int x, int y, int width, int height, QRegion *exposed)
- \since 4.6
This convenience function is equivalent to calling QPixmap::scroll(\a dx,
\a dy, QRect(\a x, \a y, \a width, \a height), \a exposed).
@@ -298,8 +297,6 @@ QPixmap QPixmap::copy(const QRect &rect) const
*/
/*!
- \since 4.6
-
Scrolls the area \a rect of this pixmap by (\a dx, \a dy). The exposed
region is left unchanged. You can optionally pass a pointer to an empty
QRegion to get the region that is \a exposed by the scroll operation.
@@ -371,7 +368,6 @@ QPixmap &QPixmap::operator=(const QPixmap &pixmap)
/*!
\fn void QPixmap::swap(QPixmap &other)
- \since 4.8
Swaps pixmap \a other with this pixmap. This operation is very
fast and never fails.
@@ -970,12 +966,7 @@ bool QPixmap::isDetached() const
Passing 0 for \a flags sets all the default options. Returns \c true
if the result is that this pixmap is not null.
- Note: this function was part of Qt 3 support in Qt 4.6 and earlier.
- It has been promoted to official API status in 4.7 to support updating
- the pixmap's image without creating a new QPixmap as fromImage() would.
-
\sa fromImage()
- \since 4.7
*/
bool QPixmap::convertFromImage(const QImage &image, Qt::ImageConversionFlags flags)
{
diff --git a/src/gui/kernel/qevent.h b/src/gui/kernel/qevent.h
index a001b8f347..a24f0c471c 100644
--- a/src/gui/kernel/qevent.h
+++ b/src/gui/kernel/qevent.h
@@ -71,6 +71,7 @@ protected:
class Q_GUI_EXPORT QPointerEvent : public QInputEvent
{
+ Q_GADGET
Q_DECL_EVENT_COMMON(QPointerEvent)
public:
explicit QPointerEvent(Type type, const QPointingDevice *dev,
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 636956aafa..5228ac9477 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -1531,7 +1531,7 @@ void QGuiApplicationPrivate::createPlatformIntegration()
init_platform(QLatin1StringView(platformName), platformPluginPath, platformThemeName, argc, argv);
if (const QPlatformTheme *theme = platformTheme())
- QStyleHintsPrivate::get(QGuiApplication::styleHints())->setColorScheme(theme->colorScheme());
+ QStyleHintsPrivate::get(QGuiApplication::styleHints())->updateColorScheme(theme->colorScheme());
if (!icon.isEmpty())
forcedWindowIcon = QDir::isAbsolutePath(icon) ? QIcon(icon) : QIcon::fromTheme(icon);
@@ -2643,28 +2643,18 @@ void QGuiApplicationPrivate::processThemeChanged(QWindowSystemInterfacePrivate::
QIconPrivate::clearIconCache();
- QStyleHintsPrivate::get(QGuiApplication::styleHints())->setColorScheme(colorScheme());
-
QEvent themeChangeEvent(QEvent::ThemeChange);
const QWindowList windows = tce->window ? QWindowList{tce->window} : window_list;
for (auto *window : windows)
QGuiApplication::sendSpontaneousEvent(window, &themeChangeEvent);
}
-/*!
- \internal
- \brief QGuiApplicationPrivate::colorScheme
- \return the platform theme's color scheme
- or Qt::ColorScheme::Unknown if a platform theme cannot be established
- */
-Qt::ColorScheme QGuiApplicationPrivate::colorScheme()
-{
- return platformTheme() ? platformTheme()->colorScheme()
- : Qt::ColorScheme::Unknown;
-}
-
void QGuiApplicationPrivate::handleThemeChanged()
{
+ const auto newColorScheme = platformTheme() ? platformTheme()->colorScheme()
+ : Qt::ColorScheme::Unknown;
+ QStyleHintsPrivate::get(QGuiApplication::styleHints())->updateColorScheme(newColorScheme);
+
updatePalette();
QIconLoader::instance()->updateSystemTheme();
@@ -3457,6 +3447,15 @@ void QGuiApplicationPrivate::updatePalette()
}
}
+QEvent::Type QGuiApplicationPrivate::contextMenuEventType()
+{
+ switch (QGuiApplication::styleHints()->contextMenuTrigger()) {
+ case Qt::ContextMenuTrigger::Press: return QEvent::MouseButtonPress;
+ case Qt::ContextMenuTrigger::Release: return QEvent::MouseButtonRelease;
+ }
+ return QEvent::None;
+}
+
void QGuiApplicationPrivate::clearPalette()
{
delete app_pal;
@@ -3675,9 +3674,13 @@ void QGuiApplicationPrivate::notifyWindowIconChanged()
The default is \c true.
- If this property is \c true, the applications quits when the last visible
- \l{Primary and Secondary Windows}{primary window} (i.e. top level window
- with no transient parent) is closed.
+ If this property is \c true, the application will attempt to
+ quit when the last visible \l{Primary and Secondary Windows}{primary window}
+ (i.e. top level window with no transient parent) is closed.
+
+ Note that attempting a quit may not necessarily result in the
+ application quitting, for example if there still are active
+ QEventLoopLocker instances, or the QEvent::Quit event is ignored.
\sa quit(), QWindow::close()
*/
@@ -3733,7 +3736,13 @@ bool QGuiApplicationPrivate::lastWindowClosed() const
bool QGuiApplicationPrivate::canQuitAutomatically()
{
- if (quitOnLastWindowClosed && !lastWindowClosed())
+ // The automatic quit functionality is triggered by
+ // both QEventLoopLocker and maybeLastWindowClosed.
+ // Although the former is a QCoreApplication feature
+ // we don't want to quit the application when there
+ // are open windows, regardless of whether the app
+ // also quits automatically on maybeLastWindowClosed.
+ if (!lastWindowClosed())
return false;
return QCoreApplicationPrivate::canQuitAutomatically();
@@ -4392,6 +4401,9 @@ void *QGuiApplication::resolveInterface(const char *name, int revision) const
#if QT_CONFIG(wayland)
QT_NATIVE_INTERFACE_RETURN_IF(QWaylandApplication, platformNativeInterface());
#endif
+#if defined(Q_OS_VISIONOS)
+ QT_NATIVE_INTERFACE_RETURN_IF(QVisionOSApplication, platformIntegration);
+#endif
return QCoreApplication::resolveInterface(name, revision);
}
diff --git a/src/gui/kernel/qguiapplication.h b/src/gui/kernel/qguiapplication.h
index 14bce88c62..23d7fb3d65 100644
--- a/src/gui/kernel/qguiapplication.h
+++ b/src/gui/kernel/qguiapplication.h
@@ -42,7 +42,7 @@ class Q_GUI_EXPORT QGuiApplication : public QCoreApplication
Q_PROPERTY(QString desktopFileName READ desktopFileName WRITE setDesktopFileName)
Q_PROPERTY(Qt::LayoutDirection layoutDirection READ layoutDirection WRITE setLayoutDirection
NOTIFY layoutDirectionChanged)
- Q_PROPERTY(QString platformName READ platformName STORED false)
+ Q_PROPERTY(QString platformName READ platformName STORED false CONSTANT)
Q_PROPERTY(bool quitOnLastWindowClosed READ quitOnLastWindowClosed
WRITE setQuitOnLastWindowClosed)
Q_PROPERTY(QScreen *primaryScreen READ primaryScreen NOTIFY primaryScreenChanged STORED false)
diff --git a/src/gui/kernel/qguiapplication_p.h b/src/gui/kernel/qguiapplication_p.h
index 58c3f33394..39c490c581 100644
--- a/src/gui/kernel/qguiapplication_p.h
+++ b/src/gui/kernel/qguiapplication_p.h
@@ -323,7 +323,7 @@ public:
static void updatePalette();
- static Qt::ColorScheme colorScheme();
+ static QEvent::Type contextMenuEventType();
protected:
virtual void handleThemeChanged();
@@ -403,8 +403,6 @@ struct Q_GUI_EXPORT QWindowsApplication
virtual bool isWinTabEnabled() const = 0;
virtual bool setWinTabEnabled(bool enabled) = 0;
- virtual bool isDarkMode() const = 0;
-
virtual DarkModeHandling darkModeHandling() const = 0;
virtual void setDarkModeHandling(DarkModeHandling handling) = 0;
diff --git a/src/gui/kernel/qguiapplication_platform.h b/src/gui/kernel/qguiapplication_platform.h
index 545bf75c84..d9ff01bf14 100644
--- a/src/gui/kernel/qguiapplication_platform.h
+++ b/src/gui/kernel/qguiapplication_platform.h
@@ -32,6 +32,22 @@ struct wl_pointer;
struct wl_touch;
#endif
+#if defined(Q_OS_VISIONOS) || defined(Q_QDOC)
+# ifdef __OBJC__
+Q_FORWARD_DECLARE_OBJC_CLASS(CP_OBJECT_cp_layer_renderer_capabilities);
+typedef CP_OBJECT_cp_layer_renderer_capabilities *cp_layer_renderer_capabilities_t;
+Q_FORWARD_DECLARE_OBJC_CLASS(CP_OBJECT_cp_layer_renderer_configuration);
+typedef CP_OBJECT_cp_layer_renderer_configuration *cp_layer_renderer_configuration_t;
+Q_FORWARD_DECLARE_OBJC_CLASS(CP_OBJECT_cp_layer_renderer);
+typedef CP_OBJECT_cp_layer_renderer *cp_layer_renderer_t;
+# else
+typedef struct cp_layer_renderer_capabilities_s *cp_layer_renderer_capabilities_t;
+typedef struct cp_layer_renderer_configuration_s *cp_layer_renderer_configuration_t;
+typedef struct cp_layer_renderer_s *cp_layer_renderer_t;
+# endif
+#endif
+
+
QT_BEGIN_NAMESPACE
namespace QNativeInterface
@@ -61,6 +77,20 @@ struct Q_GUI_EXPORT QWaylandApplication
};
#endif
+#if defined(Q_OS_VISIONOS) || defined(Q_QDOC)
+struct Q_GUI_EXPORT QVisionOSApplication
+{
+ QT_DECLARE_NATIVE_INTERFACE(QVisionOSApplication, 1, QGuiApplication)
+ struct ImmersiveSpaceCompositorLayer {
+ virtual void configure(cp_layer_renderer_capabilities_t, cp_layer_renderer_configuration_t) const {}
+ virtual void render(cp_layer_renderer_t) = 0;
+ };
+ virtual void setImmersiveSpaceCompositorLayer(ImmersiveSpaceCompositorLayer *layer) = 0;
+ virtual void openImmersiveSpace() = 0;
+ virtual void dismissImmersiveSpace() = 0;
+};
+#endif
+
} // QNativeInterface
QT_END_NAMESPACE
diff --git a/src/gui/kernel/qguivariant.cpp b/src/gui/kernel/qguivariant.cpp
index fe72e7782f..78a1660355 100644
--- a/src/gui/kernel/qguivariant.cpp
+++ b/src/gui/kernel/qguivariant.cpp
@@ -78,7 +78,9 @@ static constexpr struct : QMetaTypeModuleHelper
// either two nullptrs from canConvert, or two valid pointers
Q_ASSERT(onlyCheck || (bool(from) && bool(to)));
+#if QT_CONFIG(shortcut)
using Int = int;
+#endif
switch (makePair(toTypeId, fromTypeId)) {
QMETATYPE_CONVERTER(QByteArray, QColor,
result = source.name(source.alpha() != 255 ?
diff --git a/src/gui/kernel/qhighdpiscaling_p.h b/src/gui/kernel/qhighdpiscaling_p.h
index 189f31fd0a..d6deb8a72a 100644
--- a/src/gui/kernel/qhighdpiscaling_p.h
+++ b/src/gui/kernel/qhighdpiscaling_p.h
@@ -172,7 +172,7 @@ inline QMargins scale(const QMargins &margins, qreal scaleFactor, QPoint origin
template<typename T>
QList<T> scale(const QList<T> &list, qreal scaleFactor, QPoint origin = QPoint(0, 0))
{
- if (!QHighDpiScaling::isActive())
+ if (qFuzzyCompare(scaleFactor, qreal(1)))
return list;
QList<T> scaled;
@@ -184,7 +184,7 @@ QList<T> scale(const QList<T> &list, qreal scaleFactor, QPoint origin = QPoint(0
inline QRegion scale(const QRegion &region, qreal scaleFactor, QPoint origin = QPoint(0, 0))
{
- if (!QHighDpiScaling::isActive())
+ if (qFuzzyCompare(scaleFactor, qreal(1)))
return region;
QRegion scaled = region.translated(-origin);
diff --git a/src/gui/kernel/qopenglcontext.cpp b/src/gui/kernel/qopenglcontext.cpp
index 02781f4aa0..dd41318f72 100644
--- a/src/gui/kernel/qopenglcontext.cpp
+++ b/src/gui/kernel/qopenglcontext.cpp
@@ -170,6 +170,9 @@ QOpenGLContext *QOpenGLContextPrivate::setCurrentContext(QOpenGLContext *context
qWarning("No QTLS available. currentContext won't work");
return nullptr;
}
+ if (!context)
+ return nullptr;
+
threadContext = new QGuiGLThreadContext;
qwindow_context_storage()->setLocalData(threadContext);
}
diff --git a/src/gui/kernel/qplatformtheme.cpp b/src/gui/kernel/qplatformtheme.cpp
index 48978b849a..3d1319615e 100644
--- a/src/gui/kernel/qplatformtheme.cpp
+++ b/src/gui/kernel/qplatformtheme.cpp
@@ -447,6 +447,11 @@ Qt::ColorScheme QPlatformTheme::colorScheme() const
return Qt::ColorScheme::Unknown;
}
+void QPlatformTheme::requestColorScheme(Qt::ColorScheme scheme)
+{
+ Q_UNUSED(scheme);
+}
+
const QPalette *QPlatformTheme::palette(Palette type) const
{
Q_D(const QPlatformTheme);
diff --git a/src/gui/kernel/qplatformtheme.h b/src/gui/kernel/qplatformtheme.h
index c0193947b9..d007a19675 100644
--- a/src/gui/kernel/qplatformtheme.h
+++ b/src/gui/kernel/qplatformtheme.h
@@ -295,6 +295,7 @@ public:
#endif
virtual Qt::ColorScheme colorScheme() const;
+ virtual void requestColorScheme(Qt::ColorScheme scheme);
virtual const QPalette *palette(Palette type = SystemPalette) const;
diff --git a/src/gui/kernel/qplatformwindow.cpp b/src/gui/kernel/qplatformwindow.cpp
index 3baa48247b..5c0ae2ee2a 100644
--- a/src/gui/kernel/qplatformwindow.cpp
+++ b/src/gui/kernel/qplatformwindow.cpp
@@ -778,6 +778,15 @@ void QPlatformWindow::deliverUpdateRequest()
QWindow *w = window();
QWindowPrivate *wp = qt_window_private(w);
+
+ // We expect that the platform plugins send DevicePixelRatioChange events.
+ // As a fail-safe make a final check here to make sure the cached DPR value is
+ // always up to date before delivering the update request.
+ if (wp->updateDevicePixelRatio()) {
+ qWarning() << "The cached device pixel ratio value was stale on window update. "
+ << "Please file a QTBUG which explains how to reproduce.";
+ }
+
wp->updateRequestPending = false;
QEvent request(QEvent::UpdateRequest);
QCoreApplication::sendEvent(w, &request);
diff --git a/src/gui/kernel/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 5becae76c6..73c6199733 100644
--- a/src/gui/kernel/qstylehints.cpp
+++ b/src/gui/kernel/qstylehints.cpp
@@ -123,8 +123,29 @@ int QStyleHints::touchDoubleTapDistance() const
/*!
\property QStyleHints::colorScheme
- \brief the color scheme of the platform theme.
- \sa Qt::ColorScheme
+ \brief the color scheme used by the application.
+
+ By default, this follows the system's default color scheme (also known as appearance),
+ and changes when the system color scheme changes (e.g. during dusk or dawn).
+ Setting the color scheme to an explicit value will override the system setting and
+ ignore any changes to the system's color scheme. However, doing so is a hint to the
+ system, and overriding the color scheme is not supported on all platforms.
+
+ Resetting this property, or setting it to \l{Qt::ColorScheme::Unknown}, will remove
+ the override and make the application follow the system default again. The property
+ value will change to the color scheme the system currently has.
+
+ When this property changes, Qt will read the system palette and update the default
+ palette, but won't overwrite palette entries that have been explicitly set by the
+ application. When the colorSchemeChange() signal gets emitted, the old palette is
+ still in effect.
+
+ Application-specific colors should be selected to work well with the effective
+ palette, taking the current color scheme into account. To update application-
+ specific colors when the effective palette changes, handle
+ \l{QEvent::}{PaletteChange} or \l{QEvent::}{ApplicationPaletteChange} events.
+
+ \sa Qt::ColorScheme, QGuiApplication::palette(), QEvent::PaletteChange
\since 6.5
*/
Qt::ColorScheme QStyleHints::colorScheme() const
@@ -134,6 +155,30 @@ Qt::ColorScheme QStyleHints::colorScheme() const
}
/*!
+ \since 6.8
+
+ Sets the color scheme used by the application to an explicit \a scheme, or
+ revert to the system's current color scheme if \a scheme is Qt::ColorScheme::Unknown.
+*/
+void QStyleHints::setColorScheme(Qt::ColorScheme scheme)
+{
+ if (!QCoreApplication::instance()) {
+ qWarning("Must construct a QGuiApplication before accessing a platform theme hint.");
+ return;
+ }
+ if (QPlatformTheme *theme = QGuiApplicationPrivate::platformTheme())
+ theme->requestColorScheme(scheme);
+}
+
+/*!
+ \fn void QStyleHints::unsetColorScheme()
+ \since 6.8
+
+ Restores the color scheme to the system's current color scheme.
+*/
+
+
+/*!
Sets the \a mousePressAndHoldInterval.
\internal
\sa mousePressAndHoldInterval()
@@ -398,6 +443,40 @@ void QStyleHints::setShowShortcutsInContextMenus(bool s)
}
/*!
+ \property QStyleHints::contextMenuTrigger
+ \since 6.8
+ \brief mouse event used to trigger a context menu event.
+
+ The default on UNIX systems is to show context menu on mouse button press event, while on
+ Windows it is the mouse button release event. This property can be used to override the default
+ platform behavior.
+
+ \note Developers must use this property with great care, as it changes the default interaction
+ mode that their users will expect on the platform that they are running on.
+
+ \sa Qt::ContextMenuTrigger
+*/
+Qt::ContextMenuTrigger QStyleHints::contextMenuTrigger() const
+{
+ Q_D(const QStyleHints);
+ if (d->m_contextMenuTrigger == -1) {
+ return themeableHint(QPlatformTheme::ContextMenuOnMouseRelease).toBool()
+ ? Qt::ContextMenuTrigger::Release
+ : Qt::ContextMenuTrigger::Press;
+ }
+ return Qt::ContextMenuTrigger(d->m_contextMenuTrigger);
+}
+
+void QStyleHints::setContextMenuTrigger(Qt::ContextMenuTrigger contextMenuTrigger)
+{
+ Q_D(QStyleHints);
+ const Qt::ContextMenuTrigger currentTrigger = this->contextMenuTrigger();
+ d->m_contextMenuTrigger = int(contextMenuTrigger);
+ if (currentTrigger != contextMenuTrigger)
+ emit contextMenuTriggerChanged(contextMenuTrigger);
+}
+
+/*!
\property QStyleHints::passwordMaskDelay
\brief the time, in milliseconds, a typed letter is displayed unshrouded
in a text input field in password mode.
@@ -595,11 +674,15 @@ int QStyleHints::mouseQuickSelectionThreshold() const
/*!
\internal
- QStyleHintsPrivate::setColorScheme - set a new color scheme.
+ QStyleHintsPrivate::updateColorScheme - set a new color scheme.
+
+ This function is called by the QPA plugin when the system theme changes. This in
+ turn might be the result of an explicit request of a color scheme via setColorScheme.
+
Set \a colorScheme as the new color scheme of the QStyleHints.
The colorSchemeChanged signal will be emitted if present and new color scheme differ.
*/
-void QStyleHintsPrivate::setColorScheme(Qt::ColorScheme colorScheme)
+void QStyleHintsPrivate::updateColorScheme(Qt::ColorScheme colorScheme)
{
if (m_colorScheme == colorScheme)
return;
diff --git a/src/gui/kernel/qstylehints.h b/src/gui/kernel/qstylehints.h
index 969bec4b35..97ef59f3cf 100644
--- a/src/gui/kernel/qstylehints.h
+++ b/src/gui/kernel/qstylehints.h
@@ -36,6 +36,8 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(bool showIsMaximized READ showIsMaximized STORED false CONSTANT FINAL)
Q_PROPERTY(bool showShortcutsInContextMenus READ showShortcutsInContextMenus
WRITE setShowShortcutsInContextMenus NOTIFY showShortcutsInContextMenusChanged FINAL)
+ Q_PROPERTY(Qt::ContextMenuTrigger contextMenuTrigger READ contextMenuTrigger WRITE
+ setContextMenuTrigger NOTIFY contextMenuTriggerChanged FINAL)
Q_PROPERTY(int startDragDistance READ startDragDistance NOTIFY startDragDistanceChanged FINAL)
Q_PROPERTY(int startDragTime READ startDragTime NOTIFY startDragTimeChanged FINAL)
Q_PROPERTY(int startDragVelocity READ startDragVelocity STORED false CONSTANT FINAL)
@@ -52,7 +54,8 @@ class Q_GUI_EXPORT QStyleHints : public QObject
Q_PROPERTY(int mouseDoubleClickDistance READ mouseDoubleClickDistance STORED false CONSTANT
FINAL)
Q_PROPERTY(int touchDoubleTapDistance READ touchDoubleTapDistance STORED false CONSTANT FINAL)
- Q_PROPERTY(Qt::ColorScheme colorScheme READ colorScheme NOTIFY colorSchemeChanged FINAL)
+ Q_PROPERTY(Qt::ColorScheme colorScheme READ colorScheme WRITE setColorScheme
+ RESET unsetColorScheme NOTIFY colorSchemeChanged FINAL)
public:
void setMouseDoubleClickInterval(int mouseDoubleClickInterval);
@@ -79,6 +82,8 @@ public:
bool showIsMaximized() const;
bool showShortcutsInContextMenus() const;
void setShowShortcutsInContextMenus(bool showShortcutsInContextMenus);
+ Qt::ContextMenuTrigger contextMenuTrigger() const;
+ void setContextMenuTrigger(Qt::ContextMenuTrigger contextMenuTrigger);
int passwordMaskDelay() const;
QChar passwordMaskCharacter() const;
qreal fontSmoothingGamma() const;
@@ -94,6 +99,8 @@ public:
void setMouseQuickSelectionThreshold(int threshold);
int mouseQuickSelectionThreshold() const;
Qt::ColorScheme colorScheme() const;
+ void setColorScheme(Qt::ColorScheme scheme);
+ void unsetColorScheme() { setColorScheme(Qt::ColorScheme::Unknown); }
Q_SIGNALS:
void cursorFlashTimeChanged(int cursorFlashTime);
@@ -105,6 +112,7 @@ Q_SIGNALS:
void tabFocusBehaviorChanged(Qt::TabFocusBehavior tabFocusBehavior);
void useHoverEffectsChanged(bool useHoverEffects);
void showShortcutsInContextMenusChanged(bool);
+ void contextMenuTriggerChanged(Qt::ContextMenuTrigger contextMenuTrigger);
void wheelScrollLinesChanged(int scrollLines);
void mouseQuickSelectionThresholdChanged(int threshold);
void colorSchemeChanged(Qt::ColorScheme colorScheme);
diff --git a/src/gui/kernel/qstylehints_p.h b/src/gui/kernel/qstylehints_p.h
index c58386d7a3..497bf95cbf 100644
--- a/src/gui/kernel/qstylehints_p.h
+++ b/src/gui/kernel/qstylehints_p.h
@@ -35,13 +35,14 @@ public:
int m_tabFocusBehavior = -1;
int m_uiEffects = -1;
int m_showShortcutsInContextMenus = -1;
+ int m_contextMenuTrigger = -1;
int m_wheelScrollLines = -1;
int m_mouseQuickSelectionThreshold = -1;
int m_mouseDoubleClickDistance = -1;
int m_touchDoubleTapDistance = -1;
Qt::ColorScheme colorScheme() const { return m_colorScheme; }
- void setColorScheme(Qt::ColorScheme colorScheme);
+ void updateColorScheme(Qt::ColorScheme colorScheme);
static QStyleHintsPrivate *get(QStyleHints *q);
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index 46a787e706..7c885032c7 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -521,7 +521,9 @@ void QWindowPrivate::setTopLevelScreen(QScreen *newScreen, bool recreate)
}
}
-void QWindowPrivate::create(bool recursive, WId nativeHandle)
+static constexpr auto kForeignWindowId = "_q_foreignWinId";
+
+void QWindowPrivate::create(bool recursive)
{
Q_Q(QWindow);
if (platformWindow)
@@ -549,6 +551,8 @@ void QWindowPrivate::create(bool recursive, WId nativeHandle)
setTopLevelScreen(screen, false);
}
+ const WId nativeHandle = q->property(kForeignWindowId).value<WId>();
+
QPlatformIntegration *platformIntegration = QGuiApplicationPrivate::platformIntegration();
platformWindow = nativeHandle ? platformIntegration->createForeignWindow(q, nativeHandle)
: platformIntegration->createPlatformWindow(q);
@@ -2059,6 +2063,16 @@ void QWindowPrivate::destroy()
QObject *object = childrenWindows.at(i);
if (object->isWindowType()) {
QWindow *w = static_cast<QWindow*>(object);
+ auto *childPlatformWindow = w->handle();
+ if (!childPlatformWindow)
+ continue;
+
+ // Decouple the foreign window from this window,
+ // so that destroying our native handle doesn't
+ // bring down the foreign window as well.
+ if (childPlatformWindow->isForeignWindow())
+ childPlatformWindow->setParent(nullptr);
+
qt_window_private(w)->destroy();
}
}
@@ -2640,16 +2654,14 @@ bool QWindow::event(QEvent *ev)
This logic could be simplified by always synthesizing events in
QGuiApplicationPrivate, or perhaps even in each QPA plugin. See QTBUG-93486.
*/
- static const QEvent::Type contextMenuTrigger =
- QGuiApplicationPrivate::platformTheme()->themeHint(QPlatformTheme::ContextMenuOnMouseRelease).toBool() ?
- QEvent::MouseButtonRelease : QEvent::MouseButtonPress;
auto asMouseEvent = [](QEvent *ev) {
const auto t = ev->type();
return t == QEvent::MouseButtonPress || t == QEvent::MouseButtonRelease
? static_cast<QMouseEvent *>(ev) : nullptr ;
};
- if (QMouseEvent *me = asMouseEvent(ev); me &&
- ev->type() == contextMenuTrigger && me->button() == Qt::RightButton) {
+ if (QMouseEvent *me = asMouseEvent(ev);
+ me && ev->type() == QGuiApplicationPrivate::contextMenuEventType()
+ && me->button() == Qt::RightButton) {
QContextMenuEvent e(QContextMenuEvent::Mouse, me->position().toPoint(),
me->globalPosition().toPoint(), me->modifiers());
QGuiApplication::sendEvent(this, &e);
@@ -2986,7 +2998,11 @@ QWindow *QWindow::fromWinId(WId id)
}
QWindow *window = new QWindow;
- qt_window_private(window)->create(false, id);
+
+ // Persist the winId in a private property so that we
+ // can recreate the window after being destroyed.
+ window->setProperty(kForeignWindowId, id);
+ window->create();
if (!window->handle()) {
delete window;
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index 1bcbda6b8f..40ab06af8b 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -66,7 +66,7 @@ public:
void updateSiblingPosition(SiblingPosition);
bool windowRecreationRequired(QScreen *newScreen) const;
- void create(bool recursive, WId nativeHandle = 0);
+ void create(bool recursive);
void destroy();
void setTopLevelScreen(QScreen *newScreen, bool recreate);
void connectToScreen(QScreen *topLevelScreen);
@@ -76,6 +76,16 @@ public:
void setTransientParent(QWindow *parent);
virtual void clearFocusObject();
+
+ enum class FocusTarget {
+ First,
+ Last,
+ Current,
+ Next,
+ Prev
+ };
+ virtual void setFocusToTarget(FocusTarget, Qt::FocusReason) {}
+
virtual QRectF closestAcceptableGeometry(const QRectF &rect) const;
void setMinOrMaxSize(QSize *oldSizeMember, const QSize &size,
diff --git a/src/gui/painting/qbackingstore.cpp b/src/gui/painting/qbackingstore.cpp
index 2304ee2256..3b709ec77b 100644
--- a/src/gui/painting/qbackingstore.cpp
+++ b/src/gui/painting/qbackingstore.cpp
@@ -50,6 +50,7 @@ public:
QScopedPointer<QImage> highDpiBackingstore;
QRegion staticContents;
QSize size;
+ QSize nativeSize;
bool downscale = qEnvironmentVariableIntValue("QT_WIDGETS_HIGHDPI_DOWNSCALE") > 0;
};
@@ -115,14 +116,13 @@ QWindow* QBackingStore::window() const
void QBackingStore::beginPaint(const QRegion &region)
{
- const qreal dpr = d_ptr->backingStoreDevicePixelRatio();
+ const qreal toNativeFactor = d_ptr->deviceIndependentToNativeFactor();
- if (d_ptr->highDpiBackingstore &&
- d_ptr->highDpiBackingstore->devicePixelRatio() != dpr)
+ if (d_ptr->nativeSize != QHighDpi::scale(size(), toNativeFactor))
resize(size());
QPlatformBackingStore *platformBackingStore = handle();
- platformBackingStore->beginPaint(QHighDpi::scale(region, d_ptr->deviceIndependentToNativeFactor()));
+ platformBackingStore->beginPaint(QHighDpi::scale(region, toNativeFactor));
// When QtGui is applying a high-dpi scale factor the backing store
// creates a "large" backing store image. This image needs to be
@@ -131,18 +131,20 @@ void QBackingStore::beginPaint(const QRegion &region)
// the image data to avoid having the new devicePixelRatio be propagated
// back to the platform plugin.
QPaintDevice *device = platformBackingStore->paintDevice();
- if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image) {
+ if (!qFuzzyCompare(toNativeFactor, qreal(1)) && device->devType() == QInternal::Image) {
QImage *source = static_cast<QImage *>(device);
const bool needsNewImage = d_ptr->highDpiBackingstore.isNull()
- || source->data_ptr() != d_ptr->highDpiBackingstore->data_ptr()
+ || source->constBits() != d_ptr->highDpiBackingstore->constBits()
|| source->size() != d_ptr->highDpiBackingstore->size()
- || source->devicePixelRatio() != d_ptr->highDpiBackingstore->devicePixelRatio();
- if (needsNewImage) {
+ || source->bytesPerLine() != d_ptr->highDpiBackingstore->bytesPerLine()
+ || source->format() != d_ptr->highDpiBackingstore->format();
+ if (needsNewImage)
d_ptr->highDpiBackingstore.reset(
new QImage(source->bits(), source->width(), source->height(), source->bytesPerLine(), source->format()));
- d_ptr->highDpiBackingstore->setDevicePixelRatio(dpr);
- }
+ d_ptr->highDpiBackingstore->setDevicePixelRatio(d_ptr->backingStoreDevicePixelRatio());
+ } else {
+ d_ptr->highDpiBackingstore.reset();
}
}
@@ -156,7 +158,7 @@ QPaintDevice *QBackingStore::paintDevice()
{
QPaintDevice *device = handle()->paintDevice();
- if (QHighDpiScaling::isActive() && device->devType() == QInternal::Image)
+ if (!qFuzzyCompare(d_ptr->deviceIndependentToNativeFactor(), qreal(1)) && device->devType() == QInternal::Image)
return d_ptr->highDpiBackingstore.data();
return device;
@@ -229,9 +231,10 @@ void QBackingStore::flush(const QRegion &region, QWindow *window, const QPoint &
*/
void QBackingStore::resize(const QSize &size)
{
- d_ptr->size = size;
const qreal factor = d_ptr->deviceIndependentToNativeFactor();
- handle()->resize(QHighDpi::scale(size, factor), QHighDpi::scale(d_ptr->staticContents, factor));
+ d_ptr->size = size;
+ d_ptr->nativeSize = QHighDpi::scale(size, factor);
+ handle()->resize(d_ptr->nativeSize, QHighDpi::scale(d_ptr->staticContents, factor));
}
/*!
diff --git a/src/gui/painting/qcolorspace.cpp b/src/gui/painting/qcolorspace.cpp
index 7a1d34a408..f21e6ec738 100644
--- a/src/gui/painting/qcolorspace.cpp
+++ b/src/gui/painting/qcolorspace.cpp
@@ -448,11 +448,15 @@ QColorTransform QColorSpacePrivate::transformationToXYZ() const
transform.d = ptr;
ptr->colorSpaceIn = this;
ptr->colorSpaceOut = this;
- // Convert to XYZ relative to our white point, not the regular D50 white point.
if (isThreeComponentMatrix())
- ptr->colorMatrix = QColorMatrix::chromaticAdaptation(whitePoint).inverted() * toXyz;
+ ptr->colorMatrix = toXyz;
else
ptr->colorMatrix = QColorMatrix::identity();
+ // Convert to XYZ relative to our white point, not the regular D50 white point.
+ if (!chad.isNull())
+ ptr->colorMatrix = chad.inverted() * ptr->colorMatrix;
+ else if (!whitePoint.isNull())
+ ptr->colorMatrix = QColorMatrix::chromaticAdaptation(whitePoint).inverted() * ptr->colorMatrix;
return transform;
}
diff --git a/src/gui/painting/qcolortransfertable_p.h b/src/gui/painting/qcolortransfertable_p.h
index 51c9cff6d6..ce6ad0c4b2 100644
--- a/src/gui/painting/qcolortransfertable_p.h
+++ b/src/gui/painting/qcolortransfertable_p.h
@@ -101,7 +101,7 @@ public:
return x;
x = std::clamp(x, 0.0f, 1.0f);
x *= m_tableSize - 1;
- const uint32_t lo = static_cast<uint32_t>(std::floor(x));
+ const uint32_t lo = static_cast<uint32_t>(x);
const uint32_t hi = std::min(lo + 1, m_tableSize - 1);
const float frac = x - lo;
if (!m_table16.isEmpty())
@@ -120,36 +120,10 @@ public:
return 0.0f;
if (x >= 1.0f)
return 1.0f;
- if (!m_table16.isEmpty()) {
- const float v = x * 65535.0f;
- uint32_t i = static_cast<uint32_t>(std::floor(resultLargerThan * (m_tableSize - 1)));
- auto it = std::lower_bound(m_table16.cbegin() + i, m_table16.cend(), v);
- i = it - m_table16.cbegin();
- if (i == 0)
- return 0.0f;
- if (i >= m_tableSize - 1)
- return 1.0f;
- const float y1 = m_table16[i - 1];
- const float y2 = m_table16[i];
- Q_ASSERT(v >= y1 && v <= y2);
- const float fr = (v - y1) / (y2 - y1);
- return (i + fr) * (1.0f / (m_tableSize - 1));
- }
- if (!m_table8.isEmpty()) {
- const float v = x * 255.0f;
- uint32_t i = static_cast<uint32_t>(std::floor(resultLargerThan * (m_tableSize - 1)));
- auto it = std::lower_bound(m_table8.cbegin() + i, m_table8.cend(), v);
- i = it - m_table8.cbegin();
- if (i == 0)
- return 0.0f;
- if (i >= m_tableSize - 1)
- return 1.0f;
- const float y1 = m_table8[i - 1];
- const float y2 = m_table8[i];
- Q_ASSERT(v >= y1 && v <= y2);
- const float fr = (v - y1) / (y2 - y1);
- return (i + fr) * (1.0f / (m_tableSize - 1));
- }
+ if (!m_table16.isEmpty())
+ return inverseLookup(x * 65535.0f, resultLargerThan, m_table16, m_tableSize - 1);
+ if (!m_table8.isEmpty())
+ return inverseLookup(x * 255.0f, resultLargerThan, m_table8, m_tableSize - 1);
return x;
}
@@ -213,6 +187,24 @@ public:
uint32_t m_tableSize = 0;
QList<uint8_t> m_table8;
QList<uint16_t> m_table16;
+private:
+ template<typename T>
+ static float inverseLookup(float needle, float resultLargerThan, const QList<T> &table, quint32 tableMax)
+ {
+ uint32_t i = static_cast<uint32_t>(resultLargerThan * tableMax);
+ auto it = std::lower_bound(table.cbegin() + i, table.cend(), needle);
+ i = it - table.cbegin();
+ if (i == 0)
+ return 0.0f;
+ if (i >= tableMax)
+ return 1.0f;
+ const float y1 = table[i - 1];
+ const float y2 = table[i];
+ Q_ASSERT(needle >= y1 && needle <= y2);
+ const float fr = (needle - y1) / (y2 - y1);
+ return (i + fr) * (1.0f / tableMax);
+ }
+
};
inline bool operator!=(const QColorTransferTable &t1, const QColorTransferTable &t2)
diff --git a/src/gui/painting/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp
index aac07bdc09..33b1dcdeb0 100644
--- a/src/gui/painting/qcolortransform.cpp
+++ b/src/gui/painting/qcolortransform.cpp
@@ -1640,7 +1640,7 @@ void QColorTransformPrivate::applyConvertIn(const S *src, QColorVector *buffer,
loadUnpremultiplied(buffer, src, len, this);
if (!colorSpaceOut->isThreeComponentMatrix())
- applyMatrix<DoClamp>(buffer, len, colorMatrix); // colorMatrix should have the first half only.
+ applyMatrix<DoClamp>(buffer, len, colorSpaceIn->toXyz);
return;
}
}
@@ -1666,7 +1666,7 @@ void QColorTransformPrivate::applyConvertOut(D *dst, const S *src, QColorVector
// Avoid compiling this part for D=QCmyk32:
if constexpr (!std::is_same_v<D, QCmyk32>) {
if (colorSpaceOut->isThreeComponentMatrix()) {
- applyMatrix<doClamp>(buffer, len, colorMatrix); // colorMatrix should have the latter half only.
+ applyMatrix<doClamp>(buffer, len, colorMatrix);
if constexpr (std::is_same_v<S, QCmyk32>) {
storeOpaque(dst, buffer, len, this);
@@ -1695,14 +1695,34 @@ void QColorTransformPrivate::applyConvertOut(D *dst, const S *src, QColorVector
storeUnpremultipliedLUT(dst, src, buffer, len);
}
-template<typename D, typename S>
-void QColorTransformPrivate::applyElementListTransform(D *dst, const S *src, qsizetype count, TransformFlags flags) const
+/*!
+ \internal
+ Adapt Profile Connecting Color spaces.
+*/
+void QColorTransformPrivate::pcsAdapt(QColorVector *buffer, qsizetype count) const
{
- Q_ASSERT(!colorSpaceIn->isThreeComponentMatrix() || !colorSpaceOut->isThreeComponentMatrix());
+ // Match Profile Connection Spaces (PCS):
+ if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab) {
+ for (qsizetype j = 0; j < count; ++j)
+ buffer[j] = buffer[j].xyzToLab();
+ } else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab) {
+ for (qsizetype j = 0; j < count; ++j)
+ buffer[j] = buffer[j].labToXyz();
+ }
+}
- if (!colorMatrix.isValid())
- return;
+/*!
+ \internal
+ Applies the color transformation on \a count S pixels starting from
+ \a src and stores the result in \a dst as D pixels .
+ Assumes unpremultiplied data by default. Set \a flags to change defaults.
+
+ \sa prepare()
+*/
+template<typename D, typename S>
+void QColorTransformPrivate::apply(D *dst, const S *src, qsizetype count, TransformFlags flags) const
+{
if (colorSpaceIn->isThreeComponentMatrix())
updateLutsIn();
if (colorSpaceOut->isThreeComponentMatrix())
@@ -1715,14 +1735,7 @@ void QColorTransformPrivate::applyElementListTransform(D *dst, const S *src, qsi
applyConvertIn(src + i, buffer, len, flags);
- // Match Profile Connection Spaces (PCS):
- if (colorSpaceOut->isPcsLab && !colorSpaceIn->isPcsLab) {
- for (qsizetype j = 0; j < len; ++j)
- buffer[j] = buffer[j].xyzToLab();
- } else if (colorSpaceIn->isPcsLab && !colorSpaceOut->isPcsLab) {
- for (qsizetype j = 0; j < len; ++j)
- buffer[j] = buffer[j].labToXyz();
- }
+ pcsAdapt(buffer, len);
applyConvertOut(dst + i, src + i, buffer, len, flags);
@@ -1730,64 +1743,6 @@ void QColorTransformPrivate::applyElementListTransform(D *dst, const S *src, qsi
}
}
-template<typename D, typename S>
-void QColorTransformPrivate::applyThreeComponentMatrix(D *dst, const S *src, qsizetype count, TransformFlags flags) const
-{
- Q_ASSERT(colorSpaceIn->isThreeComponentMatrix() && colorSpaceOut->isThreeComponentMatrix());
-
- if (!colorMatrix.isValid())
- return;
-
- updateLutsIn();
- updateLutsOut();
-
- bool doApplyMatrix = !colorMatrix.isIdentity();
- constexpr ApplyMatrixForm doClamp = (std::is_same_v<D, QRgbaFloat16> || std::is_same_v<D, QRgbaFloat32>) ? DoNotClamp : DoClamp;
-
- QUninitialized<QColorVector, WorkBlockSize> buffer;
- qsizetype i = 0;
- while (i < count) {
- const qsizetype len = qMin(count - i, WorkBlockSize);
- if (flags & InputPremultiplied)
- loadPremultiplied(buffer, src + i, len, this);
- else
- loadUnpremultiplied(buffer, src + i, len, this);
-
- if (doApplyMatrix)
- applyMatrix<doClamp>(buffer, len, colorMatrix);
- else
- clampIfNeeded<doClamp>(buffer, len);
-
- if (flags & InputOpaque)
- storeOpaque(dst + i, buffer, len, this);
- else if (flags & OutputPremultiplied)
- storePremultiplied(dst + i, src + i, buffer, len, this);
- else
- storeUnpremultiplied(dst + i, src + i, buffer, len, this);
-
- i += len;
- }
-}
-
-/*!
- \internal
- Applies the color transformation on \a count S pixels starting from
- \a src and stores the result in \a dst as D pixels .
-
- Assumes unpremultiplied data by default. Set \a flags to change defaults.
-
- \sa prepare()
-*/
-template<typename D, typename S>
-void QColorTransformPrivate::apply(D *dst, const S *src, qsizetype count, TransformFlags flags) const
-{
- if constexpr (!std::is_same_v<D, QCmyk32> && !std::is_same_v<S, QCmyk32>) {
- if (isThreeComponentMatrix())
- return applyThreeComponentMatrix<D, S>(dst, src, count, flags);
- }
- applyElementListTransform<D, S>(dst, src, count, flags);
-}
-
/*!
\internal
Is to be called on a color-transform to XYZ, returns only luminance values.
@@ -1970,15 +1925,6 @@ template void QColorTransformPrivate::apply<QRgbaFloat32, QCmyk32>(QRgbaFloat32
template void QColorTransformPrivate::apply<QRgbaFloat32, QRgba64>(QRgbaFloat32 *dst, const QRgba64 *src, qsizetype count, TransformFlags flags) const;
template void QColorTransformPrivate::apply<QRgbaFloat32, QRgbaFloat32>(QRgbaFloat32 *dst, const QRgbaFloat32 *src, qsizetype count, TransformFlags flags) const;
-bool QColorTransformPrivate::isThreeComponentMatrix() const
-{
- if (colorSpaceIn && !colorSpaceIn->isThreeComponentMatrix())
- return false;
- if (colorSpaceOut && !colorSpaceOut->isThreeComponentMatrix())
- return false;
- return true;
-}
-
/*!
\internal
*/
@@ -1991,7 +1937,7 @@ bool QColorTransformPrivate::isIdentity() const
if (colorSpaceIn && colorSpaceOut) {
if (colorSpaceIn->equals(colorSpaceOut.constData()))
return true;
- if (!isThreeComponentMatrix())
+ if (!colorSpaceIn->isThreeComponentMatrix() || !colorSpaceOut->isThreeComponentMatrix())
return false;
if (colorSpaceIn->transferFunction != colorSpaceOut->transferFunction)
return false;
@@ -2001,7 +1947,9 @@ bool QColorTransformPrivate::isIdentity() const
&& colorSpaceIn->trc[2] == colorSpaceOut->trc[2];
}
} else {
- if (!isThreeComponentMatrix())
+ if (colorSpaceIn && !colorSpaceIn->isThreeComponentMatrix())
+ return false;
+ if (colorSpaceOut && !colorSpaceOut->isThreeComponentMatrix())
return false;
if (colorSpaceIn && colorSpaceIn->transferFunction != QColorSpace::TransferFunction::Linear)
return false;
diff --git a/src/gui/painting/qcolortransform_p.h b/src/gui/painting/qcolortransform_p.h
index 59ea6a2405..c74fe100eb 100644
--- a/src/gui/painting/qcolortransform_p.h
+++ b/src/gui/painting/qcolortransform_p.h
@@ -37,7 +37,6 @@ public:
void updateLutsIn() const;
void updateLutsOut() const;
bool isIdentity() const;
- bool isThreeComponentMatrix() const;
Q_GUI_EXPORT void prepare();
enum TransformFlag {
@@ -60,14 +59,11 @@ public:
void applyReturnGray(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
private:
+ void pcsAdapt(QColorVector *buffer, qsizetype len) const;
template<typename S>
void applyConvertIn(const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const;
template<typename D, typename S>
void applyConvertOut(D *dst, const S *src, QColorVector *buffer, qsizetype len, TransformFlags flags) const;
- template<typename D, typename S>
- void applyElementListTransform(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
- template<typename D, typename S>
- void applyThreeComponentMatrix(D *dst, const S *src, qsizetype count, TransformFlags flags) const;
};
QT_END_NAMESPACE
diff --git a/src/gui/painting/qicc.cpp b/src/gui/painting/qicc.cpp
index 59f941b017..a2786fbb8b 100644
--- a/src/gui/painting/qicc.cpp
+++ b/src/gui/painting/qicc.cpp
@@ -559,6 +559,8 @@ static bool parseXyzData(const QByteArray &data, const TagEntry &tagEntry, QColo
static quint32 parseTRC(const QByteArrayView &tagData, QColorTrc &gamma, QColorTransferTable::Type type = QColorTransferTable::TwoWay)
{
+ if (tagData.size() < 12)
+ return 0;
const GenericTagData trcData = qFromUnaligned<GenericTagData>(tagData.constData());
if (trcData.type == quint32(Tag::curv)) {
Q_STATIC_ASSERT(sizeof(CurvTagData) == 12);
@@ -778,6 +780,10 @@ static bool parseLutData(const QByteArray &data, const TagEntry &tagEntry, QColo
qCWarning(lcIcc) << "Undersized lut8/lut16 tag, no room for tables";
return false;
}
+ if (colorSpacePrivate->colorModel == QColorSpace::ColorModel::Cmyk && clutTableSize == 0) {
+ qCWarning(lcIcc) << "Cmyk conversion must have a CLUT";
+ return false;
+ }
const uint8_t *tableData = reinterpret_cast<const uint8_t *>(data.constData() + tagEntry.offset + sizeof(T));
@@ -997,6 +1003,9 @@ static bool parseMabData(const QByteArray &data, const TagEntry &tagEntry, QColo
const uint8_t *clutTable = reinterpret_cast<const uint8_t *>(data.constData() + tagEntry.offset + mab.clutOffset + 20);
parseCLUT(clutTable, (1.f/255.f), &clutElement, mab.outputChannels);
}
+ } else if (colorSpacePrivate->colorModel == QColorSpace::ColorModel::Cmyk) {
+ qCWarning(lcIcc) << "Cmyk conversion must have a CLUT";
+ return false;
}
if (isAb) {
@@ -1060,6 +1069,8 @@ static bool parseDesc(const QByteArray &data, const TagEntry &tagEntry, QString
// Either 'desc' (ICCv2) or 'mluc' (ICCv4)
if (tag.type == quint32(Tag::desc)) {
+ if (tagEntry.size < sizeof(DescTagData))
+ return false;
Q_STATIC_ASSERT(sizeof(DescTagData) == 12);
const DescTagData desc = qFromUnaligned<DescTagData>(data.constData() + tagEntry.offset);
const quint32 len = desc.asciiDescriptionLength;
@@ -1280,7 +1291,7 @@ bool fromIccProfile(const QByteArray &data, QColorSpace *colorSpace)
qCWarning(lcIcc) << "fromIccProfile: failed tag offset sanity 2";
return false;
}
- if (tagTable.size < 12) {
+ if (tagTable.size < 8) {
qCWarning(lcIcc) << "fromIccProfile: failed minimal tag size sanity";
return false;
}
diff --git a/src/gui/painting/qpagelayout.cpp b/src/gui/painting/qpagelayout.cpp
index ec505f2cce..e60f464d6e 100644
--- a/src/gui/painting/qpagelayout.cpp
+++ b/src/gui/painting/qpagelayout.cpp
@@ -79,7 +79,7 @@ public:
bool isValid() const;
- void clampMargins(const QMarginsF &margins);
+ QMarginsF clampMargins(const QMarginsF &margins) const;
QMarginsF margins(QPageLayout::Unit units) const;
QMarginsF marginsPoints() const;
@@ -151,12 +151,12 @@ bool QPageLayoutPrivate::isValid() const
return m_pageSize.isValid();
}
-void QPageLayoutPrivate::clampMargins(const QMarginsF &margins)
+QMarginsF QPageLayoutPrivate::clampMargins(const QMarginsF &margins) const
{
- m_margins = QMarginsF(qBound(m_minMargins.left(), margins.left(), m_maxMargins.left()),
- qBound(m_minMargins.top(), margins.top(), m_maxMargins.top()),
- qBound(m_minMargins.right(), margins.right(), m_maxMargins.right()),
- qBound(m_minMargins.bottom(), margins.bottom(), m_maxMargins.bottom()));
+ return QMarginsF(qBound(m_minMargins.left(), margins.left(), m_maxMargins.left()),
+ qBound(m_minMargins.top(), margins.top(), m_maxMargins.top()),
+ qBound(m_minMargins.right(), margins.right(), m_maxMargins.right()),
+ qBound(m_minMargins.bottom(), margins.bottom(), m_maxMargins.bottom()));
}
QMarginsF QPageLayoutPrivate::margins(QPageLayout::Unit units) const
@@ -182,7 +182,7 @@ void QPageLayoutPrivate::setDefaultMargins(const QMarginsF &minMargins)
qMax(m_fullSize.width() - m_minMargins.left(), qreal(0)),
qMax(m_fullSize.height() - m_minMargins.top(), qreal(0)));
if (m_mode == QPageLayout::StandardMode)
- clampMargins(m_margins);
+ m_margins = clampMargins(m_margins);
}
QSizeF QPageLayoutPrivate::fullSizeUnits(QPageLayout::Unit units) const
@@ -288,6 +288,27 @@ QRectF QPageLayoutPrivate::paintRect() const
\value StandardMode Paint Rect includes margins, margins must fall between the minimum and maximum.
\value FullPageMode Paint Rect excludes margins, margins can be any value and must be managed manually.
+
+ In StandardMode, when setting margins, use \l{QPageLayout::OutOfBoundsPolicy::}{Clamp} to
+ automatically clamp the margins to fall between the minimum and maximum
+ allowed values.
+
+ \sa OutOfBoundsPolicy
+*/
+
+/*!
+ \enum QPageLayout::OutOfBoundsPolicy
+ \since 6.8
+
+ Defines the policy for margins that are out of bounds
+
+ \value Reject The margins must fall within the minimum and maximum values,
+ otherwise they will be rejected.
+ \value Clamp The margins are clamped between the minimum and maximum
+ values to ensure they are valid.
+
+ \note The policy has no effect in \l{QPageLayout::Mode}{FullPageMode},
+ where all margins are accepted.
*/
/*!
@@ -525,39 +546,52 @@ QPageLayout::Unit QPageLayout::units() const
}
/*!
- Sets the page margins of the page layout to \a margins
+ Sets the page margins of the page layout to \a margins.
Returns true if the margins were successfully set.
The units used are those currently defined for the layout. To use different
units then call setUnits() first.
- If in the default StandardMode then all the new margins must fall between the
- minimum margins set and the maximum margins allowed by the page size,
- otherwise the margins will not be set.
-
- If in FullPageMode then any margin values will be accepted.
+ Since Qt 6.8, the optional \a outOfBoundsPolicy can be used to specify how
+ margins that are out of bounds are handled.
\sa margins(), units()
*/
-bool QPageLayout::setMargins(const QMarginsF &margins)
+bool QPageLayout::setMargins(const QMarginsF &margins, OutOfBoundsPolicy outOfBoundsPolicy)
{
if (d->m_mode == FullPageMode) {
- d.detach();
- d->m_margins = margins;
+ if (margins != d->m_margins) {
+ d.detach();
+ d->m_margins = margins;
+ }
return true;
- } else if (margins.left() >= d->m_minMargins.left()
- && margins.right() >= d->m_minMargins.right()
- && margins.top() >= d->m_minMargins.top()
- && margins.bottom() >= d->m_minMargins.bottom()
- && margins.left() <= d->m_maxMargins.left()
- && margins.right() <= d->m_maxMargins.right()
- && margins.top() <= d->m_maxMargins.top()
- && margins.bottom() <= d->m_maxMargins.bottom()) {
- d.detach();
- d->m_margins = margins;
+ }
+
+ if (outOfBoundsPolicy == OutOfBoundsPolicy::Clamp) {
+ const QMarginsF clampedMargins = d->clampMargins(margins);
+ if (clampedMargins != d->m_margins) {
+ d.detach();
+ d->m_margins = clampedMargins;
+ }
return true;
}
+
+ if (margins.left() >= d->m_minMargins.left()
+ && margins.right() >= d->m_minMargins.right()
+ && margins.top() >= d->m_minMargins.top()
+ && margins.bottom() >= d->m_minMargins.bottom()
+ && margins.left() <= d->m_maxMargins.left()
+ && margins.right() <= d->m_maxMargins.right()
+ && margins.top() <= d->m_maxMargins.top()
+ && margins.bottom() <= d->m_maxMargins.bottom()) {
+ if (margins != d->m_margins) {
+ d.detach();
+ d->m_margins = margins;
+ }
+ return true;
+ }
+
return false;
}
@@ -568,23 +602,27 @@ bool QPageLayout::setMargins(const QMarginsF &margins)
The units used are those currently defined for the layout. To use different
units call setUnits() first.
- If in the default StandardMode then the new margin must fall between the
- minimum margin set and the maximum margin allowed by the page size,
- otherwise the margin will not be set.
-
- If in FullPageMode then any margin values will be accepted.
+ Since Qt 6.8, the optional \a outOfBoundsPolicy can be used to specify how
+ margins that are out of bounds are handled.
\sa setMargins(), margins()
*/
-bool QPageLayout::setLeftMargin(qreal leftMargin)
+bool QPageLayout::setLeftMargin(qreal leftMargin, OutOfBoundsPolicy outOfBoundsPolicy)
{
+ if (d->m_mode == StandardMode && outOfBoundsPolicy == OutOfBoundsPolicy::Clamp)
+ leftMargin = qBound(d->m_minMargins.left(), leftMargin, d->m_maxMargins.left());
+
+ if (qFuzzyCompare(leftMargin, d->m_margins.left()))
+ return true;
+
if (d->m_mode == FullPageMode
|| (leftMargin >= d->m_minMargins.left() && leftMargin <= d->m_maxMargins.left())) {
d.detach();
d->m_margins.setLeft(leftMargin);
return true;
}
+
return false;
}
@@ -595,23 +633,27 @@ bool QPageLayout::setLeftMargin(qreal leftMargin)
The units used are those currently defined for the layout. To use different
units call setUnits() first.
- If in the default StandardMode then the new margin must fall between the
- minimum margin set and the maximum margin allowed by the page size,
- otherwise the margin will not be set.
-
- If in FullPageMode then any margin values will be accepted.
+ Since Qt 6.8, the optional \a outOfBoundsPolicy can be used to specify how
+ margins that are out of bounds are handled.
\sa setMargins(), margins()
*/
-bool QPageLayout::setRightMargin(qreal rightMargin)
+bool QPageLayout::setRightMargin(qreal rightMargin, OutOfBoundsPolicy outOfBoundsPolicy)
{
+ if (d->m_mode == StandardMode && outOfBoundsPolicy == OutOfBoundsPolicy::Clamp)
+ rightMargin = qBound(d->m_minMargins.right(), rightMargin, d->m_maxMargins.right());
+
+ if (qFuzzyCompare(rightMargin, d->m_margins.right()))
+ return true;
+
if (d->m_mode == FullPageMode
|| (rightMargin >= d->m_minMargins.right() && rightMargin <= d->m_maxMargins.right())) {
d.detach();
d->m_margins.setRight(rightMargin);
return true;
}
+
return false;
}
@@ -622,23 +664,27 @@ bool QPageLayout::setRightMargin(qreal rightMargin)
The units used are those currently defined for the layout. To use different
units call setUnits() first.
- If in the default StandardMode then the new margin must fall between the
- minimum margin set and the maximum margin allowed by the page size,
- otherwise the margin will not be set.
-
- If in FullPageMode then any margin values will be accepted.
+ Since Qt 6.8, the optional \a outOfBoundsPolicy can be used to specify how
+ margins that are out of bounds are handled.
\sa setMargins(), margins()
*/
-bool QPageLayout::setTopMargin(qreal topMargin)
+bool QPageLayout::setTopMargin(qreal topMargin, OutOfBoundsPolicy outOfBoundsPolicy)
{
+ if (d->m_mode == StandardMode && outOfBoundsPolicy == OutOfBoundsPolicy::Clamp)
+ topMargin = qBound(d->m_minMargins.top(), topMargin, d->m_maxMargins.top());
+
+ if (qFuzzyCompare(topMargin, d->m_margins.top()))
+ return true;
+
if (d->m_mode == FullPageMode
|| (topMargin >= d->m_minMargins.top() && topMargin <= d->m_maxMargins.top())) {
d.detach();
d->m_margins.setTop(topMargin);
return true;
}
+
return false;
}
@@ -649,23 +695,27 @@ bool QPageLayout::setTopMargin(qreal topMargin)
The units used are those currently defined for the layout. To use different
units call setUnits() first.
- If in the default StandardMode then the new margin must fall between the
- minimum margin set and the maximum margin allowed by the page size,
- otherwise the margin will not be set.
-
- If in FullPageMode then any margin values will be accepted.
+ Since Qt 6.8, the optional \a outOfBoundsPolicy can be used to specify how
+ margins that are out of bounds are handled.
\sa setMargins(), margins()
*/
-bool QPageLayout::setBottomMargin(qreal bottomMargin)
+bool QPageLayout::setBottomMargin(qreal bottomMargin, OutOfBoundsPolicy outOfBoundsPolicy)
{
+ if (d->m_mode == StandardMode && outOfBoundsPolicy == OutOfBoundsPolicy::Clamp)
+ bottomMargin = qBound(d->m_minMargins.bottom(), bottomMargin, d->m_maxMargins.bottom());
+
+ if (qFuzzyCompare(bottomMargin, d->m_margins.bottom()))
+ return true;
+
if (d->m_mode == FullPageMode
|| (bottomMargin >= d->m_minMargins.bottom() && bottomMargin <= d->m_maxMargins.bottom())) {
d.detach();
d->m_margins.setBottom(bottomMargin);
return true;
}
+
return false;
}
diff --git a/src/gui/painting/qpagelayout.h b/src/gui/painting/qpagelayout.h
index 29be2f9725..1e340b6d75 100644
--- a/src/gui/painting/qpagelayout.h
+++ b/src/gui/painting/qpagelayout.h
@@ -40,6 +40,11 @@ public:
FullPageMode // Paint Rect excludes margins
};
+ enum class OutOfBoundsPolicy {
+ Reject,
+ Clamp
+ };
+
QPageLayout();
QPageLayout(const QPageSize &pageSize, Orientation orientation,
const QMarginsF &margins, Unit units = Point,
@@ -68,11 +73,19 @@ public:
void setUnits(Unit units);
Unit units() const;
+#if QT_GUI_REMOVED_SINCE(6, 8)
bool setMargins(const QMarginsF &margins);
bool setLeftMargin(qreal leftMargin);
bool setRightMargin(qreal rightMargin);
bool setTopMargin(qreal topMargin);
bool setBottomMargin(qreal bottomMargin);
+#endif
+
+ bool setMargins(const QMarginsF &margins, OutOfBoundsPolicy outOfBoundsPolicy = OutOfBoundsPolicy::Reject);
+ bool setLeftMargin(qreal leftMargin, OutOfBoundsPolicy outOfBoundsPolicy = OutOfBoundsPolicy::Reject);
+ bool setRightMargin(qreal rightMargin, OutOfBoundsPolicy outOfBoundsPolicy = OutOfBoundsPolicy::Reject);
+ bool setTopMargin(qreal topMargin, OutOfBoundsPolicy outOfBoundsPolicy = OutOfBoundsPolicy::Reject);
+ bool setBottomMargin(qreal bottomMargin, OutOfBoundsPolicy outOfBoundsPolicy = OutOfBoundsPolicy::Reject);
QMarginsF margins() const;
QMarginsF margins(Unit units) const;
diff --git a/src/gui/painting/qpagesize.h b/src/gui/painting/qpagesize.h
index b3629bb8d2..221863aad7 100644
--- a/src/gui/painting/qpagesize.h
+++ b/src/gui/painting/qpagesize.h
@@ -203,7 +203,9 @@ public:
void swap(QPageSize &other) noexcept { d.swap(other.d); }
+#if QT_GUI_REMOVED_SINCE(6, 4)
friend Q_GUI_EXPORT bool operator==(const QPageSize &lhs, const QPageSize &rhs);
+#endif
bool isEquivalentTo(const QPageSize &other) const;
bool isValid() const;
diff --git a/src/gui/platform/ios/qiosnativeinterface.cpp b/src/gui/platform/ios/qiosnativeinterface.cpp
new file mode 100644
index 0000000000..c942709e33
--- /dev/null
+++ b/src/gui/platform/ios/qiosnativeinterface.cpp
@@ -0,0 +1,26 @@
+// Copyright (C) 2024 The Qt Company Ltd.
+// SPDX-License-Identifier: LicenseRef-Qt-Commercial OR LGPL-3.0-only OR GPL-2.0-only OR GPL-3.0-only
+
+#include <QtGui/private/qguiapplication_p.h>
+
+QT_BEGIN_NAMESPACE
+
+using namespace QNativeInterface::Private;
+
+#if defined(Q_OS_VISIONOS)
+
+/*!
+ \class QNativeInterface::QVisionOSApplication
+ \since 6.8
+ \internal
+ \preliminary
+ \brief Native interface to QGuiApplication, to be retrieved from QPlatformIntegration.
+ \inmodule QtGui
+ \ingroup native-interfaces
+*/
+
+QT_DEFINE_NATIVE_INTERFACE(QVisionOSApplication);
+
+#endif // Q_OS_VISIONOS
+
+QT_END_NAMESPACE
diff --git a/src/gui/platform/unix/qgenericunixthemes.cpp b/src/gui/platform/unix/qgenericunixthemes.cpp
index ce729a74a3..67de34923f 100644
--- a/src/gui/platform/unix/qgenericunixthemes.cpp
+++ b/src/gui/platform/unix/qgenericunixthemes.cpp
@@ -541,6 +541,48 @@ class QKdeThemePrivate : public QPlatformThemePrivate
{
public:
+ enum class KdeSettingType {
+ Root,
+ KDE,
+ Icons,
+ ToolBarIcons,
+ ToolBarStyle,
+ Fonts,
+ Colors,
+ };
+
+ enum class KdeSetting {
+ WidgetStyle,
+ ColorScheme,
+ SingleClick,
+ ShowIconsOnPushButtons,
+ IconTheme,
+ ToolBarIconSize,
+ ToolButtonStyle,
+ WheelScrollLines,
+ DoubleClickInterval,
+ StartDragDistance,
+ StartDragTime,
+ CursorBlinkRate,
+ Font,
+ Fixed,
+ MenuFont,
+ ToolBarFont,
+ ButtonBackground,
+ WindowBackground,
+ ViewForeground,
+ WindowForeground,
+ ViewBackground,
+ SelectionBackground,
+ SelectionForeground,
+ ViewBackgroundAlternate,
+ ButtonForeground,
+ ViewForegroundLink,
+ ViewForegroundVisited,
+ TooltipBackground,
+ TooltipForeground,
+ };
+
QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion);
static QString kdeGlobals(const QString &kdeDir, int kdeVersion)
@@ -551,7 +593,9 @@ public:
}
void refresh();
- static QVariant readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings);
+ static QVariant readKdeSetting(KdeSetting s, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &settings);
+ QVariant readKdeSetting(KdeSetting s) const;
+ void clearKdeSettings() const;
static void readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal);
static QFont *kdeFont(const QVariant &fontValue);
static QStringList kdeIconThemeSearchPaths(const QStringList &kdeDirs);
@@ -575,8 +619,9 @@ public:
Qt::ColorScheme m_colorScheme = Qt::ColorScheme::Unknown;
void updateColorScheme(const QString &themeName);
-#ifndef QT_NO_DBUS
private:
+ mutable QHash<QString, QSettings *> kdeSettings;
+#ifndef QT_NO_DBUS
std::unique_ptr<QGenericUnixThemeDBusListener> dbus;
bool initDbus();
void settingChangedHandler(QGenericUnixThemeDBusListener::Provider provider,
@@ -632,9 +677,136 @@ QKdeThemePrivate::QKdeThemePrivate(const QStringList &kdeDirs, int kdeVersion)
#endif // QT_NO_DBUS
}
+static constexpr QLatin1StringView settingsPrefix(QKdeThemePrivate::KdeSettingType type)
+{
+ switch (type) {
+ case QKdeThemePrivate::KdeSettingType::Root:
+ return QLatin1StringView();
+ case QKdeThemePrivate::KdeSettingType::KDE:
+ return QLatin1StringView("KDE/");
+ case QKdeThemePrivate::KdeSettingType::Fonts:
+ return QLatin1StringView();
+ case QKdeThemePrivate::KdeSettingType::Colors:
+ return QLatin1StringView("Colors:");
+ case QKdeThemePrivate::KdeSettingType::Icons:
+ return QLatin1StringView("Icons/");
+ case QKdeThemePrivate::KdeSettingType::ToolBarIcons:
+ return QLatin1StringView("ToolbarIcons/");
+ case QKdeThemePrivate::KdeSettingType::ToolBarStyle:
+ return QLatin1StringView("Toolbar style/");
+ }
+ Q_UNREACHABLE_RETURN(QLatin1StringView());
+}
+
+static constexpr QKdeThemePrivate::KdeSettingType settingsType(QKdeThemePrivate::KdeSetting setting)
+{
+#define CASE(s, type) case QKdeThemePrivate::KdeSetting::s:\
+ return QKdeThemePrivate::KdeSettingType::type
+
+ switch (setting) {
+ CASE(WidgetStyle, Root);
+ CASE(ColorScheme, Root);
+ CASE(SingleClick, KDE);
+ CASE(ShowIconsOnPushButtons, KDE);
+ CASE(IconTheme, Icons);
+ CASE(ToolBarIconSize, ToolBarIcons);
+ CASE(ToolButtonStyle, ToolBarStyle);
+ CASE(WheelScrollLines, KDE);
+ CASE(DoubleClickInterval, KDE);
+ CASE(StartDragDistance, KDE);
+ CASE(StartDragTime, KDE);
+ CASE(CursorBlinkRate, KDE);
+ CASE(Font, Root);
+ CASE(Fixed, Root);
+ CASE(MenuFont, Root);
+ CASE(ToolBarFont, Root);
+ CASE(ButtonBackground, Colors);
+ CASE(WindowBackground, Colors);
+ CASE(ViewForeground, Colors);
+ CASE(WindowForeground, Colors);
+ CASE(ViewBackground, Colors);
+ CASE(SelectionBackground, Colors);
+ CASE(SelectionForeground, Colors);
+ CASE(ViewBackgroundAlternate, Colors);
+ CASE(ButtonForeground, Colors);
+ CASE(ViewForegroundLink, Colors);
+ CASE(ViewForegroundVisited, Colors);
+ CASE(TooltipBackground, Colors);
+ CASE(TooltipForeground, Colors);
+ };
+ Q_UNREACHABLE_RETURN(QKdeThemePrivate::KdeSettingType::Root);
+}
+#undef CASE
+
+static constexpr QLatin1StringView settingsKey(QKdeThemePrivate::KdeSetting setting)
+{
+ switch (setting) {
+ case QKdeThemePrivate::KdeSetting::WidgetStyle:
+ return QLatin1StringView("widgetStyle");
+ case QKdeThemePrivate::KdeSetting::ColorScheme:
+ return QLatin1StringView("ColorScheme");
+ case QKdeThemePrivate::KdeSetting::SingleClick:
+ return QLatin1StringView("SingleClick");
+ case QKdeThemePrivate::KdeSetting::ShowIconsOnPushButtons:
+ return QLatin1StringView("ShowIconsOnPushButtons");
+ case QKdeThemePrivate::KdeSetting::IconTheme:
+ return QLatin1StringView("Theme");
+ case QKdeThemePrivate::KdeSetting::ToolBarIconSize:
+ return QLatin1StringView("Size");
+ case QKdeThemePrivate::KdeSetting::ToolButtonStyle:
+ return QLatin1StringView("ToolButtonStyle");
+ case QKdeThemePrivate::KdeSetting::WheelScrollLines:
+ return QLatin1StringView("WheelScrollLines");
+ case QKdeThemePrivate::KdeSetting::DoubleClickInterval:
+ return QLatin1StringView("DoubleClickInterval");
+ case QKdeThemePrivate::KdeSetting::StartDragDistance:
+ return QLatin1StringView("StartDragDist");
+ case QKdeThemePrivate::KdeSetting::StartDragTime:
+ return QLatin1StringView("StartDragTime");
+ case QKdeThemePrivate::KdeSetting::CursorBlinkRate:
+ return QLatin1StringView("CursorBlinkRate");
+ case QKdeThemePrivate::KdeSetting::Font:
+ return QLatin1StringView("font");
+ case QKdeThemePrivate::KdeSetting::Fixed:
+ return QLatin1StringView("fixed");
+ case QKdeThemePrivate::KdeSetting::MenuFont:
+ return QLatin1StringView("menuFont");
+ case QKdeThemePrivate::KdeSetting::ToolBarFont:
+ return QLatin1StringView("toolBarFont");
+ case QKdeThemePrivate::KdeSetting::ButtonBackground:
+ return QLatin1StringView("Button/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::WindowBackground:
+ return QLatin1StringView("Window/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::ViewForeground:
+ return QLatin1StringView("View/ForegroundNormal");
+ case QKdeThemePrivate::KdeSetting::WindowForeground:
+ return QLatin1StringView("Window/ForegroundNormal");
+ case QKdeThemePrivate::KdeSetting::ViewBackground:
+ return QLatin1StringView("View/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::SelectionBackground:
+ return QLatin1StringView("Selection/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::SelectionForeground:
+ return QLatin1StringView("Selection/ForegroundNormal");
+ case QKdeThemePrivate::KdeSetting::ViewBackgroundAlternate:
+ return QLatin1StringView("View/BackgroundAlternate");
+ case QKdeThemePrivate::KdeSetting::ButtonForeground:
+ return QLatin1StringView("Button/ForegroundNormal");
+ case QKdeThemePrivate::KdeSetting::ViewForegroundLink:
+ return QLatin1StringView("View/ForegroundLink");
+ case QKdeThemePrivate::KdeSetting::ViewForegroundVisited:
+ return QLatin1StringView("View/ForegroundVisited");
+ case QKdeThemePrivate::KdeSetting::TooltipBackground:
+ return QLatin1StringView("Tooltip/BackgroundNormal");
+ case QKdeThemePrivate::KdeSetting::TooltipForeground:
+ return QLatin1StringView("Tooltip/ForegroundNormal");
+ };
+ Q_UNREACHABLE_RETURN(QLatin1StringView());
+}
+
void QKdeThemePrivate::refresh()
{
resources.clear();
+ clearKdeSettings();
toolButtonStyle = Qt::ToolButtonTextBesideIcon;
toolBarIconSize = 0;
@@ -647,45 +819,39 @@ void QKdeThemePrivate::refresh()
else
iconFallbackThemeName = iconThemeName = QStringLiteral("oxygen");
- QHash<QString, QSettings*> kdeSettings;
-
QPalette systemPalette = QPalette();
readKdeSystemPalette(kdeDirs, kdeVersion, kdeSettings, &systemPalette);
resources.palettes[QPlatformTheme::SystemPalette] = new QPalette(systemPalette);
//## TODO tooltip color
- const QVariant styleValue = readKdeSetting(QStringLiteral("widgetStyle"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant styleValue = readKdeSetting(KdeSetting::WidgetStyle);
if (styleValue.isValid()) {
const QString style = styleValue.toString();
if (style != styleNames.front())
styleNames.push_front(style);
}
- const QVariant colorScheme = readKdeSetting(QStringLiteral("ColorScheme"), kdeDirs,
- kdeVersion, kdeSettings);
+ const QVariant colorScheme = readKdeSetting(KdeSetting::ColorScheme);
- if (colorScheme.isValid())
- updateColorScheme(colorScheme.toString());
- else
- m_colorScheme = Qt::ColorScheme::Unknown;
+ updateColorScheme(colorScheme.toString());
- const QVariant singleClickValue = readKdeSetting(QStringLiteral("KDE/SingleClick"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant singleClickValue = readKdeSetting(KdeSetting::SingleClick);
if (singleClickValue.isValid())
singleClick = singleClickValue.toBool();
- const QVariant showIconsOnPushButtonsValue = readKdeSetting(QStringLiteral("KDE/ShowIconsOnPushButtons"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant showIconsOnPushButtonsValue = readKdeSetting(KdeSetting::ShowIconsOnPushButtons);
if (showIconsOnPushButtonsValue.isValid())
showIconsOnPushButtons = showIconsOnPushButtonsValue.toBool();
- const QVariant themeValue = readKdeSetting(QStringLiteral("Icons/Theme"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant themeValue = readKdeSetting(KdeSetting::IconTheme);
if (themeValue.isValid())
iconThemeName = themeValue.toString();
- const QVariant toolBarIconSizeValue = readKdeSetting(QStringLiteral("ToolbarIcons/Size"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant toolBarIconSizeValue = readKdeSetting(KdeSetting::ToolBarIconSize);
if (toolBarIconSizeValue.isValid())
toolBarIconSize = toolBarIconSizeValue.toInt();
- const QVariant toolbarStyleValue = readKdeSetting(QStringLiteral("Toolbar style/ToolButtonStyle"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant toolbarStyleValue = readKdeSetting(KdeSetting::ToolButtonStyle);
if (toolbarStyleValue.isValid()) {
const QString toolBarStyle = toolbarStyleValue.toString();
if (toolBarStyle == "TextBesideIcon"_L1)
@@ -696,35 +862,35 @@ void QKdeThemePrivate::refresh()
toolButtonStyle = Qt::ToolButtonTextUnderIcon;
}
- const QVariant wheelScrollLinesValue = readKdeSetting(QStringLiteral("KDE/WheelScrollLines"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant wheelScrollLinesValue = readKdeSetting(KdeSetting::WheelScrollLines);
if (wheelScrollLinesValue.isValid())
wheelScrollLines = wheelScrollLinesValue.toInt();
- const QVariant doubleClickIntervalValue = readKdeSetting(QStringLiteral("KDE/DoubleClickInterval"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant doubleClickIntervalValue = readKdeSetting(KdeSetting::DoubleClickInterval);
if (doubleClickIntervalValue.isValid())
doubleClickInterval = doubleClickIntervalValue.toInt();
- const QVariant startDragDistValue = readKdeSetting(QStringLiteral("KDE/StartDragDist"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant startDragDistValue = readKdeSetting(KdeSetting::StartDragDistance);
if (startDragDistValue.isValid())
startDragDist = startDragDistValue.toInt();
- const QVariant startDragTimeValue = readKdeSetting(QStringLiteral("KDE/StartDragTime"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant startDragTimeValue = readKdeSetting(KdeSetting::StartDragTime);
if (startDragTimeValue.isValid())
startDragTime = startDragTimeValue.toInt();
- const QVariant cursorBlinkRateValue = readKdeSetting(QStringLiteral("KDE/CursorBlinkRate"), kdeDirs, kdeVersion, kdeSettings);
+ const QVariant cursorBlinkRateValue = readKdeSetting(KdeSetting::CursorBlinkRate);
if (cursorBlinkRateValue.isValid()) {
cursorBlinkRate = cursorBlinkRateValue.toInt();
cursorBlinkRate = cursorBlinkRate > 0 ? qBound(200, cursorBlinkRate, 2000) : 0;
}
// Read system font, ignore 'smallestReadableFont'
- if (QFont *systemFont = kdeFont(readKdeSetting(QStringLiteral("font"), kdeDirs, kdeVersion, kdeSettings)))
+ if (QFont *systemFont = kdeFont(readKdeSetting(KdeSetting::Font)))
resources.fonts[QPlatformTheme::SystemFont] = systemFont;
else
resources.fonts[QPlatformTheme::SystemFont] = new QFont(QLatin1StringView(defaultSystemFontNameC), defaultSystemFontSize);
- if (QFont *fixedFont = kdeFont(readKdeSetting(QStringLiteral("fixed"), kdeDirs, kdeVersion, kdeSettings))) {
+ if (QFont *fixedFont = kdeFont(readKdeSetting(KdeSetting::Fixed))) {
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
} else {
fixedFont = new QFont(QLatin1StringView(defaultFixedFontNameC), defaultSystemFontSize);
@@ -732,12 +898,12 @@ void QKdeThemePrivate::refresh()
resources.fonts[QPlatformTheme::FixedFont] = fixedFont;
}
- if (QFont *menuFont = kdeFont(readKdeSetting(QStringLiteral("menuFont"), kdeDirs, kdeVersion, kdeSettings))) {
+ if (QFont *menuFont = kdeFont(readKdeSetting(KdeSetting::MenuFont))) {
resources.fonts[QPlatformTheme::MenuFont] = menuFont;
resources.fonts[QPlatformTheme::MenuBarFont] = new QFont(*menuFont);
}
- if (QFont *toolBarFont = kdeFont(readKdeSetting(QStringLiteral("toolBarFont"), kdeDirs, kdeVersion, kdeSettings)))
+ if (QFont *toolBarFont = kdeFont(readKdeSetting(KdeSetting::ToolBarFont)))
resources.fonts[QPlatformTheme::ToolButtonFont] = toolBarFont;
QWindowSystemInterface::handleThemeChange();
@@ -747,7 +913,7 @@ void QKdeThemePrivate::refresh()
qDeleteAll(kdeSettings);
}
-QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings)
+QVariant QKdeThemePrivate::readKdeSetting(KdeSetting s, const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings)
{
for (const QString &kdeDir : kdeDirs) {
QSettings *settings = kdeSettings.value(kdeDir);
@@ -759,6 +925,7 @@ QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList
}
}
if (settings) {
+ const QString key = settingsPrefix(settingsType(s)) + settingsKey(s);
const QVariant value = settings->value(key);
if (value.isValid())
return value;
@@ -767,6 +934,16 @@ QVariant QKdeThemePrivate::readKdeSetting(const QString &key, const QStringList
return QVariant();
}
+QVariant QKdeThemePrivate::readKdeSetting(KdeSetting s) const
+{
+ return readKdeSetting(s, kdeDirs, kdeVersion, kdeSettings);
+}
+
+void QKdeThemePrivate::clearKdeSettings() const
+{
+ kdeSettings.clear();
+}
+
// Reads the color from the KDE configuration, and store it in the
// palette with the given color role if found.
static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVariant &value)
@@ -782,7 +959,7 @@ static inline bool kdeColor(QPalette *pal, QPalette::ColorRole role, const QVari
void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, int kdeVersion, QHash<QString, QSettings*> &kdeSettings, QPalette *pal)
{
- if (!kdeColor(pal, QPalette::Button, readKdeSetting(QStringLiteral("Colors:Button/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings))) {
+ if (!kdeColor(pal, QPalette::Button, readKdeSetting(KdeSetting::ButtonBackground, kdeDirs, kdeVersion, kdeSettings))) {
// kcolorscheme.cpp: SetDefaultColors
const QColor defaultWindowBackground(214, 210, 208);
const QColor defaultButtonBackground(223, 220, 217);
@@ -790,18 +967,18 @@ void QKdeThemePrivate::readKdeSystemPalette(const QStringList &kdeDirs, int kdeV
return;
}
- kdeColor(pal, QPalette::Window, readKdeSetting(QStringLiteral("Colors:Window/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::Text, readKdeSetting(QStringLiteral("Colors:View/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::WindowText, readKdeSetting(QStringLiteral("Colors:Window/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::Base, readKdeSetting(QStringLiteral("Colors:View/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::Highlight, readKdeSetting(QStringLiteral("Colors:Selection/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::HighlightedText, readKdeSetting(QStringLiteral("Colors:Selection/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::AlternateBase, readKdeSetting(QStringLiteral("Colors:View/BackgroundAlternate"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::ButtonText, readKdeSetting(QStringLiteral("Colors:Button/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::Link, readKdeSetting(QStringLiteral("Colors:View/ForegroundLink"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::LinkVisited, readKdeSetting(QStringLiteral("Colors:View/ForegroundVisited"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::ToolTipBase, readKdeSetting(QStringLiteral("Colors:Tooltip/BackgroundNormal"), kdeDirs, kdeVersion, kdeSettings));
- kdeColor(pal, QPalette::ToolTipText, readKdeSetting(QStringLiteral("Colors:Tooltip/ForegroundNormal"), kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Window, readKdeSetting(KdeSetting::WindowBackground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Text, readKdeSetting(KdeSetting::ViewForeground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::WindowText, readKdeSetting(KdeSetting::WindowForeground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Base, readKdeSetting(KdeSetting::ViewBackground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Highlight, readKdeSetting(KdeSetting::SelectionBackground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::HighlightedText, readKdeSetting(KdeSetting::SelectionForeground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::AlternateBase, readKdeSetting(KdeSetting::ViewBackgroundAlternate, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::ButtonText, readKdeSetting(KdeSetting::ButtonForeground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::Link, readKdeSetting(KdeSetting::ViewForegroundLink, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::LinkVisited, readKdeSetting(KdeSetting::ViewForegroundVisited, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::ToolTipBase, readKdeSetting(KdeSetting::TooltipBackground, kdeDirs, kdeVersion, kdeSettings));
+ kdeColor(pal, QPalette::ToolTipText, readKdeSetting(KdeSetting::TooltipForeground, kdeDirs, kdeVersion, kdeSettings));
// The above code sets _all_ color roles to "normal" colors. In KDE, the disabled
// color roles are calculated by applying various effects described in kdeglobals.
@@ -957,13 +1134,13 @@ Qt::ColorScheme QKdeTheme::colorScheme() const
/*!
\internal
- \brief QKdeTheme::setColorScheme - guess and set appearance for unix themes.
- KDE themes do not have an appearance property.
- The key words "dark" or "light" should be part of the theme name.
+ \brief QKdeTheme::updateColorScheme - guess and set a color scheme for unix themes.
+ KDE themes do not have a color scheme property.
+ The key words "dark" or "light" are usually part of the theme name.
This is, however, not a mandatory convention.
- If \param themeName contains a key word, the respective appearance is set.
- If it doesn't, the appearance is heuristically determined by comparing text and base color
+ If \param themeName contains a valid key word, the respective color scheme is set.
+ If it doesn't, the color scheme is heuristically determined by comparing text and base color
of the system palette.
*/
void QKdeThemePrivate::updateColorScheme(const QString &themeName)
@@ -991,7 +1168,6 @@ void QKdeThemePrivate::updateColorScheme(const QString &themeName)
m_colorScheme = Qt::ColorScheme::Unknown;
}
-
const QPalette *QKdeTheme::palette(Palette type) const
{
Q_D(const QKdeTheme);
diff --git a/src/gui/platform/windows/qwindowsnativeinterface.cpp b/src/gui/platform/windows/qwindowsnativeinterface.cpp
index 7ebddb5b9d..44f230e1d3 100644
--- a/src/gui/platform/windows/qwindowsnativeinterface.cpp
+++ b/src/gui/platform/windows/qwindowsnativeinterface.cpp
@@ -181,15 +181,7 @@ QT_DEFINE_NATIVE_INTERFACE(QWindowsScreen);
\value DarkModeStyle The Windows Vista style will be turned off and
a simple dark style will be used.
- \sa isDarkMode(), setDarkModeHandling()
-*/
-
-/*!
- \fn bool QNativeInterface::Private::QWindowsApplication::isDarkMode() const = 0
- \internal
-
- Returns \c true if Windows 10 is configured to use dark mode for
- applications.
+ \sa setDarkModeHandling()
*/
/*!
diff --git a/src/gui/qt_cmdline.cmake b/src/gui/qt_cmdline.cmake
index 379cc417e7..446618ebc4 100644
--- a/src/gui/qt_cmdline.cmake
+++ b/src/gui/qt_cmdline.cmake
@@ -27,7 +27,8 @@ qt_commandline_option(opengl TYPE optionalString VALUES no yes desktop es2 dynam
qt_commandline_option(opengl-es-2 TYPE void NAME opengl VALUE es2)
qt_commandline_option(opengles3 TYPE boolean)
qt_commandline_option(openvg TYPE boolean)
-qt_commandline_option(qpa TYPE string NAME qpa_default_platform)
+qt_commandline_option(qpa TYPE string NAME qpa_platforms)
+qt_commandline_option(default-qpa TYPE string NAME qpa_default_platform)
qt_commandline_option(sm TYPE boolean NAME sessionmanager)
qt_commandline_option(tslib TYPE boolean)
qt_commandline_option(vulkan TYPE boolean)
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 62830c291d..dcaa87a5ff 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -1096,6 +1096,8 @@ bool QRhiGles2::create(QRhi::Flags flags)
caps.glesMultiviewMultisampleRenderToTexture = false;
}
+ caps.unpackRowLength = !caps.gles || caps.ctxMajor >= 3;
+
nativeHandlesStruct.context = ctx;
contextLost = false;
@@ -1426,7 +1428,7 @@ bool QRhiGles2::isFeatureSupported(QRhi::Feature feature) const
case QRhi::PipelineCacheDataLoadSave:
return caps.programBinary;
case QRhi::ImageDataStride:
- return !caps.gles || caps.ctxMajor >= 3;
+ return caps.unpackRowLength;
case QRhi::RenderBufferImport:
return true;
case QRhi::ThreeDimensionalTextures:
@@ -2363,7 +2365,7 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
dataStride = bytesPerLine;
cmd.args.subImage.rowStartAlign = (dataStride & 3) ? 1 : 4;
- cmd.args.subImage.rowLength = bytesPerPixel ? dataStride / bytesPerPixel : 0;
+ cmd.args.subImage.rowLength = caps.unpackRowLength ? (bytesPerPixel ? dataStride / bytesPerPixel : 0) : 0;
cmd.args.subImage.data = data;
};
@@ -2375,7 +2377,15 @@ void QRhiGles2::enqueueSubresUpload(QGles2Texture *texD, QGles2CommandBuffer *cb
const QPoint sp = subresDesc.sourceTopLeft();
if (!subresDesc.sourceSize().isEmpty())
size = subresDesc.sourceSize();
- img = img.copy(sp.x(), sp.y(), size.width(), size.height());
+
+ if (caps.unpackRowLength) {
+ cbD->retainImage(img);
+ // create a non-owning wrapper for the subimage
+ const uchar *data = img.constBits() + sp.y() * img.bytesPerLine() + sp.x() * (qMax(1, img.depth() / 8));
+ img = QImage(data, size.width(), size.height(), img.bytesPerLine(), img.format());
+ } else {
+ img = img.copy(sp.x(), sp.y(), size.width(), size.height());
+ }
}
setCmdByNotCompressedData(cbD->retainImage(img), size, img.bytesPerLine());
diff --git a/src/gui/rhi/qrhigles2_p.h b/src/gui/rhi/qrhigles2_p.h
index 4305186c02..4139579864 100644
--- a/src/gui/rhi/qrhigles2_p.h
+++ b/src/gui/rhi/qrhigles2_p.h
@@ -1014,7 +1014,10 @@ public:
halfAttributes(false),
multiView(false),
timestamps(false),
- objectLabel(false)
+ objectLabel(false),
+ glesMultisampleRenderToTexture(false),
+ glesMultiviewMultisampleRenderToTexture(false),
+ unpackRowLength(false)
{ }
int ctxMajor;
int ctxMinor;
@@ -1073,6 +1076,7 @@ public:
uint objectLabel : 1;
uint glesMultisampleRenderToTexture : 1;
uint glesMultiviewMultisampleRenderToTexture : 1;
+ uint unpackRowLength : 1;
} caps;
QGles2SwapChain *currentSwapChain = nullptr;
QSet<GLint> supportedCompressedFormats;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index 1c7b397193..9fadfc15fa 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -2402,6 +2402,16 @@ QRhi::FrameOpResult QRhiMetal::endFrame(QRhiSwapChain *swapChain, QRhi::EndFrame
dispatch_semaphore_signal(swapChainD->d->sem[thisFrameSlot]);
}];
+#ifdef QRHI_METAL_COMMAND_BUFFERS_WITH_UNRETAINED_REFERENCES
+ // When Metal API validation diagnostics is enabled in Xcode the texture is
+ // released before the command buffer is done with it. Manually keep it alive
+ // to work around this.
+ id<MTLTexture> drawableTexture = [swapChainD->d->curDrawable.texture retain];
+ [swapChainD->cbWrapper.d->cb addCompletedHandler:^(id<MTLCommandBuffer>) {
+ [drawableTexture release];
+ }];
+#endif
+
const bool needsPresent = !flags.testFlag(QRhi::SkipPresent);
const bool presentsWithTransaction = swapChainD->d->layer.presentsWithTransaction;
if (!presentsWithTransaction && needsPresent) {
@@ -2579,7 +2589,6 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
int w = img.width();
int h = img.height();
int bpl = img.bytesPerLine();
- int srcOffset = 0;
if (!subresDesc.sourceSize().isEmpty() || !subresDesc.sourceTopLeft().isNull()) {
const int sx = subresDesc.sourceTopLeft().x();
@@ -2588,10 +2597,12 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
w = subresDesc.sourceSize().width();
h = subresDesc.sourceSize().height();
}
- if (img.depth() == 32) {
- memcpy(reinterpret_cast<char *>(mp) + *curOfs, img.constBits(), size_t(fullImageSizeBytes));
- srcOffset = sy * bpl + sx * 4;
- // bpl remains set to the original image's row stride
+ if (w == img.width()) {
+ const int bpc = qMax(1, img.depth() / 8);
+ Q_ASSERT(h * img.bytesPerLine() <= fullImageSizeBytes);
+ memcpy(reinterpret_cast<char *>(mp) + *curOfs,
+ img.constBits() + sy * img.bytesPerLine() + sx * bpc,
+ h * img.bytesPerLine());
} else {
img = img.copy(sx, sy, w, h);
bpl = img.bytesPerLine();
@@ -2603,7 +2614,7 @@ void QRhiMetal::enqueueSubresUpload(QMetalTexture *texD, void *mp, void *blitEnc
}
[blitEnc copyFromBuffer: texD->d->stagingBuf[currentFrameSlot]
- sourceOffset: NSUInteger(*curOfs + srcOffset)
+ sourceOffset: NSUInteger(*curOfs)
sourceBytesPerRow: NSUInteger(bpl)
sourceBytesPerImage: 0
sourceSize: MTLSizeMake(NSUInteger(w), NSUInteger(h), 1)
@@ -2971,9 +2982,11 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
cbD->d->currentPassRpDesc.depthAttachment.loadAction = MTLLoadActionLoad;
cbD->d->currentPassRpDesc.stencilAttachment.loadAction = MTLLoadActionLoad;
}
+ int colorAttCount = 0;
for (auto it = rtTex->m_desc.cbeginColorAttachments(), itEnd = rtTex->m_desc.cendColorAttachments();
it != itEnd; ++it)
{
+ colorAttCount += 1;
if (it->texture()) {
QRHI_RES(QMetalTexture, it->texture())->lastActiveFrameSlot = currentFrameSlot;
if (it->multiViewCount() >= 2)
@@ -2986,8 +2999,12 @@ void QRhiMetal::beginPass(QRhiCommandBuffer *cb,
}
if (rtTex->m_desc.depthStencilBuffer())
QRHI_RES(QMetalRenderBuffer, rtTex->m_desc.depthStencilBuffer())->lastActiveFrameSlot = currentFrameSlot;
- if (rtTex->m_desc.depthTexture())
- QRHI_RES(QMetalTexture, rtTex->m_desc.depthTexture())->lastActiveFrameSlot = currentFrameSlot;
+ if (rtTex->m_desc.depthTexture()) {
+ QMetalTexture *depthTexture = QRHI_RES(QMetalTexture, rtTex->m_desc.depthTexture());
+ depthTexture->lastActiveFrameSlot = currentFrameSlot;
+ if (colorAttCount == 0 && depthTexture->arraySize() >= 2)
+ cbD->d->currentPassRpDesc.renderTargetArrayLength = NSUInteger(depthTexture->arraySize());
+ }
if (rtTex->m_desc.depthResolveTexture())
QRHI_RES(QMetalTexture, rtTex->m_desc.depthResolveTexture())->lastActiveFrameSlot = currentFrameSlot;
}
@@ -4840,7 +4857,7 @@ void QMetalGraphicsPipeline::setupAttachmentsInMetalRenderPassDescriptor(void *m
}
QRHI_RES_RHI(QRhiMetal);
- rpDesc.sampleCount = NSUInteger(rhiD->effectiveSampleCount(m_sampleCount));
+ rpDesc.rasterSampleCount = NSUInteger(rhiD->effectiveSampleCount(m_sampleCount));
}
void QMetalGraphicsPipeline::setupMetalDepthStencilDescriptor(void *metalDsDesc)
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index f0b51146cc..3dd3c57bd4 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -1598,8 +1598,8 @@ struct RenderPass2SetupHelper
#endif // VK_KHR_create_renderpass2
bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
- const QRhiColorAttachment *firstColorAttachment,
- const QRhiColorAttachment *lastColorAttachment,
+ const QRhiColorAttachment *colorAttachmentsBegin,
+ const QRhiColorAttachment *colorAttachmentsEnd,
bool preserveColor,
bool preserveDs,
bool storeDs,
@@ -1610,7 +1610,7 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
// attachment list layout is color (0-8), ds (0-1), resolve (0-8), ds resolve (0-1)
int multiViewCount = 0;
- for (auto it = firstColorAttachment; it != lastColorAttachment; ++it) {
+ for (auto it = colorAttachmentsBegin; it != colorAttachmentsEnd; ++it) {
QVkTexture *texD = QRHI_RES(QVkTexture, it->texture());
QVkRenderBuffer *rbD = QRHI_RES(QVkRenderBuffer, it->renderBuffer());
Q_ASSERT(texD || rbD);
@@ -1662,10 +1662,14 @@ bool QRhiVulkan::createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
attDesc.initialLayout = preserveDs ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_UNDEFINED;
attDesc.finalLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
rpD->attDescs.append(attDesc);
+ if (depthTexture && depthTexture->arraySize() >= 2 && colorAttachmentsBegin == colorAttachmentsEnd) {
+ multiViewCount = depthTexture->arraySize();
+ rpD->multiViewCount = multiViewCount;
+ }
}
rpD->dsRef = { uint32_t(rpD->attDescs.size() - 1), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL };
- for (auto it = firstColorAttachment; it != lastColorAttachment; ++it) {
+ for (auto it = colorAttachmentsBegin; it != colorAttachmentsEnd; ++it) {
if (it->resolveTexture()) {
QVkTexture *rtexD = QRHI_RES(QVkTexture, it->resolveTexture());
const VkFormat dstFormat = rtexD->vkformat;
@@ -3497,12 +3501,12 @@ void QRhiVulkan::prepareUploadSubres(QVkTexture *texD, int layer, int level,
const int sy = subresDesc.sourceTopLeft().y();
if (!subresDesc.sourceSize().isEmpty())
size = subresDesc.sourceSize();
- if (image.depth() == 32) {
- // The staging buffer will get the full image
- // regardless, just adjust the vk
- // buffer-to-image copy start offset.
- copyInfo.bufferOffset += VkDeviceSize(sy * image.bytesPerLine() + sx * 4);
- // bufferRowLength remains set to the original image's width
+
+ if (size.width() == image.width()) {
+ // No need to make a QImage copy here, can copy from the source
+ // QImage into staging directly.
+ src = image.constBits() + sy * image.bytesPerLine() + sx * bpc;
+ copySizeBytes = size.height() * image.bytesPerLine();
} else {
image = image.copy(sx, sy, size.width(), size.height());
src = image.constBits();
diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h
index ad8687de5d..f23d8550f0 100644
--- a/src/gui/rhi/qrhivulkan_p.h
+++ b/src/gui/rhi/qrhivulkan_p.h
@@ -773,8 +773,8 @@ public:
VkSampleCountFlagBits samples,
VkFormat colorFormat);
bool createOffscreenRenderPass(QVkRenderPassDescriptor *rpD,
- const QRhiColorAttachment *firstColorAttachment,
- const QRhiColorAttachment *lastColorAttachment,
+ const QRhiColorAttachment *colorAttachmentsBegin,
+ const QRhiColorAttachment *colorAttachmentsEnd,
bool preserveColor,
bool preserveDs,
bool storeDs,
diff --git a/src/gui/text/coretext/qfontengine_coretext.mm b/src/gui/text/coretext/qfontengine_coretext.mm
index b6fef2fecb..1050c03d75 100644
--- a/src/gui/text/coretext/qfontengine_coretext.mm
+++ b/src/gui/text/coretext/qfontengine_coretext.mm
@@ -13,6 +13,7 @@
#include <private/qcoregraphics_p.h>
#include <private/qimage_p.h>
#include <private/qguiapplication_p.h>
+#include <private/qstringiterator_p.h>
#include <qpa/qplatformtheme.h>
#include <cmath>
@@ -274,29 +275,30 @@ glyph_t QCoreTextFontEngine::glyphIndex(uint ucs4) const
return glyphIndices[0];
}
-bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
- int *nglyphs, QFontEngine::ShaperFlags flags) const
+int QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
+ int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
if (*nglyphs < len) {
*nglyphs = len;
- return false;
+ return -1;
}
QVarLengthArray<CGGlyph> cgGlyphs(len);
CTFontGetGlyphsForCharacters(ctfont, (const UniChar*)str, cgGlyphs.data(), len);
int glyph_pos = 0;
- for (int i = 0; i < len; ++i) {
- glyphs->glyphs[glyph_pos] = cgGlyphs[i];
- if (glyph_pos < i)
- cgGlyphs[glyph_pos] = cgGlyphs[i];
- glyph_pos++;
-
- // If it's a non-BMP char, skip the lower part of surrogate pair and go
- // directly to the next char without increasing glyph_pos
- if (str[i].isHighSurrogate() && i < len-1 && str[i+1].isLowSurrogate())
- ++i;
+ int mappedGlyphs = 0;
+ QStringIterator it(str, str + len);
+ while (it.hasNext()) {
+ qsizetype idx = it.index();
+ char32_t ucs4 = it.next();
+ glyphs->glyphs[glyph_pos] = cgGlyphs[idx];
+ if (glyph_pos < idx)
+ cgGlyphs[glyph_pos] = cgGlyphs[idx];
+ if (glyphs->glyphs[glyph_pos] != 0 || isIgnorableChar(ucs4))
+ mappedGlyphs++;
+ glyph_pos++;
}
*nglyphs = glyph_pos;
@@ -305,7 +307,7 @@ bool QCoreTextFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *
if (!(flags & GlyphIndicesOnly))
loadAdvancesForGlyphs(cgGlyphs, glyphs);
- return true;
+ return mappedGlyphs;
}
glyph_metrics_t QCoreTextFontEngine::boundingBox(glyph_t glyph)
diff --git a/src/gui/text/coretext/qfontengine_coretext_p.h b/src/gui/text/coretext/qfontengine_coretext_p.h
index af87f5f6f3..2f388c32bc 100644
--- a/src/gui/text/coretext/qfontengine_coretext_p.h
+++ b/src/gui/text/coretext/qfontengine_coretext_p.h
@@ -38,7 +38,7 @@ public:
~QCoreTextFontEngine();
glyph_t glyphIndex(uint ucs4) const override;
- bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
+ int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
void recalcAdvances(QGlyphLayout *, ShaperFlags) const override;
glyph_metrics_t boundingBox(glyph_t glyph) override;
diff --git a/src/gui/text/freetype/qfontengine_ft.cpp b/src/gui/text/freetype/qfontengine_ft.cpp
index 72d2c72fe3..d3791f1f6e 100644
--- a/src/gui/text/freetype/qfontengine_ft.cpp
+++ b/src/gui/text/freetype/qfontengine_ft.cpp
@@ -1678,15 +1678,16 @@ glyph_t QFontEngineFT::glyphIndex(uint ucs4) const
return glyph;
}
-bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
+int QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
if (*nglyphs < len) {
*nglyphs = len;
- return false;
+ return -1;
}
+ int mappedGlyphs = 0;
int glyph_pos = 0;
if (freetype->symbol_map) {
FT_Face face = freetype->face;
@@ -1719,6 +1720,8 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
if (uc < QFreetypeFace::cmapCacheSize)
freetype->cmapCache[uc] = glyph;
}
+ if (glyphs->glyphs[glyph_pos] || isIgnorableChar(uc))
+ mappedGlyphs++;
++glyph_pos;
}
} else {
@@ -1740,6 +1743,8 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
freetype->cmapCache[uc] = glyph;
}
}
+ if (glyphs->glyphs[glyph_pos] || isIgnorableChar(uc))
+ mappedGlyphs++;
++glyph_pos;
}
}
@@ -1750,7 +1755,7 @@ bool QFontEngineFT::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs
if (!(flags & GlyphIndicesOnly))
recalcAdvances(glyphs, flags);
- return true;
+ return mappedGlyphs;
}
bool QFontEngineFT::shouldUseDesignMetrics(QFontEngine::ShaperFlags flags) const
diff --git a/src/gui/text/freetype/qfontengine_ft_p.h b/src/gui/text/freetype/qfontengine_ft_p.h
index c8e5e20d37..bdd4549827 100644
--- a/src/gui/text/freetype/qfontengine_ft_p.h
+++ b/src/gui/text/freetype/qfontengine_ft_p.h
@@ -186,7 +186,7 @@ private:
void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs,
QPainterPath *path, QTextItem::RenderFlags flags) override;
- bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
+ int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
glyph_metrics_t boundingBox(glyph_t glyph) override;
diff --git a/src/gui/text/qcssparser.cpp b/src/gui/text/qcssparser.cpp
index e5815ffce2..7886d9ba91 100644
--- a/src/gui/text/qcssparser.cpp
+++ b/src/gui/text/qcssparser.cpp
@@ -12,6 +12,7 @@
#include <qfontmetrics.h>
#include <qbrush.h>
#include <qimagereader.h>
+#include <qtextformat.h>
#include <algorithm>
@@ -35,6 +36,7 @@ struct QCssKnownValue
quint64 id;
};
+// This array is sorted alphabetically.
static const QCssKnownValue properties[NumProperties - 1] = {
{ "-qt-background-role", QtBackgroundRole },
{ "-qt-block-indent", QtBlockIndent },
@@ -46,6 +48,11 @@ static const QCssKnownValue properties[NumProperties - 1] = {
{ "-qt-list-number-suffix", QtListNumberSuffix },
{ "-qt-paragraph-type", QtParagraphType },
{ "-qt-stroke-color", QtStrokeColor },
+ { "-qt-stroke-dasharray", QtStrokeDashArray },
+ { "-qt-stroke-dashoffset", QtStrokeDashOffset },
+ { "-qt-stroke-linecap", QtStrokeLineCap },
+ { "-qt-stroke-linejoin", QtStrokeLineJoin },
+ { "-qt-stroke-miterlimit", QtStrokeMiterLimit },
{ "-qt-stroke-width", QtStrokeWidth },
{ "-qt-style-features", QtStyleFeatures },
{ "-qt-table-type", QtTableType },
@@ -159,6 +166,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "always", Value_Always },
{ "auto", Value_Auto },
{ "base", Value_Base },
+ { "beveljoin", Value_BevelJoin},
{ "bold", Value_Bold },
{ "bottom", Value_Bottom },
{ "bright-text", Value_BrightText },
@@ -175,6 +183,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "dot-dot-dash", Value_DotDotDash },
{ "dotted", Value_Dotted },
{ "double", Value_Double },
+ { "flatcap", Value_FlatCap},
{ "groove", Value_Groove },
{ "highlight", Value_Highlight },
{ "highlighted-text", Value_HighlightedText },
@@ -193,6 +202,7 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "mid", Value_Mid },
{ "middle", Value_Middle },
{ "midlight", Value_Midlight },
+ { "miterjoin", Value_MiterJoin},
{ "native", Value_Native },
{ "none", Value_None },
{ "normal", Value_Normal },
@@ -207,14 +217,18 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
{ "pre-wrap", Value_PreWrap },
{ "ridge", Value_Ridge },
{ "right", Value_Right },
+ { "roundcap", Value_RoundCap},
+ { "roundjoin", Value_RoundJoin},
{ "selected", Value_Selected },
{ "shadow", Value_Shadow },
{ "small" , Value_Small },
{ "small-caps", Value_SmallCaps },
{ "solid", Value_Solid },
{ "square", Value_Square },
+ { "squarecap", Value_SquareCap},
{ "sub", Value_Sub },
{ "super", Value_Super },
+ { "svgmiterjoin", Value_SvgMiterJoin},
{ "text", Value_Text },
{ "top", Value_Top },
{ "transparent", Value_Transparent },
@@ -230,10 +244,10 @@ static const QCssKnownValue values[NumKnownValues - 1] = {
};
//Map id to strings as they appears in the 'values' array above
-static const short indexOfId[NumKnownValues] = { 0, 41, 48, 42, 49, 50, 55, 35, 26, 71, 72, 25, 43, 5, 64, 48,
- 29, 59, 60, 27, 52, 62, 6, 10, 39, 56, 19, 13, 17, 18, 20, 21, 51, 24, 46, 68, 37, 3, 2, 40, 63, 16,
- 11, 58, 14, 32, 65, 33, 66, 56, 67, 34, 70, 8, 28, 38, 12, 36, 61, 7, 9, 4, 69, 54, 22, 23, 30, 31,
- 1, 15, 0, 53, 45, 44 };
+static const short indexOfId[NumKnownValues] = { 0, 44, 51, 45, 52, 53, 60, 37, 28, 78, 79, 27, 46, 6, 71, 50,
+ 31, 65, 66, 29, 55, 69, 7, 11, 42, 62, 20, 14, 18, 19, 21, 23, 54, 26, 49, 75, 39, 3, 2, 43, 70, 17, 12,
+ 63, 15, 34, 72, 35, 73, 61, 74, 36, 64, 22, 56, 41, 5, 57, 67, 77, 9, 30, 40, 13, 38, 68, 8, 10, 4, 76,
+ 59, 24, 25, 32, 33, 1, 16, 0, 58, 48, 47 };
QString Value::toString() const
{
@@ -396,6 +410,8 @@ LengthData ValueExtractor::lengthValue(const Value& v)
if (data.unit != LengthData::None)
s.chop(2);
+ else if (v.type == Value::Percentage)
+ data.unit = LengthData::Percent;
data.number = s.toDouble();
return data;
@@ -409,6 +425,15 @@ static int lengthValueFromData(const LengthData& data, const QFont& f)
return qRound(qBound(double(INT_MIN) + 0.1, scale * data.number, double(INT_MAX)));
}
+QTextLength ValueExtractor::textLength(const Declaration &decl)
+{
+ const LengthData data = lengthValue(decl.d->values.at(0));
+ if (data.unit == LengthData::Percent)
+ return QTextLength(QTextLength::PercentageLength, data.number);
+
+ return QTextLength(QTextLength::FixedLength, lengthValueFromData(data, f));
+}
+
int ValueExtractor::lengthValue(const Declaration &decl)
{
if (decl.d->parsed.isValid())
@@ -1823,6 +1848,35 @@ bool Declaration::borderCollapseValue() const
return d->values.at(0).toString() == "collapse"_L1;
}
+QList<qreal> Declaration::dashArray() const
+{
+ if (d->propertyId != Property::QtStrokeDashArray || d->values.empty())
+ return QList<qreal>();
+
+ bool isValid = true;
+ QList<qreal> dashes;
+ for (int i = 0; i < d->values.size(); i++) {
+ Value v = d->values[i];
+ // Separators must be at odd indices and Numbers at even indices.
+ bool isValidSeparator = (i & 1) && v.type == Value::TermOperatorComma;
+ bool isValidNumber = !(i & 1) && v.type == Value::Number;
+ if (!isValidNumber && !isValidSeparator) {
+ isValid = false;
+ break;
+ } else if (isValidNumber) {
+ bool ok;
+ dashes.append(v.variant.toReal(&ok));
+ if (!ok) {
+ isValid = false;
+ break;
+ }
+ }
+ }
+
+ isValid &= !(dashes.size() & 1);
+ return isValid ? dashes : QList<qreal>();
+}
+
QIcon Declaration::iconValue() const
{
if (d->parsed.isValid())
diff --git a/src/gui/text/qcssparser_p.h b/src/gui/text/qcssparser_p.h
index c1cfb1ac9b..ba4a611df3 100644
--- a/src/gui/text/qcssparser_p.h
+++ b/src/gui/text/qcssparser_p.h
@@ -169,6 +169,11 @@ enum Property {
QtAccent,
QtStrokeWidth,
QtStrokeColor,
+ QtStrokeLineCap,
+ QtStrokeLineJoin,
+ QtStrokeMiterLimit,
+ QtStrokeDashArray,
+ QtStrokeDashOffset,
QtForeground,
NumProperties
};
@@ -226,6 +231,13 @@ enum KnownValue {
Value_SmallCaps,
Value_Uppercase,
Value_Lowercase,
+ Value_SquareCap,
+ Value_FlatCap,
+ Value_RoundCap,
+ Value_MiterJoin,
+ Value_BevelJoin,
+ Value_RoundJoin,
+ Value_SvgMiterJoin,
/* keep these in same order as QPalette::ColorRole */
Value_FirstColorRole,
@@ -392,7 +404,7 @@ QT_CSS_DECLARE_TYPEINFO(BackgroundData, Q_RELOCATABLE_TYPE)
struct LengthData {
qreal number;
- enum { None, Px, Ex, Em } unit;
+ enum { None, Px, Ex, Em, Percent } unit;
};
QT_CSS_DECLARE_TYPEINFO(LengthData, Q_PRIMITIVE_TYPE)
@@ -451,6 +463,8 @@ struct Q_GUI_EXPORT Declaration
void borderImageValue(QString *image, int *cuts, TileMode *h, TileMode *v) const;
bool borderCollapseValue() const;
+
+ QList<qreal> dashArray() const;
};
QT_CSS_DECLARE_TYPEINFO(Declaration, Q_RELOCATABLE_TYPE)
@@ -835,6 +849,7 @@ struct Q_GUI_EXPORT ValueExtractor
bool extractIcon(QIcon *icon, QSize *size);
void lengthValues(const Declaration &decl, int *m);
+ QTextLength textLength(const Declaration &decl);
private:
void extractFont();
diff --git a/src/gui/text/qfont.cpp b/src/gui/text/qfont.cpp
index bf89905c53..f3a35a4269 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -1462,6 +1462,14 @@ QFont::StyleHint QFont::styleHint() const
\value NoAntialias don't antialias the fonts.
\value NoSubpixelAntialias avoid subpixel antialiasing on the fonts if possible.
\value PreferAntialias antialias if possible.
+ \value [since 6.8] ContextFontMerging If the selected font does not contain a certain character,
+ then Qt automatically chooses a similar-looking fallback font that contains the
+ character. By default this is done on a character-by-character basis. This means that in
+ certain uncommon cases, multiple fonts may be used to represent one string of text even
+ if it's in the same script. Setting \c ContextFontMerging will try finding the fallback
+ font that matches the largest subset of the input string instead. This will be more
+ expensive for strings where missing glyphs occur, but may give more consistent results.
+ If \c NoFontMerging is set, then \c ContextFontMerging will have no effect.
\value NoFontMerging If the font selected for a certain writing system
does not contain a character requested to draw, then Qt automatically chooses a similar
looking font that contains the character. The NoFontMerging flag disables this feature.
@@ -1534,7 +1542,7 @@ void QFont::setStyleStrategy(StyleStrategy s)
Predefined stretch values that follow the CSS naming convention. The higher
the value, the more stretched the text is.
- \value AnyStretch 0 Accept any stretch matched using the other QFont properties (added in Qt 5.8)
+ \value [since 5.8] AnyStretch 0 Accept any stretch matched using the other QFont properties
\value UltraCondensed 50
\value ExtraCondensed 62
\value Condensed 75
@@ -2427,9 +2435,7 @@ std::optional<QFont::Tag> QFont::Tag::fromString(QAnyStringView view) noexcept
By default, no variable axes are set.
- \note In order to use variable axes on Windows, the application has to run with either the
- FreeType or DirectWrite font databases. See the documentation for
- QGuiApplication::QGuiApplication() for more information on how to select these technologies.
+ \note On Windows, variable axes are not supported if the optional GDI font backend is in use.
\sa unsetVariableAxis
*/
@@ -3266,7 +3272,7 @@ bool QFontInfo::fixedPitch() const
QChar ch[2] = { u'i', u'm' };
QGlyphLayoutArray<2> g;
int l = 2;
- if (!engine->stringToCMap(ch, 2, &g, &l, {}))
+ if (engine->stringToCMap(ch, 2, &g, &l, {}) < 0)
Q_UNREACHABLE();
Q_ASSERT(l == 2);
engine->fontDef.fixedPitch = g.advances[0] == g.advances[1];
diff --git a/src/gui/text/qfont.h b/src/gui/text/qfont.h
index ace07780b5..66a5f7c155 100644
--- a/src/gui/text/qfont.h
+++ b/src/gui/text/qfont.h
@@ -47,6 +47,7 @@ public:
NoAntialias = 0x0100,
NoSubpixelAntialias = 0x0800,
PreferNoShaping = 0x1000,
+ ContextFontMerging = 0x2000,
NoFontMerging = 0x8000
};
Q_ENUM(StyleStrategy)
diff --git a/src/gui/text/qfontdatabase.cpp b/src/gui/text/qfontdatabase.cpp
index d3a13d801b..3d6d3b7886 100644
--- a/src/gui/text/qfontdatabase.cpp
+++ b/src/gui/text/qfontdatabase.cpp
@@ -670,7 +670,7 @@ static QStringList fallbacksForFamily(const QString &family, QFont::Style style,
return *fallbacks;
// make sure that the db has all fallback families
- QStringList userFallbacks = db->applicationFallbackFontFamilies.value(script == QChar::Script_Common ? QChar::Script_Latin : script);
+ QStringList userFallbacks = db->applicationFallbackFontFamilies.value(script == QChar::Script_Latin ? QChar::Script_Common : script);
QStringList retList = userFallbacks + QGuiApplicationPrivate::platformIntegration()->fontDatabase()->fallbacksForFamily(family,style,styleHint,script);
QStringList::iterator i;
@@ -2187,6 +2187,8 @@ int QFontDatabasePrivate::addAppFont(const QByteArray &fontData, const QString &
// loaded, so it has to be flushed.
QFontCache::instance()->clear();
+ fallbacksCache.clear();
+
emit qApp->fontDatabaseChanged();
return i;
@@ -2386,23 +2388,32 @@ bool QFontDatabase::removeAllApplicationFonts()
be prioritized in reverse order, so that the last family added will be checked first and so
on.
+ \note Qt's font matching algorithm considers \c{QChar::Script_Common} (undetermined script)
+ and \c{QChar::Script_Latin} the same. Adding a fallback for either of these will also apply
+ to the other.
+
\sa setApplicationFallbackFontFamilies(), removeApplicationFallbackFontFamily(), applicationFallbackFontFamilies()
*/
void QFontDatabase::addApplicationFallbackFontFamily(QChar::Script script, const QString &familyName)
{
QMutexLocker locker(fontDatabaseMutex());
- if (script < QChar::Script_Latin) {
+ if (script < QChar::Script_Common) {
qCWarning(lcFontDb) << "Invalid script passed to addApplicationFallbackFontFamily:" << script;
return;
}
+ if (script == QChar::Script_Latin)
+ script = QChar::Script_Common;
+
auto *db = QFontDatabasePrivate::instance();
auto it = db->applicationFallbackFontFamilies.find(script);
if (it == db->applicationFallbackFontFamilies.end())
it = db->applicationFallbackFontFamilies.insert(script, QStringList{});
it->prepend(familyName);
+
+ QFontCache::instance()->clear();
db->fallbacksCache.clear();
}
@@ -2420,6 +2431,14 @@ bool QFontDatabase::removeApplicationFallbackFontFamily(QChar::Script script, co
{
QMutexLocker locker(fontDatabaseMutex());
+ if (script < QChar::Script_Common) {
+ qCWarning(lcFontDb) << "Invalid script passed to removeApplicationFallbackFontFamily:" << script;
+ return false;
+ }
+
+ if (script == QChar::Script_Latin)
+ script = QChar::Script_Common;
+
auto *db = QFontDatabasePrivate::instance();
auto it = db->applicationFallbackFontFamilies.find(script);
if (it != db->applicationFallbackFontFamilies.end()) {
@@ -2452,11 +2471,14 @@ void QFontDatabase::setApplicationFallbackFontFamilies(QChar::Script script, con
{
QMutexLocker locker(fontDatabaseMutex());
- if (script < QChar::Script_Latin) {
+ if (script < QChar::Script_Common) {
qCWarning(lcFontDb) << "Invalid script passed to setApplicationFallbackFontFamilies:" << script;
return;
}
+ if (script == QChar::Script_Latin)
+ script = QChar::Script_Common;
+
auto *db = QFontDatabasePrivate::instance();
db->applicationFallbackFontFamilies[script] = familyNames;
@@ -2476,6 +2498,9 @@ QStringList QFontDatabase::applicationFallbackFontFamilies(QChar::Script script)
{
QMutexLocker locker(fontDatabaseMutex());
+ if (script == QChar::Script_Latin)
+ script = QChar::Script_Common;
+
auto *db = QFontDatabasePrivate::instance();
return db->applicationFallbackFontFamilies.value(script);
}
diff --git a/src/gui/text/qfontengine.cpp b/src/gui/text/qfontengine.cpp
index dff400c18b..4e78aaac2e 100644
--- a/src/gui/text/qfontengine.cpp
+++ b/src/gui/text/qfontengine.cpp
@@ -13,6 +13,7 @@
#include "qpainter.h"
#include "qpainterpath.h"
#include "qvarlengtharray.h"
+#include "qtextengine_p.h"
#include <qmath.h>
#include <qendian.h>
#include <private/qstringiterator_p.h>
@@ -1542,12 +1543,12 @@ glyph_t QFontEngineBox::glyphIndex(uint ucs4) const
return 1;
}
-bool QFontEngineBox::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
+int QFontEngineBox::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
if (*nglyphs < len) {
*nglyphs = len;
- return false;
+ return -1;
}
int ucs4Length = 0;
@@ -1563,7 +1564,7 @@ bool QFontEngineBox::stringToCMap(const QChar *str, int len, QGlyphLayout *glyph
if (!(flags & GlyphIndicesOnly))
recalcAdvances(glyphs, flags);
- return true;
+ return *nglyphs;
}
void QFontEngineBox::recalcAdvances(QGlyphLayout *glyphs, QFontEngine::ShaperFlags) const
@@ -1793,11 +1794,7 @@ QFontEngine *QFontEngineMulti::loadEngine(int at)
glyph_t QFontEngineMulti::glyphIndex(uint ucs4) const
{
glyph_t glyph = engine(0)->glyphIndex(ucs4);
- if (glyph == 0
- && ucs4 != QChar::LineSeparator
- && ucs4 != QChar::LineFeed
- && ucs4 != QChar::CarriageReturn
- && ucs4 != QChar::ParagraphSeparator) {
+ if (glyph == 0 && !isIgnorableChar(ucs4)) {
if (!m_fallbackFamiliesQueried)
const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {
@@ -1824,13 +1821,55 @@ glyph_t QFontEngineMulti::glyphIndex(uint ucs4) const
return glyph;
}
-bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
- QGlyphLayout *glyphs, int *nglyphs,
- QFontEngine::ShaperFlags flags) const
+int QFontEngineMulti::stringToCMap(const QChar *str, int len,
+ QGlyphLayout *glyphs, int *nglyphs,
+ QFontEngine::ShaperFlags flags) const
{
- if (!engine(0)->stringToCMap(str, len, glyphs, nglyphs, flags))
- return false;
+ const int originalNumGlyphs = glyphs->numGlyphs;
+ int mappedGlyphCount = engine(0)->stringToCMap(str, len, glyphs, nglyphs, flags);
+ if (mappedGlyphCount < 0)
+ return -1;
+
+ // If ContextFontMerging is set and the match for the string was incomplete, we try all
+ // fallbacks on the full string until we find the best match.
+ bool contextFontMerging = mappedGlyphCount < *nglyphs && (fontDef.styleStrategy & QFont::ContextFontMerging);
+ if (contextFontMerging) {
+ QVarLengthGlyphLayoutArray tempLayout(len);
+ if (!m_fallbackFamiliesQueried)
+ const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
+ int maxGlyphCount = 0;
+ uchar engineIndex = 0;
+ for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {
+ int numGlyphs = len;
+ const_cast<QFontEngineMulti *>(this)->ensureEngineAt(x);
+ maxGlyphCount = engine(x)->stringToCMap(str, len, &tempLayout, &numGlyphs, flags);
+
+ // If we found a better match, we copy data into the main QGlyphLayout
+ if (maxGlyphCount > mappedGlyphCount) {
+ *nglyphs = numGlyphs;
+ glyphs->numGlyphs = originalNumGlyphs;
+ glyphs->copy(&tempLayout);
+ engineIndex = x;
+ if (maxGlyphCount == numGlyphs)
+ break;
+ }
+ }
+
+ if (engineIndex > 0) {
+ for (int y = 0; y < glyphs->numGlyphs; ++y) {
+ if (glyphs->glyphs[y] != 0)
+ glyphs->glyphs[y] |= (engineIndex << 24);
+ }
+ } else {
+ contextFontMerging = false;
+ }
+
+ mappedGlyphCount = maxGlyphCount;
+ }
+
+ // Fill in missing glyphs by going through string one character at the time and finding
+ // the first viable fallback.
int glyph_pos = 0;
QStringIterator it(str, str + len);
@@ -1861,15 +1900,10 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
lastFallback = -1;
}
- if (glyphs->glyphs[glyph_pos] == 0
- && ucs4 != QChar::LineSeparator
- && ucs4 != QChar::LineFeed
- && ucs4 != QChar::CarriageReturn
- && ucs4 != QChar::ParagraphSeparator
- && QChar::category(ucs4) != QChar::Other_Control) {
+ if (glyphs->glyphs[glyph_pos] == 0 && !isIgnorableChar(ucs4)) {
if (!m_fallbackFamiliesQueried)
const_cast<QFontEngineMulti *>(this)->ensureFallbackFamiliesQueried();
- for (int x = 1, n = qMin(m_engines.size(), 256); x < n; ++x) {
+ for (int x = contextFontMerging ? 0 : 1, n = qMin(m_engines.size(), 256); x < n; ++x) {
QFontEngine *engine = m_engines.at(x);
if (!engine) {
if (!shouldLoadFontEngineForCharacter(x, ucs4))
@@ -1946,8 +1980,7 @@ bool QFontEngineMulti::stringToCMap(const QChar *str, int len,
*nglyphs = glyph_pos;
glyphs->numGlyphs = glyph_pos;
-
- return true;
+ return mappedGlyphCount;
}
bool QFontEngineMulti::shouldLoadFontEngineForCharacter(int at, uint ucs4) const
@@ -2239,7 +2272,7 @@ bool QFontEngineMulti::canRender(const QChar *string, int len) const
QGlyphLayout g;
g.numGlyphs = nglyphs;
g.glyphs = glyphs.data();
- if (!stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly))
+ if (stringToCMap(string, len, &g, &nglyphs, GlyphIndicesOnly) < 0)
Q_UNREACHABLE();
for (int i = 0; i < nglyphs; i++) {
diff --git a/src/gui/text/qfontengine_p.h b/src/gui/text/qfontengine_p.h
index af44eeab3f..a0e0801354 100644
--- a/src/gui/text/qfontengine_p.h
+++ b/src/gui/text/qfontengine_p.h
@@ -76,7 +76,8 @@ public:
enum ShaperFlag {
DesignMetrics = 0x0002,
- GlyphIndicesOnly = 0x0004
+ GlyphIndicesOnly = 0x0004,
+ FullStringFallback = 0x008
};
Q_DECLARE_FLAGS(ShaperFlags, ShaperFlag)
@@ -148,12 +149,20 @@ public:
}
bool isColorFont() const { return glyphFormat == Format_ARGB; }
+ static bool isIgnorableChar(char32_t ucs4)
+ {
+ return ucs4 == QChar::LineSeparator
+ || ucs4 == QChar::LineFeed
+ || ucs4 == QChar::CarriageReturn
+ || ucs4 == QChar::ParagraphSeparator
+ || QChar::category(ucs4) == QChar::Other_Control;
+ }
virtual QFixed emSquareSize() const { return ascent(); }
/* returns 0 as glyph index for non existent glyphs */
virtual glyph_t glyphIndex(uint ucs4) const = 0;
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const = 0;
+ virtual int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const = 0;
virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const {}
virtual void doKerning(QGlyphLayout *, ShaperFlags) const;
@@ -393,7 +402,7 @@ public:
~QFontEngineBox();
virtual glyph_t glyphIndex(uint ucs4) const override;
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
+ virtual int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
virtual void recalcAdvances(QGlyphLayout *, ShaperFlags) const override;
void draw(QPaintEngine *p, qreal x, qreal y, const QTextItemInt &si);
@@ -431,7 +440,7 @@ public:
~QFontEngineMulti();
virtual glyph_t glyphIndex(uint ucs4) const override;
- virtual bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
+ virtual int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
virtual glyph_metrics_t boundingBox(const QGlyphLayout &glyphs) override;
virtual glyph_metrics_t boundingBox(glyph_t glyph) override;
diff --git a/src/gui/text/qrawfont.cpp b/src/gui/text/qrawfont.cpp
index c5a92f95cb..54676b3560 100644
--- a/src/gui/text/qrawfont.cpp
+++ b/src/gui/text/qrawfont.cpp
@@ -498,7 +498,7 @@ QList<quint32> QRawFont::glyphIndexesForString(const QString &text) const
QGlyphLayout glyphs;
glyphs.numGlyphs = numGlyphs;
glyphs.glyphs = glyphIndexes.data();
- if (!d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly))
+ if (d->fontEngine->stringToCMap(text.data(), text.size(), &glyphs, &numGlyphs, QFontEngine::GlyphIndicesOnly) < 0)
Q_UNREACHABLE();
glyphIndexes.resize(numGlyphs);
@@ -531,7 +531,7 @@ bool QRawFont::glyphIndexesForChars(const QChar *chars, int numChars, quint32 *g
QGlyphLayout glyphs;
glyphs.numGlyphs = *numGlyphs;
glyphs.glyphs = glyphIndexes;
- return d->fontEngine->stringToCMap(chars, numChars, &glyphs, numGlyphs, QFontEngine::GlyphIndicesOnly);
+ return d->fontEngine->stringToCMap(chars, numChars, &glyphs, numGlyphs, QFontEngine::GlyphIndicesOnly) >= 0;
}
/*!
diff --git a/src/gui/text/qtextdocument.cpp b/src/gui/text/qtextdocument.cpp
index 15a313e13d..c39d3514c5 100644
--- a/src/gui/text/qtextdocument.cpp
+++ b/src/gui/text/qtextdocument.cpp
@@ -53,6 +53,9 @@ namespace {
QTextDocument::ResourceProvider qt_defaultResourceProvider;
};
+QAbstractUndoItem::~QAbstractUndoItem()
+ = default;
+
/*!
\fn bool Qt::mightBeRichText(QAnyStringView text)
@@ -2757,6 +2760,51 @@ bool QTextHtmlExporter::emitCharFormatStyle(const QTextCharFormat &format)
html += " -qt-stroke-width:"_L1;
html += QString::number(outlinePen.widthF());
html += "px;"_L1;
+
+ html += " -qt-stroke-linecap:"_L1;
+ if (outlinePen.capStyle() == Qt::SquareCap)
+ html += "squarecap;"_L1;
+ else if (outlinePen.capStyle() == Qt::FlatCap)
+ html += "flatcap;"_L1;
+ else if (outlinePen.capStyle() == Qt::RoundCap)
+ html += "roundcap;"_L1;
+
+ html += " -qt-stroke-linejoin:"_L1;
+ if (outlinePen.joinStyle() == Qt::MiterJoin)
+ html += "miterjoin;"_L1;
+ else if (outlinePen.joinStyle() == Qt::SvgMiterJoin)
+ html += "svgmiterjoin;"_L1;
+ else if (outlinePen.joinStyle() == Qt::BevelJoin)
+ html += "beveljoin;"_L1;
+ else if (outlinePen.joinStyle() == Qt::RoundJoin)
+ html += "roundjoin;"_L1;
+
+ if (outlinePen.joinStyle() == Qt::MiterJoin ||
+ outlinePen.joinStyle() == Qt::SvgMiterJoin) {
+ html += " -qt-stroke-miterlimit:"_L1;
+ html += QString::number(outlinePen.miterLimit());
+ html += u';';
+ }
+
+ if (outlinePen.style() == Qt::CustomDashLine && !outlinePen.dashPattern().empty()) {
+ html += " -qt-stroke-dasharray:"_L1;
+ QString dashArrayString;
+ QList<qreal> dashes = outlinePen.dashPattern();
+
+ for (int i = 0; i < dashes.length() - 1; i++) {
+ qreal dash = dashes[i];
+ dashArrayString += QString::number(dash) + u',';
+ }
+
+ dashArrayString += QString::number(dashes.last());
+ html += dashArrayString;
+ html += u';';
+
+ html += " -qt-stroke-dashoffset:"_L1;
+ html += QString::number(outlinePen.dashOffset());
+ html += u';';
+ }
+
attributesEmitted = true;
}
@@ -2944,6 +2992,17 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
html += "<img"_L1;
+ QString maxWidthCss;
+
+ if (imgFmt.hasProperty(QTextFormat::ImageMaxWidth)) {
+ auto length = imgFmt.lengthProperty(QTextFormat::ImageMaxWidth);
+ maxWidthCss += "max-width:"_L1;
+ if (length.type() == QTextLength::PercentageLength)
+ maxWidthCss += QString::number(length.rawValue()) + "%;"_L1;
+ else if (length.type() == QTextLength::FixedLength)
+ maxWidthCss += QString::number(length.rawValue()) + "px;"_L1;
+ }
+
if (imgFmt.hasProperty(QTextFormat::ImageName))
emitAttribute("src", imgFmt.name());
@@ -2960,9 +3019,11 @@ void QTextHtmlExporter::emitFragment(const QTextFragment &fragment)
emitAttribute("height", QString::number(imgFmt.height()));
if (imgFmt.verticalAlignment() == QTextCharFormat::AlignMiddle)
- html += " style=\"vertical-align: middle;\""_L1;
+ html += " style=\"vertical-align: middle;"_L1 + maxWidthCss + u'\"';
else if (imgFmt.verticalAlignment() == QTextCharFormat::AlignTop)
- html += " style=\"vertical-align: top;\""_L1;
+ html += " style=\"vertical-align: top;"_L1 + maxWidthCss + u'\"';
+ else if (!maxWidthCss.isEmpty())
+ html += " style=\""_L1 + maxWidthCss + u'\"';
if (QTextFrame *imageFrame = qobject_cast<QTextFrame *>(doc->objectForFormat(imgFmt)))
emitFloatStyle(imageFrame->frameFormat().position());
diff --git a/src/gui/text/qtextdocument.h b/src/gui/text/qtextdocument.h
index b6253bfa46..11a8abcb50 100644
--- a/src/gui/text/qtextdocument.h
+++ b/src/gui/text/qtextdocument.h
@@ -45,15 +45,11 @@ namespace Qt
class Q_GUI_EXPORT QAbstractUndoItem
{
public:
- virtual ~QAbstractUndoItem() = 0;
+ virtual ~QAbstractUndoItem();
virtual void undo() = 0;
virtual void redo() = 0;
};
-inline QAbstractUndoItem::~QAbstractUndoItem()
-{
-}
-
class QTextDocumentPrivate;
class Q_GUI_EXPORT QTextDocument : public QObject
diff --git a/src/gui/text/qtextdocumentlayout.cpp b/src/gui/text/qtextdocumentlayout.cpp
index baff79973f..452f814231 100644
--- a/src/gui/text/qtextdocumentlayout.cpp
+++ b/src/gui/text/qtextdocumentlayout.cpp
@@ -2216,17 +2216,15 @@ void QTextDocumentLayoutPrivate::drawListItem(const QPointF &offset, QPainter *p
}
case QTextListFormat::ListSquare:
if (!marker)
- painter->fillRect(r, brush);
+ painter->fillRect(r, painter->pen().brush());
break;
case QTextListFormat::ListCircle:
- if (!marker) {
- painter->setPen(QPen(brush, 0));
+ if (!marker)
painter->drawEllipse(r.translated(0.5, 0.5)); // pixel align for sharper rendering
- }
break;
case QTextListFormat::ListDisc:
if (!marker) {
- painter->setBrush(brush);
+ painter->setBrush(painter->pen().brush());
painter->setPen(Qt::NoPen);
painter->drawEllipse(r);
}
diff --git a/src/gui/text/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index cb945b73ce..08512bead5 100644
--- a/src/gui/text/qtextengine.cpp
+++ b/src/gui/text/qtextengine.cpp
@@ -1396,7 +1396,9 @@ void QTextEngine::shapeText(int item) const
QFontEngine *fontEngine = this->fontEngine(si, &si.ascent, &si.descent, &si.leading);
+#if QT_CONFIG(harfbuzz)
bool kerningEnabled;
+#endif
bool letterSpacingIsAbsolute;
bool shapingEnabled = false;
QHash<QFont::Tag, quint32> features;
@@ -1405,8 +1407,8 @@ void QTextEngine::shapeText(int item) const
if (useRawFont) {
QTextCharFormat f = format(&si);
QFont font = f.font();
- kerningEnabled = font.kerning();
# if QT_CONFIG(harfbuzz)
+ kerningEnabled = font.kerning();
shapingEnabled = QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script))
|| (font.styleStrategy() & QFont::PreferNoShaping) == 0;
# endif
@@ -1418,8 +1420,8 @@ void QTextEngine::shapeText(int item) const
#endif
{
QFont font = this->font(si);
- kerningEnabled = font.d->kerning;
#if QT_CONFIG(harfbuzz)
+ kerningEnabled = font.d->kerning;
shapingEnabled = QFontEngine::scriptRequiresOpenType(QChar::Script(si.analysis.script))
|| (font.d->request.styleStrategy & QFont::PreferNoShaping) == 0;
#endif
@@ -1445,7 +1447,7 @@ void QTextEngine::shapeText(int item) const
shapingEnabled
? QFontEngine::GlyphIndicesOnly
: QFontEngine::ShaperFlag(0);
- if (!fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags))
+ if (fontEngine->stringToCMap(reinterpret_cast<const QChar *>(string), itemLength, &initialGlyphs, &nGlyphs, shaperFlags) < 0)
Q_UNREACHABLE();
}
@@ -2741,6 +2743,21 @@ bool QTextEngine::LayoutData::reallocate(int totalGlyphs)
return true;
}
+void QGlyphLayout::copy(QGlyphLayout *oldLayout)
+{
+ Q_ASSERT(offsets != oldLayout->offsets);
+
+ int n = std::min(numGlyphs, oldLayout->numGlyphs);
+
+ memcpy(offsets, oldLayout->offsets, n * sizeof(QFixedPoint));
+ memcpy(attributes, oldLayout->attributes, n * sizeof(QGlyphAttributes));
+ memcpy(justifications, oldLayout->justifications, n * sizeof(QGlyphJustification));
+ memcpy(advances, oldLayout->advances, n * sizeof(QFixed));
+ memcpy(glyphs, oldLayout->glyphs, n * sizeof(glyph_t));
+
+ numGlyphs = n;
+}
+
// grow to the new size, copying the existing data to the new layout
void QGlyphLayout::grow(char *address, int totalGlyphs)
{
diff --git a/src/gui/text/qtextengine_p.h b/src/gui/text/qtextengine_p.h
index a829265a22..c01d3a0711 100644
--- a/src/gui/text/qtextengine_p.h
+++ b/src/gui/text/qtextengine_p.h
@@ -224,6 +224,7 @@ struct QGlyphLayout
return reinterpret_cast<char *>(offsets);
}
+ void copy(QGlyphLayout *other);
void grow(char *address, int totalGlyphs);
};
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index 509b2eb7cc..dacef70812 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -405,26 +405,26 @@ Q_GUI_EXPORT QDataStream &operator<<(QDataStream &stream, const QTextFormat &fmt
{
QMap<int, QVariant> properties = fmt.properties();
if (stream.version() < QDataStream::Qt_6_0) {
- auto it = properties.find(QTextFormat::FontLetterSpacingType);
- if (it != properties.end()) {
+ auto it = properties.constFind(QTextFormat::FontLetterSpacingType);
+ if (it != properties.cend()) {
properties[QTextFormat::OldFontLetterSpacingType] = it.value();
properties.erase(it);
}
- it = properties.find(QTextFormat::FontStretch);
- if (it != properties.end()) {
+ it = properties.constFind(QTextFormat::FontStretch);
+ if (it != properties.cend()) {
properties[QTextFormat::OldFontStretch] = it.value();
properties.erase(it);
}
- it = properties.find(QTextFormat::TextUnderlineColor);
- if (it != properties.end()) {
+ it = properties.constFind(QTextFormat::TextUnderlineColor);
+ if (it != properties.cend()) {
properties[QTextFormat::OldTextUnderlineColor] = it.value();
properties.erase(it);
}
- it = properties.find(QTextFormat::FontFamilies);
- if (it != properties.end()) {
+ it = properties.constFind(QTextFormat::FontFamilies);
+ if (it != properties.cend()) {
properties[QTextFormat::OldFontFamily] = QVariant(it.value().toStringList().constFirst());
properties.erase(it);
}
@@ -745,6 +745,7 @@ Q_GUI_EXPORT QDataStream &operator>>(QDataStream &stream, QTextTableCellFormat &
\value ImageWidth
\value ImageHeight
\value ImageQuality
+ \value ImageMaxWidth This enum value has been added in Qt 6.8.
Selection properties
@@ -3156,7 +3157,8 @@ QTextTableFormat::QTextTableFormat()
: QTextFrameFormat()
{
setObjectType(TableObject);
- setCellSpacing(2);
+ setCellPadding(4);
+ setBorderCollapse(true);
setBorder(1);
}
@@ -3425,7 +3427,7 @@ QTextImageFormat::QTextImageFormat(const QTextFormat &fmt)
Sets the \a width of the rectangle occupied by the image.
- \sa width(), setHeight()
+ \sa width(), setHeight(), maximumWidth()
*/
@@ -3437,6 +3439,24 @@ QTextImageFormat::QTextImageFormat(const QTextFormat &fmt)
\sa height(), setWidth()
*/
+/*!
+ \fn void QTextImageFormat::setMaximumWidth(QTextLength maximumWidth)
+
+ Sets the \a maximumWidth of the rectangle occupied by the image. This
+ can be an absolute number or a percentage of the available document size.
+
+ \sa width(), setHeight()
+*/
+
+
+/*!
+ \fn QTextLength QTextImageFormat::maximumWidth() const
+
+ Returns the maximum width of the rectangle occupied by the image.
+
+ \sa width(), setMaximumWidth()
+*/
+
/*!
\fn void QTextImageFormat::setHeight(qreal height)
diff --git a/src/gui/text/qtextformat.h b/src/gui/text/qtextformat.h
index c009d328cb..2fa86ed0d1 100644
--- a/src/gui/text/qtextformat.h
+++ b/src/gui/text/qtextformat.h
@@ -241,6 +241,7 @@ public:
ImageWidth = 0x5010,
ImageHeight = 0x5011,
ImageQuality = 0x5014,
+ ImageMaxWidth = 0x5015,
// internal
/*
@@ -796,6 +797,10 @@ public:
inline qreal width() const
{ return doubleProperty(ImageWidth); }
+ inline void setMaximumWidth(QTextLength maxWidth);
+ inline QTextLength maximumWidth() const
+ { return lengthProperty(ImageMaxWidth); }
+
inline void setHeight(qreal height);
inline qreal height() const
{ return doubleProperty(ImageHeight); }
@@ -823,6 +828,9 @@ inline void QTextImageFormat::setName(const QString &aname)
inline void QTextImageFormat::setWidth(qreal awidth)
{ setProperty(ImageWidth, awidth); }
+inline void QTextImageFormat::setMaximumWidth(QTextLength maxWidth)
+{ setProperty(ImageMaxWidth, maxWidth); }
+
inline void QTextImageFormat::setHeight(qreal aheight)
{ setProperty(ImageHeight, aheight); }
diff --git a/src/gui/text/qtexthtmlparser.cpp b/src/gui/text/qtexthtmlparser.cpp
index ee92cece78..54c291b82e 100644
--- a/src/gui/text/qtexthtmlparser.cpp
+++ b/src/gui/text/qtexthtmlparser.cpp
@@ -1422,12 +1422,74 @@ void QTextHtmlParserNode::applyCssDeclarations(const QList<QCss::Declaration> &d
}
break;
}
+ case QCss::QtStrokeLineCap:
+ {
+ QPen pen = charFormat.textOutline();
+ switch (identifier) {
+ case QCss::Value_SquareCap: pen.setCapStyle(Qt::SquareCap); break;
+ case QCss::Value_FlatCap: pen.setCapStyle(Qt::FlatCap); break;
+ case QCss::Value_RoundCap: pen.setCapStyle(Qt::RoundCap); break;
+ default: break;
+ }
+ charFormat.setTextOutline(pen);
+ break;
+ }
+ case QCss::QtStrokeLineJoin:
+ {
+ QPen pen = charFormat.textOutline();
+ switch (identifier) {
+ case QCss::Value_MiterJoin: pen.setJoinStyle(Qt::MiterJoin); break;
+ case QCss::Value_BevelJoin: pen.setJoinStyle(Qt::BevelJoin); break;
+ case QCss::Value_RoundJoin: pen.setJoinStyle(Qt::RoundJoin); break;
+ case QCss::Value_SvgMiterJoin: pen.setJoinStyle(Qt::SvgMiterJoin); break;
+ default: break;
+ }
+ charFormat.setTextOutline(pen);
+ break;
+ }
+ case QCss::QtStrokeMiterLimit:
+ {
+ qreal miterLimit;
+ if (decl.realValue(&miterLimit)) {
+ QPen pen = charFormat.textOutline();
+ pen.setMiterLimit(miterLimit);
+ charFormat.setTextOutline(pen);
+ }
+ break;
+ }
+ case QCss::QtStrokeDashArray:
+ {
+ QList<qreal> dashes = decl.dashArray();
+ if (!dashes.empty()) {
+ QPen pen = charFormat.textOutline();
+ pen.setDashPattern(dashes);
+ charFormat.setTextOutline(pen);
+ }
+ break;
+ }
+ case QCss::QtStrokeDashOffset:
+ {
+ qreal dashOffset;
+ if (decl.realValue(&dashOffset)) {
+ QPen pen = charFormat.textOutline();
+ pen.setDashOffset(dashOffset);
+ charFormat.setTextOutline(pen);
+ }
+ break;
+ }
case QCss::QtForeground:
{
QBrush brush = decl.brushValue();
charFormat.setForeground(brush);
break;
}
+ case QCss::MaximumWidth:
+ if (id == Html_img) {
+ auto imageFormat = charFormat.toImageFormat();
+ imageFormat.setMaximumWidth(extractor.textLength(decl));
+ charFormat = imageFormat;
+ }
+ break;
default: break;
}
}
diff --git a/src/gui/text/qtextimagehandler.cpp b/src/gui/text/qtextimagehandler.cpp
index 5c56c30711..920e6c689c 100644
--- a/src/gui/text/qtextimagehandler.cpp
+++ b/src/gui/text/qtextimagehandler.cpp
@@ -12,6 +12,7 @@
#include <private/qtextengine_p.h>
#include <qpalette.h>
#include <qthread.h>
+#include <limits>
QT_BEGIN_NAMESPACE
@@ -72,21 +73,40 @@ template<typename T>
static QSize getSize(QTextDocument *doc, const QTextImageFormat &format)
{
const bool hasWidth = format.hasProperty(QTextFormat::ImageWidth);
- const int width = qRound(format.width());
+ int width = qRound(format.width());
const bool hasHeight = format.hasProperty(QTextFormat::ImageHeight);
const int height = qRound(format.height());
+ const bool hasMaxWidth = format.hasProperty(QTextFormat::ImageMaxWidth);
+ const auto maxWidth = format.maximumWidth();
+
+ int effectiveMaxWidth = std::numeric_limits<int>::max();
+ if (hasMaxWidth) {
+ if (maxWidth.type() == QTextLength::PercentageLength)
+ effectiveMaxWidth = (doc->pageSize().width() - 2 * doc->documentMargin()) * maxWidth.value(100) / 100;
+ else
+ effectiveMaxWidth = maxWidth.rawValue();
+
+ width = qMin(effectiveMaxWidth, width);
+ }
+
T source;
QSize size(width, height);
if (!hasWidth || !hasHeight) {
source = getAs<T>(doc, format);
- const QSizeF sourceSize = source.deviceIndependentSize();
+ QSizeF sourceSize = source.deviceIndependentSize();
+
+ if (sourceSize.width() > effectiveMaxWidth) {
+ // image is bigger than effectiveMaxWidth, scale it down
+ sourceSize.setHeight(effectiveMaxWidth * (sourceSize.height() / qreal(sourceSize.width())));
+ sourceSize.setWidth(effectiveMaxWidth);
+ }
if (!hasWidth) {
if (!hasHeight)
size.setWidth(sourceSize.width());
else
- size.setWidth(qRound(height * (sourceSize.width() / qreal(sourceSize.height()))));
+ size.setWidth(qMin(effectiveMaxWidth, qRound(height * (sourceSize.width() / qreal(sourceSize.height())))));
}
if (!hasHeight) {
if (!hasWidth)
diff --git a/src/gui/text/unix/qfontconfigdatabase.cpp b/src/gui/text/unix/qfontconfigdatabase.cpp
index 975a583220..d607d38235 100644
--- a/src/gui/text/unix/qfontconfigdatabase.cpp
+++ b/src/gui/text/unix/qfontconfigdatabase.cpp
@@ -642,7 +642,7 @@ QFontEngineMulti *QFontconfigDatabase::fontEngineMulti(QFontEngine *fontEngine,
}
namespace {
-QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match, bool useXftConf)
+QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintingPreference, FcPattern *match, bool preferXftConf)
{
switch (hintingPreference) {
case QFont::PreferNoHinting:
@@ -658,6 +658,13 @@ QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintin
if (isDprScaling())
return QFontEngine::HintNone;
+ void *hintStyleResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle",
+ QGuiApplication::primaryScreen());
+ int xftHintStyle = int(reinterpret_cast<qintptr>(hintStyleResource));
+ if (preferXftConf && xftHintStyle > 0)
+ return QFontEngine::HintStyle(xftHintStyle - 1);
+
int hint_style = 0;
if (FcPatternGetInteger (match, FC_HINT_STYLE, 0, &hint_style) == FcResultMatch) {
switch (hint_style) {
@@ -674,21 +681,21 @@ QFontEngine::HintStyle defaultHintStyleFromMatch(QFont::HintingPreference hintin
break;
}
}
-
- if (useXftConf) {
- void *hintStyleResource =
- QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle",
- QGuiApplication::primaryScreen());
- int hintStyle = int(reinterpret_cast<qintptr>(hintStyleResource));
- if (hintStyle > 0)
- return QFontEngine::HintStyle(hintStyle - 1);
- }
+ if (xftHintStyle > 0)
+ return QFontEngine::HintStyle(xftHintStyle - 1);
return QFontEngine::HintFull;
}
-QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bool useXftConf)
+QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bool preferXftConf)
{
+ void *subpixelTypeResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype",
+ QGuiApplication::primaryScreen());
+ int xftSubpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource));
+ if (preferXftConf && xftSubpixelType > 0)
+ return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
+
int subpixel = FC_RGBA_UNKNOWN;
if (FcPatternGetInteger(match, FC_RGBA, 0, &subpixel) == FcResultMatch) {
switch (subpixel) {
@@ -709,14 +716,8 @@ QFontEngine::SubpixelAntialiasingType subpixelTypeFromMatch(FcPattern *match, bo
}
}
- if (useXftConf) {
- void *subpixelTypeResource =
- QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype",
- QGuiApplication::primaryScreen());
- int subpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource));
- if (subpixelType > 0)
- return QFontEngine::SubpixelAntialiasingType(subpixelType - 1);
- }
+ if (xftSubpixelType > 0)
+ return QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
return QFontEngine::Subpixel_None;
}
@@ -965,20 +966,11 @@ void QFontconfigDatabase::setupFontEngine(QFontEngineFT *engine, const QFontDef
bool forcedAntialiasSetting = !antialias || isDprScaling();
const QPlatformServices *services = QGuiApplicationPrivate::platformIntegration()->services();
- bool useXftConf = false;
+ bool preferXftConf = false;
if (services) {
const QList<QByteArray> desktopEnv = services->desktopEnvironment().split(':');
- useXftConf = desktopEnv.contains("GNOME") || desktopEnv.contains("UNITY") || desktopEnv.contains("XFCE");
- }
-
- if (useXftConf && !forcedAntialiasSetting) {
- void *antialiasResource =
- QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled",
- QGuiApplication::primaryScreen());
- int antialiasingEnabled = int(reinterpret_cast<qintptr>(antialiasResource));
- if (antialiasingEnabled > 0)
- antialias = antialiasingEnabled - 1;
+ preferXftConf = !(desktopEnv.contains("KDE") || desktopEnv.contains("LXQT") || desktopEnv.contains("UKUI"));
}
QFontEngine::GlyphFormat format;
@@ -1060,8 +1052,19 @@ bail:
if (!match)
match = FcFontMatch(nullptr, pattern, &result);
+ int xftAntialias = 0;
+ if (!forcedAntialiasSetting) {
+ void *antialiasResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("antialiasingEnabled",
+ QGuiApplication::primaryScreen());
+ xftAntialias = int(reinterpret_cast<qintptr>(antialiasResource));
+ if ((preferXftConf || !match) && xftAntialias > 0) {
+ antialias = xftAntialias - 1;
+ forcedAntialiasSetting = true;
+ }
+ }
if (match) {
- engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, useXftConf));
+ engine->setDefaultHintStyle(defaultHintStyleFromMatch((QFont::HintingPreference)fontDef.hintingPreference, match, preferXftConf));
FcBool fc_autohint;
if (FcPatternGetBool(match, FC_AUTOHINT,0, &fc_autohint) == FcResultMatch)
@@ -1082,18 +1085,37 @@ bail:
if (antialias) {
QFontEngine::SubpixelAntialiasingType subpixelType = QFontEngine::Subpixel_None;
if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias))
- subpixelType = subpixelTypeFromMatch(match, useXftConf);
+ subpixelType = subpixelTypeFromMatch(match, preferXftConf);
engine->subpixelType = subpixelType;
-
- format = (subpixelType == QFontEngine::Subpixel_None)
- ? QFontEngine::Format_A8
- : QFontEngine::Format_A32;
- } else
- format = QFontEngine::Format_Mono;
+ }
FcPatternDestroy(match);
- } else
- format = antialias ? QFontEngine::Format_A8 : QFontEngine::Format_Mono;
+ } else {
+ void *hintStyleResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("hintstyle",
+ QGuiApplication::primaryScreen());
+ int xftHintStyle = int(reinterpret_cast<qintptr>(hintStyleResource));
+ if (xftHintStyle > 0)
+ engine->setDefaultHintStyle(QFontEngine::HintStyle(xftHintStyle - 1));
+ if (antialias) {
+ engine->subpixelType = QFontEngine::Subpixel_None;
+ if (!(fontDef.styleStrategy & QFont::NoSubpixelAntialias)) {
+ void *subpixelTypeResource =
+ QGuiApplication::platformNativeInterface()->nativeResourceForScreen("subpixeltype",
+ QGuiApplication::primaryScreen());
+ int xftSubpixelType = int(reinterpret_cast<qintptr>(subpixelTypeResource));
+ if (xftSubpixelType > 1)
+ engine->subpixelType = QFontEngine::SubpixelAntialiasingType(xftSubpixelType - 1);
+ }
+ }
+ }
+ if (antialias) {
+ format = (engine->subpixelType == QFontEngine::Subpixel_None)
+ ? QFontEngine::Format_A8
+ : QFontEngine::Format_A32;
+ } else {
+ format = QFontEngine::Format_Mono;
+ }
FcPatternDestroy(pattern);
diff --git a/src/gui/text/windows/qwindowsfontengine.cpp b/src/gui/text/windows/qwindowsfontengine.cpp
index fe07897369..5de80dc8a3 100644
--- a/src/gui/text/windows/qwindowsfontengine.cpp
+++ b/src/gui/text/windows/qwindowsfontengine.cpp
@@ -132,8 +132,9 @@ void QWindowsFontEngine::getCMap()
}
}
-int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs) const
+int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLayout *glyphs, int *mappedGlyphs) const
{
+ *mappedGlyphs = 0;
int glyph_pos = 0;
{
if (symbol) {
@@ -143,6 +144,8 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
if (!glyphs->glyphs[glyph_pos] && uc < 0x100)
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc + 0xf000);
+ if (glyphs->glyphs[glyph_pos] || isIgnorableChar(uc))
+ (*mappedGlyphs)++;
++glyph_pos;
}
} else if (ttf) {
@@ -150,6 +153,8 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa
while (it.hasNext()) {
const uint uc = it.next();
glyphs->glyphs[glyph_pos] = getTrueTypeGlyphIndex(cmap, cmapSize, uc);
+ if (glyphs->glyphs[glyph_pos] || isIgnorableChar(uc))
+ (*mappedGlyphs)++;
++glyph_pos;
}
} else {
@@ -160,6 +165,8 @@ int QWindowsFontEngine::getGlyphIndexes(const QChar *str, int numChars, QGlyphLa
glyphs->glyphs[glyph_pos] = uc;
else
glyphs->glyphs[glyph_pos] = 0;
+ if (glyphs->glyphs[glyph_pos] || isIgnorableChar(uc))
+ (*mappedGlyphs)++;
++glyph_pos;
}
}
@@ -259,7 +266,7 @@ HGDIOBJ QWindowsFontEngine::selectDesignFont() const
return SelectObject(m_fontEngineData->hdc, designFont);
}
-bool QWindowsFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
+int QWindowsFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
if (*nglyphs < len) {
@@ -268,12 +275,13 @@ bool QWindowsFontEngine::stringToCMap(const QChar *str, int len, QGlyphLayout *g
}
glyphs->numGlyphs = *nglyphs;
- *nglyphs = getGlyphIndexes(str, len, glyphs);
+ int mappedGlyphs;
+ *nglyphs = getGlyphIndexes(str, len, glyphs, &mappedGlyphs);
if (!(flags & GlyphIndicesOnly))
recalcAdvances(glyphs, flags);
- return true;
+ return mappedGlyphs;
}
inline void calculateTTFGlyphWidth(HDC hdc, UINT glyph, int &width)
diff --git a/src/gui/text/windows/qwindowsfontengine_p.h b/src/gui/text/windows/qwindowsfontengine_p.h
index afe8ee4ca5..07f4db3c4a 100644
--- a/src/gui/text/windows/qwindowsfontengine_p.h
+++ b/src/gui/text/windows/qwindowsfontengine_p.h
@@ -48,7 +48,7 @@ public:
QFixed emSquareSize() const override;
glyph_t glyphIndex(uint ucs4) const override;
- bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
+ int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs, ShaperFlags flags) const override;
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const override;
void addOutlineToPath(qreal x, qreal y, const QGlyphLayout &glyphs, QPainterPath *path, QTextItem::RenderFlags flags) override;
@@ -88,7 +88,7 @@ public:
bool hasUnreliableGlyphOutline() const override;
- int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs) const;
+ int getGlyphIndexes(const QChar *ch, int numChars, QGlyphLayout *glyphs, int *mappedGlyphs) const;
void getCMap();
bool getOutlineMetrics(glyph_t glyph, const QTransform &t, glyph_metrics_t *metrics) const;
diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
index 2070deb296..47b8a7ee3c 100644
--- a/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
+++ b/src/gui/text/windows/qwindowsfontenginedirectwrite.cpp
@@ -435,13 +435,13 @@ glyph_t QWindowsFontEngineDirectWrite::glyphIndex(uint ucs4) const
return glyphIndex;
}
-bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
- int *nglyphs, QFontEngine::ShaperFlags flags) const
+int QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs,
+ int *nglyphs, QFontEngine::ShaperFlags flags) const
{
Q_ASSERT(glyphs->numGlyphs >= *nglyphs);
if (*nglyphs < len) {
*nglyphs = len;
- return false;
+ return -1;
}
QVarLengthArray<UINT32> codePoints(len);
@@ -455,11 +455,15 @@ bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGly
glyphIndices.data());
if (FAILED(hr)) {
qErrnoWarning("%s: GetGlyphIndicesW failed", __FUNCTION__);
- return false;
+ return -1;
}
- for (int i = 0; i < actualLength; ++i)
+ int mappedGlyphs = 0;
+ for (int i = 0; i < actualLength; ++i) {
glyphs->glyphs[i] = glyphIndices.at(i);
+ if (glyphs->glyphs[i] != 0 || isIgnorableChar(codePoints.at(i)))
+ mappedGlyphs++;
+ }
*nglyphs = actualLength;
glyphs->numGlyphs = actualLength;
@@ -467,7 +471,7 @@ bool QWindowsFontEngineDirectWrite::stringToCMap(const QChar *str, int len, QGly
if (!(flags & GlyphIndicesOnly))
recalcAdvances(glyphs, {});
- return true;
+ return mappedGlyphs;
}
QFontEngine::FaceId QWindowsFontEngineDirectWrite::faceId() const
diff --git a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
index 44e466789c..d7c9a79267 100644
--- a/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
+++ b/src/gui/text/windows/qwindowsfontenginedirectwrite_p.h
@@ -53,8 +53,8 @@ public:
QFixed emSquareSize() const override;
glyph_t glyphIndex(uint ucs4) const override;
- bool stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
- ShaperFlags flags) const override;
+ int stringToCMap(const QChar *str, int len, QGlyphLayout *glyphs, int *nglyphs,
+ ShaperFlags flags) const override;
void recalcAdvances(QGlyphLayout *glyphs, ShaperFlags) const override;
void addGlyphsToPath(glyph_t *glyphs, QFixedPoint *positions, int nglyphs,
diff --git a/src/gui/util/qdesktopservices.cpp b/src/gui/util/qdesktopservices.cpp
index 4a12f6db6f..4d98faf398 100644
--- a/src/gui/util/qdesktopservices.cpp
+++ b/src/gui/util/qdesktopservices.cpp
@@ -18,8 +18,6 @@
#include <qpa/qplatformintegration.h>
#include <qdir.h>
-#include <QtCore/private/qlocking_p.h>
-
QT_BEGIN_NAMESPACE
class QOpenUrlHandlerRegistry
@@ -36,36 +34,10 @@ public:
};
typedef QHash<QString, Handler> HandlerHash;
HandlerHash handlers;
-
-#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
- QObject context;
-
- void handlerDestroyed(QObject *handler);
-#endif
-
};
Q_GLOBAL_STATIC(QOpenUrlHandlerRegistry, handlerRegistry)
-#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
-void QOpenUrlHandlerRegistry::handlerDestroyed(QObject *handler)
-{
- const auto lock = qt_scoped_lock(mutex);
- HandlerHash::Iterator it = handlers.begin();
- while (it != handlers.end()) {
- if (it->receiver == handler) {
- it = handlers.erase(it);
- qWarning("Please call QDesktopServices::unsetUrlHandler() before destroying a "
- "registered URL handler object.\n"
- "Support for destroying a registered URL handler object is deprecated, "
- "and will be removed in Qt 6.6.");
- } else {
- ++it;
- }
- }
-}
-#endif
-
/*!
\class QDesktopServices
\brief The QDesktopServices class provides methods for accessing common desktop services.
@@ -238,10 +210,11 @@ bool QDesktopServices::openUrl(const QUrl &url)
the destruction of the handler object does not overlap with concurrent
invocations of openUrl() using it.
- \section1 iOS
+ \section1 iOS and \macos
- To use this function for receiving data from other apps on iOS you also need to
- add the custom scheme to the \c CFBundleURLSchemes list in your Info.plist file:
+ To use this function for receiving data from other apps on iOS/\macos
+ you also need to add the custom scheme to the \c CFBundleURLSchemes
+ list in your Info.plist file:
\snippet code/src_gui_util_qdesktopservices.cpp 4
@@ -256,7 +229,7 @@ bool QDesktopServices::openUrl(const QUrl &url)
\snippet code/src_gui_util_qdesktopservices.cpp 7
- iOS will search for /.well-known/apple-app-site-association on your domain,
+ iOS/\macos will search for /.well-known/apple-app-site-association on your domain,
when the application is installed. If you want to listen to
\c{https://your.domain.com/help?topic=ABCDEF} you need to provide the following
content there:
@@ -306,11 +279,6 @@ void QDesktopServices::setUrlHandler(const QString &scheme, QObject *receiver, c
h.receiver = receiver;
h.name = method;
registry->handlers.insert(scheme.toLower(), h);
-#if QT_VERSION < QT_VERSION_CHECK(6, 6, 0)
- QObject::connect(receiver, &QObject::destroyed, &registry->context,
- [registry](QObject *obj) { registry->handlerDestroyed(obj); },
- Qt::DirectConnection);
-#endif
}
/*!
diff --git a/src/gui/util/qgridlayoutengine.cpp b/src/gui/util/qgridlayoutengine.cpp
index e8648eb91d..07981e8388 100644
--- a/src/gui/util/qgridlayoutengine.cpp
+++ b/src/gui/util/qgridlayoutengine.cpp
@@ -720,7 +720,7 @@ void QGridLayoutItem::dump(int indent) const
if (q_alignment != 0)
qDebug("%*s Alignment: %x", indent, "", uint(q_alignment));
qDebug("%*s Horizontal size policy: %x Vertical size policy: %x",
- indent, "", sizePolicy(Qt::Horizontal), sizePolicy(Qt::Vertical));
+ indent, "", (unsigned int)sizePolicy(Qt::Horizontal), (unsigned int)sizePolicy(Qt::Vertical));
}
#endif
@@ -1182,7 +1182,7 @@ void QGridLayoutEngine::dump(int indent) const
{
qDebug("%*sEngine", indent, "");
- qDebug("%*s Items (%d)", indent, "", q_items.count());
+ qDebug("%*s Items (%lld)", indent, "", q_items.count());
int i;
for (i = 0; i < q_items.count(); ++i)
q_items.at(i)->dump(indent + 2);