فهرست منبع

improved gradients

Nicolas Winkler 4 سال پیش
والد
کامیت
4fa03e3978

+ 0 - 48
include/Color.h

@@ -1,48 +0,0 @@
-#pragma once
-#ifndef COLOR_H_
-#define COLOR_H_
-
-#include <cinttypes>
-
-
-struct RGBColor;
-struct RGBColorf;
-
-/*!
- * \brief Represents a color in the sRGB color space with 8-bit channels
- */
-struct RGBColor
-{
-    uint8_t r, g, b;
-
-    inline RGBColor(void) :
-        r{ 0 }, g{ 0 }, b{ 0 }
-    {
-    }
-
-    inline RGBColor(uint8_t r, uint8_t g, uint8_t b) :
-        r{ r }, g{ g }, b{ b }
-    {
-    }
-
-    RGBColor(const RGBColorf& rgb);
-};
-
-
-/*!
- * \brief Represents a color in a linear RGB color space with 32-bit floating
- *        point numbers as channels.
- */
-struct RGBColorf
-{
-    float r, g, b;
-
-    inline RGBColorf(float r, float g, float b) :
-        r{ r }, g{ g }, b{ b }
-    {
-    }
-
-    RGBColorf(const RGBColor& srgb);
-};
-
-#endif // COLOR_H_

+ 62 - 7
libalmond/include/Color.h

@@ -8,9 +8,9 @@
 struct RGBColor;
 struct RGBColorf;
 
-/*!
- * \brief Represents a color in the sRGB color space with 8-bit channels
- */
+///
+/// \brief Represents a color in RGB color space with 8-bit channels
+///
 struct RGBColor
 {
     uint8_t r, g, b;
@@ -29,20 +29,75 @@ struct RGBColor
 };
 
 
-/*!
- * \brief Represents a color in a linear RGB color space with 32-bit floating
- *        point numbers as channels.
- */
+///
+/// \brief Represents a color in a RGB color space with 32-bit floating
+///        point numbers as channels.
+///
 struct RGBColorf
 {
     float r, g, b;
 
+    inline RGBColorf(void) :
+        r{ 0.0f }, g{ 0.0f }, b{ 0.0f}
+    {
+    }
+
+
     inline RGBColorf(float r, float g, float b) :
         r{ r }, g{ g }, b{ b }
     {
     }
 
+
     RGBColorf(const RGBColor& srgb);
+
+
+    ///
+    /// \brief calculates the channel-wise sum of two colors
+    ///
+    inline RGBColorf operator + (const RGBColorf& o) const
+    {
+        return RGBColorf {
+            r + o.r,
+            g + o.g,
+            b + o.b
+        };
+    }
+
+
+    ///
+    /// \brief calculates the channel-wise difference between two colors
+    ///
+    inline RGBColorf operator - (const RGBColorf& o) const
+    {
+        return RGBColorf {
+            r - o.r,
+            g - o.g,
+            b - o.b
+        };
+    }
+
+
+    ///
+    /// \brief multiplies all channels by a factor
+    ///
+    inline RGBColorf operator * (float f) const
+    {
+        return RGBColorf {
+            r * f,
+            g * f,
+            b * f
+        };
+    }
+
+
+    ///
+    /// \brief divides all channels by a factor
+    ///
+    inline RGBColorf operator / (float f) const
+    {
+        return this->operator * (1.0f / f);
+    }
 };
 
 #endif // COLOR_H_

+ 21 - 1
libalmond/include/CubicSpline.h

@@ -4,6 +4,8 @@
 #include <vector>
 #include <utility>
 #include <tuple>
+#include <map>
+#include <Color.h>
 
 class CubicSpline
 {
@@ -11,9 +13,27 @@ class CubicSpline
     std::vector<std::tuple<float, float, float>> points;
     bool useSlopes;
 public:
-    CubicSpline(const std::vector<std::pair<float, float>>& dataPoints, bool useSlopes, bool minSlopes);
+    CubicSpline(const std::vector<std::pair<float, float>>& dataPoints,
+                bool useSlopes, bool minSlopes);
 
     float interpolateAt(float x);
 };
 
+
+class ColorSpline
+{
+    ///
+    /// \brief at each position, stores the color value and the channel-wise
+    ///        slopes of the spline.
+    ///
+    std::map<float, std::pair<RGBColorf, RGBColorf>> points;
+    bool useSlopes;
+public:
+    ColorSpline(void) = default;
+    ColorSpline(const std::vector<std::pair<float, RGBColorf>>& dataPoints,
+                bool useSlopes, bool minSlopes);
+
+    RGBColorf interpolateAt(float x) const;
+};
+
 #endif // CUBICSPLINE_H

+ 2 - 0
libalmond/include/Gradient.h

@@ -5,6 +5,7 @@
 #include <map>
 #include <string>
 #include "Color.h"
+#include "CubicSpline.h"
 #include <tuple>
 #include <cinttypes>
 
@@ -13,6 +14,7 @@ class Gradient
 {
     std::vector<std::pair<RGBColor, float>> points;
     std::map<float, RGBColor, std::greater<float>> pointMap;
+    ColorSpline colorSpline;
 
     /// the colors of this gradient stored in linear RGB format
     /// so they can be easily interpolated

+ 9 - 6
libalmond/src/Color.cpp

@@ -2,21 +2,24 @@
 #include <cmath>
 #include <algorithm>
 
+const static float cGamma = 1.0f;
 
 RGBColor::RGBColor(const RGBColorf& rgb)
 {
     float cr = std::clamp(rgb.r, 0.0f, 1.0f);
     float cg = std::clamp(rgb.g, 0.0f, 1.0f);
     float cb = std::clamp(rgb.b, 0.0f, 1.0f);
-    r = uint8_t(cr * cr * 255.0f);
-    g = uint8_t(cg * cg * 255.0f);
-    b = uint8_t(cb * cb * 255.0f);
+    
+    const float invGamma = 1.0f / cGamma;
+    r = uint8_t(::powf(cr, invGamma) * 255.0f);
+    g = uint8_t(::powf(cg, invGamma) * 255.0f);
+    b = uint8_t(::powf(cb, invGamma) * 255.0f);
 }
 
 
 RGBColorf::RGBColorf(const RGBColor& srgb)
 {
-    r = ::sqrtf(srgb.r / 255.0f);
-    g = ::sqrtf(srgb.g / 255.0f);
-    b = ::sqrtf(srgb.b / 255.0f);
+    r = ::powf(srgb.r / 255.0f, cGamma);
+    g = ::powf(srgb.g / 255.0f, cGamma);
+    b = ::powf(srgb.b / 255.0f, cGamma);
 }

+ 117 - 1
libalmond/src/CubicSpline.cpp

@@ -1,7 +1,8 @@
 #include "CubicSpline.h"
 #include <cmath>
 
-CubicSpline::CubicSpline(const std::vector<std::pair<float, float> >& dataPoints, bool useSlopes, bool minSlopes) :
+CubicSpline::CubicSpline(const std::vector<std::pair<float, float> >& dataPoints,
+                         bool useSlopes, bool minSlopes) :
     useSlopes{ useSlopes }
 {
     if (dataPoints.size() < 2) {
@@ -81,3 +82,118 @@ float CubicSpline::interpolateAt(float x)
     }
     return std::get<1>(points[points.size() - 1]);
 }
+
+
+ColorSpline::ColorSpline(const std::vector<std::pair<float, RGBColorf> >& dataPoints,
+                         bool useSlopes, bool minSlopes) :
+    useSlopes{ useSlopes }
+{
+    if (dataPoints.size() < 1) {
+        points.emplace(0.0f, std::make_pair(RGBColorf{ 0, 0, 0 }, RGBColorf{ 0, 0, 0 }));
+        return;
+    }
+    if (dataPoints.size() == 1) {
+        points.emplace(dataPoints[0].first, std::make_pair(dataPoints[0].second, RGBColorf{ 0, 0, 0 }));
+        return;
+    }
+    
+    const auto& dpf = dataPoints[0];
+    const auto& dps = dataPoints[1];
+    points.emplace(dpf.first, std::make_pair(dpf.second,
+                       (dps.second - dpf.second) / (dps.first - dpf.first)));
+    for (size_t i = 1; i < dataPoints.size() - 1; i++) {
+
+        const auto& dp1 = dataPoints[i - 1];
+        const auto& dp2 = dataPoints[i];
+        const auto& dp3 = dataPoints[i + 1];
+
+        float w1 = dp2.first - dp1.first;
+        float w2 = dp3.first - dp2.first;
+        RGBColorf h1 = dp2.second - dp1.second;
+        RGBColorf h2 = dp3.second - dp2.second;
+
+        RGBColorf s1 = h1 / w1;
+        RGBColorf s2 = h2 / w2;
+
+        RGBColorf slope;
+        if (minSlopes) {
+            auto minAbs = [] (float a, float b) { return fabs(a) > fabs(b) ? b : a; };
+            slope.r = minAbs(s1.r, s2.r);
+        } else
+            slope = (s1 + s2) / 2;
+        points.emplace(dp2.first, std::make_pair(dp2.second, slope));
+    }
+
+    const auto& dpSecondLast = dataPoints[dataPoints.size() - 2];
+    const auto& dpLast = dataPoints[dataPoints.size() - 1];
+    points.emplace(dpLast.first, std::make_pair(dpLast.second,
+                       (dpSecondLast.second - dpLast.second) /
+                       (dpSecondLast.first - dpLast.first)));
+}
+
+
+RGBColorf ColorSpline::interpolateAt(float x) const
+{
+    const static auto h00 = [] (float t) { return (1 + 2 * t) * (1 - t) * (1 - t); };
+    const static auto h01 = [] (float t) { return t * t * (3 - 2 * t); };
+    const static auto h10 = [] (float t) { return t * (1 - t) * (1 - t); };
+    const static auto h11 = [] (float t) { return t * t * (t - 1); };
+
+    if (points.empty()) {
+        return RGBColorf{ 0, 0, 0 };
+    }
+
+
+    auto firstAfter = points.upper_bound(x);
+    if (firstAfter == points.begin()) {
+        return firstAfter->second.first;
+    }
+    auto lastBefore = firstAfter; lastBefore--;
+    if (firstAfter == points.end()) {
+        return lastBefore->second.first;
+    }
+
+    float xLeft = lastBefore->first;
+    float xRight = firstAfter->first;
+
+    RGBColorf yLeft = lastBefore->second.first;
+    RGBColorf yRight = firstAfter->second.first;
+    RGBColorf slopeLeft = lastBefore->second.second;
+    RGBColorf slopeRight = firstAfter->second.second;
+
+    float t = (x - xLeft) / (xRight - xLeft);
+
+    RGBColorf interpolated = yLeft * h00(t) + yRight * h01(t);
+    if (useSlopes) {
+        interpolated = interpolated + slopeLeft * h10(t) * (xRight - xLeft);
+        interpolated = interpolated + slopeRight * h11(t) * (xRight - xLeft);
+    }
+
+    return interpolated;
+
+    /*
+    for (auto it = points.begin(); it != points.end() && (it + 1) != points.end(); ++it) {
+        auto& left = *it;
+        auto& right = *(it + 1);
+        float xleft = std::get<0>(left);
+        float xright = std::get<0>(right);
+        if (xleft <= x && xright >= x) {
+            float w = (xright - xleft);
+            float t = (x - xleft) / w;
+            float yleft = std::get<1>(left);
+            float yright = std::get<1>(right);
+            float sleft = std::get<2>(left);
+            float sright = std::get<2>(right);
+
+            float inter = h00(t) * yleft +
+                          h01(t) * yright;
+
+            if (useSlopes)
+                inter += h10(t) * w * sleft +
+                         h11(t) * w * sright;
+
+            return inter;
+        }
+    }
+    return std::get<1>(points[points.size() - 1]);*/
+}

+ 18 - 1
libalmond/src/Gradient.cpp

@@ -34,6 +34,12 @@ Gradient::Gradient(std::vector<std::pair<RGBColor, float>> colors, bool repeat,
     points = colors;
     max = colors.at(colors.size() - 1).second;
 
+    std::vector<std::pair<float, RGBColorf>> fs;
+    for (const auto& [col, pos] : points) {
+        fs.push_back(std::make_pair(pos, col));
+    }
+    colorSpline = ColorSpline{ fs, false, false };
+    
     return;
     std::vector<std::pair<RGBColorf, float>> linearColors;
     std::transform(colors.begin(), colors.end(), std::back_inserter(linearColors),
@@ -89,6 +95,13 @@ Gradient::Gradient(std::vector<std::pair<RGBColor, float>> colors, float maxVal,
 
     points = colors;
     max = maxVal;
+    
+
+    std::vector<std::pair<float, RGBColorf>> fs;
+    for (const auto& [col, pos] : points) {
+        fs.push_back(std::make_pair(pos, col));
+    }
+    colorSpline = ColorSpline{ fs, false, false };
     return;
     std::vector<std::pair<RGBColorf, float>> linearColors;
     std::transform(colors.begin(), colors.end(), std::back_inserter(linearColors),
@@ -205,7 +218,9 @@ std::string Gradient::toXml(void) const
 {
     std::stringstream buf;
 
-    buf << "<gradient max=\"" << max << "\" repeat=\"" << (repeat ? "true" : "false") << "\">" << std::endl;
+    std::string version = "1.0.0";
+    buf << "<gradient max=\"" << max << "\" repeat=\"" << (repeat ? "true" : "false") 
+        << "\" version=\"" << version << "\" >" << std::endl;
     for (const auto&[color, val] : points) {
         buf << "    <color " <<
                "r=\"" << int(color.r) <<
@@ -264,6 +279,8 @@ RGBColor Gradient::get(float x) const
 
 RGBColor Gradient::interpolate(float x) const
 {
+    return colorSpline.interpolateAt(x);
+    
     if (pointMap.empty()) {
         return RGBColor{ 0, 0, 0 };
     }

+ 35 - 6
resources/icons/cancel.svg

@@ -5,11 +5,39 @@
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
-   id="svg8"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
+   sodipodi:docname="cancel.svg"
+   width="12.690882mm"
+   height="12.683558mm"
+   viewBox="0 0 12.690882 12.683558"
    version="1.1"
-   viewBox="0 0 210 297"
-   height="297mm"
-   width="210mm">
+   id="svg8">
+  <sodipodi:namedview
+     fit-margin-bottom="0"
+     fit-margin-right="0"
+     fit-margin-left="0"
+     fit-margin-top="0"
+     inkscape:current-layer="svg8"
+     inkscape:window-maximized="0"
+     inkscape:window-y="34"
+     inkscape:window-x="0"
+     inkscape:cy="59.061224"
+     inkscape:cx="20.161843"
+     inkscape:zoom="8.5724337"
+     showgrid="false"
+     id="namedview2497"
+     inkscape:window-height="1360"
+     inkscape:window-width="2552"
+     inkscape:pageshadow="2"
+     inkscape:pageopacity="0"
+     guidetolerance="10"
+     gridtolerance="10"
+     objecttolerance="10"
+     borderopacity="1"
+     bordercolor="#666666"
+     pagecolor="#ffffff" />
   <defs
      id="defs2" />
   <metadata
@@ -25,10 +53,11 @@
     </rdf:RDF>
   </metadata>
   <g
+     transform="matrix(0.06284129,0,0,0.06286613,-0.15410871,-2.9496449)"
      id="layer1">
     <path
-       id="path832"
+       style="fill:none;stroke:#ec2900;stroke-width:45.1731;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
        d="m 27.854233,223.32152 c -5.883202,-6.26321 -5.275239,-7.12501 29.66983,-42.05665 17.74761,-17.74081 32.2684,-32.80134 32.2684,-33.4679 0,-0.66653 -14.52079,-15.72707 -32.2684,-33.46788 C 29.249776,86.065646 25.255669,81.617004 25.255669,78.388467 c 0,-4.920247 4.276916,-8.882457 9.587959,-8.882457 3.713063,0 6.813285,2.751136 36.683505,32.55286 l 32.627687,32.55285 32.56476,-32.55285 c 29.23171,-29.221038 32.96149,-32.55286 36.44091,-32.55286 5.28047,0 8.65664,3.595229 8.65664,9.218288 0,4.211257 -1.64139,6.081976 -32.24511,36.749912 l -32.24515,32.31277 32.24515,32.32769 c 30.01558,30.09242 32.24511,32.61973 32.24511,36.55155 0,5.21525 -4.03264,9.42173 -9.03245,9.42173 -2.98751,0 -8.26987,-4.76779 -36.05527,-32.54304 l -32.55492,-32.54302 -32.678497,32.54302 c -30.293713,30.16814 -32.983692,32.54304 -36.860829,32.54304 -2.826495,0 -5.024765,-0.89685 -6.780931,-2.76643 z"
-       style="fill:none;stroke:#ec2900;stroke-width:45.17306137;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" />
+       id="path832" />
   </g>
 </svg>

+ 37 - 5
resources/icons/zoom_in.svg

@@ -5,11 +5,42 @@
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    id="svg8"
    version="1.1"
-   viewBox="0 0 210 297"
-   height="297mm"
-   width="210mm">
+   viewBox="0 0 16.933334 16.933334"
+   height="64"
+   width="64"
+   sodipodi:docname="zoom_in.svg"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)">
+  <sodipodi:namedview
+     inkscape:document-rotation="0"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="2552"
+     inkscape:window-height="1360"
+     id="namedview1248"
+     showgrid="false"
+     inkscape:zoom="8.1125928"
+     inkscape:cx="34.041413"
+     inkscape:cy="49.145806"
+     inkscape:window-x="0"
+     inkscape:window-y="34"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg8"
+     borderlayer="false"
+     units="px"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
   <defs
      id="defs2" />
   <metadata
@@ -25,7 +56,8 @@
     </rdf:RDF>
   </metadata>
   <g
-     id="layer1">
+     id="layer1"
+     transform="matrix(0.06701976,0,0,0.06525021,1.9663419,-0.83650476)">
     <ellipse
        ry="58.99258"
        rx="58.992577"
@@ -36,7 +68,7 @@
     <path
        id="path4584"
        d="m 111.18412,154.81261 72.69731,76.97362"
-       style="fill:none;stroke:#000000;stroke-width:16.00000045;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke fill markers" />
+       style="fill:none;stroke:#000000;stroke-width:16;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" />
     <path
        id="path816"
        d="M 69.093491,80.283767 V 144.43648"

+ 36 - 5
resources/icons/zoom_out.svg

@@ -5,11 +5,41 @@
    xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#"
    xmlns:svg="http://www.w3.org/2000/svg"
    xmlns="http://www.w3.org/2000/svg"
+   xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
+   xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    id="svg8"
    version="1.1"
-   viewBox="0 0 210 297"
-   height="297mm"
-   width="210mm">
+   viewBox="0 0 16.933334 16.933334"
+   height="64"
+   width="64"
+   sodipodi:docname="zoom_out.svg"
+   inkscape:version="1.0 (4035a4fb49, 2020-05-01)">
+  <sodipodi:namedview
+     units="px"
+     inkscape:document-rotation="0"
+     pagecolor="#ffffff"
+     bordercolor="#666666"
+     borderopacity="1"
+     objecttolerance="10"
+     gridtolerance="10"
+     guidetolerance="10"
+     inkscape:pageopacity="0"
+     inkscape:pageshadow="2"
+     inkscape:window-width="2552"
+     inkscape:window-height="1360"
+     id="namedview1300"
+     showgrid="false"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0"
+     inkscape:zoom="0.74742565"
+     inkscape:cx="60.47417"
+     inkscape:cy="389.76731"
+     inkscape:window-x="0"
+     inkscape:window-y="34"
+     inkscape:window-maximized="0"
+     inkscape:current-layer="svg8" />
   <defs
      id="defs2" />
   <metadata
@@ -25,7 +55,8 @@
     </rdf:RDF>
   </metadata>
   <g
-     id="layer1">
+     id="layer1"
+     transform="matrix(0.06675232,0,0,0.06525582,1.9922812,-0.83730462)">
     <ellipse
        ry="58.99258"
        rx="58.992577"
@@ -36,7 +67,7 @@
     <path
        id="path4584"
        d="m 111.18412,154.81261 72.69731,76.97362"
-       style="fill:none;stroke:#000000;stroke-width:16.00000045;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke fill markers" />
+       style="fill:none;stroke:#000000;stroke-width:16;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers" />
     <path
        id="path816-4"
        d="M 101.16985,112.36012 H 37.017135"

+ 30 - 23
resources/icons/zoom_zero.svg

@@ -9,19 +9,20 @@
    xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
    inkscape:version="1.0 (4035a4fb49, 2020-05-01)"
    sodipodi:docname="zoom_zero.svg"
-   width="210mm"
-   height="297mm"
-   viewBox="0 0 210 297"
+   width="64"
+   height="64"
+   viewBox="0 0 16.933333 16.933333"
    version="1.1"
    id="svg8">
   <sodipodi:namedview
+     units="px"
      inkscape:current-layer="layer1"
      inkscape:window-maximized="0"
      inkscape:window-y="34"
      inkscape:window-x="0"
-     inkscape:cy="561.25984"
-     inkscape:cx="36.27941"
-     inkscape:zoom="0.74742565"
+     inkscape:cy="8.3242034"
+     inkscape:cx="41.722802"
+     inkscape:zoom="5.5928823"
      showgrid="false"
      id="namedview10"
      inkscape:window-height="1360"
@@ -33,7 +34,12 @@
      objecttolerance="10"
      borderopacity="1"
      bordercolor="#666666"
-     pagecolor="#ffffff" />
+     pagecolor="#ffffff"
+     inkscape:document-rotation="0"
+     fit-margin-top="0"
+     fit-margin-left="0"
+     fit-margin-right="0"
+     fit-margin-bottom="0" />
   <defs
      id="defs2" />
   <metadata
@@ -49,28 +55,29 @@
     </rdf:RDF>
   </metadata>
   <g
-     id="layer1">
+     id="layer1"
+     transform="translate(-2.1009127,-45.367542)">
     <ellipse
-       style="fill:none;stroke:#000000;stroke-width:16;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
-       id="path4526"
-       cx="69.093491"
-       cy="112.36012"
-       rx="58.992577"
-       ry="58.99258" />
+       cx="8.6986227"
+       cy="51.862511"
+       rx="3.9521058"
+       ry="3.8493688"
+       style="fill:none;stroke:#000000;stroke-width:1.05787;stroke-linecap:round;stroke-linejoin:round;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:normal"
+       id="path4526" />
     <path
-       style="fill:none;stroke:#000000;stroke-width:16.00000045;stroke-linecap:round;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none;paint-order:stroke fill markers"
-       d="m 111.18412,154.81261 72.69731,76.97362"
+       style="fill:none;stroke:#000000;stroke-width:1.05787;stroke-linecap:round;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1;paint-order:stroke fill markers"
+       d="m 11.518412,54.63261 4.87023,5.022664"
        id="path4584" />
     <ellipse
-       ry="33.163971"
-       rx="21.126312"
-       cy="112.36012"
-       cx="69.093491"
+       ry="2.1640072"
+       rx="1.4153208"
+       cy="51.862511"
+       cx="8.6986227"
        id="path12"
-       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:13.8082;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
+       style="fill:none;fill-rule:evenodd;stroke:#000000;stroke-width:0.912953;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
     <path
        id="path863"
-       d="M 57.790024,90.093966 81.672225,136.93685"
-       style="fill:none;stroke:#000000;stroke-width:7.93750002;stroke-linecap:butt;stroke-linejoin:miter;stroke-opacity:1;stroke-miterlimit:4;stroke-dasharray:none" />
+       d="m 7.9413666,50.409606 1.5999468,3.05658"
+       style="fill:none;stroke:#000000;stroke-width:0.524802;stroke-linecap:butt;stroke-linejoin:miter;stroke-miterlimit:4;stroke-dasharray:none;stroke-opacity:1" />
   </g>
 </svg>

+ 0 - 22
src/Color.cpp

@@ -1,22 +0,0 @@
-#include "Color.h"
-#include <cmath>
-#include <algorithm>
-
-
-RGBColor::RGBColor(const RGBColorf& rgb)
-{
-    float cr = std::clamp(rgb.r, 0.0f, 1.0f);
-    float cg = std::clamp(rgb.g, 0.0f, 1.0f);
-    float cb = std::clamp(rgb.b, 0.0f, 1.0f);
-    r = uint8_t(cr * cr * 255.0f);
-    g = uint8_t(cg * cg * 255.0f);
-    b = uint8_t(cb * cb * 255.0f);
-}
-
-
-RGBColorf::RGBColorf(const RGBColor& srgb)
-{
-    r = ::sqrtf(srgb.r / 255.0f);
-    g = ::sqrtf(srgb.g / 255.0f);
-    b = ::sqrtf(srgb.b / 255.0f);
-}

+ 0 - 3
src/EscapeTimeVisualWidget.cpp

@@ -192,9 +192,6 @@ void EscapeTimeVisualWidget::initializeGL(void)
     fprintf(stdout, "version: %s\n", gl.glGetString(GL_VERSION));
     fflush(stdout);
 
-    // looks not even better
-    //gl.glEnable(GL_FRAMEBUFFER_SRGB);
-
     //glShadeModel(GL_SMOOTH);
 
     renderTextures = new QOpenGLShaderProgram{ this->context() };

+ 10 - 1
src/GradientWidget.cpp

@@ -77,8 +77,17 @@ void GradientWidget::paintEvent(QPaintEvent* e)
     QLinearGradient linGrad;
     linGrad.setStart(0, gradientRect.top());
     linGrad.setFinalStop(0, gradientRect.bottom());
-    for (const auto& [col, at] : points) {
+    for (auto it = points.cbegin(); it != points.cend(); it++) {
+        float at = it->second;
+        RGBColor col = it->first;
         linGrad.setColorAt(at / maxValue, QColor{ col.r, col.g, col.b });
+        /*if (it + 1 != points.cend()) {
+            float nat = (it + 1)->second;
+            for (int i = 0; i < 5; i++) {
+                float iat = at + i * (nat - at) / 5.0;
+                linGrad.setColorAt(iat / maxValue, fromRGB(gradient.get(iat)));
+            }
+        }*/
     }
 
     // adjust rect to have small margins, so the frame

+ 2 - 2
ui/Almond.ui

@@ -64,8 +64,8 @@
          <rect>
           <x>0</x>
           <y>0</y>
-          <width>271</width>
-          <height>661</height>
+          <width>593</width>
+          <height>1063</height>
          </rect>
         </property>
         <layout class="QHBoxLayout" name="horizontalLayout_3">