raw = ($raw ?? 0) & 0x7FFFFFFF; } public static function none(): self { return new Colour(self::FLAG_INHERIT); } public static function fromRgb(int $red, int $green, int $blue): self { $raw = (($red & 0xFF) << 16) | (($green & 0xFF) << 8) | ($blue & 0xFF); return new Colour($raw); } public static function fromHex(string $hex): self { if($hex[0] === '#') $hex = mb_substr($hex, 1); if(!ctype_xdigit($hex)) throw new InvalidArgumentException('Argument contains invalid characters.'); $length = mb_strlen($hex); if($length === 3) { $hex = $hex[0] . $hex[0] . $hex[1] . $hex[1] . $hex[2] . $hex[2]; } elseif($length !== 6) { throw new InvalidArgumentException('Argument is not a hex string.'); } return new Colour(hexdec($hex)); } public function getRaw(): int { return $this->raw; } public function getInherit(): bool { return ($this->getRaw() & self::FLAG_INHERIT) > 0; } public function getRed(): int { return ($this->getRaw() & 0xFF0000) >> 16; } public function getGreen(): int { return ($this->getRaw() & 0xFF00) >> 8; } public function getBlue(): int { return ($this->getRaw() & 0xFF); } public function getLuminance(): float { return self::LUMINANCE_WEIGHT_RED * $this->getRed() + self::LUMINANCE_WEIGHT_GREEN * $this->getGreen() + self::LUMINANCE_WEIGHT_BLUE * $this->getBlue(); } public function getHex(): string { return str_pad(dechex($this->getRaw() & 0xFFFFFF), 6, '0', STR_PAD_LEFT); } public function getCSS(): string { if($this->getInherit()) return 'inherit'; return '#' . $this->getHex(); } public function extractCSSContract( string $dark = 'dark', string $light = 'light', bool $inheritIsDark = true ): string { if($this->getInherit()) return $inheritIsDark ? $dark : $light; return $this->getLuminance() > self::READABILITY_THRESHOLD ? $dark : $light; } public function __toString() { return $this->getCSS(); } }