summary refs log tree commit diff
path: root/src/Utils.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/Utils.cpp')
-rw-r--r--src/Utils.cpp122
1 files changed, 122 insertions, 0 deletions
diff --git a/src/Utils.cpp b/src/Utils.cpp

index 8176cb43..0d3e9384 100644 --- a/src/Utils.cpp +++ b/src/Utils.cpp
@@ -15,6 +15,8 @@ using TimelineEvent = mtx::events::collections::TimelineEvents; +QHash<QString, QString> authorColors_; + QString utils::localUser() { @@ -382,6 +384,126 @@ utils::linkColor() return QPalette().color(QPalette::Link).name(); } +int +utils::hashQString(const QString &input) +{ + auto hash = 0; + + for (int i = 0; i < input.length(); i++) { + hash = input.at(i).digitValue() + ((hash << 5) - hash); + } + + return hash; +} + +QString +utils::generateContrastingHexColor(const QString &input, const QString &background) +{ + const QColor backgroundCol(background); + const qreal backgroundLum = luminance(background); + + // Create a color for the input + auto hash = hashQString(input); + // create a hue value based on the hash of the input. + auto userHue = qAbs(hash % 360); + // 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::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); + + 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(); + + return colorHex; +} + +qreal +utils::computeContrast(const qreal &one, const qreal &two) +{ + auto ratio = (one + 0.05) / (two + 0.05); + + if (two > one) { + ratio = 1 / ratio; + } + + return ratio; +} + +qreal +utils::luminance(const QColor &col) +{ + int colRgb[3] = {col.red(), col.green(), col.blue()}; + qreal lumRgb[3]; + + for (int i = 0; i < 3; i++) { + qreal v = colRgb[i] / 255.0; + v <= 0.03928 ? lumRgb[i] = v / 12.92 : lumRgb[i] = qPow((v + 0.055) / 1.055, 2.4); + } + + auto lum = lumRgb[0] * 0.2126 + lumRgb[1] * 0.7152 + lumRgb[2] * 0.0722; + + return lum; +} + void utils::centerWidget(QWidget *widget, QWidget *parent) {