Ensure contrast in critical theme parts.

This commit is contained in:
John Preston 2019-09-09 21:35:06 +03:00
parent f7f195eb98
commit 9fd32fc85b
3 changed files with 66 additions and 0 deletions

View File

@ -28,6 +28,11 @@ namespace {
constexpr int kErrorBadIconSize = 861;
const auto kMustBeContrast = std::map<QString, QString>{
{ "dialogsMenuIconFg", "dialogsBg" },
{ "windowBoldFg", "windowBg" },
};
// crc32 hash, taken somewhere from the internet
class Crc32Table {
@ -797,6 +802,15 @@ void palette::finalize() {\n\
auto count = indexInPalette;
auto checksum = hashCrc32(checksumString.constData(), checksumString.size());
source_->stream() << "\n\n";
for (const auto &[over, under] : kMustBeContrast) {
const auto overIndex = paletteIndices_.find(over);
const auto underIndex = paletteIndices_.find(under);
if (overIndex == paletteIndices_.end() || underIndex == paletteIndices_.end()) {
return false;
}
source_->stream() << "\tinternal::EnsureContrast(*data(" << overIndex->second << "), *data(" << underIndex->second << "));\n";
}
source_->stream() << "\
}\n\
\n\

View File

@ -11,6 +11,10 @@ namespace style {
namespace internal {
namespace {
constexpr auto kMinContrastAlpha = 64;
constexpr auto kMinContrastDistance = 64 * 64 * 4;
constexpr auto kContrastDeltaL = 64;
using ModulesList = QList<internal::ModuleBase*>;
NeverFreedPointer<ModulesList> styleModules;
@ -142,5 +146,51 @@ QImage createCircleMask(int size, QColor bg, QColor fg) {
return result;
}
[[nodiscard]] bool GoodForContrast(const QColor &c1, const QColor &c2) {
auto r1 = 0;
auto g1 = 0;
auto b1 = 0;
auto r2 = 0;
auto g2 = 0;
auto b2 = 0;
c1.getRgb(&r1, &g1, &b1);
c2.getRgb(&r2, &g2, &b2);
const auto rMean = (r1 + r2) / 2;
const auto r = r1 - r2;
const auto g = g1 - g2;
const auto b = b1 - b2;
const auto distance = (((512 + rMean) * r * r) >> 8)
+ (4 * g * g)
+ (((767 - rMean) * b * b) >> 8);
return (distance > kMinContrastDistance);
}
void EnsureContrast(ColorData &over, const ColorData &under) {
auto overH = 0;
auto overS = 0;
auto overL = 0;
auto overA = 0;
auto underH = 0;
auto underS = 0;
auto underL = 0;
over.c.getHsl(&overH, &overS, &overL, &overA);
under.c.getHsl(&underH, &underS, &underL);
const auto good = GoodForContrast(over.c, under.c);
if (overA >= kMinContrastAlpha && good) {
return;
}
const auto newA = std::max(overA, kMinContrastAlpha);
const auto newL = (overL > underL && overL + kContrastDeltaL <= 255)
? (overL + kContrastDeltaL)
: (overL < underL && overL - kContrastDeltaL >= 0)
? (overL - kContrastDeltaL)
: (underL > 128)
? (underL - kContrastDeltaL)
: (underL + kContrastDeltaL);
over.c = QColor::fromHsl(overH, overS, newL, newA).toRgb();
over.p = QPen(over.c);
over.b = QBrush(over.c);
}
} // namespace internal
} // namespace style

View File

@ -54,6 +54,8 @@ void unregisterModule(ModuleBase *module);
// This method is implemented in palette.cpp (codegen).
bool setPaletteColor(QLatin1String name, uchar r, uchar g, uchar b, uchar a);
void EnsureContrast(ColorData &over, const ColorData &under);
} // namespace internal
void startManager();