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/configure.cmake2
-rw-r--r--src/gui/image/qbitmap.cpp1
-rw-r--r--src/gui/image/qicon.cpp145
-rw-r--r--src/gui/image/qicon_p.h39
-rw-r--r--src/gui/image/qiconengine.cpp7
-rw-r--r--src/gui/image/qiconengine.h1
-rw-r--r--src/gui/image/qiconloader.cpp15
-rw-r--r--src/gui/image/qimage.cpp17
-rw-r--r--src/gui/image/qimagereader.cpp18
-rw-r--r--src/gui/image/qimagewriter.cpp4
-rw-r--r--src/gui/image/qmovie.cpp7
-rw-r--r--src/gui/image/qpicture.cpp1
-rw-r--r--src/gui/image/qpixmap.cpp9
-rw-r--r--src/gui/image/qpixmapcache.cpp11
-rw-r--r--src/gui/kernel/qguiapplication.cpp30
-rw-r--r--src/gui/kernel/qguiapplication.h2
-rw-r--r--src/gui/kernel/qguiapplication_p.h2
-rw-r--r--src/gui/kernel/qguiapplication_platform.h31
-rw-r--r--src/gui/kernel/qguivariant.cpp2
-rw-r--r--src/gui/kernel/qhighdpiscaling_p.h4
-rw-r--r--src/gui/kernel/qpalette.cpp5
-rw-r--r--src/gui/kernel/qplatformtheme.cpp5
-rw-r--r--src/gui/kernel/qplatformtheme.h1
-rw-r--r--src/gui/kernel/qstylehints.cpp83
-rw-r--r--src/gui/kernel/qstylehints.h10
-rw-r--r--src/gui/kernel/qstylehints_p.h1
-rw-r--r--src/gui/kernel/qwindow.cpp8
-rw-r--r--src/gui/kernel/qwindow_p.h2
-rw-r--r--src/gui/painting/qbackingstore.cpp29
-rw-r--r--src/gui/painting/qbackingstorerhisupport.cpp4
-rw-r--r--src/gui/painting/qcmyk_p.h6
-rw-r--r--src/gui/painting/qcolorspace.cpp8
-rw-r--r--src/gui/painting/qcolortransform.cpp136
-rw-r--r--src/gui/painting/qcolortransform_p.h6
-rw-r--r--src/gui/painting/qicc.cpp6
-rw-r--r--src/gui/painting/qimagescale.cpp2
-rw-r--r--src/gui/painting/qpdf.cpp54
-rw-r--r--src/gui/painting/qpdf_p.h4
-rw-r--r--src/gui/painting/qregion.cpp64
-rw-r--r--src/gui/painting/qregion.h4
-rw-r--r--src/gui/platform/ios/qiosnativeinterface.cpp26
-rw-r--r--src/gui/platform/unix/qgenericunixthemes.cpp266
-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.mm25
-rw-r--r--src/gui/rhi/qrhivulkan.cpp24
-rw-r--r--src/gui/rhi/qrhivulkan_p.h4
-rw-r--r--src/gui/text/qcssparser.cpp62
-rw-r--r--src/gui/text/qcssparser_p.h17
-rw-r--r--src/gui/text/qfont.cpp4
-rw-r--r--src/gui/text/qfontdatabase.cpp31
-rw-r--r--src/gui/text/qtextdocument.cpp65
-rw-r--r--src/gui/text/qtextdocument.h6
-rw-r--r--src/gui/text/qtextengine.cpp6
-rw-r--r--src/gui/text/qtextformat.cpp21
-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/util/qdesktopservices.cpp42
68 files changed, 1238 insertions, 497 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/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/qbitmap.cpp b/src/gui/image/qbitmap.cpp
index 2208cca1be..315c847c91 100644
--- a/src/gui/image/qbitmap.cpp
+++ b/src/gui/image/qbitmap.cpp
@@ -129,7 +129,6 @@ QBitmap::QBitmap(const QString& fileName, const char *format)
/*!
\fn void QBitmap::swap(QBitmap &other)
- \since 4.8
Swaps bitmap \a other with this bitmap. This operation is very
fast and never fails.
diff --git a/src/gui/image/qicon.cpp b/src/gui/image/qicon.cpp
index 086ac37a07..62904f957d 100644
--- a/src/gui/image/qicon.cpp
+++ b/src/gui/image/qicon.cpp
@@ -32,6 +32,33 @@
QT_BEGIN_NAMESPACE
using namespace Qt::StringLiterals;
+// Convenience class providing a bool read() function.
+namespace {
+class ImageReader
+{
+public:
+ ImageReader(const QString &fileName) : m_reader(fileName), m_atEnd(false) { }
+
+ QByteArray format() const { return m_reader.format(); }
+
+ bool read(QImage *image)
+ {
+ if (m_atEnd)
+ return false;
+ *image = m_reader.read();
+ if (!image->size().isValid()) {
+ m_atEnd = true;
+ return false;
+ }
+ m_atEnd = !m_reader.jumpToNextImage();
+ return true;
+ }
+
+private:
+ QImageReader m_reader;
+ bool m_atEnd;
+};
+} // namespace
/*!
\enum QIcon::Mode
@@ -150,7 +177,7 @@ void QPixmapIconEngine::paint(QPainter *painter, const QRect &rect, QIcon::Mode
painter->drawPixmap(rect, px);
}
-static inline int area(const QSize &s) { return s.width() * s.height(); }
+static inline qint64 area(const QSize &s) { return qint64(s.width()) * s.height(); }
// Returns the smallest of the two that is still larger than or equal to size.
// Pixmaps at the correct scale are preferred, pixmaps at lower scale are
@@ -160,15 +187,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))
@@ -177,18 +205,18 @@ static QPixmapIconEngineEntry *bestSizeScaleMatch(const QSize &size, qreal scale
return (qAbs(ascore) < qAbs(bscore)) ? pa : pb;
}
- int s = area(size);
+ qint64 s = area(size);
if (pa->size == QSize() && pa->pixmap.isNull()) {
pa->pixmap = QPixmap(pa->fileName);
pa->size = pa->pixmap.size();
}
- int a = area(pa->size);
+ qint64 a = area(pa->size);
if (pb->size == QSize() && pb->pixmap.isNull()) {
pb->pixmap = QPixmap(pb->fileName);
pb->size = pb->pixmap.size();
}
- int b = area(pb->size);
- int res = a;
+ qint64 b = area(pb->size);
+ qint64 res = a;
if (qMin(a,b) >= s)
res = qMin(a,b);
else
@@ -201,13 +229,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;
}
@@ -271,41 +300,30 @@ QPixmap QPixmapIconEngine::pixmap(const QSize &size, QIcon::Mode mode, QIcon::St
QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIcon::State state, qreal scale)
{
-
QPixmap pm;
QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state, false);
if (pe)
pm = pe->pixmap;
if (pm.isNull()) {
- int idx = pixmaps.size();
- while (--idx >= 0) {
- if (pe == &pixmaps.at(idx)) {
- pixmaps.remove(idx);
- break;
- }
- }
+ removePixmapEntry(pe);
if (pixmaps.isEmpty())
return pm;
- else
- return pixmap(size, mode, state);
+ return scaledPixmap(size, mode, state, scale);
}
- QSize actualSize = pm.size();
- if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
- actualSize.scale(size, Qt::KeepAspectRatio);
-
+ const auto actualSize = adjustSize(size, pm.size());
QString key = "qt_"_L1
% HexString<quint64>(pm.cacheKey())
- % HexString<uint>(pe ? pe->mode : QIcon::Normal)
+ % HexString<quint8>(pe ? pe->mode : QIcon::Normal)
% HexString<quint64>(QGuiApplication::palette().cacheKey())
% HexString<uint>(actualSize.width())
% HexString<uint>(actualSize.height());
if (mode == QIcon::Active) {
- if (QPixmapCache::find(key % HexString<uint>(mode), &pm))
+ if (QPixmapCache::find(key % HexString<quint8>(mode), &pm))
return pm; // horray
- if (QPixmapCache::find(key % HexString<uint>(QIcon::Normal), &pm)) {
+ if (QPixmapCache::find(key % HexString<quint8>(QIcon::Normal), &pm)) {
QPixmap active = pm;
if (QGuiApplication *guiApp = qobject_cast<QGuiApplication *>(qApp))
active = static_cast<QGuiApplicationPrivate*>(QObjectPrivate::get(guiApp))->applyQIconStyleHelper(QIcon::Active, pm);
@@ -314,7 +332,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc
}
}
- if (!QPixmapCache::find(key % HexString<uint>(mode), &pm)) {
+ if (!QPixmapCache::find(key % HexString<quint8>(mode), &pm)) {
if (pm.size() != actualSize)
pm = pm.scaled(actualSize, Qt::IgnoreAspectRatio, Qt::SmoothTransformation);
if (pe->mode != mode && mode != QIcon::Normal) {
@@ -324,7 +342,7 @@ QPixmap QPixmapIconEngine::scaledPixmap(const QSize &size, QIcon::Mode mode, QIc
if (!generated.isNull())
pm = generated;
}
- QPixmapCache::insert(key % HexString<uint>(mode), pm);
+ QPixmapCache::insert(key % HexString<quint8>(mode), pm);
}
return pm;
}
@@ -341,12 +359,7 @@ QSize QPixmapIconEngine::actualSize(const QSize &size, QIcon::Mode mode, QIcon::
if (QPixmapIconEngineEntry *pe = bestMatch(size, scale, mode, state, true))
actualSize = pe->size;
- if (actualSize.isNull())
- return actualSize;
-
- if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
- actualSize.scale(size, Qt::KeepAspectRatio);
- return actualSize;
+ return adjustSize(size, actualSize);
}
QList<QSize> QPixmapIconEngine::availableSizes(QIcon::Mode mode, QIcon::State state)
@@ -369,7 +382,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,41 +400,13 @@ 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;
}
return -1;
}
-// Convenience class providing a bool read() function.
-namespace {
-class ImageReader
-{
-public:
- ImageReader(const QString &fileName) : m_reader(fileName), m_atEnd(false) {}
-
- QByteArray format() const { return m_reader.format(); }
-
- bool read(QImage *image)
- {
- if (m_atEnd)
- return false;
- *image = m_reader.read();
- if (!image->size().isValid()) {
- m_atEnd = true;
- return false;
- }
- m_atEnd = !m_reader.jumpToNextImage();
- return true;
- }
-
-private:
- QImageReader m_reader;
- bool m_atEnd;
-};
-} // namespace
-
void QPixmapIconEngine::addFile(const QString &fileName, const QSize &size, QIcon::Mode mode, QIcon::State state)
{
if (fileName.isEmpty())
@@ -787,7 +772,6 @@ QIcon &QIcon::operator=(const QIcon &other)
/*!
\fn void QIcon::swap(QIcon &other)
- \since 4.8
Swaps icon \a other with this icon. This operation is very
fast and never fails.
@@ -805,7 +789,6 @@ QIcon::operator QVariant() const
Returns a number that identifies the contents of this QIcon
object. Distinct QIcon objects can have the same key if
they refer to the same contents.
- \since 4.3
The cacheKey() will change when the icon is altered via
addPixmap() or addFile().
@@ -862,7 +845,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()
*/
@@ -1134,8 +1119,6 @@ void QIcon::addFile(const QString &fileName, const QSize &size, Mode mode, State
}
/*!
- \since 4.5
-
Returns a list of available icon sizes for the specified \a mode and
\a state.
*/
@@ -1147,8 +1130,6 @@ QList<QSize> QIcon::availableSizes(Mode mode, State state) const
}
/*!
- \since 4.7
-
Returns the name used to create the icon, if available.
Depending on the way the icon was created, it may have an associated
@@ -1164,8 +1145,6 @@ QString QIcon::name() const
}
/*!
- \since 4.6
-
Sets the search paths for icon themes to \a paths.
The content of \a paths should follow the theme format
@@ -1179,8 +1158,6 @@ void QIcon::setThemeSearchPaths(const QStringList &paths)
}
/*!
- \since 4.6
-
Returns the search paths for icon themes.
The default search paths will be defined by the platform.
@@ -1235,8 +1212,6 @@ void QIcon::setFallbackSearchPaths(const QStringList &paths)
}
/*!
- \since 4.6
-
Sets the current icon theme to \a name.
The theme will be will be looked up in themeSearchPaths().
@@ -1255,8 +1230,6 @@ void QIcon::setThemeName(const QString &name)
}
/*!
- \since 4.6
-
Returns the name of the current icon theme.
If not set, the current icon theme will be defined by the
@@ -1317,8 +1290,6 @@ void QIcon::setFallbackThemeName(const QString &name)
}
/*!
- \since 4.6
-
Returns the QIcon corresponding to \a name in the
\l{themeName()}{current icon theme}.
@@ -1388,8 +1359,6 @@ QIcon QIcon::fromTheme(const QString &name, const QIcon &fallback)
}
/*!
- \since 4.6
-
Returns \c true if there is an icon available for \a name in the
current icon theme or any of the fallbacks, as described by
fromTheme(), otherwise returns \c false.
@@ -1836,7 +1805,6 @@ bool QIcon::isMask() const
/*!
\fn QDataStream &operator<<(QDataStream &stream, const QIcon &icon)
\relates QIcon
- \since 4.2
Writes the given \a icon to the given \a stream as a PNG
image. If the icon contains more than one image, all images will
@@ -1877,7 +1845,6 @@ QDataStream &operator<<(QDataStream &s, const QIcon &icon)
/*!
\fn QDataStream &operator>>(QDataStream &stream, QIcon &icon)
\relates QIcon
- \since 4.2
Reads an image, or a set of images, from the given \a stream into
the given \a icon.
diff --git a/src/gui/image/qicon_p.h b/src/gui/image/qicon_p.h
index c5bf120620..8050d76435 100644
--- a/src/gui/image/qicon_p.h
+++ b/src/gui/image/qicon_p.h
@@ -34,7 +34,7 @@ public:
delete engine;
}
- qreal pixmapDevicePixelRatio(qreal displayDevicePixelRatio, const QSize &requestedSize, const QSize &actualSize);
+ static qreal pixmapDevicePixelRatio(qreal displayDevicePixelRatio, const QSize &requestedSize, const QSize &actualSize);
QIconEngine *engine;
@@ -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);
}
@@ -91,7 +89,24 @@ public:
bool read(QDataStream &in) override;
bool write(QDataStream &out) const override;
+ static inline QSize adjustSize(const QSize &expectedSize, QSize size)
+ {
+ if (!size.isNull() && (size.width() > expectedSize.width() || size.height() > expectedSize.height()))
+ size.scale(expectedSize, Qt::KeepAspectRatio);
+ return size;
+ }
+
private:
+ void removePixmapEntry(QPixmapIconEngineEntry *pe)
+ {
+ auto idx = pixmaps.size();
+ while (--idx >= 0) {
+ if (pe == &pixmaps.at(idx)) {
+ pixmaps.remove(idx);
+ return;
+ }
+ }
+ }
QPixmapIconEngineEntry *tryMatch(const QSize &size, qreal scale, QIcon::Mode mode, QIcon::State state);
QList<QPixmapIconEngineEntry> pixmaps;
diff --git a/src/gui/image/qiconengine.cpp b/src/gui/image/qiconengine.cpp
index 78273bdeb3..efcc3824ba 100644
--- a/src/gui/image/qiconengine.cpp
+++ b/src/gui/image/qiconengine.cpp
@@ -114,7 +114,6 @@ void QIconEngine::addFile(const QString &/*fileName*/, const QSize &/*size*/, QI
/*!
\enum QIconEngine::IconEngineHook
- \since 4.5
These enum values are used for virtual_hook() to allow additional
queries to icon engine without breaking binary compatibility.
@@ -224,8 +223,6 @@ bool QIconEngine::write(QDataStream &) const
}
/*!
- \since 4.5
-
Additional method to allow extending QIconEngine without
adding new virtual methods (and without breaking binary compatibility).
The actual action and format of \a data depends on \a id argument
@@ -249,8 +246,6 @@ void QIconEngine::virtual_hook(int id, void *data)
}
/*!
- \since 4.5
-
Returns sizes of all images that are contained in the engine for the
specific \a mode and \a state.
*/
@@ -260,8 +255,6 @@ QList<QSize> QIconEngine::availableSizes(QIcon::Mode /*mode*/, QIcon::State /*st
}
/*!
- \since 4.7
-
Returns the name used to create the engine, if available.
*/
QString QIconEngine::iconName()
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/qiconloader.cpp b/src/gui/image/qiconloader.cpp
index 982b9a26b4..bacb30a103 100644
--- a/src/gui/image/qiconloader.cpp
+++ b/src/gui/image/qiconloader.cpp
@@ -894,18 +894,15 @@ QPixmap PixmapEntry::pixmap(const QSize &size, QIcon::Mode mode, QIcon::State st
if (basePixmap.isNull())
basePixmap.load(filename);
- QSize actualSize = basePixmap.size();
// If the size of the best match we have (basePixmap) is larger than the
// requested size, we downscale it to match.
- if (!actualSize.isNull() && (actualSize.width() > size.width() || actualSize.height() > size.height()))
- actualSize.scale(size, Qt::KeepAspectRatio);
-
+ const auto actualSize = QPixmapIconEngine::adjustSize(size, basePixmap.size());
QString key = "$qt_theme_"_L1
- % HexString<qint64>(basePixmap.cacheKey())
- % HexString<int>(mode)
- % HexString<qint64>(QGuiApplication::palette().cacheKey())
- % HexString<int>(actualSize.width())
- % HexString<int>(actualSize.height());
+ % HexString<quint64>(basePixmap.cacheKey())
+ % HexString<quint8>(mode)
+ % HexString<quint64>(QGuiApplication::palette().cacheKey())
+ % HexString<uint>(actualSize.width())
+ % HexString<uint>(actualSize.height());
QPixmap cachedPixmap;
if (QPixmapCache::find(key, &cachedPixmap)) {
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 3bbf21320e..8998db301d 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -1093,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.
@@ -1412,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.
@@ -1676,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
{
@@ -1732,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
{
@@ -1839,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.
@@ -1865,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)
@@ -2123,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
@@ -4607,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
@@ -4702,6 +4693,8 @@ QImage QImage::smoothScaled(int w, int h) const
src.convertTo(QImage::Format_RGBA32FPx4_Premultiplied);
break;
#endif
+ case QImage::Format_CMYK8888:
+ break;
default:
if (src.hasAlphaChannel())
src.convertTo(QImage::Format_ARGB32_Premultiplied);
@@ -4844,6 +4837,9 @@ QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(const QTransform &matrix, Q
// with scaling smoothly more than 2x down.
if (hd * 2 < hs || wd * 2 < ws)
nonpaintable_scale_xform = true;
+ // We cannot paint on a CMYK image, so don't try to do so
+ if (format() == QImage::Format_CMYK8888)
+ nonpaintable_scale_xform = true;
} else {
if (mat.type() <= QTransform::TxRotate && mat.m11() == 0 && mat.m22() == 0) {
if (mat.m12() == 1. && mat.m21() == -1.)
@@ -4875,6 +4871,7 @@ QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(const QTransform &matrix, Q
case QImage::Format_RGBX64:
case QImage::Format_RGBA64_Premultiplied:
#endif
+ case QImage::Format_CMYK8888:
// Use smoothScaled for scaling when we can do so without conversion.
if (mat.m11() > 0.0F && mat.m22() > 0.0F)
return smoothScaled(wd, hd);
@@ -4945,7 +4942,7 @@ QImage Q_TRACE_INSTRUMENT(qtgui) QImage::transformed(const QTransform &matrix, Q
} else
memset(dImage.bits(), 0x00, dImage.d->nbytes);
- if (target_format >= QImage::Format_RGB32) {
+ if (target_format >= QImage::Format_RGB32 && target_format != QImage::Format_CMYK8888) {
// Prevent QPainter from applying devicePixelRatio corrections
QImage sImage = (devicePixelRatio() != 1) ? QImage(constBits(), width(), height(), format()) : *this;
if (sImage.d != d
diff --git a/src/gui/image/qimagereader.cpp b/src/gui/image/qimagereader.cpp
index 9366e9cbb1..1f85fef3bd 100644
--- a/src/gui/image/qimagereader.cpp
+++ b/src/gui/image/qimagereader.cpp
@@ -800,8 +800,6 @@ QString QImageReader::fileName() const
}
/*!
- \since 4.2
-
Sets the quality setting of the image format to \a quality.
Some image formats, in particular lossy ones, entail a tradeoff between a)
@@ -825,8 +823,6 @@ void QImageReader::setQuality(int quality)
}
/*!
- \since 4.2
-
Returns the quality setting of the image format.
\sa setQuality()
@@ -856,8 +852,6 @@ QSize QImageReader::size() const
}
/*!
- \since 4.5
-
Returns the format of the image, without actually reading the image
contents. The format describes the image format \l QImageReader::read()
returns, not the format of the actual image.
@@ -876,8 +870,6 @@ QImage::Format QImageReader::imageFormat() const
}
/*!
- \since 4.1
-
Returns the text keys for this image. You can use
these keys with text() to list the image text for
a certain key.
@@ -894,8 +886,6 @@ QStringList QImageReader::textKeys() const
}
/*!
- \since 4.1
-
Returns the image text associated with \a key.
Support for this option is implemented through
@@ -985,8 +975,6 @@ QRect QImageReader::scaledClipRect() const
}
/*!
- \since 4.1
-
Sets the background color to \a color.
Image formats that support this operation are expected to
initialize the background to \a color before reading an image.
@@ -1000,8 +988,6 @@ void QImageReader::setBackgroundColor(const QColor &color)
}
/*!
- \since 4.1
-
Returns the background color that's used when reading an image.
If the image format does not support setting the background color
an invalid color is returned.
@@ -1016,8 +1002,6 @@ QColor QImageReader::backgroundColor() const
}
/*!
- \since 4.1
-
Returns \c true if the image format supports animation;
otherwise, false is returned.
@@ -1432,8 +1416,6 @@ QString QImageReader::errorString() const
}
/*!
- \since 4.2
-
Returns \c true if the reader supports \a option; otherwise returns
false.
diff --git a/src/gui/image/qimagewriter.cpp b/src/gui/image/qimagewriter.cpp
index d2176e4189..0fcc783e6d 100644
--- a/src/gui/image/qimagewriter.cpp
+++ b/src/gui/image/qimagewriter.cpp
@@ -588,8 +588,6 @@ QImageIOHandler::Transformations QImageWriter::transformation() const
}
/*!
- \since 4.1
-
Sets the image text associated with the key \a key to
\a text. This is useful for storing copyright information
or other information about the image. Example:
@@ -710,8 +708,6 @@ QString QImageWriter::errorString() const
}
/*!
- \since 4.2
-
Returns \c true if the writer supports \a option; otherwise returns
false.
diff --git a/src/gui/image/qmovie.cpp b/src/gui/image/qmovie.cpp
index 0d13639d35..8fd62c2361 100644
--- a/src/gui/image/qmovie.cpp
+++ b/src/gui/image/qmovie.cpp
@@ -103,7 +103,6 @@
*/
/*! \fn void QMovie::frameChanged(int frameNumber)
- \since 4.1
This signal is emitted when the frame number has changed to
\a frameNumber. You can call currentImage() or currentPixmap() to get a
@@ -973,8 +972,6 @@ void QMovie::stop()
}
/*!
- \since 4.1
-
Returns the scaled size of frames.
\sa QImageReader::scaledSize()
@@ -986,8 +983,6 @@ QSize QMovie::scaledSize()
}
/*!
- \since 4.1
-
Sets the scaled frame size to \a size.
\sa QImageReader::setScaledSize()
@@ -999,8 +994,6 @@ void QMovie::setScaledSize(const QSize &size)
}
/*!
- \since 4.1
-
Returns the list of image formats supported by QMovie.
\sa QImageReader::supportedImageFormats()
diff --git a/src/gui/image/qpicture.cpp b/src/gui/image/qpicture.cpp
index da8c5ef1e5..0bc21a3e9f 100644
--- a/src/gui/image/qpicture.cpp
+++ b/src/gui/image/qpicture.cpp
@@ -925,7 +925,6 @@ QPicture& QPicture::operator=(const QPicture &p)
/*!
\fn void QPicture::swap(QPicture &other)
- \since 4.8
Swaps picture \a other with this picture. This operation is very
fast and never fails.
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/image/qpixmapcache.cpp b/src/gui/image/qpixmapcache.cpp
index 45c9743f93..b0db1f48cb 100644
--- a/src/gui/image/qpixmapcache.cpp
+++ b/src/gui/image/qpixmapcache.cpp
@@ -81,7 +81,6 @@ static inline bool qt_pixmapcache_thread_test()
\brief The QPixmapCache::Key class can be used for efficient access
to the QPixmapCache.
\inmodule QtGui
- \since 4.6
Use QPixmapCache::insert() to receive an instance of Key generated
by the pixmap cache. You can store the key in your own objects for
@@ -421,8 +420,6 @@ QPixmapCacheEntry::~QPixmapCacheEntry()
If the pixmap is found, the function sets \a pixmap to that pixmap and
returns \c true; otherwise it leaves \a pixmap alone and returns \c false.
- \since 4.6
-
Example:
\snippet code/src_gui_image_qpixmapcache.cpp 1
*/
@@ -443,8 +440,6 @@ bool QPixmapCache::find(const QString &key, QPixmap *pixmap)
returns \c true; otherwise it leaves \a pixmap alone and returns \c false. If
the pixmap is not found, it means that the \a key is no longer valid,
so it will be released for the next insertion.
-
- \since 4.6
*/
bool QPixmapCache::find(const Key &key, QPixmap *pixmap)
{
@@ -498,8 +493,6 @@ bool QPixmapCache::insert(const QString &key, const QPixmap &pixmap)
deleted when more space is needed.
\sa setCacheLimit(), replace()
-
- \since 4.6
*/
QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
{
@@ -523,8 +516,6 @@ QPixmapCache::Key QPixmapCache::insert(const QPixmap &pixmap)
the cache by this function.
\sa setCacheLimit(), insert()
-
- \since 4.6
*/
#endif // QT_DEPRECATED_SINCE(6, 6)
@@ -571,8 +562,6 @@ void QPixmapCache::remove(const QString &key)
/*!
Removes the pixmap associated with \a key from the cache and releases
the key for a future insertion.
-
- \since 4.6
*/
void QPixmapCache::remove(const Key &key)
{
diff --git a/src/gui/kernel/qguiapplication.cpp b/src/gui/kernel/qguiapplication.cpp
index 1d7cd37f67..5228ac9477 100644
--- a/src/gui/kernel/qguiapplication.cpp
+++ b/src/gui/kernel/qguiapplication.cpp
@@ -2643,28 +2643,18 @@ void QGuiApplicationPrivate::processThemeChanged(QWindowSystemInterfacePrivate::
QIconPrivate::clearIconCache();
- QStyleHintsPrivate::get(QGuiApplication::styleHints())->updateColorScheme(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;
@@ -4402,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 2bfcd87f3f..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();
diff --git a/src/gui/kernel/qguiapplication_platform.h b/src/gui/kernel/qguiapplication_platform.h
index 545bf75c84..98e19427ae 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,21 @@ 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 handleSpatialEvents(const QJsonObject &) {};
+ };
+ 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/qpalette.cpp b/src/gui/kernel/qpalette.cpp
index 256ea52f01..e308b796ab 100644
--- a/src/gui/kernel/qpalette.cpp
+++ b/src/gui/kernel/qpalette.cpp
@@ -958,7 +958,10 @@ static constexpr QPalette::ResolveMask allResolveMask()
/*!
Returns a new QPalette that is a union of this instance and \a other.
- Color roles set in this instance take precedence.
+ Color roles set in this instance take precedence. Roles that are not
+ set in this instance will be taken from \a other.
+
+ \sa isBrushSet
*/
QPalette QPalette::resolve(const QPalette &other) const
{
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/qstylehints.cpp b/src/gui/kernel/qstylehints.cpp
index 5029701f24..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.
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 2b3979512a..497bf95cbf 100644
--- a/src/gui/kernel/qstylehints_p.h
+++ b/src/gui/kernel/qstylehints_p.h
@@ -35,6 +35,7 @@ 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;
diff --git a/src/gui/kernel/qwindow.cpp b/src/gui/kernel/qwindow.cpp
index b40fd7e8e8..7c885032c7 100644
--- a/src/gui/kernel/qwindow.cpp
+++ b/src/gui/kernel/qwindow.cpp
@@ -2654,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);
diff --git a/src/gui/kernel/qwindow_p.h b/src/gui/kernel/qwindow_p.h
index f6c8aee9f6..40ab06af8b 100644
--- a/src/gui/kernel/qwindow_p.h
+++ b/src/gui/kernel/qwindow_p.h
@@ -84,7 +84,7 @@ public:
Next,
Prev
};
- virtual void setFocusToTarget(QWindowPrivate::FocusTarget) {}
+ virtual void setFocusToTarget(FocusTarget, Qt::FocusReason) {}
virtual QRectF closestAcceptableGeometry(const QRectF &rect) const;
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/qbackingstorerhisupport.cpp b/src/gui/painting/qbackingstorerhisupport.cpp
index fe5589dc2d..37c52155eb 100644
--- a/src/gui/painting/qbackingstorerhisupport.cpp
+++ b/src/gui/painting/qbackingstorerhisupport.cpp
@@ -114,8 +114,8 @@ bool QBackingStoreRhiSupport::create()
if (QRhi::probe(QRhi::Metal, &params)) {
rhi = QRhi::create(QRhi::Metal, &params, flags);
} else {
- qCDebug(lcQpaBackingStore, "Metal does not seem to be supported. Falling back to OpenGL.");
- rhi = QRhi::create(QRhi::OpenGLES2, &params, flags);
+ qCDebug(lcQpaBackingStore, "Metal does not seem to be supported");
+ return false;
}
}
#endif
diff --git a/src/gui/painting/qcmyk_p.h b/src/gui/painting/qcmyk_p.h
index d00a4b5a6e..1294a18244 100644
--- a/src/gui/painting/qcmyk_p.h
+++ b/src/gui/painting/qcmyk_p.h
@@ -24,6 +24,10 @@ class QCmyk32
{
private:
uint m_cmyk = 0;
+ friend constexpr bool comparesEqual(const QCmyk32 &lhs, const QCmyk32 &rhs) noexcept
+ {
+ return lhs.m_cmyk == rhs.m_cmyk;
+ }
public:
QCmyk32() = default;
@@ -77,6 +81,8 @@ public:
QColor c = color.toCmyk();
return QCmyk32(c.cyan(), c.magenta(), c.yellow(), c.black());
}
+
+ Q_DECLARE_EQUALITY_COMPARABLE_LITERAL_TYPE(QCmyk32)
};
static_assert(sizeof(QCmyk32) == sizeof(int));
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/qcolortransform.cpp b/src/gui/painting/qcolortransform.cpp
index aac07bdc09..7692e853fe 100644
--- a/src/gui/painting/qcolortransform.cpp
+++ b/src/gui/painting/qcolortransform.cpp
@@ -390,6 +390,14 @@ template<>
inline int getAlpha<QRgba64>(const QRgba64 &p)
{ return p.alpha(); }
+template<typename T>
+static inline constexpr int getFactor();
+template<>
+inline constexpr int getFactor<QRgb>()
+{ return 255; }
+template<>
+inline constexpr int getFactor<QRgba64>()
+{ return 65535; }
#endif
template<typename T>
@@ -823,8 +831,9 @@ static void storePremultiplied(D *dst, const S *src, const QColorVector *buffer,
const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
const __m128 iFF00 = _mm_set1_ps(1.0f / (255 * 256));
constexpr bool isARGB = isArgb<D>();
+ static_assert(getFactor<D>() >= getFactor<S>());
for (qsizetype i = 0; i < len; ++i) {
- const int a = getAlpha<S>(src[i]);
+ const int a = getAlpha<S>(src[i]) * (getFactor<D>() / getFactor<S>());
__m128 vf = _mm_loadu_ps(&buffer[i].x);
__m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
__m128 va = _mm_mul_ps(_mm_set1_ps(a), iFF00);
@@ -905,8 +914,9 @@ static void storeUnpremultiplied(D *dst, const S *src, const QColorVector *buffe
{
const __m128 vTrcRes = _mm_set1_ps(float(QColorTrcLut::Resolution));
constexpr bool isARGB = isArgb<D>();
+ static_assert(getFactor<D>() >= getFactor<S>());
for (qsizetype i = 0; i < len; ++i) {
- const int a = getAlpha<S>(src[i]);
+ const int a = getAlpha<S>(src[i]) * (getFactor<D>() / getFactor<S>());
__m128 vf = _mm_loadu_ps(&buffer[i].x);
__m128i v = _mm_cvtps_epi32(_mm_mul_ps(vf, vTrcRes));
const int ridx = _mm_extract_epi16(v, 0);
@@ -1029,8 +1039,9 @@ static void storePremultiplied(D *dst, const S *src, const QColorVector *buffer,
{
const float iFF00 = 1.0f / (255 * 256);
constexpr bool isARGB = isArgb<D>();
+ static_assert(getFactor<D>() >= getFactor<S>());
for (qsizetype i = 0; i < len; ++i) {
- const int a = getAlpha<S>(src[i]);
+ const int a = getAlpha<S>(src[i]) * (getFactor<D>() / getFactor<S>());
float32x4_t vf = vld1q_f32(&buffer[i].x);
uint32x4_t v = vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, float(QColorTrcLut::Resolution)), vdupq_n_f32(0.5f)));
const int ridx = vgetq_lane_u32(v, 0);
@@ -1073,8 +1084,9 @@ static void storeUnpremultiplied(D *dst, const S *src, const QColorVector *buffe
const QColorTransformPrivate *d_ptr)
{
constexpr bool isARGB = isArgb<D>();
+ static_assert(getFactor<D>() >= getFactor<S>());
for (qsizetype i = 0; i < len; ++i) {
- const int a = getAlpha<S>(src[i]);
+ const int a = getAlpha<S>(src[i]) * (getFactor<D>() / getFactor<S>());
float32x4_t vf = vld1q_f32(&buffer[i].x);
uint16x4_t v = vmovn_u32(vcvtq_u32_f32(vaddq_f32(vmulq_n_f32(vf, float(QColorTrcLut::Resolution)), vdupq_n_f32(0.5f))));
const int ridx = vget_lane_u16(v, 0);
@@ -1640,7 +1652,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 +1678,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 +1707,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 +1747,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 +1755,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 +1937,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 +1949,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 +1959,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 c01fa433ea..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);
@@ -1067,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;
@@ -1287,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/qimagescale.cpp b/src/gui/painting/qimagescale.cpp
index a636635fd5..eb5f12389f 100644
--- a/src/gui/painting/qimagescale.cpp
+++ b/src/gui/painting/qimagescale.cpp
@@ -1208,7 +1208,7 @@ QImage qSmoothScaleImage(const QImage &src, int dw, int dh)
dw, dh, dw, src.bytesPerLine() / 8);
else
#endif
- if (src.hasAlphaChannel())
+ if (src.hasAlphaChannel() || src.format() == QImage::Format_CMYK8888)
qt_qimageScaleAARGBA(scaleinfo, (unsigned int *)buffer.scanLine(0),
dw, dh, dw, src.bytesPerLine() / 4);
else
diff --git a/src/gui/painting/qpdf.cpp b/src/gui/painting/qpdf.cpp
index 38f2a9b803..31e8bbdc12 100644
--- a/src/gui/painting/qpdf.cpp
+++ b/src/gui/painting/qpdf.cpp
@@ -20,6 +20,7 @@
#include <qimagewriter.h>
#include <qnumeric.h>
#include <qtemporaryfile.h>
+#include <qtimezone.h>
#include <quuid.h>
#ifndef QT_NO_COMPRESS
@@ -1035,6 +1036,7 @@ void QPdfEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
*d->currentPage << "Q\n";
}
+// Used by QtWebKit
void QPdfEngine::drawHyperlink(const QRectF &r, const QUrl &url)
{
Q_D(QPdfEngine);
@@ -1564,7 +1566,7 @@ void QPdfEnginePrivate::writeHeader()
int metaDataObj = -1;
int outputIntentObj = -1;
if (pdfVersion == QPdfEngine::Version_A1b || !xmpDocumentMetadata.isEmpty()) {
- metaDataObj = writeXmpDcumentMetaData();
+ metaDataObj = writeXmpDocumentMetaData();
}
if (pdfVersion == QPdfEngine::Version_A1b) {
outputIntentObj = writeOutputIntent();
@@ -1740,11 +1742,12 @@ void QPdfEnginePrivate::writeInfo()
xprintf("+%02d'%02d')\n", hours , mins);
else
xprintf("Z)\n");
+ xprintf("/Trapped /False\n");
xprintf(">>\n"
"endobj\n");
}
-int QPdfEnginePrivate::writeXmpDcumentMetaData()
+int QPdfEnginePrivate::writeXmpDocumentMetaData()
{
const int metaDataObj = addXrefEntry(-1);
QByteArray metaDataContent;
@@ -1752,26 +1755,12 @@ int QPdfEnginePrivate::writeXmpDcumentMetaData()
if (xmpDocumentMetadata.isEmpty()) {
const QString producer(QString::fromLatin1("Qt " QT_VERSION_STR));
- const QDateTime now = QDateTime::currentDateTime();
- const QDate date = now.date();
- const QTime time = now.time();
- const QString timeStr =
- QString::asprintf("%d-%02d-%02dT%02d:%02d:%02d",
- date.year(), date.month(), date.day(),
- time.hour(), time.minute(), time.second());
-
- const int offset = now.offsetFromUtc();
- const int hours = (offset / 60) / 60;
- const int mins = (offset / 60) % 60;
- QString tzStr;
- if (offset < 0)
- tzStr = QString::asprintf("-%02d:%02d", -hours, -mins);
- else if (offset > 0)
- tzStr = QString::asprintf("+%02d:%02d", hours , mins);
- else
- tzStr = "Z"_L1;
-
- const QString metaDataDate = timeStr + tzStr;
+#if QT_CONFIG(timezone)
+ const QDateTime now = QDateTime::currentDateTime(QTimeZone::systemTimeZone());
+#else
+ const QDateTime now = QDateTime::currentDateTimeUtc();
+#endif
+ const QString metaDataDate = now.toString(Qt::ISODate);
QFile metaDataFile(":/qpdf/qpdfa_metadata.xml"_L1);
bool ok = metaDataFile.open(QIODevice::ReadOnly);
@@ -1813,7 +1802,8 @@ int QPdfEnginePrivate::writeOutputIntent()
s << "/N 3\n";
s << "/Alternate /DeviceRGB\n";
s << "/Length " << length_object << "0 R\n";
- s << "/Filter /FlateDecode\n";
+ if (do_compress)
+ s << "/Filter /FlateDecode\n";
s << ">>\n";
s << "stream\n";
write(data);
@@ -1922,7 +1912,8 @@ void QPdfEnginePrivate::writeAttachmentRoot()
attachments.push_back(addXrefEntry(-1));
xprintf("<<\n"
- "/F (%s)", attachment.fileName.toLatin1().constData());
+ "/F ");
+ printString(attachment.fileName);
xprintf("\n/EF <</F %d 0 R>>\n"
"/Type/Filespec\n"
@@ -2135,17 +2126,24 @@ void QPdfEnginePrivate::writePage()
qreal userUnit = calcUserUnit();
addXrefEntry(pages.constLast());
+
+ // make sure we use the pagesize from when we started the page, since the user may have changed it
+ const QByteArray formattedPageWidth = QByteArray::number(currentPage->pageSize.width() / userUnit, 'f');
+ const QByteArray formattedPageHeight = QByteArray::number(currentPage->pageSize.height() / userUnit, 'f');
+
xprintf("<<\n"
"/Type /Page\n"
"/Parent %d 0 R\n"
"/Contents %d 0 R\n"
"/Resources %d 0 R\n"
"/Annots %d 0 R\n"
- "/MediaBox [0 0 %s %s]\n",
+ "/MediaBox [0 0 %s %s]\n"
+ "/TrimBox [0 0 %s %s]\n",
pageRoot, pageStream, resources, annots,
- // make sure we use the pagesize from when we started the page, since the user may have changed it
- QByteArray::number(currentPage->pageSize.width() / userUnit, 'f').constData(),
- QByteArray::number(currentPage->pageSize.height() / userUnit, 'f').constData());
+ formattedPageWidth.constData(),
+ formattedPageHeight.constData(),
+ formattedPageWidth.constData(),
+ formattedPageHeight.constData());
if (pdfVersion >= QPdfEngine::Version_1_6)
xprintf("/UserUnit %s\n", QByteArray::number(userUnit, 'f').constData());
diff --git a/src/gui/painting/qpdf_p.h b/src/gui/painting/qpdf_p.h
index 3c34e0bd7a..54d37b00a8 100644
--- a/src/gui/painting/qpdf_p.h
+++ b/src/gui/painting/qpdf_p.h
@@ -290,7 +290,7 @@ private:
QPdfEngine::ColorModel colorModelForColor(const QColor &color) const;
void writeColor(ColorDomain domain, const QColor &color);
void writeInfo();
- int writeXmpDcumentMetaData();
+ int writeXmpDocumentMetaData();
int writeOutputIntent();
void writePageRoot();
void writeDestsRoot();
@@ -319,7 +319,7 @@ private:
int addXrefEntry(int object, bool printostr = true);
void printString(QStringView string);
void xprintf(const char* fmt, ...);
- inline void write(const QByteArray &data) {
+ inline void write(QByteArrayView data) {
stream->writeRawData(data.constData(), data.size());
streampos += data.size();
}
diff --git a/src/gui/painting/qregion.cpp b/src/gui/painting/qregion.cpp
index 8b712ee46d..f9089d7bba 100644
--- a/src/gui/painting/qregion.cpp
+++ b/src/gui/painting/qregion.cpp
@@ -876,9 +876,15 @@ QRegion QRegion::intersect(const QRect &r) const
/*!
\fn void QRegion::setRects(const QRect *rects, int number)
+ \overload
+ \obsolete Use the QSpan overload instead.
+*/
+
+/*!
+ \fn void QRegion::setRects(QSpan<const QRect> rects)
+ \since 6.8
- Sets the region using the array of rectangles specified by \a rects and
- \a number.
+ Sets the region using the array of rectangles specified by \a rects.
The rectangles \e must be optimally Y-X sorted and follow these restrictions:
\list
@@ -892,6 +898,11 @@ QRegion QRegion::intersect(const QRect &r) const
\omit
Only some platforms have these restrictions (Qt for Embedded Linux, X11 and \macos).
\endomit
+
+ \note For historical reasons, \c{rects.size()} must be less than \c{INT_MAX}
+ (see rectCount()).
+
+ \sa rects()
*/
namespace {
@@ -4214,18 +4225,39 @@ QRegion::const_iterator QRegion::end() const noexcept
return d->qt_rgn ? d->qt_rgn->end() : nullptr;
}
-void QRegion::setRects(const QRect *rects, int num)
+static Q_DECL_COLD_FUNCTION
+void set_rects_warn(const char *what)
+{
+ qWarning("QRegion::setRects(): %s", what);
+}
+
+void QRegion::setRects(const QRect *r, int n)
{
+ if (!r && n) { // old setRects() allowed this, but QSpan doesn't
+ set_rects_warn("passing num != 0 when rects == nullptr is deprecated.");
+ n = 0;
+ }
+ setRects(QSpan<const QRect>(r, n));
+}
+
+void QRegion::setRects(QSpan<const QRect> rects)
+{
+ const auto num = int(rects.size());
+ if (num != rects.size()) {
+ set_rects_warn("span size exceeds INT_MAX, ignoring");
+ return;
+ }
+
*this = QRegion();
- if (!rects || num == 0 || (num == 1 && rects->isEmpty()))
+ if (!rects.data() || num == 0 || (num == 1 && rects.front().isEmpty()))
return;
detach();
d->qt_rgn->numRects = num;
if (num == 1) {
- d->qt_rgn->extents = *rects;
- d->qt_rgn->innerRect = *rects;
+ d->qt_rgn->extents = rects.front();
+ d->qt_rgn->innerRect = rects.front();
} else {
d->qt_rgn->rects.resize(num);
@@ -4246,12 +4278,30 @@ void QRegion::setRects(const QRect *rects, int num)
}
}
+/*!
+ \since 6.8
+
+ Returns a span of non-overlapping rectangles that make up the region. The
+ span remains valid until the next call of a mutating (non-const) method on
+ this region.
+
+ The union of all the rectangles is equal to the original region.
+
+ \note This functions existed in Qt 5, too, but returned QVector<QRect>
+ instead.
+
+ \sa setRects()
+*/
+QSpan<const QRect> QRegion::rects() const noexcept
+{
+ return {begin(), end()};
+};
+
int QRegion::rectCount() const noexcept
{
return (d->qt_rgn ? d->qt_rgn->numRects : 0);
}
-
bool QRegion::operator==(const QRegion &r) const
{
if (!d->qt_rgn)
diff --git a/src/gui/painting/qregion.h b/src/gui/painting/qregion.h
index b0051b6067..4b852815f3 100644
--- a/src/gui/painting/qregion.h
+++ b/src/gui/painting/qregion.h
@@ -8,11 +8,11 @@
#include <QtCore/qatomic.h>
#include <QtCore/qrect.h>
#include <QtGui/qwindowdefs.h>
-#include <QtCore/qcontainerfwd.h>
#ifndef QT_NO_DATASTREAM
#include <QtCore/qdatastream.h>
#endif
+#include <QtCore/qspan.h>
QT_BEGIN_NAMESPACE
@@ -75,6 +75,8 @@ public:
QRect boundingRect() const noexcept;
void setRects(const QRect *rect, int num);
+ void setRects(QSpan<const QRect> r);
+ QSpan<const QRect> rects() const noexcept;
int rectCount() const noexcept;
QRegion operator|(const QRegion &r) 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 fc4b2296d2..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::updateColorScheme - 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/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 b99afc596c..9fadfc15fa 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -2589,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();
@@ -2598,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();
@@ -2613,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)
@@ -2981,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)
@@ -2996,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;
}
@@ -4850,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/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 f3b861957e..f3a35a4269 100644
--- a/src/gui/text/qfont.cpp
+++ b/src/gui/text/qfont.cpp
@@ -2435,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
*/
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/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/qtextengine.cpp b/src/gui/text/qtextengine.cpp
index a18157ab9b..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
diff --git a/src/gui/text/qtextformat.cpp b/src/gui/text/qtextformat.cpp
index daa79a55d2..dacef70812 100644
--- a/src/gui/text/qtextformat.cpp
+++ b/src/gui/text/qtextformat.cpp
@@ -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
@@ -3426,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()
*/
@@ -3438,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/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
}
/*!