// This file is part of Desktop App Toolkit, // a set of libraries for developing nice desktop applications. // // For license and copyright information please follow this link: // https://github.com/desktop-app/legal/blob/master/LEGAL // #pragma once #include "base/flat_map.h" #include "ui/effects/animation_value.h" #include #include namespace anim { namespace details { template class gradients { public: gradients(base::flat_map> colors) : _colors(colors) { Expects(_colors.size() > 0); } 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 = empty_gradient(); 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; } 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; details::gradients::cache_gradients(); } private: QGradient empty_gradient() const override { return QLinearGradient(_point1, _point2); } QPointF _point1; QPointF _point2; }; template class radial_gradients final : public details::gradients { public: radial_gradients( base::flat_map> colors, QPointF center, float radius) : details::gradients(std::move(colors)) { set_points(center, radius); } void set_points(QPointF center, float radius) { if (_center == center && _radius == radius) { return; } _center = center; _radius = radius; details::gradients::cache_gradients(); } private: QGradient empty_gradient() const override { return QRadialGradient(_center, _radius); } QPointF _center; float _radius = 0.; }; } // namespace anim