diff --git a/Telegram/SourceFiles/codegen/style/generator.cpp b/Telegram/SourceFiles/codegen/style/generator.cpp index 13a593a6a1..547b12abd3 100644 --- a/Telegram/SourceFiles/codegen/style/generator.cpp +++ b/Telegram/SourceFiles/codegen/style/generator.cpp @@ -28,6 +28,11 @@ namespace { constexpr int kErrorBadIconSize = 861; +const auto kMustBeContrast = std::map{ + { "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\ diff --git a/Telegram/SourceFiles/ui/style/style_core.cpp b/Telegram/SourceFiles/ui/style/style_core.cpp index 287efde111..d9d4a0f230 100644 --- a/Telegram/SourceFiles/ui/style/style_core.cpp +++ b/Telegram/SourceFiles/ui/style/style_core.cpp @@ -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; NeverFreedPointer 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 diff --git a/Telegram/SourceFiles/ui/style/style_core.h b/Telegram/SourceFiles/ui/style/style_core.h index 0e0e6cc592..0ff24a4f35 100644 --- a/Telegram/SourceFiles/ui/style/style_core.h +++ b/Telegram/SourceFiles/ui/style/style_core.h @@ -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();