summaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/3rdparty/pcre2/qt_attribution.json2
-rw-r--r--src/corelib/CMakeLists.txt5
-rw-r--r--src/corelib/configure.cmake2
-rw-r--r--src/corelib/doc/images/javaiterators1.svg59
-rw-r--r--src/corelib/doc/images/javaiterators2.svg63
-rw-r--r--src/corelib/doc/src/java-style-iterators.qdoc4
-rw-r--r--src/corelib/itemmodels/qrangemodel.cpp12
-rw-r--r--src/corelib/itemmodels/qrangemodel_impl.h70
-rw-r--r--src/corelib/kernel/qvariant.cpp152
-rw-r--r--src/corelib/kernel/qvariant.h132
-rw-r--r--src/corelib/platform/windows/quniquehandle_types_windows.cpp17
-rw-r--r--src/corelib/platform/windows/quniquehandle_types_windows_p.h65
-rw-r--r--src/corelib/text/qstring.cpp95
-rw-r--r--src/corelib/thread/qthread.h28
-rw-r--r--src/corelib/time/qgregoriancalendar.cpp1
-rw-r--r--src/corelib/time/qjalalicalendar.cpp1
-rw-r--r--src/corelib/time/qjuliancalendar.cpp1
-rw-r--r--src/corelib/time/qmilankoviccalendar.cpp1
-rw-r--r--src/corelib/time/qromancalendar.cpp1
-rw-r--r--src/corelib/time/qtimezone.cpp7
-rw-r--r--src/corelib/time/qtimezonelocale.cpp64
-rw-r--r--src/corelib/time/qtimezoneprivate.cpp12
-rw-r--r--src/corelib/time/qtimezoneprivate_p.h18
-rw-r--r--src/corelib/tools/qiterator.qdoc20
-rw-r--r--src/corelib/tools/quniquehandle_p.h103
-rw-r--r--src/gui/configure.cmake11
-rw-r--r--src/gui/image/qimage.cpp5
-rw-r--r--src/gui/image/qplatformpixmap.h7
-rw-r--r--src/gui/kernel/qevent.cpp75
-rw-r--r--src/gui/kernel/qinputdevice.cpp5
-rw-r--r--src/gui/kernel/qpointingdevice.cpp23
-rw-r--r--src/gui/painting/qtextureglyphcache.cpp2
-rw-r--r--src/gui/rhi/qrhi.cpp20
-rw-r--r--src/gui/rhi/qrhi.h4
-rw-r--r--src/gui/rhi/qrhid3d11.cpp2
-rw-r--r--src/gui/rhi/qrhid3d12.cpp2
-rw-r--r--src/gui/rhi/qrhigles2.cpp22
-rw-r--r--src/gui/rhi/qrhigles2_p.h3
-rw-r--r--src/gui/rhi/qrhimetal.mm8
-rw-r--r--src/gui/rhi/qrhimetal_p.h1
-rw-r--r--src/gui/rhi/qrhivulkan.cpp4
-rw-r--r--src/gui/rhi/qrhivulkan_p.h1
-rw-r--r--src/gui/text/qfontvariableaxis.cpp38
-rw-r--r--src/network/access/qnetworkreplyhttpimpl.cpp14
-rw-r--r--src/network/access/qnetworkreplyhttpimpl_p.h1
-rw-r--r--src/plugins/networkinformation/glib/qglibnetworkinformationbackend.cpp3
-rw-r--r--src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm2
-rw-r--r--src/plugins/platforms/cocoa/qcocoamessagedialog.mm5
-rw-r--r--src/plugins/platforms/wasm/qwasmaccessibility.cpp9
-rw-r--r--src/plugins/platforms/wayland/qwaylandinputcontext.cpp10
-rw-r--r--src/plugins/platforms/windows/qwindowsiconengine.cpp6
-rw-r--r--src/plugins/platforms/windows/qwindowswindow.cpp23
-rw-r--r--src/plugins/platforms/xcb/CMakeLists.txt24
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp175
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qbackingstore_x11_p.h38
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qcolormap_x11.cpp615
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qcolormap_x11_p.h43
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp2807
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h86
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp2087
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h131
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qpolygonclipper_p.h278
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qt_x11_p.h163
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qtessellator.cpp1466
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qtessellator_p.h51
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp288
-rw-r--r--src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.h64
-rw-r--r--src/plugins/platforms/xcb/qxcbimage.cpp6
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.cpp31
-rw-r--r--src/plugins/platforms/xcb/qxcbintegration.h2
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style.cpp102
-rw-r--r--src/plugins/styles/modernwindows/qwindows11style_p.h1
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistastyle.cpp3
-rw-r--r--src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h4
-rw-r--r--src/testlib/qtestcase.cpp13
-rw-r--r--src/widgets/accessible/itemviews.cpp4
-rw-r--r--src/widgets/accessible/itemviews_p.h4
-rw-r--r--src/widgets/accessible/rangecontrols.cpp10
-rw-r--r--src/widgets/accessible/rangecontrols_p.h1
-rw-r--r--src/widgets/dialogs/qcolordialog.cpp123
-rw-r--r--src/widgets/dialogs/qfontdialog.cpp2
-rw-r--r--src/widgets/kernel/qlayout.cpp11
82 files changed, 1189 insertions, 8685 deletions
diff --git a/src/3rdparty/pcre2/qt_attribution.json b/src/3rdparty/pcre2/qt_attribution.json
index ef29ad7d951..0468bca1b3e 100644
--- a/src/3rdparty/pcre2/qt_attribution.json
+++ b/src/3rdparty/pcre2/qt_attribution.json
@@ -30,7 +30,7 @@
"Homepage": "http://www.pcre.org/",
"Version": "10.47",
"DownloadLocation": "https://github.com/PCRE2Project/pcre2/releases/download/pcre2-10.47/pcre2-10.47.tar.bz2",
- "PURL": "pkg:github/PCRE2Project/pcre2@$<VERSION>",
+ "PURL": "pkg:github/PCRE2Project/pcre2@pcre2-$<VERSION>",
"CPE": "cpe:2.3:a:pcre:pcre2:$<VERSION>:*:*:*:*:*:*:*",
"License": "BSD 2-clause \"Simplified\" License",
"LicenseId": "BSD-2-Clause",
diff --git a/src/corelib/CMakeLists.txt b/src/corelib/CMakeLists.txt
index 1147205b79f..380b571c3cf 100644
--- a/src/corelib/CMakeLists.txt
+++ b/src/corelib/CMakeLists.txt
@@ -638,6 +638,7 @@ qt_internal_extend_target(Core CONDITION WIN32
platform/windows/qcomptr_p.h
platform/windows/qbstr_p.h
platform/windows/qcomvariant_p.h
+ platform/windows/quniquehandle_types_windows.cpp platform/windows/quniquehandle_types_windows_p.h
LIBRARIES
advapi32
authz
@@ -1028,7 +1029,7 @@ qt_internal_extend_target(Core
qt_internal_extend_target(Core
CONDITION
- QT_FEATURE_timezone AND UNIX
+ QT_FEATURE_timezone AND UNIX AND NOT VXWORKS
AND NOT ANDROID AND NOT APPLE AND NOT QT_FEATURE_timezone_tzdb
SOURCES
time/qtimezoneprivate_tz.cpp
@@ -1037,7 +1038,7 @@ qt_internal_extend_target(Core
qt_internal_extend_target(Core
CONDITION
QT_FEATURE_icu AND QT_FEATURE_timezone
- AND NOT UNIX AND NOT QT_FEATURE_timezone_tzdb
+ AND (VXWORKS OR NOT UNIX) AND NOT QT_FEATURE_timezone_tzdb
SOURCES
time/qtimezoneprivate_icu.cpp
)
diff --git a/src/corelib/configure.cmake b/src/corelib/configure.cmake
index d951b85c147..edcfba0f6ce 100644
--- a/src/corelib/configure.cmake
+++ b/src/corelib/configure.cmake
@@ -1150,7 +1150,7 @@ qt_feature("timezone" PUBLIC
SECTION "Utilities"
LABEL "QTimeZone"
PURPOSE "Provides support for time-zone handling."
- CONDITION NOT WASM AND NOT VXWORKS
+ CONDITION NOT WASM
)
qt_feature("timezone_locale" PRIVATE
SECTION "Utilities"
diff --git a/src/corelib/doc/images/javaiterators1.svg b/src/corelib/doc/images/javaiterators1.svg
new file mode 100644
index 00000000000..468dbe5371c
--- /dev/null
+++ b/src/corelib/doc/images/javaiterators1.svg
@@ -0,0 +1,59 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ width="340"
+ height="110"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+
+<style>
+ svg .box-style { stroke: black; fill: white }
+ svg .line-style { stroke: red; fill: none }
+ svg .text-style { font: 20px arial; fill: black }
+ svg .fill-style { stroke: none; fill: red }
+
+ [data-theme="dark"] svg .box-style { stroke: #f2f2f2; fill: black }
+ [data-theme="dark"] svg .line-style { stroke: red; fill: none }
+ [data-theme="dark"] svg .text-style { font: 20px arial; fill: #f2f2f2 }
+ [data-theme="dark"] svg .fill-style { stroke: none; fill: red }
+
+ [data-theme="light"] svg .box-style { stroke: black; fill: white }
+ [data-theme="light"] svg .line-style { stroke: red; fill: none }
+ [data-theme="light"] svg .text-style { font: 20px arial; fill: black }
+ [data-theme="light"] svg .fill-style { stroke: none; fill: red }
+</style>
+
+<g transform="translate(10.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">A</text>
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+<g transform="translate(90.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">B</text>
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+<g transform="translate(170.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">C</text>
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+<g transform="translate(250.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">D</text>
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+<g transform="translate(330.5, 10.5)">
+<path d="M 0,60 v 30" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+</g>
+
+</svg>
diff --git a/src/corelib/doc/images/javaiterators2.svg b/src/corelib/doc/images/javaiterators2.svg
new file mode 100644
index 00000000000..df4c6b352a6
--- /dev/null
+++ b/src/corelib/doc/images/javaiterators2.svg
@@ -0,0 +1,63 @@
+<?xml version="1.0" encoding="UTF-8" standalone="no"?>
+<svg
+ version="1.1"
+ width="340"
+ height="130"
+ xmlns="http://www.w3.org/2000/svg"
+ xmlns:svg="http://www.w3.org/2000/svg">
+
+<style>
+ svg .box-style { stroke: black; fill: white }
+ svg .line-style { stroke: red; fill: none }
+ svg .fill-style { stroke: none; fill: red }
+ svg .np-line-style { stroke: blue; fill: none }
+ svg .np-fill-style { stroke: none; fill: blue }
+ svg .text-style { font: 20px arial; fill: black }
+ svg .small-text-style { font: 12px monospace; fill: black }
+
+ [data-theme="dark"] svg .box-style { stroke: #f2f2f2; fill: black }
+ [data-theme="dark"] svg .line-style { stroke: red; fill: none }
+ [data-theme="dark"] svg .fill-style { stroke: none; fill: red }
+ [data-theme="dark"] svg .np-line-style { stroke: #4080ff; fill: none; stroke-width: 1.5 }
+ [data-theme="dark"] svg .np-fill-style { stroke: none; fill: #4080ff }
+ [data-theme="dark"] svg .text-style { font: 20px arial; fill: #f2f2f2 }
+ [data-theme="dark"] svg .small-text-style { font: 12px monospace; fill: #f2f2f2 }
+
+ [data-theme="light"] svg .box-style { stroke: black; fill: white }
+ [data-theme="light"] svg .line-style { stroke: red; fill: none }
+ [data-theme="light"] svg .fill-style { stroke: none; fill: red }
+ [data-theme="light"] svg .np-line-style { stroke: blue; fill: none }
+ [data-theme="light"] svg .np-fill-style { stroke: none; fill: blue }
+ [data-theme="light"] svg .text-style { font: 20px arial; fill: black }
+ [data-theme="light"] svg .small-text-style { font: 12px monospace; fill: black }
+</style>
+
+<g transform="translate(10.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">A</text>
+</g>
+
+<g transform="translate(90.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">B</text>
+<path d="M 0,60 c 0,30 50,40 80,30" class="np-line-style" />
+<path d="M 0,60 l -2,14 l 11,-4 z" class="np-fill-style" />
+<text x="-15" y="110" class="small-text-style">previous()</text>
+</g>
+
+<g transform="translate(170.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">C</text>
+<path d="M 0,60 v 50" class="line-style" />
+<path d="M 0,60 l -5,10 l 10,0 z" class="fill-style" />
+<text x="30" y="110" class="small-text-style">next()</text>
+</g>
+
+<g transform="translate(250.5, 10.5)">
+<path d="m 0,0 h 80 v 60 h -80 z" class="box-style" />
+<text x="35" y="36" class="text-style">D</text>
+<path d="M 0,60 c 0,30 -50,40 -80,30" class="np-line-style" />
+<path d="M 0,60 l 2,14 l -11,-4 z" class="np-fill-style" />
+</g>
+
+</svg>
diff --git a/src/corelib/doc/src/java-style-iterators.qdoc b/src/corelib/doc/src/java-style-iterators.qdoc
index 856005cb66c..a0e5c53d633 100644
--- a/src/corelib/doc/src/java-style-iterators.qdoc
+++ b/src/corelib/doc/src/java-style-iterators.qdoc
@@ -42,7 +42,7 @@
diagram below shows the valid iterator positions as red arrows for a list
containing four items:
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's a typical loop for iterating through all the elements of a
QList<QString> in order:
@@ -70,7 +70,7 @@
\l{QListIterator::next()}{next()} and
\l{QListIterator::previous()}{previous()} on an iterator:
- \image javaiterators2.png
+ \image javaiterators2.png Iterating to the next and previous items
The following table summarizes the QListIterator API:
diff --git a/src/corelib/itemmodels/qrangemodel.cpp b/src/corelib/itemmodels/qrangemodel.cpp
index 05e3a39e589..b0c6c46b125 100644
--- a/src/corelib/itemmodels/qrangemodel.cpp
+++ b/src/corelib/itemmodels/qrangemodel.cpp
@@ -20,6 +20,8 @@ public:
private:
std::unique_ptr<QRangeModelImplBase, QRangeModelImplBase::Deleter> impl;
+ friend class QRangeModelImplBase;
+
mutable QHash<int, QByteArray> m_roleNames;
};
@@ -28,6 +30,16 @@ QRangeModel::QRangeModel(QRangeModelImplBase *impl, QObject *parent)
{
}
+QRangeModelImplBase *QRangeModelImplBase::getImplementation(QRangeModel *model)
+{
+ return model->d_func()->impl.get();
+}
+
+const QRangeModelImplBase *QRangeModelImplBase::getImplementation(const QRangeModel *model)
+{
+ return model->d_func()->impl.get();
+}
+
/*!
\class QRangeModel
\inmodule QtCore
diff --git a/src/corelib/itemmodels/qrangemodel_impl.h b/src/corelib/itemmodels/qrangemodel_impl.h
index f38dc88c0d9..c2f473542d7 100644
--- a/src/corelib/itemmodels/qrangemodel_impl.h
+++ b/src/corelib/itemmodels/qrangemodel_impl.h
@@ -842,6 +842,11 @@ namespace QRangeModelDetails
{
using protocol = wrapped_t<Protocol>;
using row = typename range_traits<wrapped_t<Range>>::value_type;
+ static constexpr bool is_tree = std::conjunction_v<protocol_parentRow<protocol, row>,
+ protocol_childRows<protocol, row>>;
+ static constexpr bool is_list = static_size_v<row> == 0
+ && (!has_metaobject_v<row> || row_category<row>::isMultiRole);
+ static constexpr bool is_table = !is_list && !is_tree;
static constexpr bool has_newRow = protocol_newRow<protocol>();
static constexpr bool has_deleteRow = protocol_deleteRow<protocol, row>();
@@ -1046,6 +1051,9 @@ public:
typename C::MultiData
>;
+ static Q_CORE_EXPORT QRangeModelImplBase *getImplementation(QRangeModel *model);
+ static Q_CORE_EXPORT const QRangeModelImplBase *getImplementation(const QRangeModel *model);
+
private:
friend class QRangeModelPrivate;
QRangeModel *m_rangeModel;
@@ -1147,13 +1155,6 @@ protected:
}
}
- static constexpr bool isMutable()
- {
- return range_features::is_mutable && row_features::is_mutable
- && std::is_reference_v<row_reference>
- && Structure::is_mutable_impl;
- }
-
static constexpr int static_row_count = QRangeModelDetails::static_size_v<range_type>;
static constexpr bool rows_are_raw_pointers = std::is_pointer_v<row_type>;
static constexpr bool rows_are_owning_or_raw_pointers =
@@ -1161,9 +1162,6 @@ protected:
static constexpr int static_column_count = QRangeModelDetails::static_size_v<row_type>;
static constexpr bool one_dimensional_range = static_column_count == 0;
- static constexpr bool dynamicRows() { return isMutable() && static_row_count < 0; }
- static constexpr bool dynamicColumns() { return static_column_count < 0; }
-
// A row might be a value (or range of values), or a pointer.
// row_ptr is always a pointer, and const_row_ptr is a pointer to const.
using row_ptr = wrapped_row_type *;
@@ -1205,6 +1203,15 @@ protected:
"The range holding a move-only row-type must support insert(pos, start, end)");
public:
+ static constexpr bool isMutable()
+ {
+ return range_features::is_mutable && row_features::is_mutable
+ && std::is_reference_v<row_reference>
+ && Structure::is_mutable_impl;
+ }
+ static constexpr bool dynamicRows() { return isMutable() && static_row_count < 0; }
+ static constexpr bool dynamicColumns() { return static_column_count < 0; }
+
explicit QRangeModelImpl(Range &&model, Protocol&& protocol, QRangeModel *itemModel)
: Ancestor(itemModel)
, ProtocolStorage{std::forward<Protocol>(protocol)}
@@ -1236,7 +1243,7 @@ public:
if (row == index.row() && column == index.column())
return index;
- if (column < 0 || column >= this->itemModel().columnCount())
+ if (column < 0 || column >= this->columnCount({}))
return {};
if (row == index.row())
@@ -1974,8 +1981,8 @@ public:
}
if (sourceRow == destRow || sourceRow == destRow - 1 || count <= 0
- || sourceRow < 0 || sourceRow + count - 1 >= this->itemModel().rowCount(sourceParent)
- || destRow < 0 || destRow > this->itemModel().rowCount(destParent)) {
+ || sourceRow < 0 || sourceRow + count - 1 >= this->rowCount(sourceParent)
+ || destRow < 0 || destRow > this->rowCount(destParent)) {
return false;
}
@@ -1995,11 +2002,14 @@ public:
}
}
- QModelIndex parent(const QModelIndex &child) const { return that().parent(child); }
+ const protocol_type& protocol() const { return QRangeModelDetails::refTo(ProtocolStorage::object()); }
+ protocol_type& protocol() { return QRangeModelDetails::refTo(ProtocolStorage::object()); }
+
+ QModelIndex parent(const QModelIndex &child) const { return that().parentImpl(child); }
- int rowCount(const QModelIndex &parent) const { return that().rowCount(parent); }
+ int rowCount(const QModelIndex &parent) const { return that().rowCountImpl(parent); }
- int columnCount(const QModelIndex &parent) const { return that().columnCount(parent); }
+ int columnCount(const QModelIndex &parent) const { return that().columnCountImpl(parent); }
void destroy() { delete std::addressof(that()); }
@@ -2035,6 +2045,11 @@ public:
protected:
~QRangeModelImpl()
{
+ deleteOwnedRows();
+ }
+
+ void deleteOwnedRows()
+ {
// We delete row objects if we are not operating on a reference or pointer
// to a range, as in that case, the owner of the referenced/pointed to
// range also owns the row entries.
@@ -2335,9 +2350,6 @@ protected:
}
- const protocol_type& protocol() const { return QRangeModelDetails::refTo(ProtocolStorage::object()); }
- protocol_type& protocol() { return QRangeModelDetails::refTo(ProtocolStorage::object()); }
-
ModelData m_data;
};
@@ -2385,7 +2397,7 @@ protected:
return this->createIndex(row, column, QRangeModelDetails::pointerTo(*it));
}
- QModelIndex parent(const QModelIndex &child) const
+ QModelIndex parentImpl(const QModelIndex &child) const
{
if (!child.isValid())
return {};
@@ -2410,12 +2422,12 @@ protected:
return {};
}
- int rowCount(const QModelIndex &parent) const
+ int rowCountImpl(const QModelIndex &parent) const
{
return Base::size(this->childRange(parent));
}
- int columnCount(const QModelIndex &) const
+ int columnCountImpl(const QModelIndex &) const
{
// all levels of a tree have to have the same, static, column count
if constexpr (Base::one_dimensional_range)
@@ -2662,6 +2674,9 @@ class QGenericTableItemModelImpl
using Base = QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
friend class QRangeModelImpl<QGenericTableItemModelImpl<Range>, Range>;
+ static constexpr bool is_mutable_impl = true;
+
+public:
using range_type = typename Base::range_type;
using range_features = typename Base::range_features;
using row_type = typename Base::row_type;
@@ -2669,9 +2684,6 @@ class QGenericTableItemModelImpl
using row_traits = typename Base::row_traits;
using row_features = typename Base::row_features;
- static constexpr bool is_mutable_impl = true;
-
-public:
explicit QGenericTableItemModelImpl(Range &&model, QRangeModel *itemModel)
: Base(std::forward<Range>(model), {}, itemModel)
{}
@@ -2692,19 +2704,19 @@ protected:
}
}
- QModelIndex parent(const QModelIndex &) const
+ QModelIndex parentImpl(const QModelIndex &) const
{
return {};
}
- int rowCount(const QModelIndex &parent) const
+ int rowCountImpl(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
return int(Base::size(*this->m_data.model()));
}
- int columnCount(const QModelIndex &parent) const
+ int columnCountImpl(const QModelIndex &parent) const
{
if (parent.isValid())
return 0;
@@ -2760,7 +2772,7 @@ protected:
// dynamically sized rows all have to have the same column count
if constexpr (Base::dynamicColumns() && row_features::has_resize) {
if (QRangeModelDetails::isValid(empty_row))
- QRangeModelDetails::refTo(empty_row).resize(this->itemModel().columnCount());
+ QRangeModelDetails::refTo(empty_row).resize(this->columnCount({}));
}
return empty_row;
diff --git a/src/corelib/kernel/qvariant.cpp b/src/corelib/kernel/qvariant.cpp
index 8366787ea66..57089f164b2 100644
--- a/src/corelib/kernel/qvariant.cpp
+++ b/src/corelib/kernel/qvariant.cpp
@@ -2974,4 +2974,156 @@ const QVariant *QVariantConstPointer::operator->() const
implement operator->().
*/
+/*!
+ \class QVariant::ConstReference
+ \since 6.11
+ \inmodule QtCore
+ \brief The QVariant::ConstReference acts as a const reference to a QVariant.
+
+ As the generic iterators don't actually instantiate a QVariant on each
+ step, they cannot return a reference to one from operator*().
+ QVariant::ConstReference provides the same functionality as an actual
+ reference to a QVariant would, but is backed a referred-to value given as
+ template parameter. The template is implemented for
+ QMetaSequence::ConstIterator, QMetaSequence::Iterator,
+ QMetaAssociation::ConstIterator, and QMetaAssociation::Iterator.
+*/
+
+/*!
+ \fn template<typename Referred> QVariant::ConstReference<Referred>::ConstReference(const Referred &referred)
+
+ Creates a QVariant::ConstReference from a \a referred.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::ConstReference<Referred>::ConstReference(Referred &&referred)
+
+ Creates a QVariant::ConstReference from a \a referred.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::ConstReference<Referred>::operator QVariant() const
+
+ Dereferences the reference to a QVariant.
+ This method needs to be specialized for each Referred type. It is
+ pre-defined for QMetaSequence::ConstIterator, QMetaSequence::Iterator,
+ QMetaAssociation::ConstIterator, and QMetaAssociation::Iterator.
+ */
+
+
+/*!
+ \class QVariant::Reference
+ \since 6.11
+ \inmodule QtCore
+ \brief The QVariant::Reference acts as a non-const reference to a QVariant.
+
+ As the generic iterators don't actually instantiate a QVariant on each
+ step, they cannot return a reference to one from operator*().
+ QVariant::Reference provides the same functionality as an actual reference
+ to a QVariant would, but is backed a referred-to value given as template
+ parameter. The template is implemented for QMetaSequence::Iterator and
+ QMetaAssociation::Iterator.
+*/
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred>::Reference(const Referred &referred)
+
+ Creates a QVariant::Reference from a \a referred.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred>::Reference(Referred &&referred)
+
+ Creates a QVariant::Reference from a \a referred.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred> &QVariant::Reference<Referred>::operator=(const Reference<Referred> &value)
+
+ Assigns a new \a value to the value referred to by this QVariant::Reference.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred> &QVariant::Reference<Referred>::operator=(Reference<Referred> &&value)
+
+ Assigns a new \a value to the value referred to by this QVariant::Reference.
+*/
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred> &QVariant::Reference<Referred>::operator=(const QVariant &value)
+
+ Assigns a new \a value to the value referred to by this QVariant::Reference.
+ This method needs to be specialized for each Referred type. It is
+ pre-defined for QMetaSequence::Iterator and QMetaAssociation::Iterator.
+ */
+
+/*!
+ \fn template<typename Referred> QVariant::Reference<Referred>::operator QVariant() const
+
+ Dereferences the reference to a QVariant. By default this instantiates a
+ temporary QVariant::ConstReference and calls dereferences that. In cases
+ where instantiating a temporary ConstReference is expensive, this method
+ should be specialized.
+ */
+
+/*!
+ \class QVariant::ConstPointer
+ \since 6.11
+ \inmodule QtCore
+ \brief QVariant::ConstPointer is a template class that emulates a const pointer to QVariant.
+
+ QVariant::ConstPointer wraps pointed-to value and returns a
+ QVariant::ConstReference to it from its operator*(). This makes it suitable
+ as replacement for an actual pointer. We cannot return an actual pointer
+ from generic iterators as the iterators don't hold an actual QVariant.
+*/
+
+/*!
+ \fn template<typename Pointed> QVariant::ConstPointer<Pointed>::ConstPointer(const Pointed &pointed)
+
+ Constructs a QVariant::ConstPointer from the value \a pointed to.
+ */
+
+/*!
+ \fn template<typename Pointed> QVariant::ConstPointer<Pointed>::ConstPointer(Pointed &&pointed)
+
+ Constructs a QVariant::ConstPointer from the value \a pointed to.
+ */
+
+/*!
+ \fn template<typename Pointed> QVariant::ConstReference<Pointer> QVariant::ConstPointer<Pointed>::operator*() const
+
+ Dereferences the QVariant::ConstPointer to a QVariant::ConstReference.
+ */
+
+/*!
+ \class QVariant::Pointer
+ \since 6.11
+ \inmodule QtCore
+ \brief QVariant::Pointer is a template class that emulates a non-const pointer to QVariant.
+
+ QVariant::Pointer wraps pointed-to value and returns a QVariant::Reference
+ to it from its operator*(). This makes it suitable as replacement for an
+ actual pointer. We cannot return an actual pointer from generic iterators as
+ the iterators don't hold an actual QVariant.
+*/
+
+/*!
+ \fn template<typename Pointed> QVariant::Pointer<Pointed>::Pointer(const Pointed &pointed)
+
+ Constructs a QVariant::Pointer from the value \a pointed to.
+ */
+
+/*!
+ \fn template<typename Pointed> QVariant::Pointer<Pointed>::Pointer(Pointed &&pointed)
+
+ Constructs a QVariant::Pointer from the value \a pointed to.
+ */
+
+/*!
+ \fn template<typename Pointed> QVariant::Reference<Pointer> QVariant::Pointer<Pointed>::operator*() const
+
+ Dereferences the QVariant::Pointer to a QVariant::Reference.
+ */
+
QT_END_NAMESPACE
diff --git a/src/corelib/kernel/qvariant.h b/src/corelib/kernel/qvariant.h
index 542b1d9b709..9b219d089b5 100644
--- a/src/corelib/kernel/qvariant.h
+++ b/src/corelib/kernel/qvariant.h
@@ -61,7 +61,20 @@ inline T qvariant_cast(const QVariant &);
namespace QtPrivate {
template<> constexpr inline bool qIsRelocatable<QVariant> = true;
-}
+
+template<typename Referred>
+class ConstReference;
+
+template<typename Referred>
+class Reference;
+
+template<typename Pointed>
+class ConstPointer;
+
+template<typename Pointed>
+class Pointer;
+} // namespace QtPrivate
+
class Q_CORE_EXPORT QVariant
{
template <typename T, typename... Args>
@@ -228,6 +241,123 @@ private:
>;
public:
+ template<typename Referred>
+ class ConstReference
+ {
+ private:
+ const Referred m_referred;
+
+ public:
+ // You can initialize a const reference from another one, but you can't assign to it.
+
+ explicit ConstReference(const Referred &referred)
+ noexcept(std::is_nothrow_copy_constructible_v<Referred>)
+ : m_referred(referred) {}
+ explicit ConstReference(Referred &&referred)
+ noexcept(std::is_nothrow_move_constructible_v<Referred>)
+ : m_referred(std::move(referred)) {}
+ ConstReference(const ConstReference &) = default;
+ ConstReference(ConstReference &&) = default;
+ ~ConstReference() = default;
+ ConstReference &operator=(const ConstReference &value) = delete;
+ ConstReference &operator=(ConstReference &&value) = delete;
+
+ // To be specialized for each Referred
+ operator QVariant() const noexcept(Referred::canNoexceptConvertToQVariant);
+ };
+
+ template<typename Referred>
+ class Reference
+ {
+ private:
+ Referred m_referred;
+
+ friend void swap(Reference a, Reference b) { return a.swap(std::move(b)); }
+
+ public:
+ // Assigning and initializing are different operations for references.
+
+ explicit Reference(const Referred &referred)
+ noexcept(std::is_nothrow_copy_constructible_v<Referred>)
+ : m_referred(referred) {}
+ explicit Reference(Referred &&referred)
+ noexcept(std::is_nothrow_move_constructible_v<Referred>)
+ : m_referred(std::move(referred)) {}
+ Reference(const Reference &) = default;
+ Reference(Reference &&) = default;
+ ~Reference() = default;
+
+ Reference &operator=(const Reference &value)
+ noexcept(Referred::canNoexceptAssignQVariant)
+ {
+ return operator=(QVariant(value));
+ }
+
+ Reference &operator=(Reference &&value)
+ noexcept(Referred::canNoexceptAssignQVariant)
+ {
+ return operator=(QVariant(value));
+ }
+
+ operator QVariant() const noexcept(Referred::canNoexceptConvertToQVariant)
+ {
+ return ConstReference(m_referred);
+ }
+
+ void swap(Reference b)
+ {
+ // swapping a reference is not swapping the referred item, but swapping its contents.
+ QVariant tmp = *this;
+ *this = std::move(b);
+ b = std::move(tmp);
+ }
+
+ // To be specialized for each Referred
+ Reference &operator=(const QVariant &value) noexcept(Referred::canNoexceptAssignQVariant);
+ };
+
+ template<typename Pointed>
+ class ConstPointer
+ {
+ private:
+ Pointed m_pointed;
+
+ public:
+ explicit ConstPointer(const Pointed &pointed)
+ noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
+ : m_pointed(pointed) {}
+ explicit ConstPointer(Pointed &&pointed)
+ noexcept(std::is_nothrow_move_constructible_v<Pointed>)
+ : m_pointed(std::move(pointed)) {}
+
+ ConstReference<Pointed> operator*()
+ const noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
+ {
+ return ConstReference<Pointed>(m_pointed);
+ }
+ };
+
+ template<typename Pointed>
+ class Pointer
+ {
+ private:
+ Pointed m_pointed;
+
+ public:
+ explicit Pointer(const Pointed &pointed)
+ noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
+ : m_pointed(pointed) {}
+ explicit Pointer(Pointed &&pointed)
+ noexcept(std::is_nothrow_move_constructible_v<Pointed>)
+ : m_pointed(std::move(pointed)) {}
+
+ Reference<Pointed> operator*()
+ const noexcept(std::is_nothrow_copy_constructible_v<Pointed>)
+ {
+ return Reference<Pointed>(m_pointed);
+ }
+ };
+
template <typename T, typename... Args,
if_constructible<T, Args...> = true>
explicit QVariant(std::in_place_type_t<T>, Args&&... args)
diff --git a/src/corelib/platform/windows/quniquehandle_types_windows.cpp b/src/corelib/platform/windows/quniquehandle_types_windows.cpp
new file mode 100644
index 00000000000..801c9ab13d6
--- /dev/null
+++ b/src/corelib/platform/windows/quniquehandle_types_windows.cpp
@@ -0,0 +1,17 @@
+// Copyright (C) 2025 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 "quniquehandle_types_windows_p.h"
+
+QT_BEGIN_NAMESPACE
+
+namespace QtUniqueHandleTraits {
+
+bool HDCTraits::close(Type handle, HWND hwnd) noexcept
+{
+ return ::ReleaseDC(hwnd, handle);
+}
+
+} // namespace QtUniqueHandleTraits
+
+QT_END_NAMESPACE
diff --git a/src/corelib/platform/windows/quniquehandle_types_windows_p.h b/src/corelib/platform/windows/quniquehandle_types_windows_p.h
new file mode 100644
index 00000000000..0b832d2b9d1
--- /dev/null
+++ b/src/corelib/platform/windows/quniquehandle_types_windows_p.h
@@ -0,0 +1,65 @@
+// Copyright (C) 2025 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
+
+#ifndef QUNIQUEHANDLE_TYPES_WINDOWS_P_H
+#define QUNIQUEHANDLE_TYPES_WINDOWS_P_H
+
+//
+// W A R N I N G
+// -------------
+//
+// This file is not part of the Qt API. It exists purely as an
+// implementation detail. This header file may change from version to
+// version without notice, or even be removed.
+//
+// We mean it.
+//
+
+#if defined(Q_OS_WIN) || defined(Q_QDOC)
+
+#include <QtCore/qnamespace.h>
+#include <QtCore/qt_windows.h>
+#include <QtCore/private/quniquehandle_p.h>
+
+QT_BEGIN_NAMESPACE
+
+namespace QtUniqueHandleTraits {
+
+struct HDCTraits
+{
+ using Type = HDC;
+ static Type invalidValue() noexcept { return nullptr; }
+ Q_CORE_EXPORT static bool close(Type handle, HWND hwnd) noexcept;
+};
+
+struct HDCDeleter
+{
+ using Type = HDCTraits::Type;
+
+ constexpr HDCDeleter() noexcept = default;
+ explicit constexpr HDCDeleter(HWND hwnd) noexcept
+ : hwnd(hwnd)
+ {}
+
+ void operator()(Type handle) const noexcept
+ {
+ if (handle != HDCTraits::invalidValue()) {
+ const bool success = HDCTraits::close(handle, hwnd);
+ Q_ASSERT(success);
+ }
+ }
+
+ HWND hwnd{ nullptr };
+};
+
+} // namespace QtUniqueHandleTraits
+using QUniqueHDCHandle = QUniqueHandle<
+ QtUniqueHandleTraits::HDCTraits,
+ QtUniqueHandleTraits::HDCDeleter
+>;
+
+QT_END_NAMESPACE
+
+#endif // Q_OS_WIN
+
+#endif // QUNIQUEHANDLE_TYPES_WINDOWS_P_H
diff --git a/src/corelib/text/qstring.cpp b/src/corelib/text/qstring.cpp
index 711b70ebf8f..c01c1a9999d 100644
--- a/src/corelib/text/qstring.cpp
+++ b/src/corelib/text/qstring.cpp
@@ -3681,95 +3681,24 @@ QString &QString::remove(QChar ch, Qt::CaseSensitivity cs)
\sa remove()
*/
-
-/*! \internal
- Instead of detaching, or reallocating if "before" is shorter than "after"
- and there isn't enough capacity, create a new string, copy characters to it
- as needed, then swap it with "str".
-*/
-static void replace_with_copy(QString &str, QSpan<size_t> indices, qsizetype blen,
- QStringView after)
-{
- const qsizetype alen = after.size();
- const char16_t *after_b = after.utf16();
-
- const QString::DataPointer &str_d = str.data_ptr();
- auto src_start = str_d.begin();
- const qsizetype newSize = str_d.size + indices.size() * (alen - blen);
- QString copy{ newSize, Qt::Uninitialized };
- QString::DataPointer &copy_d = copy.data_ptr();
- auto dst = copy_d.begin();
- for (size_t index : indices) {
- auto hit = str_d.begin() + index;
- dst = std::copy(src_start, hit, dst);
- dst = std::copy_n(after_b, alen, dst);
- src_start = hit + blen;
- }
- dst = std::copy(src_start, str_d.end(), dst);
- str.swap(copy);
-}
-
-// No detaching or reallocation is needed
-static void replace_in_place(QString &str, QSpan<size_t> indices,
- qsizetype blen, QStringView after)
-{
- const qsizetype alen = after.size();
- const char16_t *after_b = after.utf16();
- const char16_t *after_e = after.utf16() + after.size();
-
- if (blen == alen) { // Replace in place
- for (size_t index : indices)
- std::copy_n(after_b, alen, str.data_ptr().begin() + index);
- } else if (blen > alen) { // Replace from front
- char16_t *begin = str.data_ptr().begin();
- char16_t *hit = begin + indices.front();
- char16_t *to = hit;
- to = std::copy_n(after_b, alen, to);
- char16_t *movestart = hit + blen;
- for (size_t index : indices.sliced(1)) {
- hit = begin + index;
- to = std::move(movestart, hit, to);
- to = std::copy_n(after_b, alen, to);
- movestart = hit + blen;
- }
- to = std::move(movestart, str.data_ptr().end(), to);
- str.resize(std::distance(begin, to));
- } else { // blen < alen, Replace from back
- const qsizetype oldSize = str.data_ptr().size;
- const qsizetype adjust = indices.size() * (alen - blen);
- const qsizetype newSize = oldSize + adjust;
-
- str.resize(newSize);
- char16_t *begin = str.data_ptr().begin();
- char16_t *moveend = begin + oldSize;
- char16_t *to = str.data_ptr().end();
-
- for (auto it = indices.rbegin(), end = indices.rend(); it != end; ++it) {
- char16_t *hit = begin + *it;
- char16_t *movestart = hit + blen;
- to = std::move_backward(movestart, moveend, to);
- to = std::copy_backward(after_b, after_e, to);
- moveend = hit;
- }
- }
-}
-
-static void replace_helper(QString &str, QSpan<size_t> indices, qsizetype blen, QStringView after)
+static void replace_helper(QString &str, QSpan<qsizetype> indices, qsizetype blen, QStringView after)
{
const qsizetype oldSize = str.data_ptr().size;
const qsizetype adjust = indices.size() * (after.size() - blen);
const qsizetype newSize = oldSize + adjust;
+ using A = QStringAlgorithms<QString>;
if (str.data_ptr().needsDetach() || needsReallocate(str, newSize)) {
- replace_with_copy(str, indices, blen, after);
+ A::replace_helper(str, blen, after, indices);
return;
}
- if (QtPrivate::q_points_into_range(after.begin(), str))
+ if (QtPrivate::q_points_into_range(after.begin(), str)) {
// Copy after if it lies inside our own d.b area (which we could
// possibly invalidate via a realloc or modify by replacement)
- replace_in_place(str, indices, blen, QVarLengthArray(after.begin(), after.end()));
- else
- replace_in_place(str, indices, blen, after);
+ A::replace_helper(str, blen, QVarLengthArray(after.begin(), after.end()), indices);
+ } else {
+ A::replace_helper(str, blen, after, indices);
+ }
}
/*!
@@ -3811,8 +3740,8 @@ QString &QString::replace(qsizetype pos, qsizetype len, const QChar *after, qsiz
if (len > this->size() - pos)
len = this->size() - pos;
- size_t index = pos;
- replace_helper(*this, QSpan(&index, 1), len, QStringView{after, alen});
+ qsizetype indices[] = {pos};
+ replace_helper(*this, indices, len, QStringView{after, alen});
return *this;
}
@@ -3890,7 +3819,7 @@ QString &QString::replace(const QChar *before, qsizetype blen,
qsizetype index = 0;
- QVarLengthArray<size_t> indices;
+ QVarLengthArray<qsizetype> indices;
while ((index = matcher.indexIn(*this, index)) != -1) {
indices.push_back(index);
if (blen) // Step over before:
@@ -3925,7 +3854,7 @@ QString& QString::replace(QChar ch, const QString &after, Qt::CaseSensitivity cs
const char16_t cc = (cs == Qt::CaseSensitive ? ch.unicode() : ch.toCaseFolded().unicode());
- QVarLengthArray<size_t> indices;
+ QVarLengthArray<qsizetype> indices;
if (cs == Qt::CaseSensitive) {
const char16_t *begin = d.begin();
const char16_t *end = d.end();
diff --git a/src/corelib/thread/qthread.h b/src/corelib/thread/qthread.h
index bb70678a958..6e4e532fd7d 100644
--- a/src/corelib/thread/qthread.h
+++ b/src/corelib/thread/qthread.h
@@ -172,27 +172,15 @@ inline Qt::HANDLE QThread::currentThreadId() noexcept
#elif defined(Q_PROCESSOR_X86_64) && ((defined(Q_OS_LINUX) && defined(__GLIBC__)) || defined(Q_OS_FREEBSD))
// x86_64 Linux, BSD uses FS
__asm__("mov %%fs:%c1, %0" : "=r" (tid) : "i" (2 * sizeof(void*)) : );
-#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN)
+#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN) && defined(Q_CC_MSVC)
// See https://en.wikipedia.org/wiki/Win32_Thread_Information_Block
- // First get the pointer to the TIB
- quint8 *tib;
-# if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
- __asm__("movq %%gs:0x30, %0" : "=r" (tib) : :);
-# else
- tib = reinterpret_cast<quint8 *>(__readgsqword(0x30));
-# endif
- // Then read the thread ID
- tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x48);
-#elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN)
- // First get the pointer to the TIB
- quint8 *tib;
-# if defined(Q_CC_MINGW) // internal compiler error when using the intrinsics
- __asm__("movl %%fs:0x18, %0" : "=r" (tib) : :);
-# else
- tib = reinterpret_cast<quint8 *>(__readfsdword(0x18));
-# endif
- // Then read the thread ID
- tid = *reinterpret_cast<Qt::HANDLE *>(tib + 0x24);
+ tid = reinterpret_cast<Qt::HANDLE>(__readgsqword(0x48));
+#elif defined(Q_PROCESSOR_X86_64) && defined(Q_OS_WIN) // !Q_CC_MSVC
+ __asm__("mov %%gs:0x48, %0" : "=r" (tid));
+#elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN) && defined(Q_CC_MSVC)
+ tid = reinterpret_cast<Qt::HANDLE>(__readfsdword(0x24));
+#elif defined(Q_PROCESSOR_X86_32) && defined(Q_OS_WIN) // !Q_CC_MSVC
+ __asm__("mov %%fs:0x24, %0" : "=r" (tid));
#else
#undef QT_HAS_FAST_CURRENT_THREAD_ID
tid = currentThreadIdImpl();
diff --git a/src/corelib/time/qgregoriancalendar.cpp b/src/corelib/time/qgregoriancalendar.cpp
index d46d24ac30d..dfb99c5073d 100644
--- a/src/corelib/time/qgregoriancalendar.cpp
+++ b/src/corelib/time/qgregoriancalendar.cpp
@@ -31,6 +31,7 @@ static_assert(qDivMod<86400>(-172800).remainder == 0);
/*!
\since 5.14
+ \internal
\class QGregorianCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qjalalicalendar.cpp b/src/corelib/time/qjalalicalendar.cpp
index 8bc9fe125e7..683ce6e7712 100644
--- a/src/corelib/time/qjalalicalendar.cpp
+++ b/src/corelib/time/qjalalicalendar.cpp
@@ -39,6 +39,7 @@ qint64 firstDayOfYear(int year, int cycleNo)
/*!
\since 5.14
+ \internal
\class QJalaliCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qjuliancalendar.cpp b/src/corelib/time/qjuliancalendar.cpp
index 47da952b84a..cf3718f471d 100644
--- a/src/corelib/time/qjuliancalendar.cpp
+++ b/src/corelib/time/qjuliancalendar.cpp
@@ -13,6 +13,7 @@ using namespace QRoundingDown;
/*!
\since 5.14
+ \internal
\class QJulianCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qmilankoviccalendar.cpp b/src/corelib/time/qmilankoviccalendar.cpp
index a3ffa2a3053..14aef83afe3 100644
--- a/src/corelib/time/qmilankoviccalendar.cpp
+++ b/src/corelib/time/qmilankoviccalendar.cpp
@@ -13,6 +13,7 @@ using namespace QRoundingDown;
/*!
\since 5.14
+ \internal
\class QMilankovicCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qromancalendar.cpp b/src/corelib/time/qromancalendar.cpp
index ae113cf8323..a8ce027275a 100644
--- a/src/corelib/time/qromancalendar.cpp
+++ b/src/corelib/time/qromancalendar.cpp
@@ -9,6 +9,7 @@ QT_BEGIN_NAMESPACE
/*!
\since 5.14
+ \internal
\class QRomanCalendar
\inmodule QtCore
diff --git a/src/corelib/time/qtimezone.cpp b/src/corelib/time/qtimezone.cpp
index f44c681ea80..7b43aab22d1 100644
--- a/src/corelib/time/qtimezone.cpp
+++ b/src/corelib/time/qtimezone.cpp
@@ -29,7 +29,7 @@ static QTimeZonePrivate *newBackendTimeZone()
return new QMacTimeZonePrivate();
#elif defined(Q_OS_ANDROID)
return new QAndroidTimeZonePrivate();
-#elif defined(Q_OS_UNIX)
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
return new QTzTimeZonePrivate();
#elif QT_CONFIG(icu)
return new QIcuTimeZonePrivate();
@@ -50,7 +50,7 @@ static QTimeZonePrivate *newBackendTimeZone(const QByteArray &ianaId)
return new QMacTimeZonePrivate(ianaId);
#elif defined(Q_OS_ANDROID)
return new QAndroidTimeZonePrivate(ianaId);
-#elif defined(Q_OS_UNIX)
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
return new QTzTimeZonePrivate(ianaId);
#elif QT_CONFIG(icu)
return new QIcuTimeZonePrivate(ianaId);
@@ -1482,7 +1482,8 @@ QTimeZone QTimeZone::utc()
bool QTimeZone::isTimeZoneIdAvailable(const QByteArray &ianaId)
{
-#if defined(Q_OS_UNIX) && !(defined(Q_OS_ANDROID) || defined(Q_OS_DARWIN))
+#if defined(Q_OS_UNIX) && !(QT_CONFIG(timezone_tzdb) || defined(Q_OS_DARWIN) \
+ || defined(Q_OS_ANDROID) || defined(Q_OS_VXWORKS))
// Keep #if-ery consistent with selection of QTzTimeZonePrivate in
// newBackendTimeZone(). Skip the pre-check, as the TZ backend accepts POSIX
// zone IDs, which need not be valid IANA IDs. See also QTBUG-112006.
diff --git a/src/corelib/time/qtimezonelocale.cpp b/src/corelib/time/qtimezonelocale.cpp
index a794682fe0b..6ad4aa1479c 100644
--- a/src/corelib/time/qtimezonelocale.cpp
+++ b/src/corelib/time/qtimezonelocale.cpp
@@ -611,6 +611,27 @@ QString QTimeZonePrivate::localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc
// Custom zone with perverse m_id ?
return;
}
+ const auto isMixedCaseAbbrev = [tail](char ch) {
+ // cv-RU and en-GU abbreviate Chamorro as ChST
+ // scn-IT abbreviates Cuba as CuT/CuST/CuDT
+ // blo-BJ abbreviates GMT as Gk
+ switch (tail.size()) {
+ case 2: return tail == "Gk";
+ case 3: return tail == "CuT";
+ case 4:
+ if (tail[0] == 'C' && tail[1] == ch && tail[3] == 'T') {
+ switch (ch) {
+ case 'h': return tail[2] == 'S';
+ case 'u': return tail[2] == 'S' || tail[2] == 'D';
+ default: break;
+ }
+ }
+ return false;
+ default:
+ break;
+ }
+ return false;
+ };
// Even if it is abbr or city name, we don't care if we've found one before.
bool maybeAbbr = ianaAbbrev.isEmpty(), maybeCityName = ianaTail.isEmpty(), inword = false;
@@ -632,7 +653,7 @@ QString QTimeZonePrivate::localeName(qint64 atMSecsSinceEpoch, int offsetFromUtc
maybeCityName = false;
inword = false;
} else if (QChar::isLower(ch)) {
- maybeAbbr = false;
+ maybeAbbr = isMixedCaseAbbrev(ch);
// Dar_es_Salaam shows both cases as word starts
inword = true;
} else if (QChar::isUpper(ch)) {
@@ -891,8 +912,11 @@ QTimeZonePrivate::findLongNamePrefix(QStringView text, const QLocale &locale,
if (best.ianaIdIndex != invalidIanaId)
return { QByteArray(ianaIdData + best.ianaIdIndex), best.nameLength, best.timeType };
- // Now try for a region format:
- best = {};
+ // Now try for a region format.
+ // Since we may get the IANA ID directly from a zone, we may not need an
+ // ianaIdIndex from CLDR-derived tables: and the active backend may know
+ // some zones newer than our latest CLDR.
+ NamePrefixMatch found;
for (const qsizetype locInd : indices) {
const LocaleZoneData &locData = localeZoneData[locInd];
const LocaleZoneData &nextData = localeZoneData[locInd + 1];
@@ -928,11 +952,11 @@ QTimeZonePrivate::findLongNamePrefix(QStringView text, const QLocale &locale,
QStringView city = row.exemplarCity().viewData(exemplarCityTable);
if (textMatches(city)) {
qsizetype length = cut + city.size() + suffix.size();
- if (length > best.nameLength) {
- bool gotZone = row.ianaIdIndex == best.ianaIdIndex
+ if (length > found.nameLength) {
+ bool gotZone = row.ianaId() == found.ianaId // (cheap pre-test)
|| QTimeZone::isTimeZoneIdAvailable(row.ianaId().toByteArray());
if (gotZone)
- best = { length, timeType, row.ianaIdIndex };
+ found = { row.ianaId().toByteArray(), length, timeType };
}
}
}
@@ -945,38 +969,16 @@ QTimeZonePrivate::findLongNamePrefix(QStringView text, const QLocale &locale,
QString city = QString::fromLatin1(local.replace('_', ' '));
if (textMatches(city)) {
qsizetype length = cut + city.size() + suffix.size();
- if (length > best.nameLength) {
- // Have to find iana in ianaIdData. Although its entries
- // from locale-independent data are nicely sorted, the
- // rest are (sadly) not.
- QByteArrayView run(ianaIdData, qstrlen(ianaIdData));
- // std::size includes the trailing '\0', so subtract one:
- const char *stop = ianaIdData + std::size(ianaIdData) - 1;
- while (run != iana) {
- if (run.end() < stop) { // Step to the next:
- run = QByteArrayView(run.end() + 1);
- } else {
- run = QByteArrayView();
- break;
- }
- }
- if (!run.isEmpty()) {
- Q_ASSERT(run == iana);
- const auto ianaIdIndex = run.begin() - ianaIdData;
- Q_ASSERT(ianaIdIndex <= (std::numeric_limits<quint16>::max)());
- best = { length, timeType, quint16(ianaIdIndex) };
- }
- }
+ if (length > found.nameLength)
+ found = { iana, length, timeType };
}
}
// TODO: similar for territories, at least once localeName() does so.
}
}
- if (best.ianaIdIndex != invalidIanaId)
- return { QByteArray(ianaIdData + best.ianaIdIndex), best.nameLength, best.timeType };
#undef localeRows
- return {}; // No match found.
+ return found;
}
QTimeZonePrivate::NamePrefixMatch
diff --git a/src/corelib/time/qtimezoneprivate.cpp b/src/corelib/time/qtimezoneprivate.cpp
index 556f7e21402..3f0254b1c5f 100644
--- a/src/corelib/time/qtimezoneprivate.cpp
+++ b/src/corelib/time/qtimezoneprivate.cpp
@@ -1177,7 +1177,7 @@ QUtcTimeZonePrivate::QUtcTimeZonePrivate(qint32 offsetSeconds)
}
Q_ASSERT(!name.isEmpty());
} else { // Fall back to a UTC-offset name:
- name = isoOffsetFormat(offsetSeconds, QTimeZone::ShortName);
+ name = isoOffsetFormat(offsetSeconds, QTimeZone::OffsetName);
id = name.toUtf8();
}
init(id, offsetSeconds, name, name, QLocale::AnyTerritory, name);
@@ -1292,12 +1292,16 @@ QString QUtcTimeZonePrivate::displayName(QTimeZone::TimeType timeType,
if (!(name.startsWith("GMT"_L1) || name.startsWith("UTC"_L1)) || name.size() < 5)
return false;
// Fallback drops trailing ":00" minute:
- QStringView tail{avoid};
+ QStringView tail{avoid}; // TODO: deal with sign earlier ! Also: invisible Unicode !
tail = tail.sliced(3);
- if (tail.endsWith(":00"_L1))
- tail = tail.chopped(3);
if (name.sliced(3) == tail)
return true;
+ while (tail.endsWith(":00"_L1))
+ tail = tail.chopped(3);
+ while (name.endsWith(":00"_L1))
+ name = name.chopped(3);
+ if (name == tail)
+ return true;
// Accept U+2212 as minus sign:
const QChar sign = name[3] == u'\u2212' ? u'-' : name[3];
// Fallback doesn't zero-pad hour:
diff --git a/src/corelib/time/qtimezoneprivate_p.h b/src/corelib/time/qtimezoneprivate_p.h
index 804c28af372..9a86ded6efb 100644
--- a/src/corelib/time/qtimezoneprivate_p.h
+++ b/src/corelib/time/qtimezoneprivate_p.h
@@ -50,7 +50,7 @@ class Q_AUTOTEST_EXPORT QTimeZonePrivate : public QSharedData
{
// Nothing should be copy-assigning instances of either this or its derived
// classes (only clone() should copy, using the copy-constructor):
- bool operator=(const QTimeZonePrivate &) const = delete;
+ QTimeZonePrivate &operator=(const QTimeZonePrivate &) const = delete;
protected:
QTimeZonePrivate(const QTimeZonePrivate &other) = default;
public:
@@ -210,7 +210,7 @@ Q_DECLARE_TYPEINFO(QTimeZonePrivate::Data, Q_RELOCATABLE_TYPE);
class Q_AUTOTEST_EXPORT QUtcTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QUtcTimeZonePrivate &) const = delete;
+ QUtcTimeZonePrivate &operator=(const QUtcTimeZonePrivate &) const = delete;
QUtcTimeZonePrivate(const QUtcTimeZonePrivate &other);
public:
// Create default UTC time zone
@@ -273,7 +273,7 @@ private:
#if QT_CONFIG(timezone_tzdb)
class QChronoTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QChronoTimeZonePrivate &) const = delete;
+ QChronoTimeZonePrivate &operator=(const QChronoTimeZonePrivate &) const = delete;
QChronoTimeZonePrivate(const QChronoTimeZonePrivate &) = default;
public:
QChronoTimeZonePrivate();
@@ -307,7 +307,7 @@ private:
#elif defined(Q_OS_DARWIN)
class Q_AUTOTEST_EXPORT QMacTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QMacTimeZonePrivate &) const = delete;
+ QMacTimeZonePrivate &operator=(const QMacTimeZonePrivate &) const = delete;
QMacTimeZonePrivate(const QMacTimeZonePrivate &other);
public:
// Create default time zone
@@ -353,7 +353,7 @@ private:
#elif defined(Q_OS_ANDROID)
class QAndroidTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QAndroidTimeZonePrivate &) const = delete;
+ QAndroidTimeZonePrivate &operator=(const QAndroidTimeZonePrivate &) const = delete;
QAndroidTimeZonePrivate(const QAndroidTimeZonePrivate &) = default;
public:
// Create default time zone
@@ -388,7 +388,7 @@ private:
QJniObject androidTimeZone;
};
-#elif defined(Q_OS_UNIX)
+#elif defined(Q_OS_UNIX) && !defined(Q_OS_VXWORKS)
struct QTzTransitionTime
{
qint64 atMSecsSinceEpoch;
@@ -421,7 +421,7 @@ struct QTzTimeZoneCacheEntry
class Q_AUTOTEST_EXPORT QTzTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QTzTimeZonePrivate &) const = delete;
+ QTzTimeZonePrivate &operator=(const QTzTimeZonePrivate &) const = delete;
QTzTimeZonePrivate(const QTzTimeZonePrivate &) = default;
public:
// Create default time zone
@@ -474,7 +474,7 @@ private:
#elif QT_CONFIG(icu)
class Q_AUTOTEST_EXPORT QIcuTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QIcuTimeZonePrivate &) const = delete;
+ QIcuTimeZonePrivate &operator=(const QIcuTimeZonePrivate &) const = delete;
QIcuTimeZonePrivate(const QIcuTimeZonePrivate &other);
public:
// Create default time zone
@@ -518,7 +518,7 @@ private:
#elif defined(Q_OS_WIN)
class Q_AUTOTEST_EXPORT QWinTimeZonePrivate final : public QTimeZonePrivate
{
- bool operator=(const QWinTimeZonePrivate &) const = delete;
+ QWinTimeZonePrivate &operator=(const QWinTimeZonePrivate &) const = delete;
QWinTimeZonePrivate(const QWinTimeZonePrivate &) = default;
public:
struct QWinTransitionRule {
diff --git a/src/corelib/tools/qiterator.qdoc b/src/corelib/tools/qiterator.qdoc
index 3d8ea595167..d517457027a 100644
--- a/src/corelib/tools/qiterator.qdoc
+++ b/src/corelib/tools/qiterator.qdoc
@@ -165,7 +165,7 @@
position between the second and third item, and returns the second
item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -211,7 +211,7 @@
position between the second and third item, returning the second
item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
If you want to find all occurrences of a particular value, use
findNext() in a loop.
@@ -260,7 +260,7 @@
position between the second and third item, returning the second
item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -321,7 +321,7 @@
position between the second and third item, returning the second
item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
If you want to remove items as you iterate over the set, use
remove().
@@ -718,7 +718,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -768,7 +768,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -819,7 +819,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
If you want to find all occurrences of a particular value, use
findNext() in a loop. For example:
@@ -867,7 +867,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -931,7 +931,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
Here's how to iterate over the elements in reverse order:
@@ -994,7 +994,7 @@
next() advances the iterator to the position between the second
and third item; and so on.
- \image javaiterators1.png
+ \image javaiterators1.svg Java-style iterators point between items
If you want to find all occurrences of a particular value, use
findNext() in a loop. For example:
diff --git a/src/corelib/tools/quniquehandle_p.h b/src/corelib/tools/quniquehandle_p.h
index 3ba557e838d..fd6ab693912 100644
--- a/src/corelib/tools/quniquehandle_p.h
+++ b/src/corelib/tools/quniquehandle_p.h
@@ -18,6 +18,7 @@
#include <QtCore/qtconfigmacros.h>
#include <QtCore/qassert.h>
#include <QtCore/qcompare.h>
+#include <QtCore/qfunctionaltools_impl.h>
#include <QtCore/qswap.h>
#include <QtCore/qtclasshelpermacros.h>
@@ -99,6 +100,42 @@ QT_BEGIN_NAMESPACE
...
+ Example 3:
+
+ struct TempFileTraits {
+ using Type = FILE*;
+
+ static Type invalidValue() {
+ return nullptr;
+ }
+
+ static bool close(Type handle) {
+ return fclose(handle) == 0;
+ }
+ };
+
+ struct TempFileDeleter {
+ using Type = TempFileTraits::Type;
+
+ void operator()(Type handle) {
+ if (handle != TempFileTraits::invalidValue()) {
+ TempFileTraits::close(handle);
+ if (path)
+ remove(path);
+ }
+ }
+
+ const char* path{ nullptr };
+ };
+
+ using TempFileHandle = QUniqueHandle<TempFileTraits, TempFileDeleter>;
+
+ Usage:
+
+ TempFileHandle tempFile(fopen("temp.bin", "wb"), TempFileDeleter{ "my_temp.bin" });
+
+ ...
+
NOTE: The QUniqueHandle assumes that closing a resource is
guaranteed to succeed, and provides no support for handling failure
to close a resource. It is therefore only recommended for use cases
@@ -108,9 +145,32 @@ QT_BEGIN_NAMESPACE
// clang-format off
+namespace QtUniqueHandleTraits {
+
template <typename HandleTraits>
-class QUniqueHandle
+struct DefaultDeleter
{
+ using Type = typename HandleTraits::Type;
+
+ void operator()(Type handle) const noexcept
+ {
+ if (handle != HandleTraits::invalidValue()) {
+ const bool success = HandleTraits::close(handle);
+ Q_ASSERT(success);
+ }
+ }
+};
+
+} // namespace QtUniqueHandleTraits
+
+template <typename HandleTraits, typename Deleter = QtUniqueHandleTraits::DefaultDeleter<HandleTraits>>
+class QUniqueHandle : private QtPrivate::CompactStorage<Deleter>
+{
+ using Storage = QtPrivate::CompactStorage<Deleter>;
+
+ template <typename D>
+ using if_default_constructible = std::enable_if_t<std::is_default_constructible_v<D>, bool>;
+
public:
using Type = typename HandleTraits::Type;
static_assert(std::is_nothrow_default_constructible_v<Type>);
@@ -120,6 +180,11 @@ public:
static_assert(std::is_nothrow_copy_assignable_v<Type>);
static_assert(std::is_nothrow_move_assignable_v<Type>);
static_assert(std::is_nothrow_destructible_v<Type>);
+ static_assert(std::is_nothrow_copy_constructible_v<Deleter>);
+ static_assert(std::is_nothrow_move_constructible_v<Deleter>);
+ static_assert(std::is_nothrow_copy_assignable_v<Deleter>);
+ static_assert(std::is_nothrow_move_assignable_v<Deleter>);
+ static_assert(std::is_nothrow_destructible_v<Deleter>);
static_assert(noexcept(std::declval<Type>() == std::declval<Type>()));
static_assert(noexcept(std::declval<Type>() != std::declval<Type>()));
static_assert(noexcept(std::declval<Type>() < std::declval<Type>()));
@@ -127,16 +192,24 @@ public:
static_assert(noexcept(std::declval<Type>() > std::declval<Type>()));
static_assert(noexcept(std::declval<Type>() >= std::declval<Type>()));
- QUniqueHandle() = default;
-
- explicit QUniqueHandle(const Type &handle) noexcept
+ template <if_default_constructible<Deleter> = true>
+ explicit QUniqueHandle(const Type& handle = HandleTraits::invalidValue()) noexcept
: m_handle{ handle }
{}
- QUniqueHandle(QUniqueHandle &&other) noexcept
- : m_handle{ other.release() }
+ QUniqueHandle(const Type &handle, const Deleter &deleter) noexcept
+ : Storage{ deleter }, m_handle{ handle }
+ {}
+
+ QUniqueHandle(const Type &handle, Deleter &&deleter) noexcept
+ : Storage{ std::move(deleter) }, m_handle{ handle }
{}
+ QUniqueHandle(QUniqueHandle &&other) noexcept
+ : Storage{ std::move(other.deleter()) }, m_handle{ other.release() }
+ {
+ }
+
~QUniqueHandle() noexcept
{
close();
@@ -145,6 +218,7 @@ public:
void swap(QUniqueHandle &other) noexcept
{
qSwap(m_handle, other.m_handle);
+ qSwap(deleter(), other.deleter());
}
QT_MOVE_ASSIGNMENT_OPERATOR_IMPL_VIA_MOVE_AND_SWAP(QUniqueHandle)
@@ -168,6 +242,16 @@ public:
return m_handle;
}
+ [[nodiscard]] Deleter& deleter() noexcept
+ {
+ return Storage::object();
+ }
+
+ [[nodiscard]] const Deleter& deleter() const noexcept
+ {
+ return Storage::object();
+ }
+
void reset(const Type& handle = HandleTraits::invalidValue()) noexcept
{
if (handle == m_handle)
@@ -193,8 +277,7 @@ public:
if (!isValid())
return;
- const bool success = HandleTraits::close(m_handle);
- Q_ASSERT(success);
+ deleter()(m_handle);
m_handle = HandleTraits::invalidValue();
}
@@ -222,8 +305,8 @@ private:
// clang-format on
-template <typename Trait>
-void swap(QUniqueHandle<Trait> &lhs, QUniqueHandle<Trait> &rhs) noexcept
+template <typename Trait, typename Deleter>
+void swap(QUniqueHandle<Trait, Deleter> &lhs, QUniqueHandle<Trait, Deleter> &rhs) noexcept
{
lhs.swap(rhs);
}
diff --git a/src/gui/configure.cmake b/src/gui/configure.cmake
index ad76bb095a0..5001f2deeec 100644
--- a/src/gui/configure.cmake
+++ b/src/gui/configure.cmake
@@ -1217,17 +1217,6 @@ qt_feature("xcb-egl-plugin" PRIVATE
CONDITION QT_FEATURE_egl AND QT_FEATURE_opengl
EMIT_IF QT_FEATURE_xcb
)
-qt_feature("xcb-native-painting" PRIVATE
- LABEL "Native painting (experimental)"
- AUTODETECT OFF
- CONDITION QT_FEATURE_xcb_xlib AND QT_FEATURE_fontconfig AND XRender_FOUND
- EMIT_IF QT_FEATURE_xcb
-)
-qt_feature("xrender" PRIVATE
- LABEL "XRender for native painting"
- CONDITION QT_FEATURE_xcb_native_painting
- EMIT_IF QT_FEATURE_xcb AND QT_FEATURE_xcb_native_painting
-)
qt_feature("xcb-xlib" PRIVATE
LABEL "XCB Xlib"
CONDITION QT_FEATURE_xlib AND X11_XCB_FOUND
diff --git a/src/gui/image/qimage.cpp b/src/gui/image/qimage.cpp
index 6ba113ef8fb..4a8b409379c 100644
--- a/src/gui/image/qimage.cpp
+++ b/src/gui/image/qimage.cpp
@@ -47,6 +47,9 @@
#include <memory>
+#define QT_XFORM_TYPE_MSBFIRST 0
+#define QT_XFORM_TYPE_LSBFIRST 1
+
QT_BEGIN_NAMESPACE
class QCmyk32;
@@ -4447,6 +4450,8 @@ int QImage::metric(PaintDeviceMetric metric) const
trigx += m11; \
trigy += m12;
// END OF MACRO
+
+static
bool qt_xForm_helper(const QTransform &trueMat, int xoffset, int type, int depth,
uchar *dptr, qsizetype dbpl, int p_inc, int dHeight,
const uchar *sptr, qsizetype sbpl, int sWidth, int sHeight)
diff --git a/src/gui/image/qplatformpixmap.h b/src/gui/image/qplatformpixmap.h
index 5621afa4da5..3346ca85375 100644
--- a/src/gui/image/qplatformpixmap.h
+++ b/src/gui/image/qplatformpixmap.h
@@ -33,7 +33,7 @@ public:
enum ClassId { RasterClass, DirectFBClass,
BlitterClass, Direct2DClass,
- X11Class, CustomClass = 1024 };
+ CustomClass = 1024 };
QPlatformPixmap(PixelType pixelType, int classId);
virtual ~QPlatformPixmap();
@@ -111,7 +111,6 @@ protected:
private:
friend class QPixmap;
- friend class QX11PlatformPixmap;
friend class QImagePixmapCleanupHooks; // Needs to set is_cached
int detach_no;
@@ -122,10 +121,6 @@ private:
uint is_cached;
};
-# define QT_XFORM_TYPE_MSBFIRST 0
-# define QT_XFORM_TYPE_LSBFIRST 1
-Q_GUI_EXPORT bool qt_xForm_helper(const QTransform&, int, int, int, uchar*, qsizetype, int, int, const uchar*, qsizetype, int, int);
-
QT_END_NAMESPACE
#endif // QPLATFORMPIXMAP_H
diff --git a/src/gui/kernel/qevent.cpp b/src/gui/kernel/qevent.cpp
index ae730a9b3af..7b1e76cc78f 100644
--- a/src/gui/kernel/qevent.cpp
+++ b/src/gui/kernel/qevent.cpp
@@ -1146,6 +1146,33 @@ Q_IMPL_POINTER_EVENT(QHoverEvent)
*/
/*!
+ \property QWheelEvent::device
+ \brief the device from which the wheel event originated
+
+ \sa pointingDevice()
+*/
+
+/*!
+ \property QWheelEvent::inverted
+ \since 5.7
+ \brief whether the delta values delivered with the event are inverted
+
+ Normally, a vertical wheel will produce a QWheelEvent with positive delta
+ values if the top of the wheel is rotating away from the hand operating it.
+ Similarly, a horizontal wheel movement will produce a QWheelEvent with
+ positive delta values if the top of the wheel is moved to the left.
+
+ However, on some platforms this is configurable, so that the same
+ operations described above will produce negative delta values (but with the
+ same magnitude). With the inverted property a wheel event consumer can
+ choose to always follow the direction of the wheel, regardless of the
+ system settings, but only for specific widgets.
+
+ \note Many platforms provide no such information. On such platforms
+ \l inverted always returns false.
+*/
+
+/*!
\fn bool QWheelEvent::inverted() const
\since 5.7
@@ -1236,6 +1263,24 @@ bool QWheelEvent::isEndEvent() const
#endif // QT_CONFIG(wheelevent)
/*!
+ \property QWheelEvent::pixelDelta
+ \brief the scrolling distance in pixels on screen
+
+ This value is provided on platforms that support high-resolution
+ pixel-based delta values, such as \macos. The value should be used
+ directly to scroll content on screen.
+
+ \note On platforms that support scrolling \l{phase()}{phases}, the delta
+ may be null when scrolling is about to begin (Qt::ScrollBegin) or has
+ ended (Qt::ScrollEnd).
+
+ \note On X11 this value is driver-specific and unreliable, use
+ angleDelta() instead.
+
+ \sa angleDelta()
+*/
+
+/*!
\fn QPoint QWheelEvent::pixelDelta() const
Returns the scrolling distance in pixels on screen. This value is
@@ -1256,6 +1301,27 @@ bool QWheelEvent::isEndEvent() const
*/
/*!
+ \property QWheelEvent::angleDelta
+ \brief the relative amount that the wheel was rotated, in eighths of a degree
+
+ A positive value indicates that the wheel was rotated forwards away from the
+ user; a negative value indicates that the wheel was rotated backwards toward
+ the user. \c angleDelta().y() provides the angle through which the common
+ vertical mouse wheel was rotated since the previous event. \c angleDelta().x()
+ provides the angle through which the horizontal mouse wheel was rotated, if
+ the mouse has a horizontal wheel; otherwise it stays at zero.
+
+ Most mouse types work in steps of 15 degrees, in which case the delta value
+ is a multiple of 120; i.e., 120 units * 1/8 = 15 degrees.
+
+ \note On platforms that support scrolling \l{phase()}{phases}, the delta
+ may be null when scrolling is about to begin (Qt::ScrollBegin) or has
+ ended (Qt::ScrollEnd).
+
+ \sa pixelDelta()
+*/
+
+/*!
\fn QPoint QWheelEvent::angleDelta() const
Returns the relative amount that the wheel was rotated, in eighths of a
@@ -1294,6 +1360,15 @@ bool QWheelEvent::isEndEvent() const
*/
/*!
+ \property QWheelEvent::phase
+ \since 5.2
+ \brief the scrolling phase of this wheel event
+
+ \note The Qt::ScrollBegin and Qt::ScrollEnd phases are currently
+ supported only on \macos.
+*/
+
+/*!
\fn Qt::ScrollPhase QWheelEvent::phase() const
\since 5.2
diff --git a/src/gui/kernel/qinputdevice.cpp b/src/gui/kernel/qinputdevice.cpp
index 8e5c38922e0..caed0fc6135 100644
--- a/src/gui/kernel/qinputdevice.cpp
+++ b/src/gui/kernel/qinputdevice.cpp
@@ -187,6 +187,11 @@ QString QInputDevice::name() const
}
/*!
+ \property QInputDevice::type
+ \brief the device type
+*/
+
+/*!
Returns the device type.
*/
QInputDevice::DeviceType QInputDevice::type() const
diff --git a/src/gui/kernel/qpointingdevice.cpp b/src/gui/kernel/qpointingdevice.cpp
index dcce354688a..7062340b287 100644
--- a/src/gui/kernel/qpointingdevice.cpp
+++ b/src/gui/kernel/qpointingdevice.cpp
@@ -241,6 +241,11 @@ void QPointingDevice::setMaximumTouchPoints(int c)
#endif // QT_DEPRECATED_SINCE(6, 0)
/*!
+ \property QPointingDevice::pointerType
+ \brief the pointer type
+*/
+
+/*!
Returns the pointer type.
*/
QPointingDevice::PointerType QPointingDevice::pointerType() const
@@ -250,6 +255,12 @@ QPointingDevice::PointerType QPointingDevice::pointerType() const
}
/*!
+ \property QPointingDevice::maximumPoints
+ \brief the maximum number of simultaneous touch points (fingers) that
+ can be detected
+*/
+
+/*!
Returns the maximum number of simultaneous touch points (fingers) that
can be detected.
*/
@@ -260,6 +271,11 @@ int QPointingDevice::maximumPoints() const
}
/*!
+ \property QPointingDevice::buttonCount
+ \brief the maximum number of on-device buttons that can be detected
+*/
+
+/*!
Returns the maximum number of on-device buttons that can be detected.
*/
int QPointingDevice::buttonCount() const
@@ -269,6 +285,13 @@ int QPointingDevice::buttonCount() const
}
/*!
+ \property QPointingDevice::uniqueId
+ \brief a unique ID (of dubious utility) for the device
+
+ You probably should rather be concerned with QPointerEventPoint::uniqueId().
+*/
+
+/*!
Returns a unique ID (of dubious utility) for the device.
You probably should rather be concerned with QPointerEventPoint::uniqueId().
diff --git a/src/gui/painting/qtextureglyphcache.cpp b/src/gui/painting/qtextureglyphcache.cpp
index d27539b2419..c9df5d28a45 100644
--- a/src/gui/painting/qtextureglyphcache.cpp
+++ b/src/gui/painting/qtextureglyphcache.cpp
@@ -301,6 +301,8 @@ void QImageTextureGlyphCache::fillTexture(const Coord &c,
const QFixedPoint &subPixelPosition)
{
QImage mask = textureMapForGlyph(g, subPixelPosition);
+ if (mask.isNull())
+ return;
#ifdef CACHE_DEBUG
printf("fillTexture of %dx%d at %d,%d in the cache of %dx%d\n", c.w, c.h, c.x, c.y, m_image.width(), m_image.height());
diff --git a/src/gui/rhi/qrhi.cpp b/src/gui/rhi/qrhi.cpp
index 62b7ab6efb0..5590f2fb431 100644
--- a/src/gui/rhi/qrhi.cpp
+++ b/src/gui/rhi/qrhi.cpp
@@ -7186,6 +7186,26 @@ QRhiResource::Type QRhiGraphicsPipeline::resourceType() const
*/
/*!
+ \fn bool QRhiGraphicsPipeline::hasDepthClamp() const
+ \return true if depth clamp is enabled.
+
+ \since 6.11
+ */
+
+/*!
+ \fn void QRhiGraphicsPipeline::setDepthClamp(bool enable)
+
+ Enables depth clamping when \a enable is true. When depth clamping is
+ enabled, primitives that would otherwise be clipped by the near or far
+ clip plane are rasterized and their depth values are clamped to the
+ depth range. When disabled (the default), such primitives are clipped.
+
+ \note This setting is ignored on OpenGL ES.
+
+ \since 6.11
+ */
+
+/*!
\fn QRhiGraphicsPipeline::CompareOp QRhiGraphicsPipeline::depthOp() const
\return the depth comparison function.
*/
diff --git a/src/gui/rhi/qrhi.h b/src/gui/rhi/qrhi.h
index b5a3f7b43be..5ee2a9acd13 100644
--- a/src/gui/rhi/qrhi.h
+++ b/src/gui/rhi/qrhi.h
@@ -1453,6 +1453,9 @@ public:
bool hasDepthWrite() const { return m_depthWrite; }
void setDepthWrite(bool enable) { m_depthWrite = enable; }
+ bool hasDepthClamp() const { return m_depthClamp; }
+ void setDepthClamp(bool enable) { m_depthClamp = enable; }
+
CompareOp depthOp() const { return m_depthOp; }
void setDepthOp(CompareOp op) { m_depthOp = op; }
@@ -1524,6 +1527,7 @@ protected:
QVarLengthArray<TargetBlend, 8> m_targetBlends;
bool m_depthTest = false;
bool m_depthWrite = false;
+ bool m_depthClamp = false;
CompareOp m_depthOp = Less;
bool m_stencilTest = false;
StencilOpState m_stencilFront;
diff --git a/src/gui/rhi/qrhid3d11.cpp b/src/gui/rhi/qrhid3d11.cpp
index a5f860e7724..1441be24043 100644
--- a/src/gui/rhi/qrhid3d11.cpp
+++ b/src/gui/rhi/qrhid3d11.cpp
@@ -4673,7 +4673,7 @@ bool QD3D11GraphicsPipeline::create()
rastDesc.FrontCounterClockwise = m_frontFace == CCW;
rastDesc.DepthBias = m_depthBias;
rastDesc.SlopeScaledDepthBias = m_slopeScaledDepthBias;
- rastDesc.DepthClipEnable = true;
+ rastDesc.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
rastDesc.ScissorEnable = m_flags.testFlag(UsesScissor);
rastDesc.MultisampleEnable = rhiD->effectiveSampleDesc(m_sampleCount).Count > 1;
HRESULT hr = rhiD->dev->CreateRasterizerState(&rastDesc, &rastState);
diff --git a/src/gui/rhi/qrhid3d12.cpp b/src/gui/rhi/qrhid3d12.cpp
index 4f09b3c136b..b68b65b1063 100644
--- a/src/gui/rhi/qrhid3d12.cpp
+++ b/src/gui/rhi/qrhid3d12.cpp
@@ -6263,7 +6263,7 @@ bool QD3D12GraphicsPipeline::create()
stream.rasterizerState.object.FrontCounterClockwise = m_frontFace == CCW;
stream.rasterizerState.object.DepthBias = m_depthBias;
stream.rasterizerState.object.SlopeScaledDepthBias = m_slopeScaledDepthBias;
- stream.rasterizerState.object.DepthClipEnable = TRUE;
+ stream.rasterizerState.object.DepthClipEnable = m_depthClamp ? FALSE : TRUE;
stream.rasterizerState.object.MultisampleEnable = sampleDesc.Count > 1;
stream.depthStencilState.object.DepthEnable = m_depthTest;
diff --git a/src/gui/rhi/qrhigles2.cpp b/src/gui/rhi/qrhigles2.cpp
index 15f5cd8f7e8..1308d4362e5 100644
--- a/src/gui/rhi/qrhigles2.cpp
+++ b/src/gui/rhi/qrhigles2.cpp
@@ -585,6 +585,10 @@ QT_BEGIN_NAMESPACE
#define GL_PROGRAM 0x82E2
#endif
+#ifndef GL_DEPTH_CLAMP
+#define GL_DEPTH_CLAMP 0x864F
+#endif
+
/*!
Constructs a new QRhiGles2InitParams.
@@ -998,6 +1002,13 @@ bool QRhiGles2::create(QRhi::Flags flags)
}
if (caps.gles)
+ caps.depthClamp = false;
+ else
+ caps.depthClamp = caps.ctxMajor > 3 || (caps.ctxMajor == 3 && caps.ctxMinor >= 2); // Desktop 3.2
+ if (!caps.depthClamp)
+ caps.depthClamp = ctx->hasExtension("GL_EXT_depth_clamp") || ctx->hasExtension("GL_ARB_depth_clamp");
+
+ if (caps.gles)
caps.textureCompareMode = caps.ctxMajor >= 3; // ES 3.0
else
caps.textureCompareMode = true;
@@ -3959,6 +3970,7 @@ void QRhiGles2::executeCommandBuffer(QRhiCommandBuffer *cb)
break;
case QGles2CommandBuffer::Command::InvalidateFramebuffer:
if (caps.gles && caps.ctxMajor >= 3) {
+ f->glBindFramebuffer(GL_FRAMEBUFFER, cmd.args.invalidateFramebuffer.fbo);
f->glInvalidateFramebuffer(GL_DRAW_FRAMEBUFFER,
cmd.args.invalidateFramebuffer.attCount,
cmd.args.invalidateFramebuffer.att);
@@ -4095,6 +4107,15 @@ void QRhiGles2::executeBindGraphicsPipeline(QGles2CommandBuffer *cbD, QGles2Grap
f->glDepthMask(depthWrite);
}
+ const bool depthClamp = psD->m_depthClamp;
+ if (caps.depthClamp && (forceUpdate || depthClamp != state.depthClamp)) {
+ state.depthClamp = depthClamp;
+ if (depthClamp)
+ f->glEnable(GL_DEPTH_CLAMP);
+ else
+ f->glDisable(GL_DEPTH_CLAMP);
+ }
+
const GLenum depthFunc = toGlCompareOp(psD->m_depthOp);
if (forceUpdate || depthFunc != state.depthFunc) {
state.depthFunc = depthFunc;
@@ -4881,6 +4902,7 @@ void QRhiGles2::endPass(QRhiCommandBuffer *cb, QRhiResourceUpdateBatch *resource
if (mayDiscardDepthStencil) {
QGles2CommandBuffer::Command &cmd(cbD->commands.get());
cmd.cmd = QGles2CommandBuffer::Command::InvalidateFramebuffer;
+ cmd.args.invalidateFramebuffer.fbo = rtTex->framebuffer;
if (caps.needsDepthStencilCombinedAttach) {
cmd.args.invalidateFramebuffer.attCount = 1;
cmd.args.invalidateFramebuffer.att[0] = GL_DEPTH_STENCIL_ATTACHMENT;
diff --git a/src/gui/rhi/qrhigles2_p.h b/src/gui/rhi/qrhigles2_p.h
index 725e71a3665..70dd96a8dc7 100644
--- a/src/gui/rhi/qrhigles2_p.h
+++ b/src/gui/rhi/qrhigles2_p.h
@@ -547,6 +547,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
GLbitfield barriers;
} barrier;
struct {
+ GLuint fbo;
int attCount;
GLenum att[3];
} invalidateFramebuffer;
@@ -592,6 +593,7 @@ struct QGles2CommandBuffer : public QRhiCommandBuffer
} blend[16];
bool depthTest;
bool depthWrite;
+ bool depthClamp;
GLenum depthFunc;
bool stencilTest;
GLuint stencilReadMask;
@@ -1074,6 +1076,7 @@ public:
uint baseVertex : 1;
uint compute : 1;
uint textureCompareMode : 1;
+ uint depthClamp : 1;
uint properMapBuffer : 1;
uint nonBaseLevelFramebufferTexture : 1;
uint texelFetch : 1;
diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm
index c3f1031b44b..7fa05f69232 100644
--- a/src/gui/rhi/qrhimetal.mm
+++ b/src/gui/rhi/qrhimetal.mm
@@ -403,6 +403,7 @@ struct QMetalGraphicsPipelineData
MTLWinding winding;
MTLCullMode cullMode;
MTLTriangleFillMode triangleFillMode;
+ MTLDepthClipMode depthClipMode;
float depthBias;
float slopeScaledDepthBias;
QMetalShader vs;
@@ -1477,7 +1478,6 @@ void QMetalGraphicsPipeline::makeActiveForCurrentRenderPassEncoder(QMetalCommand
[cbD->d->currentRenderPassEncoder setDepthStencilState: d->ds];
cbD->d->currentDepthStencilState = d->ds;
}
-
if (cbD->currentCullMode == -1 || d->cullMode != uint(cbD->currentCullMode)) {
[cbD->d->currentRenderPassEncoder setCullMode: d->cullMode];
cbD->currentCullMode = int(d->cullMode);
@@ -1486,6 +1486,10 @@ void QMetalGraphicsPipeline::makeActiveForCurrentRenderPassEncoder(QMetalCommand
[cbD->d->currentRenderPassEncoder setTriangleFillMode: d->triangleFillMode];
cbD->currentTriangleFillMode = int(d->triangleFillMode);
}
+ if (cbD->currentDepthClipMode == -1 || d->depthClipMode != uint(cbD->currentDepthClipMode)) {
+ [cbD->d->currentRenderPassEncoder setDepthClipMode: d->depthClipMode];
+ cbD->currentDepthClipMode = int(d->depthClipMode);
+ }
if (cbD->currentFrontFaceWinding == -1 || d->winding != uint(cbD->currentFrontFaceWinding)) {
[cbD->d->currentRenderPassEncoder setFrontFacingWinding: d->winding];
cbD->currentFrontFaceWinding = int(d->winding);
@@ -5035,6 +5039,7 @@ void QMetalGraphicsPipeline::mapStates()
d->winding = m_frontFace == CCW ? MTLWindingCounterClockwise : MTLWindingClockwise;
d->cullMode = toMetalCullMode(m_cullMode);
d->triangleFillMode = toMetalTriangleFillMode(m_polygonMode);
+ d->depthClipMode = m_depthClamp ? MTLDepthClipModeClamp : MTLDepthClipModeClip;
d->depthBias = float(m_depthBias);
d->slopeScaledDepthBias = m_slopeScaledDepthBias;
}
@@ -6257,6 +6262,7 @@ void QMetalCommandBuffer::resetPerPassCachedState()
currentIndexFormat = QRhiCommandBuffer::IndexUInt16;
currentCullMode = -1;
currentTriangleFillMode = -1;
+ currentDepthClipMode = -1;
currentFrontFaceWinding = -1;
currentDepthBiasValues = { 0.0f, 0.0f };
diff --git a/src/gui/rhi/qrhimetal_p.h b/src/gui/rhi/qrhimetal_p.h
index 7c19ae9e767..6649a6cd304 100644
--- a/src/gui/rhi/qrhimetal_p.h
+++ b/src/gui/rhi/qrhimetal_p.h
@@ -299,6 +299,7 @@ struct QMetalCommandBuffer : public QRhiCommandBuffer
QRhiCommandBuffer::IndexFormat currentIndexFormat;
int currentCullMode;
int currentTriangleFillMode;
+ int currentDepthClipMode;
int currentFrontFaceWinding;
std::pair<float, float> currentDepthBiasValues;
diff --git a/src/gui/rhi/qrhivulkan.cpp b/src/gui/rhi/qrhivulkan.cpp
index c5167a6e7de..481ffd57b5d 100644
--- a/src/gui/rhi/qrhivulkan.cpp
+++ b/src/gui/rhi/qrhivulkan.cpp
@@ -949,6 +949,8 @@ bool QRhiVulkan::create(QRhi::Flags flags)
// elsewhere states that the minimum bufferOffset is 4...
texbufAlign = qMax<VkDeviceSize>(4, physDevProperties.limits.optimalBufferCopyOffsetAlignment);
+ caps.depthClamp = physDevFeatures.depthClamp;
+
caps.wideLines = physDevFeatures.wideLines;
caps.texture3DSliceAs2D = caps.apiVersion >= QVersionNumber(1, 1);
@@ -8402,6 +8404,8 @@ bool QVkGraphicsPipeline::create()
VkPipelineRasterizationStateCreateInfo rastInfo = {};
rastInfo.sType = VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO;
+ if (m_depthClamp && rhiD->caps.depthClamp)
+ rastInfo.depthClampEnable = m_depthClamp;
rastInfo.cullMode = toVkCullMode(m_cullMode);
rastInfo.frontFace = toVkFrontFace(m_frontFace);
if (m_depthBias != 0 || !qFuzzyIsNull(m_slopeScaledDepthBias)) {
diff --git a/src/gui/rhi/qrhivulkan_p.h b/src/gui/rhi/qrhivulkan_p.h
index d141a84c5fb..1e9318513fd 100644
--- a/src/gui/rhi/qrhivulkan_p.h
+++ b/src/gui/rhi/qrhivulkan_p.h
@@ -936,6 +936,7 @@ public:
struct {
bool compute = false;
+ bool depthClamp = false;
bool wideLines = false;
bool debugUtils = false;
bool vertexAttribDivisor = false;
diff --git a/src/gui/text/qfontvariableaxis.cpp b/src/gui/text/qfontvariableaxis.cpp
index be83a3e02ce..bbc14f4cd11 100644
--- a/src/gui/text/qfontvariableaxis.cpp
+++ b/src/gui/text/qfontvariableaxis.cpp
@@ -60,6 +60,18 @@ QT_DEFINE_QESDP_SPECIALIZATION_DTOR(QFontVariableAxisPrivate)
QFontVariableAxis::QFontVariableAxis(const QFontVariableAxis &axis) = default;
/*!
+ \property QFontVariableAxis::tag
+ \brief the tag of the axis
+
+ This is a four-character sequence which identifies the axis. Certain tags
+ have standardized meanings, such as "wght" (weight) and "wdth" (width),
+ but any sequence of four latin-1 characters is a valid tag. By convention,
+ non-standard/custom axes are denoted by tags in all uppercase.
+
+ \sa QFont::setVariableAxis(), name()
+*/
+
+/*!
Returns the tag of the axis. This is a four-character sequence which identifies the axis.
Certain tags have standardized meanings, such as "wght" (weight) and "wdth" (width), but any
sequence of four latin-1 characters is a valid tag. By convention, non-standard/custom axes
@@ -91,6 +103,13 @@ void QFontVariableAxis::setTag(QFont::Tag tag)
}
/*!
+ \property QFontVariableAxis::name
+ \brief the name of the axis, if provided by the font
+
+ \sa tag()
+*/
+
+/*!
Returns the name of the axis, if provided by the font.
\sa tag()
@@ -153,6 +172,15 @@ void QFontVariableAxis::setMinimumValue(qreal minimumValue)
}
/*!
+ \property QFontVariableAxis::maximumValue
+ \brief the maximum value of the axis
+
+ Setting the axis to a value which is higher than this is not supported.
+
+ \sa minimumValue(), defaultValue()
+*/
+
+/*!
Returns the maximum value of the axis. Setting the axis to a value which is higher than this
is not supported.
@@ -182,6 +210,16 @@ void QFontVariableAxis::setMaximumValue(qreal maximumValue)
}
/*!
+ \property QFontVariableAxis::defaultValue
+ \brief the default value of the axis
+
+ This is the value the axis will have if none has been provided in the
+ QFont query.
+
+ \sa minimumValue(), maximumValue()
+*/
+
+/*!
Returns the default value of the axis. This is the value the axis will have if none has been
provided in the QFont query.
diff --git a/src/network/access/qnetworkreplyhttpimpl.cpp b/src/network/access/qnetworkreplyhttpimpl.cpp
index f680950701c..f76d79571c3 100644
--- a/src/network/access/qnetworkreplyhttpimpl.cpp
+++ b/src/network/access/qnetworkreplyhttpimpl.cpp
@@ -272,6 +272,11 @@ void QNetworkReplyHttpImpl::close()
void QNetworkReplyHttpImpl::abort()
{
+ abortImpl(QNetworkReply::OperationCanceledError);
+}
+
+void QNetworkReplyHttpImpl::abortImpl(QNetworkReply::NetworkError error)
+{
Q_D(QNetworkReplyHttpImpl);
// FIXME
if (d->state == QNetworkReplyPrivate::Finished || d->state == QNetworkReplyPrivate::Aborted)
@@ -282,7 +287,8 @@ void QNetworkReplyHttpImpl::abort()
if (d->state != QNetworkReplyPrivate::Finished) {
// call finished which will emit signals
// FIXME shouldn't this be emitted Queued?
- d->error(OperationCanceledError, tr("Operation canceled"));
+ d->error(error,
+ error == TimeoutError ? tr("Operation timed out") : tr("Operation canceled"));
d->finished();
}
@@ -2120,7 +2126,7 @@ void QNetworkReplyHttpImplPrivate::_q_bufferOutgoingData()
void QNetworkReplyHttpImplPrivate::_q_transferTimedOut()
{
Q_Q(QNetworkReplyHttpImpl);
- q->abort();
+ q->abortImpl(QNetworkReply::TimeoutError);
}
void QNetworkReplyHttpImplPrivate::setupTransferTimeout()
@@ -2242,8 +2248,10 @@ void QNetworkReplyHttpImplPrivate::error(QNetworkReplyImpl::NetworkError code, c
// Can't set and emit multiple errors.
if (errorCode != QNetworkReply::NoError) {
// But somewhat unavoidable if we have cancelled the request:
- if (errorCode != QNetworkReply::OperationCanceledError)
+ if (errorCode != QNetworkReply::OperationCanceledError
+ && errorCode != QNetworkReply::TimeoutError) {
qWarning("QNetworkReplyImplPrivate::error: Internal problem, this method must only be called once.");
+ }
return;
}
diff --git a/src/network/access/qnetworkreplyhttpimpl_p.h b/src/network/access/qnetworkreplyhttpimpl_p.h
index 0d16d02ff53..a354b388ad6 100644
--- a/src/network/access/qnetworkreplyhttpimpl_p.h
+++ b/src/network/access/qnetworkreplyhttpimpl_p.h
@@ -59,6 +59,7 @@ public:
void close() override;
void abort() override;
+ void abortImpl(QNetworkReply::NetworkError error);
qint64 bytesAvailable() const override;
bool isSequential () const override;
qint64 size() const override;
diff --git a/src/plugins/networkinformation/glib/qglibnetworkinformationbackend.cpp b/src/plugins/networkinformation/glib/qglibnetworkinformationbackend.cpp
index 62d24eefd33..e5ada714ba5 100644
--- a/src/plugins/networkinformation/glib/qglibnetworkinformationbackend.cpp
+++ b/src/plugins/networkinformation/glib/qglibnetworkinformationbackend.cpp
@@ -110,7 +110,8 @@ QGlibNetworkInformationBackend::QGlibNetworkInformationBackend()
connectivityHandlerId = g_signal_connect_swapped(networkMonitor, "notify::connectivity",
G_CALLBACK(updateConnectivity), this);
- networkHandlerId = g_signal_connect_swapped(networkMonitor, "network-changed",
+ // needed until GLib 2.86 for netlink support
+ networkHandlerId = g_signal_connect_swapped(networkMonitor, "notify::network-available",
G_CALLBACK(updateConnectivity), this);
meteredHandlerId = g_signal_connect_swapped(networkMonitor, "notify::network-metered",
diff --git a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
index e0ef6cec794..4c4e5fac962 100644
--- a/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
+++ b/src/plugins/platforms/cocoa/qcocoafiledialoghelper.mm
@@ -491,7 +491,7 @@ typedef QSharedPointer<QFileDialogOptions> SharedPointerFileDialogOptions;
return;
if (m_panel.visible) {
- const QString selection = QString::fromNSString(m_panel.URL.path);
+ const QString selection = QString::fromNSString(m_panel.URL.path).normalized(QString::NormalizationForm_C);
if (selection != m_currentSelection) {
m_currentSelection = selection;
emit m_helper->currentChanged(QUrl::fromLocalFile(selection));
diff --git a/src/plugins/platforms/cocoa/qcocoamessagedialog.mm b/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
index dab348beaa4..7a6f010ba8f 100644
--- a/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
+++ b/src/plugins/platforms/cocoa/qcocoamessagedialog.mm
@@ -88,6 +88,11 @@ bool QCocoaMessageDialog::show(Qt::WindowFlags windowFlags, Qt::WindowModality w
return false;
}
+ // Tahoe has issues with window-modal alert buttons not responding to mouse
+ if (windowModality == Qt::WindowModal
+ && QOperatingSystemVersion::current() >= QOperatingSystemVersion::MacOSTahoe)
+ return false;
+
// And without options we don't know what to show
if (!options())
return false;
diff --git a/src/plugins/platforms/wasm/qwasmaccessibility.cpp b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
index a87c33c8346..5807d157636 100644
--- a/src/plugins/platforms/wasm/qwasmaccessibility.cpp
+++ b/src/plugins/platforms/wasm/qwasmaccessibility.cpp
@@ -586,14 +586,7 @@ void QWasmAccessibility::linkToParent(QAccessibleInterface *iface)
void QWasmAccessibility::setHtmlElementVisibility(QAccessibleInterface *iface, bool visible)
{
emscripten::val element = getHtmlElement(iface);
-
- if (visible) {
- setAttribute(element, "aria-hidden", false);
- setAttribute(element, "tabindex", "");
- } else {
- setAttribute(element, "aria-hidden", true); // aria-hidden mean completely hidden; maybe some sort of soft-hidden should be used.
- setAttribute(element, "tabindex", "-1");
- }
+ setAttribute(element, "aria-hidden", !visible);
}
void QWasmAccessibility::setHtmlElementGeometry(QAccessibleInterface *iface)
diff --git a/src/plugins/platforms/wayland/qwaylandinputcontext.cpp b/src/plugins/platforms/wayland/qwaylandinputcontext.cpp
index 0ccc4dba57a..5ab285ad97d 100644
--- a/src/plugins/platforms/wayland/qwaylandinputcontext.cpp
+++ b/src/plugins/platforms/wayland/qwaylandinputcontext.cpp
@@ -192,10 +192,12 @@ void QWaylandInputContext::setFocusObject(QObject *object)
if (window && window->handle()) {
if (mCurrentWindow.data() != window) {
if (!inputMethodAccepted()) {
- auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
- if (surface)
- inputInterface->disableSurface(surface);
- mCurrentWindow.clear();
+ if (mCurrentWindow) {
+ auto *surface = static_cast<QWaylandWindow *>(mCurrentWindow->handle())->wlSurface();
+ if (surface)
+ inputInterface->disableSurface(surface);
+ mCurrentWindow.clear();
+ }
} else {
auto *surface = static_cast<QWaylandWindow *>(window->handle())->wlSurface();
if (surface) {
diff --git a/src/plugins/platforms/windows/qwindowsiconengine.cpp b/src/plugins/platforms/windows/qwindowsiconengine.cpp
index 71103183183..edc1ea3a9dc 100644
--- a/src/plugins/platforms/windows/qwindowsiconengine.cpp
+++ b/src/plugins/platforms/windows/qwindowsiconengine.cpp
@@ -63,8 +63,8 @@ static QString getGlyphs(QStringView iconName)
{"go-home"_L1, u"\ue80f"},
// {"go-jump"_L1, u"\uf719"},
//{"go-last"_L1, u"\ue5dd"},
- {"go-next"_L1, u"\ue893"},
- {"go-previous"_L1, u"\ue892"},
+ {"go-next"_L1, u"\ue72a"},
+ {"go-previous"_L1, u"\ue72b"},
//{"go-top"_L1, u"\ue25a"},
{"go-up"_L1, u"\ue74a"},
{"help-about"_L1, u"\ue946"},
@@ -100,7 +100,7 @@ static QString getGlyphs(QStringView iconName)
//{"object-flip-vertical"_L1, u"\u"},
{"object-rotate-left"_L1, u"\ue80c"},
{"object-rotate-right"_L1, u"\ue80d"},
- //{"process-stop"_L1, u"\ue5c9"},
+ {"process-stop"_L1, u"\uf140"},
{"system-lock-screen"_L1, u"\uee3f"},
{"system-log-out"_L1, u"\uf3b1"},
//{"system-run"_L1, u"\u"},
diff --git a/src/plugins/platforms/windows/qwindowswindow.cpp b/src/plugins/platforms/windows/qwindowswindow.cpp
index 8e3ab67ced5..72daffb56b1 100644
--- a/src/plugins/platforms/windows/qwindowswindow.cpp
+++ b/src/plugins/platforms/windows/qwindowswindow.cpp
@@ -466,15 +466,17 @@ static bool applyBlurBehindWindow(HWND hwnd)
return result;
}
+static bool shouldShowTitlebarButton(Qt::WindowFlags flags, Qt::WindowFlags button)
+{
+ return !flags.testFlag(Qt::CustomizeWindowHint) || flags.testFlags(Qt::CustomizeWindowHint | button);
+}
+
// from qwidget_win.cpp, pass flags separately in case they have been "autofixed".
static bool shouldShowMaximizeButton(const QWindow *w, Qt::WindowFlags flags)
{
- if ((flags & Qt::MSWindowsFixedSizeDialogHint) || !(flags & Qt::WindowMaximizeButtonHint))
- return false;
- // if the user explicitly asked for the maximize button, we try to add
- // it even if the window has fixed size.
- return (flags & Qt::CustomizeWindowHint) ||
- w->maximumSize() == QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX);
+ return !flags.testFlag(Qt::MSWindowsFixedSizeDialogHint) &&
+ (shouldShowTitlebarButton(flags, Qt::WindowMaximizeButtonHint) ||
+ w->maximumSize() == QSize(QWINDOWSIZE_MAX, QWINDOWSIZE_MAX));
}
bool QWindowsWindow::hasNoNativeFrame(HWND hwnd, Qt::WindowFlags flags)
@@ -805,6 +807,7 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
if (topLevel) {
if ((type == Qt::Window || dialog || tool)) {
+ const bool defaultTitlebar = !flags.testFlag(Qt::CustomizeWindowHint);
if (!(flags & Qt::FramelessWindowHint)) {
style |= WS_POPUP;
if (flags & Qt::MSWindowsFixedSizeDialogHint) {
@@ -812,16 +815,16 @@ void WindowCreationData::fromWindow(const QWindow *w, const Qt::WindowFlags flag
} else {
style |= WS_THICKFRAME;
}
- if (flags & Qt::WindowTitleHint)
+ if (defaultTitlebar || flags.testFlags(Qt::CustomizeWindowHint | Qt::WindowTitleHint))
style |= WS_CAPTION; // Contains WS_DLGFRAME
}
- if (flags & Qt::WindowSystemMenuHint)
+ if (defaultTitlebar || flags.testFlags(Qt::CustomizeWindowHint | Qt::WindowSystemMenuHint))
style |= WS_SYSMENU;
- else if (dialog && (flags & Qt::WindowCloseButtonHint) && !(flags & Qt::FramelessWindowHint)) {
+ else if (dialog && (defaultTitlebar || flags.testFlags(Qt::CustomizeWindowHint | Qt::WindowCloseButtonHint)) && !(flags & Qt::FramelessWindowHint)) {
style |= WS_SYSMENU | WS_BORDER; // QTBUG-2027, dialogs without system menu.
exStyle |= WS_EX_DLGMODALFRAME;
}
- const bool showMinimizeButton = flags & Qt::WindowMinimizeButtonHint;
+ const bool showMinimizeButton = shouldShowTitlebarButton(flags, Qt::WindowMinimizeButtonHint);
if (showMinimizeButton)
style |= WS_MINIMIZEBOX;
const bool showMaximizeButton = shouldShowMaximizeButton(w, flags);
diff --git a/src/plugins/platforms/xcb/CMakeLists.txt b/src/plugins/platforms/xcb/CMakeLists.txt
index 492d274c2fd..204acd72ba0 100644
--- a/src/plugins/platforms/xcb/CMakeLists.txt
+++ b/src/plugins/platforms/xcb/CMakeLists.txt
@@ -120,30 +120,6 @@ qt_internal_extend_target(XcbQpaPrivate CONDITION CLANG
-ftemplate-depth=1024
)
-qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_xcb_native_painting
- SOURCES
- nativepainting/qbackingstore_x11.cpp nativepainting/qbackingstore_x11_p.h
- nativepainting/qcolormap_x11.cpp nativepainting/qcolormap_x11_p.h
- nativepainting/qpaintengine_x11.cpp nativepainting/qpaintengine_x11_p.h
- nativepainting/qpixmap_x11.cpp nativepainting/qpixmap_x11_p.h
- nativepainting/qpolygonclipper_p.h
- nativepainting/qt_x11_p.h
- nativepainting/qtessellator.cpp nativepainting/qtessellator_p.h
- nativepainting/qxcbnativepainting.cpp nativepainting/qxcbnativepainting.h
- INCLUDE_DIRECTORIES
- nativepainting
-)
-
-qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_xcb_native_painting AND QT_FEATURE_xrender
- PUBLIC_LIBRARIES
- PkgConfig::XRender
-)
-
-qt_internal_extend_target(XcbQpaPrivate CONDITION QT_FEATURE_fontconfig AND QT_FEATURE_xcb_native_painting
- LIBRARIES
- WrapFreetype::WrapFreetype
-)
-
if(QT_FEATURE_system_xcb_xinput)
qt_internal_extend_target(XcbQpaPrivate LIBRARIES XCB::XINPUT)
else()
diff --git a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
deleted file mode 100644
index 1ac5f6a64bc..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11.cpp
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#include "qbackingstore_x11_p.h"
-#include "qxcbwindow.h"
-#include "qpixmap_x11_p.h"
-
-#include <private/qhighdpiscaling_p.h>
-#include <QPainter>
-
-#if QT_CONFIG(xrender)
-# include <X11/extensions/Xrender.h>
-#endif
-
-#define register /* C++17 deprecated register */
-#include <X11/Xlib.h>
-#undef register
-
-QT_BEGIN_NAMESPACE
-
-QXcbNativeBackingStore::QXcbNativeBackingStore(QWindow *window)
- : QPlatformBackingStore(window)
- , m_translucentBackground(false)
-{
- if (QXcbWindow *w = static_cast<QXcbWindow *>(window->handle())) {
- m_translucentBackground = w->connection()->hasXRender() &&
- QImage::toPixelFormat(w->imageFormat()).alphaUsage() == QPixelFormat::UsesAlpha;
- }
-}
-
-QXcbNativeBackingStore::~QXcbNativeBackingStore()
-{}
-
-QPaintDevice *QXcbNativeBackingStore::paintDevice()
-{
- return &m_pixmap;
-}
-
-void QXcbNativeBackingStore::flush(QWindow *window, const QRegion &region, const QPoint &offset)
-{
- if (m_pixmap.isNull())
- return;
-
- QSize pixmapSize = m_pixmap.size();
-
- QRegion clipped = region;
- clipped &= QRect(QPoint(), QHighDpi::toNativePixels(window->size(), window));
- clipped &= QRect(0, 0, pixmapSize.width(), pixmapSize.height()).translated(-offset);
-
- QRect br = clipped.boundingRect();
- if (br.isNull())
- return;
-
- QXcbWindow *platformWindow = static_cast<QXcbWindow *>(window->handle());
- if (!platformWindow) {
- qWarning("QXcbBackingStore::flush: QWindow has no platform window (QTBUG-32681)");
- return;
- }
-
- Window wid = platformWindow->xcb_window();
- Pixmap pid = qt_x11PixmapHandle(m_pixmap);
-
- QList<XRectangle> clipRects = qt_region_to_xrectangles(clipped);
-
-#if QT_CONFIG(xrender)
- if (m_translucentBackground)
- {
- XWindowAttributes attrib;
- XGetWindowAttributes(display(), wid, &attrib);
- XRenderPictFormat *format = XRenderFindVisualFormat(display(), attrib.visual);
-
- Picture srcPic = qt_x11PictureHandle(m_pixmap);
- Picture dstPic = XRenderCreatePicture(display(), wid, format, 0, 0);
-
- XRenderSetPictureClipRectangles(display(), dstPic, 0, 0, clipRects.constData(), clipRects.size());
-
- XRenderComposite(display(), PictOpSrc, srcPic, 0L /*None*/, dstPic, br.x() + offset.x(),
- br.y() + offset.y(), 0, 0, br.x(), br.y(), br.width(), br.height());
-
- XRenderFreePicture(display(), dstPic);
- }
- else
-#endif
- {
- GC gc = XCreateGC(display(), wid, 0, nullptr);
-
- if (clipRects.size() != 1)
- XSetClipRectangles(display(), gc, 0, 0, clipRects.data(), clipRects.size(), YXBanded);
-
- XCopyArea(display(), pid, wid, gc, br.x() + offset.x(), br.y() + offset.y(), br.width(), br.height(), br.x(), br.y());
- XFreeGC(display(), gc);
- }
-
-
- if (platformWindow->needsSync()) {
- platformWindow->updateSyncRequestCounter();
- } else {
- XFlush(display());
- }
-}
-
-QImage QXcbNativeBackingStore::toImage() const
-{
- return m_pixmap.toImage();
-}
-
-void QXcbNativeBackingStore::resize(const QSize &size, const QRegion &staticContents)
-{
- if (size == m_pixmap.size())
- return;
-
- QPixmap newPixmap(size);
-
-#if QT_CONFIG(xrender)
- if (m_translucentBackground && newPixmap.depth() != 32)
- qt_x11Pixmap(newPixmap)->convertToARGB32();
-#endif
-
- if (!m_pixmap.isNull()) {
- Pixmap from = qt_x11PixmapHandle(m_pixmap);
- Pixmap to = qt_x11PixmapHandle(newPixmap);
- QRect br = staticContents.boundingRect().intersected(QRect(QPoint(0, 0), size));
-
- if (!br.isEmpty()) {
- GC gc = XCreateGC(display(), to, 0, nullptr);
- XCopyArea(display(), from, to, gc, br.x(), br.y(), br.width(), br.height(), br.x(), br.y());
- XFreeGC(display(), gc);
- }
- }
-
- m_pixmap = newPixmap;
-}
-
-bool QXcbNativeBackingStore::scroll(const QRegion &area, int dx, int dy)
-{
- if (m_pixmap.isNull())
- return false;
-
- QRect rect = area.boundingRect();
- Pixmap pix = qt_x11PixmapHandle(m_pixmap);
-
- GC gc = XCreateGC(display(), pix, 0, nullptr);
- XCopyArea(display(), pix, pix, gc,
- rect.x(), rect.y(), rect.width(), rect.height(),
- rect.x()+dx, rect.y()+dy);
- XFreeGC(display(), gc);
- return true;
-}
-
-void QXcbNativeBackingStore::beginPaint(const QRegion &region)
-{
- QX11PlatformPixmap *x11pm = qt_x11Pixmap(m_pixmap);
- if (x11pm)
- x11pm->setIsBackingStore(true);
-
-#if QT_CONFIG(xrender)
- if (m_translucentBackground) {
- const QList<XRectangle> xrects = qt_region_to_xrectangles(region);
- const XRenderColor color = { 0, 0, 0, 0 };
- XRenderFillRectangles(display(), PictOpSrc,
- qt_x11PictureHandle(m_pixmap), &color,
- xrects.constData(), xrects.size());
- }
-#else
- Q_UNUSED(region);
-#endif
-}
-
-Display *QXcbNativeBackingStore::display() const
-{
- return static_cast<Display *>(static_cast<QXcbWindow *>(window()->handle())->connection()->xlib_display());
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11_p.h
deleted file mode 100644
index b730b076d3f..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qbackingstore_x11_p.h
+++ /dev/null
@@ -1,38 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#pragma once
-
-#include <qpa/qplatformbackingstore.h>
-
-typedef struct _XDisplay Display;
-
-QT_BEGIN_NAMESPACE
-
-class QXcbWindow;
-
-class QXcbNativeBackingStore : public QPlatformBackingStore
-{
-public:
- QXcbNativeBackingStore(QWindow *window);
- ~QXcbNativeBackingStore();
-
- QPaintDevice *paintDevice() override;
- void flush(QWindow *window, const QRegion &region, const QPoint &offset) override;
-
- QImage toImage() const override;
-
- void resize(const QSize &size, const QRegion &staticContents) override;
- bool scroll(const QRegion &area, int dx, int dy) override;
-
- void beginPaint(const QRegion &region) override;
-
-private:
- Display *display() const;
-
- QPixmap m_pixmap;
- bool m_translucentBackground;
-};
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qcolormap_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qcolormap_x11.cpp
deleted file mode 100644
index fddd3e03989..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qcolormap_x11.cpp
+++ /dev/null
@@ -1,615 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#include <QVarLengthArray>
-
-#include <private/qguiapplication_p.h>
-
-#include "qcolormap_x11_p.h"
-#include "qxcbnativepainting.h"
-#include "qt_x11_p.h"
-
-QT_BEGIN_NAMESPACE
-
-class QXcbColormapPrivate
-{
-public:
- QXcbColormapPrivate()
- : ref(1), mode(QXcbColormap::Direct), depth(0),
- colormap(0), defaultColormap(true),
- visual(0), defaultVisual(true),
- r_max(0), g_max(0), b_max(0),
- r_shift(0), g_shift(0), b_shift(0)
- {}
-
- QAtomicInt ref;
-
- QXcbColormap::Mode mode;
- int depth;
-
- Colormap colormap;
- bool defaultColormap;
-
- Visual *visual;
- bool defaultVisual;
-
- int r_max;
- int g_max;
- int b_max;
-
- uint r_shift;
- uint g_shift;
- uint b_shift;
-
- QList<QColor> colors;
- QList<int> pixels;
-};
-
-static uint right_align(uint v)
-{
- while (!(v & 0x1))
- v >>= 1;
- return v;
-}
-
-static int cube_root(int v)
-{
- if (v == 1)
- return 1;
- // brute force algorithm
- int i = 1;
- for (;;) {
- const int b = i * i * i;
- if (b <= v) {
- ++i;
- } else {
- --i;
- break;
- }
- }
- return i;
-}
-
-static Visual *find_visual(Display *display,
- int screen,
- int visual_class,
- int visual_id,
- int *depth,
- bool *defaultVisual)
-{
- XVisualInfo *vi, rvi;
- int count;
-
- uint mask = VisualScreenMask;
- rvi.screen = screen;
-
- if (visual_class != -1) {
- rvi.c_class = visual_class;
- mask |= VisualClassMask;
- }
- if (visual_id != -1) {
- rvi.visualid = visual_id;
- mask |= VisualIDMask;
- }
-
- Visual *visual = DefaultVisual(display, screen);
- *defaultVisual = true;
- *depth = DefaultDepth(display, screen);
-
- vi = XGetVisualInfo(display, mask, &rvi, &count);
- if (vi) {
- int best = 0;
- for (int x = 0; x < count; ++x) {
- if (vi[x].depth > vi[best].depth)
- best = x;
- }
- if (best >= 0 && best <= count && vi[best].visualid != XVisualIDFromVisual(visual)) {
- visual = vi[best].visual;
- *defaultVisual = (visual == DefaultVisual(display, screen));
- *depth = vi[best].depth;
- }
- }
- if (vi)
- XFree((char *)vi);
- return visual;
-}
-
-static void query_colormap(QXcbColormapPrivate *d, int screen)
-{
- Display *display = X11->display;
-
- // query existing colormap
- int q_colors = (((1u << d->depth) > 256u) ? 256u : (1u << d->depth));
- XColor queried[256];
- memset(queried, 0, sizeof(queried));
- for (int x = 0; x < q_colors; ++x)
- queried[x].pixel = x;
- XQueryColors(display, d->colormap, queried, q_colors);
-
- d->colors.resize(q_colors);
- for (int x = 0; x < q_colors; ++x) {
- if (queried[x].red == 0
- && queried[x].green == 0
- && queried[x].blue == 0
- && queried[x].pixel != BlackPixel(display, screen)) {
- // unallocated color cell, skip it
- continue;
- }
-
- d->colors[x] = QColor::fromRgbF(queried[x].red / float(USHRT_MAX),
- queried[x].green / float(USHRT_MAX),
- queried[x].blue / float(USHRT_MAX));
- }
-
- // for missing colors, find the closest color in the existing colormap
- Q_ASSERT(d->pixels.size());
- for (int x = 0; x < d->pixels.size(); ++x) {
- if (d->pixels.at(x) != -1)
- continue;
-
- QRgb rgb;
- if (d->mode == QXcbColormap::Indexed) {
- const int r = (x / (d->g_max * d->b_max)) % d->r_max;
- const int g = (x / d->b_max) % d->g_max;
- const int b = x % d->b_max;
- rgb = qRgb((r * 0xff + (d->r_max - 1) / 2) / (d->r_max - 1),
- (g * 0xff + (d->g_max - 1) / 2) / (d->g_max - 1),
- (b * 0xff + (d->b_max - 1) / 2) / (d->b_max - 1));
- } else {
- rgb = qRgb(x, x, x);
- }
-
- // find closest color
- int mindist = INT_MAX, best = -1;
- for (int y = 0; y < q_colors; ++y) {
- int r = qRed(rgb) - (queried[y].red >> 8);
- int g = qGreen(rgb) - (queried[y].green >> 8);
- int b = qBlue(rgb) - (queried[y].blue >> 8);
- int dist = (r * r) + (g * g) + (b * b);
- if (dist < mindist) {
- mindist = dist;
- best = y;
- }
- }
-
- Q_ASSERT(best >= 0 && best < q_colors);
- if (d->visual->c_class & 1) {
- XColor xcolor;
- xcolor.red = queried[best].red;
- xcolor.green = queried[best].green;
- xcolor.blue = queried[best].blue;
- xcolor.pixel = queried[best].pixel;
-
- if (XAllocColor(display, d->colormap, &xcolor)) {
- d->pixels[x] = xcolor.pixel;
- } else {
- // some weird stuff is going on...
- d->pixels[x] = (qGray(rgb) < 127
- ? BlackPixel(display, screen)
- : WhitePixel(display, screen));
- }
- } else {
- d->pixels[x] = best;
- }
- }
-}
-
-static void init_gray(QXcbColormapPrivate *d, int screen)
-{
- d->pixels.resize(d->r_max);
-
- for (int g = 0; g < d->g_max; ++g) {
- const int gray = (g * 0xff + (d->r_max - 1) / 2) / (d->r_max - 1);
- const QRgb rgb = qRgb(gray, gray, gray);
-
- d->pixels[g] = -1;
-
- if (d->visual->c_class & 1) {
- XColor xcolor;
- xcolor.red = qRed(rgb) * 0x101;
- xcolor.green = qGreen(rgb) * 0x101;
- xcolor.blue = qBlue(rgb) * 0x101;
- xcolor.pixel = 0ul;
-
- if (XAllocColor(X11->display, d->colormap, &xcolor))
- d->pixels[g] = xcolor.pixel;
- }
- }
-
- query_colormap(d, screen);
-}
-
-static void init_indexed(QXcbColormapPrivate *d, int screen)
-{
- d->pixels.resize(d->r_max * d->g_max * d->b_max);
-
- // create color cube
- for (int x = 0, r = 0; r < d->r_max; ++r) {
- for (int g = 0; g < d->g_max; ++g) {
- for (int b = 0; b < d->b_max; ++b, ++x) {
- const QRgb rgb = qRgb((r * 0xff + (d->r_max - 1) / 2) / (d->r_max - 1),
- (g * 0xff + (d->g_max - 1) / 2) / (d->g_max - 1),
- (b * 0xff + (d->b_max - 1) / 2) / (d->b_max - 1));
-
- d->pixels[x] = -1;
-
- if (d->visual->c_class & 1) {
- XColor xcolor;
- xcolor.red = qRed(rgb) * 0x101;
- xcolor.green = qGreen(rgb) * 0x101;
- xcolor.blue = qBlue(rgb) * 0x101;
- xcolor.pixel = 0ul;
-
- if (XAllocColor(X11->display, d->colormap, &xcolor))
- d->pixels[x] = xcolor.pixel;
- }
- }
- }
- }
-
- query_colormap(d, screen);
-}
-
-static void init_direct(QXcbColormapPrivate *d, bool ownColormap)
-{
- if (d->visual->c_class != DirectColor || !ownColormap)
- return;
-
- // preallocate 768 on the stack, so that we don't have to malloc
- // for the common case (<= 24 bpp)
- QVarLengthArray<XColor, 768> colorTable(d->r_max + d->g_max + d->b_max);
- int i = 0;
-
- for (int r = 0; r < d->r_max; ++r) {
- colorTable[i].red = r << 8 | r;
- colorTable[i].pixel = r << d->r_shift;
- colorTable[i].flags = DoRed;
- ++i;
- }
-
- for (int g = 0; g < d->g_max; ++g) {
- colorTable[i].green = g << 8 | g;
- colorTable[i].pixel = g << d->g_shift;
- colorTable[i].flags = DoGreen;
- ++i;
- }
-
- for (int b = 0; b < d->b_max; ++b) {
- colorTable[i].blue = (b << 8 | b);
- colorTable[i].pixel = b << d->b_shift;
- colorTable[i].flags = DoBlue;
- ++i;
- }
-
- XStoreColors(X11->display, d->colormap, colorTable.data(), colorTable.count());
-}
-
-static QXcbColormap **cmaps = nullptr;
-
-void QXcbColormap::initialize()
-{
- Display *display = X11->display;
- const int screens = ScreenCount(display);
-
- cmaps = new QXcbColormap*[screens];
-
- for (int i = 0; i < screens; ++i) {
- cmaps[i] = new QXcbColormap;
- QXcbColormapPrivate * const d = cmaps[i]->d;
-
- bool use_stdcmap = false;
- int color_count = X11->color_count;
-
- // defaults
- d->depth = DefaultDepth(display, i);
- d->colormap = DefaultColormap(display, i);
- d->defaultColormap = true;
- d->visual = DefaultVisual(display, i);
- d->defaultVisual = true;
-
- Visual *argbVisual = nullptr;
-
- if (X11->visual && i == DefaultScreen(display)) {
- // only use the outside colormap on the default screen
- d->visual = find_visual(display, i, X11->visual->c_class,
- XVisualIDFromVisual(X11->visual),
- &d->depth, &d->defaultVisual);
- } else if ((X11->visual_class != -1 && X11->visual_class >= 0 && X11->visual_class < 6)
- || (X11->visual_id != -1)) {
- // look for a specific visual or type of visual
- d->visual = find_visual(display, i, X11->visual_class, X11->visual_id,
- &d->depth, &d->defaultVisual);
- } else if (!X11->custom_cmap) {
- XStandardColormap *stdcmap = nullptr;
- int ncmaps = 0;
-
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- int nvi;
- XVisualInfo templ;
- templ.screen = i;
- templ.depth = 32;
- templ.c_class = TrueColor;
- XVisualInfo *xvi = XGetVisualInfo(X11->display, VisualScreenMask |
- VisualDepthMask |
- VisualClassMask, &templ, &nvi);
- for (int idx = 0; idx < nvi; ++idx) {
- XRenderPictFormat *format = XRenderFindVisualFormat(X11->display,
- xvi[idx].visual);
- if (format->type == PictTypeDirect && format->direct.alphaMask) {
- argbVisual = xvi[idx].visual;
- break;
- }
- }
- XFree(xvi);
- }
-#endif
- if (XGetRGBColormaps(display, RootWindow(display, i),
- &stdcmap, &ncmaps, XA_RGB_DEFAULT_MAP)) {
- if (stdcmap) {
- for (int c = 0; c < ncmaps; ++c) {
- if (!stdcmap[c].red_max ||
- !stdcmap[c].green_max ||
- !stdcmap[c].blue_max ||
- !stdcmap[c].red_mult ||
- !stdcmap[c].green_mult ||
- !stdcmap[c].blue_mult)
- continue; // invalid stdcmap
-
- XVisualInfo proto;
- proto.visualid = stdcmap[c].visualid;
- proto.screen = i;
-
- int nvisuals = 0;
- XVisualInfo *vi = XGetVisualInfo(display, VisualIDMask | VisualScreenMask,
- &proto, &nvisuals);
- if (vi) {
- if (nvisuals > 0) {
- use_stdcmap = true;
-
- d->mode = ((vi[0].visual->c_class < StaticColor)
- ? Gray
- : ((vi[0].visual->c_class < TrueColor)
- ? Indexed
- : Direct));
-
- d->depth = vi[0].depth;
- d->colormap = stdcmap[c].colormap;
- d->defaultColormap = true;
- d->visual = vi[0].visual;
- d->defaultVisual = (d->visual == DefaultVisual(display, i));
-
- d->r_max = stdcmap[c].red_max + 1;
- d->g_max = stdcmap[c].green_max + 1;
- d->b_max = stdcmap[c].blue_max + 1;
-
- if (d->mode == Direct) {
- // calculate offsets
- d->r_shift = lowest_bit(d->visual->red_mask);
- d->g_shift = lowest_bit(d->visual->green_mask);
- d->b_shift = lowest_bit(d->visual->blue_mask);
- } else {
- d->r_shift = 0;
- d->g_shift = 0;
- d->b_shift = 0;
- }
- }
- XFree(vi);
- }
- break;
- }
- XFree(stdcmap);
- }
- }
- }
- if (!use_stdcmap) {
- switch (d->visual->c_class) {
- case StaticGray:
- d->mode = Gray;
-
- d->r_max = d->g_max = d->b_max = d->visual->map_entries;
- break;
-
- case XGrayScale:
- d->mode = Gray;
-
- // follow precedent set in libXmu...
- if (color_count != 0)
- d->r_max = d->g_max = d->b_max = color_count;
- else if (d->visual->map_entries > 65000)
- d->r_max = d->g_max = d->b_max = 4096;
- else if (d->visual->map_entries > 4000)
- d->r_max = d->g_max = d->b_max = 512;
- else if (d->visual->map_entries > 250)
- d->r_max = d->g_max = d->b_max = 12;
- else
- d->r_max = d->g_max = d->b_max = 4;
- break;
-
- case StaticColor:
- d->mode = Indexed;
-
- d->r_max = right_align(d->visual->red_mask) + 1;
- d->g_max = right_align(d->visual->green_mask) + 1;
- d->b_max = right_align(d->visual->blue_mask) + 1;
- break;
-
- case PseudoColor:
- d->mode = Indexed;
-
- // follow precedent set in libXmu...
- if (color_count != 0)
- d->r_max = d->g_max = d->b_max = cube_root(color_count);
- else if (d->visual->map_entries > 65000)
- d->r_max = d->g_max = d->b_max = 27;
- else if (d->visual->map_entries > 4000)
- d->r_max = d->g_max = d->b_max = 12;
- else if (d->visual->map_entries > 250)
- d->r_max = d->g_max = d->b_max = cube_root(d->visual->map_entries - 125);
- else
- d->r_max = d->g_max = d->b_max = cube_root(d->visual->map_entries);
- break;
-
- case TrueColor:
- case DirectColor:
- d->mode = Direct;
-
- d->r_max = right_align(d->visual->red_mask) + 1;
- d->g_max = right_align(d->visual->green_mask) + 1;
- d->b_max = right_align(d->visual->blue_mask) + 1;
-
- d->r_shift = lowest_bit(d->visual->red_mask);
- d->g_shift = lowest_bit(d->visual->green_mask);
- d->b_shift = lowest_bit(d->visual->blue_mask);
- break;
- }
- }
-
- bool ownColormap = false;
- if (X11->colormap && i == DefaultScreen(display)) {
- // only use the outside colormap on the default screen
- d->colormap = X11->colormap;
- d->defaultColormap = (d->colormap == DefaultColormap(display, i));
- } else if ((!use_stdcmap
- && (((d->visual->c_class & 1) && X11->custom_cmap)
- || d->visual != DefaultVisual(display, i)))
- || d->visual->c_class == DirectColor) {
- // allocate custom colormap (we always do this when using DirectColor visuals)
- d->colormap =
- XCreateColormap(display, RootWindow(display, i), d->visual,
- d->visual->c_class == DirectColor ? AllocAll : AllocNone);
- d->defaultColormap = false;
- ownColormap = true;
- }
-
- switch (d->mode) {
- case Gray:
- init_gray(d, i);
- break;
- case Indexed:
- init_indexed(d, i);
- break;
- case Direct:
- init_direct(d, ownColormap);
- break;
- }
-
- QX11InfoData *screen = X11->screens + i;
- screen->depth = d->depth;
- screen->visual = d->visual;
- screen->defaultVisual = d->defaultVisual;
- screen->colormap = d->colormap;
- screen->defaultColormap = d->defaultColormap;
- screen->cells = screen->visual->map_entries;
-
- if (argbVisual) {
- X11->argbVisuals[i] = argbVisual;
- X11->argbColormaps[i] = XCreateColormap(display, RootWindow(display, i), argbVisual, AllocNone);
- }
-
- // ###
- // We assume that 8bpp == pseudocolor, but this is not
- // always the case (according to the X server), so we need
- // to make sure that our internal data is setup in a way
- // that is compatible with our assumptions
- if (screen->visual->c_class == TrueColor && screen->depth == 8 && screen->cells == 8)
- screen->cells = 256;
- }
-}
-
-void QXcbColormap::cleanup()
-{
- Display *display = X11->display;
- const int screens = ScreenCount(display);
-
- for (int i = 0; i < screens; ++i)
- delete cmaps[i];
-
- delete [] cmaps;
- cmaps = 0;
-}
-
-
-QXcbColormap QXcbColormap::instance(int screen)
-{
- if (screen == -1)
- screen = QXcbX11Info::appScreen();
- return *cmaps[screen];
-}
-
-/*! \internal
- Constructs a new colormap.
-*/
-QXcbColormap::QXcbColormap()
- : d(new QXcbColormapPrivate)
-{}
-
-QXcbColormap::QXcbColormap(const QXcbColormap &colormap)
- :d (colormap.d)
-{ d->ref.ref(); }
-
-QXcbColormap::~QXcbColormap()
-{
- if (!d->ref.deref()) {
- if (!d->defaultColormap)
- XFreeColormap(X11->display, d->colormap);
- delete d;
- }
-}
-
-QXcbColormap::Mode QXcbColormap::mode() const
-{ return d->mode; }
-
-int QXcbColormap::depth() const
-{ return d->depth; }
-
-int QXcbColormap::size() const
-{
- return (d->mode == Gray
- ? d->r_max
- : (d->mode == Indexed
- ? d->r_max * d->g_max * d->b_max
- : -1));
-}
-
-uint QXcbColormap::pixel(const QColor &color) const
-{
- const QRgba64 rgba64 = color.rgba64();
- // XXX We emulate the raster engine here by getting the
- // 8-bit values, but we could instead use the 16-bit
- // values for slightly better color accuracy
- const uint r = (rgba64.red8() * d->r_max) >> 8;
- const uint g = (rgba64.green8() * d->g_max) >> 8;
- const uint b = (rgba64.blue8() * d->b_max) >> 8;
- if (d->mode != Direct) {
- if (d->mode == Gray)
- return d->pixels.at((r * 30 + g * 59 + b * 11) / 100);
- return d->pixels.at(r * d->g_max * d->b_max + g * d->b_max + b);
- }
- return (r << d->r_shift) + (g << d->g_shift) + (b << d->b_shift);
-}
-
-const QColor QXcbColormap::colorAt(uint pixel) const
-{
- if (d->mode != Direct) {
- Q_ASSERT(pixel <= (uint)d->colors.size());
- return d->colors.at(pixel);
- }
-
- const int r = (((pixel & d->visual->red_mask) >> d->r_shift) << 8) / d->r_max;
- const int g = (((pixel & d->visual->green_mask) >> d->g_shift) << 8) / d->g_max;
- const int b = (((pixel & d->visual->blue_mask) >> d->b_shift) << 8) / d->b_max;
- return QColor(r, g, b);
-}
-
-const QList<QColor> QXcbColormap::colormap() const
-{ return d->colors; }
-
-QXcbColormap &QXcbColormap::operator=(const QXcbColormap &colormap)
-{
- qAtomicAssign(d, colormap.d);
- return *this;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qcolormap_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qcolormap_x11_p.h
deleted file mode 100644
index 9c9cce424c9..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qcolormap_x11_p.h
+++ /dev/null
@@ -1,43 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#pragma once
-
-#include <QColor>
-#include <QList>
-
-QT_BEGIN_NAMESPACE
-
-class QXcbColormapPrivate;
-class QXcbColormap
-{
-public:
- enum Mode { Direct, Indexed, Gray };
-
- static void initialize();
- static void cleanup();
-
- static QXcbColormap instance(int screen = -1);
-
- QXcbColormap(const QXcbColormap &colormap);
- ~QXcbColormap();
-
- QXcbColormap &operator=(const QXcbColormap &colormap);
-
- Mode mode() const;
-
- int depth() const;
- int size() const;
-
- uint pixel(const QColor &color) const;
- const QColor colorAt(uint pixel) const;
-
- const QList<QColor> colormap() const;
-
-private:
- QXcbColormap();
- QXcbColormapPrivate *d;
-};
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
deleted file mode 100644
index 2f3827025f3..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11.cpp
+++ /dev/null
@@ -1,2807 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#include <QtCore/qrandom.h>
-
-#include <private/qpixmapcache_p.h>
-#include <private/qpaintengine_p.h>
-#include <private/qpainterpath_p.h>
-#include <private/qdrawhelper_p.h>
-#include <private/qfontengineglyphcache_p.h>
-
-#if QT_CONFIG(fontconfig)
-#include <private/qfontengine_ft_p.h>
-#endif
-
-#include "qpaintengine_x11_p.h"
-#include "qpolygonclipper_p.h"
-#include "qtessellator_p.h"
-#include "qpixmap_x11_p.h"
-#include "qcolormap_x11_p.h"
-#include "qt_x11_p.h"
-#include "qxcbexport.h"
-#include "qxcbnativepainting.h"
-
-QT_BEGIN_NAMESPACE
-
-using namespace Qt::StringLiterals;
-
-#if QT_CONFIG(xrender)
-
-class QXRenderTessellator : public QTessellator
-{
-public:
- QXRenderTessellator() : traps(0), allocated(0), size(0) {}
- ~QXRenderTessellator() { free(traps); }
- XTrapezoid *traps;
- int allocated;
- int size;
- void addTrap(const Trapezoid &trap) override;
- QRect tessellate(const QPointF *points, int nPoints, bool winding) {
- size = 0;
- setWinding(winding);
- return QTessellator::tessellate(points, nPoints).toRect();
- }
- void done() {
- if (allocated > 64) {
- free(traps);
- traps = 0;
- allocated = 0;
- }
- }
-};
-
-void QXRenderTessellator::addTrap(const Trapezoid &trap)
-{
- if (size == allocated) {
- allocated = qMax(2*allocated, 64);
- traps = q_check_ptr((XTrapezoid *)realloc(traps, allocated * sizeof(XTrapezoid)));
- }
- traps[size].top = Q27Dot5ToXFixed(trap.top);
- traps[size].bottom = Q27Dot5ToXFixed(trap.bottom);
- traps[size].left.p1.x = Q27Dot5ToXFixed(trap.topLeft->x);
- traps[size].left.p1.y = Q27Dot5ToXFixed(trap.topLeft->y);
- traps[size].left.p2.x = Q27Dot5ToXFixed(trap.bottomLeft->x);
- traps[size].left.p2.y = Q27Dot5ToXFixed(trap.bottomLeft->y);
- traps[size].right.p1.x = Q27Dot5ToXFixed(trap.topRight->x);
- traps[size].right.p1.y = Q27Dot5ToXFixed(trap.topRight->y);
- traps[size].right.p2.x = Q27Dot5ToXFixed(trap.bottomRight->x);
- traps[size].right.p2.y = Q27Dot5ToXFixed(trap.bottomRight->y);
- ++size;
-}
-
-#endif // QT_CONFIG(xrender)
-
-class QX11PaintEnginePrivate : public QPaintEnginePrivate
-{
- Q_DECLARE_PUBLIC(QX11PaintEngine)
-public:
- QX11PaintEnginePrivate()
- {
- opacity = 1.0;
- scrn = -1;
- hd = 0;
- picture = 0;
- gc = gc_brush = 0;
- dpy = 0;
- xinfo = 0;
- txop = QTransform::TxNone;
- has_clipping = false;
- render_hints = 0;
- xform_scale = 1;
-#if QT_CONFIG(xrender)
- tessellator = 0;
-#endif
- }
- enum GCMode {
- PenGC,
- BrushGC
- };
-
- void init();
- void fillPolygon_translated(const QPointF *points, int pointCount, GCMode gcMode,
- QPaintEngine::PolygonDrawMode mode);
- void fillPolygon_dev(const QPointF *points, int pointCount, GCMode gcMode,
- QPaintEngine::PolygonDrawMode mode);
- void fillPath(const QPainterPath &path, GCMode gcmode, bool transform);
- void strokePolygon_dev(const QPointF *points, int pointCount, bool close);
- void strokePolygon_translated(const QPointF *points, int pointCount, bool close);
- void setupAdaptedOrigin(const QPoint &p);
- void resetAdaptedOrigin();
- void decidePathFallback() {
- use_path_fallback = has_alpha_brush
- || has_alpha_pen
- || has_custom_pen
- || has_complex_xform
- || (render_hints & QPainter::Antialiasing);
- }
- void decideCoordAdjust() {
- adjust_coords = false;
- }
- void clipPolygon_dev(const QPolygonF &poly, QPolygonF *clipped_poly);
- void systemStateChanged() override;
- inline bool isCosmeticPen() const {
- return cpen.isCosmetic();
- }
-
- Display *dpy;
- int scrn;
- int pdev_depth;
- unsigned long hd;
- QPixmap brush_pm;
-#if QT_CONFIG(xrender)
- unsigned long picture;
- unsigned long current_brush;
- QPixmap bitmap_texture;
- int composition_mode;
-#else
- unsigned long picture;
-#endif
- GC gc;
- GC gc_brush;
-
- QPen cpen;
- QBrush cbrush;
- QRegion crgn;
- QTransform matrix;
- qreal opacity;
-
- uint has_complex_xform : 1;
- uint has_scaling_xform : 1;
- uint has_non_scaling_xform : 1;
- uint has_custom_pen : 1;
- uint use_path_fallback : 1;
- uint adjust_coords : 1;
- uint has_clipping : 1;
- uint adapted_brush_origin : 1;
- uint adapted_pen_origin : 1;
- uint has_pen : 1;
- uint has_brush : 1;
- uint has_texture : 1;
- uint has_alpha_texture : 1;
- uint has_pattern : 1;
- uint has_alpha_pen : 1;
- uint has_alpha_brush : 1;
- uint use_sysclip : 1;
- uint render_hints;
-
- const QXcbX11Info *xinfo;
- QPointF bg_origin;
- QTransform::TransformationType txop;
- qreal xform_scale;
-
- struct qt_float_point
- {
- qreal x, y;
- };
- QPolygonClipper<qt_float_point, qt_float_point, float> polygonClipper;
-
- int xlibMaxLinePoints;
-#if QT_CONFIG(xrender)
- QXRenderTessellator *tessellator;
-#endif
-};
-
-#if QT_CONFIG(xrender)
-class QXRenderGlyphCache : public QFontEngineGlyphCache
-{
-public:
- QXRenderGlyphCache(QXcbX11Info x, QFontEngine::GlyphFormat format, const QTransform &matrix);
- ~QXRenderGlyphCache();
-
- bool addGlyphs(const QTextItemInt &ti,
- const QVarLengthArray<glyph_t> &glyphs,
- const QVarLengthArray<QFixedPoint> &positions);
- bool draw(Drawable src, Drawable dst, const QTransform &matrix, const QTextItemInt &ti);
-
- inline GlyphSet glyphSet();
- inline int glyphBufferSize(const QFontEngineFT::Glyph &glyph) const;
-
- inline QImage::Format imageFormat() const;
- inline const XRenderPictFormat *renderPictFormat() const;
-
- static inline QFontEngine::GlyphFormat glyphFormatForDepth(QFontEngine *fontEngine, int depth);
- static inline Glyph glyphId(glyph_t glyph, QFixed subPixelPosition);
-
- static inline bool isValidCoordinate(const QFixedPoint &fp);
-
-private:
- QXcbX11Info xinfo;
- GlyphSet gset;
- QSet<Glyph> cachedGlyphs;
-};
-#endif // QT_CONFIG(xrender)
-
-extern QPixmap qt_pixmapForBrush(int brushStyle, bool invert); //in qbrush.cpp
-extern QPixmap qt_toX11Pixmap(const QPixmap &pixmap);
-
-extern "C" {
-Q_XCB_EXPORT Drawable qt_x11Handle(const QPaintDevice *pd)
-{
- if (!pd)
- return 0;
-
-// if (pd->devType() == QInternal::Widget)
-// return static_cast<const QWidget *>(pd)->handle();
-
- if (pd->devType() == QInternal::Pixmap)
- return qt_x11PixmapHandle(*static_cast<const QPixmap *>(pd));
-
- return 0;
-}
-}
-
-static const QXcbX11Info *qt_x11Info(const QPaintDevice *pd)
-{
- if (!pd)
- return 0;
-
-// if (pd->devType() == QInternal::Widget)
-// return &static_cast<const QWidget *>(pd)->x11Info();
-
- if (pd->devType() == QInternal::Pixmap)
- return &qt_x11Info(*static_cast<const QPixmap *>(pd));
-
- return 0;
-}
-
-// use the same rounding as in qrasterizer.cpp (6 bit fixed point)
-static const qreal aliasedCoordinateDelta = 0.5 - 0.015625;
-
-#undef X11 // defined in qt_x11_p.h
-extern "C" {
-/*!
- Returns the X11 specific pen GC for the painter \a p. Note that
- QPainter::begin() must be called before this function returns a
- valid GC.
-*/
-GC Q_XCB_EXPORT qt_x11_get_pen_gc(QPainter *p)
-{
- if (p && p->paintEngine()
- && p->paintEngine()->isActive()
- && p->paintEngine()->type() == QPaintEngine::X11) {
- return static_cast<QX11PaintEngine *>(p->paintEngine())->d_func()->gc;
- }
- return 0;
-}
-
-/*!
- Returns the X11 specific brush GC for the painter \a p. Note that
- QPainter::begin() must be called before this function returns a
- valid GC.
-*/
-GC Q_XCB_EXPORT qt_x11_get_brush_gc(QPainter *p)
-{
- if (p && p->paintEngine()
- && p->paintEngine()->isActive()
- && p->paintEngine()->type() == QPaintEngine::X11) {
- return static_cast<QX11PaintEngine *>(p->paintEngine())->d_func()->gc_brush;
- }
- return 0;
-}
-}
-#define X11 qt_x11Data
-
-// internal helper. Converts an integer value to an unique string token
-template <typename T>
- struct HexString
-{
- inline HexString(const T t)
- : val(t)
- {}
-
- inline void write(QChar *&dest) const
- {
- const ushort hexChars[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f' };
- const char *c = reinterpret_cast<const char *>(&val);
- for (uint i = 0; i < sizeof(T); ++i) {
- *dest++ = hexChars[*c & 0xf];
- *dest++ = hexChars[(*c & 0xf0) >> 4];
- ++c;
- }
- }
- const T val;
-};
-
-// specialization to enable fast concatenating of our string tokens to a string
-template <typename T>
- struct QConcatenable<HexString<T> >
-{
- typedef HexString<T> type;
- enum { ExactSize = true };
- static int size(const HexString<T> &) { return sizeof(T) * 2; }
- static inline void appendTo(const HexString<T> &str, QChar *&out) { str.write(out); }
- typedef QString ConvertTo;
-};
-
-#if QT_CONFIG(xrender)
-static const int compositionModeToRenderOp[QPainter::CompositionMode_Xor + 1] = {
- PictOpOver, //CompositionMode_SourceOver,
- PictOpOverReverse, //CompositionMode_DestinationOver,
- PictOpClear, //CompositionMode_Clear,
- PictOpSrc, //CompositionMode_Source,
- PictOpDst, //CompositionMode_Destination,
- PictOpIn, //CompositionMode_SourceIn,
- PictOpInReverse, //CompositionMode_DestinationIn,
- PictOpOut, //CompositionMode_SourceOut,
- PictOpOutReverse, //CompositionMode_DestinationOut,
- PictOpAtop, //CompositionMode_SourceAtop,
- PictOpAtopReverse, //CompositionMode_DestinationAtop,
- PictOpXor //CompositionMode_Xor
-};
-
-static inline int qpainterOpToXrender(QPainter::CompositionMode mode)
-{
- Q_ASSERT(mode <= QPainter::CompositionMode_Xor);
- return compositionModeToRenderOp[mode];
-}
-
-static inline bool complexPictOp(int op)
-{
- return op != PictOpOver && op != PictOpSrc;
-}
-#endif
-
-static inline void x11SetClipRegion(Display *dpy, GC gc, GC gc2,
-#if QT_CONFIG(xrender)
- Picture picture,
-#else
- Qt::HANDLE picture,
-#endif
- const QRegion &r)
-{
-// int num;
-// XRectangle *rects = (XRectangle *)qt_getClipRects(r, num);
- QList<XRectangle> rects = qt_region_to_xrectangles(r);
- int num = rects.size();
-
- if (gc)
- XSetClipRectangles( dpy, gc, 0, 0, rects.data(), num, Unsorted );
- if (gc2)
- XSetClipRectangles( dpy, gc2, 0, 0, rects.data(), num, Unsorted );
-
-#if QT_CONFIG(xrender)
- if (picture)
- XRenderSetPictureClipRectangles(dpy, picture, 0, 0, rects.data(), num);
-#else
- Q_UNUSED(picture);
-#endif // QT_CONFIG(xrender)
-}
-
-
-static inline void x11ClearClipRegion(Display *dpy, GC gc, GC gc2,
-#if QT_CONFIG(xrender)
- Picture picture
-#else
- Qt::HANDLE picture
-#endif
- )
-{
- if (gc)
- XSetClipMask(dpy, gc, XNone);
- if (gc2)
- XSetClipMask(dpy, gc2, XNone);
-
-#if QT_CONFIG(xrender)
- if (picture) {
- XRenderPictureAttributes attrs;
- attrs.clip_mask = XNone;
- XRenderChangePicture (dpy, picture, CPClipMask, &attrs);
- }
-#else
- Q_UNUSED(picture);
-#endif // QT_CONFIG(xrender)
-}
-
-
-#define DITHER_SIZE 16
-static const uchar base_dither_matrix[DITHER_SIZE][DITHER_SIZE] = {
- { 0,192, 48,240, 12,204, 60,252, 3,195, 51,243, 15,207, 63,255 },
- { 128, 64,176,112,140, 76,188,124,131, 67,179,115,143, 79,191,127 },
- { 32,224, 16,208, 44,236, 28,220, 35,227, 19,211, 47,239, 31,223 },
- { 160, 96,144, 80,172,108,156, 92,163, 99,147, 83,175,111,159, 95 },
- { 8,200, 56,248, 4,196, 52,244, 11,203, 59,251, 7,199, 55,247 },
- { 136, 72,184,120,132, 68,180,116,139, 75,187,123,135, 71,183,119 },
- { 40,232, 24,216, 36,228, 20,212, 43,235, 27,219, 39,231, 23,215 },
- { 168,104,152, 88,164,100,148, 84,171,107,155, 91,167,103,151, 87 },
- { 2,194, 50,242, 14,206, 62,254, 1,193, 49,241, 13,205, 61,253 },
- { 130, 66,178,114,142, 78,190,126,129, 65,177,113,141, 77,189,125 },
- { 34,226, 18,210, 46,238, 30,222, 33,225, 17,209, 45,237, 29,221 },
- { 162, 98,146, 82,174,110,158, 94,161, 97,145, 81,173,109,157, 93 },
- { 10,202, 58,250, 6,198, 54,246, 9,201, 57,249, 5,197, 53,245 },
- { 138, 74,186,122,134, 70,182,118,137, 73,185,121,133, 69,181,117 },
- { 42,234, 26,218, 38,230, 22,214, 41,233, 25,217, 37,229, 21,213 },
- { 170,106,154, 90,166,102,150, 86,169,105,153, 89,165,101,149, 85 }
-};
-
-static QPixmap qt_patternForAlpha(uchar alpha, int screen)
-{
- QPixmap pm;
- QString key = "$qt-alpha-brush$"_L1
- % HexString<uchar>(alpha)
- % HexString<int>(screen);
-
- if (!QPixmapCache::find(key, &pm)) {
- // #### why not use a mono image here????
- QImage pattern(DITHER_SIZE, DITHER_SIZE, QImage::Format_ARGB32);
- pattern.fill(0xffffffff);
- for (int y = 0; y < DITHER_SIZE; ++y) {
- for (int x = 0; x < DITHER_SIZE; ++x) {
- if (base_dither_matrix[x][y] <= alpha)
- pattern.setPixel(x, y, 0x00000000);
- }
- }
- pm = QBitmap::fromImage(pattern);
- qt_x11SetScreen(pm, screen);
- //pm.x11SetScreen(screen);
- QPixmapCache::insert(key, pm);
- }
- return pm;
-}
-
-
-#if QT_CONFIG(xrender)
-static Picture getPatternFill(int screen, const QBrush &b)
-{
- if (!X11->use_xrender)
- return XNone;
-
- XRenderColor color = X11->preMultiply(b.color());
- XRenderColor bg_color;
-
- bg_color = X11->preMultiply(QColor(0, 0, 0, 0));
-
- for (int i = 0; i < X11->pattern_fill_count; ++i) {
- if (X11->pattern_fills[i].screen == screen
- && X11->pattern_fills[i].opaque == false
- && X11->pattern_fills[i].style == b.style()
- && X11->pattern_fills[i].color.alpha == color.alpha
- && X11->pattern_fills[i].color.red == color.red
- && X11->pattern_fills[i].color.green == color.green
- && X11->pattern_fills[i].color.blue == color.blue
- && X11->pattern_fills[i].bg_color.alpha == bg_color.alpha
- && X11->pattern_fills[i].bg_color.red == bg_color.red
- && X11->pattern_fills[i].bg_color.green == bg_color.green
- && X11->pattern_fills[i].bg_color.blue == bg_color.blue)
- return X11->pattern_fills[i].picture;
- }
- // none found, replace one
- int i = QRandomGenerator::global()->generate() % 16;
-
- if (X11->pattern_fills[i].screen != screen && X11->pattern_fills[i].picture) {
- XRenderFreePicture (QXcbX11Info::display(), X11->pattern_fills[i].picture);
- X11->pattern_fills[i].picture = 0;
- }
-
- if (!X11->pattern_fills[i].picture) {
- Pixmap pixmap = XCreatePixmap (QXcbX11Info::display(), RootWindow (QXcbX11Info::display(), screen), 8, 8, 32);
- XRenderPictureAttributes attrs;
- attrs.repeat = True;
- X11->pattern_fills[i].picture = XRenderCreatePicture (QXcbX11Info::display(), pixmap,
- XRenderFindStandardFormat(QXcbX11Info::display(), PictStandardARGB32),
- CPRepeat, &attrs);
- XFreePixmap (QXcbX11Info::display(), pixmap);
- }
-
- X11->pattern_fills[i].screen = screen;
- X11->pattern_fills[i].color = color;
- X11->pattern_fills[i].bg_color = bg_color;
- X11->pattern_fills[i].opaque = false;
- X11->pattern_fills[i].style = b.style();
-
- XRenderFillRectangle(QXcbX11Info::display(), PictOpSrc, X11->pattern_fills[i].picture, &bg_color, 0, 0, 8, 8);
-
- QPixmap pattern(qt_pixmapForBrush(b.style(), true));
- XRenderPictureAttributes attrs;
- attrs.repeat = true;
- XRenderChangePicture(QXcbX11Info::display(), qt_x11PictureHandle(pattern), CPRepeat, &attrs);
-
- Picture fill_fg = X11->getSolidFill(screen, b.color());
- XRenderComposite(QXcbX11Info::display(), PictOpOver, fill_fg, qt_x11PictureHandle(pattern),
- X11->pattern_fills[i].picture,
- 0, 0, 0, 0, 0, 0, 8, 8);
-
- return X11->pattern_fills[i].picture;
-}
-
-static void qt_render_bitmap(Display *dpy, int scrn, Picture src, Picture dst,
- int sx, int sy, int x, int y, int sw, int sh,
- const QPen &pen)
-{
- Picture fill_fg = X11->getSolidFill(scrn, pen.color());
- XRenderComposite(dpy, PictOpOver,
- fill_fg, src, dst, sx, sy, sx, sy, x, y, sw, sh);
-}
-#endif
-
-void QX11PaintEnginePrivate::init()
-{
- dpy = 0;
- scrn = 0;
- hd = 0;
- picture = 0;
- xinfo = 0;
-#if QT_CONFIG(xrender)
- current_brush = 0;
- composition_mode = PictOpOver;
- tessellator = new QXRenderTessellator;
-#endif
-}
-
-void QX11PaintEnginePrivate::setupAdaptedOrigin(const QPoint &p)
-{
- if (adapted_pen_origin)
- XSetTSOrigin(dpy, gc, p.x(), p.y());
- if (adapted_brush_origin)
- XSetTSOrigin(dpy, gc_brush, p.x(), p.y());
-}
-
-void QX11PaintEnginePrivate::resetAdaptedOrigin()
-{
- if (adapted_pen_origin)
- XSetTSOrigin(dpy, gc, 0, 0);
- if (adapted_brush_origin)
- XSetTSOrigin(dpy, gc_brush, 0, 0);
-}
-
-void QX11PaintEnginePrivate::clipPolygon_dev(const QPolygonF &poly, QPolygonF *clipped_poly)
-{
- int clipped_count = 0;
- qt_float_point *clipped_points = 0;
- polygonClipper.clipPolygon((qt_float_point *) poly.data(), poly.size(),
- &clipped_points, &clipped_count);
- clipped_poly->resize(clipped_count);
- for (int i=0; i<clipped_count; ++i)
- (*clipped_poly)[i] = *((QPointF *)(&clipped_points[i]));
-}
-
-void QX11PaintEnginePrivate::systemStateChanged()
-{
- Q_Q(QX11PaintEngine);
- QPainter *painter = q->state ? q->state->painter() : nullptr;
- if (painter && painter->hasClipping()) {
- if (q->testDirty(QPaintEngine::DirtyTransform))
- q->updateMatrix(q->state->transform());
- QPolygonF clip_poly_dev(matrix.map(painter->clipPath().toFillPolygon()));
- QPolygonF clipped_poly_dev;
- clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
- q->updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), Qt::ReplaceClip);
- } else {
- q->updateClipRegion_dev(QRegion(), Qt::NoClip);
- }
-}
-
-static QPaintEngine::PaintEngineFeatures qt_decide_features()
-{
- QPaintEngine::PaintEngineFeatures features =
- QPaintEngine::PrimitiveTransform
- | QPaintEngine::PatternBrush
- | QPaintEngine::AlphaBlend
- | QPaintEngine::PainterPaths
- | QPaintEngine::RasterOpModes;
-
- if (X11->use_xrender) {
- features |= QPaintEngine::Antialiasing;
- features |= QPaintEngine::PorterDuff;
- features |= QPaintEngine::MaskedBrush;
-#if 0
- if (X11->xrender_version > 10) {
- features |= QPaintEngine::LinearGradientFill;
- // ###
- }
-#endif
- }
-
- return features;
-}
-
-/*
- * QX11PaintEngine members
- */
-
-QX11PaintEngine::QX11PaintEngine()
- : QPaintEngine(*(new QX11PaintEnginePrivate), qt_decide_features())
-{
- Q_D(QX11PaintEngine);
- d->init();
-}
-
-QX11PaintEngine::QX11PaintEngine(QX11PaintEnginePrivate &dptr)
- : QPaintEngine(dptr, qt_decide_features())
-{
- Q_D(QX11PaintEngine);
- d->init();
-}
-
-QX11PaintEngine::~QX11PaintEngine()
-{
-#if QT_CONFIG(xrender)
- Q_D(QX11PaintEngine);
- delete d->tessellator;
-#endif
-}
-
-bool QX11PaintEngine::begin(QPaintDevice *pdev)
-{
- Q_D(QX11PaintEngine);
- d->xinfo = qt_x11Info(pdev);
-#if QT_CONFIG(xrender)
- if (pdev->devType() == QInternal::Pixmap) {
- const QPixmap *pm = static_cast<const QPixmap *>(pdev);
- QX11PlatformPixmap *data = static_cast<QX11PlatformPixmap*>(pm->handle());
- if (X11->use_xrender && data->depth() != 32 && data->x11_mask)
- data->convertToARGB32();
- d->picture = qt_x11PictureHandle(*static_cast<const QPixmap *>(pdev));
- }
-#else
- d->picture = 0;
-#endif
- d->hd = qt_x11Handle(pdev);
-
- Q_ASSERT(d->xinfo != 0);
- d->dpy = d->xinfo->display(); // get display variable
- d->scrn = d->xinfo->screen(); // get screen variable
-
- d->crgn = QRegion();
- d->gc = XCreateGC(d->dpy, d->hd, 0, 0);
- d->gc_brush = XCreateGC(d->dpy, d->hd, 0, 0);
- d->has_alpha_brush = false;
- d->has_alpha_pen = false;
- d->has_clipping = false;
- d->has_complex_xform = false;
- d->has_scaling_xform = false;
- d->has_non_scaling_xform = true;
- d->xform_scale = 1;
- d->has_custom_pen = false;
- d->matrix = QTransform();
- d->pdev_depth = d->pdev->depth();
- d->render_hints = 0;
- d->txop = QTransform::TxNone;
- d->use_path_fallback = false;
-#if QT_CONFIG(xrender)
- d->composition_mode = PictOpOver;
-#endif
- d->xlibMaxLinePoints = 32762; // a safe number used to avoid, call to XMaxRequestSize(d->dpy) - 3;
- d->opacity = 1;
-
- QX11PlatformPixmap *x11pm = paintDevice()->devType() == QInternal::Pixmap ? qt_x11Pixmap(*static_cast<QPixmap *>(paintDevice())) : nullptr;
- d->use_sysclip = paintDevice()->devType() == QInternal::Widget || (x11pm ? x11pm->isBackingStore() : false);
-
- // Set up the polygon clipper. Note: This will only work in
- // polyline mode as long as we have a buffer zone, since a
- // polyline may be clipped into several non-connected polylines.
- const int BUFFERZONE = 1000;
- QRect devClipRect(-BUFFERZONE, -BUFFERZONE,
- pdev->width() + 2*BUFFERZONE, pdev->height() + 2*BUFFERZONE);
- d->polygonClipper.setBoundingRect(devClipRect);
-
- setSystemClip(systemClip());
- d->systemStateChanged();
-
- qt_x11SetDefaultScreen(d->xinfo->screen());
-
- updatePen(QPen(Qt::black));
- updateBrush(QBrush(Qt::white), QPoint());
-
- setDirty(QPaintEngine::DirtyClipRegion);
- setDirty(QPaintEngine::DirtyPen);
- setDirty(QPaintEngine::DirtyBrush);
- setDirty(QPaintEngine::DirtyBackground);
-
- setActive(true);
- return true;
-}
-
-bool QX11PaintEngine::end()
-{
- Q_D(QX11PaintEngine);
-
-#if QT_CONFIG(xrender)
- if (d->picture) {
- // reset clipping/subwindow mode on our render picture
- XRenderPictureAttributes attrs;
- attrs.subwindow_mode = ClipByChildren;
- attrs.clip_mask = XNone;
- XRenderChangePicture(d->dpy, d->picture, CPClipMask|CPSubwindowMode, &attrs);
- }
-#endif
-
- if (d->gc_brush && d->pdev->painters < 2) {
- XFreeGC(d->dpy, d->gc_brush);
- d->gc_brush = 0;
- }
-
- if (d->gc && d->pdev->painters < 2) {
- XFreeGC(d->dpy, d->gc);
- d->gc = 0;
- }
-
- // Restore system clip for alien widgets painting outside the paint event.
-// if (d->pdev->devType() == QInternal::Widget && !static_cast<QWidget *>(d->pdev)->internalWinId())
- d->currentClipDevice = nullptr;
- setSystemClip(QRegion());
-
- setActive(false);
- return true;
-}
-
-static bool clipLine(QLineF *line, const QRect &rect)
-{
- qreal x1 = line->x1();
- qreal x2 = line->x2();
- qreal y1 = line->y1();
- qreal y2 = line->y2();
-
- qreal left = rect.x();
- qreal right = rect.x() + rect.width() - 1;
- qreal top = rect.y();
- qreal bottom = rect.y() + rect.height() - 1;
-
- enum { Left, Right, Top, Bottom };
- // clip the lines, after cohen-sutherland, see e.g. http://www.nondot.org/~sabre/graphpro/line6.html
- int p1 = ((x1 < left) << Left)
- | ((x1 > right) << Right)
- | ((y1 < top) << Top)
- | ((y1 > bottom) << Bottom);
- int p2 = ((x2 < left) << Left)
- | ((x2 > right) << Right)
- | ((y2 < top) << Top)
- | ((y2 > bottom) << Bottom);
-
- if (p1 & p2)
- // completely outside
- return false;
-
- if (p1 | p2) {
- qreal dx = x2 - x1;
- qreal dy = y2 - y1;
-
- // clip x coordinates
- if (x1 < left) {
- y1 += dy/dx * (left - x1);
- x1 = left;
- } else if (x1 > right) {
- y1 -= dy/dx * (x1 - right);
- x1 = right;
- }
- if (x2 < left) {
- y2 += dy/dx * (left - x2);
- x2 = left;
- } else if (x2 > right) {
- y2 -= dy/dx * (x2 - right);
- x2 = right;
- }
- p1 = ((y1 < top) << Top)
- | ((y1 > bottom) << Bottom);
- p2 = ((y2 < top) << Top)
- | ((y2 > bottom) << Bottom);
- if (p1 & p2)
- return false;
- // clip y coordinates
- if (y1 < top) {
- x1 += dx/dy * (top - y1);
- y1 = top;
- } else if (y1 > bottom) {
- x1 -= dx/dy * (y1 - bottom);
- y1 = bottom;
- }
- if (y2 < top) {
- x2 += dx/dy * (top - y2);
- y2 = top;
- } else if (y2 > bottom) {
- x2 -= dx/dy * (y2 - bottom);
- y2 = bottom;
- }
- *line = QLineF(QPointF(x1, y1), QPointF(x2, y2));
- }
- return true;
-}
-
-void QX11PaintEngine::drawLines(const QLine *lines, int lineCount)
-{
- Q_ASSERT(lines);
- Q_ASSERT(lineCount);
- Q_D(QX11PaintEngine);
-
- if (d->has_alpha_brush
- || d->has_alpha_pen
- || d->has_custom_pen
- || (d->cpen.widthF() > 0 && d->has_complex_xform
- && !d->has_non_scaling_xform)
- || (d->render_hints & QPainter::Antialiasing)) {
- for (int i = 0; i < lineCount; ++i) {
- QPainterPath path(lines[i].p1());
- path.lineTo(lines[i].p2());
- drawPath(path);
- }
- return;
- }
-
- if (d->has_pen) {
- for (int i = 0; i < lineCount; ++i) {
- QLineF linef;
- if (d->txop == QTransform::TxNone) {
- linef = lines[i];
- } else {
- linef = d->matrix.map(QLineF(lines[i]));
- }
- if (clipLine(&linef, d->polygonClipper.boundingRect())) {
- int x1 = qRound(linef.x1() + aliasedCoordinateDelta);
- int y1 = qRound(linef.y1() + aliasedCoordinateDelta);
- int x2 = qRound(linef.x2() + aliasedCoordinateDelta);
- int y2 = qRound(linef.y2() + aliasedCoordinateDelta);
-
- XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2);
- }
- }
- }
-}
-
-void QX11PaintEngine::drawLines(const QLineF *lines, int lineCount)
-{
- Q_ASSERT(lines);
- Q_ASSERT(lineCount);
- Q_D(QX11PaintEngine);
-
- if (d->has_alpha_brush
- || d->has_alpha_pen
- || d->has_custom_pen
- || (d->cpen.widthF() > 0 && d->has_complex_xform
- && !d->has_non_scaling_xform)
- || (d->render_hints & QPainter::Antialiasing)) {
- for (int i = 0; i < lineCount; ++i) {
- QPainterPath path(lines[i].p1());
- path.lineTo(lines[i].p2());
- drawPath(path);
- }
- return;
- }
-
- if (d->has_pen) {
- for (int i = 0; i < lineCount; ++i) {
- QLineF linef = d->matrix.map(lines[i]);
- if (clipLine(&linef, d->polygonClipper.boundingRect())) {
- int x1 = qRound(linef.x1() + aliasedCoordinateDelta);
- int y1 = qRound(linef.y1() + aliasedCoordinateDelta);
- int x2 = qRound(linef.x2() + aliasedCoordinateDelta);
- int y2 = qRound(linef.y2() + aliasedCoordinateDelta);
-
- XDrawLine(d->dpy, d->hd, d->gc, x1, y1, x2, y2);
- }
- }
- }
-}
-
-static inline QLine clipStraightLine(const QRect &clip, const QLine &l)
-{
- if (l.p1().x() == l.p2().x()) {
- int x = qBound(clip.left(), l.p1().x(), clip.right());
- int y1 = qBound(clip.top(), l.p1().y(), clip.bottom());
- int y2 = qBound(clip.top(), l.p2().y(), clip.bottom());
-
- return QLine(x, y1, x, y2);
- } else {
- Q_ASSERT(l.p1().y() == l.p2().y());
-
- int x1 = qBound(clip.left(), l.p1().x(), clip.right());
- int x2 = qBound(clip.left(), l.p2().x(), clip.right());
- int y = qBound(clip.top(), l.p1().y(), clip.bottom());
-
- return QLine(x1, y, x2, y);
- }
-}
-
-void QX11PaintEngine::drawRects(const QRectF *rects, int rectCount)
-{
- Q_D(QX11PaintEngine);
- Q_ASSERT(rects);
- Q_ASSERT(rectCount);
-
- if (rectCount != 1
- || d->has_pen
- || d->has_alpha_brush
- || d->has_complex_xform
- || d->has_custom_pen
- || d->cbrush.style() != Qt::SolidPattern
-#if QT_CONFIG(xrender)
- || complexPictOp(d->composition_mode)
-#endif
- )
- {
- QPaintEngine::drawRects(rects, rectCount);
- return;
- }
-
- QPoint alignedOffset;
- if (d->txop == QTransform::TxTranslate) {
- QPointF offset(d->matrix.dx(), d->matrix.dy());
- alignedOffset = offset.toPoint();
- if (offset != QPointF(alignedOffset)) {
- QPaintEngine::drawRects(rects, rectCount);
- return;
- }
- }
-
- const QRectF& r = rects[0];
- QRect alignedRect = r.toAlignedRect();
- if (r != QRectF(alignedRect)) {
- QPaintEngine::drawRects(rects, rectCount);
- return;
- }
- alignedRect.translate(alignedOffset);
-
- QRect clip(d->polygonClipper.boundingRect());
- alignedRect = alignedRect.intersected(clip);
- if (alignedRect.isEmpty())
- return;
-
- // simple-case:
- // the rectangle is pixel-aligned
- // the fill brush is just a solid non-alpha color
- // the painter transform is only integer translation
- // ignore: antialiasing and just XFillRectangles directly
- XRectangle xrect;
- xrect.x = short(alignedRect.x());
- xrect.y = short(alignedRect.y());
- xrect.width = ushort(alignedRect.width());
- xrect.height = ushort(alignedRect.height());
- XFillRectangles(d->dpy, d->hd, d->gc_brush, &xrect, 1);
-}
-
-void QX11PaintEngine::drawRects(const QRect *rects, int rectCount)
-{
- Q_D(QX11PaintEngine);
- Q_ASSERT(rects);
- Q_ASSERT(rectCount);
-
- if (d->has_alpha_pen
- || d->has_complex_xform
- || d->has_custom_pen
- || (d->render_hints & QPainter::Antialiasing))
- {
- for (int i = 0; i < rectCount; ++i) {
- QPainterPath path;
- path.addRect(rects[i]);
- drawPath(path);
- }
- return;
- }
-
- QRect clip(d->polygonClipper.boundingRect());
- QPoint offset(qRound(d->matrix.dx()), qRound(d->matrix.dy()));
-#if QT_CONFIG(xrender)
- ::Picture pict = d->picture;
-
- if (X11->use_xrender && pict && d->has_brush && d->pdev_depth != 1
- && (d->has_texture || d->has_alpha_brush || complexPictOp(d->composition_mode)))
- {
- XRenderColor xc;
- if (!d->has_texture && !d->has_pattern)
- xc = X11->preMultiply(d->cbrush.color());
-
- for (int i = 0; i < rectCount; ++i) {
- QRect r(rects[i]);
- if (d->txop == QTransform::TxTranslate)
- r.translate(offset);
-
- if (r.width() == 0 || r.height() == 0) {
- if (d->has_pen) {
- const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height()));
- XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y());
- }
- continue;
- }
-
- r = r.intersected(clip);
- if (r.isEmpty())
- continue;
- if (d->has_texture || d->has_pattern) {
- XRenderComposite(d->dpy, d->composition_mode, d->current_brush, 0, pict,
- qRound(r.x() - d->bg_origin.x()), qRound(r.y() - d->bg_origin.y()),
- 0, 0, r.x(), r.y(), r.width(), r.height());
- } else {
- XRenderFillRectangle(d->dpy, d->composition_mode, pict, &xc, r.x(), r.y(), r.width(), r.height());
- }
- if (d->has_pen)
- XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height());
- }
- } else
-#endif // QT_CONFIG(xrender)
- {
- if (d->has_brush && d->has_pen) {
- for (int i = 0; i < rectCount; ++i) {
- QRect r(rects[i]);
- if (d->txop == QTransform::TxTranslate)
- r.translate(offset);
-
- if (r.width() == 0 || r.height() == 0) {
- const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height()));
- XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y());
- continue;
- }
-
- r = r.intersected(clip);
- if (r.isEmpty())
- continue;
- d->setupAdaptedOrigin(r.topLeft());
- XFillRectangle(d->dpy, d->hd, d->gc_brush, r.x(), r.y(), r.width(), r.height());
- XDrawRectangle(d->dpy, d->hd, d->gc, r.x(), r.y(), r.width(), r.height());
- }
- d->resetAdaptedOrigin();
- } else {
- QVarLengthArray<XRectangle> xrects(rectCount);
- int numClipped = rectCount;
- for (int i = 0; i < rectCount; ++i) {
- QRect r(rects[i]);
- if (d->txop == QTransform::TxTranslate)
- r.translate(offset);
-
- if (r.width() == 0 || r.height() == 0) {
- --numClipped;
- if (d->has_pen) {
- const QLine l = clipStraightLine(clip, QLine(r.left(), r.top(), r.left() + r.width(), r.top() + r.height()));
- XDrawLine(d->dpy, d->hd, d->gc, l.p1().x(), l.p1().y(), l.p2().x(), l.p2().y());
- }
- continue;
- }
-
- r = r.intersected(clip);
- if (r.isEmpty()) {
- --numClipped;
- continue;
- }
- xrects[i].x = short(r.x());
- xrects[i].y = short(r.y());
- xrects[i].width = ushort(r.width());
- xrects[i].height = ushort(r.height());
- }
- if (numClipped) {
- d->setupAdaptedOrigin(rects[0].topLeft());
- if (d->has_brush)
- XFillRectangles(d->dpy, d->hd, d->gc_brush, xrects.data(), numClipped);
- else if (d->has_pen)
- XDrawRectangles(d->dpy, d->hd, d->gc, xrects.data(), numClipped);
- d->resetAdaptedOrigin();
- }
- }
- }
-}
-
-static inline void setCapStyle(int cap_style, GC gc)
-{
- ulong mask = GCCapStyle;
- XGCValues vals;
- vals.cap_style = cap_style;
- XChangeGC(QXcbX11Info::display(), gc, mask, &vals);
-}
-
-void QX11PaintEngine::drawPoints(const QPoint *points, int pointCount)
-{
- Q_ASSERT(points);
- Q_ASSERT(pointCount);
- Q_D(QX11PaintEngine);
-
- if (!d->has_pen)
- return;
-
- // use the same test here as in drawPath to ensure that we don't use the path fallback
- // and end up in XDrawLines for pens with width <= 1
- if (d->cpen.widthF() > 1.0f
- || (X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing)))
- || (!d->isCosmeticPen() && d->txop > QTransform::TxTranslate))
- {
- Qt::PenCapStyle capStyle = d->cpen.capStyle();
- if (capStyle == Qt::FlatCap) {
- setCapStyle(CapProjecting, d->gc);
- d->cpen.setCapStyle(Qt::SquareCap);
- }
- const QPoint *end = points + pointCount;
- while (points < end) {
- QPainterPath path;
- path.moveTo(*points);
- path.lineTo(points->x()+.005, points->y());
- drawPath(path);
- ++points;
- }
-
- if (capStyle == Qt::FlatCap) {
- setCapStyle(CapButt, d->gc);
- d->cpen.setCapStyle(capStyle);
- }
- return;
- }
-
- static const int BUF_SIZE = 1024;
- XPoint xPoints[BUF_SIZE];
- int i = 0, j = 0;
- while (i < pointCount) {
- while (i < pointCount && j < BUF_SIZE) {
- const QPoint &xformed = d->matrix.map(points[i]);
- int x = xformed.x();
- int y = xformed.y();
- if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) {
- xPoints[j].x = x;
- xPoints[j].y = y;
- ++j;
- }
- ++i;
- }
- if (j)
- XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin);
-
- j = 0;
- }
-}
-
-void QX11PaintEngine::drawPoints(const QPointF *points, int pointCount)
-{
- Q_ASSERT(points);
- Q_ASSERT(pointCount);
- Q_D(QX11PaintEngine);
-
- if (!d->has_pen)
- return;
-
- // use the same test here as in drawPath to ensure that we don't use the path fallback
- // and end up in XDrawLines for pens with width <= 1
- if (d->cpen.widthF() > 1.0f
- || (X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing)))
- || (!d->isCosmeticPen() && d->txop > QTransform::TxTranslate))
- {
- Qt::PenCapStyle capStyle = d->cpen.capStyle();
- if (capStyle == Qt::FlatCap) {
- setCapStyle(CapProjecting, d->gc);
- d->cpen.setCapStyle(Qt::SquareCap);
- }
-
- const QPointF *end = points + pointCount;
- while (points < end) {
- QPainterPath path;
- path.moveTo(*points);
- path.lineTo(points->x() + 0.005, points->y());
- drawPath(path);
- ++points;
- }
- if (capStyle == Qt::FlatCap) {
- setCapStyle(CapButt, d->gc);
- d->cpen.setCapStyle(capStyle);
- }
- return;
- }
-
- static const int BUF_SIZE = 1024;
- XPoint xPoints[BUF_SIZE];
- int i = 0, j = 0;
- while (i < pointCount) {
- while (i < pointCount && j < BUF_SIZE) {
- const QPointF &xformed = d->matrix.map(points[i]);
- int x = qFloor(xformed.x());
- int y = qFloor(xformed.y());
-
- if (x >= SHRT_MIN && y >= SHRT_MIN && x < SHRT_MAX && y < SHRT_MAX) {
- xPoints[j].x = x;
- xPoints[j].y = y;
- ++j;
- }
- ++i;
- }
- if (j)
- XDrawPoints(d->dpy, d->hd, d->gc, xPoints, j, CoordModeOrigin);
-
- j = 0;
- }
-}
-
-QPainter::RenderHints QX11PaintEngine::supportedRenderHints() const
-{
-#if QT_CONFIG(xrender)
- if (X11->use_xrender)
- return QPainter::Antialiasing;
-#endif
- return QFlag(0);
-}
-
-void QX11PaintEngine::updateState(const QPaintEngineState &state)
-{
- Q_D(QX11PaintEngine);
- QPaintEngine::DirtyFlags flags = state.state();
-
-
- if (flags & DirtyOpacity) {
- d->opacity = state.opacity();
- // Force update pen/brush as to get proper alpha colors propagated
- flags |= DirtyPen;
- flags |= DirtyBrush;
- }
-
- if (flags & DirtyTransform) updateMatrix(state.transform());
- if (flags & DirtyPen) updatePen(state.pen());
- if (flags & (DirtyBrush | DirtyBrushOrigin)) updateBrush(state.brush(), state.brushOrigin());
- if (flags & DirtyFont) updateFont(state.font());
-
- if (state.state() & DirtyClipEnabled) {
- if (state.isClipEnabled()) {
- QPolygonF clip_poly_dev(d->matrix.map(painter()->clipPath().toFillPolygon()));
- QPolygonF clipped_poly_dev;
- d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
- updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), Qt::ReplaceClip);
- } else {
- updateClipRegion_dev(QRegion(), Qt::NoClip);
- }
- }
-
- if (flags & DirtyClipPath) {
- QPolygonF clip_poly_dev(d->matrix.map(state.clipPath().toFillPolygon()));
- QPolygonF clipped_poly_dev;
- d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
- updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon(), state.clipPath().fillRule()),
- state.clipOperation());
- } else if (flags & DirtyClipRegion) {
- extern QPainterPath qt_regionToPath(const QRegion &region);
- QPainterPath clip_path = qt_regionToPath(state.clipRegion());
- QPolygonF clip_poly_dev(d->matrix.map(clip_path.toFillPolygon()));
- QPolygonF clipped_poly_dev;
- d->clipPolygon_dev(clip_poly_dev, &clipped_poly_dev);
- updateClipRegion_dev(QRegion(clipped_poly_dev.toPolygon()), state.clipOperation());
- }
- if (flags & DirtyHints) updateRenderHints(state.renderHints());
- if (flags & DirtyCompositionMode) {
- int function = GXcopy;
- if (state.compositionMode() >= QPainter::RasterOp_SourceOrDestination) {
- switch (state.compositionMode()) {
- case QPainter::RasterOp_SourceOrDestination:
- function = GXor;
- break;
- case QPainter::RasterOp_SourceAndDestination:
- function = GXand;
- break;
- case QPainter::RasterOp_SourceXorDestination:
- function = GXxor;
- break;
- case QPainter::RasterOp_NotSourceAndNotDestination:
- function = GXnor;
- break;
- case QPainter::RasterOp_NotSourceOrNotDestination:
- function = GXnand;
- break;
- case QPainter::RasterOp_NotSourceXorDestination:
- function = GXequiv;
- break;
- case QPainter::RasterOp_NotSource:
- function = GXcopyInverted;
- break;
- case QPainter::RasterOp_SourceAndNotDestination:
- function = GXandReverse;
- break;
- case QPainter::RasterOp_NotSourceAndDestination:
- function = GXandInverted;
- break;
- default:
- function = GXcopy;
- }
- }
-#if QT_CONFIG(xrender)
- else {
- d->composition_mode =
- qpainterOpToXrender(state.compositionMode());
- }
-#endif
- XSetFunction(X11->display, d->gc, function);
- XSetFunction(X11->display, d->gc_brush, function);
- }
- d->decidePathFallback();
- d->decideCoordAdjust();
-}
-
-void QX11PaintEngine::updateRenderHints(QPainter::RenderHints hints)
-{
- Q_D(QX11PaintEngine);
- d->render_hints = hints;
-
-#if QT_CONFIG(xrender)
- if (X11->use_xrender && d->picture) {
- XRenderPictureAttributes attrs;
- attrs.poly_edge = (hints & QPainter::Antialiasing) ? PolyEdgeSmooth : PolyEdgeSharp;
- XRenderChangePicture(d->dpy, d->picture, CPPolyEdge, &attrs);
- }
-#endif
-}
-
-void QX11PaintEngine::updatePen(const QPen &pen)
-{
- Q_D(QX11PaintEngine);
- d->cpen = pen;
- int cp = CapButt;
- int jn = JoinMiter;
- int ps = pen.style();
-
- if (d->opacity < 1.0) {
- QColor c = d->cpen.color();
- c.setAlpha(qRound(c.alpha()*d->opacity));
- d->cpen.setColor(c);
- }
-
- d->has_pen = (ps != Qt::NoPen);
- d->has_alpha_pen = (pen.color().alpha() != 255);
-
- switch (pen.capStyle()) {
- case Qt::SquareCap:
- cp = CapProjecting;
- break;
- case Qt::RoundCap:
- cp = CapRound;
- break;
- case Qt::FlatCap:
- default:
- cp = CapButt;
- break;
- }
- switch (pen.joinStyle()) {
- case Qt::BevelJoin:
- jn = JoinBevel;
- break;
- case Qt::RoundJoin:
- jn = JoinRound;
- break;
- case Qt::MiterJoin:
- default:
- jn = JoinMiter;
- break;
- }
-
- d->adapted_pen_origin = false;
-
- char dashes[10]; // custom pen dashes
- int dash_len = 0; // length of dash list
- int xStyle = LineSolid;
-
- /*
- We are emulating Windows here. Windows treats cpen.width() == 1
- (or 0) as a very special case. The fudge variable unifies this
- case with the general case.
- */
- qreal pen_width = pen.widthF();
- int scale = qRound(pen_width < 1 ? 1 : pen_width);
- int space = (pen_width < 1 && pen_width > 0 ? 1 : (2 * scale));
- int dot = 1 * scale;
- int dash = 4 * scale;
-
- d->has_custom_pen = false;
-
- switch (ps) {
- case Qt::NoPen:
- case Qt::SolidLine:
- xStyle = LineSolid;
- break;
- case Qt::DashLine:
- dashes[0] = dash;
- dashes[1] = space;
- dash_len = 2;
- xStyle = LineOnOffDash;
- break;
- case Qt::DotLine:
- dashes[0] = dot;
- dashes[1] = space;
- dash_len = 2;
- xStyle = LineOnOffDash;
- break;
- case Qt::DashDotLine:
- dashes[0] = dash;
- dashes[1] = space;
- dashes[2] = dot;
- dashes[3] = space;
- dash_len = 4;
- xStyle = LineOnOffDash;
- break;
- case Qt::DashDotDotLine:
- dashes[0] = dash;
- dashes[1] = space;
- dashes[2] = dot;
- dashes[3] = space;
- dashes[4] = dot;
- dashes[5] = space;
- dash_len = 6;
- xStyle = LineOnOffDash;
- break;
- case Qt::CustomDashLine:
- d->has_custom_pen = true;
- break;
- }
-
- ulong mask = GCForeground | GCBackground | GCGraphicsExposures | GCLineWidth
- | GCCapStyle | GCJoinStyle | GCLineStyle;
- XGCValues vals;
- vals.graphics_exposures = false;
- if (d->pdev_depth == 1) {
- vals.foreground = qGray(pen.color().rgb()) > 127 ? 0 : 1;
- vals.background = qGray(QColor(Qt::transparent).rgb()) > 127 ? 0 : 1;
- } else if (d->pdev->devType() == QInternal::Pixmap && d->pdev_depth == 32
- && X11->use_xrender) {
- vals.foreground = pen.color().rgba();
- vals.background = QColor(Qt::transparent).rgba();
- } else {
- QXcbColormap cmap = QXcbColormap::instance(d->scrn);
- vals.foreground = cmap.pixel(pen.color());
- vals.background = cmap.pixel(QColor(Qt::transparent));
- }
-
-
- vals.line_width = qRound(pen.widthF());
- vals.cap_style = cp;
- vals.join_style = jn;
- vals.line_style = xStyle;
-
- XChangeGC(d->dpy, d->gc, mask, &vals);
-
- if (dash_len) { // make dash list
- XSetDashes(d->dpy, d->gc, 0, dashes, dash_len);
- }
-
- if (!d->has_clipping) { // if clipping is set the paintevent clip region is merged with the clip region
- QRegion sysClip = d->use_sysclip ? systemClip() : QRegion();
- if (!sysClip.isEmpty())
- x11SetClipRegion(d->dpy, d->gc, 0, d->picture, sysClip);
- else
- x11ClearClipRegion(d->dpy, d->gc, 0, d->picture);
- }
-}
-
-void QX11PaintEngine::updateBrush(const QBrush &brush, const QPointF &origin)
-{
- Q_D(QX11PaintEngine);
- d->cbrush = brush;
- d->bg_origin = origin;
- d->adapted_brush_origin = false;
-#if QT_CONFIG(xrender)
- d->current_brush = 0;
-#endif
- if (d->opacity < 1.0) {
- QColor c = d->cbrush.color();
- c.setAlpha(qRound(c.alpha()*d->opacity));
- d->cbrush.setColor(c);
- }
-
- int s = FillSolid;
- int bs = d->cbrush.style();
- d->has_brush = (bs != Qt::NoBrush);
- d->has_pattern = bs >= Qt::Dense1Pattern && bs <= Qt::DiagCrossPattern;
- d->has_texture = bs == Qt::TexturePattern;
- d->has_alpha_brush = brush.color().alpha() != 255;
- d->has_alpha_texture = d->has_texture && d->cbrush.texture().hasAlphaChannel();
-
- ulong mask = GCForeground | GCBackground | GCGraphicsExposures
- | GCLineStyle | GCCapStyle | GCJoinStyle | GCFillStyle;
- XGCValues vals;
- vals.graphics_exposures = false;
- if (d->pdev_depth == 1) {
- vals.foreground = qGray(d->cbrush.color().rgb()) > 127 ? 0 : 1;
- vals.background = qGray(QColor(Qt::transparent).rgb()) > 127 ? 0 : 1;
- } else if (X11->use_xrender && d->pdev->devType() == QInternal::Pixmap
- && d->pdev_depth == 32) {
- vals.foreground = d->cbrush.color().rgba();
- vals.background = QColor(Qt::transparent).rgba();
- } else {
- QXcbColormap cmap = QXcbColormap::instance(d->scrn);
- vals.foreground = cmap.pixel(d->cbrush.color());
- vals.background = cmap.pixel(QColor(Qt::transparent));
-
- if (!X11->use_xrender && d->has_brush && !d->has_pattern && !brush.isOpaque()) {
- QPixmap pattern = qt_patternForAlpha(brush.color().alpha(), d->scrn);
- mask |= GCStipple;
- vals.stipple = qt_x11PixmapHandle(pattern);
- s = FillStippled;
- d->adapted_brush_origin = true;
- }
- }
- vals.cap_style = CapButt;
- vals.join_style = JoinMiter;
- vals.line_style = LineSolid;
-
- if (d->has_pattern || d->has_texture) {
- if (bs == Qt::TexturePattern) {
- d->brush_pm = qt_toX11Pixmap(d->cbrush.texture());
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- XRenderPictureAttributes attrs;
- attrs.repeat = true;
- XRenderChangePicture(d->dpy, qt_x11PictureHandle(d->brush_pm), CPRepeat, &attrs);
- QX11PlatformPixmap *data = static_cast<QX11PlatformPixmap*>(d->brush_pm.handle());
- if (data->mask_picture)
- XRenderChangePicture(d->dpy, data->mask_picture, CPRepeat, &attrs);
- }
-#endif
- } else {
- d->brush_pm = qt_toX11Pixmap(qt_pixmapForBrush(bs, true));
- }
- qt_x11SetScreen(d->brush_pm, d->scrn);
- if (d->brush_pm.depth() == 1) {
- mask |= GCStipple;
- vals.stipple = qt_x11PixmapHandle(d->brush_pm);
- s = FillStippled;
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- d->bitmap_texture = QPixmap(d->brush_pm.size());
- d->bitmap_texture.fill(Qt::transparent);
- d->bitmap_texture = qt_toX11Pixmap(d->bitmap_texture);
- qt_x11SetScreen(d->bitmap_texture, d->scrn);
-
- ::Picture src = X11->getSolidFill(d->scrn, d->cbrush.color());
- XRenderComposite(d->dpy, PictOpSrc, src, qt_x11PictureHandle(d->brush_pm),
- qt_x11PictureHandle(d->bitmap_texture),
- 0, 0, d->brush_pm.width(), d->brush_pm.height(),
- 0, 0, d->brush_pm.width(), d->brush_pm.height());
-
- XRenderPictureAttributes attrs;
- attrs.repeat = true;
- XRenderChangePicture(d->dpy, qt_x11PictureHandle(d->bitmap_texture), CPRepeat, &attrs);
-
- d->current_brush = qt_x11PictureHandle(d->bitmap_texture);
- }
-#endif
- } else {
- mask |= GCTile;
-#if QT_CONFIG(xrender)
- if (d->pdev_depth == 32 && d->brush_pm.depth() != 32) {
- d->brush_pm.detach();
- QX11PlatformPixmap *brushData = static_cast<QX11PlatformPixmap*>(d->brush_pm.handle());
- brushData->convertToARGB32();
- }
-#endif
- vals.tile = (d->brush_pm.depth() == d->pdev_depth
- ? qt_x11PixmapHandle(d->brush_pm)
- : static_cast<QX11PlatformPixmap*>(d->brush_pm.handle())->x11ConvertToDefaultDepth());
- s = FillTiled;
-#if QT_CONFIG(xrender)
- d->current_brush = qt_x11PictureHandle(d->cbrush.texture());
-#endif
- }
-
- mask |= GCTileStipXOrigin | GCTileStipYOrigin;
- vals.ts_x_origin = qRound(origin.x());
- vals.ts_y_origin = qRound(origin.y());
- }
-#if QT_CONFIG(xrender)
- else if (d->has_alpha_brush) {
- d->current_brush = X11->getSolidFill(d->scrn, d->cbrush.color());
- }
-#endif
-
- vals.fill_style = s;
- XChangeGC(d->dpy, d->gc_brush, mask, &vals);
- if (!d->has_clipping) {
- QRegion sysClip = d->use_sysclip ? systemClip() : QRegion();
- if (!sysClip.isEmpty())
- x11SetClipRegion(d->dpy, d->gc_brush, 0, d->picture, sysClip);
- else
- x11ClearClipRegion(d->dpy, d->gc_brush, 0, d->picture);
- }
-}
-
-void QX11PaintEngine::drawEllipse(const QRectF &rect)
-{
- QRect aligned = rect.toAlignedRect();
- if (aligned == rect)
- drawEllipse(aligned);
- else
- QPaintEngine::drawEllipse(rect);
-}
-
-void QX11PaintEngine::drawEllipse(const QRect &rect)
-{
- if (rect.isEmpty()) {
- drawRects(&rect, 1);
- return;
- }
-
- Q_D(QX11PaintEngine);
- QRect devclip(SHRT_MIN, SHRT_MIN, SHRT_MAX*2 - 1, SHRT_MAX*2 - 1);
- QRect r(rect);
- if (d->txop < QTransform::TxRotate) {
- r = d->matrix.mapRect(rect);
- } else if (d->txop == QTransform::TxRotate && rect.width() == rect.height()) {
- QPainterPath path;
- path.addEllipse(rect);
- r = d->matrix.map(path).boundingRect().toRect();
- }
-
- if (d->has_alpha_brush || d->has_alpha_pen || d->has_custom_pen || (d->render_hints & QPainter::Antialiasing)
- || d->has_alpha_texture || devclip.intersected(r) != r
- || (d->has_complex_xform
- && !(d->has_non_scaling_xform && rect.width() == rect.height())))
- {
- QPainterPath path;
- path.addEllipse(rect);
- drawPath(path);
- return;
- }
-
- int x = r.x();
- int y = r.y();
- int w = r.width();
- int h = r.height();
- if (w < 1 || h < 1)
- return;
- if (w == 1 && h == 1) {
- XDrawPoint(d->dpy, d->hd, d->has_pen ? d->gc : d->gc_brush, x, y);
- return;
- }
- d->setupAdaptedOrigin(rect.topLeft());
- if (d->has_brush) { // draw filled ellipse
- XFillArc(d->dpy, d->hd, d->gc_brush, x, y, w, h, 0, 360*64);
- if (!d->has_pen) // make smoother outline
- XDrawArc(d->dpy, d->hd, d->gc_brush, x, y, w-1, h-1, 0, 360*64);
- }
- if (d->has_pen) // draw outline
- XDrawArc(d->dpy, d->hd, d->gc, x, y, w, h, 0, 360*64);
- d->resetAdaptedOrigin();
-}
-
-
-
-void QX11PaintEnginePrivate::fillPolygon_translated(const QPointF *polygonPoints, int pointCount,
- QX11PaintEnginePrivate::GCMode gcMode,
- QPaintEngine::PolygonDrawMode mode)
-{
-
- QVarLengthArray<QPointF> translated_points(pointCount);
- QPointF offset(matrix.dx(), matrix.dy());
-
- qreal offs = adjust_coords ? aliasedCoordinateDelta : 0.0;
- if (!X11->use_xrender || !(render_hints & QPainter::Antialiasing))
- offset += QPointF(aliasedCoordinateDelta, aliasedCoordinateDelta);
-
- for (int i = 0; i < pointCount; ++i) {
- translated_points[i] = polygonPoints[i] + offset;
-
- translated_points[i].rx() = qRound(translated_points[i].x()) + offs;
- translated_points[i].ry() = qRound(translated_points[i].y()) + offs;
- }
-
- fillPolygon_dev(translated_points.data(), pointCount, gcMode, mode);
-}
-
-#if QT_CONFIG(xrender)
-static void qt_XRenderCompositeTrapezoids(Display *dpy,
- int op,
- Picture src,
- Picture dst,
- _Xconst XRenderPictFormat *maskFormat,
- int xSrc,
- int ySrc,
- const XTrapezoid *traps, int size)
-{
- const int MAX_TRAPS = 50000;
- while (size) {
- int to_draw = size;
- if (to_draw > MAX_TRAPS)
- to_draw = MAX_TRAPS;
- XRenderCompositeTrapezoids(dpy, op, src, dst,
- maskFormat,
- xSrc, ySrc,
- traps, to_draw);
- size -= to_draw;
- traps += to_draw;
- }
-}
-#endif
-
-void QX11PaintEnginePrivate::fillPolygon_dev(const QPointF *polygonPoints, int pointCount,
- QX11PaintEnginePrivate::GCMode gcMode,
- QPaintEngine::PolygonDrawMode mode)
-{
- Q_Q(QX11PaintEngine);
-
- int clippedCount = 0;
- qt_float_point *clippedPoints = 0;
-
-#if QT_CONFIG(xrender)
- //can change if we switch to pen if gcMode != BrushGC
- bool has_fill_texture = has_texture;
- bool has_fill_pattern = has_pattern;
- ::Picture src;
-#endif
- QBrush fill;
- GC fill_gc;
- if (gcMode == BrushGC) {
- fill = cbrush;
- fill_gc = gc_brush;
-#if QT_CONFIG(xrender)
- if (current_brush)
- src = current_brush;
- else
- src = X11->getSolidFill(scrn, fill.color());
-#endif
- } else {
- fill = QBrush(cpen.brush());
- fill_gc = gc;
-#if QT_CONFIG(xrender)
- //we use the pens brush
- has_fill_texture = (fill.style() == Qt::TexturePattern);
- has_fill_pattern = (fill.style() >= Qt::Dense1Pattern && fill.style() <= Qt::DiagCrossPattern);
- if (has_fill_texture)
- src = qt_x11PictureHandle(fill.texture());
- else if (has_fill_pattern)
- src = getPatternFill(scrn, fill);
- else
- src = X11->getSolidFill(scrn, fill.color());
-#endif
- }
-
- polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount,
- &clippedPoints, &clippedCount);
-
-#if QT_CONFIG(xrender)
- bool solid_fill = fill.color().alpha() == 255;
- if (has_fill_texture && fill.texture().depth() == 1 && solid_fill) {
- has_fill_texture = false;
- has_fill_pattern = true;
- }
-
- bool antialias = render_hints & QPainter::Antialiasing;
-
- if (X11->use_xrender
- && picture
- && !has_fill_pattern
- && (clippedCount > 0)
- && (fill.style() != Qt::NoBrush)
- && ((has_fill_texture && fill.texture().hasAlpha()) || antialias || !solid_fill || has_alpha_pen != has_alpha_brush))
- {
- tessellator->tessellate((QPointF *)clippedPoints, clippedCount,
- mode == QPaintEngine::WindingMode);
- if (tessellator->size > 0) {
- XRenderPictureAttributes attrs;
- attrs.poly_edge = antialias ? PolyEdgeSmooth : PolyEdgeSharp;
- XRenderChangePicture(dpy, picture, CPPolyEdge, &attrs);
- int x_offset = int(XFixedToDouble(tessellator->traps[0].left.p1.x) - bg_origin.x());
- int y_offset = int(XFixedToDouble(tessellator->traps[0].left.p1.y) - bg_origin.y());
- qt_XRenderCompositeTrapezoids(dpy, composition_mode, src, picture,
- antialias
- ? XRenderFindStandardFormat(dpy, PictStandardA8)
- : XRenderFindStandardFormat(dpy, PictStandardA1),
- x_offset, y_offset,
- tessellator->traps, tessellator->size);
- tessellator->done();
- }
- } else
-#endif
- if (fill.style() != Qt::NoBrush) {
- if (clippedCount > 200000) {
- QPolygon poly;
- for (int i = 0; i < clippedCount; ++i)
- poly << QPoint(qFloor(clippedPoints[i].x), qFloor(clippedPoints[i].y));
-
- const QRect bounds = poly.boundingRect();
- const QRect aligned = bounds
- & QRect(QPoint(), QSize(pdev->width(), pdev->height()));
-
- QImage img(aligned.size(), QImage::Format_ARGB32_Premultiplied);
- img.fill(0);
-
- QPainter painter(&img);
- painter.translate(-aligned.x(), -aligned.y());
- painter.setPen(Qt::NoPen);
- painter.setBrush(fill);
- if (gcMode == BrushGC)
- painter.setBrushOrigin(q->painter()->brushOriginF());
- painter.drawPolygon(poly);
- painter.end();
-
- q->drawImage(aligned, img, img.rect(), Qt::AutoColor);
- } else if (clippedCount > 0) {
- QVarLengthArray<XPoint> xpoints(clippedCount);
- for (int i = 0; i < clippedCount; ++i) {
- xpoints[i].x = qFloor(clippedPoints[i].x);
- xpoints[i].y = qFloor(clippedPoints[i].y);
- }
- if (mode == QPaintEngine::WindingMode)
- XSetFillRule(dpy, fill_gc, WindingRule);
- setupAdaptedOrigin(QPoint(xpoints[0].x, xpoints[0].y));
- XFillPolygon(dpy, hd, fill_gc,
- xpoints.data(), clippedCount,
- mode == QPaintEngine::ConvexMode ? Convex : Complex, CoordModeOrigin);
- resetAdaptedOrigin();
- if (mode == QPaintEngine::WindingMode)
- XSetFillRule(dpy, fill_gc, EvenOddRule);
- }
- }
-}
-
-void QX11PaintEnginePrivate::strokePolygon_translated(const QPointF *polygonPoints, int pointCount, bool close)
-{
- QVarLengthArray<QPointF> translated_points(pointCount);
- QPointF offset(matrix.dx(), matrix.dy());
- for (int i = 0; i < pointCount; ++i)
- translated_points[i] = polygonPoints[i] + offset;
- strokePolygon_dev(translated_points.data(), pointCount, close);
-}
-
-void QX11PaintEnginePrivate::strokePolygon_dev(const QPointF *polygonPoints, int pointCount, bool close)
-{
- int clippedCount = 0;
- qt_float_point *clippedPoints = 0;
- polygonClipper.clipPolygon((qt_float_point *) polygonPoints, pointCount,
- &clippedPoints, &clippedCount, close);
-
- if (clippedCount > 0) {
- QVarLengthArray<XPoint> xpoints(clippedCount);
- for (int i = 0; i < clippedCount; ++i) {
- xpoints[i].x = qRound(clippedPoints[i].x + aliasedCoordinateDelta);
- xpoints[i].y = qRound(clippedPoints[i].y + aliasedCoordinateDelta);
- }
- uint numberPoints = qMin(clippedCount, xlibMaxLinePoints);
- XPoint *pts = xpoints.data();
- XDrawLines(dpy, hd, gc, pts, numberPoints, CoordModeOrigin);
- pts += numberPoints;
- clippedCount -= numberPoints;
- numberPoints = qMin(clippedCount, xlibMaxLinePoints-1);
- while (clippedCount) {
- XDrawLines(dpy, hd, gc, pts-1, numberPoints+1, CoordModeOrigin);
- pts += numberPoints;
- clippedCount -= numberPoints;
- numberPoints = qMin(clippedCount, xlibMaxLinePoints-1);
- }
- }
-}
-
-void QX11PaintEngine::drawPolygon(const QPointF *polygonPoints, int pointCount, PolygonDrawMode mode)
-{
- Q_D(QX11PaintEngine);
-
- if (d->use_path_fallback) {
- QPainterPath path(polygonPoints[0]);
- for (int i = 1; i < pointCount; ++i)
- path.lineTo(polygonPoints[i]);
- if (mode == PolylineMode) {
- QBrush oldBrush = d->cbrush;
- d->cbrush = QBrush(Qt::NoBrush);
- path.setFillRule(Qt::WindingFill);
- drawPath(path);
- d->cbrush = oldBrush;
- } else {
- path.setFillRule(mode == OddEvenMode ? Qt::OddEvenFill : Qt::WindingFill);
- path.closeSubpath();
- drawPath(path);
- }
- return;
- }
- if (mode != PolylineMode && d->has_brush)
- d->fillPolygon_translated(polygonPoints, pointCount, QX11PaintEnginePrivate::BrushGC, mode);
-
- if (d->has_pen)
- d->strokePolygon_translated(polygonPoints, pointCount, mode != PolylineMode);
-}
-
-
-void QX11PaintEnginePrivate::fillPath(const QPainterPath &path, QX11PaintEnginePrivate::GCMode gc_mode, bool transform)
-{
- qreal offs = adjust_coords ? aliasedCoordinateDelta : 0.0;
-
- QPainterPath clippedPath;
- QPainterPath clipPath;
- clipPath.addRect(polygonClipper.boundingRect());
-
- if (transform)
- clippedPath = (path*matrix).intersected(clipPath);
- else
- clippedPath = path.intersected(clipPath);
-
- QList<QPolygonF> polys = clippedPath.toFillPolygons();
- for (int i = 0; i < polys.size(); ++i) {
- QVarLengthArray<QPointF> translated_points(polys.at(i).size());
-
- for (int j = 0; j < polys.at(i).size(); ++j) {
- translated_points[j] = polys.at(i).at(j);
- if (!X11->use_xrender || !(render_hints & QPainter::Antialiasing)) {
- translated_points[j].rx() = qRound(translated_points[j].rx() + aliasedCoordinateDelta) + offs;
- translated_points[j].ry() = qRound(translated_points[j].ry() + aliasedCoordinateDelta) + offs;
- }
- }
-
- fillPolygon_dev(translated_points.data(), polys.at(i).size(), gc_mode,
- path.fillRule() == Qt::OddEvenFill ? QPaintEngine::OddEvenMode : QPaintEngine::WindingMode);
- }
-}
-
-void QX11PaintEngine::drawPath(const QPainterPath &path)
-{
- Q_D(QX11PaintEngine);
- if (path.isEmpty())
- return;
-
- if (d->has_brush)
- d->fillPath(path, QX11PaintEnginePrivate::BrushGC, true);
- if (d->has_pen
- && ((X11->use_xrender && (d->has_alpha_pen || (d->render_hints & QPainter::Antialiasing)))
- || (!d->isCosmeticPen() && d->txop > QTransform::TxTranslate
- && !d->has_non_scaling_xform)
- || (d->cpen.style() == Qt::CustomDashLine))) {
- QPainterPathStroker stroker;
- if (d->cpen.style() == Qt::CustomDashLine) {
- stroker.setDashPattern(d->cpen.dashPattern());
- stroker.setDashOffset(d->cpen.dashOffset());
- } else {
- stroker.setDashPattern(d->cpen.style());
- }
- stroker.setCapStyle(d->cpen.capStyle());
- stroker.setJoinStyle(d->cpen.joinStyle());
- QPainterPath stroke;
- qreal width = d->cpen.widthF();
- QPolygonF poly;
- QRectF deviceRect(0, 0, d->pdev->width(), d->pdev->height());
- // necessary to get aliased alphablended primitives to be drawn correctly
- if (d->isCosmeticPen() || d->has_scaling_xform) {
- if (d->isCosmeticPen())
- stroker.setWidth(width == 0 ? 1 : width);
- else
- stroker.setWidth(width * d->xform_scale);
- stroker.d_ptr->stroker.setClipRect(deviceRect);
- stroke = stroker.createStroke(path * d->matrix);
- if (stroke.isEmpty())
- return;
- stroke.setFillRule(Qt::WindingFill);
- d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, false);
- } else {
- stroker.setWidth(width);
- stroker.d_ptr->stroker.setClipRect(d->matrix.inverted().mapRect(deviceRect));
- stroke = stroker.createStroke(path);
- if (stroke.isEmpty())
- return;
- stroke.setFillRule(Qt::WindingFill);
- d->fillPath(stroke, QX11PaintEnginePrivate::PenGC, true);
- }
- } else if (d->has_pen) {
- // if we have a cosmetic pen - use XDrawLine() for speed
- QList<QPolygonF> polys = path.toSubpathPolygons(d->matrix);
- for (int i = 0; i < polys.size(); ++i)
- d->strokePolygon_dev(polys.at(i).data(), polys.at(i).size(), false);
- }
-}
-
-Q_GUI_EXPORT void qt_x11_drawImage(const QRect &rect, const QPoint &pos, const QImage &image,
- Drawable hd, GC gc, Display *dpy, Visual *visual, int depth)
-{
- Q_ASSERT(image.format() == QImage::Format_RGB32);
- Q_ASSERT(image.depth() == 32);
-
- XImage *xi;
- // Note: this code assumes either RGB or BGR, 8 bpc server layouts
- const uint red_mask = (uint) visual->red_mask;
- bool bgr_layout = (red_mask == 0xff);
-
- const int w = rect.width();
- const int h = rect.height();
-
- QImage im;
- int image_byte_order = ImageByteOrder(QXcbX11Info::display());
- if ((QSysInfo::ByteOrder == QSysInfo::BigEndian && ((image_byte_order == LSBFirst) || bgr_layout))
- || (image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)
- || (image_byte_order == LSBFirst && bgr_layout))
- {
- im = image.copy(rect);
- const qsizetype iw = im.bytesPerLine() / 4;
- uint *data = (uint *)im.bits();
- for (int i=0; i < h; i++) {
- uint *p = data;
- uint *end = p + w;
- if (bgr_layout && image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian) {
- while (p < end) {
- *p = ((*p << 8) & 0xffffff00) | ((*p >> 24) & 0x000000ff);
- p++;
- }
- } else if ((image_byte_order == LSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
- || (image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::LittleEndian)) {
- while (p < end) {
- *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
- | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
- p++;
- }
- } else if ((image_byte_order == MSBFirst && QSysInfo::ByteOrder == QSysInfo::BigEndian)
- || (image_byte_order == LSBFirst && bgr_layout))
- {
- while (p < end) {
- *p = ((*p << 16) & 0x00ff0000) | ((*p >> 16) & 0x000000ff)
- | ((*p ) & 0xff00ff00);
- p++;
- }
- }
- data += iw;
- }
- xi = XCreateImage(dpy, visual, depth, ZPixmap,
- 0, (char *) im.bits(), w, h, 32, im.bytesPerLine());
- } else {
- xi = XCreateImage(dpy, visual, depth, ZPixmap,
- 0, (char *) image.scanLine(rect.y())+rect.x()*sizeof(uint), w, h, 32, image.bytesPerLine());
- }
- XPutImage(dpy, hd, gc, xi, 0, 0, pos.x(), pos.y(), w, h);
- xi->data = 0; // QImage owns these bits
- XDestroyImage(xi);
-}
-
-void QX11PaintEngine::drawImage(const QRectF &r, const QImage &image, const QRectF &sr, Qt::ImageConversionFlags flags)
-{
- Q_D(QX11PaintEngine);
-
- if (image.format() == QImage::Format_RGB32
- && d->pdev_depth >= 24 && image.depth() == 32
- && r.size() == sr.size())
- {
- int sx = qRound(sr.x());
- int sy = qRound(sr.y());
- int x = qRound(r.x());
- int y = qRound(r.y());
- int w = qRound(r.width());
- int h = qRound(r.height());
-
- qt_x11_drawImage(QRect(sx, sy, w, h), QPoint(x, y), image, d->hd, d->gc, d->dpy,
- (Visual *)d->xinfo->visual(), d->pdev_depth);
- } else {
- QPaintEngine::drawImage(r, image, sr, flags);
- }
-}
-
-void QX11PaintEngine::drawPixmap(const QRectF &r, const QPixmap &px, const QRectF &_sr)
-{
- Q_D(QX11PaintEngine);
- QRectF sr = _sr;
- int x = qRound(r.x());
- int y = qRound(r.y());
- int sx = qRound(sr.x());
- int sy = qRound(sr.y());
- int sw = qRound(sr.width());
- int sh = qRound(sr.height());
-
- QPixmap pixmap = qt_toX11Pixmap(px);
- if (pixmap.isNull())
- return;
-
- if ((d->xinfo && d->xinfo->screen() != qt_x11Info(pixmap).screen())
- || (qt_x11Info(pixmap).screen() != DefaultScreen(QXcbX11Info::display()))) {
- qt_x11SetScreen(pixmap, d->xinfo ? d->xinfo->screen() : DefaultScreen(X11->display));
- }
-
- qt_x11SetDefaultScreen(qt_x11Info(pixmap).screen());
-
-#if QT_CONFIG(xrender)
- ::Picture src_pict = qt_x11PictureHandle(pixmap);
- if (src_pict && d->picture) {
- const int pDepth = pixmap.depth();
- if (pDepth == 1 && (d->has_alpha_pen)) {
- qt_render_bitmap(d->dpy, d->scrn, src_pict, d->picture,
- sx, sy, x, y, sw, sh, d->cpen);
- return;
- } else if (pDepth != 1 && (pDepth == 32 || pDepth != d->pdev_depth)) {
- XRenderComposite(d->dpy, d->composition_mode,
- src_pict, 0, d->picture, sx, sy, 0, 0, x, y, sw, sh);
- return;
- }
- }
-#endif
-
- bool mono_src = pixmap.depth() == 1;
- bool mono_dst = d->pdev_depth == 1;
- bool restore_clip = false;
-
- if (static_cast<QX11PlatformPixmap*>(pixmap.handle())->x11_mask) { // pixmap has a mask
- QBitmap comb(sw, sh);
- GC cgc = XCreateGC(d->dpy, qt_x11PixmapHandle(comb), 0, 0);
- XSetForeground(d->dpy, cgc, 0);
- XFillRectangle(d->dpy, qt_x11PixmapHandle(comb), cgc, 0, 0, sw, sh);
- XSetBackground(d->dpy, cgc, 0);
- XSetForeground(d->dpy, cgc, 1);
- if (!d->crgn.isEmpty()) {
- QList<XRectangle> rects = qt_region_to_xrectangles(d->crgn);
- XSetClipRectangles(d->dpy, cgc, -x, -y, rects.data(), rects.size(), Unsorted);
- } else if (d->has_clipping) {
- XSetClipRectangles(d->dpy, cgc, 0, 0, 0, 0, Unsorted);
- }
- XSetFillStyle(d->dpy, cgc, FillOpaqueStippled);
- XSetTSOrigin(d->dpy, cgc, -sx, -sy);
- XSetStipple(d->dpy, cgc,
- static_cast<QX11PlatformPixmap*>(pixmap.handle())->x11_mask);
- XFillRectangle(d->dpy, qt_x11PixmapHandle(comb), cgc, 0, 0, sw, sh);
- XFreeGC(d->dpy, cgc);
-
- XSetClipOrigin(d->dpy, d->gc, x, y);
- XSetClipMask(d->dpy, d->gc, qt_x11PixmapHandle(comb));
- restore_clip = true;
- }
-
- if (mono_src) {
- if (!d->crgn.isEmpty()) {
- Pixmap comb = XCreatePixmap(d->dpy, d->hd, sw, sh, 1);
- GC cgc = XCreateGC(d->dpy, comb, 0, 0);
- XSetForeground(d->dpy, cgc, 0);
- XFillRectangle(d->dpy, comb, cgc, 0, 0, sw, sh);
- QList<XRectangle> rects = qt_region_to_xrectangles(d->crgn);
- XSetClipRectangles(d->dpy, cgc, -x, -y, rects.data(), rects.size(), Unsorted);
- XCopyArea(d->dpy, qt_x11PixmapHandle(pixmap), comb, cgc, sx, sy, sw, sh, 0, 0);
- XFreeGC(d->dpy, cgc);
-
- XSetClipMask(d->dpy, d->gc, comb);
- XSetClipOrigin(d->dpy, d->gc, x, y);
- XFreePixmap(d->dpy, comb);
- } else {
- XSetClipMask(d->dpy, d->gc, qt_x11PixmapHandle(pixmap));
- XSetClipOrigin(d->dpy, d->gc, x - sx, y - sy);
- }
-
- if (mono_dst) {
- XSetForeground(d->dpy, d->gc, qGray(d->cpen.color().rgb()) > 127 ? 0 : 1);
- } else {
- QXcbColormap cmap = QXcbColormap::instance(d->scrn);
- XSetForeground(d->dpy, d->gc, cmap.pixel(d->cpen.color()));
- }
- XFillRectangle(d->dpy, d->hd, d->gc, x, y, sw, sh);
- restore_clip = true;
- } else if (mono_dst && !mono_src) {
- QBitmap bitmap = QBitmap::fromPixmap(pixmap);
- XCopyArea(d->dpy, qt_x11PixmapHandle(bitmap), d->hd, d->gc, sx, sy, sw, sh, x, y);
- } else {
- XCopyArea(d->dpy, qt_x11PixmapHandle(pixmap), d->hd, d->gc, sx, sy, sw, sh, x, y);
- }
-
- if (d->pdev->devType() == QInternal::Pixmap) {
- const QPixmap *px = static_cast<const QPixmap*>(d->pdev);
- Pixmap src_mask = static_cast<QX11PlatformPixmap*>(pixmap.handle())->x11_mask;
- Pixmap dst_mask = static_cast<QX11PlatformPixmap*>(px->handle())->x11_mask;
- if (dst_mask) {
- GC cgc = XCreateGC(d->dpy, dst_mask, 0, 0);
- XSetClipOrigin(d->dpy, cgc, x, y);
- XSetClipMask(d->dpy, cgc, src_mask);
- if (src_mask) { // copy src mask into dst mask
- XCopyArea(d->dpy, src_mask, dst_mask, cgc, sx, sy, sw, sh, x, y);
- } else { // no src mask, but make sure the area copied is opaque in dest
- XSetBackground(d->dpy, cgc, 0);
- XSetForeground(d->dpy, cgc, 1);
- XFillRectangle(d->dpy, dst_mask, cgc, x, y, sw, sh);
- }
- XFreeGC(d->dpy, cgc);
- }
- }
-
- if (restore_clip) {
- XSetClipOrigin(d->dpy, d->gc, 0, 0);
- QList<XRectangle> rects = qt_region_to_xrectangles(d->crgn);
- if (rects.isEmpty())
- XSetClipMask(d->dpy, d->gc, XNone);
- else
- XSetClipRectangles(d->dpy, d->gc, 0, 0, rects.data(), rects.size(), Unsorted);
- }
-}
-
-void QX11PaintEngine::updateMatrix(const QTransform &mtx)
-{
- Q_D(QX11PaintEngine);
- d->txop = mtx.type();
- d->matrix = mtx;
-
- d->has_complex_xform = (d->txop > QTransform::TxTranslate);
-
- extern bool qt_scaleForTransform(const QTransform &transform, qreal *scale);
- bool scaling = qt_scaleForTransform(d->matrix, &d->xform_scale);
- d->has_scaling_xform = scaling && d->xform_scale != 1.0;
- d->has_non_scaling_xform = scaling && d->xform_scale == 1.0;
-}
-
-/*
- NB! the clip region is expected to be in dev coordinates
-*/
-void QX11PaintEngine::updateClipRegion_dev(const QRegion &clipRegion, Qt::ClipOperation op)
-{
- Q_D(QX11PaintEngine);
- QRegion sysClip = d->use_sysclip ? systemClip() : QRegion();
- if (op == Qt::NoClip) {
- d->has_clipping = false;
- d->crgn = sysClip;
- if (!sysClip.isEmpty()) {
- x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, sysClip);
- } else {
- x11ClearClipRegion(d->dpy, d->gc, d->gc_brush, d->picture);
- }
- return;
- }
-
- switch (op) {
- case Qt::IntersectClip:
- if (d->has_clipping) {
- d->crgn &= clipRegion;
- break;
- }
- // fall through
- case Qt::ReplaceClip:
- if (!sysClip.isEmpty())
- d->crgn = clipRegion.intersected(sysClip);
- else
- d->crgn = clipRegion;
- break;
-// case Qt::UniteClip:
-// d->crgn |= clipRegion;
-// if (!sysClip.isEmpty())
-// d->crgn = d->crgn.intersected(sysClip);
-// break;
- default:
- break;
- }
- d->has_clipping = true;
- x11SetClipRegion(d->dpy, d->gc, d->gc_brush, d->picture, d->crgn);
-}
-
-void QX11PaintEngine::updateFont(const QFont &)
-{
-}
-
-Drawable QX11PaintEngine::handle() const
-{
- Q_D(const QX11PaintEngine);
- Q_ASSERT(isActive());
- Q_ASSERT(d->hd);
- return d->hd;
-}
-
-extern void qt_draw_tile(QPaintEngine *, qreal, qreal, qreal, qreal, const QPixmap &,
- qreal, qreal);
-
-void QX11PaintEngine::drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &p)
-{
- int x = qRound(r.x());
- int y = qRound(r.y());
- int w = qRound(r.width());
- int h = qRound(r.height());
- int sx = qRound(p.x());
- int sy = qRound(p.y());
-
- bool mono_src = pixmap.depth() == 1;
- Q_D(QX11PaintEngine);
-
- if ((d->xinfo && d->xinfo->screen() != qt_x11Info(pixmap).screen())
- || (qt_x11Info(pixmap).screen() != DefaultScreen(QXcbX11Info::display()))) {
- QPixmap* p = const_cast<QPixmap *>(&pixmap);
- qt_x11SetScreen(*p, d->xinfo ? d->xinfo->screen() : DefaultScreen(QXcbX11Info::display()));
- }
-
- qt_x11SetDefaultScreen(qt_x11Info(pixmap).screen());
-
-#if QT_CONFIG(xrender)
- if (X11->use_xrender && d->picture && qt_x11PictureHandle(pixmap)) {
- const int numTiles = (w / pixmap.width()) * (h / pixmap.height());
- if (numTiles < 100) {
- // this is essentially qt_draw_tile(), inlined for
- // the XRenderComposite call
- int yPos, xPos, drawH, drawW, yOff, xOff;
- yPos = y;
- yOff = sy;
- while (yPos < y + h) {
- drawH = pixmap.height() - yOff; // Cropping first row
- if (yPos + drawH > y + h) // Cropping last row
- drawH = y + h - yPos;
- xPos = x;
- xOff = sx;
- while (xPos < x + w) {
- drawW = pixmap.width() - xOff; // Cropping first column
- if (xPos + drawW > x + w) // Cropping last column
- drawW = x + w - xPos;
- if (mono_src) {
- qt_render_bitmap(d->dpy, d->scrn, qt_x11PictureHandle(pixmap), d->picture,
- xOff, yOff, xPos, yPos, drawW, drawH, d->cpen);
- } else {
- XRenderComposite(d->dpy, d->composition_mode,
- qt_x11PictureHandle(pixmap), XNone, d->picture,
- xOff, yOff, 0, 0, xPos, yPos, drawW, drawH);
- }
- xPos += drawW;
- xOff = 0;
- }
- yPos += drawH;
- yOff = 0;
- }
- } else {
- w = qMin(w, d->pdev->width() - x);
- h = qMin(h, d->pdev->height() - y);
- if (w <= 0 || h <= 0)
- return;
-
- const int pw = w + sx;
- const int ph = h + sy;
- QPixmap pm(pw, ph);
- if (pixmap.hasAlpha() || mono_src)
- pm.fill(Qt::transparent);
-
- const int mode = pixmap.hasAlpha() ? PictOpOver : PictOpSrc;
- const ::Picture pmPicture = qt_x11PictureHandle(pm);
-
- // first tile
- XRenderComposite(d->dpy, mode,
- qt_x11PictureHandle(pixmap), XNone, pmPicture,
- 0, 0, 0, 0, 0, 0, qMin(pw, pixmap.width()), qMin(ph, pixmap.height()));
-
- // first row of tiles
- int xPos = pixmap.width();
- const int sh = qMin(ph, pixmap.height());
- while (xPos < pw) {
- const int sw = qMin(xPos, pw - xPos);
- XRenderComposite(d->dpy, mode,
- pmPicture, XNone, pmPicture,
- 0, 0, 0, 0, xPos, 0, sw, sh);
- xPos *= 2;
- }
-
- // remaining rows
- int yPos = pixmap.height();
- const int sw = pw;
- while (yPos < ph) {
- const int sh = qMin(yPos, ph - yPos);
- XRenderComposite(d->dpy, mode,
- pmPicture, XNone, pmPicture,
- 0, 0, 0, 0, 0, yPos, sw, sh);
- yPos *= 2;
- }
-
- // composite
- if (mono_src)
- qt_render_bitmap(d->dpy, d->scrn, pmPicture, d->picture,
- sx, sy, x, y, w, h, d->cpen);
- else
- XRenderComposite(d->dpy, d->composition_mode,
- pmPicture, XNone, d->picture,
- sx, sy, 0, 0, x, y, w, h);
- }
- } else
-#endif // QT_CONFIG(xrender)
- if (pixmap.depth() > 1 && !static_cast<QX11PlatformPixmap*>(pixmap.handle())->x11_mask) {
- XSetTile(d->dpy, d->gc, qt_x11PixmapHandle(pixmap));
- XSetFillStyle(d->dpy, d->gc, FillTiled);
- XSetTSOrigin(d->dpy, d->gc, x-sx, y-sy);
- XFillRectangle(d->dpy, d->hd, d->gc, x, y, w, h);
- XSetTSOrigin(d->dpy, d->gc, 0, 0);
- XSetFillStyle(d->dpy, d->gc, FillSolid);
- } else {
- qt_draw_tile(this, x, y, w, h, pixmap, sx, sy);
- }
-}
-
-bool QX11PaintEngine::drawCachedGlyphs(const QTransform &transform, const QTextItemInt &ti)
-{
-#if QT_CONFIG(xrender)
- Q_D(QX11PaintEngine);
- Q_ASSERT(ti.fontEngine->type() == QFontEngine::Freetype);
-
- if (!X11->use_xrender)
- return false;
-
- QFontEngineFT *ft = static_cast<QFontEngineFT *>(ti.fontEngine);
- QFontEngineFT::QGlyphSet *set = ft->loadGlyphSet(transform);
-
- if (!set || set->outline_drawing)
- return false;
-
- QFontEngine::GlyphFormat glyphFormat = QXRenderGlyphCache::glyphFormatForDepth(ft, d->pdev_depth);
-
- QXRenderGlyphCache *cache = static_cast<QXRenderGlyphCache *>(ft->glyphCache(set, glyphFormat, transform));
- if (!cache) {
- cache = new QXRenderGlyphCache(QXcbX11Info(), glyphFormat, transform);
- ft->setGlyphCache(set, cache);
- }
-
- return cache->draw(X11->getSolidFill(d->scrn, d->cpen.color()), d->picture, transform, ti);
-#else // !QT_CONFIG(xrender)
- return false;
-#endif // QT_CONFIG(xrender)
-}
-
-void QX11PaintEngine::drawTextItem(const QPointF &p, const QTextItem &textItem)
-{
- Q_D(QX11PaintEngine);
- const QTextItemInt &ti = static_cast<const QTextItemInt &>(textItem);
-
- switch (ti.fontEngine->type()) {
- case QFontEngine::TestFontEngine:
- case QFontEngine::Box:
- d->drawBoxTextItem(p, ti);
- break;
-#if QT_CONFIG(fontconfig)
- case QFontEngine::Freetype:
- drawFreetype(p, ti);
- break;
-#endif
- default:
- Q_ASSERT(false);
- }
-}
-
-#if QT_CONFIG(fontconfig)
-static bool path_for_glyphs(QPainterPath *path,
- const QVarLengthArray<glyph_t> &glyphs,
- const QVarLengthArray<QFixedPoint> &positions,
- const QFontEngineFT *ft)
-{
- bool result = true;
- *path = QPainterPath();
- path->setFillRule(Qt::WindingFill);
- ft->lockFace();
- int i = 0;
- while (i < glyphs.size()) {
- QFontEngineFT::Glyph *glyph = ft->loadGlyph(glyphs[i], QFixedPoint(), QFontEngineFT::Format_Mono);
- // #### fix case where we don't get a glyph
- if (!glyph || glyph->format != QFontEngineFT::Format_Mono) {
- result = false;
- break;
- }
-
- int n = 0;
- int h = glyph->height;
- int xp = qRound(positions[i].x);
- int yp = qRound(positions[i].y);
-
- xp += glyph->x;
- yp += -glyph->y + glyph->height;
- int pitch = ((glyph->width + 31) & ~31) >> 3;
-
- uchar *src = glyph->data;
- while (h--) {
- for (int x = 0; x < glyph->width; ++x) {
- bool set = src[x >> 3] & (0x80 >> (x & 7));
- if (set) {
- QRect r(xp + x, yp - h, 1, 1);
- while (x+1 < glyph->width && src[(x+1) >> 3] & (0x80 >> ((x+1) & 7))) {
- ++x;
- r.setRight(r.right()+1);
- }
-
- path->addRect(r);
- ++n;
- }
- }
- src += pitch;
- }
- ++i;
- }
- ft->unlockFace();
- return result;
-}
-
-void QX11PaintEngine::drawFreetype(const QPointF &p, const QTextItemInt &ti)
-{
- Q_D(QX11PaintEngine);
-
- if (!ti.glyphs.numGlyphs)
- return;
-
- if (!d->cpen.isSolid()) {
- QPaintEngine::drawTextItem(p, ti);
- return;
- }
-
- const bool xrenderPath = (X11->use_xrender
- && !(d->pdev->devType() == QInternal::Pixmap
- && static_cast<const QPixmap *>(d->pdev)->handle()->pixelType() == QPlatformPixmap::BitmapType));
-
- if (xrenderPath) {
- QTransform transform = d->matrix;
- transform.translate(p.x(), p.y());
-
- if (drawCachedGlyphs(transform, ti))
- return;
- }
-
- QTransform transform;
- transform.translate(p.x(), p.y());
-
- QVarLengthArray<QFixedPoint> positions;
- QVarLengthArray<glyph_t> glyphs;
- ti.fontEngine->getGlyphPositions(ti.glyphs, transform, ti.flags, glyphs, positions);
-
- if (glyphs.count() == 0)
- return;
-
- QFontEngineFT *ft = static_cast<QFontEngineFT *>(ti.fontEngine);
- QFontEngineFT::QGlyphSet *set = ft->loadGlyphSet(transform);
- QPainterPath path;
-
- if (!set || set->outline_drawing || !path_for_glyphs(&path, glyphs, positions, ft)) {
- QPaintEngine::drawTextItem(p, ti);
- return;
- }
-
- if (path.elementCount() <= 1)
- return;
-
- Q_ASSERT((path.elementCount() % 5) == 0);
- if (d->txop >= QTransform::TxScale) {
- painter()->save();
- painter()->setBrush(d->cpen.brush());
- painter()->setPen(Qt::NoPen);
- painter()->drawPath(path);
- painter()->restore();
- return;
- }
-
- const int rectcount = 256;
- XRectangle rects[rectcount];
- int num_rects = 0;
-
- QPoint delta(qRound(d->matrix.dx()), qRound(d->matrix.dy()));
- QRect clip(d->polygonClipper.boundingRect());
- for (int i=0; i < path.elementCount(); i+=5) {
- int x = qRound(path.elementAt(i).x);
- int y = qRound(path.elementAt(i).y);
- int w = qRound(path.elementAt(i+1).x) - x;
- int h = qRound(path.elementAt(i+2).y) - y;
-
- QRect rect = QRect(x + delta.x(), y + delta.y(), w, h);
- rect = rect.intersected(clip);
- if (rect.isEmpty())
- continue;
-
- rects[num_rects].x = short(rect.x());
- rects[num_rects].y = short(rect.y());
- rects[num_rects].width = ushort(rect.width());
- rects[num_rects].height = ushort(rect.height());
- ++num_rects;
- if (num_rects == rectcount) {
- XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects);
- num_rects = 0;
- }
- }
- if (num_rects > 0)
- XFillRectangles(d->dpy, d->hd, d->gc, rects, num_rects);
-}
-#endif // QT_CONFIG(fontconfig)
-
-#if QT_CONFIG(xrender)
-QXRenderGlyphCache::QXRenderGlyphCache(QXcbX11Info x, QFontEngine::GlyphFormat format, const QTransform &matrix)
- : QFontEngineGlyphCache(format, matrix)
- , xinfo(x)
- , gset(XNone)
-{}
-
-QXRenderGlyphCache::~QXRenderGlyphCache()
-{
- if (gset != XNone)
- XRenderFreeGlyphSet(xinfo.display(), gset);
-}
-
-bool QXRenderGlyphCache::addGlyphs(const QTextItemInt &ti,
- const QVarLengthArray<glyph_t> &glyphs,
- const QVarLengthArray<QFixedPoint> &positions)
-{
- Q_ASSERT(ti.fontEngine->type() == QFontEngine::Freetype);
-
- QFontEngineFT *ft = static_cast<QFontEngineFT *>(ti.fontEngine);
- QFontEngineFT::QGlyphSet *set = ft->loadGlyphSet(transform());
-
- XGlyphInfo xglyphinfo;
-
- for (int i = 0; i < glyphs.size(); ++i) {
- const QFixed sppx = ft->subPixelPositionForX(positions[i].x);
- const QFixedPoint spp(sppx, 0);
- QFontEngineFT::Glyph *glyph = set->getGlyph(glyphs[i], spp);
- Glyph xglyphid = qHash(QFontEngineFT::GlyphAndSubPixelPosition(glyphs[i], spp));
-
- if (glyph && glyph->format == glyphFormat()) {
- if (cachedGlyphs.contains(xglyphid)) {
- continue;
- } else {
- set->setGlyph(glyphs[i], spp, nullptr);
- delete glyph;
- glyph = 0;
- }
- }
-
- glyph = ft->loadGlyphFor(glyphs[i], spp, glyphFormat(), transform(), QColor());
-
- if (glyph == 0 || glyph->format != glyphFormat())
- return false;
-
- if (glyph->format == QFontEngine::Format_Mono) {
- // Must convert bitmap from msb to lsb bit order
- QImage img(glyph->data, glyph->width, glyph->height, QImage::Format_Mono);
- img = img.convertToFormat(QImage::Format_MonoLSB);
- memcpy(glyph->data, img.constBits(), static_cast<size_t>(img.sizeInBytes()));
- }
-
- set->setGlyph(glyphs[i], spp, glyph);
- Q_ASSERT(glyph->data || glyph->width == 0 || glyph->height == 0);
-
- xglyphinfo.width = glyph->width;
- xglyphinfo.height = glyph->height;
- xglyphinfo.x = -glyph->x;
- xglyphinfo.y = glyph->y;
- xglyphinfo.xOff = glyph->advance;
- xglyphinfo.yOff = 0;
-
- XRenderAddGlyphs(xinfo.display(), glyphSet(), &xglyphid, &xglyphinfo, 1, (const char *) glyph->data, glyphBufferSize(*glyph));
- cachedGlyphs.insert(xglyphid);
- }
-
- return true;
-}
-
-bool QXRenderGlyphCache::draw(Drawable src, Drawable dst, const QTransform &matrix, const QTextItemInt &ti)
-{
- Q_ASSERT(ti.fontEngine->type() == QFontEngine::Freetype);
-
- if (ti.glyphs.numGlyphs == 0)
- return true;
-
- QFontEngineFT *ft = static_cast<QFontEngineFT *>(ti.fontEngine);
- QFontEngineFT::QGlyphSet *set = ft->loadGlyphSet(matrix);
-
- QVarLengthArray<glyph_t> glyphs;
- QVarLengthArray<QFixedPoint> positions;
- ti.fontEngine->getGlyphPositions(ti.glyphs, matrix, ti.flags, glyphs, positions);
-
- if (glyphs.isEmpty())
- return true;
-
- if (!addGlyphs(ti, glyphs, positions))
- return false;
-
- QVarLengthArray<unsigned int> chars(glyphs.size());
-
- for (int i = 0; i < glyphs.size(); ++i)
- chars[i] = glyphId(glyphs[i], ft->subPixelPositionForX(positions[i].x));
-
- int i = 0;
- while (i < glyphs.size() && !isValidCoordinate(positions[i]))
- ++i;
-
- if (i >= glyphs.size())
- return true;
-
- QFixed xp = positions[i].x;
- QFixed yp = positions[i].y;
- QFixed offs = QFixed::fromReal(aliasedCoordinateDelta);
-
- XGlyphElt32 elt;
- elt.glyphset = gset;
- elt.chars = &chars[i];
- elt.nchars = 1;
- elt.xOff = qRound(xp + offs);
- elt.yOff = qRound(yp + offs);
-
- ++i;
-
- for (; i < glyphs.size(); ++i) {
- if (!isValidCoordinate(positions[i]))
- break;
-
- const QFixed sppx = ft->subPixelPositionForX(positions[i].x);
- const QFixedPoint spp(sppx, 0);
- QFontEngineFT::Glyph *g = set->getGlyph(glyphs[i], spp);
-
- if (g
- && positions[i].x == xp + g->advance
- && positions[i].y == yp
- && elt.nchars < 253 // don't draw more than 253 characters as some X servers
- // hang with it
- ) {
- elt.nchars++;
- xp += g->advance;
- } else {
- xp = positions[i].x;
- yp = positions[i].y;
-
- XRenderCompositeText32(xinfo.display(), PictOpOver, src, dst,
- renderPictFormat(), 0, 0, 0, 0,
- &elt, 1);
- elt.chars = &chars[i];
- elt.nchars = 1;
- elt.xOff = qRound(xp + offs);
- elt.yOff = qRound(yp + offs);
- }
- }
-
- XRenderCompositeText32(xinfo.display(), PictOpOver, src, dst,
- renderPictFormat(), 0, 0, 0, 0, &elt, 1);
-
- return true;
-}
-
-GlyphSet QXRenderGlyphCache::glyphSet()
-{
- if (gset == XNone)
- gset = XRenderCreateGlyphSet(xinfo.display(), renderPictFormat());
-
- Q_ASSERT(gset != XNone);
- return gset;
-}
-
-int QXRenderGlyphCache::glyphBufferSize(const QFontEngineFT::Glyph &glyph) const
-{
- int pitch = 0;
-
- switch (glyphFormat()) {
- case QFontEngine::Format_Mono:
- pitch = ((glyph.width + 31) & ~31) >> 3;
- break;
- case QFontEngine::Format_A8:
- pitch = (glyph.width + 3) & ~3;
- break;
- default:
- pitch = glyph.width * 4;
- break;
- }
-
- return pitch * glyph.height;
-}
-
-QImage::Format QXRenderGlyphCache::imageFormat() const
-{
- switch (glyphFormat()) {
- case QFontEngine::Format_None:
- Q_UNREACHABLE();
- break;
- case QFontEngine::Format_Mono:
- return QImage::Format_Mono;
- break;
- case QFontEngine::Format_A8:
- return QImage::Format_Alpha8;
- break;
- case QFontEngine::Format_A32:
- case QFontEngine::Format_ARGB:
- return QImage::Format_ARGB32_Premultiplied;
- break;
- }
-
- Q_UNREACHABLE();
-}
-
-const XRenderPictFormat *QXRenderGlyphCache::renderPictFormat() const
-{
- switch (glyphFormat()) {
- case QFontEngine::Format_None:
- Q_UNREACHABLE();
- break;
- case QFontEngine::Format_Mono:
- return XRenderFindStandardFormat(xinfo.display(), PictStandardA1);
- break;
- case QFontEngine::Format_A8:
- return XRenderFindStandardFormat(xinfo.display(), PictStandardA8);
- break;
- case QFontEngine::Format_A32:
- case QFontEngine::Format_ARGB:
- return XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32);
- break;
- }
-
- Q_UNREACHABLE();
-}
-
-QFontEngine::GlyphFormat QXRenderGlyphCache::glyphFormatForDepth(QFontEngine *fontEngine, int depth)
-{
- QFontEngine::GlyphFormat glyphFormat = fontEngine->glyphFormat;
-
- if (glyphFormat == QFontEngine::Format_None) {
- switch (depth) {
- case 32:
- glyphFormat = QFontEngine::Format_ARGB;
- break;
- case 24:
- glyphFormat = QFontEngine::Format_A32;
- break;
- case 1:
- glyphFormat = QFontEngine::Format_Mono;
- break;
- default:
- glyphFormat = QFontEngine::Format_A8;
- break;
- }
- }
-
- return glyphFormat;
-}
-
-Glyph QXRenderGlyphCache::glyphId(glyph_t glyph, QFixed subPixelPosition)
-{
- return qHash(QFontEngineFT::GlyphAndSubPixelPosition(glyph, QFixedPoint(subPixelPosition, 0)));
-}
-
-bool QXRenderGlyphCache::isValidCoordinate(const QFixedPoint &fp)
-{
- enum { t_min = SHRT_MIN, t_max = SHRT_MAX };
- return (fp.x < t_min || fp.x > t_max || fp.y < t_min || fp.y > t_max) ? false : true;
-}
-#endif // QT_CONFIG(xrender)
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
deleted file mode 100644
index bcbf84682c6..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qpaintengine_x11_p.h
+++ /dev/null
@@ -1,86 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#pragma once
-
-#include <QtGui/QPaintEngine>
-
-typedef unsigned long XID;
-typedef XID Drawable;
-typedef struct _XGC *GC;
-
-QT_BEGIN_NAMESPACE
-
-extern "C" {
-Drawable qt_x11Handle(const QPaintDevice *pd);
-GC qt_x11_get_pen_gc(QPainter *);
-GC qt_x11_get_brush_gc(QPainter *);
-}
-
-class QX11PaintEnginePrivate;
-class QX11PaintEngine : public QPaintEngine
-{
- Q_DECLARE_PRIVATE(QX11PaintEngine)
-public:
- QX11PaintEngine();
- ~QX11PaintEngine();
-
- bool begin(QPaintDevice *pdev) override;
- bool end() override;
-
- void updateState(const QPaintEngineState &state) override;
-
- void updatePen(const QPen &pen);
- void updateBrush(const QBrush &brush, const QPointF &pt);
- void updateRenderHints(QPainter::RenderHints hints);
- void updateFont(const QFont &font);
- void updateMatrix(const QTransform &matrix);
- void updateClipRegion_dev(const QRegion &region, Qt::ClipOperation op);
-
- void drawLines(const QLine *lines, int lineCount) override;
- void drawLines(const QLineF *lines, int lineCount) override;
-
- void drawRects(const QRect *rects, int rectCount) override;
- void drawRects(const QRectF *rects, int rectCount) override;
-
- void drawPoints(const QPoint *points, int pointCount) override;
- void drawPoints(const QPointF *points, int pointCount) override;
-
- void drawEllipse(const QRect &r) override;
- void drawEllipse(const QRectF &r) override;
-
- virtual void drawPolygon(const QPointF *points, int pointCount, PolygonDrawMode mode) override;
- inline void drawPolygon(const QPoint *points, int pointCount, PolygonDrawMode mode) override
- { QPaintEngine::drawPolygon(points, pointCount, mode); }
-
- void drawPixmap(const QRectF &r, const QPixmap &pm, const QRectF &sr) override;
- void drawTiledPixmap(const QRectF &r, const QPixmap &pixmap, const QPointF &s) override;
- void drawPath(const QPainterPath &path) override;
- void drawTextItem(const QPointF &p, const QTextItem &textItem) override;
- void drawImage(const QRectF &r, const QImage &img, const QRectF &sr,
- Qt::ImageConversionFlags flags = Qt::AutoColor) override;
-
- virtual Drawable handle() const;
- inline Type type() const override { return QPaintEngine::X11; }
-
- QPainter::RenderHints supportedRenderHints() const;
-
-protected:
- QX11PaintEngine(QX11PaintEnginePrivate &dptr);
-
-#if QT_CONFIG(fontconfig)
- void drawFreetype(const QPointF &p, const QTextItemInt &ti);
- bool drawCachedGlyphs(const QTransform &transform, const QTextItemInt &ti);
-#endif // QT_CONFIG(fontconfig)
-
- friend class QPixmap;
- friend class QFontEngineBox;
- friend GC qt_x11_get_pen_gc(QPainter *);
- friend GC qt_x11_get_brush_gc(QPainter *);
-
-private:
- Q_DISABLE_COPY_MOVE(QX11PaintEngine)
-};
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
deleted file mode 100644
index b47bd3f5dcc..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11.cpp
+++ /dev/null
@@ -1,2087 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#include <QGuiApplication>
-
-#include <private/qdrawhelper_p.h>
-#include <private/qimage_p.h>
-#include <private/qimagepixmapcleanuphooks_p.h>
-
-#include "qxcbnativepainting.h"
-#include "qpixmap_x11_p.h"
-#include "qcolormap_x11_p.h"
-#include "qpaintengine_x11_p.h"
-
-QT_BEGIN_NAMESPACE
-
-#if QT_POINTER_SIZE == 8 // 64-bit versions
-
-Q_ALWAYS_INLINE uint PREMUL(uint x) {
- uint a = x >> 24;
- quint64 t = (((quint64(x)) | ((quint64(x)) << 24)) & 0x00ff00ff00ff00ff) * a;
- t = (t + ((t >> 8) & 0xff00ff00ff00ff) + 0x80008000800080) >> 8;
- t &= 0x000000ff00ff00ff;
- return (uint(t)) | (uint(t >> 24)) | (a << 24);
-}
-
-#else // 32-bit versions
-
-Q_ALWAYS_INLINE uint PREMUL(uint x) {
- uint a = x >> 24;
- uint t = (x & 0xff00ff) * a;
- t = (t + ((t >> 8) & 0xff00ff) + 0x800080) >> 8;
- t &= 0xff00ff;
-
- x = ((x >> 8) & 0xff) * a;
- x = (x + ((x >> 8) & 0xff) + 0x80);
- x &= 0xff00;
- x |= t | (a << 24);
- return x;
-}
-#endif
-
-
-
-struct QXImageWrapper
-{
- XImage *xi;
-};
-
-QPixmap qt_toX11Pixmap(const QImage &image)
-{
- QPlatformPixmap *data =
- new QX11PlatformPixmap(image.depth() == 1
- ? QPlatformPixmap::BitmapType
- : QPlatformPixmap::PixmapType);
-
- data->fromImage(image, Qt::AutoColor);
-
- return QPixmap(data);
-}
-
-QPixmap qt_toX11Pixmap(const QPixmap &pixmap)
-{
- if (pixmap.isNull())
- return QPixmap();
-
- if (QPixmap(pixmap).data_ptr()->classId() == QPlatformPixmap::X11Class)
- return pixmap;
-
- return qt_toX11Pixmap(pixmap.toImage());
-}
-
-// For thread-safety:
-// image->data does not belong to X11, so we must free it ourselves.
-
-inline static void qSafeXDestroyImage(XImage *x)
-{
- if (x->data) {
- free(x->data);
- x->data = 0;
- }
- XDestroyImage(x);
-}
-
-QBitmap QX11PlatformPixmap::mask_to_bitmap(int screen) const
-{
- if (!x11_mask)
- return QBitmap();
- qt_x11SetDefaultScreen(screen);
- QBitmap bm(w, h);
- QX11PlatformPixmap *that = qt_x11Pixmap(bm);
- const QXcbX11Info *x = that->x11_info();
- GC gc = XCreateGC(x->display(), that->handle(), 0, 0);
- XCopyArea(x->display(), x11_mask, that->handle(), gc, 0, 0,
- that->width(), that->height(), 0, 0);
- XFreeGC(x->display(), gc);
- return bm;
-}
-
-void QX11PlatformPixmap::bitmapFromImage(const QImage &image)
-{
- w = image.width();
- h = image.height();
- d = 1;
- is_null = (w <= 0 || h <= 0);
- hd = createBitmapFromImage(image);
-#if QT_CONFIG(xrender)
- if (X11->use_xrender)
- picture = XRenderCreatePicture(xinfo.display(), hd,
- XRenderFindStandardFormat(xinfo.display(), PictStandardA1), 0, 0);
-#endif // QT_CONFIG(xrender)
-}
-
-bool QX11PlatformPixmap::canTakeQImageFromXImage(const QXImageWrapper &xiWrapper) const
-{
- XImage *xi = xiWrapper.xi;
-
- if (xi->format != ZPixmap)
- return false;
-
- // ARGB32_Premultiplied
- if (picture && depth() == 32)
- return true;
-
- // RGB32
- if (depth() == 24 && xi->bits_per_pixel == 32 && xi->red_mask == 0xff0000
- && xi->green_mask == 0xff00 && xi->blue_mask == 0xff)
- return true;
-
- // RGB16
- if (depth() == 16 && xi->bits_per_pixel == 16 && xi->red_mask == 0xf800
- && xi->green_mask == 0x7e0 && xi->blue_mask == 0x1f)
- return true;
-
- return false;
-}
-
-QImage QX11PlatformPixmap::takeQImageFromXImage(const QXImageWrapper &xiWrapper) const
-{
- XImage *xi = xiWrapper.xi;
-
- QImage::Format format = QImage::Format_ARGB32_Premultiplied;
- if (depth() == 24)
- format = QImage::Format_RGB32;
- else if (depth() == 16)
- format = QImage::Format_RGB16;
-
- QImage image((uchar *)xi->data, xi->width, xi->height, xi->bytes_per_line, format);
- image.setDevicePixelRatio(devicePixelRatio());
- // take ownership
- image.data_ptr()->own_data = true;
- xi->data = 0;
-
- // we may have to swap the byte order
- if ((QSysInfo::ByteOrder == QSysInfo::LittleEndian && xi->byte_order == MSBFirst)
- || (QSysInfo::ByteOrder == QSysInfo::BigEndian && xi->byte_order == LSBFirst))
- {
- for (int i=0; i < image.height(); i++) {
- if (depth() == 16) {
- ushort *p = (ushort*)image.scanLine(i);
- ushort *end = p + image.width();
- while (p < end) {
- *p = ((*p << 8) & 0xff00) | ((*p >> 8) & 0x00ff);
- p++;
- }
- } else {
- uint *p = (uint*)image.scanLine(i);
- uint *end = p + image.width();
- while (p < end) {
- *p = ((*p << 24) & 0xff000000) | ((*p << 8) & 0x00ff0000)
- | ((*p >> 8) & 0x0000ff00) | ((*p >> 24) & 0x000000ff);
- p++;
- }
- }
- }
- }
-
- // fix-up alpha channel
- if (format == QImage::Format_RGB32) {
- QRgb *p = (QRgb *)image.bits();
- for (int y = 0; y < xi->height; ++y) {
- for (int x = 0; x < xi->width; ++x)
- p[x] |= 0xff000000;
- p += xi->bytes_per_line / 4;
- }
- }
-
- XDestroyImage(xi);
- return image;
-}
-
-XID QX11PlatformPixmap::bitmap_to_mask(const QBitmap &bitmap, int screen)
-{
- if (bitmap.isNull())
- return 0;
- QBitmap bm = bitmap;
- qt_x11SetScreen(bm, screen);
-
- QX11PlatformPixmap *that = qt_x11Pixmap(bm);
- const QXcbX11Info *x = that->x11_info();
- Pixmap mask = XCreatePixmap(x->display(), RootWindow(x->display(), screen),
- that->width(), that->height(), 1);
- GC gc = XCreateGC(x->display(), mask, 0, 0);
- XCopyArea(x->display(), that->handle(), mask, gc, 0, 0,
- that->width(), that->height(), 0, 0);
- XFreeGC(x->display(), gc);
- return mask;
-}
-
-Drawable qt_x11Handle(const QPixmap &pixmap)
-{
- if (pixmap.isNull())
- return XNone;
-
- if (pixmap.handle()->classId() != QPlatformPixmap::X11Class)
- return XNone;
-
- return static_cast<const QX11PlatformPixmap *>(pixmap.handle())->handle();
-}
-
-
-/*****************************************************************************
- Internal functions
- *****************************************************************************/
-
-//extern const uchar *qt_get_bitflip_array(); // defined in qimage.cpp
-
-// Returns position of highest bit set or -1 if none
-static int highest_bit(uint v)
-{
- int i;
- uint b = (uint)1 << 31;
- for (i=31; ((b & v) == 0) && i>=0; i--)
- b >>= 1;
- return i;
-}
-
-// Counts the number of bits set in 'v'
-static uint n_bits(uint v)
-{
- int i = 0;
- while (v) {
- v = v & (v - 1);
- i++;
- }
- return i;
-}
-
-static uint *red_scale_table = nullptr;
-static uint *green_scale_table = nullptr;
-static uint *blue_scale_table = nullptr;
-
-static void cleanup_scale_tables()
-{
- delete[] red_scale_table;
- delete[] green_scale_table;
- delete[] blue_scale_table;
-}
-
-/*
- Could do smart bitshifting, but the "obvious" algorithm only works for
- nBits >= 4. This is more robust.
-*/
-static void build_scale_table(uint **table, uint nBits)
-{
- if (nBits > 7) {
- qWarning("build_scale_table: internal error, nBits = %i", nBits);
- return;
- }
- if (!*table) {
- static bool firstTable = true;
- if (firstTable) {
- qAddPostRoutine(cleanup_scale_tables);
- firstTable = false;
- }
- *table = new uint[256];
- }
- int maxVal = (1 << nBits) - 1;
- int valShift = 8 - nBits;
- int i;
- for (i = 0 ; i < maxVal + 1 ; i++)
- (*table)[i << valShift] = i*255/maxVal;
-}
-
-static int defaultScreen = -1;
-
-int qt_x11SetDefaultScreen(int screen)
-{
- int old = defaultScreen;
- defaultScreen = screen;
- return old;
-}
-
-void qt_x11SetScreen(QPixmap &pixmap, int screen)
-{
- if (pixmap.paintingActive()) {
- qWarning("qt_x11SetScreen(): Cannot change screens during painting");
- return;
- }
-
- if (pixmap.isNull())
- return;
-
- if (pixmap.handle()->classId() != QPlatformPixmap::X11Class)
- return;
-
- if (screen < 0)
- screen = QXcbX11Info::appScreen();
-
- QX11PlatformPixmap *pm = static_cast<QX11PlatformPixmap *>(pixmap.handle());
- if (screen == pm->xinfo.screen())
- return; // nothing to do
-
- if (pixmap.isNull()) {
- pm->xinfo = QXcbX11Info::fromScreen(screen);
- return;
- }
-
-#if 0
- qDebug("qt_x11SetScreen for %p from %d to %d. Size is %d/%d", pm, pm->xinfo.screen(), screen, pm->width(), pm->height());
-#endif
-
- qt_x11SetDefaultScreen(screen);
- pixmap = qt_toX11Pixmap(pixmap.toImage());
-}
-
-/*****************************************************************************
- QPixmap member functions
- *****************************************************************************/
-
-QBasicAtomicInt qt_pixmap_serial = Q_BASIC_ATOMIC_INITIALIZER(0);
-int Q_GUI_EXPORT qt_x11_preferred_pixmap_depth = 0;
-
-QX11PlatformPixmap::QX11PlatformPixmap(PixelType pixelType)
- : QPlatformPixmap(pixelType, X11Class), hd(0),
- flags(Uninitialized), x11_mask(0), picture(0), mask_picture(0), hd2(0),
- dpr(1.0), pengine(0)
-{}
-
-QX11PlatformPixmap::~QX11PlatformPixmap()
-{
- // Cleanup hooks have to be called before the handles are freed
- if (is_cached) {
- QImagePixmapCleanupHooks::executePlatformPixmapDestructionHooks(this);
- is_cached = false;
- }
-
- release();
-}
-
-QPlatformPixmap *QX11PlatformPixmap::createCompatiblePlatformPixmap() const
-{
- QX11PlatformPixmap *p = new QX11PlatformPixmap(pixelType());
- p->setDevicePixelRatio(devicePixelRatio());
- return p;
-}
-
-void QX11PlatformPixmap::resize(int width, int height)
-{
- setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
-
- w = width;
- h = height;
- is_null = (w <= 0 || h <= 0);
-
- if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
- xinfo = QXcbX11Info::fromScreen(defaultScreen);
- }
-
- int dd = xinfo.depth();
-
- if (qt_x11_preferred_pixmap_depth)
- dd = qt_x11_preferred_pixmap_depth;
-
- bool make_null = w <= 0 || h <= 0; // create null pixmap
- d = (pixelType() == BitmapType ? 1 : dd);
- if (make_null || d == 0) {
- w = 0;
- h = 0;
- is_null = true;
- hd = 0;
- picture = 0;
- d = 0;
- if (!make_null)
- qWarning("QPixmap: Invalid pixmap parameters");
- return;
- }
- hd = XCreatePixmap(xinfo.display(),
- RootWindow(xinfo.display(), xinfo.screen()),
- w, h, d);
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- XRenderPictFormat *format = d == 1
- ? XRenderFindStandardFormat(xinfo.display(), PictStandardA1)
- : XRenderFindVisualFormat(xinfo.display(), (Visual *) xinfo.visual());
- picture = XRenderCreatePicture(xinfo.display(), hd, format, 0, 0);
- }
-#endif // QT_CONFIG(xrender)
-}
-
-struct QX11AlphaDetector
-{
- bool hasAlpha() const {
- if (checked)
- return has;
- // Will implicitly also check format and return quickly for opaque types...
- checked = true;
- has = image->isNull() ? false : const_cast<QImage *>(image)->data_ptr()->checkForAlphaPixels();
- return has;
- }
-
- bool hasXRenderAndAlpha() const {
- if (!X11->use_xrender)
- return false;
- return hasAlpha();
- }
-
- QX11AlphaDetector(const QImage *i, Qt::ImageConversionFlags flags)
- : image(i), checked(false), has(false)
- {
- if (flags & Qt::NoOpaqueDetection) {
- checked = true;
- has = image->hasAlphaChannel();
- }
- }
-
- const QImage *image;
- mutable bool checked;
- mutable bool has;
-};
-
-void QX11PlatformPixmap::fromImage(const QImage &img, Qt::ImageConversionFlags flags)
-{
- setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
-
- w = img.width();
- h = img.height();
- d = img.depth();
- is_null = (w <= 0 || h <= 0);
- setDevicePixelRatio(img.devicePixelRatio());
-
- if (is_null) {
- w = h = 0;
- return;
- }
-
- if (defaultScreen >= 0 && defaultScreen != xinfo.screen()) {
- xinfo = QXcbX11Info::fromScreen(defaultScreen);
- }
-
- if (pixelType() == BitmapType) {
- bitmapFromImage(img);
- return;
- }
-
- if (uint(w) >= 32768 || uint(h) >= 32768) {
- w = h = 0;
- is_null = true;
- return;
- }
-
- QX11AlphaDetector alphaCheck(&img, flags);
- int dd = alphaCheck.hasXRenderAndAlpha() ? 32 : xinfo.depth();
-
- if (qt_x11_preferred_pixmap_depth)
- dd = qt_x11_preferred_pixmap_depth;
-
- QImage image = img;
-
- // must be monochrome
- if (dd == 1 || (flags & Qt::ColorMode_Mask) == Qt::MonoOnly) {
- if (d != 1) {
- // dither
- image = image.convertToFormat(QImage::Format_MonoLSB, flags);
- d = 1;
- }
- } else { // can be both
- bool conv8 = false;
- if (d > 8 && dd <= 8) { // convert to 8 bit
- if ((flags & Qt::DitherMode_Mask) == Qt::AutoDither)
- flags = (flags & ~Qt::DitherMode_Mask)
- | Qt::PreferDither;
- conv8 = true;
- } else if ((flags & Qt::ColorMode_Mask) == Qt::ColorOnly) {
- conv8 = (d == 1); // native depth wanted
- } else if (d == 1) {
- if (image.colorCount() == 2) {
- QRgb c0 = image.color(0); // Auto: convert to best
- QRgb c1 = image.color(1);
- conv8 = qMin(c0,c1) != qRgb(0,0,0) || qMax(c0,c1) != qRgb(255,255,255);
- } else {
- // eg. 1-color monochrome images (they do exist).
- conv8 = true;
- }
- }
- if (conv8) {
- image = image.convertToFormat(QImage::Format_Indexed8, flags);
- d = 8;
- }
- }
-
- if (d == 1 || image.format() > QImage::Format_ARGB32_Premultiplied) {
- QImage::Format fmt = QImage::Format_RGB32;
- if (alphaCheck.hasXRenderAndAlpha() && d > 1)
- fmt = QImage::Format_ARGB32_Premultiplied;
- image = image.convertToFormat(fmt, flags);
- fromImage(image, Qt::AutoColor);
- return;
- }
-
- Display *dpy = xinfo.display();
- Visual *visual = (Visual *)xinfo.visual();
- XImage *xi = nullptr;
- bool trucol = (visual->c_class >= TrueColor);
- size_t nbytes = image.sizeInBytes();
- uchar *newbits= nullptr;
-
-#if QT_CONFIG(xrender)
- if (alphaCheck.hasXRenderAndAlpha()) {
- const QImage &cimage = image;
-
- d = 32;
-
- if (QXcbX11Info::appDepth() != d) {
- xinfo.setDepth(d);
- }
-
- hd = XCreatePixmap(dpy, RootWindow(dpy, xinfo.screen()), w, h, d);
- picture = XRenderCreatePicture(dpy, hd,
- XRenderFindStandardFormat(dpy, PictStandardARGB32), 0, 0);
-
- xi = XCreateImage(dpy, visual, d, ZPixmap, 0, 0, w, h, 32, 0);
- Q_CHECK_PTR(xi);
- newbits = (uchar *)malloc(xi->bytes_per_line*h);
- Q_CHECK_PTR(newbits);
- xi->data = (char *)newbits;
-
- switch (cimage.format()) {
- case QImage::Format_Indexed8: {
- QList<QRgb> colorTable = cimage.colorTable();
- uint *xidata = (uint *)xi->data;
- for (int y = 0; y < h; ++y) {
- const uchar *p = cimage.scanLine(y);
- for (int x = 0; x < w; ++x) {
- const QRgb rgb = colorTable[p[x]];
- const int a = qAlpha(rgb);
- if (a == 0xff)
- *xidata = rgb;
- else
- // RENDER expects premultiplied alpha
- *xidata = qRgba(qt_div_255(qRed(rgb) * a),
- qt_div_255(qGreen(rgb) * a),
- qt_div_255(qBlue(rgb) * a),
- a);
- ++xidata;
- }
- }
- }
- break;
- case QImage::Format_RGB32: {
- uint *xidata = (uint *)xi->data;
- for (int y = 0; y < h; ++y) {
- const QRgb *p = (const QRgb *) cimage.scanLine(y);
- for (int x = 0; x < w; ++x)
- *xidata++ = p[x] | 0xff000000;
- }
- }
- break;
- case QImage::Format_ARGB32: {
- uint *xidata = (uint *)xi->data;
- for (int y = 0; y < h; ++y) {
- const QRgb *p = (const QRgb *) cimage.scanLine(y);
- for (int x = 0; x < w; ++x) {
- const QRgb rgb = p[x];
- const int a = qAlpha(rgb);
- if (a == 0xff)
- *xidata = rgb;
- else
- // RENDER expects premultiplied alpha
- *xidata = qRgba(qt_div_255(qRed(rgb) * a),
- qt_div_255(qGreen(rgb) * a),
- qt_div_255(qBlue(rgb) * a),
- a);
- ++xidata;
- }
- }
-
- }
- break;
- case QImage::Format_ARGB32_Premultiplied: {
- uint *xidata = (uint *)xi->data;
- for (int y = 0; y < h; ++y) {
- const QRgb *p = (const QRgb *) cimage.scanLine(y);
- memcpy(xidata, p, w*sizeof(QRgb));
- xidata += w;
- }
- }
- break;
- default:
- Q_ASSERT(false);
- }
-
- if ((xi->byte_order == MSBFirst) != (QSysInfo::ByteOrder == QSysInfo::BigEndian)) {
- uint *xidata = (uint *)xi->data;
- uint *xiend = xidata + w*h;
- while (xidata < xiend) {
- *xidata = (*xidata >> 24)
- | ((*xidata >> 8) & 0xff00)
- | ((*xidata << 8) & 0xff0000)
- | (*xidata << 24);
- ++xidata;
- }
- }
-
- GC gc = XCreateGC(dpy, hd, 0, 0);
- XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h);
- XFreeGC(dpy, gc);
-
- qSafeXDestroyImage(xi);
-
- return;
- }
-#endif // QT_CONFIG(xrender)
-
- if (trucol) { // truecolor display
- if (image.format() == QImage::Format_ARGB32_Premultiplied)
- image = image.convertToFormat(QImage::Format_ARGB32);
-
- const QImage &cimage = image;
- QRgb pix[256]; // pixel translation table
- const bool d8 = (d == 8);
- const uint red_mask = (uint)visual->red_mask;
- const uint green_mask = (uint)visual->green_mask;
- const uint blue_mask = (uint)visual->blue_mask;
- const int red_shift = highest_bit(red_mask) - 7;
- const int green_shift = highest_bit(green_mask) - 7;
- const int blue_shift = highest_bit(blue_mask) - 7;
- const uint rbits = highest_bit(red_mask) - lowest_bit(red_mask) + 1;
- const uint gbits = highest_bit(green_mask) - lowest_bit(green_mask) + 1;
- const uint bbits = highest_bit(blue_mask) - lowest_bit(blue_mask) + 1;
-
- if (d8) { // setup pixel translation
- QList<QRgb> ctable = cimage.colorTable();
- for (int i=0; i < cimage.colorCount(); i++) {
- int r = qRed (ctable[i]);
- int g = qGreen(ctable[i]);
- int b = qBlue (ctable[i]);
- r = red_shift > 0 ? r << red_shift : r >> -red_shift;
- g = green_shift > 0 ? g << green_shift : g >> -green_shift;
- b = blue_shift > 0 ? b << blue_shift : b >> -blue_shift;
- pix[i] = (b & blue_mask) | (g & green_mask) | (r & red_mask)
- | ~(blue_mask | green_mask | red_mask);
- }
- }
-
- xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
- Q_CHECK_PTR(xi);
- newbits = (uchar *)malloc(xi->bytes_per_line*h);
- Q_CHECK_PTR(newbits);
- if (!newbits) // no memory
- return;
- int bppc = xi->bits_per_pixel;
-
- bool contig_bits = n_bits(red_mask) == rbits &&
- n_bits(green_mask) == gbits &&
- n_bits(blue_mask) == bbits;
- bool dither_tc =
- // Want it?
- (flags & Qt::Dither_Mask) != Qt::ThresholdDither &&
- (flags & Qt::DitherMode_Mask) != Qt::AvoidDither &&
- // Need it?
- bppc < 24 && !d8 &&
- // Can do it? (Contiguous bits?)
- contig_bits;
-
- static bool init=false;
- static int D[16][16];
- if (dither_tc && !init) {
- // I also contributed this code to XV - WWA.
- /*
- The dither matrix, D, is obtained with this formula:
-
- D2 = [0 2]
- [3 1]
-
-
- D2*n = [4*Dn 4*Dn+2*Un]
- [4*Dn+3*Un 4*Dn+1*Un]
- */
- int n,i,j;
- init=1;
-
- /* Set D2 */
- D[0][0]=0;
- D[1][0]=2;
- D[0][1]=3;
- D[1][1]=1;
-
- /* Expand using recursive definition given above */
- for (n=2; n<16; n*=2) {
- for (i=0; i<n; i++) {
- for (j=0; j<n; j++) {
- D[i][j]*=4;
- D[i+n][j]=D[i][j]+2;
- D[i][j+n]=D[i][j]+3;
- D[i+n][j+n]=D[i][j]+1;
- }
- }
- }
- init=true;
- }
-
- enum { BPP8,
- BPP16_565, BPP16_555,
- BPP16_MSB, BPP16_LSB,
- BPP24_888,
- BPP24_MSB, BPP24_LSB,
- BPP32_8888,
- BPP32_MSB, BPP32_LSB
- } mode = BPP8;
-
- bool same_msb_lsb = (xi->byte_order == MSBFirst) == (QSysInfo::ByteOrder == QSysInfo::BigEndian);
-
- if (bppc == 8) // 8 bit
- mode = BPP8;
- else if (bppc == 16) { // 16 bit MSB/LSB
- if (red_shift == 8 && green_shift == 3 && blue_shift == -3 && !d8 && same_msb_lsb)
- mode = BPP16_565;
- else if (red_shift == 7 && green_shift == 2 && blue_shift == -3 && !d8 && same_msb_lsb)
- mode = BPP16_555;
- else
- mode = (xi->byte_order == LSBFirst) ? BPP16_LSB : BPP16_MSB;
- } else if (bppc == 24) { // 24 bit MSB/LSB
- if (red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb)
- mode = BPP24_888;
- else
- mode = (xi->byte_order == LSBFirst) ? BPP24_LSB : BPP24_MSB;
- } else if (bppc == 32) { // 32 bit MSB/LSB
- if (red_shift == 16 && green_shift == 8 && blue_shift == 0 && !d8 && same_msb_lsb)
- mode = BPP32_8888;
- else
- mode = (xi->byte_order == LSBFirst) ? BPP32_LSB : BPP32_MSB;
- } else
- qFatal("Logic error 3");
-
-#define GET_PIXEL \
- uint pixel; \
- if (d8) pixel = pix[*src++]; \
- else { \
- int r = qRed (*p); \
- int g = qGreen(*p); \
- int b = qBlue (*p++); \
- r = red_shift > 0 \
- ? r << red_shift : r >> -red_shift; \
- g = green_shift > 0 \
- ? g << green_shift : g >> -green_shift; \
- b = blue_shift > 0 \
- ? b << blue_shift : b >> -blue_shift; \
- pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask) \
- | ~(blue_mask | green_mask | red_mask); \
- }
-
-#define GET_PIXEL_DITHER_TC \
- int r = qRed (*p); \
- int g = qGreen(*p); \
- int b = qBlue (*p++); \
- const int thres = D[x%16][y%16]; \
- if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
- > thres) \
- r += (1<<(8-rbits)); \
- if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
- > thres) \
- g += (1<<(8-gbits)); \
- if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
- > thres) \
- b += (1<<(8-bbits)); \
- r = red_shift > 0 \
- ? r << red_shift : r >> -red_shift; \
- g = green_shift > 0 \
- ? g << green_shift : g >> -green_shift; \
- b = blue_shift > 0 \
- ? b << blue_shift : b >> -blue_shift; \
- uint pixel = (r & red_mask)|(g & green_mask) | (b & blue_mask);
-
-// again, optimized case
-// can't be optimized that much :(
-#define GET_PIXEL_DITHER_TC_OPT(red_shift,green_shift,blue_shift,red_mask,green_mask,blue_mask, \
- rbits,gbits,bbits) \
- const int thres = D[x%16][y%16]; \
- int r = qRed (*p); \
- if (r <= (255-(1<<(8-rbits))) && ((r<<rbits) & 255) \
- > thres) \
- r += (1<<(8-rbits)); \
- int g = qGreen(*p); \
- if (g <= (255-(1<<(8-gbits))) && ((g<<gbits) & 255) \
- > thres) \
- g += (1<<(8-gbits)); \
- int b = qBlue (*p++); \
- if (b <= (255-(1<<(8-bbits))) && ((b<<bbits) & 255) \
- > thres) \
- b += (1<<(8-bbits)); \
- uint pixel = ((r red_shift) & red_mask) \
- | ((g green_shift) & green_mask) \
- | ((b blue_shift) & blue_mask);
-
-#define CYCLE(body) \
- for (int y=0; y<h; y++) { \
- const uchar* src = cimage.scanLine(y); \
- uchar* dst = newbits + xi->bytes_per_line*y; \
- const QRgb* p = (const QRgb *)src; \
- body \
- }
-
- if (dither_tc) {
- switch (mode) {
- case BPP16_565:
- CYCLE(
- quint16* dst16 = (quint16*)dst;
- for (int x=0; x<w; x++) {
- GET_PIXEL_DITHER_TC_OPT(<<8,<<3,>>3,0xf800,0x7e0,0x1f,5,6,5)
- *dst16++ = pixel;
- }
- )
- break;
- case BPP16_555:
- CYCLE(
- quint16* dst16 = (quint16*)dst;
- for (int x=0; x<w; x++) {
- GET_PIXEL_DITHER_TC_OPT(<<7,<<2,>>3,0x7c00,0x3e0,0x1f,5,5,5)
- *dst16++ = pixel;
- }
- )
- break;
- case BPP16_MSB: // 16 bit MSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL_DITHER_TC
- *dst++ = (pixel >> 8);
- *dst++ = pixel;
- }
- )
- break;
- case BPP16_LSB: // 16 bit LSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL_DITHER_TC
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- }
- )
- break;
- default:
- qFatal("Logic error");
- }
- } else {
- switch (mode) {
- case BPP8: // 8 bit
- CYCLE(
- Q_UNUSED(p);
- for (int x=0; x<w; x++)
- *dst++ = pix[*src++];
- )
- break;
- case BPP16_565:
- CYCLE(
- quint16* dst16 = (quint16*)dst;
- for (int x = 0; x < w; x++) {
- *dst16++ = ((*p >> 8) & 0xf800)
- | ((*p >> 5) & 0x7e0)
- | ((*p >> 3) & 0x1f);
- ++p;
- }
- )
- break;
- case BPP16_555:
- CYCLE(
- quint16* dst16 = (quint16*)dst;
- for (int x=0; x<w; x++) {
- *dst16++ = ((*p >> 9) & 0x7c00)
- | ((*p >> 6) & 0x3e0)
- | ((*p >> 3) & 0x1f);
- ++p;
- }
- )
- break;
- case BPP16_MSB: // 16 bit MSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = (pixel >> 8);
- *dst++ = pixel;
- }
- )
- break;
- case BPP16_LSB: // 16 bit LSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- }
- )
- break;
- case BPP24_888:
- CYCLE(
- if (QSysInfo::ByteOrder == QSysInfo::BigEndian) {
- for (int x=0; x<w; x++) {
- *dst++ = qRed (*p);
- *dst++ = qGreen(*p);
- *dst++ = qBlue (*p++);
- }
- } else {
- for (int x=0; x<w; x++) {
- *dst++ = qBlue (*p);
- *dst++ = qGreen(*p);
- *dst++ = qRed (*p++);
- }
- }
- )
- break;
- case BPP24_MSB: // 24 bit MSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel >> 16;
- *dst++ = pixel >> 8;
- *dst++ = pixel;
- }
- )
- break;
- case BPP24_LSB: // 24 bit LSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- *dst++ = pixel >> 16;
- }
- )
- break;
- case BPP32_8888:
- CYCLE(
- memcpy(dst, p, w * 4);
- )
- break;
- case BPP32_MSB: // 32 bit MSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel >> 24;
- *dst++ = pixel >> 16;
- *dst++ = pixel >> 8;
- *dst++ = pixel;
- }
- )
- break;
- case BPP32_LSB: // 32 bit LSB
- CYCLE(
- for (int x=0; x<w; x++) {
- GET_PIXEL
- *dst++ = pixel;
- *dst++ = pixel >> 8;
- *dst++ = pixel >> 16;
- *dst++ = pixel >> 24;
- }
- )
- break;
- default:
- qFatal("Logic error 2");
- }
- }
- xi->data = (char *)newbits;
- }
-
- if (d == 8 && !trucol) { // 8 bit pixmap
- int pop[256]; // pixel popularity
-
- if (image.colorCount() == 0)
- image.setColorCount(1);
-
- const QImage &cimage = image;
- memset(pop, 0, sizeof(int)*256); // reset popularity array
- for (int i = 0; i < h; i++) { // for each scanline...
- const uchar* p = cimage.scanLine(i);
- const uchar *end = p + w;
- while (p < end) // compute popularity
- pop[*p++]++;
- }
-
- newbits = (uchar *)malloc(nbytes); // copy image into newbits
- Q_CHECK_PTR(newbits);
- if (!newbits) // no memory
- return;
- uchar* p = newbits;
- memcpy(p, cimage.bits(), nbytes); // copy image data into newbits
-
- /*
- * The code below picks the most important colors. It is based on the
- * diversity algorithm, implemented in XV 3.10. XV is (C) by John Bradley.
- */
-
- struct PIX { // pixel sort element
- uchar r,g,b,n; // color + pad
- int use; // popularity
- int index; // index in colormap
- int mindist;
- };
- int ncols = 0;
- for (int i=0; i< cimage.colorCount(); i++) { // compute number of colors
- if (pop[i] > 0)
- ncols++;
- }
- for (int i = cimage.colorCount(); i < 256; i++) // ignore out-of-range pixels
- pop[i] = 0;
-
- // works since we make sure above to have at least
- // one color in the image
- if (ncols == 0)
- ncols = 1;
-
- PIX pixarr[256]; // pixel array
- PIX pixarr_sorted[256]; // pixel array (sorted)
- memset(pixarr, 0, ncols*sizeof(PIX));
- PIX *px = &pixarr[0];
- int maxpop = 0;
- int maxpix = 0;
- uint j = 0;
- QList<QRgb> ctable = cimage.colorTable();
- for (int i = 0; i < 256; i++) { // init pixel array
- if (pop[i] > 0) {
- px->r = qRed (ctable[i]);
- px->g = qGreen(ctable[i]);
- px->b = qBlue (ctable[i]);
- px->n = 0;
- px->use = pop[i];
- if (pop[i] > maxpop) { // select most popular entry
- maxpop = pop[i];
- maxpix = j;
- }
- px->index = i;
- px->mindist = 1000000;
- px++;
- j++;
- }
- }
- pixarr_sorted[0] = pixarr[maxpix];
- pixarr[maxpix].use = 0;
-
- for (int i = 1; i < ncols; i++) { // sort pixels
- int minpix = -1, mindist = -1;
- px = &pixarr_sorted[i-1];
- int r = px->r;
- int g = px->g;
- int b = px->b;
- int dist;
- if ((i & 1) || i<10) { // sort on max distance
- for (int j=0; j<ncols; j++) {
- px = &pixarr[j];
- if (px->use) {
- dist = (px->r - r)*(px->r - r) +
- (px->g - g)*(px->g - g) +
- (px->b - b)*(px->b - b);
- if (px->mindist > dist)
- px->mindist = dist;
- if (px->mindist > mindist) {
- mindist = px->mindist;
- minpix = j;
- }
- }
- }
- } else { // sort on max popularity
- for (int j=0; j<ncols; j++) {
- px = &pixarr[j];
- if (px->use) {
- dist = (px->r - r)*(px->r - r) +
- (px->g - g)*(px->g - g) +
- (px->b - b)*(px->b - b);
- if (px->mindist > dist)
- px->mindist = dist;
- if (px->use > mindist) {
- mindist = px->use;
- minpix = j;
- }
- }
- }
- }
- pixarr_sorted[i] = pixarr[minpix];
- pixarr[minpix].use = 0;
- }
-
- QXcbColormap cmap = QXcbColormap::instance(xinfo.screen());
- uint pix[256]; // pixel translation table
- px = &pixarr_sorted[0];
- for (int i = 0; i < ncols; i++) { // allocate colors
- QColor c(px->r, px->g, px->b);
- pix[px->index] = cmap.pixel(c);
- px++;
- }
-
- p = newbits;
- for (size_t i = 0; i < nbytes; i++) { // translate pixels
- *p = pix[*p];
- p++;
- }
- }
-
- if (!xi) { // X image not created
- xi = XCreateImage(dpy, visual, dd, ZPixmap, 0, 0, w, h, 32, 0);
- if (xi->bits_per_pixel == 16) { // convert 8 bpp ==> 16 bpp
- ushort *p2;
- int p2inc = xi->bytes_per_line/sizeof(ushort);
- ushort *newerbits = (ushort *)malloc(xi->bytes_per_line * h);
- Q_CHECK_PTR(newerbits);
- if (!newerbits) // no memory
- return;
- uchar* p = newbits;
- for (int y = 0; y < h; y++) { // OOPS: Do right byte order!!
- p2 = newerbits + p2inc*y;
- for (int x = 0; x < w; x++)
- *p2++ = *p++;
- }
- free(newbits);
- newbits = (uchar *)newerbits;
- } else if (xi->bits_per_pixel != 8) {
- qWarning("QPixmap::fromImage: Display not supported "
- "(bpp=%d)", xi->bits_per_pixel);
- }
- xi->data = (char *)newbits;
- }
-
- hd = XCreatePixmap(dpy,
- RootWindow(dpy, xinfo.screen()),
- w, h, dd);
-
- GC gc = XCreateGC(dpy, hd, 0, 0);
- XPutImage(dpy, hd, gc, xi, 0, 0, 0, 0, w, h);
- XFreeGC(dpy, gc);
-
- qSafeXDestroyImage(xi);
- d = dd;
-
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- XRenderPictFormat *format = d == 1
- ? XRenderFindStandardFormat(dpy, PictStandardA1)
- : XRenderFindVisualFormat(dpy, (Visual *)xinfo.visual());
- picture = XRenderCreatePicture(dpy, hd, format, 0, 0);
- }
-#endif
-
- if (alphaCheck.hasAlpha()) {
- QBitmap m = QBitmap::fromImage(image.createAlphaMask(flags));
- setMask(m);
- }
-}
-
-void QX11PlatformPixmap::copy(const QPlatformPixmap *data, const QRect &rect)
-{
- if (data->pixelType() == BitmapType) {
- fromImage(data->toImage().copy(rect), Qt::AutoColor);
- return;
- }
-
- const QX11PlatformPixmap *x11Data = static_cast<const QX11PlatformPixmap*>(data);
-
- setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
-
- flags &= ~Uninitialized;
- xinfo = x11Data->xinfo;
- d = x11Data->d;
- w = rect.width();
- h = rect.height();
- is_null = (w <= 0 || h <= 0);
- hd = XCreatePixmap(xinfo.display(),
- RootWindow(xinfo.display(), x11Data->xinfo.screen()),
- w, h, d);
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- XRenderPictFormat *format = d == 32
- ? XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32)
- : XRenderFindVisualFormat(xinfo.display(), (Visual *)xinfo.visual());
- picture = XRenderCreatePicture(xinfo.display(), hd, format, 0, 0);
- }
-#endif // QT_CONFIG(xrender)
- if (x11Data->x11_mask) {
- x11_mask = XCreatePixmap(xinfo.display(), hd, w, h, 1);
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- mask_picture = XRenderCreatePicture(xinfo.display(), x11_mask,
- XRenderFindStandardFormat(xinfo.display(), PictStandardA1), 0, 0);
- XRenderPictureAttributes attrs;
- attrs.alpha_map = x11Data->mask_picture;
- XRenderChangePicture(xinfo.display(), x11Data->picture, CPAlphaMap, &attrs);
- }
-#endif
- }
-
-#if QT_CONFIG(xrender)
- if (x11Data->picture && x11Data->d == 32) {
- XRenderComposite(xinfo.display(), PictOpSrc,
- x11Data->picture, 0, picture,
- rect.x(), rect.y(), 0, 0, 0, 0, w, h);
- } else
-#endif
- {
- GC gc = XCreateGC(xinfo.display(), hd, 0, 0);
- XCopyArea(xinfo.display(), x11Data->hd, hd, gc,
- rect.x(), rect.y(), w, h, 0, 0);
- if (x11Data->x11_mask) {
- GC monogc = XCreateGC(xinfo.display(), x11_mask, 0, 0);
- XCopyArea(xinfo.display(), x11Data->x11_mask, x11_mask, monogc,
- rect.x(), rect.y(), w, h, 0, 0);
- XFreeGC(xinfo.display(), monogc);
- }
- XFreeGC(xinfo.display(), gc);
- }
-}
-
-bool QX11PlatformPixmap::scroll(int dx, int dy, const QRect &rect)
-{
- GC gc = XCreateGC(xinfo.display(), hd, 0, 0);
- XCopyArea(xinfo.display(), hd, hd, gc,
- rect.left(), rect.top(), rect.width(), rect.height(),
- rect.left() + dx, rect.top() + dy);
- XFreeGC(xinfo.display(), gc);
- return true;
-}
-
-int QX11PlatformPixmap::metric(QPaintDevice::PaintDeviceMetric metric) const
-{
- switch (metric) {
- case QPaintDevice::PdmDevicePixelRatio:
- return devicePixelRatio();
- break;
- case QPaintDevice::PdmDevicePixelRatioScaled:
- return devicePixelRatio() * QPaintDevice::devicePixelRatioFScale();
- break;
- case QPaintDevice::PdmWidth:
- return w;
- case QPaintDevice::PdmHeight:
- return h;
- case QPaintDevice::PdmNumColors:
- return 1 << d;
- case QPaintDevice::PdmDepth:
- return d;
- case QPaintDevice::PdmWidthMM: {
- const int screen = xinfo.screen();
- const int mm = DisplayWidthMM(xinfo.display(), screen) * w
- / DisplayWidth(xinfo.display(), screen);
- return mm;
- }
- case QPaintDevice::PdmHeightMM: {
- const int screen = xinfo.screen();
- const int mm = (DisplayHeightMM(xinfo.display(), screen) * h)
- / DisplayHeight(xinfo.display(), screen);
- return mm;
- }
- case QPaintDevice::PdmDpiX:
- case QPaintDevice::PdmPhysicalDpiX:
- return QXcbX11Info::appDpiX(xinfo.screen());
- case QPaintDevice::PdmDpiY:
- case QPaintDevice::PdmPhysicalDpiY:
- return QXcbX11Info::appDpiY(xinfo.screen());
- default:
- qWarning("QX11PlatformPixmap::metric(): Invalid metric");
- return 0;
- }
-}
-
-void QX11PlatformPixmap::fill(const QColor &fillColor)
-{
- if (fillColor.alpha() != 255) {
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- if (!picture || d != 32)
- convertToARGB32(/*preserveContents = */false);
-
- ::Picture src = X11->getSolidFill(xinfo.screen(), fillColor);
- XRenderComposite(xinfo.display(), PictOpSrc, src, 0, picture,
- 0, 0, width(), height(),
- 0, 0, width(), height());
- } else
-#endif
- {
- QImage im(width(), height(), QImage::Format_ARGB32_Premultiplied);
- im.fill(PREMUL(fillColor.rgba()));
- release();
- fromImage(im, Qt::AutoColor | Qt::OrderedAlphaDither);
- }
- return;
- }
-
- GC gc = XCreateGC(xinfo.display(), hd, 0, 0);
- if (depth() == 1) {
- XSetForeground(xinfo.display(), gc, qGray(fillColor.rgb()) > 127 ? 0 : 1);
- } else if (X11->use_xrender && d >= 24) {
- XSetForeground(xinfo.display(), gc, fillColor.rgba());
- } else {
- XSetForeground(xinfo.display(), gc,
- QXcbColormap::instance(xinfo.screen()).pixel(fillColor));
- }
- XFillRectangle(xinfo.display(), hd, gc, 0, 0, width(), height());
- XFreeGC(xinfo.display(), gc);
-}
-
-QBitmap QX11PlatformPixmap::mask() const
-{
- QBitmap mask;
-#if QT_CONFIG(xrender)
- if (picture && d == 32) {
- // #### slow - there must be a better way..
- mask = QBitmap::fromImage(toImage().createAlphaMask());
- } else
-#endif
- if (d == 1) {
- QX11PlatformPixmap *that = const_cast<QX11PlatformPixmap*>(this);
- mask = QBitmap::fromPixmap(QPixmap(that));
- } else {
- mask = mask_to_bitmap(xinfo.screen());
- }
- return mask;
-}
-
-void QX11PlatformPixmap::setMask(const QBitmap &newmask)
-{
- if (newmask.isNull()) { // clear mask
-#if QT_CONFIG(xrender)
- if (picture && d == 32) {
- QX11PlatformPixmap newData(pixelType());
- newData.resize(w, h);
- newData.fill(Qt::black);
- XRenderComposite(xinfo.display(), PictOpOver,
- picture, 0, newData.picture,
- 0, 0, 0, 0, 0, 0, w, h);
- release();
- *this = newData;
- // the new QX11PlatformPixmap object isn't referenced yet, so
- // ref it
- ref.ref();
-
- // the below is to make sure the QX11PlatformPixmap destructor
- // doesn't delete our newly created render picture
- newData.hd = 0;
- newData.x11_mask = 0;
- newData.picture = 0;
- newData.mask_picture = 0;
- newData.hd2 = 0;
- } else
-#endif
- if (x11_mask) {
-#if QT_CONFIG(xrender)
- if (picture) {
- XRenderPictureAttributes attrs;
- attrs.alpha_map = 0;
- XRenderChangePicture(xinfo.display(), picture, CPAlphaMap,
- &attrs);
- }
- if (mask_picture)
- XRenderFreePicture(xinfo.display(), mask_picture);
- mask_picture = 0;
-#endif
- XFreePixmap(xinfo.display(), x11_mask);
- x11_mask = 0;
- }
- return;
- }
-
-#if QT_CONFIG(xrender)
- if (picture && d == 32) {
- XRenderComposite(xinfo.display(), PictOpSrc,
- picture, qt_x11Pixmap(newmask)->x11PictureHandle(),
- picture, 0, 0, 0, 0, 0, 0, w, h);
- } else
-#endif
- if (depth() == 1) {
- XGCValues vals;
- vals.function = GXand;
- GC gc = XCreateGC(xinfo.display(), hd, GCFunction, &vals);
- XCopyArea(xinfo.display(), qt_x11Pixmap(newmask)->handle(), hd, gc, 0, 0,
- width(), height(), 0, 0);
- XFreeGC(xinfo.display(), gc);
- } else {
- // ##### should or the masks together
- if (x11_mask) {
- XFreePixmap(xinfo.display(), x11_mask);
-#if QT_CONFIG(xrender)
- if (mask_picture)
- XRenderFreePicture(xinfo.display(), mask_picture);
-#endif
- }
- x11_mask = QX11PlatformPixmap::bitmap_to_mask(newmask, xinfo.screen());
-#if QT_CONFIG(xrender)
- if (picture) {
- mask_picture = XRenderCreatePicture(xinfo.display(), x11_mask,
- XRenderFindStandardFormat(xinfo.display(), PictStandardA1), 0, 0);
- XRenderPictureAttributes attrs;
- attrs.alpha_map = mask_picture;
- XRenderChangePicture(xinfo.display(), picture, CPAlphaMap, &attrs);
- }
-#endif
- }
-}
-
-bool QX11PlatformPixmap::hasAlphaChannel() const
-{
- if (picture && d == 32)
- return true;
-
- if (x11_mask && d == 1)
- return true;
-
- return false;
-}
-
-QPixmap QX11PlatformPixmap::transformed(const QTransform &transform, Qt::TransformationMode mode) const
-{
- if (mode == Qt::SmoothTransformation || transform.type() >= QTransform::TxProject) {
- QImage image = toImage();
- return QPixmap::fromImage(image.transformed(transform, mode));
- }
-
- uint w = 0;
- uint h = 0; // size of target pixmap
- uint ws, hs; // size of source pixmap
- uchar *dptr; // data in target pixmap
- uint dbpl, dbytes; // bytes per line/bytes total
- uchar *sptr; // data in original pixmap
- int sbpl; // bytes per line in original
- int bpp; // bits per pixel
- bool depth1 = depth() == 1;
- Display *dpy = xinfo.display();
-
- ws = width();
- hs = height();
-
- QTransform mat(transform.m11(), transform.m12(), transform.m13(),
- transform.m21(), transform.m22(), transform.m23(),
- 0., 0., 1);
- bool complex_xform = false;
-
- if (mat.type() <= QTransform::TxScale) {
- h = qRound(qAbs(mat.m22()) * hs);
- w = qRound(qAbs(mat.m11()) * ws);
- } else { // rotation or shearing
- QPolygonF a(QRectF(0, 0, ws, hs));
- a = mat.map(a);
- QRect r = a.boundingRect().toAlignedRect();
- w = r.width();
- h = r.height();
- complex_xform = true;
- }
- mat = QPixmap::trueMatrix(mat, ws, hs); // true matrix
-
- bool invertible;
- mat = mat.inverted(&invertible); // invert matrix
-
- if (h == 0 || w == 0 || !invertible
- || qAbs(h) >= 32768 || qAbs(w) >= 32768 )
- // error, return null pixmap
- return QPixmap();
-
- XImage *xi = XGetImage(xinfo.display(), handle(), 0, 0, ws, hs, AllPlanes,
- depth1 ? XYPixmap : ZPixmap);
-
- if (!xi)
- return QPixmap();
-
- sbpl = xi->bytes_per_line;
- sptr = (uchar *)xi->data;
- bpp = xi->bits_per_pixel;
-
- if (depth1)
- dbpl = (w+7)/8;
- else
- dbpl = ((w*bpp+31)/32)*4;
- dbytes = dbpl*h;
-
- dptr = (uchar *)malloc(dbytes); // create buffer for bits
- Q_CHECK_PTR(dptr);
- if (depth1) // fill with zeros
- memset(dptr, 0, dbytes);
- else if (bpp == 8) // fill with background color
- memset(dptr, WhitePixel(xinfo.display(), xinfo.screen()), dbytes);
- else
- memset(dptr, 0, dbytes);
-
- // #define QT_DEBUG_XIMAGE
-#if defined(QT_DEBUG_XIMAGE)
- qDebug("----IMAGE--INFO--------------");
- qDebug("width............. %d", xi->width);
- qDebug("height............ %d", xi->height);
- qDebug("xoffset........... %d", xi->xoffset);
- qDebug("format............ %d", xi->format);
- qDebug("byte order........ %d", xi->byte_order);
- qDebug("bitmap unit....... %d", xi->bitmap_unit);
- qDebug("bitmap bit order.. %d", xi->bitmap_bit_order);
- qDebug("depth............. %d", xi->depth);
- qDebug("bytes per line.... %d", xi->bytes_per_line);
- qDebug("bits per pixel.... %d", xi->bits_per_pixel);
-#endif
-
- int type;
- if (xi->bitmap_bit_order == MSBFirst)
- type = QT_XFORM_TYPE_MSBFIRST;
- else
- type = QT_XFORM_TYPE_LSBFIRST;
- int xbpl, p_inc;
- if (depth1) {
- xbpl = (w+7)/8;
- p_inc = dbpl - xbpl;
- } else {
- xbpl = (w*bpp)/8;
- p_inc = dbpl - xbpl;
- }
-
- if (!qt_xForm_helper(mat, xi->xoffset, type, bpp, dptr, xbpl, p_inc, h, sptr, sbpl, ws, hs)){
- qWarning("QPixmap::transform: display not supported (bpp=%d)",bpp);
- QPixmap pm;
- free(dptr);
- return pm;
- }
-
- qSafeXDestroyImage(xi);
-
- if (depth1) { // mono bitmap
- QBitmap bm = QBitmap::fromData(QSize(w, h), dptr,
- BitmapBitOrder(xinfo.display()) == MSBFirst
- ? QImage::Format_Mono
- : QImage::Format_MonoLSB);
- free(dptr);
- return bm;
- } else { // color pixmap
- QX11PlatformPixmap *x11Data = new QX11PlatformPixmap(QPlatformPixmap::PixmapType);
- QPixmap pm(x11Data);
- x11Data->flags &= ~QX11PlatformPixmap::Uninitialized;
- x11Data->xinfo = xinfo;
- x11Data->d = d;
- x11Data->w = w;
- x11Data->h = h;
- x11Data->is_null = (w <= 0 || h <= 0);
- x11Data->hd = XCreatePixmap(xinfo.display(),
- RootWindow(xinfo.display(), xinfo.screen()),
- w, h, d);
- x11Data->setSerialNumber(qt_pixmap_serial.fetchAndAddRelaxed(1));
-
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- XRenderPictFormat *format = x11Data->d == 32
- ? XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32)
- : XRenderFindVisualFormat(xinfo.display(), (Visual *) x11Data->xinfo.visual());
- x11Data->picture = XRenderCreatePicture(xinfo.display(), x11Data->hd, format, 0, 0);
- }
-#endif // QT_CONFIG(xrender)
-
- GC gc = XCreateGC(xinfo.display(), x11Data->hd, 0, 0);
- xi = XCreateImage(dpy, (Visual*)x11Data->xinfo.visual(),
- x11Data->d,
- ZPixmap, 0, (char *)dptr, w, h, 32, 0);
- XPutImage(dpy, qt_x11Pixmap(pm)->handle(), gc, xi, 0, 0, 0, 0, w, h);
- qSafeXDestroyImage(xi);
- XFreeGC(xinfo.display(), gc);
-
- if (x11_mask) { // xform mask, too
- pm.setMask(mask_to_bitmap(xinfo.screen()).transformed(transform));
- } else if (d != 32 && complex_xform) { // need a mask!
- QBitmap mask(ws, hs);
- mask.fill(Qt::color1);
- pm.setMask(mask.transformed(transform));
- }
- return pm;
- }
-}
-
-QImage QX11PlatformPixmap::toImage() const
-{
- return toImage(QRect(0, 0, w, h));
-}
-
-QImage QX11PlatformPixmap::toImage(const QRect &rect) const
-{
- Window root_return;
- int x_return;
- int y_return;
- unsigned int width_return;
- unsigned int height_return;
- unsigned int border_width_return;
- unsigned int depth_return;
-
- XGetGeometry(xinfo.display(), hd, &root_return, &x_return, &y_return, &width_return, &height_return, &border_width_return, &depth_return);
-
- QXImageWrapper xiWrapper;
- xiWrapper.xi = XGetImage(xinfo.display(), hd, rect.x(), rect.y(), rect.width(), rect.height(),
- AllPlanes, (depth() == 1) ? XYPixmap : ZPixmap);
-
- Q_CHECK_PTR(xiWrapper.xi);
- if (!xiWrapper.xi)
- return QImage();
-
- if (!x11_mask && canTakeQImageFromXImage(xiWrapper))
- return takeQImageFromXImage(xiWrapper);
-
- QImage image = toImage(xiWrapper, rect);
- qSafeXDestroyImage(xiWrapper.xi);
- return image;
-}
-
-#if QT_CONFIG(xrender)
-static XRenderPictFormat *qt_renderformat_for_depth(const QXcbX11Info &xinfo, int depth)
-{
- if (depth == 1)
- return XRenderFindStandardFormat(xinfo.display(), PictStandardA1);
- else if (depth == 32)
- return XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32);
- else
- return XRenderFindVisualFormat(xinfo.display(), (Visual *)xinfo.visual());
-}
-#endif
-
-Q_GLOBAL_STATIC(QX11PaintEngine, qt_x11_paintengine)
-
-QPaintEngine *QX11PlatformPixmap::paintEngine() const
-{
- QX11PlatformPixmap *that = const_cast<QX11PlatformPixmap*>(this);
-
- if ((flags & Readonly)/* && share_mode == QPixmap::ImplicitlyShared*/) {
- // if someone wants to draw onto us, copy the shared contents
- // and turn it into a fully fledged QPixmap
- ::Pixmap hd_copy = XCreatePixmap(xinfo.display(), RootWindow(xinfo.display(), xinfo.screen()),
- w, h, d);
-#if QT_CONFIG(xrender)
- if (picture && d == 32) {
- XRenderPictFormat *format = qt_renderformat_for_depth(xinfo, d);
- ::Picture picture_copy = XRenderCreatePicture(xinfo.display(),
- hd_copy, format,
- 0, 0);
-
- XRenderComposite(xinfo.display(), PictOpSrc, picture, 0, picture_copy,
- 0, 0, 0, 0, 0, 0, w, h);
- XRenderFreePicture(xinfo.display(), picture);
- that->picture = picture_copy;
- } else
-#endif
- {
- GC gc = XCreateGC(xinfo.display(), hd_copy, 0, 0);
- XCopyArea(xinfo.display(), hd, hd_copy, gc, 0, 0, w, h, 0, 0);
- XFreeGC(xinfo.display(), gc);
- }
- that->hd = hd_copy;
- that->flags &= ~QX11PlatformPixmap::Readonly;
- }
-
- if (qt_x11_paintengine->isActive()) {
- if (!that->pengine)
- that->pengine = new QX11PaintEngine;
-
- return that->pengine;
- }
-
- return qt_x11_paintengine();
-}
-
-qreal QX11PlatformPixmap::devicePixelRatio() const
-{
- return dpr;
-}
-
-void QX11PlatformPixmap::setDevicePixelRatio(qreal scaleFactor)
-{
- dpr = scaleFactor;
-}
-
-Pixmap QX11PlatformPixmap::x11ConvertToDefaultDepth()
-{
-#if QT_CONFIG(xrender)
- if (d == xinfo.appDepth() || !X11->use_xrender)
- return hd;
- if (!hd2) {
- hd2 = XCreatePixmap(xinfo.display(), hd, w, h, xinfo.appDepth());
- XRenderPictFormat *format = XRenderFindVisualFormat(xinfo.display(),
- (Visual*) xinfo.visual());
- Picture pic = XRenderCreatePicture(xinfo.display(), hd2, format, 0, 0);
- XRenderComposite(xinfo.display(), PictOpSrc, picture,
- XNone, pic, 0, 0, 0, 0, 0, 0, w, h);
- XRenderFreePicture(xinfo.display(), pic);
- }
- return hd2;
-#else
- return hd;
-#endif
-}
-
-XID QX11PlatformPixmap::createBitmapFromImage(const QImage &image)
-{
- QImage img = image.convertToFormat(QImage::Format_MonoLSB);
- const QRgb c0 = QColor(Qt::black).rgb();
- const QRgb c1 = QColor(Qt::white).rgb();
- if (img.color(0) == c0 && img.color(1) == c1) {
- img.invertPixels();
- img.setColor(0, c1);
- img.setColor(1, c0);
- }
-
- char *bits;
- uchar *tmp_bits;
- int w = img.width();
- int h = img.height();
- int bpl = (w + 7) / 8;
- qsizetype ibpl = img.bytesPerLine();
- if (bpl != ibpl) {
- tmp_bits = new uchar[bpl*h];
- bits = (char *)tmp_bits;
- uchar *p, *b;
- int y;
- b = tmp_bits;
- p = img.scanLine(0);
- for (y = 0; y < h; y++) {
- memcpy(b, p, bpl);
- b += bpl;
- p += ibpl;
- }
- } else {
- bits = (char *)img.bits();
- tmp_bits = 0;
- }
- XID hd = XCreateBitmapFromData(QXcbX11Info::display(),
- QXcbX11Info::appRootWindow(),
- bits, w, h);
- if (tmp_bits) // Avoid purify complaint
- delete [] tmp_bits;
- return hd;
-}
-
-bool QX11PlatformPixmap::isBackingStore() const
-{
- return (flags & IsBackingStore);
-}
-
-void QX11PlatformPixmap::setIsBackingStore(bool on)
-{
- if (on)
- flags |= IsBackingStore;
- else {
- flags &= ~IsBackingStore;
- }
-}
-
-#if QT_CONFIG(xrender)
-void QX11PlatformPixmap::convertToARGB32(bool preserveContents)
-{
- if (!X11->use_xrender)
- return;
-
- // Q_ASSERT(count == 1);
- if ((flags & Readonly)/* && share_mode == QPixmap::ExplicitlyShared*/)
- return;
-
- Pixmap pm = XCreatePixmap(xinfo.display(), RootWindow(xinfo.display(), xinfo.screen()),
- w, h, 32);
- Picture p = XRenderCreatePicture(xinfo.display(), pm,
- XRenderFindStandardFormat(xinfo.display(), PictStandardARGB32), 0, 0);
- if (picture) {
- if (preserveContents)
- XRenderComposite(xinfo.display(), PictOpSrc, picture, 0, p, 0, 0, 0, 0, 0, 0, w, h);
- if (!(flags & Readonly))
- XRenderFreePicture(xinfo.display(), picture);
- }
- if (hd && !(flags & Readonly))
- XFreePixmap(xinfo.display(), hd);
- if (x11_mask) {
- XFreePixmap(xinfo.display(), x11_mask);
- if (mask_picture)
- XRenderFreePicture(xinfo.display(), mask_picture);
- x11_mask = 0;
- mask_picture = 0;
- }
- hd = pm;
- picture = p;
-
- d = 32;
- xinfo.setDepth(32);
-
- XVisualInfo visinfo;
- if (XMatchVisualInfo(xinfo.display(), xinfo.screen(), 32, TrueColor, &visinfo))
- xinfo.setVisual(visinfo.visual);
-}
-#endif
-
-void QX11PlatformPixmap::release()
-{
- delete pengine;
- pengine = 0;
-
- if (/*!X11*/ QCoreApplication::closingDown()) {
- // At this point, the X server will already have freed our resources,
- // so there is nothing to do.
- return;
- }
-
- if (x11_mask) {
-#if QT_CONFIG(xrender)
- if (mask_picture)
- XRenderFreePicture(xinfo.display(), mask_picture);
- mask_picture = 0;
-#endif
- XFreePixmap(xinfo.display(), x11_mask);
- x11_mask = 0;
- }
-
- if (hd) {
-#if QT_CONFIG(xrender)
- if (picture) {
- XRenderFreePicture(xinfo.display(), picture);
- picture = 0;
- }
-#endif // QT_CONFIG(xrender)
-
- if (hd2) {
- XFreePixmap(xinfo.display(), hd2);
- hd2 = 0;
- }
- if (!(flags & Readonly))
- XFreePixmap(xinfo.display(), hd);
- hd = 0;
- }
-}
-
-QImage QX11PlatformPixmap::toImage(const QXImageWrapper &xiWrapper, const QRect &rect) const
-{
- XImage *xi = xiWrapper.xi;
-
- int d = depth();
- Visual *visual = (Visual *)xinfo.visual();
- bool trucol = (visual->c_class >= TrueColor) && d > 1;
-
- QImage::Format format = QImage::Format_Mono;
- if (d > 1 && d <= 8) {
- d = 8;
- format = QImage::Format_Indexed8;
- }
- // we could run into the situation where d == 8 AND trucol is true, which can
- // cause problems when converting to and from images. in this case, always treat
- // the depth as 32...
- if (d > 8 || trucol) {
- d = 32;
- format = QImage::Format_RGB32;
- }
-
- if (d == 1 && xi->bitmap_bit_order == LSBFirst)
- format = QImage::Format_MonoLSB;
- if (x11_mask && format == QImage::Format_RGB32)
- format = QImage::Format_ARGB32;
-
- QImage image(xi->width, xi->height, format);
- image.setDevicePixelRatio(devicePixelRatio());
- if (image.isNull()) // could not create image
- return image;
-
- QImage alpha;
- if (x11_mask) {
- if (rect.contains(QRect(0, 0, w, h)))
- alpha = mask().toImage();
- else
- alpha = mask().toImage().copy(rect);
- }
- bool ale = alpha.format() == QImage::Format_MonoLSB;
-
- if (trucol) { // truecolor
- const uint red_mask = (uint)visual->red_mask;
- const uint green_mask = (uint)visual->green_mask;
- const uint blue_mask = (uint)visual->blue_mask;
- const int red_shift = highest_bit(red_mask) - 7;
- const int green_shift = highest_bit(green_mask) - 7;
- const int blue_shift = highest_bit(blue_mask) - 7;
-
- const uint red_bits = n_bits(red_mask);
- const uint green_bits = n_bits(green_mask);
- const uint blue_bits = n_bits(blue_mask);
-
- static uint red_table_bits = 0;
- static uint green_table_bits = 0;
- static uint blue_table_bits = 0;
-
- if (red_bits < 8 && red_table_bits != red_bits) {
- build_scale_table(&red_scale_table, red_bits);
- red_table_bits = red_bits;
- }
- if (blue_bits < 8 && blue_table_bits != blue_bits) {
- build_scale_table(&blue_scale_table, blue_bits);
- blue_table_bits = blue_bits;
- }
- if (green_bits < 8 && green_table_bits != green_bits) {
- build_scale_table(&green_scale_table, green_bits);
- green_table_bits = green_bits;
- }
-
- int r, g, b;
-
- QRgb *dst;
- uchar *src;
- uint pixel;
- int bppc = xi->bits_per_pixel;
-
- if (bppc > 8 && xi->byte_order == LSBFirst)
- bppc++;
-
- for (int y = 0; y < xi->height; ++y) {
- uchar* asrc = x11_mask ? alpha.scanLine(y) : 0;
- dst = (QRgb *)image.scanLine(y);
- src = (uchar *)xi->data + xi->bytes_per_line*y;
- for (int x = 0; x < xi->width; x++) {
- switch (bppc) {
- case 8:
- pixel = *src++;
- break;
- case 16: // 16 bit MSB
- pixel = src[1] | (uint)src[0] << 8;
- src += 2;
- break;
- case 17: // 16 bit LSB
- pixel = src[0] | (uint)src[1] << 8;
- src += 2;
- break;
- case 24: // 24 bit MSB
- pixel = src[2] | (uint)src[1] << 8 | (uint)src[0] << 16;
- src += 3;
- break;
- case 25: // 24 bit LSB
- pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16;
- src += 3;
- break;
- case 32: // 32 bit MSB
- pixel = src[3] | (uint)src[2] << 8 | (uint)src[1] << 16 | (uint)src[0] << 24;
- src += 4;
- break;
- case 33: // 32 bit LSB
- pixel = src[0] | (uint)src[1] << 8 | (uint)src[2] << 16 | (uint)src[3] << 24;
- src += 4;
- break;
- default: // should not really happen
- x = xi->width; // leave loop
- y = xi->height;
- pixel = 0; // eliminate compiler warning
- qWarning("QPixmap::convertToImage: Invalid depth %d", bppc);
- }
- if (red_shift > 0)
- r = (pixel & red_mask) >> red_shift;
- else
- r = (pixel & red_mask) << -red_shift;
- if (green_shift > 0)
- g = (pixel & green_mask) >> green_shift;
- else
- g = (pixel & green_mask) << -green_shift;
- if (blue_shift > 0)
- b = (pixel & blue_mask) >> blue_shift;
- else
- b = (pixel & blue_mask) << -blue_shift;
-
- if (red_bits < 8)
- r = red_scale_table[r];
- if (green_bits < 8)
- g = green_scale_table[g];
- if (blue_bits < 8)
- b = blue_scale_table[b];
-
- if (x11_mask) {
- if (ale) {
- *dst++ = (asrc[x >> 3] & (1 << (x & 7))) ? qRgba(r, g, b, 0xff) : 0;
- } else {
- *dst++ = (asrc[x >> 3] & (0x80 >> (x & 7))) ? qRgba(r, g, b, 0xff) : 0;
- }
- } else {
- *dst++ = qRgb(r, g, b);
- }
- }
- }
- } else if (xi->bits_per_pixel == d) { // compatible depth
- char *xidata = xi->data; // copy each scanline
- qsizetype bpl = qMin(image.bytesPerLine(),xi->bytes_per_line);
- for (int y=0; y<xi->height; y++) {
- memcpy(image.scanLine(y), xidata, bpl);
- xidata += xi->bytes_per_line;
- }
- } else {
- /* Typically 2 or 4 bits display depth */
- qWarning("QPixmap::convertToImage: Display not supported (bpp=%d)",
- xi->bits_per_pixel);
- return QImage();
- }
-
- if (d == 1) { // bitmap
- image.setColorCount(2);
- image.setColor(0, qRgb(255,255,255));
- image.setColor(1, qRgb(0,0,0));
- } else if (!trucol) { // pixmap with colormap
- uchar *p;
- uchar *end;
- uchar use[256]; // pixel-in-use table
- uchar pix[256]; // pixel translation table
- int ncols;
- memset(use, 0, 256);
- memset(pix, 0, 256);
- qsizetype bpl = image.bytesPerLine();
-
- if (x11_mask) { // which pixels are used?
- for (int i = 0; i < xi->height; i++) {
- uchar* asrc = alpha.scanLine(i);
- p = image.scanLine(i);
- if (ale) {
- for (int x = 0; x < xi->width; x++) {
- if (asrc[x >> 3] & (1 << (x & 7)))
- use[*p] = 1;
- ++p;
- }
- } else {
- for (int x = 0; x < xi->width; x++) {
- if (asrc[x >> 3] & (0x80 >> (x & 7)))
- use[*p] = 1;
- ++p;
- }
- }
- }
- } else {
- for (int i = 0; i < xi->height; i++) {
- p = image.scanLine(i);
- end = p + bpl;
- while (p < end)
- use[*p++] = 1;
- }
- }
- ncols = 0;
- for (int i = 0; i < 256; i++) { // build translation table
- if (use[i])
- pix[i] = ncols++;
- }
- for (int i = 0; i < xi->height; i++) { // translate pixels
- p = image.scanLine(i);
- end = p + bpl;
- while (p < end) {
- *p = pix[*p];
- p++;
- }
- }
- if (x11_mask) {
- int trans;
- if (ncols < 256) {
- trans = ncols++;
- image.setColorCount(ncols); // create color table
- image.setColor(trans, 0x00000000);
- } else {
- image.setColorCount(ncols); // create color table
- // oh dear... no spare "transparent" pixel.
- // use first pixel in image (as good as any).
- trans = image.scanLine(0)[0];
- }
- for (int i = 0; i < xi->height; i++) {
- uchar* asrc = alpha.scanLine(i);
- p = image.scanLine(i);
- if (ale) {
- for (int x = 0; x < xi->width; x++) {
- if (!(asrc[x >> 3] & (1 << (x & 7))))
- *p = trans;
- ++p;
- }
- } else {
- for (int x = 0; x < xi->width; x++) {
- if (!(asrc[x >> 3] & (1 << (7 -(x & 7)))))
- *p = trans;
- ++p;
- }
- }
- }
- } else {
- image.setColorCount(ncols); // create color table
- }
- QList<QColor> colors = QXcbColormap::instance(xinfo.screen()).colormap();
- int j = 0;
- for (int i=0; i<colors.size(); i++) { // translate pixels
- if (use[i])
- image.setColor(j++, 0xff000000 | colors.at(i).rgb());
- }
- }
-
- return image;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h
deleted file mode 100644
index 0755a34b4a8..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qpixmap_x11_p.h
+++ /dev/null
@@ -1,131 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#pragma once
-
-#include <QBitmap>
-#include <QPixmap>
-
-#include <qpa/qplatformpixmap.h>
-#include "qxcbnativepainting.h"
-
-typedef unsigned long XID;
-typedef XID Drawable;
-typedef XID Picture;
-typedef XID Pixmap;
-
-QT_BEGIN_NAMESPACE
-
-class QX11PaintEngine;
-struct QXImageWrapper;
-
-class QX11PlatformPixmap : public QPlatformPixmap
-{
-public:
- QX11PlatformPixmap(PixelType pixelType);
- ~QX11PlatformPixmap();
-
- QPlatformPixmap *createCompatiblePlatformPixmap() const override;
- void resize(int width, int height) override;
- void fromImage(const QImage &img, Qt::ImageConversionFlags flags) override;
- void copy(const QPlatformPixmap *data, const QRect &rect) override;
- bool scroll(int dx, int dy, const QRect &rect) override;
- int metric(QPaintDevice::PaintDeviceMetric metric) const override;
- void fill(const QColor &fillColor) override;
- QBitmap mask() const override;
- void setMask(const QBitmap &mask) override;
- bool hasAlphaChannel() const override;
- QPixmap transformed(const QTransform &matrix, Qt::TransformationMode mode) const override;
- QImage toImage() const override;
- QImage toImage(const QRect &rect) const override;
- QPaintEngine *paintEngine() const override;
- qreal devicePixelRatio() const override;
- void setDevicePixelRatio(qreal scaleFactor) override;
-
- inline Drawable handle() const { return hd; }
- inline Picture x11PictureHandle() const { return picture; }
- inline const QXcbX11Info *x11_info() const { return &xinfo; }
-
- Pixmap x11ConvertToDefaultDepth();
- static XID createBitmapFromImage(const QImage &image);
-
-#if QT_CONFIG(xrender)
- void convertToARGB32(bool preserveContents = true);
-#endif
-
- bool isBackingStore() const;
- void setIsBackingStore(bool on);
-private:
- friend class QX11PaintEngine;
- friend const QXcbX11Info &qt_x11Info(const QPixmap &pixmap);
- friend void qt_x11SetScreen(QPixmap &pixmap, int screen);
-
- void release();
- QImage toImage(const QXImageWrapper &xi, const QRect &rect) const;
- QBitmap mask_to_bitmap(int screen) const;
- static Pixmap bitmap_to_mask(const QBitmap &, int screen);
- void bitmapFromImage(const QImage &image);
- bool canTakeQImageFromXImage(const QXImageWrapper &xi) const;
- QImage takeQImageFromXImage(const QXImageWrapper &xi) const;
-
- Pixmap hd = 0;
-
- enum Flag {
- NoFlags = 0x0,
- Uninitialized = 0x1,
- Readonly = 0x2,
- InvertedWhenBoundToTexture = 0x4,
- GlSurfaceCreatedWithAlpha = 0x8,
- IsBackingStore = 0x10
- };
- uint flags;
-
- QXcbX11Info xinfo;
- Pixmap x11_mask;
- Picture picture;
- Picture mask_picture;
- Pixmap hd2; // sorted in the default display depth
- //QPixmap::ShareMode share_mode;
- qreal dpr;
-
- QX11PaintEngine *pengine;
-};
-
-inline QX11PlatformPixmap *qt_x11Pixmap(const QPixmap &pixmap)
-{
- return (pixmap.handle() && pixmap.handle()->classId() == QPlatformPixmap::X11Class)
- ? static_cast<QX11PlatformPixmap *>(pixmap.handle())
- : nullptr;
-}
-
-inline Picture qt_x11PictureHandle(const QPixmap &pixmap)
-{
- if (QX11PlatformPixmap *pm = qt_x11Pixmap(pixmap))
- return pm->x11PictureHandle();
-
- return 0;
-}
-
-inline Pixmap qt_x11PixmapHandle(const QPixmap &pixmap)
-{
- if (QX11PlatformPixmap *pm = qt_x11Pixmap(pixmap))
- return pm->handle();
-
- return 0;
-}
-
-inline const QXcbX11Info &qt_x11Info(const QPixmap &pixmap)
-{
- if (QX11PlatformPixmap *pm = qt_x11Pixmap(pixmap)) {
- return pm->xinfo;
- } else {
- static QXcbX11Info nullX11Info;
- return nullX11Info;
- }
-}
-
-int qt_x11SetDefaultScreen(int screen);
-void qt_x11SetScreen(QPixmap &pixmap, int screen);
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qpolygonclipper_p.h b/src/plugins/platforms/xcb/nativepainting/qpolygonclipper_p.h
deleted file mode 100644
index e1e31722d76..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qpolygonclipper_p.h
+++ /dev/null
@@ -1,278 +0,0 @@
-// Copyright (C) 2016 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
-// Qt-Security score:significant reason:default
-
-#pragma once
-
-//
-// W A R N I N G
-// -------------
-//
-// This file is not part of the Qt API. It exists for the convenience
-// of other Qt classes. This header file may change from version to
-// version without notice, or even be removed.
-//
-// We mean it.
-//
-
-#include <QtCore/qrect.h>
-#include <QtGui/private/qdatabuffer_p.h>
-
-QT_BEGIN_NAMESPACE
-
-/* based on sutherland-hodgman line-by-line clipping, as described in
- Computer Graphics and Principles */
-template <typename InType, typename OutType, typename CastType> class QPolygonClipper
-{
-public:
- QPolygonClipper() :
- buffer1(0), buffer2(0)
- {
- x1 = y1 = x2 = y2 = 0;
- }
-
- ~QPolygonClipper()
- {
- }
-
- void setBoundingRect(const QRect bounds)
- {
- x1 = bounds.x();
- x2 = bounds.x() + bounds.width();
- y1 = bounds.y();
- y2 = bounds.y() + bounds.height();
- }
-
- QRect boundingRect()
- {
- return QRect(QPoint(x1, y1), QPoint(x2, y2));
- }
-
- inline OutType intersectLeft(const OutType &p1, const OutType &p2)
- {
- OutType t;
- qreal dy = (p1.y - p2.y) / qreal(p1.x - p2.x);
- t.x = x1;
- t.y = static_cast<CastType>(p2.y + (x1 - p2.x) * dy);
- return t;
- }
-
-
- inline OutType intersectRight(const OutType &p1, const OutType &p2)
- {
- OutType t;
- qreal dy = (p1.y - p2.y) / qreal(p1.x - p2.x);
- t.x = x2;
- t.y = static_cast<CastType>(p2.y + (x2 - p2.x) * dy);
- return t;
- }
-
-
- inline OutType intersectTop(const OutType &p1, const OutType &p2)
- {
- OutType t;
- qreal dx = (p1.x - p2.x) / qreal(p1.y - p2.y);
- t.x = static_cast<CastType>(p2.x + (y1 - p2.y) * dx);
- t.y = y1;
- return t;
- }
-
-
- inline OutType intersectBottom(const OutType &p1, const OutType &p2)
- {
- OutType t;
- qreal dx = (p1.x - p2.x) / qreal(p1.y - p2.y);
- t.x = static_cast<CastType>(p2.x + (y2 - p2.y) * dx);
- t.y = y2;
- return t;
- }
-
-
- void clipPolygon(const InType *inPoints, int inCount, OutType **outPoints, int *outCount,
- bool closePolygon = true)
- {
- Q_ASSERT(outPoints);
- Q_ASSERT(outCount);
-
- if (inCount < 2) {
- *outCount = 0;
- return;
- }
-
- buffer1.reset();
- buffer2.reset();
-
- QDataBuffer<OutType> *source = &buffer1;
- QDataBuffer<OutType> *clipped = &buffer2;
-
- // Gather some info since we are iterating through the points anyway..
- bool doLeft = false, doRight = false, doTop = false, doBottom = false;
- OutType ot;
- for (int i=0; i<inCount; ++i) {
- ot = inPoints[i];
- clipped->add(ot);
-
- if (ot.x < x1)
- doLeft = true;
- else if (ot.x > x2)
- doRight = true;
- if (ot.y < y1)
- doTop = true;
- else if (ot.y > y2)
- doBottom = true;
- }
-
- if (doLeft && clipped->size() > 1) {
- QDataBuffer<OutType> *tmp = source;
- source = clipped;
- clipped = tmp;
- clipped->reset();
- int lastPos, start;
- if (closePolygon) {
- lastPos = source->size() - 1;
- start = 0;
- } else {
- lastPos = 0;
- start = 1;
- if (source->at(0).x >= x1)
- clipped->add(source->at(0));
- }
- for (int i=start; i<inCount; ++i) {
- const OutType &cpt = source->at(i);
- const OutType &ppt = source->at(lastPos);
-
- if (cpt.x >= x1) {
- if (ppt.x >= x1) {
- clipped->add(cpt);
- } else {
- clipped->add(intersectLeft(cpt, ppt));
- clipped->add(cpt);
- }
- } else if (ppt.x >= x1) {
- clipped->add(intersectLeft(cpt, ppt));
- }
- lastPos = i;
- }
- }
-
- if (doRight && clipped->size() > 1) {
- QDataBuffer<OutType> *tmp = source;
- source = clipped;
- clipped = tmp;
- clipped->reset();
- int lastPos, start;
- if (closePolygon) {
- lastPos = source->size() - 1;
- start = 0;
- } else {
- lastPos = 0;
- start = 1;
- if (source->at(0).x <= x2)
- clipped->add(source->at(0));
- }
- for (int i=start; i<source->size(); ++i) {
- const OutType &cpt = source->at(i);
- const OutType &ppt = source->at(lastPos);
-
- if (cpt.x <= x2) {
- if (ppt.x <= x2) {
- clipped->add(cpt);
- } else {
- clipped->add(intersectRight(cpt, ppt));
- clipped->add(cpt);
- }
- } else if (ppt.x <= x2) {
- clipped->add(intersectRight(cpt, ppt));
- }
-
- lastPos = i;
- }
-
- }
-
- if (doTop && clipped->size() > 1) {
- QDataBuffer<OutType> *tmp = source;
- source = clipped;
- clipped = tmp;
- clipped->reset();
- int lastPos, start;
- if (closePolygon) {
- lastPos = source->size() - 1;
- start = 0;
- } else {
- lastPos = 0;
- start = 1;
- if (source->at(0).y >= y1)
- clipped->add(source->at(0));
- }
- for (int i=start; i<source->size(); ++i) {
- const OutType &cpt = source->at(i);
- const OutType &ppt = source->at(lastPos);
-
- if (cpt.y >= y1) {
- if (ppt.y >= y1) {
- clipped->add(cpt);
- } else {
- clipped->add(intersectTop(cpt, ppt));
- clipped->add(cpt);
- }
- } else if (ppt.y >= y1) {
- clipped->add(intersectTop(cpt, ppt));
- }
-
- lastPos = i;
- }
- }
-
- if (doBottom && clipped->size() > 1) {
- QDataBuffer<OutType> *tmp = source;
- source = clipped;
- clipped = tmp;
- clipped->reset();
- int lastPos, start;
- if (closePolygon) {
- lastPos = source->size() - 1;
- start = 0;
- } else {
- lastPos = 0;
- start = 1;
- if (source->at(0).y <= y2)
- clipped->add(source->at(0));
- }
- for (int i=start; i<source->size(); ++i) {
- const OutType &cpt = source->at(i);
- const OutType &ppt = source->at(lastPos);
-
- if (cpt.y <= y2) {
- if (ppt.y <= y2) {
- clipped->add(cpt);
- } else {
- clipped->add(intersectBottom(cpt, ppt));
- clipped->add(cpt);
- }
- } else if (ppt.y <= y2) {
- clipped->add(intersectBottom(cpt, ppt));
- }
- lastPos = i;
- }
- }
-
- if (closePolygon && clipped->size() > 0) {
- // close clipped polygon
- if (clipped->at(0).x != clipped->at(clipped->size()-1).x ||
- clipped->at(0).y != clipped->at(clipped->size()-1).y) {
- OutType ot = clipped->at(0);
- clipped->add(ot);
- }
- }
- *outCount = clipped->size();
- *outPoints = clipped->data();
- }
-
-private:
- int x1, x2, y1, y2;
- QDataBuffer<OutType> buffer1;
- QDataBuffer<OutType> buffer2;
-};
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h b/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h
deleted file mode 100644
index 2986b8f1453..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qt_x11_p.h
+++ /dev/null
@@ -1,163 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#pragma once
-
-#define register /* C++17 deprecated register */
-#include <X11/Xlib.h>
-#include <X11/Xatom.h>
-#undef register
-
-#if QT_CONFIG(xrender)
-# include "qtessellator_p.h"
-# include <X11/extensions/Xrender.h>
-#endif
-
-#if QT_CONFIG(fontconfig)
-#include <fontconfig/fontconfig.h>
-#endif
-
-#if defined(FT_LCD_FILTER_H)
-#include FT_LCD_FILTER_H
-#endif
-
-#if defined(FC_LCD_FILTER)
-
-#ifndef FC_LCD_FILTER_NONE
-#define FC_LCD_FILTER_NONE FC_LCD_NONE
-#endif
-
-#ifndef FC_LCD_FILTER_DEFAULT
-#define FC_LCD_FILTER_DEFAULT FC_LCD_DEFAULT
-#endif
-
-#ifndef FC_LCD_FILTER_LIGHT
-#define FC_LCD_FILTER_LIGHT FC_LCD_LIGHT
-#endif
-
-#ifndef FC_LCD_FILTER_LEGACY
-#define FC_LCD_FILTER_LEGACY FC_LCD_LEGACY
-#endif
-
-#endif
-
-QT_BEGIN_NAMESPACE
-
-// rename a couple of X defines to get rid of name clashes
-// resolve the conflict between X11's FocusIn and QEvent::FocusIn
-enum {
- XFocusOut = FocusOut,
- XFocusIn = FocusIn,
- XKeyPress = KeyPress,
- XKeyRelease = KeyRelease,
- XNone = None,
- XRevertToParent = RevertToParent,
- XGrayScale = GrayScale,
- XCursorShape = CursorShape,
-};
-#undef FocusOut
-#undef FocusIn
-#undef KeyPress
-#undef KeyRelease
-#undef None
-#undef RevertToParent
-#undef GrayScale
-#undef CursorShape
-
-#ifdef FontChange
-#undef FontChange
-#endif
-
-Q_DECLARE_TYPEINFO(XPoint, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(XRectangle, Q_PRIMITIVE_TYPE);
-Q_DECLARE_TYPEINFO(XChar2b, Q_PRIMITIVE_TYPE);
-#if QT_CONFIG(xrender)
-Q_DECLARE_TYPEINFO(XGlyphElt32, Q_PRIMITIVE_TYPE);
-#endif
-
-struct QX11InfoData;
-
-enum DesktopEnvironment {
- DE_UNKNOWN,
- DE_KDE,
- DE_GNOME,
- DE_CDE,
- DE_MEEGO_COMPOSITOR,
- DE_4DWM
-};
-
-struct QXcbX11Data {
- Display *display = nullptr;
-
- // true if Qt is compiled w/ RENDER support and RENDER is supported on the connected Display
- bool use_xrender = false;
- int xrender_major = 0;
- int xrender_version = 0;
-
- QX11InfoData *screens = nullptr;
- Visual **argbVisuals = nullptr;
- Colormap *argbColormaps = nullptr;
- int screenCount = 0;
- int defaultScreen = 0;
-
- // options
- int visual_class = 0;
- int visual_id = 0;
- int color_count = 0;
- bool custom_cmap = false;
-
- // outside visual/colormap
- Visual *visual = nullptr;
- Colormap colormap = 0;
-
-#if QT_CONFIG(xrender)
- enum { solid_fill_count = 16 };
- struct SolidFills {
- XRenderColor color;
- int screen;
- Picture picture;
- } solid_fills[solid_fill_count];
- enum { pattern_fill_count = 16 };
- struct PatternFills {
- XRenderColor color;
- XRenderColor bg_color;
- int screen;
- int style;
- bool opaque;
- Picture picture;
- } pattern_fills[pattern_fill_count];
- Picture getSolidFill(int screen, const QColor &c);
- XRenderColor preMultiply(const QColor &c);
-#endif
-
- bool fc_antialias = true;
- int fc_hint_style = 0;
-
- DesktopEnvironment desktopEnvironment = DE_GNOME;
-};
-
-extern QXcbX11Data *qt_x11Data;
-#define X11 qt_x11Data
-
-struct QX11InfoData {
- int screen;
- int dpiX;
- int dpiY;
- int depth;
- int cells;
- Colormap colormap;
- Visual *visual;
- bool defaultColormap;
- bool defaultVisual;
- int subpixel = 0;
-};
-
-template <class T>
-constexpr inline int lowest_bit(T v) noexcept
-{
- int result = qCountTrailingZeroBits(v);
- return ((result >> 3) == sizeof(T)) ? -1 : result;
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp b/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
deleted file mode 100644
index dd83f8852b7..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qtessellator.cpp
+++ /dev/null
@@ -1,1466 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#include "qtessellator_p.h"
-
-#include <QRect>
-#include <QList>
-#include <QMap>
-#include <QDebug>
-
-#include <qmath.h>
-#include <limits.h>
-#include <algorithm>
-
-QT_BEGIN_NAMESPACE
-
-//#define DEBUG
-#ifdef DEBUG
-#define QDEBUG qDebug
-#else
-#define QDEBUG if (1){} else qDebug
-#endif
-
-static const bool emit_clever = true;
-static const bool mark_clever = false;
-
-enum VertexFlags {
- LineBeforeStarts = 0x1,
- LineBeforeEnds = 0x2,
- LineBeforeHorizontal = 0x4,
- LineAfterStarts = 0x8,
- LineAfterEnds = 0x10,
- LineAfterHorizontal = 0x20
-};
-
-
-
-class QTessellatorPrivate {
-public:
- struct Vertices;
-
- QTessellatorPrivate() {}
-
- QRectF collectAndSortVertices(const QPointF *points, int *maxActiveEdges);
- void cancelCoincidingEdges();
-
- void emitEdges(QTessellator *tessellator);
- void processIntersections();
- void removeEdges();
- void addEdges();
- void addIntersections();
-
- struct Vertex : public QTessellator::Vertex
- {
- int flags;
- };
-
- struct Intersection
- {
- Q27Dot5 y;
- int edge;
- bool operator <(const Intersection &other) const {
- if (y != other.y)
- return y < other.y;
- return edge < other.edge;
- }
- };
- struct IntersectionLink
- {
- int next;
- int prev;
- };
- typedef QMap<Intersection, IntersectionLink> Intersections;
-
- struct Edge {
- Edge(const Vertices &v, int _edge);
- int edge;
- const Vertex *v0;
- const Vertex *v1;
- Q27Dot5 y_left;
- Q27Dot5 y_right;
- signed int winding : 8;
- bool mark;
- bool free;
- bool intersect_left;
- bool intersect_right;
- bool isLeftOf(const Edge &other, Q27Dot5 y) const;
- Q27Dot5 positionAt(Q27Dot5 y) const;
- bool intersect(const Edge &other, Q27Dot5 *y, bool *det_positive) const;
-
- };
-
- class EdgeSorter
- {
- public:
- EdgeSorter(int _y) : y(_y) {}
- bool operator() (const Edge *e1, const Edge *e2);
- int y;
- };
-
- class Scanline {
- public:
- Scanline();
- ~Scanline();
-
- void init(int maxActiveEdges);
- void done();
-
- int findEdgePosition(Q27Dot5 x, Q27Dot5 y) const;
- int findEdgePosition(const Edge &e) const;
- int findEdge(int edge) const;
- void clearMarks();
-
- void swap(int p1, int p2) {
- Edge *tmp = edges[p1];
- edges[p1] = edges[p2];
- edges[p2] = tmp;
- }
- void insert(int pos, const Edge &e);
- void removeAt(int pos);
- void markEdges(int pos1, int pos2);
-
- void prepareLine();
- void lineDone();
-
- Edge **old;
- int old_size;
-
- Edge **edges;
- int size;
-
- private:
- Edge *edge_table;
- int first_unused;
- int max_edges;
- enum { default_alloc = 32 };
- };
-
- struct Vertices {
- enum { default_alloc = 128 };
- Vertices();
- ~Vertices();
- void init(int maxVertices);
- void done();
- Vertex *storage;
- Vertex **sorted;
-
- Vertex *operator[] (int i) { return storage + i; }
- const Vertex *operator[] (int i) const { return storage + i; }
- int position(const Vertex *v) const {
- return v - storage;
- }
- Vertex *next(Vertex *v) {
- ++v;
- if (v == storage + nPoints)
- v = storage;
- return v;
- }
- const Vertex *next(const Vertex *v) const {
- ++v;
- if (v == storage + nPoints)
- v = storage;
- return v;
- }
- int nextPos(const Vertex *v) const {
- ++v;
- if (v == storage + nPoints)
- return 0;
- return v - storage;
- }
- Vertex *prev(Vertex *v) {
- if (v == storage)
- v = storage + nPoints;
- --v;
- return v;
- }
- const Vertex *prev(const Vertex *v) const {
- if (v == storage)
- v = storage + nPoints;
- --v;
- return v;
- }
- int prevPos(const Vertex *v) const {
- if (v == storage)
- v = storage + nPoints;
- --v;
- return v - storage;
- }
- int nPoints;
- int allocated;
- };
- Vertices vertices;
- Intersections intersections;
- Scanline scanline;
- bool winding;
- Q27Dot5 y;
- int currentVertex;
-
-private:
- void addIntersection(const Edge *e1, const Edge *e2);
- bool edgeInChain(Intersection i, int edge);
-};
-
-
-QTessellatorPrivate::Edge::Edge(const QTessellatorPrivate::Vertices &vertices, int edge)
-{
- this->edge = edge;
- intersect_left = intersect_right = true;
- mark = false;
- free = false;
-
- v0 = vertices[edge];
- v1 = vertices.next(v0);
-
- Q_ASSERT(v0->y != v1->y);
-
- if (v0->y > v1->y) {
- qSwap(v0, v1);
- winding = -1;
- } else {
- winding = 1;
- }
- y_left = y_right = v0->y;
-}
-
-// This is basically the algorithm from graphics gems. The algorithm
-// is cubic in the coordinates at one place. Since we use 64bit
-// integers, this implies, that the allowed range for our coordinates
-// is limited to 21 bits. With 5 bits behind the decimal, this
-// implies that differences in coordaintes can range from 2*SHORT_MIN
-// to 2*SHORT_MAX, giving us efficiently a coordinate system from
-// SHORT_MIN to SHORT_MAX.
-//
-
-// WARNING: It's absolutely critical that the intersect() and isLeftOf() methods use
-// exactly the same algorithm to calculate yi. It's also important to be sure the algorithms
-// are transitive (ie. the conditions below are true for all input data):
-//
-// a.intersect(b) == b.intersect(a)
-// a.isLeftOf(b) != b.isLeftOf(a)
-//
-// This is tricky to get right, so be very careful when changing anything in here!
-
-static inline bool sameSign(qint64 a, qint64 b) {
- return (((qint64) ((quint64) a ^ (quint64) b)) >= 0 );
-}
-
-bool QTessellatorPrivate::Edge::intersect(const Edge &other, Q27Dot5 *y, bool *det_positive) const
-{
- qint64 a1 = v1->y - v0->y;
- qint64 b1 = v0->x - v1->x;
-
- qint64 a2 = other.v1->y - other.v0->y;
- qint64 b2 = other.v0->x - other.v1->x;
-
- qint64 det = a1 * b2 - a2 * b1;
- if (det == 0)
- return false;
-
- qint64 c1 = qint64(v1->x) * v0->y - qint64(v0->x) * v1->y;
-
- qint64 r3 = a1 * other.v0->x + b1 * other.v0->y + c1;
- qint64 r4 = a1 * other.v1->x + b1 * other.v1->y + c1;
-
- // Check signs of r3 and r4. If both point 3 and point 4 lie on
- // same side of line 1, the line segments do not intersect.
- QDEBUG() << " " << r3 << r4;
- if (r3 != 0 && r4 != 0 && sameSign( r3, r4 ))
- return false;
-
- qint64 c2 = qint64(other.v1->x) * other.v0->y - qint64(other.v0->x) * other.v1->y;
-
- qint64 r1 = a2 * v0->x + b2 * v0->y + c2;
- qint64 r2 = a2 * v1->x + b2 * v1->y + c2;
-
- // Check signs of r1 and r2. If both point 1 and point 2 lie
- // on same side of second line segment, the line segments do not intersect.
- QDEBUG() << " " << r1 << r2;
- if (r1 != 0 && r2 != 0 && sameSign( r1, r2 ))
- return false;
-
- // The det/2 is to get rounding instead of truncating. It
- // is added or subtracted to the numerator, depending upon the
- // sign of the numerator.
- qint64 offset = det < 0 ? -det : det;
- offset >>= 1;
-
- qint64 num = a2 * c1 - a1 * c2;
- *y = ( num < 0 ? num - offset : num + offset ) / det;
-
- *det_positive = (det > 0);
-
- return true;
-}
-
-#undef SAME_SIGNS
-
-bool QTessellatorPrivate::Edge::isLeftOf(const Edge &other, Q27Dot5 y) const
-{
-// QDEBUG() << "isLeftOf" << edge << other.edge << y;
- qint64 a1 = v1->y - v0->y;
- qint64 b1 = v0->x - v1->x;
- qint64 a2 = other.v1->y - other.v0->y;
- qint64 b2 = other.v0->x - other.v1->x;
-
- qint64 c2 = qint64(other.v1->x) * other.v0->y - qint64(other.v0->x) * other.v1->y;
-
- qint64 det = a1 * b2 - a2 * b1;
- if (det == 0) {
- // lines are parallel. Only need to check side of one point
- // fixed ordering for coincident edges
- qint64 r1 = a2 * v0->x + b2 * v0->y + c2;
-// QDEBUG() << "det = 0" << r1;
- if (r1 == 0)
- return edge < other.edge;
- return (r1 < 0);
- }
-
- // not parallel, need to find the y coordinate of the intersection point
- qint64 c1 = qint64(v1->x) * v0->y - qint64(v0->x) * v1->y;
-
- qint64 offset = det < 0 ? -det : det;
- offset >>= 1;
-
- qint64 num = a2 * c1 - a1 * c2;
- qint64 yi = ( num < 0 ? num - offset : num + offset ) / det;
-// QDEBUG() << " num=" << num << "offset=" << offset << "det=" << det;
-
- return ((yi > y) ^ (det < 0));
-}
-
-static inline bool compareVertex(const QTessellatorPrivate::Vertex *p1,
- const QTessellatorPrivate::Vertex *p2)
-{
- if (p1->y == p2->y) {
- if (p1->x == p2->x)
- return p1 < p2;
- return p1->x < p2->x;
- }
- return p1->y < p2->y;
-}
-
-Q27Dot5 QTessellatorPrivate::Edge::positionAt(Q27Dot5 y) const
-{
- if (y == v0->y)
- return v0->x;
- else if (y == v1->y)
- return v1->x;
-
- qint64 d = v1->x - v0->x;
- return (v0->x + d*(y - v0->y)/(v1->y-v0->y));
-}
-
-bool QTessellatorPrivate::EdgeSorter::operator() (const Edge *e1, const Edge *e2)
-{
- return e1->isLeftOf(*e2, y);
-}
-
-
-QTessellatorPrivate::Scanline::Scanline()
-{
- edges = 0;
- edge_table = 0;
- old = 0;
-}
-
-void QTessellatorPrivate::Scanline::init(int maxActiveEdges)
-{
- maxActiveEdges *= 2;
- if (!edges || maxActiveEdges > default_alloc) {
- max_edges = maxActiveEdges;
- int s = qMax(maxActiveEdges + 1, default_alloc + 1);
- edges = q_check_ptr((Edge **)realloc(edges, s*sizeof(Edge *)));
- edge_table = q_check_ptr((Edge *)realloc(edge_table, s*sizeof(Edge)));
- old = q_check_ptr((Edge **)realloc(old, s*sizeof(Edge *)));
- }
- size = 0;
- old_size = 0;
- first_unused = 0;
- for (int i = 0; i < maxActiveEdges; ++i)
- edge_table[i].edge = i+1;
- edge_table[maxActiveEdges].edge = -1;
-}
-
-void QTessellatorPrivate::Scanline::done()
-{
- if (max_edges > default_alloc) {
- free(edges);
- free(old);
- free(edge_table);
- edges = 0;
- old = 0;
- edge_table = 0;
- }
-}
-
-QTessellatorPrivate::Scanline::~Scanline()
-{
- free(edges);
- free(old);
- free(edge_table);
-}
-
-int QTessellatorPrivate::Scanline::findEdgePosition(Q27Dot5 x, Q27Dot5 y) const
-{
- int min = 0;
- int max = size - 1;
- while (min < max) {
- int pos = min + ((max - min + 1) >> 1);
- Q27Dot5 ax = edges[pos]->positionAt(y);
- if (ax > x) {
- max = pos - 1;
- } else {
- min = pos;
- }
- }
- return min;
-}
-
-int QTessellatorPrivate::Scanline::findEdgePosition(const Edge &e) const
-{
-// qDebug() << ">> findEdgePosition";
- int min = 0;
- int max = size;
- while (min < max) {
- int pos = min + ((max - min) >> 1);
-// qDebug() << " " << min << max << pos << edges[pos]->isLeftOf(e, e.y0);
- if (edges[pos]->isLeftOf(e, e.v0->y)) {
- min = pos + 1;
- } else {
- max = pos;
- }
- }
-// qDebug() << "<< findEdgePosition got" << min;
- return min;
-}
-
-int QTessellatorPrivate::Scanline::findEdge(int edge) const
-{
- for (int i = 0; i < size; ++i) {
- int item_edge = edges[i]->edge;
- if (item_edge == edge)
- return i;
- }
- //Q_ASSERT(false);
- return -1;
-}
-
-void QTessellatorPrivate::Scanline::clearMarks()
-{
- for (int i = 0; i < size; ++i) {
- edges[i]->mark = false;
- edges[i]->intersect_left = false;
- edges[i]->intersect_right = false;
- }
-}
-
-void QTessellatorPrivate::Scanline::prepareLine()
-{
- Edge **end = edges + size;
- Edge **e = edges;
- Edge **o = old;
- while (e < end) {
- *o = *e;
- ++o;
- ++e;
- }
- old_size = size;
-}
-
-void QTessellatorPrivate::Scanline::lineDone()
-{
- Edge **end = old + old_size;
- Edge **e = old;
- while (e < end) {
- if ((*e)->free) {
- (*e)->edge = first_unused;
- first_unused = (*e - edge_table);
- }
- ++e;
- }
-}
-
-void QTessellatorPrivate::Scanline::insert(int pos, const Edge &e)
-{
- Edge *edge = edge_table + first_unused;
- first_unused = edge->edge;
- Q_ASSERT(first_unused != -1);
- *edge = e;
- memmove(edges + pos + 1, edges + pos, (size - pos)*sizeof(Edge *));
- edges[pos] = edge;
- ++size;
-}
-
-void QTessellatorPrivate::Scanline::removeAt(int pos)
-{
- Edge *e = edges[pos];
- e->free = true;
- --size;
- memmove(edges + pos, edges + pos + 1, (size - pos)*sizeof(Edge *));
-}
-
-void QTessellatorPrivate::Scanline::markEdges(int pos1, int pos2)
-{
- if (pos2 < pos1)
- return;
-
- for (int i = pos1; i <= pos2; ++i)
- edges[i]->mark = true;
-}
-
-
-QTessellatorPrivate::Vertices::Vertices()
-{
- storage = 0;
- sorted = 0;
- allocated = 0;
- nPoints = 0;
-}
-
-QTessellatorPrivate::Vertices::~Vertices()
-{
- if (storage) {
- free(storage);
- free(sorted);
- }
-}
-
-void QTessellatorPrivate::Vertices::init(int maxVertices)
-{
- if (!storage || maxVertices > allocated) {
- int size = qMax((int)default_alloc, maxVertices);
- storage = q_check_ptr((Vertex *)realloc(storage, size*sizeof(Vertex)));
- sorted = q_check_ptr((Vertex **)realloc(sorted, size*sizeof(Vertex *)));
- allocated = maxVertices;
- }
-}
-
-void QTessellatorPrivate::Vertices::done()
-{
- if (allocated > default_alloc) {
- free(storage);
- free(sorted);
- storage = 0;
- sorted = 0;
- allocated = 0;
- }
-}
-
-
-
-static inline void fillTrapezoid(Q27Dot5 y1, Q27Dot5 y2, int left, int right,
- const QTessellatorPrivate::Vertices &vertices,
- QTessellator::Trapezoid *trap)
-{
- trap->top = y1;
- trap->bottom = y2;
- const QTessellatorPrivate::Vertex *v = vertices[left];
- trap->topLeft = v;
- trap->bottomLeft = vertices.next(v);
- if (trap->topLeft->y > trap->bottomLeft->y)
- qSwap(trap->topLeft,trap->bottomLeft);
- v = vertices[right];
- trap->topRight = v;
- trap->bottomRight = vertices.next(v);
- if (trap->topRight->y > trap->bottomRight->y)
- qSwap(trap->topRight, trap->bottomRight);
-}
-
-QRectF QTessellatorPrivate::collectAndSortVertices(const QPointF *points, int *maxActiveEdges)
-{
- *maxActiveEdges = 0;
- Vertex *v = vertices.storage;
- Vertex **vv = vertices.sorted;
-
- qreal xmin(points[0].x());
- qreal xmax(points[0].x());
- qreal ymin(points[0].y());
- qreal ymax(points[0].y());
-
- // collect vertex data
- Q27Dot5 y_prev = FloatToQ27Dot5(points[vertices.nPoints-1].y());
- Q27Dot5 x_next = FloatToQ27Dot5(points[0].x());
- Q27Dot5 y_next = FloatToQ27Dot5(points[0].y());
- int j = 0;
- int i = 0;
- while (i < vertices.nPoints) {
- Q27Dot5 y_curr = y_next;
-
- *vv = v;
-
- v->x = x_next;
- v->y = y_next;
- v->flags = 0;
-
- next_point:
-
- xmin = qMin(xmin, points[i+1].x());
- xmax = qMax(xmax, points[i+1].x());
- ymin = qMin(ymin, points[i+1].y());
- ymax = qMax(ymax, points[i+1].y());
-
- y_next = FloatToQ27Dot5(points[i+1].y());
- x_next = FloatToQ27Dot5(points[i+1].x());
-
- // skip vertices on top of each other
- if (v->x == x_next && v->y == y_next) {
- ++i;
- if (i < vertices.nPoints)
- goto next_point;
- Vertex *v0 = vertices.storage;
- v0->flags &= ~(LineBeforeStarts|LineBeforeEnds|LineBeforeHorizontal);
- if (y_prev < y_curr)
- v0->flags |= LineBeforeEnds;
- else if (y_prev > y_curr)
- v0->flags |= LineBeforeStarts;
- else
- v0->flags |= LineBeforeHorizontal;
- if ((v0->flags & (LineBeforeStarts|LineAfterStarts))
- && !(v0->flags & (LineAfterEnds|LineBeforeEnds)))
- *maxActiveEdges += 2;
- break;
- }
-
- if (y_prev < y_curr)
- v->flags |= LineBeforeEnds;
- else if (y_prev > y_curr)
- v->flags |= LineBeforeStarts;
- else
- v->flags |= LineBeforeHorizontal;
-
-
- if (y_curr < y_next)
- v->flags |= LineAfterStarts;
- else if (y_curr > y_next)
- v->flags |= LineAfterEnds;
- else
- v->flags |= LineAfterHorizontal;
- // ### could probably get better limit by looping over sorted list and counting down on ending edges
- if ((v->flags & (LineBeforeStarts|LineAfterStarts))
- && !(v->flags & (LineAfterEnds|LineBeforeEnds)))
- *maxActiveEdges += 2;
- y_prev = y_curr;
- ++v;
- ++vv;
- ++j;
- ++i;
- }
- vertices.nPoints = j;
-
- QDEBUG() << "maxActiveEdges=" << *maxActiveEdges;
- vv = vertices.sorted;
- std::sort(vv, vv + vertices.nPoints, compareVertex);
-
- return QRectF(xmin, ymin, xmax-xmin, ymax-ymin);
-}
-
-struct QCoincidingEdge {
- QTessellatorPrivate::Vertex *start;
- QTessellatorPrivate::Vertex *end;
- bool used;
- bool before;
-
- inline bool operator<(const QCoincidingEdge &e2) const
- {
- return end->y == e2.end->y ? end->x < e2.end->x : end->y < e2.end->y;
- }
-};
-
-static void cancelEdges(QCoincidingEdge &e1, QCoincidingEdge &e2)
-{
- if (e1.before) {
- e1.start->flags &= ~(LineBeforeStarts|LineBeforeHorizontal);
- e1.end->flags &= ~(LineAfterEnds|LineAfterHorizontal);
- } else {
- e1.start->flags &= ~(LineAfterStarts|LineAfterHorizontal);
- e1.end->flags &= ~(LineBeforeEnds|LineBeforeHorizontal);
- }
- if (e2.before) {
- e2.start->flags &= ~(LineBeforeStarts|LineBeforeHorizontal);
- e2.end->flags &= ~(LineAfterEnds|LineAfterHorizontal);
- } else {
- e2.start->flags &= ~(LineAfterStarts|LineAfterHorizontal);
- e2.end->flags &= ~(LineBeforeEnds|LineBeforeHorizontal);
- }
- e1.used = e2.used = true;
-}
-
-void QTessellatorPrivate::cancelCoincidingEdges()
-{
- Vertex **vv = vertices.sorted;
-
- QCoincidingEdge *tl = nullptr;
- int tlSize = 0;
-
- for (int i = 0; i < vertices.nPoints - 1; ++i) {
- Vertex *v = vv[i];
- int testListSize = 0;
- while (i < vertices.nPoints - 1) {
- Vertex *n = vv[i];
- if (v->x != n->x || v->y != n->y)
- break;
-
- if (testListSize > tlSize - 2) {
- tlSize = qMax(tlSize*2, 16);
- tl = q_check_ptr((QCoincidingEdge *)realloc(tl, tlSize*sizeof(QCoincidingEdge)));
- }
- if (n->flags & (LineBeforeStarts|LineBeforeHorizontal)) {
- tl[testListSize].start = n;
- tl[testListSize].end = vertices.prev(n);
- tl[testListSize].used = false;
- tl[testListSize].before = true;
- ++testListSize;
- }
- if (n->flags & (LineAfterStarts|LineAfterHorizontal)) {
- tl[testListSize].start = n;
- tl[testListSize].end = vertices.next(n);
- tl[testListSize].used = false;
- tl[testListSize].before = false;
- ++testListSize;
- }
- ++i;
- }
- if (!testListSize)
- continue;
-
- std::sort(tl, tl + testListSize);
-
-QT_WARNING_PUSH
-QT_WARNING_DISABLE_CLANG("-Wfor-loop-analysis")
- for (int j = 0; j < testListSize; ++j) {
- if (tl[j].used)
- continue;
-
- for (int k = j + 1; k < testListSize; ++k) {
- if (tl[j].end->x != tl[k].end->x
- || tl[j].end->y != tl[k].end->y
- || tl[k].used)
- break;
-
- if (!winding || tl[j].before != tl[k].before) {
- cancelEdges(tl[j], tl[k]);
- break;
- }
- ++k;
- }
- ++j;
- }
-QT_WARNING_POP
- }
- free(tl);
-}
-
-
-void QTessellatorPrivate::emitEdges(QTessellator *tessellator)
-{
- //QDEBUG() << "TRAPS:";
- if (!scanline.old_size)
- return;
-
- // emit edges
- if (winding) {
- // winding fill rule
- int w = 0;
-
- scanline.old[0]->y_left = y;
-
- for (int i = 0; i < scanline.old_size - 1; ++i) {
- Edge *left = scanline.old[i];
- Edge *right = scanline.old[i+1];
- w += left->winding;
-// qDebug() << "i=" << i << "edge->winding=" << left->winding << "winding=" << winding;
- if (w == 0) {
- left->y_right = y;
- right->y_left = y;
- } else if (!emit_clever || left->mark || right->mark) {
- Q27Dot5 top = qMax(left->y_right, right->y_left);
- if (top != y) {
- QTessellator::Trapezoid trap;
- fillTrapezoid(top, y, left->edge, right->edge, vertices, &trap);
- tessellator->addTrap(trap);
-// QDEBUG() << " top=" << Q27Dot5ToDouble(top) << "left=" << left->edge << "right=" << right->edge;
- }
- right->y_left = y;
- left->y_right = y;
- }
- left->mark = false;
- }
- if (scanline.old[scanline.old_size - 1]->mark) {
- scanline.old[scanline.old_size - 1]->y_right = y;
- scanline.old[scanline.old_size - 1]->mark = false;
- }
- } else {
- // odd-even fill rule
- for (int i = 0; i < scanline.old_size; i += 2) {
- Edge *left = scanline.old[i];
- Edge *right = scanline.old[i+1];
- if (!emit_clever || left->mark || right->mark) {
- Q27Dot5 top = qMax(left->y_right, right->y_left);
- if (top != y) {
- QTessellator::Trapezoid trap;
- fillTrapezoid(top, y, left->edge, right->edge, vertices, &trap);
- tessellator->addTrap(trap);
- }
-// QDEBUG() << " top=" << Q27Dot5ToDouble(top) << "left=" << left->edge << "right=" << right->edge;
- left->y_left = y;
- left->y_right = y;
- right->y_left = y;
- right->y_right = y;
- left->mark = right->mark = false;
- }
- }
- }
-}
-
-
-void QTessellatorPrivate::processIntersections()
-{
- QDEBUG() << "PROCESS INTERSECTIONS";
- // process intersections
- while (!intersections.isEmpty()) {
- Intersections::iterator it = intersections.begin();
- if (it.key().y != y)
- break;
-
- // swap edges
- QDEBUG() << " swapping intersecting edges ";
- int min = scanline.size;
- int max = 0;
- Q27Dot5 xmin = INT_MAX;
- Q27Dot5 xmax = INT_MIN;
- int num = 0;
- while (1) {
- const Intersection i = it.key();
- int next = it->next;
-
- int edgePos = scanline.findEdge(i.edge);
- if (edgePos >= 0) {
- ++num;
- min = qMin(edgePos, min);
- max = qMax(edgePos, max);
- Edge *edge = scanline.edges[edgePos];
- xmin = qMin(xmin, edge->positionAt(y));
- xmax = qMax(xmax, edge->positionAt(y));
- }
- Intersection key;
- key.y = y;
- key.edge = next;
- it = intersections.find(key);
- intersections.remove(i);
- if (it == intersections.end())
- break;
- }
- if (num < 2)
- continue;
-
- Q_ASSERT(min != max);
- QDEBUG() << "sorting between" << min << "and" << max << "xpos=" << xmin << xmax;
- while (min > 0 && scanline.edges[min - 1]->positionAt(y) >= xmin) {
- QDEBUG() << " adding edge on left";
- --min;
- }
- while (max < scanline.size - 1 && scanline.edges[max + 1]->positionAt(y) <= xmax) {
- QDEBUG() << " adding edge on right";
- ++max;
- }
-
- std::sort(scanline.edges + min, scanline.edges + max + 1, EdgeSorter(y));
-#ifdef DEBUG
- for (int i = min; i <= max; ++i)
- QDEBUG() << " " << scanline.edges[i]->edge << "at pos" << i;
-#endif
- for (int i = min; i <= max; ++i) {
- Edge *edge = scanline.edges[i];
- edge->intersect_left = true;
- edge->intersect_right = true;
- edge->mark = true;
- }
- }
-}
-
-void QTessellatorPrivate::removeEdges()
-{
- int cv = currentVertex;
- while (cv < vertices.nPoints) {
- const Vertex *v = vertices.sorted[cv];
- if (v->y > y)
- break;
- if (v->flags & LineBeforeEnds) {
- QDEBUG() << " removing edge" << vertices.prevPos(v);
- int pos = scanline.findEdge(vertices.prevPos(v));
- if (pos == -1)
- continue;
- scanline.edges[pos]->mark = true;
- if (pos > 0)
- scanline.edges[pos - 1]->intersect_right = true;
- if (pos < scanline.size - 1)
- scanline.edges[pos + 1]->intersect_left = true;
- scanline.removeAt(pos);
- }
- if (v->flags & LineAfterEnds) {
- QDEBUG() << " removing edge" << vertices.position(v);
- int pos = scanline.findEdge(vertices.position(v));
- if (pos == -1)
- continue;
- scanline.edges[pos]->mark = true;
- if (pos > 0)
- scanline.edges[pos - 1]->intersect_right = true;
- if (pos < scanline.size - 1)
- scanline.edges[pos + 1]->intersect_left = true;
- scanline.removeAt(pos);
- }
- ++cv;
- }
-}
-
-void QTessellatorPrivate::addEdges()
-{
- while (currentVertex < vertices.nPoints) {
- const Vertex *v = vertices.sorted[currentVertex];
- if (v->y > y)
- break;
- if (v->flags & LineBeforeStarts) {
- // add new edge
- int start = vertices.prevPos(v);
- Edge e(vertices, start);
- int pos = scanline.findEdgePosition(e);
- QDEBUG() << " adding edge" << start << "at position" << pos;
- scanline.insert(pos, e);
- if (!mark_clever || !(v->flags & LineAfterEnds)) {
- if (pos > 0)
- scanline.edges[pos - 1]->mark = true;
- if (pos < scanline.size - 1)
- scanline.edges[pos + 1]->mark = true;
- }
- }
- if (v->flags & LineAfterStarts) {
- Edge e(vertices, vertices.position(v));
- int pos = scanline.findEdgePosition(e);
- QDEBUG() << " adding edge" << vertices.position(v) << "at position" << pos;
- scanline.insert(pos, e);
- if (!mark_clever || !(v->flags & LineBeforeEnds)) {
- if (pos > 0)
- scanline.edges[pos - 1]->mark = true;
- if (pos < scanline.size - 1)
- scanline.edges[pos + 1]->mark = true;
- }
- }
- if (v->flags & LineAfterHorizontal) {
- int pos1 = scanline.findEdgePosition(v->x, v->y);
- const Vertex *next = vertices.next(v);
- Q_ASSERT(v->y == next->y);
- int pos2 = scanline.findEdgePosition(next->x, next->y);
- if (pos2 < pos1)
- qSwap(pos1, pos2);
- if (pos1 > 0)
- --pos1;
- if (pos2 == scanline.size)
- --pos2;
- //QDEBUG() << "marking horizontal edge from " << pos1 << "to" << pos2;
- scanline.markEdges(pos1, pos2);
- }
- ++currentVertex;
- }
-}
-
-#ifdef DEBUG
-static void checkLinkChain(const QTessellatorPrivate::Intersections &intersections,
- QTessellatorPrivate::Intersection i)
-{
-// qDebug() << " Link chain: ";
- int end = i.edge;
- while (1) {
- QTessellatorPrivate::IntersectionLink l = intersections.value(i);
-// qDebug() << " " << i.edge << "next=" << l.next << "prev=" << l.prev;
- if (l.next == end)
- break;
- Q_ASSERT(l.next != -1);
- Q_ASSERT(l.prev != -1);
-
- QTessellatorPrivate::Intersection i2 = i;
- i2.edge = l.next;
- QTessellatorPrivate::IntersectionLink l2 = intersections.value(i2);
-
- Q_ASSERT(l2.next != -1);
- Q_ASSERT(l2.prev != -1);
- Q_ASSERT(l.next == i2.edge);
- Q_ASSERT(l2.prev == i.edge);
- i = i2;
- }
-}
-#endif
-
-bool QTessellatorPrivate::edgeInChain(Intersection i, int edge)
-{
- int end = i.edge;
- while (1) {
- if (i.edge == edge)
- return true;
- IntersectionLink l = intersections.value(i);
- if (l.next == end)
- break;
- Q_ASSERT(l.next != -1);
- Q_ASSERT(l.prev != -1);
-
- Intersection i2 = i;
- i2.edge = l.next;
-
-#ifndef QT_NO_DEBUG
- IntersectionLink l2 = intersections.value(i2);
- Q_ASSERT(l2.next != -1);
- Q_ASSERT(l2.prev != -1);
- Q_ASSERT(l.next == i2.edge);
- Q_ASSERT(l2.prev == i.edge);
-#endif
- i = i2;
- }
- return false;
-}
-
-
-void QTessellatorPrivate::addIntersection(const Edge *e1, const Edge *e2)
-{
- const IntersectionLink emptyLink = {-1, -1};
-
- int next = vertices.nextPos(vertices[e1->edge]);
- if (e2->edge == next)
- return;
- int prev = vertices.prevPos(vertices[e1->edge]);
- if (e2->edge == prev)
- return;
-
- Q27Dot5 yi;
- bool det_positive;
- bool isect = e1->intersect(*e2, &yi, &det_positive);
- QDEBUG("checking edges %d and %d", e1->edge, e2->edge);
- if (!isect) {
- QDEBUG() << " no intersection";
- return;
- }
-
- // don't emit an intersection if it's at the start of a line segment or above us
- if (yi <= y) {
- if (!det_positive)
- return;
- QDEBUG() << " ----->>>>>> WRONG ORDER!";
- yi = y;
- }
- QDEBUG() << " between edges " << e1->edge << "and" << e2->edge << "at point ("
- << Q27Dot5ToDouble(yi) << ')';
-
- Intersection i1;
- i1.y = yi;
- i1.edge = e1->edge;
- IntersectionLink link1 = intersections.value(i1, emptyLink);
- Intersection i2;
- i2.y = yi;
- i2.edge = e2->edge;
- IntersectionLink link2 = intersections.value(i2, emptyLink);
-
- // new pair of edges
- if (link1.next == -1 && link2.next == -1) {
- link1.next = link1.prev = i2.edge;
- link2.next = link2.prev = i1.edge;
- } else if (link1.next == i2.edge || link1.prev == i2.edge
- || link2.next == i1.edge || link2.prev == i1.edge) {
-#ifdef DEBUG
- checkLinkChain(intersections, i1);
- checkLinkChain(intersections, i2);
- Q_ASSERT(edgeInChain(i1, i2.edge));
-#endif
- return;
- } else if (link1.next == -1 || link2.next == -1) {
- if (link2.next == -1) {
- qSwap(i1, i2);
- qSwap(link1, link2);
- }
- Q_ASSERT(link1.next == -1);
-#ifdef DEBUG
- checkLinkChain(intersections, i2);
-#endif
- // only i2 in list
- link1.next = i2.edge;
- link1.prev = link2.prev;
- link2.prev = i1.edge;
- Intersection other;
- other.y = yi;
- other.edge = link1.prev;
- IntersectionLink link = intersections.value(other, emptyLink);
- Q_ASSERT(link.next == i2.edge);
- Q_ASSERT(link.prev != -1);
- link.next = i1.edge;
- intersections.insert(other, link);
- } else {
- bool connected = edgeInChain(i1, i2.edge);
- if (connected)
- return;
-#ifdef DEBUG
- checkLinkChain(intersections, i1);
- checkLinkChain(intersections, i2);
-#endif
- // both already in some list. Have to make sure they are connected
- // this can be done by cutting open the ring(s) after the two eges and
- // connecting them again
- Intersection other1;
- other1.y = yi;
- other1.edge = link1.next;
- IntersectionLink linko1 = intersections.value(other1, emptyLink);
- Intersection other2;
- other2.y = yi;
- other2.edge = link2.next;
- IntersectionLink linko2 = intersections.value(other2, emptyLink);
-
- linko1.prev = i2.edge;
- link2.next = other1.edge;
-
- linko2.prev = i1.edge;
- link1.next = other2.edge;
- intersections.insert(other1, linko1);
- intersections.insert(other2, linko2);
- }
- intersections.insert(i1, link1);
- intersections.insert(i2, link2);
-#ifdef DEBUG
- checkLinkChain(intersections, i1);
- checkLinkChain(intersections, i2);
- Q_ASSERT(edgeInChain(i1, i2.edge));
-#endif
- return;
-
-}
-
-
-void QTessellatorPrivate::addIntersections()
-{
- if (scanline.size) {
- QDEBUG() << "INTERSECTIONS";
- // check marked edges for intersections
-#ifdef DEBUG
- for (int i = 0; i < scanline.size; ++i) {
- Edge *e = scanline.edges[i];
- QDEBUG() << " " << i << e->edge << "isect=(" << e->intersect_left << e->intersect_right
- << ')';
- }
-#endif
-
- for (int i = 0; i < scanline.size - 1; ++i) {
- Edge *e1 = scanline.edges[i];
- Edge *e2 = scanline.edges[i + 1];
- // check for intersection
- if (e1->intersect_right || e2->intersect_left)
- addIntersection(e1, e2);
- }
- }
-#if 0
- if (intersections.constBegin().key().y == y) {
- QDEBUG() << "----------------> intersection on same line";
- scanline.clearMarks();
- scanline.processIntersections(y, &intersections);
- goto redo;
- }
-#endif
-}
-
-
-QTessellator::QTessellator()
-{
- d = new QTessellatorPrivate;
-}
-
-QTessellator::~QTessellator()
-{
- delete d;
-}
-
-void QTessellator::setWinding(bool w)
-{
- d->winding = w;
-}
-
-
-QRectF QTessellator::tessellate(const QPointF *points, int nPoints)
-{
- Q_ASSERT(points[0] == points[nPoints-1]);
- --nPoints;
-
-#ifdef DEBUG
- QDEBUG()<< "POINTS:";
- for (int i = 0; i < nPoints; ++i) {
- QDEBUG() << points[i];
- }
-#endif
-
- // collect edges and calculate bounds
- d->vertices.nPoints = nPoints;
- d->vertices.init(nPoints);
-
- int maxActiveEdges = 0;
- QRectF br = d->collectAndSortVertices(points, &maxActiveEdges);
- d->cancelCoincidingEdges();
-
-#ifdef DEBUG
- QDEBUG() << "nPoints = " << nPoints << "using " << d->vertices.nPoints;
- QDEBUG()<< "VERTICES:";
- for (int i = 0; i < d->vertices.nPoints; ++i) {
- QDEBUG() << " " << i << ": "
- << "point=" << d->vertices.position(d->vertices.sorted[i])
- << "flags=" << d->vertices.sorted[i]->flags
- << "pos=(" << Q27Dot5ToDouble(d->vertices.sorted[i]->x) << '/'
- << Q27Dot5ToDouble(d->vertices.sorted[i]->y) << ')';
- }
-#endif
-
- d->scanline.init(maxActiveEdges);
- d->y = INT_MIN/256;
- d->currentVertex = 0;
-
- while (d->currentVertex < d->vertices.nPoints) {
- d->scanline.clearMarks();
-
- d->y = d->vertices.sorted[d->currentVertex]->y;
- if (!d->intersections.isEmpty())
- d->y = qMin(d->y, d->intersections.constBegin().key().y);
-
- QDEBUG()<< "===== SCANLINE: y =" << Q27Dot5ToDouble(d->y) << " =====";
-
- d->scanline.prepareLine();
- d->processIntersections();
- d->removeEdges();
- d->addEdges();
- d->addIntersections();
- d->emitEdges(this);
- d->scanline.lineDone();
-
-#ifdef DEBUG
- QDEBUG()<< "===== edges:";
- for (int i = 0; i < d->scanline.size; ++i) {
- QDEBUG() << " " << d->scanline.edges[i]->edge
- << "p0= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v0->x)
- << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v0->y)
- << ") p1= (" << Q27Dot5ToDouble(d->scanline.edges[i]->v1->x)
- << '/' << Q27Dot5ToDouble(d->scanline.edges[i]->v1->y) << ')'
- << "x=" << Q27Dot5ToDouble(d->scanline.edges[i]->positionAt(d->y))
- << "isLeftOfNext="
- << ((i < d->scanline.size - 1)
- ? d->scanline.edges[i]->isLeftOf(*d->scanline.edges[i+1], d->y)
- : true);
- }
-#endif
-}
-
- d->scanline.done();
- d->intersections.clear();
- return br;
-}
-
-// tessellates the given convex polygon
-void QTessellator::tessellateConvex(const QPointF *points, int nPoints)
-{
- Q_ASSERT(points[0] == points[nPoints-1]);
- --nPoints;
-
- d->vertices.nPoints = nPoints;
- d->vertices.init(nPoints);
-
- for (int i = 0; i < nPoints; ++i) {
- d->vertices[i]->x = FloatToQ27Dot5(points[i].x());
- d->vertices[i]->y = FloatToQ27Dot5(points[i].y());
- }
-
- int left = 0, right = 0;
-
- int top = 0;
- for (int i = 1; i < nPoints; ++i) {
- if (d->vertices[i]->y < d->vertices[top]->y)
- top = i;
- }
-
- left = (top + nPoints - 1) % nPoints;
- right = (top + 1) % nPoints;
-
- while (d->vertices[left]->x == d->vertices[top]->x && d->vertices[left]->y == d->vertices[top]->y && left != right)
- left = (left + nPoints - 1) % nPoints;
-
- while (d->vertices[right]->x == d->vertices[top]->x && d->vertices[right]->y == d->vertices[top]->y && left != right)
- right = (right + 1) % nPoints;
-
- if (left == right)
- return;
-
- int dir = 1;
-
- Vertex dLeft = { d->vertices[top]->x - d->vertices[left]->x,
- d->vertices[top]->y - d->vertices[left]->y };
-
- Vertex dRight = { d->vertices[right]->x - d->vertices[top]->x,
- d->vertices[right]->y - d->vertices[top]->y };
-
- Q27Dot5 cross = dLeft.x * dRight.y - dLeft.y * dRight.x;
-
- // flip direction if polygon is clockwise
- if (cross < 0 || (cross == 0 && dLeft.x > 0)) {
- qSwap(left, right);
- dir = -1;
- }
-
- Vertex *lastLeft = d->vertices[top];
- Vertex *lastRight = d->vertices[top];
-
- QTessellator::Trapezoid trap;
-
- while (lastLeft->y == d->vertices[left]->y && left != right) {
- lastLeft = d->vertices[left];
- left = (left + nPoints - dir) % nPoints;
- }
-
- while (lastRight->y == d->vertices[right]->y && left != right) {
- lastRight = d->vertices[right];
- right = (right + nPoints + dir) % nPoints;
- }
-
- while (true) {
- trap.top = qMax(lastRight->y, lastLeft->y);
- trap.bottom = qMin(d->vertices[left]->y, d->vertices[right]->y);
- trap.topLeft = lastLeft;
- trap.topRight = lastRight;
- trap.bottomLeft = d->vertices[left];
- trap.bottomRight = d->vertices[right];
-
- if (trap.bottom > trap.top)
- addTrap(trap);
-
- if (left == right)
- break;
-
- if (d->vertices[right]->y < d->vertices[left]->y) {
- do {
- lastRight = d->vertices[right];
- right = (right + nPoints + dir) % nPoints;
- }
- while (lastRight->y == d->vertices[right]->y && left != right);
- } else {
- do {
- lastLeft = d->vertices[left];
- left = (left + nPoints - dir) % nPoints;
- }
- while (lastLeft->y == d->vertices[left]->y && left != right);
- }
- }
-}
-
-// tessellates the stroke of the line from a_ to b_ with the given width and a flat cap
-void QTessellator::tessellateRect(const QPointF &a_, const QPointF &b_, qreal width)
-{
- Vertex a = { FloatToQ27Dot5(a_.x()), FloatToQ27Dot5(a_.y()) };
- Vertex b = { FloatToQ27Dot5(b_.x()), FloatToQ27Dot5(b_.y()) };
-
- QPointF pa = a_, pb = b_;
-
- if (a.y > b.y) {
- qSwap(a, b);
- qSwap(pa, pb);
- }
-
- Vertex delta = { b.x - a.x, b.y - a.y };
-
- if (delta.x == 0 && delta.y == 0)
- return;
-
- qreal hw = 0.5 * width;
-
- if (delta.x == 0) {
- Q27Dot5 halfWidth = FloatToQ27Dot5(hw);
-
- if (halfWidth == 0)
- return;
-
- Vertex topLeft = { a.x - halfWidth, a.y };
- Vertex topRight = { a.x + halfWidth, a.y };
- Vertex bottomLeft = { a.x - halfWidth, b.y };
- Vertex bottomRight = { a.x + halfWidth, b.y };
-
- QTessellator::Trapezoid trap = { topLeft.y, bottomLeft.y, &topLeft, &bottomLeft, &topRight, &bottomRight };
- addTrap(trap);
- } else if (delta.y == 0) {
- Q27Dot5 halfWidth = FloatToQ27Dot5(hw);
-
- if (halfWidth == 0)
- return;
-
- if (a.x > b.x)
- qSwap(a.x, b.x);
-
- Vertex topLeft = { a.x, a.y - halfWidth };
- Vertex topRight = { b.x, a.y - halfWidth };
- Vertex bottomLeft = { a.x, a.y + halfWidth };
- Vertex bottomRight = { b.x, a.y + halfWidth };
-
- QTessellator::Trapezoid trap = { topLeft.y, bottomLeft.y, &topLeft, &bottomLeft, &topRight, &bottomRight };
- addTrap(trap);
- } else {
- QPointF perp(pb.y() - pa.y(), pa.x() - pb.x());
- qreal length = qSqrt(perp.x() * perp.x() + perp.y() * perp.y());
-
- if (qFuzzyIsNull(length))
- return;
-
- // need the half of the width
- perp *= hw / length;
-
- QPointF pta = pa + perp;
- QPointF ptb = pa - perp;
- QPointF ptc = pb - perp;
- QPointF ptd = pb + perp;
-
- Vertex ta = { FloatToQ27Dot5(pta.x()), FloatToQ27Dot5(pta.y()) };
- Vertex tb = { FloatToQ27Dot5(ptb.x()), FloatToQ27Dot5(ptb.y()) };
- Vertex tc = { FloatToQ27Dot5(ptc.x()), FloatToQ27Dot5(ptc.y()) };
- Vertex td = { FloatToQ27Dot5(ptd.x()), FloatToQ27Dot5(ptd.y()) };
-
- if (ta.y < tb.y) {
- if (tb.y < td.y) {
- QTessellator::Trapezoid top = { ta.y, tb.y, &ta, &tb, &ta, &td };
- QTessellator::Trapezoid bottom = { td.y, tc.y, &tb, &tc, &td, &tc };
- addTrap(top);
- addTrap(bottom);
-
- QTessellator::Trapezoid middle = { tb.y, td.y, &tb, &tc, &ta, &td };
- addTrap(middle);
- } else {
- QTessellator::Trapezoid top = { ta.y, td.y, &ta, &tb, &ta, &td };
- QTessellator::Trapezoid bottom = { tb.y, tc.y, &tb, &tc, &td, &tc };
- addTrap(top);
- addTrap(bottom);
-
- if (tb.y != td.y) {
- QTessellator::Trapezoid middle = { td.y, tb.y, &ta, &tb, &td, &tc };
- addTrap(middle);
- }
- }
- } else {
- if (ta.y < tc.y) {
- QTessellator::Trapezoid top = { tb.y, ta.y, &tb, &tc, &tb, &ta };
- QTessellator::Trapezoid bottom = { tc.y, td.y, &tc, &td, &ta, &td };
- addTrap(top);
- addTrap(bottom);
-
- QTessellator::Trapezoid middle = { ta.y, tc.y, &tb, &tc, &ta, &td };
- addTrap(middle);
- } else {
- QTessellator::Trapezoid top = { tb.y, tc.y, &tb, &tc, &tb, &ta };
- QTessellator::Trapezoid bottom = { ta.y, td.y, &tc, &td, &ta, &td };
- addTrap(top);
- addTrap(bottom);
-
- if (ta.y != tc.y) {
- QTessellator::Trapezoid middle = { tc.y, ta.y, &tc, &td, &tb, &ta };
- addTrap(middle);
- }
- }
- }
- }
-}
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qtessellator_p.h b/src/plugins/platforms/xcb/nativepainting/qtessellator_p.h
deleted file mode 100644
index ba1d3a971a3..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qtessellator_p.h
+++ /dev/null
@@ -1,51 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#pragma once
-
-#include <QPoint>
-#include <QRect>
-
-QT_BEGIN_NAMESPACE
-
-class QTessellatorPrivate;
-
-typedef int Q27Dot5;
-#define Q27Dot5ToDouble(i) ((i)/32.)
-#define FloatToQ27Dot5(i) (int)((i) * 32)
-#define IntToQ27Dot5(i) ((i) << 5)
-#define Q27Dot5ToXFixed(i) ((i) << 11)
-#define Q27Dot5Factor 32
-
-class QTessellator {
-public:
- QTessellator();
- virtual ~QTessellator();
-
- QRectF tessellate(const QPointF *points, int nPoints);
- void tessellateConvex(const QPointF *points, int nPoints);
- void tessellateRect(const QPointF &a, const QPointF &b, qreal width);
-
- void setWinding(bool w);
-
- struct Vertex {
- Q27Dot5 x;
- Q27Dot5 y;
- };
- struct Trapezoid {
- Q27Dot5 top;
- Q27Dot5 bottom;
- const Vertex *topLeft;
- const Vertex *bottomLeft;
- const Vertex *topRight;
- const Vertex *bottomRight;
- };
- virtual void addTrap(const Trapezoid &trap) = 0;
-
-private:
- friend class QTessellatorPrivate;
- QTessellatorPrivate *d;
-};
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp
deleted file mode 100644
index 23155ef2e62..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.cpp
+++ /dev/null
@@ -1,288 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#include <QtCore/qrandom.h>
-
-#include "qxcbconnection.h"
-#include "qcolormap_x11_p.h"
-#include "qxcbnativepainting.h"
-#include "qt_x11_p.h"
-
-QT_BEGIN_NAMESPACE
-
-QXcbX11Data *qt_x11Data = nullptr;
-
-void qt_xcb_native_x11_info_init(QXcbConnection *conn)
-{
- qt_x11Data = new QXcbX11Data;
- X11->display = static_cast<Display *>(conn->xlib_display());
- X11->defaultScreen = DefaultScreen(X11->display);
- X11->screenCount = ScreenCount(X11->display);
-
- X11->screens = new QX11InfoData[X11->screenCount];
- X11->argbVisuals = new Visual *[X11->screenCount];
- X11->argbColormaps = new Colormap[X11->screenCount];
-
- for (int s = 0; s < X11->screenCount; s++) {
- QX11InfoData *screen = X11->screens + s;
- //screen->ref = 1; // ensures it doesn't get deleted
- screen->screen = s;
-
- int widthMM = DisplayWidthMM(X11->display, s);
- if (widthMM != 0) {
- screen->dpiX = (DisplayWidth(X11->display, s) * 254 + widthMM * 5) / (widthMM * 10);
- } else {
- screen->dpiX = 72;
- }
-
- int heightMM = DisplayHeightMM(X11->display, s);
- if (heightMM != 0) {
- screen->dpiY = (DisplayHeight(X11->display, s) * 254 + heightMM * 5) / (heightMM * 10);
- } else {
- screen->dpiY = 72;
- }
-
- X11->argbVisuals[s] = 0;
- X11->argbColormaps[s] = 0;
- }
-
- X11->use_xrender = conn->hasXRender() && !qEnvironmentVariableIsSet("QT_XCB_NATIVE_PAINTING_NO_XRENDER");
-
-#if QT_CONFIG(xrender)
- memset(X11->solid_fills, 0, sizeof(X11->solid_fills));
- for (int i = 0; i < X11->solid_fill_count; ++i)
- X11->solid_fills[i].screen = -1;
- memset(X11->pattern_fills, 0, sizeof(X11->pattern_fills));
- for (int i = 0; i < X11->pattern_fill_count; ++i)
- X11->pattern_fills[i].screen = -1;
-#endif
-
- QXcbColormap::initialize();
-
-#if QT_CONFIG(xrender)
- if (X11->use_xrender) {
- // XRender is supported, let's see if we have a PictFormat for the
- // default visual
- XRenderPictFormat *format =
- XRenderFindVisualFormat(X11->display,
- (Visual *) QXcbX11Info::appVisual(X11->defaultScreen));
-
- if (!format) {
- X11->use_xrender = false;
- }
- }
-#endif // QT_CONFIG(xrender)
-}
-
-QList<XRectangle> qt_region_to_xrectangles(const QRegion &r)
-{
- const int numRects = r.rectCount();
- const auto input = r.begin();
- QList<XRectangle> output(numRects);
- for (int i = 0; i < numRects; ++i) {
- const QRect &in = input[i];
- XRectangle &out = output[i];
- out.x = qMax(SHRT_MIN, in.x());
- out.y = qMax(SHRT_MIN, in.y());
- out.width = qMin((int)USHRT_MAX, in.width());
- out.height = qMin((int)USHRT_MAX, in.height());
- }
- return output;
-}
-
-class QXcbX11InfoData : public QSharedData, public QX11InfoData
-{};
-
-QXcbX11Info::QXcbX11Info()
- : d(nullptr)
-{}
-
-QXcbX11Info::~QXcbX11Info()
-{}
-
-QXcbX11Info::QXcbX11Info(const QXcbX11Info &other)
- : d(other.d)
-{}
-
-QXcbX11Info &QXcbX11Info::operator=(const QXcbX11Info &other)
-{
- d = other.d;
- return *this;
-}
-
-QXcbX11Info QXcbX11Info::fromScreen(int screen)
-{
- QXcbX11InfoData *xd = new QXcbX11InfoData;
- xd->screen = screen;
- xd->depth = QXcbX11Info::appDepth(screen);
- xd->cells = QXcbX11Info::appCells(screen);
- xd->colormap = QXcbX11Info::appColormap(screen);
- xd->defaultColormap = QXcbX11Info::appDefaultColormap(screen);
- xd->visual = (Visual *)QXcbX11Info::appVisual(screen);
- xd->defaultVisual = QXcbX11Info::appDefaultVisual(screen);
-
- QXcbX11Info info;
- info.d = xd;
- return info;
-}
-
-void QXcbX11Info::setDepth(int depth)
-{
- if (!d)
- *this = fromScreen(appScreen());
-
- d->depth = depth;
-}
-
-Display *QXcbX11Info::display()
-{
- return X11 ? X11->display : 0;
-}
-
-int QXcbX11Info::screen() const
-{
- return d ? d->screen : QXcbX11Info::appScreen();
-}
-
-int QXcbX11Info::depth() const
-{
- return d ? d->depth : QXcbX11Info::appDepth();
-}
-
-Colormap QXcbX11Info::colormap() const
-{
- return d ? d->colormap : QXcbX11Info::appColormap();
-}
-
-void *QXcbX11Info::visual() const
-{
- return d ? d->visual : QXcbX11Info::appVisual();
-}
-
-void QXcbX11Info::setVisual(void *visual)
-{
- if (!d)
- *this = fromScreen(appScreen());
-
- d->visual = (Visual *) visual;
-}
-
-int QXcbX11Info::appScreen()
-{
- return X11 ? X11->defaultScreen : 0;
-}
-
-int QXcbX11Info::appDepth(int screen)
-{
- return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].depth : 32;
-}
-
-int QXcbX11Info::appCells(int screen)
-{
- return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].cells : 0;
-}
-
-Colormap QXcbX11Info::appColormap(int screen)
-{
- return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].colormap : 0;
-}
-
-void *QXcbX11Info::appVisual(int screen)
-{
- return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].visual : 0;
-}
-
-Window QXcbX11Info::appRootWindow(int screen)
-{
- return X11 ? RootWindow(X11->display, screen == -1 ? X11->defaultScreen : screen) : 0;
-}
-
-bool QXcbX11Info::appDefaultColormap(int screen)
-{
- return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultColormap : true;
-}
-
-bool QXcbX11Info::appDefaultVisual(int screen)
-{
- return X11 ? X11->screens[screen == -1 ? X11->defaultScreen : screen].defaultVisual : true;
-}
-
-int QXcbX11Info::appDpiX(int screen)
-{
- if (!X11)
- return 75;
- if (screen < 0)
- screen = X11->defaultScreen;
- if (screen > X11->screenCount)
- return 0;
- return X11->screens[screen].dpiX;
-}
-
-int QXcbX11Info::appDpiY(int screen)
-{
- if (!X11)
- return 75;
- if (screen < 0)
- screen = X11->defaultScreen;
- if (screen > X11->screenCount)
- return 0;
- return X11->screens[screen].dpiY;
-}
-
-#if QT_CONFIG(xrender)
-Picture QXcbX11Data::getSolidFill(int screen, const QColor &c)
-{
- if (!X11->use_xrender)
- return XNone;
-
- XRenderColor color = preMultiply(c);
- for (int i = 0; i < X11->solid_fill_count; ++i) {
- if (X11->solid_fills[i].screen == screen
- && X11->solid_fills[i].color.alpha == color.alpha
- && X11->solid_fills[i].color.red == color.red
- && X11->solid_fills[i].color.green == color.green
- && X11->solid_fills[i].color.blue == color.blue)
- return X11->solid_fills[i].picture;
- }
- // none found, replace one
- int i = QRandomGenerator::global()->generate() % 16;
-
- if (X11->solid_fills[i].screen != screen && X11->solid_fills[i].picture) {
- XRenderFreePicture (X11->display, X11->solid_fills[i].picture);
- X11->solid_fills[i].picture = 0;
- }
-
- if (!X11->solid_fills[i].picture) {
- Pixmap pixmap = XCreatePixmap (X11->display, RootWindow (X11->display, screen), 1, 1, 32);
- XRenderPictureAttributes attrs;
- attrs.repeat = True;
- X11->solid_fills[i].picture = XRenderCreatePicture (X11->display, pixmap,
- XRenderFindStandardFormat(X11->display, PictStandardARGB32),
- CPRepeat, &attrs);
- XFreePixmap (X11->display, pixmap);
- }
-
- X11->solid_fills[i].color = color;
- X11->solid_fills[i].screen = screen;
- XRenderFillRectangle (X11->display, PictOpSrc, X11->solid_fills[i].picture, &color, 0, 0, 1, 1);
- return X11->solid_fills[i].picture;
-}
-
-XRenderColor QXcbX11Data::preMultiply(const QColor &c)
-{
- XRenderColor color;
- const uint A = c.alpha(),
- R = c.red(),
- G = c.green(),
- B = c.blue();
- color.alpha = (A | A << 8);
- color.red = (R | R << 8) * color.alpha / 0x10000;
- color.green = (G | G << 8) * color.alpha / 0x10000;
- color.blue = (B | B << 8) * color.alpha / 0x10000;
- return color;
-}
-#endif // QT_CONFIG(xrender)
-
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.h b/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.h
deleted file mode 100644
index dac9b101c43..00000000000
--- a/src/plugins/platforms/xcb/nativepainting/qxcbnativepainting.h
+++ /dev/null
@@ -1,64 +0,0 @@
-// Copyright (C) 2018 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
-// Qt-Security score:significant reason:default
-
-#pragma once
-
-#include <QSharedDataPointer>
-#include "qt_x11_p.h"
-
-typedef struct _FcPattern FcPattern;
-typedef unsigned long XID;
-typedef XID Colormap;
-typedef XID Window;
-typedef struct _XDisplay Display;
-
-QT_BEGIN_NAMESPACE
-
-class QXcbConnection;
-class QPixmap;
-
-void qt_xcb_native_x11_info_init(QXcbConnection *conn);
-QList<XRectangle> qt_region_to_xrectangles(const QRegion &r);
-
-class QXcbX11InfoData;
-class QXcbX11Info
-{
-public:
- QXcbX11Info();
- ~QXcbX11Info();
- QXcbX11Info(const QXcbX11Info &other);
- QXcbX11Info &operator=(const QXcbX11Info &other);
-
- static QXcbX11Info fromScreen(int screen);
- static Display *display();
-
- int depth() const;
- void setDepth(int depth);
-
- int screen() const;
- Colormap colormap() const;
-
- void *visual() const;
- void setVisual(void *visual);
-
- static int appScreen();
- static int appDepth(int screen = -1);
- static int appCells(int screen = -1);
- static Colormap appColormap(int screen = -1);
- static void *appVisual(int screen = -1);
- static Window appRootWindow(int screen = -1);
- static bool appDefaultColormap(int screen = -1);
- static bool appDefaultVisual(int screen = -1);
- static int appDpiX(int screen = -1);
- static int appDpiY(int screen = -1);
-
-private:
- QSharedDataPointer<QXcbX11InfoData> d;
-
- friend class QX11PaintEngine;
- friend class QX11PlatformPixmap;
- friend void qt_x11SetScreen(QPixmap &pixmap, int screen);
-};
-
-QT_END_NAMESPACE
diff --git a/src/plugins/platforms/xcb/qxcbimage.cpp b/src/plugins/platforms/xcb/qxcbimage.cpp
index 5b78c2c08ab..4c978152975 100644
--- a/src/plugins/platforms/xcb/qxcbimage.cpp
+++ b/src/plugins/platforms/xcb/qxcbimage.cpp
@@ -80,12 +80,6 @@ bool qt_xcb_imageFormatForVisual(QXcbConnection *connection, uint8_t depth, cons
*imageFormat = QImage::Format_Grayscale8;
return true;
}
-#if QT_CONFIG(xcb_native_painting)
- if (QXcbIntegration::instance() && QXcbIntegration::instance()->nativePaintingEnabled()) {
- *imageFormat = QImage::Format_Indexed8;
- return true;
- }
-#endif
return false;
}
diff --git a/src/plugins/platforms/xcb/qxcbintegration.cpp b/src/plugins/platforms/xcb/qxcbintegration.cpp
index c5c1fb1e638..d3a31dd35c7 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.cpp
+++ b/src/plugins/platforms/xcb/qxcbintegration.cpp
@@ -37,11 +37,6 @@
#include <X11/Xlib.h>
#undef register
#endif
-#if QT_CONFIG(xcb_native_painting)
-#include "qxcbnativepainting.h"
-#include "qpixmap_x11_p.h"
-#include "qbackingstore_x11_p.h"
-#endif
#include <qpa/qplatforminputcontextfactory_p.h>
#include <private/qgenericunixtheme_p.h>
@@ -180,13 +175,6 @@ QXcbIntegration::QXcbIntegration(const QStringList &parameters, int &argc, char
m_services->setConnection(m_connection);
m_fontDatabase.reset(new QGenericUnixFontDatabase());
-
-#if QT_CONFIG(xcb_native_painting)
- if (nativePaintingEnabled()) {
- qCDebug(lcQpaXcb, "QXCB USING NATIVE PAINTING");
- qt_xcb_native_x11_info_init(connection());
- }
-#endif
}
QXcbIntegration::~QXcbIntegration()
@@ -198,11 +186,6 @@ QXcbIntegration::~QXcbIntegration()
QPlatformPixmap *QXcbIntegration::createPlatformPixmap(QPlatformPixmap::PixelType type) const
{
-#if QT_CONFIG(xcb_native_painting)
- if (nativePaintingEnabled())
- return new QX11PlatformPixmap(type);
-#endif
-
return QPlatformIntegration::createPlatformPixmap(type);
}
@@ -281,10 +264,6 @@ QPlatformBackingStore *QXcbIntegration::createPlatformBackingStore(QWindow *wind
const bool isTrayIconWindow = QXcbWindow::isTrayIconWindow(window);
if (isTrayIconWindow) {
backingStore = new QXcbSystemTrayBackingStore(window);
-#if QT_CONFIG(xcb_native_painting)
- } else if (nativePaintingEnabled()) {
- backingStore = new QXcbNativeBackingStore(window);
-#endif
} else {
backingStore = new QXcbBackingStore(window);
}
@@ -576,16 +555,6 @@ void QXcbIntegration::beep() const
xcb_flush(connection);
}
-bool QXcbIntegration::nativePaintingEnabled() const
-{
-#if QT_CONFIG(xcb_native_painting)
- static bool enabled = qEnvironmentVariableIsSet("QT_XCB_NATIVE_PAINTING");
- return enabled;
-#else
- return false;
-#endif
-}
-
#if QT_CONFIG(vulkan)
QPlatformVulkanInstance *QXcbIntegration::createPlatformVulkanInstance(QVulkanInstance *instance) const
{
diff --git a/src/plugins/platforms/xcb/qxcbintegration.h b/src/plugins/platforms/xcb/qxcbintegration.h
index 10cc67af55f..041908e4552 100644
--- a/src/plugins/platforms/xcb/qxcbintegration.h
+++ b/src/plugins/platforms/xcb/qxcbintegration.h
@@ -94,8 +94,6 @@ public:
void beep() const override;
- bool nativePaintingEnabled() const;
-
#if QT_CONFIG(vulkan)
QPlatformVulkanInstance *createPlatformVulkanInstance(QVulkanInstance *instance) const override;
#endif
diff --git a/src/plugins/styles/modernwindows/qwindows11style.cpp b/src/plugins/styles/modernwindows/qwindows11style.cpp
index 2944c02fd79..c8cd7c26f61 100644
--- a/src/plugins/styles/modernwindows/qwindows11style.cpp
+++ b/src/plugins/styles/modernwindows/qwindows11style.cpp
@@ -109,6 +109,7 @@ inline ControlState calcControlState(const QStyleOption *option)
#define More u"\uE712"_s
#define Help u"\uE897"_s
+#define Clear u"\uE894"_s
template <typename R, typename P, typename B>
static inline void drawRoundedRect(QPainter *p, R &&rect, P &&pen, B &&brush)
@@ -1720,9 +1721,10 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
}
case CE_ItemViewItem: {
if (const QStyleOptionViewItem *vopt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
- QRect checkRect = proxy()->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
- QRect iconRect = proxy()->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
- QRect textRect = proxy()->subElementRect(SE_ItemViewItemText, vopt, widget);
+ const auto p = proxy();
+ QRect checkRect = p->subElementRect(SE_ItemViewItemCheckIndicator, vopt, widget);
+ QRect iconRect = p->subElementRect(SE_ItemViewItemDecoration, vopt, widget);
+ QRect textRect = p->subElementRect(SE_ItemViewItemText, vopt, widget);
// draw the background
proxy()->drawPrimitive(PE_PanelItemViewItem, option, painter, widget);
@@ -1823,16 +1825,17 @@ void QWindows11Style::drawControl(ControlElement element, const QStyleOption *op
d->viewItemDrawText(painter, vopt, textRect);
// paint a vertical marker for QListView
- if (vopt->state & State_Selected) {
+ if (vopt->state & State_Selected && !highContrastTheme) {
if (const QListView *lv = qobject_cast<const QListView *>(widget);
- lv && lv->viewMode() != QListView::IconMode && !highContrastTheme) {
- painter->setPen(vopt->palette.accent().color());
- const auto xPos = isRtl ? rect.right() - 1 : rect.left();
- const QLineF lines[2] = {
- QLineF(xPos, rect.y() + 2, xPos, rect.y() + rect.height() - 2),
- QLineF(xPos + 1, rect.y() + 2, xPos + 1, rect.y() + rect.height() - 2),
- };
- painter->drawLines(lines, 2);
+ lv && lv->viewMode() != QListView::IconMode) {
+ const auto col = vopt->palette.accent().color();
+ painter->setBrush(col);
+ painter->setPen(col);
+ const auto xPos = isRtl ? rect.right() - 4.5f : rect.left() + 3.5f;
+ const auto yOfs = rect.height() / 4.;
+ QRectF r(QPointF(xPos, rect.y() + yOfs),
+ QPointF(xPos + 1, rect.y() + rect.height() - yOfs));
+ painter->drawRoundedRect(r, 1, 1);
}
}
}
@@ -1872,7 +1875,7 @@ QRect QWindows11Style::subElementRect(QStyle::SubElement element, const QStyleOp
case QStyle::SE_RadioButtonIndicator:
case QStyle::SE_CheckBoxIndicator:
ret = QWindowsVistaStyle::subElementRect(element, option, widget);
- ret.moveLeft(contentItemHMargin);
+ ret.moveLeft(ret.left() + contentItemHMargin);
break;
case QStyle::SE_ComboBoxFocusRect:
case QStyle::SE_CheckBoxFocusRect:
@@ -1883,22 +1886,29 @@ QRect QWindows11Style::subElementRect(QStyle::SubElement element, const QStyleOp
case QStyle::SE_LineEditContents:
ret = option->rect.adjusted(4,0,-4,0);
break;
- case QStyle::SE_ItemViewItemText:
- if (const auto *item = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
- const int decorationOffset = item->features.testFlag(QStyleOptionViewItem::HasDecoration) ? item->decorationSize.width() : 0;
- const int checkboxOffset = item->features.testFlag(QStyleOptionViewItem::HasCheckIndicator) ? 16 : 0;
- if (widget && qobject_cast<QComboBoxPrivateContainer *>(widget->parentWidget())) {
- if (option->direction == Qt::LeftToRight)
- ret = option->rect.adjusted(decorationOffset + checkboxOffset + 5, 0, -5, 0);
- else
- ret = option->rect.adjusted(5, 0, decorationOffset - checkboxOffset - 5, 0);
+ case SE_ItemViewItemCheckIndicator:
+ case SE_ItemViewItemDecoration:
+ case SE_ItemViewItemText: {
+ ret = QWindowsVistaStyle::subElementRect(element, option, widget);
+ if (!ret.isValid() || highContrastTheme)
+ return ret;
+
+ if (const QListView *lv = qobject_cast<const QListView *>(widget);
+ lv && lv->viewMode() != QListView::IconMode) {
+ const int xOfs = contentHMargin;
+ const bool isRtl = option->direction == Qt::RightToLeft;
+ if (isRtl) {
+ ret.moveRight(ret.right() - xOfs);
+ if (ret.left() < option->rect.left())
+ ret.setLeft(option->rect.left());
} else {
- ret = QWindowsVistaStyle::subElementRect(element, option, widget);
+ ret.moveLeft(ret.left() + xOfs);
+ if (ret.right() > option->rect.right())
+ ret.setRight(option->rect.right());
}
- } else {
- ret = QWindowsVistaStyle::subElementRect(element, option, widget);
}
break;
+ }
#if QT_CONFIG(progressbar)
case SE_ProgressBarGroove:
case SE_ProgressBarContents:
@@ -2091,6 +2101,19 @@ QRect QWindows11Style::subControlRect(ComplexControl control, const QStyleOption
}
break;
}
+#if QT_CONFIG(groupbox)
+ case CC_GroupBox: {
+ ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
+ switch (subControl) {
+ case SC_GroupBoxCheckBox:
+ ret.moveTop(1);
+ break;
+ default:
+ break;
+ }
+ break;
+ }
+#endif // QT_CONFIG(groupbox)
default:
ret = QWindowsVistaStyle::subControlRect(control, option, subControl, widget);
}
@@ -2234,6 +2257,25 @@ QSize QWindows11Style::sizeFromContents(ContentsType type, const QStyleOption *o
contentSize.rwidth() += 2 * contentHMargin - oldMargin;
break;
}
+ case CT_ItemViewItem: {
+ if (const auto *viewItemOpt = qstyleoption_cast<const QStyleOptionViewItem *>(option)) {
+ if (const QListView *lv = qobject_cast<const QListView *>(widget);
+ lv && lv->viewMode() != QListView::IconMode) {
+ QStyleOptionViewItem vOpt(*viewItemOpt);
+ // viewItemSize only takes PM_FocusFrameHMargin into account but no additional
+ // margin, therefore adjust it here for a correct width during layouting when
+ // WrapText is enabled
+ vOpt.rect.setRight(vOpt.rect.right() - contentHMargin);
+ contentSize = QWindowsVistaStyle::sizeFromContents(type, &vOpt, size, widget);
+ contentSize.rwidth() += contentHMargin;
+ contentSize.rheight() += 2 * contentHMargin;
+
+ } else {
+ contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
+ }
+ }
+ break;
+ }
default:
contentSize = QWindowsVistaStyle::sizeFromContents(type, option, size, widget);
break;
@@ -2544,6 +2586,7 @@ void QWindows11Style::polish(QPalette& result)
d->m_titleBarCloseIcon = QIcon();
d->m_titleBarNormalIcon = QIcon();
d->m_toolbarExtensionButton = QIcon();
+ d->m_lineEditClearButton = QIcon();
}
QPixmap QWindows11Style::standardPixmap(StandardPixmap standardPixmap,
@@ -2568,10 +2611,17 @@ QIcon QWindows11Style::standardIcon(StandardPixmap standardIcon,
{
auto *d = const_cast<QWindows11StylePrivate*>(d_func());
switch (standardIcon) {
+ case SP_LineEditClearButton: {
+ if (d->m_lineEditClearButton.isNull()) {
+ auto e = new WinFontIconEngine(Clear.at(0), d->assetFont);
+ d->m_lineEditClearButton = QIcon(e);
+ }
+ return d->m_lineEditClearButton;
+ }
case SP_ToolBarHorizontalExtensionButton:
case SP_ToolBarVerticalExtensionButton: {
if (d->m_toolbarExtensionButton.isNull()) {
- auto e = new WinFontIconEngine(More.at(0), d->assetFont);
+ auto e = new WinFontIconEngine(More, d->assetFont);
e->setScale(1.0);
d->m_toolbarExtensionButton = QIcon(e);
}
diff --git a/src/plugins/styles/modernwindows/qwindows11style_p.h b/src/plugins/styles/modernwindows/qwindows11style_p.h
index 736caae956c..a51a93ddd9b 100644
--- a/src/plugins/styles/modernwindows/qwindows11style_p.h
+++ b/src/plugins/styles/modernwindows/qwindows11style_p.h
@@ -123,6 +123,7 @@ class QWindows11StylePrivate : public QWindowsVistaStylePrivate {
protected:
QIcon m_toolbarExtensionButton;
+ QIcon m_lineEditClearButton;
};
QT_END_NAMESPACE
diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
index 22ca18b10bf..fa0d0260f3c 100644
--- a/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle.cpp
@@ -4959,8 +4959,7 @@ QIcon QWindowsVistaStyle::standardIcon(StandardPixmap standardIcon,
return QWindowsStyle::standardIcon(standardIcon, option, widget);
}
-
-WinFontIconEngine::WinFontIconEngine(const QChar &glyph, const QFont &font)
+WinFontIconEngine::WinFontIconEngine(const QString &glyph, const QFont &font)
: QFontIconEngine({}, font)
, m_font(font)
, m_glyph(glyph)
diff --git a/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h b/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h
index cf982ceb133..23b34547faa 100644
--- a/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h
+++ b/src/plugins/styles/modernwindows/qwindowsvistastyle_p_p.h
@@ -184,7 +184,7 @@ private:
class WinFontIconEngine : public QFontIconEngine
{
public:
- WinFontIconEngine(const QChar &glyph, const QFont &font);
+ WinFontIconEngine(const QString &glyph, const QFont &font);
QString key() const override;
QIconEngine *clone() const override;
@@ -194,7 +194,7 @@ public:
protected:
QFont m_font;
- QChar m_glyph;
+ QString m_glyph;
double m_scale = 0.7;
};
diff --git a/src/testlib/qtestcase.cpp b/src/testlib/qtestcase.cpp
index 784e69d2486..a98f5da2389 100644
--- a/src/testlib/qtestcase.cpp
+++ b/src/testlib/qtestcase.cpp
@@ -410,7 +410,7 @@ public:
static QMetaMethod findMethod(const QObject *obj, const char *signature);
private:
- bool invokeTest(int index, QLatin1StringView tag, std::optional<WatchDog> &watchDog) const;
+ void invokeTest(int index, QLatin1StringView tag, std::optional<WatchDog> &watchDog) const;
void invokeTestOnData(int index) const;
QMetaMethod m_initTestCaseMethod; // might not exist, check isValid().
@@ -1315,11 +1315,8 @@ static void printUnknownDataTagError(QLatin1StringView name, QLatin1StringView t
Call slot_data(), init(), slot(), cleanup(), init(), slot(), cleanup(), ...
If data is set then it is the only test that is performed
-
- If the function was successfully called, true is returned, otherwise
- false.
*/
-bool TestMethods::invokeTest(int index, QLatin1StringView tag, std::optional<WatchDog> &watchDog) const
+void TestMethods::invokeTest(int index, QLatin1StringView tag, std::optional<WatchDog> &watchDog) const
{
QBenchmarkTestMethodData benchmarkData;
QBenchmarkTestMethodData::current = &benchmarkData;
@@ -1422,8 +1419,6 @@ bool TestMethods::invokeTest(int index, QLatin1StringView tag, std::optional<Wat
QTestResult::finishedCurrentTestFunction();
QTestResult::setSkipCurrentTest(false);
QTestResult::setBlacklistCurrentTest(false);
-
- return true;
}
void *fetchData(QTestData *data, const char *tagName, int typeId)
@@ -1743,10 +1738,8 @@ void TestMethods::invokeTests(QObject *testObject) const
const char *data = nullptr;
if (i < QTest::testTags.size() && !QTest::testTags.at(i).isEmpty())
data = qstrdup(QTest::testTags.at(i).toLatin1().constData());
- const bool ok = invokeTest(i, QLatin1StringView(data), watchDog);
+ invokeTest(i, QLatin1StringView(data), watchDog);
delete [] data;
- if (!ok)
- break;
}
}
diff --git a/src/widgets/accessible/itemviews.cpp b/src/widgets/accessible/itemviews.cpp
index fc969e17380..265c523eae0 100644
--- a/src/widgets/accessible/itemviews.cpp
+++ b/src/widgets/accessible/itemviews.cpp
@@ -60,7 +60,7 @@ int QAccessibleTable::logicalIndex(const QModelIndex &index) const
}
QAccessibleTable::QAccessibleTable(QWidget *w)
- : QAccessibleObject(w)
+ : QAccessibleWidgetV2(w)
{
Q_ASSERT(view());
@@ -677,7 +677,7 @@ void *QAccessibleTable::interface_cast(QAccessible::InterfaceType t)
return static_cast<QAccessibleSelectionInterface*>(this);
if (t == QAccessible::TableInterface)
return static_cast<QAccessibleTableInterface*>(this);
- return nullptr;
+ return QAccessibleWidgetV2::interface_cast(t);
}
void QAccessibleTable::modelChange(QAccessibleTableModelChangeEvent *event)
diff --git a/src/widgets/accessible/itemviews_p.h b/src/widgets/accessible/itemviews_p.h
index 9b30f36ced3..79f9a7f2f05 100644
--- a/src/widgets/accessible/itemviews_p.h
+++ b/src/widgets/accessible/itemviews_p.h
@@ -31,7 +31,9 @@ QT_BEGIN_NAMESPACE
class QAccessibleTableCell;
class QAccessibleTableHeaderCell;
-class QAccessibleTable :public QAccessibleTableInterface, public QAccessibleSelectionInterface, public QAccessibleObject
+class QAccessibleTable : public QAccessibleTableInterface,
+ public QAccessibleSelectionInterface,
+ public QAccessibleWidgetV2
{
public:
explicit QAccessibleTable(QWidget *w);
diff --git a/src/widgets/accessible/rangecontrols.cpp b/src/widgets/accessible/rangecontrols.cpp
index c0de5357c9a..1f7b20833dd 100644
--- a/src/widgets/accessible/rangecontrols.cpp
+++ b/src/widgets/accessible/rangecontrols.cpp
@@ -65,6 +65,16 @@ QAccessibleInterface *QAccessibleAbstractSpinBox::lineEditIface() const
#endif
}
+QAccessible::State QAccessibleAbstractSpinBox::state() const
+{
+ QAccessible::State state = QAccessibleWidgetV2::state();
+ if (abstractSpinBox()->isReadOnly())
+ state.readOnly = true;
+ else
+ state.editable = true;
+ return state;
+}
+
QString QAccessibleAbstractSpinBox::text(QAccessible::Text t) const
{
if (t == QAccessible::Value)
diff --git a/src/widgets/accessible/rangecontrols_p.h b/src/widgets/accessible/rangecontrols_p.h
index dd5a6a4531c..5a023d2f00b 100644
--- a/src/widgets/accessible/rangecontrols_p.h
+++ b/src/widgets/accessible/rangecontrols_p.h
@@ -42,6 +42,7 @@ public:
explicit QAccessibleAbstractSpinBox(QWidget *w);
virtual ~QAccessibleAbstractSpinBox();
+ QAccessible::State state() const override;
QString text(QAccessible::Text t) const override;
void *interface_cast(QAccessible::InterfaceType t) override;
diff --git a/src/widgets/dialogs/qcolordialog.cpp b/src/widgets/dialogs/qcolordialog.cpp
index 25d742039c5..f8125204045 100644
--- a/src/widgets/dialogs/qcolordialog.cpp
+++ b/src/widgets/dialogs/qcolordialog.cpp
@@ -585,18 +585,21 @@ signals:
protected:
QSize sizeHint() const override;
void paintEvent(QPaintEvent*) override;
+ void keyPressEvent(QKeyEvent *event) override;
void mouseMoveEvent(QMouseEvent *) override;
void mousePressEvent(QMouseEvent *) override;
void resizeEvent(QResizeEvent *) override;
private:
- int hue;
- int sat;
+ QPoint m_pos;
- QPoint colPt();
- int huePt(const QPoint &pt);
- int satPt(const QPoint &pt);
- void setCol(const QPoint &pt);
+ QPixmap createColorsPixmap();
+ QPoint colPt(int hue, int sat);
+ int huePt(const QPoint &pt, const QSize &widgetSize);
+ int huePt(const QPoint &pt) { return huePt(pt, size()); }
+ int satPt(const QPoint &pt, const QSize &widgetSize);
+ int satPt(const QPoint &pt) { return satPt(pt, size()); }
+ void setCol(const QPoint &pt, bool notify = true);
QPixmap pix;
bool crossVisible;
@@ -625,6 +628,7 @@ signals:
protected:
void paintEvent(QPaintEvent*) override;
+ void keyPressEvent(QKeyEvent *event) override;
void mouseMoveEvent(QMouseEvent *) override;
void mousePressEvent(QMouseEvent *) override;
@@ -660,6 +664,7 @@ QColorLuminancePicker::QColorLuminancePicker(QWidget* parent)
hue = 100; val = 100; sat = 100;
pix = nullptr;
// setAttribute(WA_NoErase, true);
+ setFocusPolicy(Qt::StrongFocus);
}
QColorLuminancePicker::~QColorLuminancePicker()
@@ -667,6 +672,21 @@ QColorLuminancePicker::~QColorLuminancePicker()
delete pix;
}
+void QColorLuminancePicker::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Down:
+ setVal(std::clamp(val - 1, 0, 255));
+ break;
+ case Qt::Key_Up:
+ setVal(std::clamp(val + 1, 0, 255));
+ break;
+ default:
+ QWidget::keyPressEvent(event);
+ break;
+ }
+}
+
void QColorLuminancePicker::mouseMoveEvent(QMouseEvent *m)
{
if (m->buttons() == Qt::NoButton) {
@@ -737,38 +757,53 @@ void QColorLuminancePicker::setCol(int h, int s , int v)
repaint();
}
-QPoint QColorPicker::colPt()
+QPoint QColorPicker::colPt(int hue, int sat)
{
QRect r = contentsRect();
return QPoint((360 - hue) * (r.width() - 1) / 360, (255 - sat) * (r.height() - 1) / 255);
}
-int QColorPicker::huePt(const QPoint &pt)
+int QColorPicker::huePt(const QPoint &pt, const QSize &widgetSize)
{
- QRect r = contentsRect();
- return 360 - pt.x() * 360 / (r.width() - 1);
+ QRect r = QRect(QPoint(0, 0), widgetSize) - contentsMargins();
+ return std::clamp(360 - pt.x() * 360 / (r.width() - 1), 0, 359);
}
-int QColorPicker::satPt(const QPoint &pt)
+int QColorPicker::satPt(const QPoint &pt, const QSize &widgetSize)
{
- QRect r = contentsRect();
- return 255 - pt.y() * 255 / (r.height() - 1);
+ QRect r = QRect(QPoint(0, 0), widgetSize) - contentsMargins();
+ return std::clamp(255 - pt.y() * 255 / (r.height() - 1), 0, 255);
}
-void QColorPicker::setCol(const QPoint &pt)
+void QColorPicker::setCol(const QPoint &pt, bool notify)
{
- setCol(huePt(pt), satPt(pt));
+ if (pt == m_pos)
+ return;
+
+ QRect r(m_pos, QSize(20, 20));
+ m_pos.setX(std::clamp(pt.x(), 0, pix.width() - 1));
+ m_pos.setY(std::clamp(pt.y(), 0, pix.height() - 1));
+ r = r.united(QRect(m_pos, QSize(20, 20)));
+ r.translate(contentsRect().x() - 9, contentsRect().y() - 9);
+ // update(r);
+ repaint(r);
+
+ if (notify)
+ emit newCol(huePt(m_pos), satPt(m_pos));
}
QColorPicker::QColorPicker(QWidget* parent)
: QFrame(parent)
, crossVisible(true)
{
- hue = 0; sat = 0;
- setCol(150, 255);
-
setAttribute(Qt::WA_NoSystemBackground);
+ setFocusPolicy(Qt::StrongFocus);
setSizePolicy(QSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed) );
+ adjustSize();
+
+ pix = createColorsPixmap();
+
+ setCol(150, 255);
}
QColorPicker::~QColorPicker()
@@ -792,15 +827,31 @@ void QColorPicker::setCol(int h, int s)
{
int nhue = qMin(qMax(0,h), 359);
int nsat = qMin(qMax(0,s), 255);
- if (nhue == hue && nsat == sat)
+ if (nhue == huePt(m_pos) && nsat == satPt(m_pos))
return;
- QRect r(colPt(), QSize(20,20));
- hue = nhue; sat = nsat;
- r = r.united(QRect(colPt(), QSize(20,20)));
- r.translate(contentsRect().x()-9, contentsRect().y()-9);
- // update(r);
- repaint(r);
+ setCol(colPt(nhue, nsat), false);
+}
+
+void QColorPicker::keyPressEvent(QKeyEvent *event)
+{
+ switch (event->key()) {
+ case Qt::Key_Down:
+ setCol(m_pos + QPoint(0, 1));
+ break;
+ case Qt::Key_Left:
+ setCol(m_pos + QPoint(-1, 0));
+ break;
+ case Qt::Key_Right:
+ setCol(m_pos + QPoint(1, 0));
+ break;
+ case Qt::Key_Up:
+ setCol(m_pos + QPoint(0, -1));
+ break;
+ default:
+ QFrame::keyPressEvent(event);
+ break;
+ }
}
void QColorPicker::mouseMoveEvent(QMouseEvent *m)
@@ -811,14 +862,12 @@ void QColorPicker::mouseMoveEvent(QMouseEvent *m)
return;
}
setCol(p);
- emit newCol(hue, sat);
}
void QColorPicker::mousePressEvent(QMouseEvent *m)
{
QPoint p = m->position().toPoint() - contentsRect().topLeft();
setCol(p);
- emit newCol(hue, sat);
}
void QColorPicker::paintEvent(QPaintEvent* )
@@ -830,7 +879,7 @@ void QColorPicker::paintEvent(QPaintEvent* )
p.drawPixmap(r.topLeft(), pix);
if (crossVisible) {
- QPoint pt = colPt() + r.topLeft();
+ QPoint pt = m_pos + r.topLeft();
p.setPen(Qt::black);
p.fillRect(pt.x()-9, pt.y(), 20, 2, Qt::black);
p.fillRect(pt.x(), pt.y()-9, 2, 20, Qt::black);
@@ -841,6 +890,21 @@ void QColorPicker::resizeEvent(QResizeEvent *ev)
{
QFrame::resizeEvent(ev);
+ pix = createColorsPixmap();
+
+ const QSize &oldSize = ev->oldSize();
+ if (!oldSize.isValid())
+ return;
+
+ // calculate hue/saturation based on previous widget size
+ // and update position accordingly
+ const int hue = huePt(m_pos, oldSize);
+ const int sat = satPt(m_pos, oldSize);
+ setCol(hue, sat);
+}
+
+QPixmap QColorPicker::createColorsPixmap()
+{
int w = width() - frameWidth() * 2;
int h = height() - frameWidth() * 2;
QImage img(w, h, QImage::Format_RGB32);
@@ -858,10 +922,9 @@ void QColorPicker::resizeEvent(QResizeEvent *ev)
++x;
}
}
- pix = QPixmap::fromImage(img);
+ return QPixmap::fromImage(img);
}
-
class QColSpinBox : public QSpinBox
{
public:
diff --git a/src/widgets/dialogs/qfontdialog.cpp b/src/widgets/dialogs/qfontdialog.cpp
index 870b0c40faf..c4f8af1a639 100644
--- a/src/widgets/dialogs/qfontdialog.cpp
+++ b/src/widgets/dialogs/qfontdialog.cpp
@@ -172,7 +172,7 @@ void QFontDialogPrivate::init()
sizeAccel = new QLabel(q);
#ifndef QT_NO_SHORTCUT
- sizeAccel->setBuddy(sizeEdit);
+ sizeAccel->setBuddy(sizeList);
#endif
sizeAccel->setIndent(2);
diff --git a/src/widgets/kernel/qlayout.cpp b/src/widgets/kernel/qlayout.cpp
index 00f9766af29..5ba92714f6c 100644
--- a/src/widgets/kernel/qlayout.cpp
+++ b/src/widgets/kernel/qlayout.cpp
@@ -345,6 +345,17 @@ void QLayout::getContentsMargins(int *left, int *top, int *right, int *bottom) c
}
/*!
+ \property QLayout::contentsMargins
+ \since 4.6
+ \brief the margins used around the layout
+
+ By default, QLayout uses the values provided by the style. On
+ most platforms, the margin is 11 pixels in all directions.
+
+ \sa setContentsMargins(), getContentsMargins()
+*/
+
+/*!
\since 4.6
Returns the margins used around the layout.