| [ Index ] |
PHP Cross Reference of Drupal 6 (yi-drupal) |
[Summary view] [Print] [Text view]
1 <?php 2 3 /** 4 * Implementation of hook_help(). 5 */ 6 function color_help($path, $arg) { 7 switch ($path) { 8 case 'admin/help#color': 9 $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>'; 10 $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>'; 11 $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>'; 12 $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>'; 13 return $output; 14 } 15 } 16 17 /** 18 * Implementation of hook_theme(). 19 */ 20 function color_theme() { 21 return array( 22 'color_scheme_form' => array( 23 'arguments' => array('form' => NULL), 24 ), 25 ); 26 } 27 28 /** 29 * Implementation of hook_form_alter(). 30 */ 31 function color_form_alter(&$form, $form_state, $form_id) { 32 // Insert the color changer into the theme settings page. 33 if ($form_id == 'system_theme_settings' && color_get_info(arg(4)) && function_exists('gd_info')) { 34 if (variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) != FILE_DOWNLOADS_PUBLIC) { 35 // Disables the color changer when the private download method is used. 36 // TODO: This should be solved in a different way. See issue #181003. 37 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'); 38 } 39 else { 40 $form['color'] = array( 41 '#type' => 'fieldset', 42 '#title' => t('Color scheme'), 43 '#weight' => -1, 44 '#attributes' => array('id' => 'color_scheme_form'), 45 '#theme' => 'color_scheme_form', 46 ); 47 $form['color'] += color_scheme_form($form_state, arg(4)); 48 $form['#validate'][] = 'color_scheme_form_validate'; 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 * Validation handler for color change form. 241 */ 242 function color_scheme_form_validate($form, &$form_state) { 243 // Only accept hexadecimal CSS color strings to avoid XSS upon use. 244 foreach ($form_state['values']['palette'] as $key => $color) { 245 if (!preg_match('/^#([a-f0-9]{3}){1,2}$/iD', $color)) { 246 form_set_error('palette][' . $key, t('%name must be a valid hexadecimal CSS color value.', array('%name' => $form['color']['palette'][$key]['#title']))); 247 } 248 } 249 } 250 251 /** 252 * Submit handler for color change form. 253 */ 254 function color_scheme_form_submit($form, &$form_state) { 255 // Get theme coloring info 256 if (!isset($form_state['values']['info'])) { 257 return; 258 } 259 $theme = $form_state['values']['theme']; 260 $info = $form_state['values']['info']; 261 262 // Resolve palette 263 $palette = $form_state['values']['palette']; 264 if ($form_state['values']['scheme'] != '') { 265 $scheme = explode(',', $form_state['values']['scheme']); 266 foreach ($palette as $k => $color) { 267 $palette[$k] = array_shift($scheme); 268 } 269 } 270 271 // Make sure enough memory is available, if PHP's memory limit is compiled in. 272 if (function_exists('memory_get_usage')) { 273 // Fetch source image dimensions. 274 $source = drupal_get_path('theme', $theme) .'/'. $info['base_image']; 275 list($width, $height) = getimagesize($source); 276 277 // We need at least a copy of the source and a target buffer of the same 278 // size (both at 32bpp). 279 $required = $width * $height * 8; 280 $usage = memory_get_usage(); 281 $limit = parse_size(ini_get('memory_limit')); 282 if ($usage + $required > $limit) { 283 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'); 284 return; 285 } 286 } 287 288 // Delete old files 289 foreach (variable_get('color_'. $theme .'_files', array()) as $file) { 290 @unlink($file); 291 } 292 if (isset($file) && $file = dirname($file)) { 293 @rmdir($file); 294 } 295 296 // Don't render the default colorscheme, use the standard theme instead. 297 if (implode(',', color_get_palette($theme, true)) == implode(',', $palette) 298 || $form_state['values']['op'] == t('Reset to defaults')) { 299 variable_del('color_'. $theme .'_palette'); 300 variable_del('color_'. $theme .'_stylesheets'); 301 variable_del('color_'. $theme .'_logo'); 302 variable_del('color_'. $theme .'_files'); 303 variable_del('color_'. $theme .'_screenshot'); 304 return; 305 } 306 307 // Prepare target locations for generated files. 308 $id = $theme .'-'. substr(md5(serialize($palette) . microtime()), 0, 8); 309 $paths['color'] = file_directory_path() .'/color'; 310 $paths['target'] = $paths['color'] .'/'. $id; 311 foreach ($paths as $path) { 312 file_check_directory($path, FILE_CREATE_DIRECTORY); 313 } 314 $paths['target'] = $paths['target'] .'/'; 315 $paths['id'] = $id; 316 $paths['source'] = drupal_get_path('theme', $theme) .'/'; 317 $paths['files'] = $paths['map'] = array(); 318 319 // Save palette and logo location. 320 variable_set('color_'. $theme .'_palette', $palette); 321 variable_set('color_'. $theme .'_logo', $paths['target'] .'logo.png'); 322 323 // Copy over neutral images. 324 foreach ($info['copy'] as $file) { 325 $base = basename($file); 326 $source = $paths['source'] . $file; 327 file_copy($source, $paths['target'] . $base); 328 $paths['map'][$file] = $base; 329 $paths['files'][] = $paths['target'] . $base; 330 } 331 332 // Render new images, if image provided. 333 if ($info['base_image']) { 334 _color_render_images($theme, $info, $paths, $palette); 335 } 336 337 // Rewrite theme stylesheets. 338 $css = array(); 339 foreach ($info['css'] as $stylesheet) { 340 // Build a temporary array with LTR and RTL files. 341 $files = array(); 342 if (file_exists($paths['source'] . $stylesheet)) { 343 $files[] = $stylesheet; 344 345 $rtl_file = str_replace('.css', '-rtl.css', $stylesheet); 346 if (file_exists($paths['source'] . $rtl_file)) { 347 $files[] = $rtl_file; 348 } 349 } 350 351 foreach ($files as $file) { 352 // Aggregate @imports recursively for each configured top level CSS file 353 // without optimization. Aggregation and optimization will be 354 // handled by drupal_build_css_cache() only. 355 $style = drupal_load_stylesheet($paths['source'] . $file, FALSE); 356 357 // Return the path to where this CSS file originated from, stripping 358 // off the name of the file at the end of the path. 359 $base = base_path() . dirname($paths['source'] . $file) .'/'; 360 _drupal_build_css_path(NULL, $base); 361 362 // Prefix all paths within this CSS file, ignoring absolute paths. 363 $style = preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $style); 364 365 // Rewrite stylesheet with new colors. 366 $style = _color_rewrite_stylesheet($theme, $info, $paths, $palette, $style); 367 $base_file = basename($file); 368 $css[] = $paths['target'] . $base_file; 369 _color_save_stylesheet($paths['target'] . $base_file, $style, $paths); 370 } 371 } 372 373 // Maintain list of files. 374 variable_set('color_'. $theme .'_stylesheets', $css); 375 variable_set('color_'. $theme .'_files', $paths['files']); 376 } 377 378 /** 379 * Rewrite the stylesheet to match the colors in the palette. 380 */ 381 function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette, $style) { 382 $themes = list_themes(); 383 384 // Prepare color conversion table 385 $conversion = $palette; 386 unset($conversion['base']); 387 foreach ($conversion as $k => $v) { 388 $conversion[$k] = drupal_strtolower($v); 389 } 390 $default = color_get_palette($theme, true); 391 392 // Split off the "Don't touch" section of the stylesheet. 393 $split = "Color Module: Don't touch"; 394 if (strpos($style, $split) !== FALSE) { 395 list($style, $fixed) = explode($split, $style); 396 } 397 398 // Find all colors in the stylesheet and the chunks in between. 399 $style = preg_split('/(#[0-9a-f]{6}|#[0-9a-f]{3})/i', $style, -1, PREG_SPLIT_DELIM_CAPTURE); 400 $is_color = false; 401 $output = ''; 402 $base = 'base'; 403 404 // Iterate over all parts. 405 foreach ($style as $chunk) { 406 if ($is_color) { 407 $chunk = drupal_strtolower($chunk); 408 // Check if this is one of the colors in the default palette. 409 if ($key = array_search($chunk, $default)) { 410 $chunk = $conversion[$key]; 411 } 412 // Not a pre-set color. Extrapolate from the base. 413 else { 414 $chunk = _color_shift($palette[$base], $default[$base], $chunk, $info['blend_target']); 415 } 416 } 417 else { 418 // Determine the most suitable base color for the next color. 419 420 // 'a' declarations. Use link. 421 if (preg_match('@[^a-z0-9_-](a)[^a-z0-9_-][^/{]*{[^{]+$@i', $chunk)) { 422 $base = 'link'; 423 } 424 // 'color:' styles. Use text. 425 else if (preg_match('/(?<!-)color[^{:]*:[^{#]*$/i', $chunk)) { 426 $base = 'text'; 427 } 428 // Reset back to base. 429 else { 430 $base = 'base'; 431 } 432 } 433 $output .= $chunk; 434 $is_color = !$is_color; 435 } 436 // Append fixed colors segment. 437 if (isset($fixed)) { 438 $output .= $fixed; 439 } 440 441 // Replace paths to images. 442 foreach ($paths['map'] as $before => $after) { 443 $before = base_path() . $paths['source'] . $before; 444 $before = preg_replace('`(^|/)(?!../)([^/]+)/../`', '$1', $before); 445 $output = str_replace($before, $after, $output); 446 } 447 448 return $output; 449 } 450 451 /** 452 * Save the rewritten stylesheet to disk. 453 */ 454 function _color_save_stylesheet($file, $style, &$paths) { 455 456 // Write new stylesheet. 457 file_save_data($style, $file, FILE_EXISTS_REPLACE); 458 $paths['files'][] = $file; 459 460 // Set standard file permissions for webserver-generated files. 461 @chmod($file, 0664); 462 } 463 464 /** 465 * Render images that match a given palette. 466 */ 467 function _color_render_images($theme, &$info, &$paths, $palette) { 468 469 // Prepare template image. 470 $source = $paths['source'] .'/'. $info['base_image']; 471 $source = imagecreatefrompng($source); 472 $width = imagesx($source); 473 $height = imagesy($source); 474 475 // Prepare target buffer. 476 $target = imagecreatetruecolor($width, $height); 477 imagealphablending($target, true); 478 479 // Fill regions of solid color. 480 foreach ($info['fill'] as $color => $fill) { 481 imagefilledrectangle($target, $fill[0], $fill[1], $fill[0] + $fill[2], $fill[1] + $fill[3], _color_gd($target, $palette[$color])); 482 } 483 484 // Render gradient. 485 for ($y = 0; $y < $info['gradient'][3]; ++$y) { 486 $color = _color_blend($target, $palette['top'], $palette['bottom'], $y / ($info['gradient'][3] - 1)); 487 imagefilledrectangle($target, $info['gradient'][0], $info['gradient'][1] + $y, $info['gradient'][0] + $info['gradient'][2], $info['gradient'][1] + $y + 1, $color); 488 } 489 490 // Blend over template. 491 imagecopy($target, $source, 0, 0, 0, 0, $width, $height); 492 493 // Clean up template image. 494 imagedestroy($source); 495 496 // Cut out slices. 497 foreach ($info['slices'] as $file => $coord) { 498 list($x, $y, $width, $height) = $coord; 499 $base = basename($file); 500 $image = $paths['target'] . $base; 501 502 // Cut out slice. 503 if ($file == 'screenshot.png') { 504 $slice = imagecreatetruecolor(150, 90); 505 imagecopyresampled($slice, $target, 0, 0, $x, $y, 150, 90, $width, $height); 506 variable_set('color_'. $theme .'_screenshot', $image); 507 } 508 else { 509 $slice = imagecreatetruecolor($width, $height); 510 imagecopy($slice, $target, 0, 0, $x, $y, $width, $height); 511 } 512 513 // Save image. 514 imagepng($slice, $image); 515 imagedestroy($slice); 516 $paths['files'][] = $image; 517 518 // Set standard file permissions for webserver-generated files 519 @chmod(realpath($image), 0664); 520 521 // Build before/after map of image paths. 522 $paths['map'][$file] = $base; 523 } 524 525 // Clean up target buffer. 526 imagedestroy($target); 527 } 528 529 /** 530 * Shift a given color, using a reference pair and a target blend color. 531 * 532 * Note: this function is significantly different from the JS version, as it 533 * is written to match the blended images perfectly. 534 * 535 * Constraint: if (ref2 == target + (ref1 - target) * delta) for some fraction delta 536 * then (return == target + (given - target) * delta) 537 * 538 * Loose constraint: Preserve relative positions in saturation and luminance 539 * space. 540 */ 541 function _color_shift($given, $ref1, $ref2, $target) { 542 543 // We assume that ref2 is a blend of ref1 and target and find 544 // delta based on the length of the difference vectors: 545 546 // delta = 1 - |ref2 - ref1| / |white - ref1| 547 $target = _color_unpack($target, true); 548 $ref1 = _color_unpack($ref1, true); 549 $ref2 = _color_unpack($ref2, true); 550 $numerator = 0; 551 $denominator = 0; 552 for ($i = 0; $i < 3; ++$i) { 553 $numerator += ($ref2[$i] - $ref1[$i]) * ($ref2[$i] - $ref1[$i]); 554 $denominator += ($target[$i] - $ref1[$i]) * ($target[$i] - $ref1[$i]); 555 } 556 $delta = ($denominator > 0) ? (1 - sqrt($numerator / $denominator)) : 0; 557 558 // Calculate the color that ref2 would be if the assumption was true. 559 for ($i = 0; $i < 3; ++$i) { 560 $ref3[$i] = $target[$i] + ($ref1[$i] - $target[$i]) * $delta; 561 } 562 563 // If the assumption is not true, there is a difference between ref2 and ref3. 564 // We measure this in HSL space. Notation: x' = hsl(x). 565 $ref2 = _color_rgb2hsl($ref2); 566 $ref3 = _color_rgb2hsl($ref3); 567 for ($i = 0; $i < 3; ++$i) { 568 $shift[$i] = $ref2[$i] - $ref3[$i]; 569 } 570 571 // Take the given color, and blend it towards the target. 572 $given = _color_unpack($given, true); 573 for ($i = 0; $i < 3; ++$i) { 574 $result[$i] = $target[$i] + ($given[$i] - $target[$i]) * $delta; 575 } 576 577 // Finally, we apply the extra shift in HSL space. 578 // Note: if ref2 is a pure blend of ref1 and target, then |shift| = 0. 579 $result = _color_rgb2hsl($result); 580 for ($i = 0; $i < 3; ++$i) { 581 $result[$i] = min(1, max(0, $result[$i] + $shift[$i])); 582 } 583 $result = _color_hsl2rgb($result); 584 585 // Return hex color. 586 return _color_pack($result, true); 587 } 588 589 /** 590 * Convert a hex triplet into a GD color. 591 */ 592 function _color_gd($img, $hex) { 593 $c = array_merge(array($img), _color_unpack($hex)); 594 return call_user_func_array('imagecolorallocate', $c); 595 } 596 597 /** 598 * Blend two hex colors and return the GD color. 599 */ 600 function _color_blend($img, $hex1, $hex2, $alpha) { 601 $in1 = _color_unpack($hex1); 602 $in2 = _color_unpack($hex2); 603 $out = array($img); 604 for ($i = 0; $i < 3; ++$i) { 605 $out[] = $in1[$i] + ($in2[$i] - $in1[$i]) * $alpha; 606 } 607 return call_user_func_array('imagecolorallocate', $out); 608 } 609 610 /** 611 * Convert a hex color into an RGB triplet. 612 */ 613 function _color_unpack($hex, $normalize = false) { 614 if (strlen($hex) == 4) { 615 $hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3]; 616 } 617 $c = hexdec($hex); 618 for ($i = 16; $i >= 0; $i -= 8) { 619 $out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1); 620 } 621 return $out; 622 } 623 624 /** 625 * Convert an RGB triplet to a hex color. 626 */ 627 function _color_pack($rgb, $normalize = false) { 628 $out = 0; 629 foreach ($rgb as $k => $v) { 630 $out |= (($v * ($normalize ? 255 : 1)) << (16 - $k * 8)); 631 } 632 return '#'. str_pad(dechex($out), 6, 0, STR_PAD_LEFT); 633 } 634 635 /** 636 * Convert a HSL triplet into RGB 637 */ 638 function _color_hsl2rgb($hsl) { 639 $h = $hsl[0]; 640 $s = $hsl[1]; 641 $l = $hsl[2]; 642 $m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l*$s; 643 $m1 = $l * 2 - $m2; 644 return array( 645 _color_hue2rgb($m1, $m2, $h + 0.33333), 646 _color_hue2rgb($m1, $m2, $h), 647 _color_hue2rgb($m1, $m2, $h - 0.33333), 648 ); 649 } 650 651 /** 652 * Helper function for _color_hsl2rgb(). 653 */ 654 function _color_hue2rgb($m1, $m2, $h) { 655 $h = ($h < 0) ? $h + 1 : (($h > 1) ? $h - 1 : $h); 656 if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6; 657 if ($h * 2 < 1) return $m2; 658 if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (0.66666 - $h) * 6; 659 return $m1; 660 } 661 662 /** 663 * Convert an RGB triplet to HSL. 664 */ 665 function _color_rgb2hsl($rgb) { 666 $r = $rgb[0]; 667 $g = $rgb[1]; 668 $b = $rgb[2]; 669 $min = min($r, min($g, $b)); 670 $max = max($r, max($g, $b)); 671 $delta = $max - $min; 672 $l = ($min + $max) / 2; 673 $s = 0; 674 if ($l > 0 && $l < 1) { 675 $s = $delta / ($l < 0.5 ? (2 * $l) : (2 - 2 * $l)); 676 } 677 $h = 0; 678 if ($delta > 0) { 679 if ($max == $r && $max != $g) $h += ($g - $b) / $delta; 680 if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta); 681 if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta); 682 $h /= 6; 683 } 684 return array($h, $s, $l); 685 }
title
Description
Body
title
Description
Body
title
Description
Body
title
Body
| Generated: Mon Jul 9 18:01:44 2012 | Cross-referenced by PHPXref 0.7 |