git » powerdevil.git » main » tree

[main] / new-brightness-logic.patch

diff --git a/daemon/powerdevilbrightnesslogic.h b/daemon/powerdevilbrightnesslogic.h
index 9ffdd02..3f4da27 100644
--- a/daemon/powerdevilbrightnesslogic.h
+++ b/daemon/powerdevilbrightnesslogic.h
@@ -146,7 +146,7 @@ public:
      * @param step Brightness step, from 0 to steps
      * @return Brightness value that corresponds to the given step
      */
-    int stepToValue(int step) const;
+    virtual int stepToValue(int step) const;
 
     /**
      * Convert raw brightness value to brightness step
@@ -154,7 +154,7 @@ public:
      * @param value Brightness value, from 0 to valueMax
      * @return Brightness step that is nearest to the given brightness value
      */
-    int valueToStep(int value) const;
+    virtual int valueToStep(int value) const;
 
 protected:
 
@@ -171,9 +171,8 @@ protected:
      * @param valueMax the maximum brightness value for which we want to calculate the number of steps
      * @return the optimal maximum step number
      */
-    virtual int calculateSteps(int valueMax) const = 0;
+    virtual int calculateSteps(int valueMax) = 0;
 
-private:
     int m_value = -1;
     int m_valueMax = -1;
     int m_steps = -1;
diff --git a/daemon/powerdevilkeyboardbrightnesslogic.cpp b/daemon/powerdevilkeyboardbrightnesslogic.cpp
index c1f5dbf..939b1ea 100644
--- a/daemon/powerdevilkeyboardbrightnesslogic.cpp
+++ b/daemon/powerdevilkeyboardbrightnesslogic.cpp
@@ -24,7 +24,7 @@
 namespace PowerDevil
 {
 
-int KeyboardBrightnessLogic::calculateSteps(int maxValue) const
+int KeyboardBrightnessLogic::calculateSteps(int maxValue)
 {
     // We assume that a generally good number of steps for keyboard brightness is about 5.
 
diff --git a/daemon/powerdevilkeyboardbrightnesslogic.h b/daemon/powerdevilkeyboardbrightnesslogic.h
index 0ae630f..c378792 100644
--- a/daemon/powerdevilkeyboardbrightnesslogic.h
+++ b/daemon/powerdevilkeyboardbrightnesslogic.h
@@ -29,7 +29,7 @@ class KeyboardBrightnessLogic : public BrightnessLogic
 {
 
 protected:
-    int calculateSteps(int valueMax) const override;
+    int calculateSteps(int valueMax) override;
 
 };
 
diff --git a/daemon/powerdevilscreenbrightnesslogic.cpp b/daemon/powerdevilscreenbrightnesslogic.cpp
index 66e2a96..f9b926a 100644
--- a/daemon/powerdevilscreenbrightnesslogic.cpp
+++ b/daemon/powerdevilscreenbrightnesslogic.cpp
@@ -30,48 +30,95 @@ int ScreenBrightnessLogic::toggled() const
     return -1;
 }
 
-int ScreenBrightnessLogic::calculateSteps(int maxValue) const
+int ScreenBrightnessLogic::increased() const
 {
-    // We assume that the preferred number of steps for screen brightness is 20, but we don't want more.
-
-    if (maxValue <= 20) {
-        // Too few steps, return the number of actual steps.
-        // Those would be uniform, but not round in some cases.
-        return maxValue;
+    if (m_value == m_valueMax) {
+        return m_valueMax; // we are at the maximum already
     }
 
-    if (maxValue >= 100 || maxValue % 20 == 0 || (maxValue >= 80 && maxValue % 4 == 0)) {
-        // In this case all 20 steps are perfect.
-        return 20;
+    int step = valueToStep(m_value) + 1;
+
+    return stepToValue(step);
+}
+
+int ScreenBrightnessLogic::decreased() const
+{
+    int step = valueToStep(m_value);
+
+    if ((m_value == 0)||(step == 0)) {
+        return 0; // we are at the minimum already
     }
+    step -= 1;
 
-    // At this point we have maxValue in the range 21-79 which probably is a rare case.
+    return stepToValue(step);
+}
 
-    if (maxValue >= 34 || maxValue == 32 || maxValue == 28) {
-        // In this case all 20 steps are matched +-1%, which is fine.
-        return 20;
+int ScreenBrightnessLogic::stepToValue(int step) const
+{
+    // This is the easy part
+    if (step >= m_steps) return m_valueMax;
+    if (step <= 0) return 0;
+    return m_steptab[step];
+}
+
+int ScreenBrightnessLogic::valueToStep(int value) const
+{
+    int step;
+    if (value >= m_valueMax) return m_steps;
+    if (value <= 0) return 0;
+    for (step = 1; step < m_steps; step++) {
+        // for very sparse steppings, endv can end up at value, thus <=
+        int endv = (m_steptab[step+1] + m_steptab[step]) / 2;
+        if (value <= endv) return step;
     }
+    return m_steps;
+}
 
-    // At this point we have maxValue in the range 21-33.
-    // Trying to make 20 steps from here will make them not uniform.
 
-    if (maxValue % 5 == 0) {
-        // For maxValue == 30 there are 10 even and round steps.
-        // For maxValue == 25 steps are shown as
-        //  0% 12% 20% 32% 40% 52% 60% 72% 80% 92% 100%, which is also fine.
-        return 10;
+int ScreenBrightnessLogic::calculateSteps(int maxValue)
+{
+    // F'ck uniformity of percentage steps. We want useful.
+    // Up to 20 steps is fine, tho.
+    // What i mean by useful is that the behaviour of values on lots of hardware is not linear,
+    // because the human visual system is not linear, and the use-cases are not linear.
+    // The use cases that matter being basically either in a dark room, or in the sunshine.
+    // Basically any implementation that works for those will also be fine for "office" 
+    // -- i mean, as long as we have some middle-of-the range points.
+
+    if (maxValue <= 20) {
+        // So few steps that we can provide each step directly. Easy.
+        for (int i = 0; i <= maxValue; i++) m_steptab[i] = i;
+        return maxValue;
     }
 
-    // Trying hard to find an uniform steps set
-    for (int steps = 9; steps <= 14; steps++) {
-        if (maxValue % steps == 0) {
-            return steps;
+    m_steptab[0] = 0;
+    // First step is the lowest (non-zero) value that averages to atleast 1 %.
+    for (int v = 1; v < maxValue; v++) {
+        int p = (percentage(v) + 0.5);
+        if (p >= 1) {
+            m_steptab[1] = v;
+            break;
         }
     }
 
-    // 4 different maxValue values left: 21, 23, 29, 31.
-    // Those produce +-2% on 10 steps, there is nothing better we can do here.
-    return 10;
+    // We need each point to evaluate to a different percentage value.
+    // These are crudely mapped from exponential-ish curve to the
+    // integer percentage space and finessed by hand to look nicer.
+    // Note: the lower end here can be unrepresentable if maxValue < 100.
+    // Thus we eliminate the duplicates.
+
+    const int basetab[14] = { 2,3,4,5,6,7,8,10,15,20,25,40,50,75 };
+    int stepout = 2;
+    for (int i = 0; i < 14; i++) {
+        float vf = (basetab[i] * maxValue) / 100.0f;
+	int v = vf + 0.5f;
+        if (m_steptab[stepout-1] == v) {
+            continue;
+        }
+        m_steptab[stepout++] = v;
+    }
+    m_steptab[stepout] = maxValue;
+    return stepout;
 }
 
 };
diff --git a/daemon/powerdevilscreenbrightnesslogic.h b/daemon/powerdevilscreenbrightnesslogic.h
index ce71e6b..1ed4254 100644
--- a/daemon/powerdevilscreenbrightnesslogic.h
+++ b/daemon/powerdevilscreenbrightnesslogic.h
@@ -31,9 +31,16 @@ class ScreenBrightnessLogic : public BrightnessLogic
 public:
     int toggled() const override;
 
-protected:
-    int calculateSteps(int valueMax) const override;
+    int increased() const override;
+    int decreased() const override;
+
+    int stepToValue(int step) const override;
+    int valueToStep(int value) const override;
 
+protected:
+    int calculateSteps(int valueMax) override;
+    // Fencepost: there's actually 21 steps going 0,5,10,...,95,100
+    int m_steptab[21];
 };
 
 }