1*4cadd4f8SNickeau<?php 2*4cadd4f8SNickeau/** 3*4cadd4f8SNickeau * Copyright (c) 2020. ComboStrap, Inc. and its affiliates. All Rights Reserved. 4*4cadd4f8SNickeau * 5*4cadd4f8SNickeau * This source code is licensed under the GPL license found in the 6*4cadd4f8SNickeau * COPYING file in the root directory of this source tree. 7*4cadd4f8SNickeau * 8*4cadd4f8SNickeau * @license GPL 3 (https://www.gnu.org/licenses/gpl-3.0.en.html) 9*4cadd4f8SNickeau * @author ComboStrap <support@combostrap.com> 10*4cadd4f8SNickeau * 11*4cadd4f8SNickeau */ 12*4cadd4f8SNickeau 13*4cadd4f8SNickeaunamespace ComboStrap; 14*4cadd4f8SNickeau 15*4cadd4f8SNickeau 16*4cadd4f8SNickeauuse dokuwiki\StyleUtils; 17*4cadd4f8SNickeau 18*4cadd4f8SNickeauclass ColorRgb 19*4cadd4f8SNickeau{ 20*4cadd4f8SNickeau 21*4cadd4f8SNickeau const COLOR = "color"; 22*4cadd4f8SNickeau 23*4cadd4f8SNickeau const BORDER_COLOR = "border-color"; 24*4cadd4f8SNickeau 25*4cadd4f8SNickeau const BOOTSTRAP_COLORS = array( 26*4cadd4f8SNickeau 'blue', 27*4cadd4f8SNickeau 'indigo', 28*4cadd4f8SNickeau 'purple', 29*4cadd4f8SNickeau 'pink', 30*4cadd4f8SNickeau 'red', 31*4cadd4f8SNickeau 'orange', 32*4cadd4f8SNickeau 'yellow', 33*4cadd4f8SNickeau 'green', 34*4cadd4f8SNickeau 'teal', 35*4cadd4f8SNickeau 'cyan', 36*4cadd4f8SNickeau //'white', css value for now otherwise we don't know the value when tinting 37*4cadd4f8SNickeau //'gray', css value for now otherwise we don't know the value when tinting 38*4cadd4f8SNickeau 'gray-dark', 39*4cadd4f8SNickeau self::PRIMARY_VALUE, 40*4cadd4f8SNickeau self::SECONDARY_VALUE, 41*4cadd4f8SNickeau 'success', 42*4cadd4f8SNickeau 'info', 43*4cadd4f8SNickeau 'warning', 44*4cadd4f8SNickeau 'danger', 45*4cadd4f8SNickeau 'light', 46*4cadd4f8SNickeau 'dark' 47*4cadd4f8SNickeau ); 48*4cadd4f8SNickeau /** 49*4cadd4f8SNickeau * https://drafts.csswg.org/css-color/#color-keywords 50*4cadd4f8SNickeau */ 51*4cadd4f8SNickeau const CSS_COLOR_NAMES = array( 52*4cadd4f8SNickeau 'aliceblue' => '#F0F8FF', 53*4cadd4f8SNickeau 'antiquewhite' => '#FAEBD7', 54*4cadd4f8SNickeau 'aqua' => '#00FFFF', 55*4cadd4f8SNickeau 'aquamarine' => '#7FFFD4', 56*4cadd4f8SNickeau 'azure' => '#F0FFFF', 57*4cadd4f8SNickeau 'beige' => '#F5F5DC', 58*4cadd4f8SNickeau 'bisque' => '#FFE4C4', 59*4cadd4f8SNickeau 'black' => '#000000', 60*4cadd4f8SNickeau 'blanchedalmond' => '#FFEBCD', 61*4cadd4f8SNickeau 'blue' => '#0000FF', 62*4cadd4f8SNickeau 'blueviolet' => '#8A2BE2', 63*4cadd4f8SNickeau 'brown' => '#A52A2A', 64*4cadd4f8SNickeau 'burlywood' => '#DEB887', 65*4cadd4f8SNickeau 'cadetblue' => '#5F9EA0', 66*4cadd4f8SNickeau 'chartreuse' => '#7FFF00', 67*4cadd4f8SNickeau 'chocolate' => '#D2691E', 68*4cadd4f8SNickeau 'coral' => '#FF7F50', 69*4cadd4f8SNickeau 'cornflowerblue' => '#6495ED', 70*4cadd4f8SNickeau 'cornsilk' => '#FFF8DC', 71*4cadd4f8SNickeau 'crimson' => '#DC143C', 72*4cadd4f8SNickeau 'cyan' => '#00FFFF', 73*4cadd4f8SNickeau 'darkblue' => '#00008B', 74*4cadd4f8SNickeau 'darkcyan' => '#008B8B', 75*4cadd4f8SNickeau 'darkgoldenrod' => '#B8860B', 76*4cadd4f8SNickeau 'darkgray' => '#A9A9A9', 77*4cadd4f8SNickeau 'darkgreen' => '#006400', 78*4cadd4f8SNickeau 'darkgrey' => '#A9A9A9', 79*4cadd4f8SNickeau 'darkkhaki' => '#BDB76B', 80*4cadd4f8SNickeau 'darkmagenta' => '#8B008B', 81*4cadd4f8SNickeau 'darkolivegreen' => '#556B2F', 82*4cadd4f8SNickeau 'darkorange' => '#FF8C00', 83*4cadd4f8SNickeau 'darkorchid' => '#9932CC', 84*4cadd4f8SNickeau 'darkred' => '#8B0000', 85*4cadd4f8SNickeau 'darksalmon' => '#E9967A', 86*4cadd4f8SNickeau 'darkseagreen' => '#8FBC8F', 87*4cadd4f8SNickeau 'darkslateblue' => '#483D8B', 88*4cadd4f8SNickeau 'darkslategray' => '#2F4F4F', 89*4cadd4f8SNickeau 'darkslategrey' => '#2F4F4F', 90*4cadd4f8SNickeau 'darkturquoise' => '#00CED1', 91*4cadd4f8SNickeau 'darkviolet' => '#9400D3', 92*4cadd4f8SNickeau 'deeppink' => '#FF1493', 93*4cadd4f8SNickeau 'deepskyblue' => '#00BFFF', 94*4cadd4f8SNickeau 'dimgray' => '#696969', 95*4cadd4f8SNickeau 'dimgrey' => '#696969', 96*4cadd4f8SNickeau 'dodgerblue' => '#1E90FF', 97*4cadd4f8SNickeau 'firebrick' => '#B22222', 98*4cadd4f8SNickeau 'floralwhite' => '#FFFAF0', 99*4cadd4f8SNickeau 'forestgreen' => '#228B22', 100*4cadd4f8SNickeau 'fuchsia' => '#FF00FF', 101*4cadd4f8SNickeau 'gainsboro' => '#DCDCDC', 102*4cadd4f8SNickeau 'ghostwhite' => '#F8F8FF', 103*4cadd4f8SNickeau 'gold' => '#FFD700', 104*4cadd4f8SNickeau 'goldenrod' => '#DAA520', 105*4cadd4f8SNickeau 'gray' => '#808080', 106*4cadd4f8SNickeau 'green' => '#008000', 107*4cadd4f8SNickeau 'greenyellow' => '#ADFF2F', 108*4cadd4f8SNickeau 'grey' => '#808080', 109*4cadd4f8SNickeau 'honeydew' => '#F0FFF0', 110*4cadd4f8SNickeau 'hotpink' => '#FF69B4', 111*4cadd4f8SNickeau 'indianred' => '#CD5C5C', 112*4cadd4f8SNickeau 'indigo' => '#4B0082', 113*4cadd4f8SNickeau 'ivory' => '#FFFFF0', 114*4cadd4f8SNickeau 'khaki' => '#F0E68C', 115*4cadd4f8SNickeau 'lavender' => '#E6E6FA', 116*4cadd4f8SNickeau 'lavenderblush' => '#FFF0F5', 117*4cadd4f8SNickeau 'lawngreen' => '#7CFC00', 118*4cadd4f8SNickeau 'lemonchiffon' => '#FFFACD', 119*4cadd4f8SNickeau 'lightblue' => '#ADD8E6', 120*4cadd4f8SNickeau 'lightcoral' => '#F08080', 121*4cadd4f8SNickeau 'lightcyan' => '#E0FFFF', 122*4cadd4f8SNickeau 'lightgoldenrodyellow' => '#FAFAD2', 123*4cadd4f8SNickeau 'lightgray' => '#D3D3D3', 124*4cadd4f8SNickeau 'lightgreen' => '#90EE90', 125*4cadd4f8SNickeau 'lightgrey' => '#D3D3D3', 126*4cadd4f8SNickeau 'lightpink' => '#FFB6C1', 127*4cadd4f8SNickeau 'lightsalmon' => '#FFA07A', 128*4cadd4f8SNickeau 'lightseagreen' => '#20B2AA', 129*4cadd4f8SNickeau 'lightskyblue' => '#87CEFA', 130*4cadd4f8SNickeau 'lightslategray' => '#778899', 131*4cadd4f8SNickeau 'lightslategrey' => '#778899', 132*4cadd4f8SNickeau 'lightsteelblue' => '#B0C4DE', 133*4cadd4f8SNickeau 'lightyellow' => '#FFFFE0', 134*4cadd4f8SNickeau 'lime' => '#00FF00', 135*4cadd4f8SNickeau 'limegreen' => '#32CD32', 136*4cadd4f8SNickeau 'linen' => '#FAF0E6', 137*4cadd4f8SNickeau 'magenta' => '#FF00FF', 138*4cadd4f8SNickeau 'maroon' => '#800000', 139*4cadd4f8SNickeau 'mediumaquamarine' => '#66CDAA', 140*4cadd4f8SNickeau 'mediumblue' => '#0000CD', 141*4cadd4f8SNickeau 'mediumorchid' => '#BA55D3', 142*4cadd4f8SNickeau 'mediumpurple' => '#9370DB', 143*4cadd4f8SNickeau 'mediumseagreen' => '#3CB371', 144*4cadd4f8SNickeau 'mediumslateblue' => '#7B68EE', 145*4cadd4f8SNickeau 'mediumspringgreen' => '#00FA9A', 146*4cadd4f8SNickeau 'mediumturquoise' => '#48D1CC', 147*4cadd4f8SNickeau 'mediumvioletred' => '#C71585', 148*4cadd4f8SNickeau 'midnightblue' => '#191970', 149*4cadd4f8SNickeau 'mintcream' => '#F5FFFA', 150*4cadd4f8SNickeau 'mistyrose' => '#FFE4E1', 151*4cadd4f8SNickeau 'moccasin' => '#FFE4B5', 152*4cadd4f8SNickeau 'navajowhite' => '#FFDEAD', 153*4cadd4f8SNickeau 'navy' => '#000080', 154*4cadd4f8SNickeau 'oldlace' => '#FDF5E6', 155*4cadd4f8SNickeau 'olive' => '#808000', 156*4cadd4f8SNickeau 'olivedrab' => '#6B8E23', 157*4cadd4f8SNickeau 'orange' => '#FFA500', 158*4cadd4f8SNickeau 'orangered' => '#FF4500', 159*4cadd4f8SNickeau 'orchid' => '#DA70D6', 160*4cadd4f8SNickeau 'palegoldenrod' => '#EEE8AA', 161*4cadd4f8SNickeau 'palegreen' => '#98FB98', 162*4cadd4f8SNickeau 'paleturquoise' => '#AFEEEE', 163*4cadd4f8SNickeau 'palevioletred' => '#DB7093', 164*4cadd4f8SNickeau 'papayawhip' => '#FFEFD5', 165*4cadd4f8SNickeau 'peachpuff' => '#FFDAB9', 166*4cadd4f8SNickeau 'peru' => '#CD853F', 167*4cadd4f8SNickeau 'pink' => '#FFC0CB', 168*4cadd4f8SNickeau 'plum' => '#DDA0DD', 169*4cadd4f8SNickeau 'powderblue' => '#B0E0E6', 170*4cadd4f8SNickeau 'purple' => '#800080', 171*4cadd4f8SNickeau 'rebeccapurple' => '#663399', 172*4cadd4f8SNickeau 'red' => '#FF0000', 173*4cadd4f8SNickeau 'rosybrown' => '#BC8F8F', 174*4cadd4f8SNickeau 'royalblue' => '#4169E1', 175*4cadd4f8SNickeau 'saddlebrown' => '#8B4513', 176*4cadd4f8SNickeau 'salmon' => '#FA8072', 177*4cadd4f8SNickeau 'sandybrown' => '#F4A460', 178*4cadd4f8SNickeau 'seagreen' => '#2E8B57', 179*4cadd4f8SNickeau 'seashell' => '#FFF5EE', 180*4cadd4f8SNickeau 'sienna' => '#A0522D', 181*4cadd4f8SNickeau 'silver' => '#C0C0C0', 182*4cadd4f8SNickeau 'skyblue' => '#87CEEB', 183*4cadd4f8SNickeau 'slateblue' => '#6A5ACD', 184*4cadd4f8SNickeau 'slategray' => '#708090', 185*4cadd4f8SNickeau 'slategrey' => '#708090', 186*4cadd4f8SNickeau 'snow' => '#FFFAFA', 187*4cadd4f8SNickeau 'springgreen' => '#00FF7F', 188*4cadd4f8SNickeau 'steelblue' => '#4682B4', 189*4cadd4f8SNickeau 'tan' => '#D2B48C', 190*4cadd4f8SNickeau 'teal' => '#008080', 191*4cadd4f8SNickeau 'tip' => self::TIP_COLOR, 192*4cadd4f8SNickeau 'thistle' => '#D8BFD8', 193*4cadd4f8SNickeau 'tomato' => '#FF6347', 194*4cadd4f8SNickeau 'turquoise' => '#40E0D0', 195*4cadd4f8SNickeau 'violet' => '#EE82EE', 196*4cadd4f8SNickeau 'wheat' => '#F5DEB3', 197*4cadd4f8SNickeau 'white' => '#FFFFFF', 198*4cadd4f8SNickeau 'whitesmoke' => '#F5F5F5', 199*4cadd4f8SNickeau 'yellow' => '#FFFF00', 200*4cadd4f8SNickeau 'yellowgreen' => '#9ACD32' 201*4cadd4f8SNickeau ); 202*4cadd4f8SNickeau 203*4cadd4f8SNickeau /** 204*4cadd4f8SNickeau * Branding colors 205*4cadd4f8SNickeau */ 206*4cadd4f8SNickeau const PRIMARY_VALUE = "primary"; 207*4cadd4f8SNickeau const SECONDARY_VALUE = "secondary"; 208*4cadd4f8SNickeau 209*4cadd4f8SNickeau const PRIMARY_COLOR_CONF = "primaryColor"; 210*4cadd4f8SNickeau const SECONDARY_COLOR_CONF = "secondaryColor"; 211*4cadd4f8SNickeau const BRANDING_COLOR_CANONICAL = "branding-colors"; 212*4cadd4f8SNickeau public const BACKGROUND_COLOR = "background-color"; 213*4cadd4f8SNickeau 214*4cadd4f8SNickeau // the value is a bootstrap name 215*4cadd4f8SNickeau const VALUE_TYPE_BOOTSTRAP_NAME = "bootstrap"; 216*4cadd4f8SNickeau const VALUE_TYPE_RGB_HEX = "rgb-hex"; 217*4cadd4f8SNickeau const VALUE_TYPE_RGB_ARRAY = "rgb-array"; 218*4cadd4f8SNickeau const VALUE_TYPE_RESET = "reset"; 219*4cadd4f8SNickeau const VALUE_TYPE_CSS_NAME = "css-name"; 220*4cadd4f8SNickeau const VALUE_TYPE_UNKNOWN_NAME = "unknown-name"; 221*4cadd4f8SNickeau 222*4cadd4f8SNickeau /** 223*4cadd4f8SNickeau * Do we set also the branding color on 224*4cadd4f8SNickeau * other elements ? 225*4cadd4f8SNickeau */ 226*4cadd4f8SNickeau const BRANDING_COLOR_INHERITANCE_ENABLE_CONF = "brandingColorInheritanceEnable"; 227*4cadd4f8SNickeau const BRANDING_COLOR_INHERITANCE_ENABLE_CONF_DEFAULT = 1; 228*4cadd4f8SNickeau 229*4cadd4f8SNickeau /** 230*4cadd4f8SNickeau * Minimum recommended ratio by the w3c 231*4cadd4f8SNickeau */ 232*4cadd4f8SNickeau const MINIMUM_CONTRAST_RATIO = 5; 233*4cadd4f8SNickeau const WHITE = "white"; 234*4cadd4f8SNickeau const TIP_COLOR = "#ffee33"; 235*4cadd4f8SNickeau const CURRENT_COLOR = "currentColor"; 236*4cadd4f8SNickeau 237*4cadd4f8SNickeau /** 238*4cadd4f8SNickeau * @var array 239*4cadd4f8SNickeau */ 240*4cadd4f8SNickeau private static $dokuWikiStyles; 241*4cadd4f8SNickeau 242*4cadd4f8SNickeau /** 243*4cadd4f8SNickeau * @var int 244*4cadd4f8SNickeau */ 245*4cadd4f8SNickeau private $red; 246*4cadd4f8SNickeau /** 247*4cadd4f8SNickeau * @var mixed 248*4cadd4f8SNickeau */ 249*4cadd4f8SNickeau private $green; 250*4cadd4f8SNickeau /** 251*4cadd4f8SNickeau * @var mixed 252*4cadd4f8SNickeau */ 253*4cadd4f8SNickeau private $blue; 254*4cadd4f8SNickeau /** 255*4cadd4f8SNickeau * @var string 256*4cadd4f8SNickeau */ 257*4cadd4f8SNickeau private $nameType = self::VALUE_TYPE_UNKNOWN_NAME; 258*4cadd4f8SNickeau /** 259*4cadd4f8SNickeau * The color name 260*4cadd4f8SNickeau * It can be: 261*4cadd4f8SNickeau * * a bootstrap 262*4cadd4f8SNickeau * * a css name 263*4cadd4f8SNickeau * * or `reset` 264*4cadd4f8SNickeau * @var null|string 265*4cadd4f8SNickeau */ 266*4cadd4f8SNickeau private $name; 267*4cadd4f8SNickeau private $transparency; 268*4cadd4f8SNickeau 269*4cadd4f8SNickeau 270*4cadd4f8SNickeau /** 271*4cadd4f8SNickeau * The styles of the dokuwiki systems 272*4cadd4f8SNickeau * @return array 273*4cadd4f8SNickeau */ 274*4cadd4f8SNickeau public static function getDokuWikiStyles(): array 275*4cadd4f8SNickeau { 276*4cadd4f8SNickeau if (self::$dokuWikiStyles === null) { 277*4cadd4f8SNickeau self::$dokuWikiStyles = (new StyleUtils())->cssStyleini(); 278*4cadd4f8SNickeau } 279*4cadd4f8SNickeau return self::$dokuWikiStyles; 280*4cadd4f8SNickeau 281*4cadd4f8SNickeau } 282*4cadd4f8SNickeau 283*4cadd4f8SNickeau /** 284*4cadd4f8SNickeau * Same round instructions than SCSS to be able to do the test 285*4cadd4f8SNickeau * have value as bootstrap 286*4cadd4f8SNickeau * @param float $value 287*4cadd4f8SNickeau * @return float 288*4cadd4f8SNickeau */ 289*4cadd4f8SNickeau private static function round(float $value): float 290*4cadd4f8SNickeau { 291*4cadd4f8SNickeau $rest = fmod($value, 1); 292*4cadd4f8SNickeau if ($rest < 0.5) { 293*4cadd4f8SNickeau return round($value, 0, PHP_ROUND_HALF_DOWN); 294*4cadd4f8SNickeau } else { 295*4cadd4f8SNickeau return round($value, 0, PHP_ROUND_HALF_UP); 296*4cadd4f8SNickeau } 297*4cadd4f8SNickeau } 298*4cadd4f8SNickeau 299*4cadd4f8SNickeau /** 300*4cadd4f8SNickeau * @throws ExceptionCombo 301*4cadd4f8SNickeau */ 302*4cadd4f8SNickeau public static function createFromRgbChannels(int $red, int $green, int $blue): ColorRgb 303*4cadd4f8SNickeau { 304*4cadd4f8SNickeau return (new ColorRgb()) 305*4cadd4f8SNickeau ->setRgbChannels([$red, $green, $blue]); 306*4cadd4f8SNickeau } 307*4cadd4f8SNickeau 308*4cadd4f8SNickeau /** 309*4cadd4f8SNickeau * Utility function to get white 310*4cadd4f8SNickeau * @throws ExceptionCombo 311*4cadd4f8SNickeau */ 312*4cadd4f8SNickeau public static function getWhite(): ColorRgb 313*4cadd4f8SNickeau { 314*4cadd4f8SNickeau 315*4cadd4f8SNickeau return (new ColorRgb()) 316*4cadd4f8SNickeau ->setName("white") 317*4cadd4f8SNickeau ->setRgbChannels([255, 255, 255]) 318*4cadd4f8SNickeau ->setNameType(self::VALUE_TYPE_CSS_NAME); 319*4cadd4f8SNickeau 320*4cadd4f8SNickeau } 321*4cadd4f8SNickeau 322*4cadd4f8SNickeau /** 323*4cadd4f8SNickeau * Utility function to get black 324*4cadd4f8SNickeau * @throws ExceptionCombo 325*4cadd4f8SNickeau */ 326*4cadd4f8SNickeau public static function getBlack(): ColorRgb 327*4cadd4f8SNickeau { 328*4cadd4f8SNickeau 329*4cadd4f8SNickeau return (new ColorRgb()) 330*4cadd4f8SNickeau ->setName("black") 331*4cadd4f8SNickeau ->setRgbChannels([0, 0, 0]) 332*4cadd4f8SNickeau ->setNameType(self::VALUE_TYPE_CSS_NAME); 333*4cadd4f8SNickeau 334*4cadd4f8SNickeau } 335*4cadd4f8SNickeau 336*4cadd4f8SNickeau /** 337*4cadd4f8SNickeau * @throws ExceptionCombo 338*4cadd4f8SNickeau */ 339*4cadd4f8SNickeau public static function createFromHex(string $color) 340*4cadd4f8SNickeau { 341*4cadd4f8SNickeau 342*4cadd4f8SNickeau return (new ColorRgb()) 343*4cadd4f8SNickeau ->setHex($color); 344*4cadd4f8SNickeau 345*4cadd4f8SNickeau 346*4cadd4f8SNickeau } 347*4cadd4f8SNickeau 348*4cadd4f8SNickeau 349*4cadd4f8SNickeau /** 350*4cadd4f8SNickeau * @return ColorHsl 351*4cadd4f8SNickeau * @throws ExceptionCombo 352*4cadd4f8SNickeau */ 353*4cadd4f8SNickeau public function toHsl(): ColorHsl 354*4cadd4f8SNickeau { 355*4cadd4f8SNickeau 356*4cadd4f8SNickeau if ($this->red === null) { 357*4cadd4f8SNickeau throw new ExceptionCombo("This color ($this) does not have any channel known, we can't transform it to hsl"); 358*4cadd4f8SNickeau } 359*4cadd4f8SNickeau $red = $this->red / 255; 360*4cadd4f8SNickeau $green = $this->green / 255; 361*4cadd4f8SNickeau $blue = $this->blue / 255; 362*4cadd4f8SNickeau 363*4cadd4f8SNickeau $max = max($red, $green, $blue); 364*4cadd4f8SNickeau $min = min($red, $green, $blue); 365*4cadd4f8SNickeau 366*4cadd4f8SNickeau 367*4cadd4f8SNickeau $lightness = ($max + $min) / 2; 368*4cadd4f8SNickeau $d = $max - $min; 369*4cadd4f8SNickeau 370*4cadd4f8SNickeau if ($d == 0) { 371*4cadd4f8SNickeau $hue = $saturation = 0; // achromatic 372*4cadd4f8SNickeau } else { 373*4cadd4f8SNickeau $saturation = $d / (1 - abs(2 * $lightness - 1)); 374*4cadd4f8SNickeau 375*4cadd4f8SNickeau switch ($max) { 376*4cadd4f8SNickeau case $red: 377*4cadd4f8SNickeau $hue = 60 * fmod((($green - $blue) / $d), 6); 378*4cadd4f8SNickeau if ($blue > $green) { 379*4cadd4f8SNickeau $hue += 360; 380*4cadd4f8SNickeau } 381*4cadd4f8SNickeau break; 382*4cadd4f8SNickeau 383*4cadd4f8SNickeau case $green: 384*4cadd4f8SNickeau $hue = 60 * (($blue - $red) / $d + 2); 385*4cadd4f8SNickeau break; 386*4cadd4f8SNickeau 387*4cadd4f8SNickeau default: 388*4cadd4f8SNickeau case $blue: 389*4cadd4f8SNickeau $hue = 60 * (($red - $green) / $d + 4); 390*4cadd4f8SNickeau break; 391*4cadd4f8SNickeau 392*4cadd4f8SNickeau } 393*4cadd4f8SNickeau } 394*4cadd4f8SNickeau 395*4cadd4f8SNickeau /** 396*4cadd4f8SNickeau * No round to get a neat inverse 397*4cadd4f8SNickeau */ 398*4cadd4f8SNickeau 399*4cadd4f8SNickeau return ColorHsl::createFromChannels($hue, $saturation * 100, $lightness * 100); 400*4cadd4f8SNickeau 401*4cadd4f8SNickeau 402*4cadd4f8SNickeau } 403*4cadd4f8SNickeau 404*4cadd4f8SNickeau 405*4cadd4f8SNickeau /** 406*4cadd4f8SNickeau * @param array|string|ColorRgb $color 407*4cadd4f8SNickeau * @param int|null $weight 408*4cadd4f8SNickeau * @return ColorRgb 409*4cadd4f8SNickeau * 410*4cadd4f8SNickeau * 411*4cadd4f8SNickeau * Because Bootstrap uses the mix function of SCSS 412*4cadd4f8SNickeau * https://sass-lang.com/documentation/modules/color#mix 413*4cadd4f8SNickeau * We try to be as clause as possible 414*4cadd4f8SNickeau * 415*4cadd4f8SNickeau * https://gist.github.com/jedfoster/7939513 416*4cadd4f8SNickeau * 417*4cadd4f8SNickeau * This is a linear extrapolation along the segment 418*4cadd4f8SNickeau * @throws ExceptionCombo 419*4cadd4f8SNickeau */ 420*4cadd4f8SNickeau function mix($color, ?int $weight = 50): ColorRgb 421*4cadd4f8SNickeau { 422*4cadd4f8SNickeau if ($weight === null) { 423*4cadd4f8SNickeau $weight = 50; 424*4cadd4f8SNickeau } 425*4cadd4f8SNickeau 426*4cadd4f8SNickeau $color2 = ColorRgb::createFromString($color); 427*4cadd4f8SNickeau $targetRed = self::round(Math::lerp($color2->getRed(), $this->getRed(), $weight)); 428*4cadd4f8SNickeau $targetGreen = self::round(Math::lerp($color2->getGreen(), $this->getGreen(), $weight)); 429*4cadd4f8SNickeau $targetBlue = self::round(Math::lerp($color2->getBlue(), $this->getBlue(), $weight)); 430*4cadd4f8SNickeau return ColorRgb::createFromRgbChannels($targetRed, $targetGreen, $targetBlue); 431*4cadd4f8SNickeau 432*4cadd4f8SNickeau } 433*4cadd4f8SNickeau 434*4cadd4f8SNickeau /** 435*4cadd4f8SNickeau * @throws ExceptionCombo 436*4cadd4f8SNickeau */ 437*4cadd4f8SNickeau function unmix($color, ?int $weight = 50): ColorRgb 438*4cadd4f8SNickeau { 439*4cadd4f8SNickeau if ($weight === null) { 440*4cadd4f8SNickeau $weight = 50; 441*4cadd4f8SNickeau } 442*4cadd4f8SNickeau 443*4cadd4f8SNickeau $color2 = ColorRgb::createFromString($color); 444*4cadd4f8SNickeau $targetRed = self::round(Math::unlerp($color2->getRed(), $this->getRed(), $weight)); 445*4cadd4f8SNickeau if ($targetRed < 0) { 446*4cadd4f8SNickeau throw new ExceptionCombo("This is not possible, the red value ({$color2->getBlue()}) with the percentage $weight could not be unmixed. They were not calculated with color mixing."); 447*4cadd4f8SNickeau } 448*4cadd4f8SNickeau $targetGreen = self::round(Math::unlerp($color2->getGreen(), $this->getGreen(), $weight)); 449*4cadd4f8SNickeau if ($targetGreen < 0) { 450*4cadd4f8SNickeau throw new ExceptionCombo("This is not possible, the green value ({$color2->getGreen()}) with the percentage $weight could not be unmixed. They were not calculated with color mixing."); 451*4cadd4f8SNickeau } 452*4cadd4f8SNickeau $targetBlue = self::round(Math::unlerp($color2->getBlue(), $this->getBlue(), $weight)); 453*4cadd4f8SNickeau if ($targetBlue < 0) { 454*4cadd4f8SNickeau throw new ExceptionCombo("This is not possible, the blue value ({$color2->getBlue()}) with the percentage $weight could not be unmixed. They were not calculated with color mixing."); 455*4cadd4f8SNickeau } 456*4cadd4f8SNickeau return ColorRgb::createFromRgbChannels($targetRed, $targetGreen, $targetBlue); 457*4cadd4f8SNickeau 458*4cadd4f8SNickeau } 459*4cadd4f8SNickeau 460*4cadd4f8SNickeau /** 461*4cadd4f8SNickeau * Takes an hexadecimal color and returns the rgb channels 462*4cadd4f8SNickeau * 463*4cadd4f8SNickeau * @param mixed $hex 464*4cadd4f8SNickeau * 465*4cadd4f8SNickeau * @throws ExceptionCombo 466*4cadd4f8SNickeau */ 467*4cadd4f8SNickeau function hex2rgb($hex = '#000000'): array 468*4cadd4f8SNickeau { 469*4cadd4f8SNickeau if ($hex[0] !== "#") { 470*4cadd4f8SNickeau throw new ExceptionCombo("The color value ($hex) does not start with a #, this is not valid CSS hexadecimal color value"); 471*4cadd4f8SNickeau } 472*4cadd4f8SNickeau $digits = str_replace("#", "", $hex); 473*4cadd4f8SNickeau $hexLen = strlen($digits); 474*4cadd4f8SNickeau $transparency = false; 475*4cadd4f8SNickeau switch ($hexLen) { 476*4cadd4f8SNickeau case 3: 477*4cadd4f8SNickeau $lengthColorHex = 1; 478*4cadd4f8SNickeau break; 479*4cadd4f8SNickeau case 6: 480*4cadd4f8SNickeau $lengthColorHex = 2; 481*4cadd4f8SNickeau break; 482*4cadd4f8SNickeau case 8: 483*4cadd4f8SNickeau $lengthColorHex = 2; 484*4cadd4f8SNickeau $transparency = true; 485*4cadd4f8SNickeau break; 486*4cadd4f8SNickeau default: 487*4cadd4f8SNickeau throw new ExceptionCombo("The digit color value ($hex) is not 3 or 6 in length, this is not a valid CSS hexadecimal color value"); 488*4cadd4f8SNickeau } 489*4cadd4f8SNickeau $result = preg_match("/[0-9a-f]{3,8}/i", $digits); 490*4cadd4f8SNickeau if ($result !== 1) { 491*4cadd4f8SNickeau throw new ExceptionCombo("The digit color value ($hex) is not a hexadecimal value, this is not a valid CSS hexadecimal color value"); 492*4cadd4f8SNickeau } 493*4cadd4f8SNickeau $channelHexs = str_split($digits, $lengthColorHex); 494*4cadd4f8SNickeau $rgbDec = []; 495*4cadd4f8SNickeau foreach ($channelHexs as $channelHex) { 496*4cadd4f8SNickeau if ($lengthColorHex === 1) { 497*4cadd4f8SNickeau $channelHex .= $channelHex; 498*4cadd4f8SNickeau } 499*4cadd4f8SNickeau $rgbDec[] = hexdec($channelHex); 500*4cadd4f8SNickeau } 501*4cadd4f8SNickeau if (!$transparency) { 502*4cadd4f8SNickeau $rgbDec[] = null; 503*4cadd4f8SNickeau } 504*4cadd4f8SNickeau return $rgbDec; 505*4cadd4f8SNickeau } 506*4cadd4f8SNickeau 507*4cadd4f8SNickeau /** 508*4cadd4f8SNickeau * rgb2hex 509*4cadd4f8SNickeau * 510*4cadd4f8SNickeau * @return string 511*4cadd4f8SNickeau */ 512*4cadd4f8SNickeau function toRgbHex(): string 513*4cadd4f8SNickeau { 514*4cadd4f8SNickeau 515*4cadd4f8SNickeau switch ($this->nameType) { 516*4cadd4f8SNickeau case self::VALUE_TYPE_CSS_NAME: 517*4cadd4f8SNickeau return strtolower(self::CSS_COLOR_NAMES[$this->name]); 518*4cadd4f8SNickeau default: 519*4cadd4f8SNickeau $toCssHex = function ($x) { 520*4cadd4f8SNickeau return str_pad(dechex($x), 2, "0", STR_PAD_LEFT); 521*4cadd4f8SNickeau }; 522*4cadd4f8SNickeau $redHex = $toCssHex($this->getRed()); 523*4cadd4f8SNickeau $greenHex = $toCssHex($this->getGreen()); 524*4cadd4f8SNickeau $blueHex = $toCssHex($this->getBlue()); 525*4cadd4f8SNickeau $withoutAlpha = "#" . $redHex . $greenHex . $blueHex; 526*4cadd4f8SNickeau if ($this->transparency === null) { 527*4cadd4f8SNickeau return $withoutAlpha; 528*4cadd4f8SNickeau } 529*4cadd4f8SNickeau return $withoutAlpha . $toCssHex($this->getTransparency()); 530*4cadd4f8SNickeau } 531*4cadd4f8SNickeau 532*4cadd4f8SNickeau } 533*4cadd4f8SNickeau 534*4cadd4f8SNickeau /** 535*4cadd4f8SNickeau * @throws ExceptionCombo 536*4cadd4f8SNickeau */ 537*4cadd4f8SNickeau public 538*4cadd4f8SNickeau static function createFromString(string $color): ColorRgb 539*4cadd4f8SNickeau { 540*4cadd4f8SNickeau if ($color[0] === "#") { 541*4cadd4f8SNickeau return self::createFromHex($color); 542*4cadd4f8SNickeau } else { 543*4cadd4f8SNickeau return self::createFromName($color); 544*4cadd4f8SNickeau } 545*4cadd4f8SNickeau } 546*4cadd4f8SNickeau 547*4cadd4f8SNickeau /** 548*4cadd4f8SNickeau * @throws ExceptionCombo 549*4cadd4f8SNickeau */ 550*4cadd4f8SNickeau public 551*4cadd4f8SNickeau static function createFromName(string $color): ColorRgb 552*4cadd4f8SNickeau { 553*4cadd4f8SNickeau return (new ColorRgb()) 554*4cadd4f8SNickeau ->setName($color); 555*4cadd4f8SNickeau } 556*4cadd4f8SNickeau 557*4cadd4f8SNickeau 558*4cadd4f8SNickeau public 559*4cadd4f8SNickeau function toCssValue(): string 560*4cadd4f8SNickeau { 561*4cadd4f8SNickeau 562*4cadd4f8SNickeau switch ($this->nameType) { 563*4cadd4f8SNickeau case self::VALUE_TYPE_RGB_ARRAY: 564*4cadd4f8SNickeau return $this->toRgbHex(); 565*4cadd4f8SNickeau case self::VALUE_TYPE_CSS_NAME: 566*4cadd4f8SNickeau case self::VALUE_TYPE_RGB_HEX; 567*4cadd4f8SNickeau return $this->name; 568*4cadd4f8SNickeau case self::VALUE_TYPE_BOOTSTRAP_NAME: 569*4cadd4f8SNickeau $bootstrapVersion = Bootstrap::getBootStrapMajorVersion(); 570*4cadd4f8SNickeau switch ($bootstrapVersion) { 571*4cadd4f8SNickeau case Bootstrap::BootStrapFiveMajorVersion: 572*4cadd4f8SNickeau $colorValue = "bs-" . $this->name; 573*4cadd4f8SNickeau break; 574*4cadd4f8SNickeau default: 575*4cadd4f8SNickeau $colorValue = $this->name; 576*4cadd4f8SNickeau break; 577*4cadd4f8SNickeau } 578*4cadd4f8SNickeau return "var(--" . $colorValue . ")"; 579*4cadd4f8SNickeau case self::VALUE_TYPE_RESET: 580*4cadd4f8SNickeau return "inherit!important"; 581*4cadd4f8SNickeau default: 582*4cadd4f8SNickeau // unknown color name 583*4cadd4f8SNickeau if ($this->name === null) { 584*4cadd4f8SNickeau LogUtility::msg("The name should not be null"); 585*4cadd4f8SNickeau return "black"; 586*4cadd4f8SNickeau } 587*4cadd4f8SNickeau return $this->name; 588*4cadd4f8SNickeau } 589*4cadd4f8SNickeau 590*4cadd4f8SNickeau 591*4cadd4f8SNickeau } 592*4cadd4f8SNickeau 593*4cadd4f8SNickeau public 594*4cadd4f8SNickeau function getRed() 595*4cadd4f8SNickeau { 596*4cadd4f8SNickeau return $this->red; 597*4cadd4f8SNickeau } 598*4cadd4f8SNickeau 599*4cadd4f8SNickeau public 600*4cadd4f8SNickeau function getGreen() 601*4cadd4f8SNickeau { 602*4cadd4f8SNickeau return $this->green; 603*4cadd4f8SNickeau } 604*4cadd4f8SNickeau 605*4cadd4f8SNickeau public 606*4cadd4f8SNickeau function getBlue() 607*4cadd4f8SNickeau { 608*4cadd4f8SNickeau return $this->blue; 609*4cadd4f8SNickeau } 610*4cadd4f8SNickeau 611*4cadd4f8SNickeau /** 612*4cadd4f8SNickeau * Mix with black 613*4cadd4f8SNickeau * @var int $percentage between 0 and 100 614*4cadd4f8SNickeau */ 615*4cadd4f8SNickeau public 616*4cadd4f8SNickeau function shade(int $percentage): ColorRgb 617*4cadd4f8SNickeau { 618*4cadd4f8SNickeau try { 619*4cadd4f8SNickeau return $this->mix('black', $percentage); 620*4cadd4f8SNickeau } catch (ExceptionCombo $e) { 621*4cadd4f8SNickeau // should not happen 622*4cadd4f8SNickeau LogUtility::msg("Error while shading. Error: {$e->getMessage()}"); 623*4cadd4f8SNickeau return $this; 624*4cadd4f8SNickeau } 625*4cadd4f8SNickeau } 626*4cadd4f8SNickeau 627*4cadd4f8SNickeau public 628*4cadd4f8SNickeau function getNameType(): string 629*4cadd4f8SNickeau { 630*4cadd4f8SNickeau return $this->nameType; 631*4cadd4f8SNickeau } 632*4cadd4f8SNickeau 633*4cadd4f8SNickeau /** 634*4cadd4f8SNickeau * @param int $percentage between -100 and 100 635*4cadd4f8SNickeau * @return $this 636*4cadd4f8SNickeau */ 637*4cadd4f8SNickeau public 638*4cadd4f8SNickeau function scale(int $percentage): ColorRgb 639*4cadd4f8SNickeau { 640*4cadd4f8SNickeau if ($percentage === 0) { 641*4cadd4f8SNickeau return $this; 642*4cadd4f8SNickeau } 643*4cadd4f8SNickeau if ($percentage > 0) { 644*4cadd4f8SNickeau return $this->shade($percentage); 645*4cadd4f8SNickeau } else { 646*4cadd4f8SNickeau return $this->tint(abs($percentage)); 647*4cadd4f8SNickeau } 648*4cadd4f8SNickeau 649*4cadd4f8SNickeau } 650*4cadd4f8SNickeau 651*4cadd4f8SNickeau 652*4cadd4f8SNickeau public 653*4cadd4f8SNickeau function toRgbChannels(): array 654*4cadd4f8SNickeau { 655*4cadd4f8SNickeau return [$this->getRed(), $this->getGreen(), $this->getBlue()]; 656*4cadd4f8SNickeau } 657*4cadd4f8SNickeau 658*4cadd4f8SNickeau /** 659*4cadd4f8SNickeau * @param int $percentage between 0 and 100 660*4cadd4f8SNickeau * @return $this 661*4cadd4f8SNickeau */ 662*4cadd4f8SNickeau public 663*4cadd4f8SNickeau function tint(int $percentage): ColorRgb 664*4cadd4f8SNickeau { 665*4cadd4f8SNickeau try { 666*4cadd4f8SNickeau return $this->mix("white", $percentage); 667*4cadd4f8SNickeau } catch (ExceptionCombo $e) { 668*4cadd4f8SNickeau // should not happen 669*4cadd4f8SNickeau LogUtility::msg("Error while tinting ($this) with a percentage ($percentage. Error: {$e->getMessage()}"); 670*4cadd4f8SNickeau return $this; 671*4cadd4f8SNickeau } 672*4cadd4f8SNickeau } 673*4cadd4f8SNickeau 674*4cadd4f8SNickeau public 675*4cadd4f8SNickeau function __toString() 676*4cadd4f8SNickeau { 677*4cadd4f8SNickeau return $this->toCssValue(); 678*4cadd4f8SNickeau } 679*4cadd4f8SNickeau 680*4cadd4f8SNickeau public 681*4cadd4f8SNickeau function getLuminance(): float 682*4cadd4f8SNickeau { 683*4cadd4f8SNickeau $toLuminanceFactor = function ($channel) { 684*4cadd4f8SNickeau $pigmentRatio = $channel / 255; 685*4cadd4f8SNickeau return $pigmentRatio <= 0.03928 ? $pigmentRatio / 12.92 : pow(($pigmentRatio + 0.055) / 1.055, 2.4); 686*4cadd4f8SNickeau }; 687*4cadd4f8SNickeau $R = $toLuminanceFactor($this->getRed()); 688*4cadd4f8SNickeau $G = $toLuminanceFactor($this->getGreen()); 689*4cadd4f8SNickeau $B = $toLuminanceFactor($this->getBlue()); 690*4cadd4f8SNickeau return $R * 0.2126 + $G * 0.7152 + $B * 0.0722; 691*4cadd4f8SNickeau 692*4cadd4f8SNickeau } 693*4cadd4f8SNickeau 694*4cadd4f8SNickeau /** 695*4cadd4f8SNickeau * The ratio that returns the chrome browser 696*4cadd4f8SNickeau * @param ColorRgb $colorRgb 697*4cadd4f8SNickeau * @return float 698*4cadd4f8SNickeau * @throws ExceptionCombo 699*4cadd4f8SNickeau */ 700*4cadd4f8SNickeau public 701*4cadd4f8SNickeau function getContrastRatio(ColorRgb $colorRgb): float 702*4cadd4f8SNickeau { 703*4cadd4f8SNickeau $actualColorHsl = $this->toHsl(); 704*4cadd4f8SNickeau $actualLightness = $actualColorHsl->getLightness(); 705*4cadd4f8SNickeau $targetColorHsl = $colorRgb->toHsl(); 706*4cadd4f8SNickeau $targetLightNess = $targetColorHsl->getLightness(); 707*4cadd4f8SNickeau if ($actualLightness > $targetLightNess) { 708*4cadd4f8SNickeau $lighter = $this; 709*4cadd4f8SNickeau $darker = $colorRgb; 710*4cadd4f8SNickeau } else { 711*4cadd4f8SNickeau $lighter = $colorRgb; 712*4cadd4f8SNickeau $darker = $this; 713*4cadd4f8SNickeau } 714*4cadd4f8SNickeau $ratio = ($lighter->getLuminance() + 0.05) / ($darker->getLuminance() + 0.05); 715*4cadd4f8SNickeau return floor($ratio * 100) / 100; 716*4cadd4f8SNickeau } 717*4cadd4f8SNickeau 718*4cadd4f8SNickeau /** 719*4cadd4f8SNickeau * @throws ExceptionCombo 720*4cadd4f8SNickeau */ 721*4cadd4f8SNickeau public 722*4cadd4f8SNickeau function toMinimumContrastRatio(string $color, float $minimum = self::MINIMUM_CONTRAST_RATIO, $darknessIncrement = 5): ColorRgb 723*4cadd4f8SNickeau { 724*4cadd4f8SNickeau $targetColor = ColorRgb::createFromString($color); 725*4cadd4f8SNickeau $ratio = $this->getContrastRatio($targetColor); 726*4cadd4f8SNickeau $newColorRgb = $this; 727*4cadd4f8SNickeau $newColorHsl = $this->toHsl(); 728*4cadd4f8SNickeau while ($ratio < $minimum) { 729*4cadd4f8SNickeau $newColorHsl = $newColorHsl->darken($darknessIncrement); 730*4cadd4f8SNickeau $newColorRgb = $newColorHsl->toRgb(); 731*4cadd4f8SNickeau if ($newColorHsl->getLightness() === 0) { 732*4cadd4f8SNickeau break; 733*4cadd4f8SNickeau } 734*4cadd4f8SNickeau $ratio = $newColorRgb->getContrastRatio($targetColor); 735*4cadd4f8SNickeau } 736*4cadd4f8SNickeau return $newColorRgb; 737*4cadd4f8SNickeau } 738*4cadd4f8SNickeau 739*4cadd4f8SNickeau /** 740*4cadd4f8SNickeau * Returns the complimentary color 741*4cadd4f8SNickeau */ 742*4cadd4f8SNickeau public 743*4cadd4f8SNickeau function complementary(): ColorRgb 744*4cadd4f8SNickeau { 745*4cadd4f8SNickeau try { 746*4cadd4f8SNickeau return $this 747*4cadd4f8SNickeau ->toHsl() 748*4cadd4f8SNickeau ->toComplement() 749*4cadd4f8SNickeau ->toRgb(); 750*4cadd4f8SNickeau } catch (ExceptionCombo $e) { 751*4cadd4f8SNickeau LogUtility::msg("Error while getting the complementary color of ($this). Error: {$e->getMessage()}"); 752*4cadd4f8SNickeau return $this; 753*4cadd4f8SNickeau } 754*4cadd4f8SNickeau 755*4cadd4f8SNickeau } 756*4cadd4f8SNickeau 757*4cadd4f8SNickeau public 758*4cadd4f8SNickeau function getName(): string 759*4cadd4f8SNickeau { 760*4cadd4f8SNickeau $hexColor = $this->toRgbHex(); 761*4cadd4f8SNickeau if (in_array($hexColor, self::CSS_COLOR_NAMES)) { 762*4cadd4f8SNickeau return self::CSS_COLOR_NAMES[$hexColor]; 763*4cadd4f8SNickeau } 764*4cadd4f8SNickeau return $hexColor; 765*4cadd4f8SNickeau } 766*4cadd4f8SNickeau 767*4cadd4f8SNickeau /** 768*4cadd4f8SNickeau * @throws ExceptionCombo 769*4cadd4f8SNickeau */ 770*4cadd4f8SNickeau public 771*4cadd4f8SNickeau function toMinimumContrastRatioAgainstWhite(float $minimumContrastRatio = self::MINIMUM_CONTRAST_RATIO, int $darknessIncrement = 5): ColorRgb 772*4cadd4f8SNickeau { 773*4cadd4f8SNickeau return $this->toMinimumContrastRatio(self::WHITE, $minimumContrastRatio, $darknessIncrement); 774*4cadd4f8SNickeau } 775*4cadd4f8SNickeau 776*4cadd4f8SNickeau /** 777*4cadd4f8SNickeau * @throws ExceptionCombo 778*4cadd4f8SNickeau */ 779*4cadd4f8SNickeau private 780*4cadd4f8SNickeau function setHex(string $color): ColorRgb 781*4cadd4f8SNickeau { 782*4cadd4f8SNickeau // Hexadecimal 783*4cadd4f8SNickeau if ($color[0] !== "#") { 784*4cadd4f8SNickeau throw new ExceptionCombo("The value is not an hexadecimal color value ($color)"); 785*4cadd4f8SNickeau } 786*4cadd4f8SNickeau [$this->red, $this->green, $this->blue, $this->transparency] = $this->hex2rgb($color); 787*4cadd4f8SNickeau $this->nameType = self::VALUE_TYPE_RGB_HEX; 788*4cadd4f8SNickeau $this->name = $color; 789*4cadd4f8SNickeau return $this; 790*4cadd4f8SNickeau } 791*4cadd4f8SNickeau 792*4cadd4f8SNickeau /** 793*4cadd4f8SNickeau * @throws ExceptionCombo 794*4cadd4f8SNickeau */ 795*4cadd4f8SNickeau public 796*4cadd4f8SNickeau function setRgbChannels(array $colorValue): ColorRgb 797*4cadd4f8SNickeau { 798*4cadd4f8SNickeau if (sizeof($colorValue) != 3) { 799*4cadd4f8SNickeau throw new ExceptionCombo("A rgb color array should be of length 3"); 800*4cadd4f8SNickeau } 801*4cadd4f8SNickeau foreach ($colorValue as $color) { 802*4cadd4f8SNickeau try { 803*4cadd4f8SNickeau $channel = DataType::toInteger($color); 804*4cadd4f8SNickeau } catch (ExceptionCombo $e) { 805*4cadd4f8SNickeau throw new ExceptionCombo("The rgb color $color is not an integer. Error: {$e->getMessage()}"); 806*4cadd4f8SNickeau } 807*4cadd4f8SNickeau if ($channel < 0 and $channel > 255) { 808*4cadd4f8SNickeau throw new ExceptionCombo("The rgb color $color is not between 0 and 255"); 809*4cadd4f8SNickeau } 810*4cadd4f8SNickeau } 811*4cadd4f8SNickeau [$this->red, $this->green, $this->blue] = $colorValue; 812*4cadd4f8SNickeau $this->nameType = self::VALUE_TYPE_RGB_ARRAY; 813*4cadd4f8SNickeau return $this; 814*4cadd4f8SNickeau } 815*4cadd4f8SNickeau 816*4cadd4f8SNickeau private 817*4cadd4f8SNickeau function setNameType(string $type): ColorRgb 818*4cadd4f8SNickeau { 819*4cadd4f8SNickeau $this->nameType = $type; 820*4cadd4f8SNickeau return $this; 821*4cadd4f8SNickeau } 822*4cadd4f8SNickeau 823*4cadd4f8SNickeau /** 824*4cadd4f8SNickeau * Via a name 825*4cadd4f8SNickeau * @throws ExceptionCombo 826*4cadd4f8SNickeau */ 827*4cadd4f8SNickeau private 828*4cadd4f8SNickeau function setName(string $name): ColorRgb 829*4cadd4f8SNickeau { 830*4cadd4f8SNickeau 831*4cadd4f8SNickeau $qualifiedName = strtolower($name); 832*4cadd4f8SNickeau $this->name = $qualifiedName; 833*4cadd4f8SNickeau if (in_array($qualifiedName, self::BOOTSTRAP_COLORS)) { 834*4cadd4f8SNickeau /** 835*4cadd4f8SNickeau * Branding colors overwrite 836*4cadd4f8SNickeau */ 837*4cadd4f8SNickeau switch ($this->name) { 838*4cadd4f8SNickeau case ColorRgb::PRIMARY_VALUE: 839*4cadd4f8SNickeau $primaryColor = Site::getPrimaryColorValue(); 840*4cadd4f8SNickeau if ($primaryColor !== null) { 841*4cadd4f8SNickeau if ($primaryColor !== ColorRgb::PRIMARY_VALUE) { 842*4cadd4f8SNickeau return self::createFromString($primaryColor); 843*4cadd4f8SNickeau } 844*4cadd4f8SNickeau LogUtility::msg("The primary color cannot be set with the value primary. Default to bootstrap color.", self::BRANDING_COLOR_CANONICAL); 845*4cadd4f8SNickeau } 846*4cadd4f8SNickeau break; 847*4cadd4f8SNickeau case ColorRgb::SECONDARY_VALUE: 848*4cadd4f8SNickeau $secondaryColor = Site::getSecondaryColorValue(); 849*4cadd4f8SNickeau if ($secondaryColor !== null) { 850*4cadd4f8SNickeau if ($secondaryColor !== ColorRgb::SECONDARY_VALUE) { 851*4cadd4f8SNickeau return self::createFromString($secondaryColor); 852*4cadd4f8SNickeau } 853*4cadd4f8SNickeau LogUtility::msg("The secondary color cannot be set with the value secondary. Default to bootstrap color.", self::BRANDING_COLOR_CANONICAL); 854*4cadd4f8SNickeau } 855*4cadd4f8SNickeau break; 856*4cadd4f8SNickeau } 857*4cadd4f8SNickeau 858*4cadd4f8SNickeau return $this->setNameType(self::VALUE_TYPE_BOOTSTRAP_NAME); 859*4cadd4f8SNickeau } 860*4cadd4f8SNickeau if ($qualifiedName === self::VALUE_TYPE_RESET) { 861*4cadd4f8SNickeau return $this->setNameType(self::VALUE_TYPE_RESET); 862*4cadd4f8SNickeau } 863*4cadd4f8SNickeau if (in_array($qualifiedName, array_keys(self::CSS_COLOR_NAMES))) { 864*4cadd4f8SNickeau $this->setHex(self::CSS_COLOR_NAMES[$qualifiedName]) 865*4cadd4f8SNickeau ->setNameType(self::VALUE_TYPE_CSS_NAME); 866*4cadd4f8SNickeau $this->name = $qualifiedName; // hex is a also a name, the previous setHex overwrite the name 867*4cadd4f8SNickeau return $this; 868*4cadd4f8SNickeau } 869*4cadd4f8SNickeau LogUtility::msg("The color name ($name) is unknown"); 870*4cadd4f8SNickeau return $this; 871*4cadd4f8SNickeau 872*4cadd4f8SNickeau } 873*4cadd4f8SNickeau 874*4cadd4f8SNickeau public 875*4cadd4f8SNickeau function getTransparency() 876*4cadd4f8SNickeau { 877*4cadd4f8SNickeau return $this->transparency; 878*4cadd4f8SNickeau } 879*4cadd4f8SNickeau 880*4cadd4f8SNickeau 881*4cadd4f8SNickeau 882*4cadd4f8SNickeau 883*4cadd4f8SNickeau} 884