Differences Between: [Versions 311 and 401] [Versions 311 and 402] [Versions 311 and 403]
1 <?php 2 // This file is part of Moodle - http://moodle.org/ 3 // 4 // Moodle is free software: you can redistribute it and/or modify 5 // it under the terms of the GNU General Public License as published by 6 // the Free Software Foundation, either version 3 of the License, or 7 // (at your option) any later version. 8 // 9 // Moodle is distributed in the hope that it will be useful, 10 // but WITHOUT ANY WARRANTY; without even the implied warranty of 11 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 12 // GNU General Public License for more details. 13 // 14 // You should have received a copy of the GNU General Public License 15 // along with Moodle. If not, see <http://www.gnu.org/licenses/>. 16 17 namespace tool_brickfield\local\htmlchecker\common; 18 19 /** 20 * Helper test base for tests dealing with color difference and luminosity. 21 * 22 * @package tool_brickfield 23 * @copyright 2020 onward: Brickfield Education Labs, www.brickfield.ie 24 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later 25 */ 26 class brickfield_accessibility_color_test extends brickfield_accessibility_test { 27 28 /** @var string[] Define colour codes. */ 29 public $colornames = [ 30 'aliceblue' => 'f0f8ff', 31 'antiquewhite' => 'faebd7', 32 'aqua' => '00ffff', 33 'aquamarine' => '7fffd4', 34 'azure' => 'f0ffff', 35 'beige' => 'f5f5dc', 36 'bisque' => 'ffe4c4', 37 'black' => '000000', 38 'blanchedalmond' => 'ffebcd', 39 'blue' => '0000ff', 40 'blueviolet' => '8a2be2', 41 'brown' => 'a52a2a', 42 'burlywood' => 'deb887', 43 'cadetblue' => '5f9ea0', 44 'chartreuse' => '7fff00', 45 'chocolate' => 'd2691e', 46 'coral' => 'ff7f50', 47 'cornflowerblue' => '6495ed', 48 'cornsilk' => 'fff8dc', 49 'crimson' => 'dc143c', 50 'cyan' => '00ffff', 51 'darkblue' => '00008b', 52 'darkcyan' => '008b8b', 53 'darkgoldenrod' => 'b8860b', 54 'darkgray' => 'a9a9a9', 55 'darkgreen' => '006400', 56 'darkkhaki' => 'bdb76b', 57 'darkmagenta' => '8b008b', 58 'darkolivegreen' => '556b2f', 59 'darkorange' => 'ff8c00', 60 'darkorchid' => '9932cc', 61 'darkred' => '8b0000', 62 'darksalmon' => 'e9967a', 63 'darkseagreen' => '8fbc8f', 64 'darkslateblue' => '483d8b', 65 'darkslategray' => '2f4f4f', 66 'darkturquoise' => '00ced1', 67 'darkviolet' => '9400d3', 68 'deeppink' => 'ff1493', 69 'deepskyblue' => '00bfff', 70 'dimgray' => '696969', 71 'dodgerblue' => '1e90ff', 72 'firebrick' => 'b22222', 73 'floralwhite' => 'fffaf0', 74 'forestgreen' => '228b22', 75 'fuchsia' => 'ff00ff', 76 'gainsboro' => 'dcdcdc', 77 'ghostwhite' => 'f8f8ff', 78 'gold' => 'ffd700', 79 'goldenrod' => 'daa520', 80 'gray' => '808080', 81 'green' => '008000', 82 'greenyellow' => 'adff2f', 83 'grey' => '808080', 84 'honeydew' => 'f0fff0', 85 'hotpink' => 'ff69b4', 86 'indianred' => 'cd5c5c', 87 'indigo' => '4b0082', 88 'ivory' => 'fffff0', 89 'khaki' => 'f0e68c', 90 'lavender' => 'e6e6fa', 91 'lavenderblush' => 'fff0f5', 92 'lawngreen' => '7cfc00', 93 'lemonchiffon' => 'fffacd', 94 'lightblue' => 'add8e6', 95 'lightcoral' => 'f08080', 96 'lightcyan' => 'e0ffff', 97 'lightgoldenrodyellow' => 'fafad2', 98 'lightgrey' => 'd3d3d3', 99 'lightgreen' => '90ee90', 100 'lightpink' => 'ffb6c1', 101 'lightsalmon' => 'ffa07a', 102 'lightseagreen' => '20b2aa', 103 'lightskyblue' => '87cefa', 104 'lightslategray' => '778899', 105 'lightsteelblue' => 'b0c4de', 106 'lightyellow' => 'ffffe0', 107 'lime' => '00ff00', 108 'limegreen' => '32cd32', 109 'linen' => 'faf0e6', 110 'magenta' => 'ff00ff', 111 'maroon' => '800000', 112 'mediumaquamarine' => '66cdaa', 113 'mediumblue' => '0000cd', 114 'mediumorchid' => 'ba55d3', 115 'mediumpurple' => '9370d8', 116 'mediumseagreen' => '3cb371', 117 'mediumslateblue' => '7b68ee', 118 'mediumspringgreen' => '00fa9a', 119 'mediumturquoise' => '48d1cc', 120 'mediumvioletred' => 'c71585', 121 'midnightblue' => '191970', 122 'mintcream' => 'f5fffa', 123 'mistyrose' => 'ffe4e1', 124 'moccasin' => 'ffe4b5', 125 'navajowhite' => 'ffdead', 126 'navy' => '000080', 127 'oldlace' => 'fdf5e6', 128 'olive' => '808000', 129 'olivedrab' => '6b8e23', 130 'orange' => 'ffa500', 131 'orangered' => 'ff4500', 132 'orchid' => 'da70d6', 133 'palegoldenrod' => 'eee8aa', 134 'palegreen' => '98fb98', 135 'paleturquoise' => 'afeeee', 136 'palevioletred' => 'd87093', 137 'papayawhip' => 'ffefd5', 138 'peachpuff' => 'ffdab9', 139 'peru' => 'cd853f', 140 'pink' => 'ffc0cb', 141 'plum' => 'dda0dd', 142 'powderblue' => 'b0e0e6', 143 'purple' => '800080', 144 'red' => 'ff0000', 145 'rosybrown' => 'bc8f8f', 146 'royalblue' => '4169e1', 147 'saddlebrown' => '8b4513', 148 'salmon' => 'fa8072', 149 'sandybrown' => 'f4a460', 150 'seagreen' => '2e8b57', 151 'seashell' => 'fff5ee', 152 'sienna' => 'a0522d', 153 'silver' => 'c0c0c0', 154 'skyblue' => '87ceeb', 155 'slateblue' => '6a5acd', 156 'slategray' => '708090', 157 'snow' => 'fffafa', 158 'springgreen' => '00ff7f', 159 'steelblue' => '4682b4', 160 'tan' => 'd2b48c', 161 'teal' => '008080', 162 'thistle' => 'd8bfd8', 163 'tomato' => 'ff6347', 164 'turquoise' => '40e0d0', 165 'violet' => 'ee82ee', 166 'wheat' => 'f5deb3', 167 'white' => 'ffffff', 168 'whitesmoke' => 'f5f5f5', 169 'yellow' => 'ffff00', 170 'yellowgreen' => '9acd32' 171 ]; 172 173 /** 174 * Helper method that finds the luminosity between the provided 175 * foreground and background parameters. 176 * @param string $foreground The HEX value of the foreground color 177 * @param string $background The HEX value of the background color 178 * @return float The luminosity contrast ratio between the colors 179 */ 180 public function get_luminosity(string $foreground, string $background): float { 181 if ($foreground == $background) { 182 return 0; 183 } 184 $forergb = $this->get_rgb($foreground); 185 $backrgb = $this->get_rgb($background); 186 187 // If get_rgb returns null for either, return 0. 188 if ($forergb === null || $backrgb === null) { 189 return 0; 190 } 191 192 return $this->luminosity($forergb['r'], $backrgb['r'], 193 $forergb['g'], $backrgb['g'], 194 $forergb['b'], $backrgb['b']); 195 } 196 197 /** 198 * Returns the luminosity between two colors 199 * @param string $r The first Red value 200 * @param string $r2 The second Red value 201 * @param string $g The first Green value 202 * @param string $g2 The second Green value 203 * @param string $b The first Blue value 204 * @param string $b2 The second Blue value 205 * @return float The luminosity contrast ratio between the colors 206 */ 207 public function luminosity(string $r, string $r2, string $g, string $g2, string $b, string $b2): float { 208 $rsrgb = $r / 255; 209 $gsrgb = $g / 255; 210 $bsrgb = $b / 255; 211 $r3 = ($rsrgb <= 0.03928) ? $rsrgb / 12.92 : pow(($rsrgb + 0.055) / 1.055, 2.4); 212 $g3 = ($gsrgb <= 0.03928) ? $gsrgb / 12.92 : pow(($gsrgb + 0.055) / 1.055, 2.4); 213 $b3 = ($bsrgb <= 0.03928) ? $bsrgb / 12.92 : pow(($bsrgb + 0.055) / 1.055, 2.4); 214 215 $rsrgb2 = $r2 / 255; 216 $gsrgb2 = $g2 / 255; 217 $bsrgb2 = $b2 / 255; 218 $r4 = ($rsrgb2 <= 0.03928) ? $rsrgb2 / 12.92 : pow(($rsrgb2 + 0.055) / 1.055, 2.4); 219 $g4 = ($gsrgb2 <= 0.03928) ? $gsrgb2 / 12.92 : pow(($gsrgb2 + 0.055) / 1.055, 2.4); 220 $b4 = ($bsrgb2 <= 0.03928) ? $bsrgb2 / 12.92 : pow(($bsrgb2 + 0.055) / 1.055, 2.4); 221 222 if ($r + $g + $b <= $r2 + $g2 + $b2) { 223 $l2 = (.2126 * $r3 + 0.7152 * $g3 + 0.0722 * $b3); 224 $l1 = (.2126 * $r4 + 0.7152 * $g4 + 0.0722 * $b4); 225 } else { 226 $l1 = (.2126 * $r3 + 0.7152 * $g3 + 0.0722 * $b3); 227 $l2 = (.2126 * $r4 + 0.7152 * $g4 + 0.0722 * $b4); 228 } 229 230 $luminosity = round(($l1 + 0.05) / ($l2 + 0.05), 2); 231 return $luminosity; 232 } 233 234 235 /** 236 * Returns the decimal equivalents for a HEX color. Returns null if it cannot be determined. 237 * @param string $color The hex color value 238 * @return array|null An array where 'r' is the Red value, 'g' is Green, and 'b' is Blue 239 */ 240 public function get_rgb(string $color): ?array { 241 $color = $this->convert_color($color); 242 $c = str_split($color, 2); 243 if (count($c) != 3) { 244 return null; 245 } 246 $results = ['r' => hexdec($c[0]), 'g' => hexdec($c[1]), 'b' => hexdec($c[2])]; 247 return $results; 248 } 249 250 /** 251 * Converts multiple color or background styles into a simple hex string 252 * @param string $color The color attribute to convert (this can also be a multi-value css background value) 253 * @return string A standard CSS hex value for the color 254 */ 255 public function convert_color(string $color): string { 256 $color = trim($color); 257 if (strpos($color, ' ') !== false) { 258 $colors = explode(' ', $color); 259 foreach ($colors as $backgroundpart) { 260 if (substr(trim($backgroundpart), 0, 1) == '#' || 261 in_array(trim($backgroundpart), array_keys($this->colornames)) || 262 strtolower(substr(trim($backgroundpart), 0, 3)) == 'rgb') { 263 $color = $backgroundpart; 264 } 265 } 266 } 267 // Normal hex color. 268 if (substr($color, 0, 1) == '#') { 269 if (strlen($color) == 7) { 270 return str_replace('#', '', $color); 271 } else if (strlen($color) == 4) { 272 return substr($color, 1, 1) . substr($color, 1, 1) . 273 substr($color, 2, 1) . substr($color, 2, 1) . 274 substr($color, 3, 1) . substr($color, 3, 1); 275 } else { 276 return "000000"; 277 } 278 } 279 // Named Color. 280 if (in_array($color, array_keys($this->colornames))) { 281 return $this->colornames[$color]; 282 } 283 // RGB values. 284 if (strtolower(substr($color, 0, 3)) == 'rgb') { 285 $colors = explode(',', trim(str_replace('rgb(', '', $color), '()')); 286 if (count($colors) != 3) { 287 return false; 288 } 289 $r = intval($colors[0]); 290 $g = intval($colors[1]); 291 $b = intval($colors[2]); 292 293 $r = dechex($r < 0 ? 0 : ($r > 255 ? 255 : $r)); 294 $g = dechex($g < 0 ? 0 : ($g > 255 ? 255 : $g)); 295 $b = dechex($b < 0 ? 0 : ($b > 255 ? 255 : $b)); 296 297 $color = (strlen($r) < 2 ? '0' : '') . $r; 298 $color .= (strlen($g) < 2 ? '0' : '') . $g; 299 $color .= (strlen($b) < 2 ? '0' : '') . $b; 300 return $color; 301 } 302 303 return ''; 304 } 305 306 /** 307 * Returns the WAIERT contrast between two colors 308 * @param string $foreground 309 * @param string $background 310 * @return array 311 * @see get_luminosity 312 */ 313 public function get_wai_ert_contrast(string $foreground, string $background): array { 314 $forergb = $this->get_rgb($foreground); 315 $backrgb = $this->get_rgb($background); 316 317 // If get_rgb returns null for either, return 0. 318 if ($forergb === null || $backrgb === null) { 319 return []; 320 } 321 322 $diffs = $this->get_wai_diffs($forergb, $backrgb); 323 324 return $diffs['red'] + $diffs['green'] + $diffs['blue']; 325 } 326 327 /** 328 * Returns the WAI ERT Brightness between two colors 329 * @param string $foreground 330 * @param string $background 331 * @return float|int 332 */ 333 public function get_wai_ert_brightness(string $foreground, string $background): float { 334 $forergb = $this->get_rgb($foreground); 335 $backrgb = $this->get_rgb($background); 336 337 // If get_rgb returns null for either, return 0. 338 if ($forergb === null || $backrgb === null) { 339 return 0; 340 } 341 342 $color = $this->get_wai_diffs($forergb, $backrgb); 343 return (($color['red'] * 299) + ($color['green'] * 587) + ($color['blue'] * 114)) / 1000; 344 } 345 346 /** 347 * Get the wai differences. 348 * @param array $forergb 349 * @param array $backrgb 350 * @return array 351 */ 352 public function get_wai_diffs(array $forergb, array $backrgb): array { 353 $reddiff = ($forergb['r'] > $backrgb['r']) 354 ? $forergb['r'] - $backrgb['r'] 355 : $backrgb['r'] - $forergb['r']; 356 $greendiff = ($forergb['g'] > $backrgb['g']) 357 ? $forergb['g'] - $backrgb['g'] 358 : $backrgb['g'] - $forergb['g']; 359 360 $bluediff = ($forergb['b'] > $backrgb['b']) 361 ? $forergb['b'] - $backrgb['b'] 362 : $backrgb['b'] - $forergb['b']; 363 return ['red' => $reddiff, 'green' => $greendiff, 'blue' => $bluediff]; 364 } 365 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body