diff --git a/ui/effects/gradient.h b/ui/effects/gradient.h index 6b2f5d2..abb181c 100644 --- a/ui/effects/gradient.h +++ b/ui/effects/gradient.h @@ -14,14 +14,47 @@ namespace anim { +struct gradient_colors { + explicit gradient_colors(QColor color) { + stops.push_back({ 0., color }); + stops.push_back({ 1., color }); + } + explicit gradient_colors(std::vector colors) { + if (colors.size() == 1) { + gradient_colors(colors.front()); + return; + } + const auto last = float(colors.size() - 1); + for (auto i = 0; i < colors.size(); i++) { + stops.push_back({ i / last, std::move(colors[i]) }); + } + } + explicit gradient_colors(QGradientStops colors) + : stops(std::move(colors)) { + } + + QGradientStops stops; +}; + namespace details { template class gradients { public: - gradients(base::flat_map> colors) - : _colors(colors) { - Expects(_colors.size() > 0); + gradients(base::flat_map> colors) { + Expects(colors.size() > 0); + + for (const auto &[key, value] : colors) { + auto c = gradient_colors(std::move(value)); + _gradients.emplace(key, gradient_with_stops(std::move(c.stops))); + } + } + gradients(base::flat_map colors) { + Expects(colors.size() > 0); + + for (const auto &[key, c] : colors) { + _gradients.emplace(key, gradient_with_stops(std::move(c.stops))); + } } QGradient gradient(T state1, T state2, float64 b_ratio) const { @@ -31,16 +64,20 @@ public: return _gradients.find(state2)->second; } - auto gradient = static_cast(this)->empty_gradient(); - const auto size = _colors.front().second.size(); - const auto colors1 = _colors.find(state1); - const auto colors2 = _colors.find(state2); + auto gradient = empty_gradient(); + const auto gradient1 = _gradients.find(state1); + const auto gradient2 = _gradients.find(state2); - Assert(colors1 != end(_colors)); - Assert(colors2 != end(_colors)); + Assert(gradient1 != end(_gradients)); + Assert(gradient2 != end(_gradients)); + + const auto stops1 = gradient1->second.stops(); + const auto stops2 = gradient2->second.stops(); + + const auto size = stops1.size(); for (auto i = 0; i < size; i++) { - auto c = color(colors1->second[i], colors2->second[i], b_ratio); + auto c = color(stops1[i].second, stops2[i].second, b_ratio); gradient.setColorAt(i / (size - 1), std::move(c)); } return gradient; @@ -48,23 +85,22 @@ public: protected: void cache_gradients() { - _gradients = base::flat_map(); - for (const auto &[key, value] : _colors) { - _gradients.emplace(key, gradient(value)); + auto copy = std::move(_gradients); + for (const auto &[key, value] : copy) { + _gradients.emplace(key, gradient_with_stops(value.stops())); } } private: - QGradient gradient(const std::vector &colors) const { - auto gradient = static_cast(this)->empty_gradient(); - const auto size = colors.size(); - for (auto i = 0; i < size; i++) { - gradient.setColorAt(i / (size - 1), colors[i]); - } + QGradient empty_gradient() const { + return static_cast(this)->empty_gradient(); + } + QGradient gradient_with_stops(QGradientStops stops) const { + auto gradient = empty_gradient(); + gradient.setStops(std::move(stops)); return gradient; } - base::flat_map> _colors; base::flat_map _gradients; }; @@ -84,6 +120,13 @@ public: : parent(std::move(colors)) { set_points(point1, point2); } + linear_gradients( + base::flat_map colors, + QPointF point1, + QPointF point2) + : parent(std::move(colors)) { + set_points(point1, point2); + } void set_points(QPointF point1, QPointF point2) { if (_point1 == point1 && _point2 == point2) { @@ -119,6 +162,13 @@ public: : parent(std::move(colors)) { set_points(center, radius); } + radial_gradients( + base::flat_map colors, + QPointF center, + float radius) + : parent(std::move(colors)) { + set_points(center, radius); + } void set_points(QPointF center, float radius) { if (_center == center && _radius == radius) {