/** * Standard modular run function for snippet hooks. Generates XHTML to insert into a page using AJAX. * * @return tempcode The snippet */ function run() { $theme = get_param('theme'); $equation = get_param('css_equation'); require_code('themewizard'); $css_path = get_custom_file_base() . '/themes/' . $theme . '/css_custom/global.css'; if (!file_exists($css_path)) { $css_path = get_file_base() . '/themes/default/css/global.css'; } $css_file_contents = file_get_contents($css_path, FILE_TEXT); $seed = find_theme_seed($theme); $dark = strpos($css_file_contents, '#000000; /* {$,wizard, 100% W/B} */') !== false; $colours = calculate_theme($seed, $theme, 'equations', 'colours', $dark); $parsed_equation = parse_css_colour_expression($equation); if (is_null($parsed_equation)) { return make_string_tempcode(''); } $answer = execute_css_colour_expression($parsed_equation, $colours[0]); if (is_null($answer)) { return make_string_tempcode(''); } return make_string_tempcode('#' . $answer); }
/** * Execute CSS colour expression. * * @param mixed Expression tree (array) OR leaf (string). * @param array Known colours at this point. * @return ?string RRGGBB colour or possibly just a number (NULL: answer cannot be computed). */ function execute_css_colour_expression($expression, $colours) { if (!is_array($expression)) { if (preg_match('#^[0-9A-Fa-f]{6}$#', $expression) != 0) { return $expression; } if (preg_match('#^\\#[0-9A-Fa-f]{6}$#', $expression) != 0) { return substr($expression, 1); } if (preg_match('#^\\d+$#', $expression) != 0) { return $expression; } foreach ($colours as $colour => $actual_colour) { if ($colour == $expression) { return $actual_colour; } } return NULL; // Couldn't find it - we'll have to instruct it to come back to it } $operation = $expression[0]; $operand_a = execute_css_colour_expression($expression[1], $colours); if (is_null($operand_a)) { return NULL; } /*if (($operation=='+') && ($expression[2][0]=='*') && (!is_array($expression[2][1])) && ((($expression[2][2]=='!W/B') && ($colours['L/D']=='light')) || (($expression[2][2]=='W/B') && ($colours['L/D']=='dark')))) { $operation='-'; $expression[2][2]='FFFFFF'; } else { // if (($operation=='-') && ($expression[2][0]=='*') && (!is_array($expression[2][1])) && ((($expression[2][2]=='W/B') && ($colours['L/D']=='light')) || (($expression[2][2]=='!W/B') && ($colours['L/D']=='dark')))) // $operation='+'; }*/ $operand_b = execute_css_colour_expression($expression[2], $colours); if (is_null($operand_b)) { return NULL; } if ($operation[0] == '&') { $operand_c = str_replace('%', '', substr($operation, 1)); $operation = '&'; } switch ($operation) { /* These are percentage modifiers */ case 'sat_to': list($h, $s, $v) = rgb_to_hsv($operand_a); $result = $s == 0 ? hsv_to_rgb(floatval($h), floatval($s), floatval(fix_colour(255 * intval($operand_b) / 100.0))) : hsv_to_rgb(floatval($h), floatval(fix_colour(255 * intval($operand_b) / 100.0)), floatval($v)); break; case 'sat_add': list($h, $s, $v) = rgb_to_hsv($operand_a); $result = hsv_to_rgb(floatval($h), floatval(fix_colour($s + intval($operand_b))), floatval($v)); break; case 'sat': list($h, $s, $v) = rgb_to_hsv($operand_a); $result = hsv_to_rgb(floatval($h), floatval(fix_colour($s * intval($operand_b) / 100.0)), floatval($v)); break; case 'val_to': list($h, $s, $v) = rgb_to_hsv($operand_a); $result = hsv_to_rgb(floatval($h), floatval($s), floatval(fix_colour(255 * intval($operand_b) / 100.0))); break; case 'val_add': list($h, $s, $v) = rgb_to_hsv($operand_a); $result = hsv_to_rgb(floatval($h), floatval($s), floatval(fix_colour($v + intval($operand_b)))); break; case 'val': list($h, $s, $v) = rgb_to_hsv($operand_a); $result = hsv_to_rgb(floatval($h), floatval($s), floatval(fix_colour($v * intval($operand_b) / 100.0))); break; case 'hue_to': list($h, $s, $v) = rgb_to_hsv($operand_a); $result = hsv_to_rgb(floatval(fix_colour(255 * intval($operand_b) / 100.0, true)), floatval($s), floatval($v)); break; case 'hue_add': list($h, $s, $v) = rgb_to_hsv($operand_a); $result = hsv_to_rgb(floatval(fix_colour($h + intval($operand_b), true)), floatval($s), floatval($v)); break; case 'hue': list($h, $s, $v) = rgb_to_hsv($operand_a); $result = hsv_to_rgb(floatval(fix_colour($h * intval($operand_b) / 100.0, true) % 255), floatval($s), floatval($v)); break; case '&': $red = hexdec(substr($operand_a, 0, 2)); $green = hexdec(substr($operand_a, 2, 2)); $blue = hexdec(substr($operand_a, 4, 2)); $fraction = 1.0 - $operand_c / 100.0; $red_b = hexdec(substr($operand_b, 0, 2)); $green_b = hexdec(substr($operand_b, 2, 2)); $blue_b = hexdec(substr($operand_b, 4, 2)); $red = intval($fraction * $red + (1 - $fraction) * $red_b); $green = intval($fraction * $green + (1 - $fraction) * $green_b); $blue = intval($fraction * $blue + (1 - $fraction) * $blue_b); $result = str_pad(dechex(fix_colour($red)), 2, '0', STR_PAD_LEFT) . str_pad(dechex(fix_colour($green)), 2, '0', STR_PAD_LEFT) . str_pad(dechex(fix_colour($blue)), 2, '0', STR_PAD_LEFT); break; case '*': $red = intval(round(floatval(hexdec(substr($operand_b, 0, 2)) * intval($operand_a)) / 100.0)); $green = intval(round(floatval(hexdec(substr($operand_b, 2, 2)) * intval($operand_a)) / 100.0)); $blue = intval(round(floatval(hexdec(substr($operand_b, 4, 2)) * intval($operand_a)) / 100.0)); /*if ((($expression[2]==='W/B') && ($colours['L/D']=='dark')) || (($expression[2]==='!W/B') && ($colours['L/D']=='light'))) { $red=255-$red; $green=255-$green; $blue=255-$blue; }*/ $result = str_pad(dechex($red), 2, '0', STR_PAD_LEFT) . str_pad(dechex($green), 2, '0', STR_PAD_LEFT) . str_pad(dechex($blue), 2, '0', STR_PAD_LEFT); break; /* These are communicative combinators */ /* These are communicative combinators */ case '+': $red = fix_colour(hexdec(substr($operand_a, 0, 2)) + hexdec(substr($operand_b, 0, 2))); $green = fix_colour(hexdec(substr($operand_a, 2, 2)) + hexdec(substr($operand_b, 2, 2))); $blue = fix_colour(hexdec(substr($operand_a, 4, 2)) + hexdec(substr($operand_b, 4, 2))); $result = str_pad(dechex($red), 2, '0', STR_PAD_LEFT) . str_pad(dechex($green), 2, '0', STR_PAD_LEFT) . str_pad(dechex($blue), 2, '0', STR_PAD_LEFT); break; case '-': $red = fix_colour(hexdec(substr($operand_a, 0, 2)) - hexdec(substr($operand_b, 0, 2))); $green = fix_colour(hexdec(substr($operand_a, 2, 2)) - hexdec(substr($operand_b, 2, 2))); $blue = fix_colour(hexdec(substr($operand_a, 4, 2)) - hexdec(substr($operand_b, 4, 2))); $result = str_pad(dechex($red), 2, '0', STR_PAD_LEFT) . str_pad(dechex($green), 2, '0', STR_PAD_LEFT) . str_pad(dechex($blue), 2, '0', STR_PAD_LEFT); break; /* These are miscellaneous */ /* These are miscellaneous */ case 'shift': if (intval($operand_b) == 1) { $result = substr($operand_a, 4) . substr($operand_a, 0, 4); } else { $result = substr($operand_a, 2) . substr($operand_a, 0, 2); } break; } return $result; }