xref: /template/strap/ComboStrap/ColorHsl.php (revision 04fd306c7c155fa133ebb3669986875d65988276)
14cadd4f8SNickeau<?php
24cadd4f8SNickeau/**
34cadd4f8SNickeau * Copyright (c) 2020. ComboStrap, Inc. and its affiliates. All Rights Reserved.
44cadd4f8SNickeau *
54cadd4f8SNickeau * This source code is licensed under the GPL license found in the
64cadd4f8SNickeau * COPYING  file in the root directory of this source tree.
74cadd4f8SNickeau *
84cadd4f8SNickeau * @license  GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html)
94cadd4f8SNickeau * @author   ComboStrap <support@combostrap.com>
104cadd4f8SNickeau *
114cadd4f8SNickeau */
124cadd4f8SNickeau
134cadd4f8SNickeaunamespace ComboStrap;
144cadd4f8SNickeauclass ColorHsl
154cadd4f8SNickeau{
164cadd4f8SNickeau
174cadd4f8SNickeau    const CANONICAL = "color";
184cadd4f8SNickeau    private $hue;
194cadd4f8SNickeau
204cadd4f8SNickeau    private $saturation;
214cadd4f8SNickeau    /**
224cadd4f8SNickeau     * @var float|int
234cadd4f8SNickeau     */
244cadd4f8SNickeau    private $lightness;
254cadd4f8SNickeau
264cadd4f8SNickeau    /**
274cadd4f8SNickeau     * ColorHsl constructor.
284cadd4f8SNickeau     * @param $hue
294cadd4f8SNickeau     * @param $saturation
304cadd4f8SNickeau     * @param float|int $lightness
314cadd4f8SNickeau     */
324cadd4f8SNickeau    public function __construct($hue, $saturation, $lightness)
334cadd4f8SNickeau    {
344cadd4f8SNickeau        $this->hue = $hue;
354cadd4f8SNickeau        $this->saturation = $saturation;
364cadd4f8SNickeau        $this->lightness = $lightness;
374cadd4f8SNickeau    }
384cadd4f8SNickeau
394cadd4f8SNickeau
404cadd4f8SNickeau    public static function createFromChannels(float $hue, float $saturation, float $lightness): ColorHsl
414cadd4f8SNickeau    {
424cadd4f8SNickeau        return new ColorHsl($hue, $saturation, $lightness);
434cadd4f8SNickeau    }
444cadd4f8SNickeau
454cadd4f8SNickeau    public function getLightness()
464cadd4f8SNickeau    {
474cadd4f8SNickeau        return $this->lightness;
484cadd4f8SNickeau    }
494cadd4f8SNickeau
504cadd4f8SNickeau    public function getSaturation()
514cadd4f8SNickeau    {
524cadd4f8SNickeau        return $this->saturation;
534cadd4f8SNickeau    }
544cadd4f8SNickeau
554cadd4f8SNickeau    public function getHue()
564cadd4f8SNickeau    {
574cadd4f8SNickeau        return $this->hue;
584cadd4f8SNickeau    }
594cadd4f8SNickeau
604cadd4f8SNickeau    /**
61*04fd306cSNickeau     * @throws ExceptionCompile
624cadd4f8SNickeau     */
634cadd4f8SNickeau    public function setLightness(int $int): ColorHsl
644cadd4f8SNickeau    {
654cadd4f8SNickeau        if ($int < 0 || $int > 100) {
66*04fd306cSNickeau            throw new ExceptionCompile("Lightness should be between 0 and 100");
674cadd4f8SNickeau        }
684cadd4f8SNickeau        $this->lightness = $int;
694cadd4f8SNickeau        return $this;
704cadd4f8SNickeau    }
714cadd4f8SNickeau
724cadd4f8SNickeau    /**
734cadd4f8SNickeau     * @return ColorRgb Reference:
744cadd4f8SNickeau     *
754cadd4f8SNickeau     * Reference:
764cadd4f8SNickeau     * https://en.wikipedia.org/wiki/HSL_and_HSV#HSL_to_RGB
774cadd4f8SNickeau     * https://gist.github.com/brandonheyer/5254516
78*04fd306cSNickeau     * @throws ExceptionCompile
794cadd4f8SNickeau     */
804cadd4f8SNickeau    function toRgb(): ColorRgb
814cadd4f8SNickeau    {
824cadd4f8SNickeau
834cadd4f8SNickeau        $lightness = $this->lightness / 100;
844cadd4f8SNickeau        $saturation = $this->saturation / 100;
854cadd4f8SNickeau        $hue = $this->hue;
864cadd4f8SNickeau
874cadd4f8SNickeau        $chroma = (1 - abs(2 * $lightness - 1)) * $saturation;
884cadd4f8SNickeau        $x = $chroma * (1 - abs(fmod(($hue / 60), 2) - 1));
894cadd4f8SNickeau        $m = $lightness - ($chroma / 2);
904cadd4f8SNickeau
914cadd4f8SNickeau        if ($hue < 60) {
924cadd4f8SNickeau            $red = $chroma;
934cadd4f8SNickeau            $green = $x;
944cadd4f8SNickeau            $blue = 0;
954cadd4f8SNickeau        } else if ($hue < 120) {
964cadd4f8SNickeau            $red = $x;
974cadd4f8SNickeau            $green = $chroma;
984cadd4f8SNickeau            $blue = 0;
994cadd4f8SNickeau        } else if ($hue < 180) {
1004cadd4f8SNickeau            $red = 0;
1014cadd4f8SNickeau            $green = $chroma;
1024cadd4f8SNickeau            $blue = $x;
1034cadd4f8SNickeau        } else if ($hue < 240) {
1044cadd4f8SNickeau            $red = 0;
1054cadd4f8SNickeau            $green = $x;
1064cadd4f8SNickeau            $blue = $chroma;
1074cadd4f8SNickeau        } else if ($hue < 300) {
1084cadd4f8SNickeau            $red = $x;
1094cadd4f8SNickeau            $green = 0;
1104cadd4f8SNickeau            $blue = $chroma;
1114cadd4f8SNickeau        } else {
1124cadd4f8SNickeau            $red = $chroma;
1134cadd4f8SNickeau            $green = 0;
1144cadd4f8SNickeau            $blue = $x;
1154cadd4f8SNickeau        }
1164cadd4f8SNickeau
1174cadd4f8SNickeau        $red = ($red + $m) * 255;
1184cadd4f8SNickeau        $green = ($green + $m) * 255;
1194cadd4f8SNickeau        $blue = ($blue + $m) * 255;
1204cadd4f8SNickeau
1214cadd4f8SNickeau        /**
1224cadd4f8SNickeau         * To the closest integer
1234cadd4f8SNickeau         */
1244cadd4f8SNickeau        try {
1254cadd4f8SNickeau            return ColorRgb::createFromRgbChannels(
1264cadd4f8SNickeau                intval(round($red)),
1274cadd4f8SNickeau                intval(round($green)),
1284cadd4f8SNickeau                intval(round($blue))
1294cadd4f8SNickeau            );
130*04fd306cSNickeau        } catch (ExceptionCompile $e) {
1314cadd4f8SNickeau            // should not happen but yeah, who knows
1324cadd4f8SNickeau            // and because there is no safe constructor, no safe default, we throw
1334cadd4f8SNickeau            $message = "Error while creating the rgb color from the hsl ($this)";
134*04fd306cSNickeau            throw new ExceptionCompile($message, self::CANONICAL, 0, $e);
1354cadd4f8SNickeau        }
1364cadd4f8SNickeau
1374cadd4f8SNickeau    }
1384cadd4f8SNickeau
1394cadd4f8SNickeau    /**
140*04fd306cSNickeau     * @throws ExceptionCompile
1414cadd4f8SNickeau     */
1424cadd4f8SNickeau    public function setSaturation(int $saturation): ColorHsl
1434cadd4f8SNickeau    {
1444cadd4f8SNickeau        if ($saturation < 0 || $saturation > 100) {
145*04fd306cSNickeau            throw new ExceptionCompile("Saturation should be between 0 and 100");
1464cadd4f8SNickeau        }
1474cadd4f8SNickeau        $this->saturation = $saturation;
1484cadd4f8SNickeau        return $this;
1494cadd4f8SNickeau    }
1504cadd4f8SNickeau
1514cadd4f8SNickeau    public function toComplement(): ColorHsl
1524cadd4f8SNickeau    {
1534cadd4f8SNickeau        // Adjust Hue 180 degrees
1544cadd4f8SNickeau        $this->hue += ($this->hue > 180) ? -180 : 180;
1554cadd4f8SNickeau        return $this;
1564cadd4f8SNickeau    }
1574cadd4f8SNickeau
1584cadd4f8SNickeau    public function __toString()
1594cadd4f8SNickeau    {
1604cadd4f8SNickeau        return "hsl($this->hue deg, $this->saturation%, $this->lightness%)";
1614cadd4f8SNickeau    }
1624cadd4f8SNickeau
1634cadd4f8SNickeau    public function darken(int $lightness = 5): ColorHsl
1644cadd4f8SNickeau    {
1654cadd4f8SNickeau        if ($this->lightness - $lightness < 0) {
1664cadd4f8SNickeau            $this->lightness = 0;
1674cadd4f8SNickeau        }
1684cadd4f8SNickeau        $this->lightness -= $lightness;
1694cadd4f8SNickeau        return $this;
1704cadd4f8SNickeau    }
1714cadd4f8SNickeau
1724cadd4f8SNickeau    /**
173*04fd306cSNickeau     * @throws ExceptionCompile
1744cadd4f8SNickeau     */
1754cadd4f8SNickeau    public function diff($color): array
1764cadd4f8SNickeau    {
1774cadd4f8SNickeau        if ($color instanceof ColorRgb) {
1784cadd4f8SNickeau            $color = $color->toHsl();
1794cadd4f8SNickeau        }
1804cadd4f8SNickeau
1814cadd4f8SNickeau        return [
1824cadd4f8SNickeau            "h" => round($this->getHue() - $color->getHue(), 2),
1834cadd4f8SNickeau            "s" => round($this->getSaturation() - $color->getSaturation(), 2),
1844cadd4f8SNickeau            "l" => round($this->getLightness() - $color->getLightness(), 2),
1854cadd4f8SNickeau        ];
1864cadd4f8SNickeau    }
1874cadd4f8SNickeau
1884cadd4f8SNickeau
1894cadd4f8SNickeau}
190