| [ Index ] |
PHP Cross Reference of Drupal 6 (gatewave) |
[Summary view] [Print] [Text view]
1 <?php 2 // $Id: color.module,v 1.39.2.2 2009/05/16 16:09:21 dries Exp $ 3 4 /** 5 * Implementation of hook_help(). 6 */ 7 function color_help($path, $arg) { 8 switch ($path) { 9 case 'admin/help#color': 10 $output = '<p>'. t('The color module allows a site administrator to quickly and easily change the color scheme of certain themes. Although not all themes support color module, both Garland (the default theme) and Minnelli were designed to take advantage of its features. By using color module with a compatible theme, you can easily change the color of links, backgrounds, text, and other theme elements. Color module requires that your <a href="@url">file download method</a> be set to public.', array('@url' => url('admin/settings/file-system'))) .'</p>'; 11 $output .= '<p>'. t("It is important to remember that color module saves a modified copy of the theme's specified stylesheets in the files directory. This means that if you make any manual changes to your theme's stylesheet, you must save your color settings again, even if they haven't changed. This causes the color module generated version of the stylesheets in the files directory to be recreated using the new version of the original file.") .'</p>'; 12 $output .= '<p>'. t('To change the color settings for a compatible theme, select the "configure" link for the theme on the <a href="@themes">themes administration page</a>.', array('@themes' => url('admin/build/themes'))) .'</p>'; 13 $output .= '<p>'. t('For more information, see the online handbook entry for <a href="@color">Color module</a>.', array('@color' => 'http://drupal.org/handbook/modules/color/')) .'</p>'; 14 return $output; 15 } 16 } 17 18 /** 19 * Implementation of hook_theme(). 20 */ 21 function color_theme() { 22 return array( 23 'color_scheme_form' => array( 24 'arguments' => array('form' => NULL), 25 ), 26 ); 27 } 28 29 /** 30 * Implementation of hook_form_alter(). 31 */ 32 function color_form_alter(&$form, $form_state, $form_id) { 33 // Insert the color changer into the theme settings page. 34 if ($form_id == 'system_theme_settings' && color_get_info(arg(4)) && function_exists('gd_info')) { 35 if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) != FILE_DOWNLOADS_PUBLIC) { 36 // Disables the color changer when the private download method is used. 37 // TODO: This should be solved in a different way. See issue #181003. 38 drupal_set_message(t('The color picker only works if the <a href="@url">download method</a> is set to public.', array('@url' => url('admin/settings/file-system'))), 'warning'); 39 } 40 else { 41 $form['color'] = array( 42 '#type' => 'fieldset', 43 '#title' => t('Color scheme'), 44 '#weight' => -1, 45 '#attributes' => array('id' => 'color_scheme_form'), 46 '#theme' => 'color_scheme_form', 47 ); 48 $form['color'] += color_scheme_form($form_state, arg(4)); 49 $form['#submit'][] = 'color_scheme_form_submit'; 50 } 51 } 52 53 // Use the generated screenshot in the theme list. 54 if ($form_id == 'system_theme_select_form' || $form_id == 'system_themes') { 55 $themes = list_themes(); 56 foreach (element_children($form) as $theme) { 57 if ($screenshot = variable_get('color_'. $theme .'_screenshot', NULL)) { 58 if (isset($form[$theme]['screenshot'])) { 59 $form[$theme]['screenshot']['#value'] = theme('image', $screenshot, '', '', array('class' => 'screenshot'), FALSE); 60 } 61 } 62 } 63 } 64 } 65 66 /** 67 * Callback for the theme to alter the resources used. 68 */ 69 function _color_page_alter(&$vars) { 70 global $language, $theme_key; 71 72 // Override stylesheets. 73 $color_paths = variable_get('color_'. $theme_key .'_stylesheets', array()); 74 if (!empty($color_paths)) { 75 // Loop over theme CSS files and try to rebuild CSS array with rewritten 76 // stylesheets. Keep the orginal order intact for CSS cascading. 77 $new_theme_css = array(); 78 79 foreach ($vars['css']['all']['theme'] as $old_path => $old_preprocess) { 80 // Add the non-colored stylesheet first as we might not find a 81 // re-colored stylesheet for replacement later. 82 $new_theme_css[$old_path] = $old_preprocess; 83 84 // Loop over the path array with recolored CSS files to find matching 85 // paths which could replace the non-recolored paths. 86 foreach ($color_paths as $color_path) { 87 // Color module currently requires unique file names to be used, 88 // which allows us to compare different file paths. 89 if (basename($old_path) == basename($color_path)) { 90 // Pull out the non-colored and add rewritten stylesheet. 91 unset($new_theme_css[$old_path]); 92 $new_theme_css[$color_path] = $old_preprocess; 93 94 // If the current language is RTL and the CSS file had an RTL variant, 95 // pull out the non-colored and add rewritten RTL stylesheet. 96 if ($language->direction == LANGUAGE_RTL) { 97 $rtl_old_path = str_replace('.css', '-rtl.css', $old_path); 98 $rtl_color_path = str_replace('.css', '-rtl.css', $color_path); 99 if (file_exists($rtl_color_path)) { 100 unset($new_theme_css[$rtl_old_path]); 101 $new_theme_css[$rtl_color_path] = $old_preprocess; 102 } 103 } 104 break; 105 } 106 } 107 } 108 $vars['css']['all']['theme'] = $new_theme_css; 109 $vars['styles'] = drupal_get_css($vars['css']); 110 } 111 112 // Override logo. 113 $logo = variable_get('color_'. $theme_key .'_logo', NULL); 114 if ($logo && $vars['logo'] && preg_match('!'. $theme_key .'/logo.png$!', $vars['logo'])) { 115 $vars['logo'] = base_path() . $logo; 116 } 117 } 118 119 /** 120 * Retrieve the color.module info for a particular theme. 121 */ 122 function color_get_info($theme) { 123 $path = drupal_get_path('theme', $theme); 124 $file = $path .'/color/color.inc'; 125 if ($path && file_exists($file)) { 126 include $file; 127 return $info; 128 } 129 } 130 131 /** 132 * Helper function to retrieve the color palette for a particular theme. 133 */ 134 function color_get_palette($theme, $default = false) { 135 // Fetch and expand default palette 136 $fields = array('base', 'link', 'top', 'bottom', 'text'); 137 $info = color_get_info($theme); 138 $keys = array_keys($info['schemes']); 139 foreach (explode(',', array_shift($keys)) as $k => $scheme) { 140 $palette[$fields[$k]] = $scheme; 141 } 142 143 // Load variable 144 return $default ? $palette : variable_get('color_'. $theme .'_palette', $palette); 145 } 146 147 /** 148 * Form callback. Returns the configuration form. 149 */ 150 function color_scheme_form(&$form_state, $theme) { 151 $base = drupal_get_path('module', 'color'); 152 $info = color_get_info($theme); 153 154 // Add Farbtastic color picker 155 drupal_add_css('misc/farbtastic/farbtastic.css', 'module', 'all', FALSE); 156 drupal_add_js('misc/farbtastic/farbtastic.js'); 157 158 // Add custom CSS/JS 159 drupal_add_css($base .'/color.css', 'module', 'all', FALSE); 160 drupal_add_js($base .'/color.js'); 161 drupal_add_js(array('color' => array( 162 'reference' => color_get_palette($theme, true) 163 )), 'setting'); 164 165 // See if we're using a predefined scheme 166 $current = implode(',', variable_get('color_'. $theme .'_palette', array())); 167 // Note: we use the original theme when the default scheme is chosen. 168 $current = isset($info['schemes'][$current]) ? $current : ($current == '' ? reset($info['schemes']) : ''); 169 170 // Add scheme selector 171 $info['schemes'][''] = t('Custom'); 172 $form['scheme'] = array( 173 '#type' => 'select', 174 '#title' => t('Color set'), 175 '#options' => $info['schemes'], 176 '#default_value' => $current, 177 ); 178 179 // Add palette fields 180 $palette = color_get_palette($theme); 181 $names = array( 182 'base' => t('Base color'), 183 'link' => t('Link color'), 184 'top' => t('Header top'), 185 'bottom' => t('Header bottom'), 186 'text' => t('Text color') 187 ); 188 $form['palette']['#tree'] = true; 189 foreach ($palette as $name => $value) { 190 $form['palette'][$name] = array( 191 '#type' => 'textfield', 192 '#title' => $names[$name], 193 '#default_value' => $value, 194 '#size' => 8, 195 ); 196 } 197 $form['theme'] = array('#type' => 'value', '#value' => arg(4)); 198 $form['info'] = array('#type' => 'value', '#value' => $info); 199 200 return $form; 201 } 202 203 /** 204 * Theme color form. 205 * 206 * @ingroup themeable 207 */ 208 function theme_color_scheme_form($form) { 209 // Include stylesheet 210 $theme = $form['theme']['#value']; 211 $info = $form['info']['#value']; 212 $path = drupal_get_path('theme', $theme) .'/'; 213 drupal_add_css($path . $info['preview_css']); 214 $output = ''; 215 // Wrapper 216 $output .= '<div class="color-form clear-block">'; 217 218 // Color schemes 219 $output .= drupal_render($form['scheme']); 220 221 // Palette 222 $output .= '<div id="palette" class="clear-block">'; 223 foreach (element_children($form['palette']) as $name) { 224 $output .= drupal_render($form['palette'][$name]); 225 } 226 $output .= '</div>'; 227 228 // Preview 229 $output .= drupal_render($form); 230 $output .= '<h2>'. t('Preview') .'</h2>'; 231 $output .= '<div id="preview"><div id="text"><h2>Lorem ipsum dolor</h2><p>Sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud <a href="#">exercitation ullamco</a> laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p></div><div id="img" style="background-image: url('. base_path() . $path . $info['preview_image'] .')"></div></div>'; 232 233 // Close wrapper 234 $output .= '</div>'; 235 236 return $output; 237 } 238 239 /** 240 * Submit handler for color change form. 241 */ 242 function color_scheme_form_submit($form, &$form_state) { 243 // Get theme coloring info 244 if (!isset($form_state['values']['info'])) { 245 return; 246 } 247 $theme = $form_state['values']['theme']; 248 $info = $form_state['values']['info']; 249 250 // Resolve palette 251 $palette = $form_state['values']['palette']; 252 if ($form_state['values']['scheme'] != '') { 253 $scheme = explode(',', $form_state['values']['scheme']); 254 foreach ($palette as $k => $color) { 255 $palette[$k] = array_shift($scheme); 256 } 257 } 258 259 // Make sure enough memory is available, if PHP's memory limit is compiled in. 260 if (function_exists('memory_get_usage')) { 261 // Fetch source image dimensions. 262 $source = drupal_get_path('theme', $theme) .'/'. $info['base_image']; 263 list($width, $height) = getimagesize($source); 264 265 // We need at least a copy of the source and a target buffer of the same 266 // size (both at 32bpp). 267 $required = $width * $height * 8; 268 $usage = memory_get_usage(); 269 $limit = parse_size(ini_get('memory_limit')); 270 if ($usage + $required > $limit) { 271 drupal_set_message(t('There is not enough memory available to PHP to change this theme\'s color scheme. You need at least %size more. Check the <a href="@url">PHP documentation</a> for more information.', array('%size' => format_size($usage + $required - $limit), '@url' => 'http://www.php.net/manual/en/ini.core.php#ini.sect.resource-limits')), 'error'); 272 return; 273 } 274 } 275 276 // Delete old files 277 foreach (variable_get('color_'. $theme .'_files', array()) as $file) { 278 @unlink($file); 279 } 280 if (isset($file) && $file = dirname($file)) { 281 @rmdir($file); 282 } 283 284 // Don't render the default colorscheme, use the standard theme instead. 285 if (implode(',', color_get_palette($theme, true)) == implode(',', $palette) 286 || $form_state['values']['op'] == t('Reset to defaults')) { 287 variable_del('color_'. $theme .'_palette'); 288 variable_del('color_'. $theme .'_stylesheets'); 289 variable_del('color_'. $theme .'_logo'); 290 variable_del('color_'. $theme .'_files'); 291 variable_del('color_'. $theme .'_screenshot'); 292 return; 293 } 294 295 // Prepare target locations for generated files. 296 $id = $theme .'-'. substr(md5(serialize($palette) . microtime()), 0, 8); 297 $paths['color'] = file_directory_path() .'/color'; 298 $paths['target'] = $paths['color'] .'/'. $id; 299 foreach ($paths as $path) { 300 file_check_directory($path, FILE_CREATE_DIRECTORY); 301 } 302 $paths['target'] = $paths['target'] .'/'; 303 $paths['id'] = $id; 304 $paths['source'] = drupal_get_path('theme', $theme) .'/'; 305 $paths['files'] = $paths['map'] = array(); 306 307 // Save palette and logo location. 308 variable_set('color_'. $theme .'_palette', $palette); 309 variable_set('color_'. $theme .'_logo', $paths['target'] .'logo.png'); 310 311 // Copy over neutral images. 312 foreach ($info['copy'] as $file) { 313 $base = basename($file); 314 $source = $paths['source'] . $file; 315 file_copy($source, $paths['target'] . $base); 316 $paths['map'][$file] = $base; 317 $paths['files'][] = $paths['target'] . $base; 318 } 319 320 // Render new images, if image provided. 321 if ($info['base_image']) { 322 _color_render_images($theme, $info, $paths, $palette); 323 } 324 325 // Rewrite theme stylesheets. 326 $css = array(); 327 foreach ($info['css'] as $stylesheet) { 328 // Build a temporary array with LTR and RTL files. 329 $files = array(); 330 if (file_exists($paths['source'] . $stylesheet)) { 331 $files[] = $stylesheet; 332 333 $rtl_file = str_replace('.css', '-rtl.css', $stylesheet); 334 if (file_exists($paths['source'] . $rtl_file)) { 335 $files[] = $rtl_file; 336 } 337 } 338 339 foreach ($files as $file) { 340 // Aggregate @imports recursively for each configured top level CSS file 341 // without optimization. Aggregation and optimization will be 342 // handled by drupal_build_css_cache() only. 343 $style = drupal_load_stylesheet($paths['source'] . $file, FALSE); 344 345 // Return the path to where this CSS file originated from, stripping 346 // off the name of the file at the end of the path. 347 $base = base_path() . dirname($paths['source'] . $file) .'/'; 348 _drupal_build_css_path(NULL, $base); 349 350 // Prefix all paths within this CSS file, ignoring absolute paths. 351 $style = preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $style); 352 353 // Rewrite stylesheet with new colors. 354 $style = _color_rewrite_stylesheet($theme, $info, $paths, $palette, $style); 355 $base_file = basename($file); 356 $css[] = $paths['target'] . $base_file; 357 _color_save_stylesheet($paths['target'] . $base_file, $style, $paths); 358 } 359 } 360 361 // Maintain list of files. 362 variable_set('color_'. $theme .'_stylesheets', $css); 363 variable_set('color_'. $theme .'_files', $paths['files']); 364 } 365 366 /** 367 * Rewrite the stylesheet to match the colors in the palette. 368 */ 369 function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette, $style) { 370 $themes = list_themes(); 371 372 // Prepare color conversion table 373 $conversion = $palette; 374 unset($conversion['base']); 375 foreach ($conversion as $k => $v) { 376 $conversion[$k] = drupal_strtolower($v); 377 } 378 $default = color_get_palette($theme, true); 379 380 // Split off the "Don't touch" section of the stylesheet. 381 $split = "Color Module: Don't touch"; 382 if (strpos($style, $split) !== FALSE) { 383 list($style, $fixed) = explode($split, $style); 384 } 385 386 // Find all colors in the stylesheet and the chunks in between. 387 $style = preg_split('/(#[0-9a-f]{6}|#[0-9a-f]{3})/i', $style, -1, PREG_SPLIT_DELIM_CAPTURE); 388 $is_color = false; 389 $output = ''; 390 $base = 'base'; 391 392 // Iterate over all parts. 393 foreach ($style as $chunk) { 394 if ($is_color) { 395 $chunk = drupal_strtolower($chunk); 396 // Check if this is one of the colors in the default palette. 397 if ($key = array_search($chunk, $default)) { 398 $chunk = $conversion[$key]; 399 } 400 // Not a pre-set color. Extrapolate from the base. 401 else { 402 $chunk = _color_shift($palette[$base], $default[$base], $chunk, $info['blend_target']); 403 } 404 } 405 else { 406 // Determine the most suitable base color for the next color. 407 408 // 'a' declarations. Use link. 409 if (preg_match('@[^a-z0-9_-](a)[^a-z0-9_-][^/{]*{[^{]+$@i', $chunk)) { 410 $base = 'link'; 411 } 412 // 'color:' styles. Use text. 413 else if (preg_match('/(?<!-)color[^{:]*:[^{#]*$/i', $chunk)) { 414 $base = 'text'; 415 } 416 // Reset back to base. 417 else { 418 $base = 'base'; 419 } 420 } 421 $output .= $chunk; 422 $is_color = !$is_color; 423 } 424 // Append fixed colors segment. 425 if (isset($fixed)) { 426 $output .= $fixed; 427 } 428 429 // Replace paths to images. 430 foreach ($paths['map'] as $before => $after) { 431 $before = base_path() . $paths['source'] . $before; 432 $before = preg_replace('`(^|/)(?!../)([^/]+)/../`', '$1', $before); 433 $output = str_replace($before, $after, $output); 434 } 435 436 return $output; 437 } 438 439 /** 440 * Save the rewritten stylesheet to disk. 441 */ 442 function _color_save_stylesheet($file, $style, &$paths) { 443 444 // Write new stylesheet. 445 file_save_data($style, $file, FILE_EXISTS_REPLACE); 446 $paths['files'][] = $file; 447 448 // Set standard file permissions for webserver-generated files. 449 @chmod($file, 0664); 450 } 451 452 /** 453 * Render images that match a given palette. 454 */ 455 function _color_render_images($theme, &$info, &$paths, $palette) { 456 457 // Prepare template image. 458 $source = $paths['source'] .'/'. $info['base_image']; 459 $source = imagecreatefrompng($source); 460 $width = imagesx($source); 461 $height = imagesy($source); 462 463 // Prepare target buffer. 464 $target = imagecreatetruecolor($width, $height); 465 imagealphablending($target, true); 466 467 // Fill regions of solid color. 468 foreach ($info['fill'] as $color => $fill) { 469 imagefilledrectangle($target, $fill[0], $fill[1], $fill[0] + $fill[2], $fill[1] + $fill[3], _color_gd($target, $palette[$color])); 470 } 471 472 // Render gradient. 473 for ($y = 0; $y < $info['gradient'][3]; ++$y) { 474 $color = _color_blend($target, $palette['top'], $palette['bottom'], $y / ($info['gradient'][3] - 1)); 475 imagefilledrectangle($target, $info['gradient'][0], $info['gradient'][1] + $y, $info['gradient'][0] + $info['gradient'][2], $info['gradient'][1] + $y + 1, $color); 476 } 477 478 // Blend over template. 479 imagecopy($target, $source, 0, 0, 0, 0, $width, $height); 480 481 // Clean up template image. 482 imagedestroy($source); 483 484 // Cut out slices. 485 foreach ($info['slices'] as $file => $coord) { 486 list($x, $y, $width, $height) = $coord; 487 $base = basename($file); 488 $image = $paths['target'] . $base; 489 490 // Cut out slice. 491 if ($file == 'screenshot.png') { 492 $slice = imagecreatetruecolor(150, 90); 493 imagecopyresampled($slice, $target, 0, 0, $x, $y, 150, 90, $width, $height); 494 variable_set('color_'. $theme .'_screenshot', $image); 495 } 496 else { 497 $slice = imagecreatetruecolor($width, $height); 498 imagecopy($slice, $target, 0, 0, $x, $y, $width, $height); 499 } 500 501 // Save image. 502 imagepng($slice, $image); 503 imagedestroy($slice); 504 $paths['files'][] = $image; 505 506 // Set standard file permissions for webserver-generated files 507 @chmod(realpath($image), 0664); 508 509 // Build before/after map of image paths. 510 $paths['map'][$file] = $base; 511 } 512 513 // Clean up target buffer. 514 imagedestroy($target); 515 } 516 517 /** 518 * Shift a given color, using a reference pair and a target blend color. 519 * 520 * Note: this function is significantly different from the JS version, as it 521 * is written to match the blended images perfectly. 522 * 523 * Constraint: if (ref2 == target + (ref1 - target) * delta) for some fraction delta 524 * then (return == target + (given - target) * delta) 525 * 526 * Loose constraint: Preserve relative positions in saturation and luminance 527 * space. 528 */ 529 function _color_shift($given, $ref1, $ref2, $target) { 530 531 // We assume that ref2 is a blend of ref1 and target and find 532 // delta based on the length of the difference vectors: 533 534 // delta = 1 - |ref2 - ref1| / |white - ref1| 535 $target = _color_unpack($target, true); 536 $ref1 = _color_unpack($ref1, true); 537 $ref2 = _color_unpack($ref2, true); 538 $numerator = 0; 539 $denominator = 0; 540 for ($i = 0; $i < 3; ++$i) { 541 $numerator += ($ref2[$i] - $ref1[$i]) * ($ref2[$i] - $ref1[$i]); 542 $denominator += ($target[$i] - $ref1[$i]) * ($target[$i] - $ref1[$i]); 543 } 544 $delta = ($denominator > 0) ? (1 - sqrt($numerator / $denominator)) : 0; 545 546 // Calculate the color that ref2 would be if the assumption was true. 547 for ($i = 0; $i < 3; ++$i) { 548 $ref3[$i] = $target[$i] + ($ref1[$i] - $target[$i]) * $delta; 549 } 550 551 // If the assumption is not true, there is a difference between ref2 and ref3. 552 // We measure this in HSL space. Notation: x' = hsl(x). 553 $ref2 = _color_rgb2hsl($ref2); 554 $ref3 = _color_rgb2hsl($ref3); 555 for ($i = 0; $i < 3; ++$i) { 556 $shift[$i] = $ref2[$i] - $ref3[$i]; 557 } 558 559 // Take the given color, and blend it towards the target. 560 $given = _color_unpack($given, true); 561 for ($i = 0; $i < 3; ++$i) { 562 $result[$i] = $target[$i] + ($given[$i] - $target[$i]) * $delta; 563 } 564 565 // Finally, we apply the extra shift in HSL space. 566 // Note: if ref2 is a pure blend of ref1 and target, then |shift| = 0. 567 $result = _color_rgb2hsl($result); 568 for ($i = 0; $i < 3; ++$i) { 569 $result[$i] = min(1, max(0, $result[$i] + $shift[$i])); 570 } 571 $result = _color_hsl2rgb($result); 572 573 // Return hex color. 574 return _color_pack($result, true); 575 } 576 577 /** 578 * Convert a hex triplet into a GD color. 579 */ 580 function _color_gd($img, $hex) { 581 $c = array_merge(array($img), _color_unpack($hex)); 582 return call_user_func_array('imagecolorallocate', $c); 583 } 584 585 /** 586 * Blend two hex colors and return the GD color. 587 */ 588 function _color_blend($img, $hex1, $hex2, $alpha) { 589 $in1 = _color_unpack($hex1); 590 $in2 = _color_unpack($hex2); 591 $out = array($img); 592 for ($i = 0; $i < 3; ++$i) { 593 $out[] = $in1[$i] + ($in2[$i] - $in1[$i]) * $alpha; 594 } 595 return call_user_func_array('imagecolorallocate', $out); 596 } 597 598 /** 599 * Convert a hex color into an RGB triplet. 600 */ 601 function _color_unpack($hex, $normalize = false) { 602 if (strlen($hex) == 4) { 603 $hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3]; 604 } 605 $c = hexdec($hex); 606 for ($i = 16; $i >= 0; $i -= 8) { 607 $out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1); 608 } 609 return $out; 610 } 611 612 /** 613 * Convert an RGB triplet to a hex color. 614 */ 615 function _color_pack($rgb, $normalize = false) { 616 $out = 0; 617 foreach ($rgb as $k => $v) { 618 $out |= (($v * ($normalize ? 255 : 1)) << (16 - $k * 8)); 619 } 620 return '#'. str_pad(dechex($out), 6, 0, STR_PAD_LEFT); 621 } 622 623 /** 624 * Convert a HSL triplet into RGB 625 */ 626 function _color_hsl2rgb($hsl) { 627 $h = $hsl[0]; 628 $s = $hsl[1]; 629 $l = $hsl[2]; 630 $m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l*$s; 631 $m1 = $l * 2 - $m2; 632 return array( 633 _color_hue2rgb($m1, $m2, $h + 0.33333), 634 _color_hue2rgb($m1, $m2, $h), 635 _color_hue2rgb($m1, $m2, $h - 0.33333), 636 ); 637 } 638 639 /** 640 * Helper function for _color_hsl2rgb(). 641 */ 642 function _color_hue2rgb($m1, $m2, $h) { 643 $h = ($h < 0) ? $h + 1 : (($h > 1) ? $h - 1 : $h); 644 if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6; 645 if ($h * 2 < 1) return $m2; 646 if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (0.66666 - $h) * 6; 647 return $m1; 648 } 649 650 /** 651 * Convert an RGB triplet to HSL. 652 */ 653 function _color_rgb2hsl($rgb) { 654 $r = $rgb[0]; 655 $g = $rgb[1]; 656 $b = $rgb[2]; 657 $min = min($r, min($g, $b)); 658 $max = max($r, max($g, $b)); 659 $delta = $max - $min; 660 $l = ($min + $max) / 2; 661 $s = 0; 662 if ($l > 0 && $l < 1) { 663 $s = $delta / ($l < 0.5 ? (2 * $l) : (2 - 2 * $l)); 664 } 665 $h = 0; 666 if ($delta > 0) { 667 if ($max == $r && $max != $g) $h += ($g - $b) / $delta; 668 if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta); 669 if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta); 670 $h /= 6; 671 } 672 return array($h, $s, $l); 673 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Thu Mar 24 11:18:33 2011 | Cross-referenced by PHPXref 0.7 |