|
@@ -1,164 +0,0 @@
|
|
|
-#include "Gradient.h"
|
|
|
-
|
|
|
-#include "CubicSpline.h"
|
|
|
-
|
|
|
-#include <cmath>
|
|
|
-#include <algorithm>
|
|
|
-#include <functional>
|
|
|
-#include <QtXml/QDomDocument>
|
|
|
-#include <QFile>
|
|
|
-
|
|
|
-
|
|
|
-Gradient::Gradient(void) :
|
|
|
- max{ 1.0 }
|
|
|
-{
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-Gradient::Gradient(std::vector<std::pair<RGBColor, float>> colors, bool repeat, int precalcSteps) :
|
|
|
- repeat{ repeat }
|
|
|
-{
|
|
|
- if(colors.empty() || colors.size() < 2)
|
|
|
- return;
|
|
|
- std::sort(colors.begin(), colors.end(),
|
|
|
- [] (const auto& a, const auto& b) {
|
|
|
- return a.second < b.second;
|
|
|
- });
|
|
|
-
|
|
|
- max = colors.at(colors.size() - 1).second;
|
|
|
-
|
|
|
- std::vector<std::pair<RGBColorf, float>> linearColors;
|
|
|
- std::transform(colors.begin(), colors.end(), std::back_inserter(linearColors),
|
|
|
- [] (auto c) { return c; });
|
|
|
-
|
|
|
- std::vector<std::pair<float, float>> rs;
|
|
|
- std::vector<std::pair<float, float>> gs;
|
|
|
- std::vector<std::pair<float, float>> bs;
|
|
|
-
|
|
|
- std::transform(linearColors.begin(), linearColors.end(), std::back_inserter(rs),
|
|
|
- [] (auto p) { return std::pair{ p.second, p.first.r }; });
|
|
|
- std::transform(linearColors.begin(), linearColors.end(), std::back_inserter(gs),
|
|
|
- [] (auto p) { return std::pair{ p.second, p.first.g }; });
|
|
|
- std::transform(linearColors.begin(), linearColors.end(), std::back_inserter(bs),
|
|
|
- [] (auto p) { return std::pair{ p.second, p.first.b }; });
|
|
|
-
|
|
|
- CubicSpline rsp(rs, false);
|
|
|
- CubicSpline gsp(gs, false);
|
|
|
- CubicSpline bsp(bs, false);
|
|
|
-
|
|
|
- if(precalcSteps <= 0) {
|
|
|
- precalcSteps = int(max * 15) + 10;
|
|
|
- }
|
|
|
-
|
|
|
- for (int i = 0; i < precalcSteps; i++) {
|
|
|
- float position = i * max / precalcSteps;
|
|
|
- RGBColorf at = {
|
|
|
- rsp.interpolateAt(position),
|
|
|
- gsp.interpolateAt(position),
|
|
|
- bsp.interpolateAt(position)
|
|
|
- };
|
|
|
- this->colors.push_back(at);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-Gradient Gradient::defaultGradient(void)
|
|
|
-{
|
|
|
- QFile res(":/gradients/default");
|
|
|
- res.open(QIODevice::ReadOnly);
|
|
|
- QString str = QString::fromUtf8(res.readAll());
|
|
|
- return readXml(str);
|
|
|
-}
|
|
|
-
|
|
|
-Gradient Gradient::readXml(const QString& xml)
|
|
|
-{
|
|
|
- QDomDocument xsr;
|
|
|
- xsr.setContent(xml);
|
|
|
- auto elem = xsr.documentElement();
|
|
|
- auto repeatAttr = elem.attributeNode("repeat");
|
|
|
- bool repeat = !repeatAttr.isNull() && repeatAttr.value().toLower() == "true";
|
|
|
- auto colors = xsr.elementsByTagName("color");
|
|
|
- std::vector<std::pair<RGBColor, float>> colorArr;
|
|
|
- for (int i = 0; i < colors.length(); ++i) {
|
|
|
- auto child = colors.item(i).toElement();
|
|
|
- uint8_t r = uint8_t(child.attributeNode("r").value().toInt());
|
|
|
- uint8_t g = uint8_t(child.attributeNode("g").value().toInt());
|
|
|
- uint8_t b = uint8_t(child.attributeNode("b").value().toInt());
|
|
|
- float p = child.attributeNode("p").value().toInt();
|
|
|
-
|
|
|
- //printf("rgb (%s): %d, %d, %d\n", child.text().toUtf8().data(), r, g, b);
|
|
|
- colorArr.push_back({ { r, g, b }, p });
|
|
|
- }
|
|
|
-
|
|
|
- return Gradient(std::move(colorArr), repeat);
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-RGBColor Gradient::get(float x) const
|
|
|
-{
|
|
|
- if (colors.empty() || std::isnan(x) || std::isinf(x))
|
|
|
- return RGBColor();
|
|
|
- /*const auto [left, right, lerp] = getNeighbors(x);
|
|
|
- RGBColor lerped = lerpColors(left, right, lerp);
|
|
|
- return lerped;*/
|
|
|
-
|
|
|
- if (x < 0)
|
|
|
- return colors[0];
|
|
|
- if (x > this->max) {
|
|
|
- if (repeat)
|
|
|
- x = ::fmodf(x, this->max);
|
|
|
- else
|
|
|
- x = this->max;
|
|
|
- }
|
|
|
- float pos = x * colors.size() / max;
|
|
|
- if (pos < 0) {
|
|
|
- pos = 0;
|
|
|
- }
|
|
|
- if (pos > colors.size() - 1) {
|
|
|
- pos = colors.size() - 1;
|
|
|
- }
|
|
|
-
|
|
|
- int left = int(pos);
|
|
|
- int right = int(pos + 1);
|
|
|
- float lerp = pos - left;
|
|
|
-
|
|
|
- if (lerp < 1e-5f) {
|
|
|
- return colors[left];
|
|
|
- }
|
|
|
- else {
|
|
|
- return lerpColors(colors[left], colors[right], lerp);
|
|
|
- }
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-RGBColorf Gradient::lerpColors(RGBColorf a, RGBColorf b, float val)
|
|
|
-{
|
|
|
- return RGBColorf {
|
|
|
- b.r * val + a.r * (1 - val),
|
|
|
- b.g * val + a.g * (1 - val),
|
|
|
- b.b * val + a.b * (1 - val)
|
|
|
- };
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-RGBColor Gradient::lerpColors(RGBColor a, RGBColor b, float val)
|
|
|
-{
|
|
|
- return RGBColor{ lerpColors(RGBColorf{ a }, RGBColorf{ b }, val) };
|
|
|
-}
|
|
|
-
|
|
|
-
|
|
|
-/*std::tuple<RGBColor, RGBColor, float> Gradient::getNeighbors(float x) const
|
|
|
-{
|
|
|
- for (auto it = colors.begin(); it != colors.end(); ++it) {
|
|
|
- if (it->second > x) {
|
|
|
- if (it == colors.begin()) {
|
|
|
- return { it->first, it->first, 0 };
|
|
|
- }
|
|
|
- else {
|
|
|
- float lerp = (x - (it - 1)->second) / (it->second - (it - 1)->second);
|
|
|
- return { (it - 1)->first, it->first, lerp };
|
|
|
- }
|
|
|
- }
|
|
|
- }
|
|
|
- return { (colors.end() - 1)->first, (colors.end() - 1)->first, 0 };
|
|
|
-}*/
|