Extracted common code for gradient classes.

This commit is contained in:
23rd 2020-12-11 02:00:20 +03:00
parent d032f4d8b5
commit d61e1a7bde

View file

@ -14,78 +14,24 @@
namespace anim { namespace anim {
class linear_gradient { namespace details {
public:
linear_gradient(
std::vector<QColor> colors_from,
std::vector<QColor> 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<QColor>(_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<QColor> &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<QColor> _colors_from;
std::vector<QColor> _colors_to;
QPointF _point1;
QPointF _point2;
QLinearGradient _gradient_from;
QLinearGradient _gradient_to;
};
template <typename T> template <typename T>
class linear_gradients { class gradients {
public: public:
linear_gradients( gradients(base::flat_map<T, std::vector<QColor>> colors)
base::flat_map<T, std::vector<QColor>> colors, : _colors(colors) {
QPointF point1,
QPointF point2)
: _colors(colors)
, _point1(point1)
, _point2(point2) {
Expects(_colors.size() > 0); 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.) { if (b_ratio == 0.) {
return _gradients.find(state1)->second; return _gradients.find(state1)->second;
} else if (b_ratio == 1.) { } else if (b_ratio == 1.) {
return _gradients.find(state2)->second; return _gradients.find(state2)->second;
} }
auto gradient = QLinearGradient(_point1, _point2); auto gradient = empty_gradient();
const auto size = _colors.front().second.size(); const auto size = _colors.front().second.size();
const auto colors1 = _colors.find(state1); const auto colors1 = _colors.find(state1);
const auto colors2 = _colors.find(state2); const auto colors2 = _colors.find(state2);
@ -100,124 +46,70 @@ public:
return gradient; return gradient;
} }
protected:
virtual QGradient empty_gradient() const = 0;
void cache_gradients() {
_gradients = base::flat_map<T, QGradient>();
for (const auto &[key, value] : _colors) {
_gradients.emplace(key, gradient(value));
}
}
QGradient gradient(const std::vector<QColor> &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<T, std::vector<QColor>> _colors;
base::flat_map<T, QGradient> _gradients;
};
} // namespace details
template <typename T>
class linear_gradients final : public details::gradients<T> {
public:
linear_gradients(
base::flat_map<T, std::vector<QColor>> colors,
QPointF point1,
QPointF point2)
: details::gradients<T>(std::move(colors)) {
set_points(point1, point2);
}
void set_points(QPointF point1, QPointF point2) { void set_points(QPointF point1, QPointF point2) {
if (_point1 == point1 && _point2 == point2) { if (_point1 == point1 && _point2 == point2) {
return; return;
} }
_point1 = point1; _point1 = point1;
_point2 = point2; _point2 = point2;
cache_gradients(); details::gradients<T>::cache_gradients();
} }
private: private:
void cache_gradients() { QGradient empty_gradient() const override {
_gradients = base::flat_map<T, QLinearGradient>(); return QLinearGradient(_point1, _point2);
for (const auto &[key, value] : _colors) {
_gradients.emplace(key, gradient(value));
}
} }
QLinearGradient gradient(const std::vector<QColor> &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<T, std::vector<QColor>> _colors;
QPointF _point1; QPointF _point1;
QPointF _point2; QPointF _point2;
base::flat_map<T, QLinearGradient> _gradients;
};
class radial_gradient {
public:
radial_gradient(
std::vector<QColor> colors_from,
std::vector<QColor> 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<QColor>(_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<QColor> &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<QColor> _colors_from;
std::vector<QColor> _colors_to;
QPointF _center;
float _radius;
QRadialGradient _gradient_from;
QRadialGradient _gradient_to;
}; };
template <typename T> template <typename T>
class radial_gradients { class radial_gradients final : public details::gradients<T> {
public: public:
radial_gradients( radial_gradients(
base::flat_map<T, std::vector<QColor>> colors, base::flat_map<T, std::vector<QColor>> colors,
QPointF center, QPointF center,
float radius) float radius)
: _colors(colors) : details::gradients<T>(std::move(colors)) {
, _center(center) set_points(center, radius);
, _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;
} }
void set_points(QPointF center, float radius) { void set_points(QPointF center, float radius) {
@ -226,32 +118,16 @@ public:
} }
_center = center; _center = center;
_radius = radius; _radius = radius;
cache_gradients(); details::gradients<T>::cache_gradients();
} }
private: private:
void cache_gradients() { QGradient empty_gradient() const override {
_gradients = base::flat_map<T, QRadialGradient>(); return QRadialGradient(_center, _radius);
for (const auto &[key, value] : _colors) {
_gradients.emplace(key, gradient(value));
}
} }
QRadialGradient gradient(const std::vector<QColor> &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<T, std::vector<QColor>> _colors;
QPointF _center; QPointF _center;
float _radius; float _radius = 0.;
base::flat_map<T, QRadialGradient> _gradients;
}; };
} // namespace anim } // namespace anim