summary refs log tree commit diff
path: root/src/Utils.cpp
diff options
context:
space:
mode:
authorredsky17 <joedonofry@gmail.com>2019-01-20 00:12:57 +0000
committerredsky17 <joedonofry@gmail.com>2019-01-20 00:16:31 +0000
commitb3f7c13e2f885bc804665cfc36011f22539bae53 (patch)
tree6481986820a7fd3736756b3c020da2c6ed7afe2d /src/Utils.cpp
parentFix UserSettings UI not showing saved prefs (diff)
downloadnheko-b3f7c13e2f885bc804665cfc36011f22539bae53.tar.xz
Update user id color generation
Update the author color generation.  Now, instead of generating
an entire hex string based on the user id, the user id instead
is used to generate a hue value.  After this hue value is created,
there is some logic to tweak first the lightness and then saturation
values to achieve a readable color (in contrast to the background).

This change makes it so that user colors will not vary as wildly
between the different themes.

The values still are not cached and still do not update
initially when the theme is changed.  Both of these things
will be resolved.
Diffstat (limited to 'src/Utils.cpp')
-rw-r--r--src/Utils.cpp132
1 files changed, 72 insertions, 60 deletions
diff --git a/src/Utils.cpp b/src/Utils.cpp
index 6a5c3491..b7980fc3 100644
--- a/src/Utils.cpp
+++ b/src/Utils.cpp
@@ -382,19 +382,6 @@ utils::linkColor()
         return QPalette().color(QPalette::Link).name();
 }
 
-QString
-utils::generateHexColor(const int hash)
-{
-        QString colour("#");
-        for (int i = 0; i < 3; i++) {
-                int value = (hash >> (i * 8)) & 0xFF;
-                colour.append(("00" + QString::number(value, 16)).right(2));
-        }
-        // nhlog::ui()->debug("Hex Generated {} -> {}", QString::number(hash).toStdString(),
-        // colour.toStdString());
-        return colour.toUpper();
-}
-
 int
 utils::hashQString(const QString &input)
 {
@@ -404,8 +391,6 @@ utils::hashQString(const QString &input)
                 hash = input.at(i).digitValue() + ((hash << 5) - hash);
         }
 
-        hash *= 13;
-
         return hash;
 }
 
@@ -417,59 +402,84 @@ utils::generateContrastingHexColor(const QString &input, const QString &backgrou
         const qreal backgroundLum = luminance(background);
 
         // Create a color for the input
-        auto hash     = hashQString(input);
-        auto colorHex = generateHexColor(hash);
+        auto hash = hashQString(input);
+        // create a hue value based on the hash of the input.
+        auto userHue = qAbs(hash % 360);
+        nhlog::ui()->debug(
+          "User Hue {} : {}", input.toStdString(), QString::number(userHue).toStdString());
+        // start with moderate saturation and lightness values.
+        auto sat       = 220;
+        auto lightness = 125;
 
         // converting to a QColor makes the luminance calc easier.
-        QColor inputColor = QColor(colorHex);
-
-        // attempt to score both the luminance and the contrast.
-        // contrast should have a higher precedence, but luminance
-        // helps dictate how exciting the colors are.
-        auto colorLum = luminance(inputColor);
-        auto contrast = computeContrast(colorLum, backgroundLum);
-
-        // If the contrast or luminance don't meet our criteria,
-        // try again and again until they do.  After 10 tries,
-        // the best-scoring color will be chosen.
-        int att = 0;
-        while ((contrast < 5 || (colorLum < 0.05 || colorLum > 0.95)) && ++att < 10) {
-                hash        = hashQString(input) + ((hash << 2) * 13);
-                auto newHex = generateHexColor(hash);
-                inputColor.setNamedColor(newHex);
-                auto tmpLum      = luminance(inputColor);
-                auto tmpContrast = computeContrast(tmpLum, backgroundLum);
-
-                // Prioritize contrast over luminance
-                // If both values are better, it's a no brainer.
-                if (tmpContrast > contrast && (tmpLum > 0.05 && tmpLum < 0.95)) {
-                        contrast = tmpContrast;
-                        colorHex = newHex;
-                        colorLum = tmpLum;
-                }
-                // Otherwise, if we still can get a more
-                // vibrant color and have met our contrast
-                // threshold, pick the more vibrant color,
-                // even if contrast will drop somewhat.
-                // choosing 50% luminance as ideal.
-                else if ((qAbs(tmpLum - 0.50) < qAbs(colorLum - 0.50)) && tmpContrast >= 5) {
-                        contrast = tmpContrast;
-                        colorHex = newHex;
-                        colorLum = tmpLum;
-                }
-                // Otherwise, just take the better contrast.
-                else if (tmpContrast > contrast) {
-                        contrast = tmpContrast;
-                        colorHex = newHex;
-                        colorLum = tmpLum;
+        QColor inputColor = QColor::fromHsl(userHue, sat, lightness);
+
+        // calculate the initial luminance and contrast of the
+        // generated color.  It's possible that no additional
+        // work will be necessary.
+        auto lum      = luminance(inputColor);
+        auto contrast = computeContrast(lum, backgroundLum);
+
+        // If the contrast doesn't meet our criteria,
+        // try again and again until they do by modifying first
+        // the lightness and then the saturation of the color.
+        while (contrast < 5) {
+                // if our lightness is at it's bounds, try changing
+                // saturation instead.
+                if (lightness == 242 || lightness == 13) {
+                        qreal newSat = qBound(26.0, sat * 1.25, 242.0);
+                        nhlog::ui()->info("newSat {}", QString::number(newSat).toStdString());
+
+                        inputColor.setHsl(userHue, qFloor(newSat), lightness);
+                        auto tmpLum         = luminance(inputColor);
+                        auto higherContrast = computeContrast(tmpLum, backgroundLum);
+                        if (higherContrast > contrast) {
+                                contrast = higherContrast;
+                                sat      = newSat;
+                        } else {
+                                newSat = qBound(26.0, sat / 1.25, 242.0);
+                                inputColor.setHsl(userHue, qFloor(newSat), lightness);
+                                tmpLum             = luminance(inputColor);
+                                auto lowerContrast = computeContrast(tmpLum, backgroundLum);
+                                if (lowerContrast > contrast) {
+                                        contrast = lowerContrast;
+                                        sat      = newSat;
+                                }
+                        }
+                } else {
+                        qreal newLightness = qBound(13.0, lightness * 1.25, 242.0);
+
+                        inputColor.setHsl(userHue, sat, qFloor(newLightness));
+
+                        auto tmpLum         = luminance(inputColor);
+                        auto higherContrast = computeContrast(tmpLum, backgroundLum);
+
+                        // Check to make sure we have actually improved contrast
+                        if (higherContrast > contrast) {
+                                contrast  = higherContrast;
+                                lightness = newLightness;
+                                // otherwise, try going the other way instead.
+                        } else {
+                                newLightness = qBound(13.0, lightness / 1.25, 242.0);
+                                inputColor.setHsl(userHue, sat, qFloor(newLightness));
+                                tmpLum             = luminance(inputColor);
+                                auto lowerContrast = computeContrast(tmpLum, backgroundLum);
+                                if (lowerContrast > contrast) {
+                                        contrast  = lowerContrast;
+                                        lightness = newLightness;
+                                }
+                        }
                 }
         }
 
+        // get the hex value of the generated color.
+        auto colorHex = inputColor.name();
+
         nhlog::ui()->debug("Hex Generated for {}: [hex: {}, contrast: {}, luminance: {}]",
                            input.toStdString(),
                            colorHex.toStdString(),
                            QString::number(contrast).toStdString(),
-                           QString::number(colorLum).toStdString());
+                           QString::number(lum).toStdString());
         return colorHex;
 }
 
@@ -496,7 +506,9 @@ utils::luminance(const QColor &col)
                 v <= 0.03928 ? lumRgb[i] = v / 12.92 : lumRgb[i] = qPow((v + 0.055) / 1.055, 2.4);
         }
 
-        return lumRgb[0] * 0.2126 + lumRgb[1] * 0.7152 + lumRgb[2] * 0.0722;
+        auto lum = lumRgb[0] * 0.2126 + lumRgb[1] * 0.7152 + lumRgb[2] * 0.0722;
+
+        return lum;
 }
 
 void