Code Coverage
 
Lines
Functions and Methods
Classes and Traits
Total
18.75% covered (danger)
18.75%
6 / 32
25.00% covered (danger)
25.00%
1 / 4
CRAP
0.00% covered (danger)
0.00%
0 / 1
Color
18.75% covered (danger)
18.75%
6 / 32
25.00% covered (danger)
25.00%
1 / 4
172.01
0.00% covered (danger)
0.00%
0 / 1
 __construct
100.00% covered (success)
100.00%
1 / 1
100.00% covered (success)
100.00%
1 / 1
1
 toCss
23.81% covered (danger)
23.81%
5 / 21
0.00% covered (danger)
0.00%
0 / 1
16.06
 serializeSpace
0.00% covered (danger)
0.00%
0 / 9
0.00% covered (danger)
0.00%
0 / 1
90
 trim
0.00% covered (danger)
0.00%
0 / 1
0.00% covered (danger)
0.00%
0 / 1
6
1<?php
2
3declare(strict_types=1);
4
5namespace Phpdftk\Css\Value;
6
7/**
8 * Resolved colour value. RGB components are stored as floats in [0, 1] for
9 * uniform handling across colour spaces; integer 0-255 forms get divided at
10 * parse time. The alpha channel is always present and defaults to 1.0.
11 */
12final readonly class Color extends Value
13{
14    public function __construct(
15        public float $r,
16        public float $g,
17        public float $b,
18        public float $a = 1.0,
19        public ColorSpace $space = ColorSpace::sRGB,
20    ) {}
21
22    public function toCss(): string
23    {
24        // For sRGB at full alpha, emit short hex when components are integer-valued.
25        if ($this->space === ColorSpace::sRGB && $this->a === 1.0) {
26            $r = (int) round($this->r * 255);
27            $g = (int) round($this->g * 255);
28            $b = (int) round($this->b * 255);
29            return sprintf('#%02x%02x%02x', $r, $g, $b);
30        }
31        if ($this->space === ColorSpace::sRGB) {
32            return sprintf(
33                'rgba(%d, %d, %d, %s)',
34                (int) round($this->r * 255),
35                (int) round($this->g * 255),
36                (int) round($this->b * 255),
37                self::trim($this->a),
38            );
39        }
40        // Wide-gamut serialise as color(<space> r g b / a).
41        return sprintf(
42            'color(%s %s %s %s%s)',
43            $this->serializeSpace(),
44            self::trim($this->r),
45            self::trim($this->g),
46            self::trim($this->b),
47            $this->a === 1.0 ? '' : ' / ' . self::trim($this->a),
48        );
49    }
50
51    private function serializeSpace(): string
52    {
53        return match ($this->space) {
54            ColorSpace::sRGB => 'srgb',
55            ColorSpace::DisplayP3 => 'display-p3',
56            ColorSpace::A98RGB => 'a98-rgb',
57            ColorSpace::ProPhotoRGB => 'prophoto-rgb',
58            ColorSpace::Rec2020 => 'rec2020',
59            ColorSpace::OKLCH => 'oklch',
60            ColorSpace::Lab => 'lab',
61            ColorSpace::Lch => 'lch',
62        };
63    }
64
65    private static function trim(float $v): string
66    {
67        return fmod($v, 1.0) === 0.0 ? (string) (int) $v : (string) $v;
68    }
69}