summaryrefslogtreecommitdiffstats
path: root/src/gui/painting/qbrush.cpp
diff options
context:
space:
mode:
authorMarc Mutz <marc.mutz@kdab.com>2017-01-10 15:48:14 +0100
committerMarc Mutz <marc.mutz@kdab.com>2017-01-14 06:27:52 +0000
commit3b0cd132225504f36bc355f239cde95a9bac0985 (patch)
tree5c492c0f9435912594b46367ae2c37553912d13a /src/gui/painting/qbrush.cpp
parent01cade50509de392f06e6f5ee939421a576e06c1 (diff)
QGradient: add a setStops fast-path for conformant QGradientStops
The setStops() docs state that the stops need to be sorted and the positions must be valid. But the implementation sorts the stops and filters out invalid ones, so we probably need to keep that behavior, which, however, causes memory allocations and, potentially, O(N²) behavior, because setColorAt() uses a form of Insertion Sort with linear scanning... Add a fast-path for the common case that users adhere to the docs and pass valid stops. Change-Id: I93099a57bc4f37d1240a9e9f763618fd5095bc64 Reviewed-by: Olivier Goffart (Woboq GmbH) <ogoffart@woboq.com>
Diffstat (limited to 'src/gui/painting/qbrush.cpp')
-rw-r--r--src/gui/painting/qbrush.cpp27
1 files changed, 27 insertions, 0 deletions
diff --git a/src/gui/painting/qbrush.cpp b/src/gui/painting/qbrush.cpp
index ebb035a2c1..06a820a859 100644
--- a/src/gui/painting/qbrush.cpp
+++ b/src/gui/painting/qbrush.cpp
@@ -1419,6 +1419,25 @@ void QGradient::setColorAt(qreal pos, const QColor &color)
m_stops.insert(index, QGradientStop(pos, color));
}
+static inline bool ok(QGradientStop stop)
+{
+ return stop.first >= 0 && stop.first <= 1; // rejects NaNs
+}
+
+static inline bool ok(const QGradientStops &stops)
+{
+ qreal lastPos = -1;
+ for (const QGradientStop &stop : stops) {
+ if (Q_UNLIKELY(!ok(stop)))
+ return false;
+ const bool sorted = stop.first > lastPos; // rejects duplicates
+ if (Q_UNLIKELY(!sorted))
+ return false;
+ lastPos = stop.first;
+ }
+ return true;
+}
+
/*!
\fn void QGradient::setStops(const QGradientStops &stopPoints)
@@ -1430,6 +1449,14 @@ void QGradient::setColorAt(qreal pos, const QColor &color)
*/
void QGradient::setStops(const QGradientStops &stops)
{
+ // ## Qt 6: consider taking \a stops by value, so we can move into m_stops
+ if (Q_LIKELY(ok(stops))) {
+ // fast path for the common case: if everything is ok with the stops, just copy them
+ m_stops = stops;
+ return;
+ }
+ // otherwise, to keep the pre-5.9 behavior, add them one after another,
+ // so each stop is checked, invalid ones are skipped, they are added in-order (which may be O(N^2)).
m_stops.clear();
for (int i=0; i<stops.size(); ++i)
setColorAt(stops.at(i).first, stops.at(i).second);