-
-
Notifications
You must be signed in to change notification settings - Fork 263
/
Copy pathAnsiColorMode.php
106 lines (88 loc) · 3.41 KB
/
AnsiColorMode.php
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
<?php
/*
* This file is part of the Symfony package.
*
* (c) Fabien Potencier <[email protected]>
*
* For the full copyright and license information, please view the LICENSE
* file that was distributed with this source code.
*/
namespace Symfony\Component\Console\Output;
use Symfony\Component\Console\Exception\InvalidArgumentException;
/**
* @author Fabien Potencier <[email protected]>
* @author Julien Boudry <[email protected]>
*/
enum AnsiColorMode
{
/*
* Classical 4-bit Ansi colors, including 8 classical colors and 8 bright color. Output syntax is "ESC[${foreGroundColorcode};${backGroundColorcode}m"
* Must be compatible with all terminals and it's the minimal version supported.
*/
case Ansi4;
/*
* 8-bit Ansi colors (240 different colors + 16 duplicate color codes, ensuring backward compatibility).
* Output syntax is: "ESC[38;5;${foreGroundColorcode};48;5;${backGroundColorcode}m"
* Should be compatible with most terminals.
*/
case Ansi8;
/*
* 24-bit Ansi colors (RGB).
* Output syntax is: "ESC[38;2;${foreGroundColorcodeRed};${foreGroundColorcodeGreen};${foreGroundColorcodeBlue};48;2;${backGroundColorcodeRed};${backGroundColorcodeGreen};${backGroundColorcodeBlue}m"
* May be compatible with many modern terminals.
*/
case Ansi24;
/**
* Converts an RGB hexadecimal color to the corresponding Ansi code.
*/
public function convertFromHexToAnsiColorCode(string $hexColor): string
{
$hexColor = str_replace('#', '', $hexColor);
if (3 === \strlen($hexColor)) {
$hexColor = $hexColor[0].$hexColor[0].$hexColor[1].$hexColor[1].$hexColor[2].$hexColor[2];
}
if (6 !== \strlen($hexColor)) {
throw new InvalidArgumentException(\sprintf('Invalid "#%s" color.', $hexColor));
}
$color = hexdec($hexColor);
$r = ($color >> 16) & 255;
$g = ($color >> 8) & 255;
$b = $color & 255;
return match ($this) {
self::Ansi4 => (string) $this->convertFromRGB($r, $g, $b),
self::Ansi8 => '8;5;'.$this->convertFromRGB($r, $g, $b),
self::Ansi24 => \sprintf('8;2;%d;%d;%d', $r, $g, $b),
};
}
private function convertFromRGB(int $r, int $g, int $b): int
{
return match ($this) {
self::Ansi4 => $this->degradeHexColorToAnsi4($r, $g, $b),
self::Ansi8 => $this->degradeHexColorToAnsi8($r, $g, $b),
default => throw new InvalidArgumentException("RGB cannot be converted to {$this->name}."),
};
}
private function degradeHexColorToAnsi4(int $r, int $g, int $b): int
{
return round($b / 255) << 2 | (round($g / 255) << 1) | round($r / 255);
}
/**
* Inspired from https://github.com/ajalt/colormath/blob/e464e0da1b014976736cf97250063248fc77b8e7/colormath/src/commonMain/kotlin/com/github/ajalt/colormath/model/Ansi256.kt code (MIT license).
*/
private function degradeHexColorToAnsi8(int $r, int $g, int $b): int
{
if ($r === $g && $g === $b) {
if ($r < 8) {
return 16;
}
if ($r > 248) {
return 231;
}
return (int) round(($r - 8) / 247 * 24) + 232;
}
return 16 +
(36 * (int) round($r / 255 * 5)) +
(6 * (int) round($g / 255 * 5)) +
(int) round($b / 255 * 5);
}
}