[ Index ] |
|
Code source de Drupal 5.3 |
1 <?php 2 // $Id: color.module,v 1.13.2.3 2007/10/16 07:02:40 drumm Exp $ 3 4 /** 5 * Implementation of hook_help 6 */ 7 function color_help($section) { 8 switch ($section) { 9 case 'admin/help#color': 10 $output = '<p>'. t('Color module allows a site administrator to quickly and easily change the color scheme of the entire site. In order for color module to work however, a theme must be specifically designed to use the color changing features. The default theme, Garland, (as well as its fixed width counterpart, Minnelli) was designed to take advantage of these features. With color module, you can easily change the color of links, backgrounds, text, and more depending on which color module enabled theme you are using. Color module requires your <a href="@url">file download method</a> to 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 style.css file in the files directory, and includes it after the theme's original style.css. This means that if you make any manual changes to your theme's style.css file, you must save your color settings again, even if they haven't changed. This causes the color module generated version of style.css in the files directory to be recreated using the new version of the original file.") .'</p>'; 12 return $output; 13 } 14 } 15 16 /** 17 * Implementation of hook_form_alter(). 18 */ 19 function color_form_alter($form_id, &$form) { 20 // Insert the color changer into the theme settings page. 21 // TODO: Last condition in the following if disables color changer when private files are used this should be solved in a different way. See issue #92059. 22 if ($form_id == 'system_theme_settings' && color_get_info(arg(4)) && function_exists('gd_info') && variable_get('file_downloads', FILE_DOWNLOADS_PUBLIC) == FILE_DOWNLOADS_PUBLIC) { 23 $form['color'] = array( 24 '#type' => 'fieldset', 25 '#title' => t('Color scheme'), 26 '#weight' => -1, 27 '#attributes' => array('id' => 'color_scheme_form'), 28 '#theme' => 'color_scheme_form', 29 ); 30 $form['color'] += color_scheme_form(arg(4)); 31 $form['#submit']['color_scheme_form_submit'] = array(); 32 } 33 34 // Use the generated screenshot in the theme list 35 if ($form_id == 'system_theme_select_form' || $form_id == 'system_themes') { 36 $themes = list_themes(); 37 foreach (element_children($form) as $theme) { 38 if ($screenshot = variable_get('color_'. $theme .'_screenshot', NULL)) { 39 if (isset($form[$theme]['screenshot'])) { 40 $form[$theme]['screenshot']['#value'] = theme('image', $screenshot, '', '', array('class' => 'screenshot'), FALSE); 41 } 42 } 43 } 44 } 45 } 46 47 /** 48 * Callback for the theme to alter the resources used. 49 */ 50 function _color_page_alter(&$vars) { 51 global $theme_key; 52 53 // Override stylesheet 54 $path = variable_get('color_'. $theme_key .'_stylesheet', NULL); 55 if ($path) { 56 $vars['css']['all']['theme'][$path] = TRUE; 57 $vars['styles'] = drupal_get_css($vars['css']); 58 } 59 60 // Override logo 61 $logo = variable_get('color_'. $theme_key .'_logo', NULL); 62 if ($logo && $vars['logo'] && preg_match('!'. $theme_key .'/logo.png$!', $vars['logo'])) { 63 $vars['logo'] = base_path() . $logo; 64 } 65 } 66 67 /** 68 * Retrieve the color.module info for a particular theme. 69 */ 70 function color_get_info($theme) { 71 $path = drupal_get_path('theme', $theme); 72 $file = $path .'/color/color.inc'; 73 if ($path && file_exists($file)) { 74 include $file; 75 return $info; 76 } 77 } 78 79 /** 80 * Helper function to retrieve the color palette for a particular theme. 81 */ 82 function color_get_palette($theme, $default = false) { 83 // Fetch and expand default palette 84 $fields = array('base', 'link', 'top', 'bottom', 'text'); 85 $info = color_get_info($theme); 86 $keys = array_keys($info['schemes']); 87 foreach (explode(',', array_shift($keys)) as $k => $scheme) { 88 $palette[$fields[$k]] = $scheme; 89 } 90 91 // Load variable 92 return $default ? $palette : variable_get('color_'. $theme .'_palette', $palette); 93 } 94 95 /** 96 * Form callback. Returns the configuration form. 97 */ 98 function color_scheme_form($theme) { 99 $base = drupal_get_path('module', 'color'); 100 $info = color_get_info($theme); 101 102 // Add Farbtastic color picker 103 drupal_add_css('misc/farbtastic/farbtastic.css', 'module', 'all', FALSE); 104 drupal_add_js('misc/farbtastic/farbtastic.js'); 105 106 // Add custom CSS/JS 107 drupal_add_css($base .'/color.css', 'module', 'all', FALSE); 108 drupal_add_js($base .'/color.js'); 109 drupal_add_js(array('color' => array( 110 'reference' => color_get_palette($theme, true) 111 )), 'setting'); 112 113 // See if we're using a predefined scheme 114 $current = implode(',', variable_get('color_'. $theme .'_palette', array())); 115 // Note: we use the original theme when the default scheme is chosen. 116 $current = isset($info['schemes'][$current]) ? $current : ($current == '' ? reset($info['schemes']) : ''); 117 118 // Add scheme selector 119 $info['schemes'][''] = t('Custom'); 120 $form['scheme'] = array( 121 '#type' => 'select', 122 '#title' => t('Color set'), 123 '#options' => $info['schemes'], 124 '#default_value' => $current, 125 ); 126 127 // Add palette fields 128 $palette = color_get_palette($theme); 129 $names = array( 130 'base' => t('Base color'), 131 'link' => t('Link color'), 132 'top' => t('Header top'), 133 'bottom' => t('Header bottom'), 134 'text' => t('Text color') 135 ); 136 $form['palette']['#tree'] = true; 137 foreach ($palette as $name => $value) { 138 $form['palette'][$name] = array( 139 '#type' => 'textfield', 140 '#title' => $names[$name], 141 '#default_value' => $value, 142 '#size' => 8, 143 ); 144 } 145 $form['theme'] = array('#type' => 'value', '#value' => arg(4)); 146 $form['info'] = array('#type' => 'value', '#value' => $info); 147 148 return $form; 149 } 150 151 /** 152 * Theme color form. 153 */ 154 function theme_color_scheme_form($form) { 155 // Include stylesheet 156 $theme = $form['theme']['#value']; 157 $info = $form['info']['#value']; 158 $path = drupal_get_path('theme', $theme) .'/'; 159 drupal_add_css($path . $info['preview_css']); 160 161 // Wrapper 162 $output .= '<div class="color-form clear-block">'; 163 164 // Color schemes 165 $output .= drupal_render($form['scheme']); 166 167 // Palette 168 $output .= '<div id="palette" class="clear-block">'; 169 foreach (element_children($form['palette']) as $name) { 170 $output .= drupal_render($form['palette'][$name]); 171 } 172 $output .= '</div>'; 173 174 // Preview 175 $output .= drupal_render($form); 176 $output .= '<h2>'. t('Preview') .'</h2>'; 177 $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'] .')" alt=""></div></div>'; 178 179 // Close wrapper 180 $output .= '</div>'; 181 182 return $output; 183 } 184 185 /** 186 * Submit handler for color change form. 187 */ 188 function color_scheme_form_submit($form_id, $values) { 189 // Get theme coloring info 190 if (!isset($values['info'])) { 191 return; 192 } 193 $theme = $values['theme']; 194 $info = $values['info']; 195 196 // Resolve palette 197 $palette = $values['palette']; 198 if ($values['scheme'] != '') { 199 $scheme = explode(',', $values['scheme']); 200 foreach ($palette as $k => $color) { 201 $palette[$k] = array_shift($scheme); 202 } 203 } 204 205 // Make sure enough memory is available, if PHP's memory limit is compiled in. 206 if (function_exists('memory_get_usage')) { 207 // Fetch source image dimensions. 208 $source = drupal_get_path('theme', $theme) .'/'. $info['base_image']; 209 list($width, $height) = getimagesize($source); 210 211 // We need at least a copy of the source and a target buffer of the same 212 // size (both at 32bpp). 213 $required = $width * $height * 8; 214 $usage = memory_get_usage(); 215 $limit = parse_size(ini_get('memory_limit')); 216 if ($usage + $required > $limit) { 217 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'); 218 return; 219 } 220 } 221 222 // Delete old files 223 foreach (variable_get('color_'. $theme .'_files', array()) as $file) { 224 @unlink($file); 225 } 226 if ($file = dirname($file)) { 227 @rmdir($file); 228 } 229 230 // Don't render the default colorscheme, use the standard theme instead. 231 if (implode(',', color_get_palette($theme, true)) == implode(',', $palette) 232 || $values['op'] == t('Reset to defaults')) { 233 variable_del('color_'. $theme .'_palette'); 234 variable_del('color_'. $theme .'_stylesheet'); 235 variable_del('color_'. $theme .'_logo'); 236 variable_del('color_'. $theme .'_files'); 237 variable_del('color_'. $theme .'_screenshot'); 238 return; 239 } 240 241 // Prepare target locations for generated files 242 $id = $theme .'-'. substr(md5(serialize($palette) . microtime()), 0, 8); 243 $paths['color'] = file_directory_path() .'/color'; 244 $paths['target'] = $paths['color'] .'/'. $id; 245 foreach ($paths as $path) { 246 file_check_directory($path, FILE_CREATE_DIRECTORY); 247 } 248 $paths['target'] = $paths['target'] .'/'; 249 $paths['id'] = $id; 250 $paths['source'] = drupal_get_path('theme', $theme) .'/'; 251 $paths['stylesheet'] = $paths['target'] .'style.css'; 252 $paths['files'] = $paths['map'] = array(); 253 254 // Save palette and stylesheet location 255 variable_set('color_'. $theme .'_palette', $palette); 256 variable_set('color_'. $theme .'_stylesheet', $paths['stylesheet']); 257 variable_set('color_'. $theme .'_logo', $paths['target'] .'logo.png'); 258 259 // Copy over neutral images 260 foreach ($info['copy'] as $file) { 261 $base = basename($file); 262 $source = $paths['source'] . $file; 263 file_copy($source, $paths['target'] . $base); 264 $paths['map'][$file] = $base; 265 $paths['files'][] = $paths['target'] . $base; 266 } 267 268 // Render new images 269 _color_render_images($theme, $info, $paths, $palette); 270 271 // Rewrite stylesheet 272 _color_rewrite_stylesheet($theme, $info, $paths, $palette); 273 274 // Maintain list of files 275 variable_set('color_'. $theme .'_files', $paths['files']); 276 } 277 278 /** 279 * Rewrite the stylesheet to match the colors in the palette. 280 */ 281 function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette) { 282 // Load stylesheet 283 $style = file_get_contents($paths['source'] .'style.css'); 284 285 // Prepare color conversion table 286 $conversion = $palette; 287 unset($conversion['base']); 288 foreach ($conversion as $k => $v) { 289 $conversion[$k] = drupal_strtolower($v); 290 } 291 $default = color_get_palette($theme, true); 292 293 // Split off the "Don't touch" section of the stylesheet. 294 list($style, $fixed) = explode("Color Module: Don't touch", $style); 295 296 // Look for @import commands and insert the referenced stylesheets. 297 $cwd = getcwd(); 298 chdir(drupal_get_path('theme', $theme)); 299 $style = preg_replace_callback('/@import\s*["\']([^"\']+)["\'];/', '_color_import_stylesheet', $style); 300 chdir($cwd); 301 302 // Find all colors in the stylesheet and the chunks in between. 303 $style = preg_split('/(#[0-9a-f]{6}|#[0-9a-f]{3})/i', $style, -1, PREG_SPLIT_DELIM_CAPTURE); 304 $is_color = false; 305 $output = ''; 306 $base = 'base'; 307 308 // Iterate over all parts 309 foreach ($style as $chunk) { 310 if ($is_color) { 311 $chunk = drupal_strtolower($chunk); 312 // Check if this is one of the colors in the default palette 313 if ($key = array_search($chunk, $default)) { 314 $chunk = $conversion[$key]; 315 } 316 // Not a pre-set color. Extrapolate from the base. 317 else { 318 $chunk = _color_shift($palette[$base], $default[$base], $chunk, $info['blend_target']); 319 } 320 } 321 else { 322 // Determine the most suitable base color for the next color. 323 324 // 'a' declarations. Use link. 325 if (preg_match('@[^a-z0-9_-](a)[^a-z0-9_-][^/{]*{[^{]+$@i', $chunk)) { 326 $base = 'link'; 327 } 328 // 'color:' styles. Use text. 329 else if (preg_match('/(?<!-)color[^{:]*:[^{#]*$/i', $chunk)) { 330 $base = 'text'; 331 } 332 // Reset back to base. 333 else { 334 $base = 'base'; 335 } 336 } 337 $output .= $chunk; 338 $is_color = !$is_color; 339 } 340 // Append fixed colors segment 341 $output .= $fixed; 342 343 // Replace paths to images 344 foreach ($paths['map'] as $before => $after) { 345 $output = str_replace($before, $after, $output); 346 } 347 348 // Write new stylesheet 349 $file = fopen($paths['stylesheet'], 'w+'); 350 fwrite($file, $output); 351 fclose($file); 352 $paths['files'][] = $paths['stylesheet']; 353 354 // Set standard file permissions for webserver-generated files 355 @chmod($paths['stylesheet'], 0664); 356 } 357 358 /** 359 * Helper function for _color_rewrite_stylesheet. 360 */ 361 function _color_import_stylesheet($matches) { 362 return preg_replace('/url\(([\'"]?)(?![a-z]+:)/i', 'url(\1'. dirname($matches[1]) .'/', file_get_contents($matches[1])); 363 } 364 365 /** 366 * Render images that match a given palette. 367 */ 368 function _color_render_images($theme, &$info, &$paths, $palette) { 369 370 // Prepare template image. 371 $source = $paths['source'] .'/'. $info['base_image']; 372 $source = imagecreatefrompng($source); 373 $width = imagesx($source); 374 $height = imagesy($source); 375 376 // Prepare target buffer. 377 $target = imagecreatetruecolor($width, $height); 378 imagealphablending($target, true); 379 380 // Fill regions of solid color. 381 foreach ($info['fill'] as $color => $fill) { 382 imagefilledrectangle($target, $fill[0], $fill[1], $fill[0] + $fill[2], $fill[1] + $fill[3], _color_gd($target, $palette[$color])); 383 } 384 385 // Render gradient. 386 for ($y = 0; $y < $info['gradient'][3]; ++$y) { 387 $color = _color_blend($target, $palette['top'], $palette['bottom'], $y / ($info['gradient'][3] - 1)); 388 imagefilledrectangle($target, $info['gradient'][0], $info['gradient'][1] + $y, $info['gradient'][2], $info['gradient'][1] + $y + 1, $color); 389 } 390 391 // Blend over template. 392 imagecopy($target, $source, 0, 0, 0, 0, $width, $height); 393 394 // Clean up template image. 395 imagedestroy($source); 396 397 // Cut out slices. 398 foreach ($info['slices'] as $file => $coord) { 399 list($x, $y, $width, $height) = $coord; 400 $base = basename($file); 401 $image = $paths['target'] . $base; 402 403 // Cut out slice. 404 if ($file == 'screenshot.png') { 405 $slice = imagecreatetruecolor(150, 90); 406 imagecopyresampled($slice, $target, 0, 0, $x, $y, 150, 90, $width, $height); 407 variable_set('color_'. $theme .'_screenshot', $image); 408 } 409 else { 410 $slice = imagecreatetruecolor($width, $height); 411 imagecopy($slice, $target, 0, 0, $x, $y, $width, $height); 412 } 413 414 // Save image. 415 imagepng($slice, $image); 416 imagedestroy($slice); 417 $paths['files'][] = $image; 418 419 // Set standard file permissions for webserver-generated files 420 @chmod(realpath($image), 0664); 421 422 // Build before/after map of image paths. 423 $paths['map'][$file] = $base; 424 } 425 426 // Clean up target buffer. 427 imagedestroy($target); 428 } 429 430 /** 431 * Shift a given color, using a reference pair and a target blend color. 432 * 433 * Note: this function is significantly different from the JS version, as it 434 * is written to match the blended images perfectly. 435 * 436 * Constraint: if (ref2 == target + (ref1 - target) * delta) for some fraction delta 437 * then (return == target + (given - target) * delta) 438 * 439 * Loose constraint: Preserve relative positions in saturation and luminance 440 * space. 441 */ 442 function _color_shift($given, $ref1, $ref2, $target) { 443 444 // We assume that ref2 is a blend of ref1 and target and find 445 // delta based on the length of the difference vectors: 446 447 // delta = 1 - |ref2 - ref1| / |white - ref1| 448 $target = _color_unpack($target, true); 449 $ref1 = _color_unpack($ref1, true); 450 $ref2 = _color_unpack($ref2, true); 451 for ($i = 0; $i < 3; ++$i) { 452 $numerator += ($ref2[$i] - $ref1[$i]) * ($ref2[$i] - $ref1[$i]); 453 $denominator += ($target[$i] - $ref1[$i]) * ($target[$i] - $ref1[$i]); 454 } 455 $delta = ($denominator > 0) ? (1 - sqrt($numerator / $denominator)) : 0; 456 457 // Calculate the color that ref2 would be if the assumption was true. 458 for ($i = 0; $i < 3; ++$i) { 459 $ref3[$i] = $target[$i] + ($ref1[$i] - $target[$i]) * $delta; 460 } 461 462 // If the assumption is not true, there is a difference between ref2 and ref3. 463 // We measure this in HSL space. Notation: x' = hsl(x). 464 $ref2 = _color_rgb2hsl($ref2); 465 $ref3 = _color_rgb2hsl($ref3); 466 for ($i = 0; $i < 3; ++$i) { 467 $shift[$i] = $ref2[$i] - $ref3[$i]; 468 } 469 470 // Take the given color, and blend it towards the target. 471 $given = _color_unpack($given, true); 472 for ($i = 0; $i < 3; ++$i) { 473 $result[$i] = $target[$i] + ($given[$i] - $target[$i]) * $delta; 474 } 475 476 // Finally, we apply the extra shift in HSL space. 477 // Note: if ref2 is a pure blend of ref1 and target, then |shift| = 0. 478 $result = _color_rgb2hsl($result); 479 for ($i = 0; $i < 3; ++$i) { 480 $result[$i] = min(1, max(0, $result[$i] + $shift[$i])); 481 } 482 $result = _color_hsl2rgb($result); 483 484 // Return hex color. 485 return _color_pack($result, true); 486 } 487 488 /** 489 * Convert a hex triplet into a GD color. 490 */ 491 function _color_gd($img, $hex) { 492 $c = array_merge(array($img), _color_unpack($hex)); 493 return call_user_func_array('imagecolorallocate', $c); 494 } 495 496 /** 497 * Blend two hex colors and return the GD color. 498 */ 499 function _color_blend($img, $hex1, $hex2, $alpha) { 500 $in1 = _color_unpack($hex1); 501 $in2 = _color_unpack($hex2); 502 $out = array($img); 503 for ($i = 0; $i < 3; ++$i) { 504 $out[] = $in1[$i] + ($in2[$i] - $in1[$i]) * $alpha; 505 } 506 return call_user_func_array('imagecolorallocate', $out); 507 } 508 509 /** 510 * Convert a hex color into an RGB triplet. 511 */ 512 function _color_unpack($hex, $normalize = false) { 513 if (strlen($hex) == 4) { 514 $hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3]; 515 } 516 $c = hexdec($hex); 517 for ($i = 16; $i >= 0; $i -= 8) { 518 $out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1); 519 } 520 return $out; 521 } 522 523 /** 524 * Convert an RGB triplet to a hex color. 525 */ 526 function _color_pack($rgb, $normalize = false) { 527 foreach ($rgb as $k => $v) { 528 $out |= (($v * ($normalize ? 255 : 1)) << (16 - $k * 8)); 529 } 530 return '#'. str_pad(dechex($out), 6, 0, STR_PAD_LEFT); 531 } 532 533 /** 534 * Convert a HSL triplet into RGB 535 */ 536 function _color_hsl2rgb($hsl) { 537 $h = $hsl[0]; 538 $s = $hsl[1]; 539 $l = $hsl[2]; 540 $m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l*$s; 541 $m1 = $l * 2 - $m2; 542 return array(_color_hue2rgb($m1, $m2, $h + 0.33333), 543 _color_hue2rgb($m1, $m2, $h), 544 _color_hue2rgb($m1, $m2, $h - 0.33333)); 545 } 546 547 /** 548 * Helper function for _color_hsl2rgb(). 549 */ 550 function _color_hue2rgb($m1, $m2, $h) { 551 $h = ($h < 0) ? $h + 1 : (($h > 1) ? $h - 1 : $h); 552 if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6; 553 if ($h * 2 < 1) return $m2; 554 if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (0.66666 - $h) * 6; 555 return $m1; 556 } 557 558 /** 559 * Convert an RGB triplet to HSL. 560 */ 561 function _color_rgb2hsl($rgb) { 562 $r = $rgb[0]; 563 $g = $rgb[1]; 564 $b = $rgb[2]; 565 $min = min($r, min($g, $b)); 566 $max = max($r, max($g, $b)); 567 $delta = $max - $min; 568 $l = ($min + $max) / 2; 569 $s = 0; 570 if ($l > 0 && $l < 1) { 571 $s = $delta / ($l < 0.5 ? (2 * $l) : (2 - 2 * $l)); 572 } 573 $h = 0; 574 if ($delta > 0) { 575 if ($max == $r && $max != $g) $h += ($g - $b) / $delta; 576 if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta); 577 if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta); 578 $h /= 6; 579 } 580 return array($h, $s, $l); 581 }
titre
Description
Corps
titre
Description
Corps
titre
Description
Corps
titre
Corps
Généré le : Fri Nov 30 16:20:15 2007 | par Balluche grâce à PHPXref 0.7 |
![]() |