[ Index ]

PHP Cross Reference of Drupal 6 (gatewave)

title

Body

[close]

/modules/color/ -> color.module (source)

   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  }


Generated: Thu Mar 24 11:18:33 2011 Cross-referenced by PHPXref 0.7