Merge pull request #15816 from MiyaNoctem/dev-core-1383-fix-reinstallation-of-extensi...
[civicrm-core.git] / CRM / Utils / Color.php
1 <?php
2 /*
3 +--------------------------------------------------------------------+
4 | CiviCRM version 5 |
5 +--------------------------------------------------------------------+
6 | Copyright CiviCRM LLC (c) 2004-2019 |
7 +--------------------------------------------------------------------+
8 | This file is a part of CiviCRM. |
9 | |
10 | CiviCRM is free software; you can copy, modify, and distribute it |
11 | under the terms of the GNU Affero General Public License |
12 | Version 3, 19 November 2007 and the CiviCRM Licensing Exception. |
13 | |
14 | CiviCRM is distributed in the hope that it will be useful, but |
15 | WITHOUT ANY WARRANTY; without even the implied warranty of |
16 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. |
17 | See the GNU Affero General Public License for more details. |
18 | |
19 | You should have received a copy of the GNU Affero General Public |
20 | License and the CiviCRM Licensing Exception along |
21 | with this program; if not, contact CiviCRM LLC |
22 | at info[AT]civicrm[DOT]org. If you have questions about the |
23 | GNU Affero General Public License or the licensing of CiviCRM, |
24 | see the CiviCRM license FAQ at http://civicrm.org/licensing |
25 +--------------------------------------------------------------------+
26 */
27
28 /**
29 *
30 * @package CRM
31 * @copyright CiviCRM LLC (c) 2004-2019
32 */
33
34 /**
35 * Static utility functions for working with colors
36 */
37 class CRM_Utils_Color {
38
39 const COLOR_FILE = '[civicrm.root]/bower_components/css-color-names/css-color-names.json';
40
41 /**
42 * Determine the appropriate text color for a given background.
43 *
44 * Based on YIQ value.
45 *
46 * @param string $color
47 * @param string $black
48 * @param string $white
49 * @return string
50 */
51 public static function getContrast($color, $black = 'black', $white = 'white') {
52 list($r, $g, $b) = self::getRgb($color);
53 $yiq = (($r * 299) + ($g * 587) + ($b * 114)) / 1000;
54 return ($yiq >= 128) ? $black : $white;
55 }
56
57 /**
58 * Parse any color string into rgb decimal values
59 *
60 * Accepted formats:
61 * Full hex: "#ffffff"
62 * Short hex: "#fff"
63 * Color name "white"
64 * RGB notation: "rgb(255, 255, 255)"
65 *
66 * @param string $color
67 * @return int[]|null
68 * [red, green, blue]
69 */
70 public static function getRgb($color) {
71 $color = str_replace(' ', '', $color);
72 $color = self::nameToHex($color) ?? $color;
73 if (strpos($color, 'rgb(') === 0) {
74 return explode(',', substr($color, 4, strpos($color, ')') - 4));
75 }
76 $color = ltrim($color, '#');
77 if (strlen($color) === 3) {
78 $color = $color[0] . $color[0] . $color[1] . $color[1] . $color[2] . $color[2];
79 }
80 if (!CRM_Utils_Rule::color('#' . $color)) {
81 return NULL;
82 }
83 return [
84 hexdec(substr($color, 0, 2)),
85 hexdec(substr($color, 2, 2)),
86 hexdec(substr($color, 4, 2)),
87 ];
88 }
89
90 /**
91 * Calculate a highlight color from a base color
92 *
93 * @param $color
94 * @return string
95 */
96 public static function getHighlight($color) {
97 $rgb = self::getRgb($color);
98 $avg = array_sum($rgb) / 3;
99 foreach ($rgb as &$v) {
100 if ($avg > 242) {
101 // For very bright values, lower the brightness
102 $v -= 50;
103 }
104 else {
105 // Bump up brightness on a nonlinear curve - darker colors get more of a boost
106 $v = min(255, intval((-.0035 * ($v - 242) ** 2) + 260));
107 }
108 }
109 return self::rgbToHex($rgb);
110 }
111
112 /**
113 * Convert named color (e.g. springgreen) to hex
114 *
115 * @param $colorName
116 * @return string|null
117 */
118 public static function nameToHex($colorName) {
119 if (strpos($colorName, '#') !== FALSE || strpos($colorName, '(') !== FALSE) {
120 return NULL;
121 }
122 if (empty(Civi::$statics[__CLASS__]['names'])) {
123 Civi::$statics[__CLASS__]['names'] = json_decode(file_get_contents(Civi::paths()->getPath(self::COLOR_FILE)), TRUE);
124 }
125 return Civi::$statics[__CLASS__]['names'][strtolower($colorName)] ?? NULL;
126 }
127
128 /**
129 * Converts rgb array to hex string
130 *
131 * @param int[] $rgb
132 * @return string
133 */
134 public static function rgbToHex($rgb) {
135 $ret = '#';
136 foreach ($rgb as $dec) {
137 $ret .= str_pad(dechex($dec), 2, '0', STR_PAD_LEFT);
138 }
139 return $ret;
140 }
141
142 /**
143 * Validate color input and convert it to standard hex notation
144 *
145 * @param string $color
146 * @return bool
147 */
148 public static function normalize(&$color) {
149 $rgb = self::getRgb($color);
150 if ($rgb) {
151 $color = self::rgbToHex($rgb);
152 return TRUE;
153 }
154 return FALSE;
155 }
156
157 }