File indexing completed on 2024-05-12 04:58:27

0001 /*
0002  *   Bespin library for Qt style, KWin decoration and everything else
0003  *   Copyright 2007-2012 by Thomas Lübking <thomas.luebking@gmail.com>
0004  *
0005  *   This library is free software; you can redistribute it and/or modify
0006  *   it under the terms of the GNU Library General Public License version 2
0007  *
0008  *   This program is distributed in the hope that it will be useful,
0009  *   but WITHOUT ANY WARRANTY; without even the implied warranty of
0010  *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
0011  *   GNU Library General Public License for more details
0012  *
0013  *   You should have received a copy of the GNU Library General Public
0014  *   License along with this program; if not, write to the
0015  *   Free Software Foundation, Inc.,
0016  *   51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
0017  */
0018 
0019 #include "colors.h"
0020 #define CLAMP(x,l,u) (x) < (l) ? (l) :\
0021     (x) > (u) ? (u) :\
0022     (x)
0023 #include <QWidget>
0024 #include <QApplication>
0025 
0026 // using namespace Bespin;
0027 
0028 const QColor &
0029 Colors::bg(const QPalette &pal, const QWidget* w)
0030 {
0031     QPalette::ColorRole role;
0032     if (!w) {
0033         role = QPalette::Window;
0034     }
0035     else if (w->parentWidget()) {
0036         role = w->parentWidget()->backgroundRole();
0037     }
0038     else {
0039         role = w->backgroundRole();
0040     }
0041 
0042 //     if (pal.brush(role).style() > 1)
0043     return pal.color(role);
0044 //     return QApplication::palette().color(role);
0045 }
0046 
0047 int
0048 Colors::contrast(const QColor &a, const QColor &b)
0049 {
0050     int ar, ag, ab, br, bg, bb;
0051     a.getRgb(&ar, &ag, &ab);
0052     b.getRgb(&br, &bg, &bb);
0053 
0054     int diff = 299 * (ar - br) + 587 * (ag - bg) + 114 * (ab - bb);
0055     diff = (diff < 0) ? -diff : 90 * diff / 100;
0056     int perc = diff / 2550;
0057 
0058     diff = qMax(ar, br) + qMax(ag, bg) + qMax(ab, bb)
0059            - (qMin(ar, br) + qMin(ag, bg) + qMin(ab, bb));
0060 
0061     perc += diff / 765;
0062     perc /= 2;
0063 
0064     return perc;
0065 }
0066 
0067 QPalette::ColorRole
0068 Colors::counterRole(QPalette::ColorRole role)
0069 {
0070     switch (role) {
0071     case QPalette::ButtonText: //8
0072         return QPalette::Button;
0073     case QPalette::WindowText: //0
0074         return QPalette::Window;
0075     case QPalette::HighlightedText: //13
0076         return QPalette::Highlight;
0077     case QPalette::Window: //10
0078         return QPalette::WindowText;
0079     case QPalette::Base: //9
0080         return QPalette::Text;
0081     case QPalette::Text: //6
0082         return QPalette::Base;
0083     case QPalette::Highlight: //12
0084         return QPalette::HighlightedText;
0085     case QPalette::Button: //1
0086         return QPalette::ButtonText;
0087     default:
0088         return QPalette::Window;
0089     }
0090 }
0091 
0092 bool
0093 Colors::counterRole(QPalette::ColorRole &from, QPalette::ColorRole &to, QPalette::ColorRole defFrom,
0094                     QPalette::ColorRole defTo)
0095 {
0096     switch (from) {
0097     case QPalette::WindowText: //0
0098         to = QPalette::Window;
0099         break;
0100     case QPalette::Window: //10
0101         to = QPalette::WindowText;
0102         break;
0103     case QPalette::Base: //9
0104         to = QPalette::Text;
0105         break;
0106     case QPalette::Text: //6
0107         to = QPalette::Base;
0108         break;
0109     case QPalette::Button: //1
0110         to = QPalette::ButtonText;
0111         break;
0112     case QPalette::ButtonText: //8
0113         to = QPalette::Button;
0114         break;
0115     case QPalette::Highlight: //12
0116         to = QPalette::HighlightedText;
0117         break;
0118     case QPalette::HighlightedText: //13
0119         to = QPalette::Highlight;
0120         break;
0121     default:
0122         from = defFrom;
0123         to = defTo;
0124         return false;
0125     }
0126     return true;
0127 }
0128 
0129 QColor
0130 Colors::emphasize(const QColor &c, int value)
0131 {
0132     int h, s, v, a;
0133     QColor ret;
0134     c.getHsv(&h, &s, &v, &a);
0135     if (v < 75 + value) {
0136         ret.setHsv(h, s, CLAMP(85 + value, 85, 255), a);
0137         return ret;
0138     }
0139     if (v > 200) {
0140         if (s > 30) {
0141             h -= 5;
0142             if (h < 0) {
0143                 h = 360 + h;
0144             }
0145             s = (s << 3) / 9;
0146             v += value;
0147             ret.setHsv(h, CLAMP(s, 30, 255), CLAMP(v, 0, 255), a);
0148             return ret;
0149         }
0150         if (v > 230) {
0151             ret.setHsv(h, s, CLAMP(v - value, 0, 255), a);
0152             return ret;
0153         }
0154     }
0155     if (v > 128) {
0156         ret.setHsv(h, s, CLAMP(v + value, 0, 255), a);
0157     }
0158     else {
0159         ret.setHsv(h, s, CLAMP(v - value, 0, 255), a);
0160     }
0161     return ret;
0162 }
0163 
0164 bool
0165 Colors::haveContrast(const QColor &a, const QColor &b)
0166 {
0167     int ar, ag, ab, br, bg, bb;
0168     a.getRgb(&ar, &ag, &ab);
0169     b.getRgb(&br, &bg, &bb);
0170 
0171     int diff = (299 * (ar - br) + 587 * (ag - bg) + 114 * (ab - bb));
0172 
0173     if (qAbs(diff) < 91001) {
0174         return false;
0175     }
0176 
0177     diff = qMax(ar, br) + qMax(ag, bg) + qMax(ab, bb)
0178            - (qMin(ar, br) + qMin(ag, bg) + qMin(ab, bb));
0179 
0180     return (diff > 300);
0181 }
0182 
0183 QColor
0184 Colors::light(const QColor &c, int value)
0185 {
0186     int h, s, v, a;
0187     c.getHsv(&h, &s, &v, &a);
0188     QColor ret;
0189     if (v < 255 - value) {
0190         ret.setHsv(h, s, CLAMP(v + value, 0, 255), a); //value could be negative
0191         return ret;
0192     }
0193     // psychovisual uplightning, i.e. shift hue and lower saturation
0194     if (s > 30) {
0195         h -= (value * 5 / 20);
0196         if (h < 0) {
0197             h = 400 + h;
0198         }
0199         s = CLAMP((s << 3) / 9, 30, 255);
0200         ret.setHsv(h, s, 255, a);
0201         return ret;
0202     }
0203     else { // hue shifting has no sense, half saturation (btw, white won't get brighter :)
0204         ret.setHsv(h, s >> 1, 255, a);
0205     }
0206     return ret;
0207 }
0208 
0209 QColor
0210 Colors::mid(const QColor &c1, const QColor &c2, int w1, int w2)
0211 {
0212     int sum = (w1 + w2);
0213     if (!sum) {
0214         return Qt::black;
0215     }
0216 
0217     int r, g, b, a;
0218 #if 0
0219     QColor c1 = oc1;
0220     b = value(c1);
0221     if (b < 70) {
0222         c1.getHsv(&r, &g, &b, &a);
0223         c1.setHsv(r, g, 70, a);
0224     }
0225 #endif
0226     r = (w1 * c1.red() + w2 * c2.red()) / sum;
0227     r = CLAMP(r, 0, 255);
0228     g = (w1 * c1.green() + w2 * c2.green()) / sum;
0229     g = CLAMP(g, 0, 255);
0230     b = (w1 * c1.blue() + w2 * c2.blue()) / sum;
0231     b = CLAMP(b, 0, 255);
0232     a = (w1 * c1.alpha() + w2 * c2.alpha()) / sum;
0233     a = CLAMP(a, 0, 255);
0234     return QColor(r, g, b, a);
0235 }
0236 
0237 int
0238 Colors::value(const QColor &c)
0239 {
0240     int v = c.red();
0241     if (c.green() > v) {
0242         v = c.green();
0243     }
0244     if (c.blue() > v) {
0245         v = c.blue();
0246     }
0247     return v;
0248 }