diff --git a/ui/effects/gradient.h b/ui/effects/gradient.h index 377ef2d..8bcbb4f 100644 --- a/ui/effects/gradient.h +++ b/ui/effects/gradient.h @@ -14,78 +14,24 @@ namespace anim { -class linear_gradient { -public: - linear_gradient( - std::vector colors_from, - std::vector colors_to, - QPointF point1, - QPointF point2) - : _colors_from(colors_from) - , _colors_to(colors_to) - , _point1(point1) - , _point2(point2) - , _gradient_from(gradient(colors_from)) - , _gradient_to(gradient(colors_to)) { - Expects(colors_from.size() == colors_to.size()); - } - - QLinearGradient gradient(float64 b_ratio) const { - if (b_ratio == 0.) { - return _gradient_from; - } else if (b_ratio == 1.) { - return _gradient_to; - } - auto colors = std::vector(_colors_to.size()); - for (auto i = 0; i < colors.size(); i++) { - colors[i] = color(_colors_from[i], _colors_to[i], b_ratio); - } - return gradient(colors); - } - -private: - QLinearGradient gradient(const std::vector &colors) const { - auto gradient = QLinearGradient(_point1, _point2); - const auto size = colors.size(); - for (auto i = 0; i < size; i++) { - gradient.setColorAt(i / (size - 1), colors[i]); - } - return gradient; - } - - std::vector _colors_from; - std::vector _colors_to; - QPointF _point1; - QPointF _point2; - - QLinearGradient _gradient_from; - QLinearGradient _gradient_to; - -}; +namespace details { template -class linear_gradients { +class gradients { public: - linear_gradients( - base::flat_map> colors, - QPointF point1, - QPointF point2) - : _colors(colors) - , _point1(point1) - , _point2(point2) { + gradients(base::flat_map> colors) + : _colors(colors) { Expects(_colors.size() > 0); - - cache_gradients(); } - QLinearGradient gradient(T state1, T state2, float64 b_ratio) const { + QGradient gradient(T state1, T state2, float64 b_ratio) const { if (b_ratio == 0.) { return _gradients.find(state1)->second; } else if (b_ratio == 1.) { return _gradients.find(state2)->second; } - auto gradient = QLinearGradient(_point1, _point2); + auto gradient = empty_gradient(); const auto size = _colors.front().second.size(); const auto colors1 = _colors.find(state1); const auto colors2 = _colors.find(state2); @@ -100,124 +46,70 @@ public: return gradient; } +protected: + virtual QGradient empty_gradient() const = 0; + + void cache_gradients() { + _gradients = base::flat_map(); + for (const auto &[key, value] : _colors) { + _gradients.emplace(key, gradient(value)); + } + } + + QGradient gradient(const std::vector &colors) const { + auto gradient = empty_gradient(); + const auto size = colors.size(); + for (auto i = 0; i < size; i++) { + gradient.setColorAt(i / (size - 1), colors[i]); + } + return gradient; + } + + base::flat_map> _colors; + base::flat_map _gradients; + +}; + +} // namespace details + +template +class linear_gradients final : public details::gradients { +public: + linear_gradients( + base::flat_map> colors, + QPointF point1, + QPointF point2) + : details::gradients(std::move(colors)) { + set_points(point1, point2); + } + void set_points(QPointF point1, QPointF point2) { if (_point1 == point1 && _point2 == point2) { return; } _point1 = point1; _point2 = point2; - cache_gradients(); + details::gradients::cache_gradients(); } private: - void cache_gradients() { - _gradients = base::flat_map(); - for (const auto &[key, value] : _colors) { - _gradients.emplace(key, gradient(value)); - } + QGradient empty_gradient() const override { + return QLinearGradient(_point1, _point2); } - QLinearGradient gradient(const std::vector &colors) const { - auto gradient = QLinearGradient(_point1, _point2); - const auto size = colors.size(); - for (auto i = 0; i < size; i++) { - gradient.setColorAt(i / (size - 1), colors[i]); - } - return gradient; - } - - base::flat_map> _colors; QPointF _point1; QPointF _point2; - - base::flat_map _gradients; - -}; - -class radial_gradient { -public: - radial_gradient( - std::vector colors_from, - std::vector colors_to, - QPointF center, - float radius) - : _colors_from(colors_from) - , _colors_to(colors_to) - , _center(center) - , _radius(radius) - , _gradient_from(gradient(colors_from)) - , _gradient_to(gradient(colors_to)) { - Expects(colors_from.size() == colors_to.size()); - } - - QRadialGradient gradient(float64 b_ratio) const { - if (b_ratio == 0.) { - return _gradient_from; - } else if (b_ratio == 1.) { - return _gradient_to; - } - auto colors = std::vector(_colors_to.size()); - for (auto i = 0; i < colors.size(); i++) { - colors[i] = color(_colors_from[i], _colors_to[i], b_ratio); - } - return gradient(colors); - } - -private: - QRadialGradient gradient(const std::vector &colors) const { - auto gradient = QRadialGradient(_center, _radius); - const auto size = colors.size(); - for (auto i = 0; i < size; i++) { - gradient.setColorAt(i / (size - 1), colors[i]); - } - return gradient; - } - - std::vector _colors_from; - std::vector _colors_to; - QPointF _center; - float _radius; - - QRadialGradient _gradient_from; - QRadialGradient _gradient_to; - }; template -class radial_gradients { +class radial_gradients final : public details::gradients { public: radial_gradients( base::flat_map> colors, QPointF center, float radius) - : _colors(colors) - , _center(center) - , _radius(radius) { - Expects(_colors.size() > 0); - - cache_gradients(); - } - - QRadialGradient gradient(T state1, T state2, float64 b_ratio) const { - if (b_ratio == 0.) { - return _gradients.find(state1)->second; - } else if (b_ratio == 1.) { - return _gradients.find(state2)->second; - } - - auto gradient = QRadialGradient(_center, _radius); - const auto size = _colors.front().second.size(); - const auto colors1 = _colors.find(state1); - const auto colors2 = _colors.find(state2); - - Assert(colors1 != end(_colors)); - Assert(colors2 != end(_colors)); - - for (auto i = 0; i < size; i++) { - auto c = color(colors1->second[i], colors2->second[i], b_ratio); - gradient.setColorAt(i / (size - 1), std::move(c)); - } - return gradient; + : details::gradients(std::move(colors)) { + set_points(center, radius); } void set_points(QPointF center, float radius) { @@ -226,32 +118,16 @@ public: } _center = center; _radius = radius; - cache_gradients(); + details::gradients::cache_gradients(); } private: - void cache_gradients() { - _gradients = base::flat_map(); - for (const auto &[key, value] : _colors) { - _gradients.emplace(key, gradient(value)); - } + QGradient empty_gradient() const override { + return QRadialGradient(_center, _radius); } - QRadialGradient gradient(const std::vector &colors) const { - auto gradient = QRadialGradient(_center, _radius); - const auto size = colors.size(); - for (auto i = 0; i < size; i++) { - gradient.setColorAt(i / (size - 1), colors[i]); - } - return gradient; - } - - base::flat_map> _colors; QPointF _center; - float _radius; - - base::flat_map _gradients; - + float _radius = 0.; }; } // namespace anim