From 6bcd6638fdbb78b1bce732eb26fa7728d9e7b8ab Mon Sep 17 00:00:00 2001 From: Nicky Gerritsen Date: Fri, 28 Feb 2025 19:37:09 +0000 Subject: [PATCH] Fix contrast color calculation --- webapp/src/Twig/TwigExtension.php | 44 ++++++++++++++++++++----------- 1 file changed, 28 insertions(+), 16 deletions(-) diff --git a/webapp/src/Twig/TwigExtension.php b/webapp/src/Twig/TwigExtension.php index 2ea4b2388b..c994c1d391 100644 --- a/webapp/src/Twig/TwigExtension.php +++ b/webapp/src/Twig/TwigExtension.php @@ -1148,12 +1148,11 @@ public function fileTypeIcon(string $type): string return 'fas fa-file-' . $iconName; } - public function problemBadge(ContestProblem $problem, bool $grayedOut = false): string + /** + * @return array{string, string} + */ + private function hexToForegroundAndBorder(string $rgb): array { - $rgb = Utils::convertToHex($problem->getColor() ?? '#ffffff'); - if ($grayedOut || empty($rgb)) { - $rgb = Utils::convertToHex('whitesmoke'); - } $background = Utils::parseHexColor($rgb); // Pick a border that's a bit darker. @@ -1163,8 +1162,29 @@ public function problemBadge(ContestProblem $problem, bool $grayedOut = false): $darker[2] = max($darker[2] - 64, 0); $border = Utils::rgbToHex($darker); - // Pick the foreground text color based on the background color. - $foreground = ($background[0] + $background[1] + $background[2] > 450) ? '#000000' : '#ffffff'; + [$r, $g, $b] = $background; + + // Calculate relative luminance + $r = ($r / 255 <= 0.03928) ? ($r / 255) / 12.92 : pow(($r / 255 + 0.055) / 1.055, 2.4); + $g = ($g / 255 <= 0.03928) ? ($g / 255) / 12.92 : pow(($g / 255 + 0.055) / 1.055, 2.4); + $b = ($b / 255 <= 0.03928) ? ($b / 255) / 12.92 : pow(($b / 255 + 0.055) / 1.055, 2.4); + + $luminance = 0.2126 * $r + 0.7152 * $g + 0.0722 * $b; + + $foreground = ($luminance > 0.179) ? '#000000' : '#FFFFFF'; + + return [$foreground, $border]; + } + + public function problemBadge(ContestProblem $problem, bool $grayedOut = false): string + { + $rgb = Utils::convertToHex($problem->getColor() ?? '#ffffff'); + if ($grayedOut || empty($rgb)) { + $rgb = Utils::convertToHex('whitesmoke'); + } + + [$foreground, $border] = $this->hexToForegroundAndBorder($rgb); + if ($grayedOut) { $foreground = 'silver'; $border = 'linen'; @@ -1184,17 +1204,9 @@ public function problemBadgeMaybe(ContestProblem $problem, ScoreboardMatrixItem if (!$matrixItem->isCorrect || empty($rgb)) { $rgb = Utils::convertToHex('whitesmoke'); } - $background = Utils::parseHexColor($rgb); - // Pick a border that's a bit darker. - $darker = $background; - $darker[0] = max($darker[0] - 64, 0); - $darker[1] = max($darker[1] - 64, 0); - $darker[2] = max($darker[2] - 64, 0); - $border = Utils::rgbToHex($darker); + [$foreground, $border] = $this->hexToForegroundAndBorder($rgb); - // Pick the foreground text color based on the background color. - $foreground = ($background[0] + $background[1] + $background[2] > 450) ? '#000000' : '#ffffff'; if (!$matrixItem->isCorrect) { $foreground = 'silver'; $border = 'linen';