source: sipes/cord/modules/color/color.module @ 8a8efa8

stableversion-3.0
Last change on this file since 8a8efa8 was b354002, checked in by José Gregorio Puentes <jpuentes@…>, 8 años ago

se agrego el directorio del cord

  • Propiedad mode establecida a 100755
File size: 23.4 KB
Línea 
1<?php
2
3/**
4 * Implementation of hook_help().
5 */
6function 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 */
20function 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 */
31function 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 */
69function _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 */
122function 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 */
134function 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 */
150function 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 */
208function 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 */
242function 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 */
254function 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 */
381function _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 */
454function _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 */
467function _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 */
541function _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 */
592function _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 */
600function _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 */
613function _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 */
627function _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 */
638function _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 */
654function _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 */
665function _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}
Nota: Vea TracBrowser para ayuda de uso del navegador del repositorio.