Commit | Line | Data |
---|---|---|
49f42e3c CW |
1 | <?php |
2 | /* | |
3 | +--------------------------------------------------------------------+ | |
fee14197 | 4 | | CiviCRM version 5 | |
49f42e3c | 5 | +--------------------------------------------------------------------+ |
6b83d5bd | 6 | | Copyright CiviCRM LLC (c) 2004-2019 | |
49f42e3c CW |
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 | |
6b83d5bd | 31 | * @copyright CiviCRM LLC (c) 2004-2019 |
49f42e3c CW |
32 | */ |
33 | ||
34 | /** | |
35 | * Static utility functions for working with colors | |
36 | */ | |
37 | class CRM_Utils_Color { | |
38 | ||
0f4485f5 CW |
39 | const COLOR_FILE = '[civicrm.root]/bower_components/css-color-names/css-color-names.json'; |
40 | ||
49f42e3c CW |
41 | /** |
42 | * Determine the appropriate text color for a given background. | |
43 | * | |
44 | * Based on YIQ value. | |
45 | * | |
0f4485f5 | 46 | * @param string $color |
8a52ae34 CW |
47 | * @param string $black |
48 | * @param string $white | |
49f42e3c CW |
49 | * @return string |
50 | */ | |
0f4485f5 CW |
51 | public static function getContrast($color, $black = 'black', $white = 'white') { |
52 | list($r, $g, $b) = self::getRgb($color); | |
49f42e3c | 53 | $yiq = (($r * 299) + ($g * 587) + ($b * 114)) / 1000; |
8a52ae34 CW |
54 | return ($yiq >= 128) ? $black : $white; |
55 | } | |
56 | ||
57 | /** | |
0f4485f5 CW |
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)" | |
8a52ae34 | 65 | * |
0f4485f5 CW |
66 | * @param string $color |
67 | * @return int[]|null | |
8a52ae34 CW |
68 | * [red, green, blue] |
69 | */ | |
0f4485f5 CW |
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; | |
8a52ae34 CW |
82 | } |
83 | return [ | |
0f4485f5 CW |
84 | hexdec(substr($color, 0, 2)), |
85 | hexdec(substr($color, 2, 2)), | |
86 | hexdec(substr($color, 4, 2)), | |
8a52ae34 CW |
87 | ]; |
88 | } | |
89 | ||
90 | /** | |
91 | * Calculate a highlight color from a base color | |
92 | * | |
0f4485f5 | 93 | * @param $color |
8a52ae34 CW |
94 | * @return string |
95 | */ | |
0f4485f5 CW |
96 | public static function getHighlight($color) { |
97 | $rgb = self::getRgb($color); | |
8a52ae34 CW |
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 | } | |
0f4485f5 CW |
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; | |
49f42e3c CW |
155 | } |
156 | ||
157 | } |