Skip to content

Commit 0812be9

Browse files
committed
Properly implement alpha channels
1 parent ea05b2a commit 0812be9

File tree

2 files changed

+71
-11
lines changed

2 files changed

+71
-11
lines changed

webapp/src/Twig/TwigExtension.php

Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1155,6 +1155,57 @@ public function fileTypeIcon(string $type): string
11551155
return 'fas fa-file-' . $iconName;
11561156
}
11571157

1158+
private function relativeLuminance(string $rgb): float
1159+
{
1160+
// See https://en.wikipedia.org/wiki/Relative_luminance
1161+
[$r, $g, $b, $a] = Utils::parseHexColor($rgb);
1162+
1163+
[$lr, $lg, $lb] = [
1164+
pow($r / 255, 2.4),
1165+
pow($g / 255, 2.4),
1166+
pow($b / 255, 2.4),
1167+
];
1168+
1169+
return 0.2126 * $lr + 0.7152 * $lg + 0.0722 * $lb;
1170+
}
1171+
1172+
private function apcaContrast(string $fgColor, string $bgColor): float
1173+
{
1174+
// Based on WCAG 3.x (https://www.w3.org/TR/wcag-3.0/)
1175+
$luminanceForeground = $this->relativeLuminance($fgColor);
1176+
$luminanceBackground = $this->relativeLuminance($bgColor);
1177+
1178+
$contrast = ($luminanceBackground > $luminanceForeground)
1179+
? (pow($luminanceBackground, 0.56) - pow($luminanceForeground, 0.57)) * 1.14
1180+
: (pow($luminanceBackground, 0.65) - pow($luminanceForeground, 0.62)) * 1.14;
1181+
1182+
return round($contrast * 100, 2);
1183+
}
1184+
1185+
/**
1186+
* @return array{string, string}
1187+
*/
1188+
private function hexToForegroundAndBorder(string $rgb): array
1189+
{
1190+
$background = Utils::parseHexColor($rgb);
1191+
1192+
// Pick a border that's a bit darker.
1193+
$darker = $background;
1194+
$darker[0] = max($darker[0] - 64, 0);
1195+
$darker[1] = max($darker[1] - 64, 0);
1196+
$darker[2] = max($darker[2] - 64, 0);
1197+
$darker[3] = max($darker[3] - 64, 0);
1198+
$border = Utils::rgbToHex($darker);
1199+
1200+
// Pick the text color with the biggest absolute contrast.
1201+
$contrastWithWhite = $this->apcaContrast('#ffffff', $rgb);
1202+
$contrastWithBlack = $this->apcaContrast('#000000', $rgb);
1203+
1204+
$foreground = (abs($contrastWithBlack) > abs($contrastWithWhite)) ? '#000000' : '#ffffff';
1205+
1206+
return [$foreground, $border];
1207+
}
1208+
11581209
public function problemBadge(ContestProblem $problem, bool $grayedOut = false): string
11591210
{
11601211
$rgb = Utils::convertToHex($problem->getColor() ?? '#ffffff');

webapp/src/Utils/Utils.php

Lines changed: 20 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -346,25 +346,34 @@ public static function convertToColor(string $hex): ?string
346346
}
347347

348348
/**
349-
* Parse a hex color into it's three RGB values.
349+
* Parse a hex color into it's four RGBA values.
350350
*
351-
* @return array{int, int, int}
351+
* @return array{int, int, int, int}
352352
*/
353353
public static function parseHexColor(string $hex): array
354354
{
355-
// Ignore alpha in hexstrings
356-
if (strlen($hex) === 5) {
357-
$hex = substr($hex, 0, 4);
358-
} else if (strlen($hex) === 9) {
359-
$hex = substr($hex, 0, 7);
355+
// Insert alpha in hexstrings
356+
switch(strlen($hex)) {
357+
case 4:
358+
$hex += 'f';
359+
break;
360+
case 7:
361+
$hex += 'ff';
362+
break;
363+
case: 5:
364+
case: 8:
365+
break;
366+
default:
367+
throw new Exception("Color length of " . strlen($hex) . " not supported.");
360368
}
361369
// Source: https://stackoverflow.com/a/21966100
362-
$length = (strlen($hex) - 1) / 3;
363-
$fact = [17, 1, 0.062272][$length - 1];
370+
$length = (strlen($hex) - 1) / 4;
371+
$fact = [17, 1, 0.062272, 1][$length - 1];
364372
return [
365-
(int)round(hexdec(substr($hex, 1, $length)) * $fact),
366-
(int)round(hexdec(substr($hex, 1 + $length, $length)) * $fact),
373+
(int)round(hexdec(substr($hex, 1, $length)) * $fact),
374+
(int)round(hexdec(substr($hex, 1 + 1 * $length, $length)) * $fact),
367375
(int)round(hexdec(substr($hex, 1 + 2 * $length, $length)) * $fact)
376+
(int)round(hexdec(substr($hex, 1 + 3 * $length, $length)) * $fact)
368377
];
369378
}
370379

0 commit comments

Comments
 (0)