diff options
author | Marc Mutz <marc.mutz@kdab.com> | 2017-01-10 15:48:14 +0100 |
---|---|---|
committer | Marc Mutz <marc.mutz@kdab.com> | 2017-01-14 06:27:52 +0000 |
commit | 3b0cd132225504f36bc355f239cde95a9bac0985 (patch) | |
tree | 5c492c0f9435912594b46367ae2c37553912d13a /src/gui | |
parent | 01cade50509de392f06e6f5ee939421a576e06c1 (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')
-rw-r--r-- | src/gui/painting/qbrush.cpp | 27 |
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); |