summaryrefslogtreecommitdiff
path: root/modules
diff options
context:
space:
mode:
authorSteven Wittens <steven@10.no-reply.drupal.org>2006-10-29 13:21:46 +0000
committerSteven Wittens <steven@10.no-reply.drupal.org>2006-10-29 13:21:46 +0000
commitb01d96aed5004b6b07cf0e9437eb0bd95b8a70da (patch)
tree1b70f8dde859d3fe15c26f8fd0cf762ac2f84b9f /modules
parente1a7144b3320dacc2b1c7065ef2c126e265967d5 (diff)
downloadbrdo-b01d96aed5004b6b07cf0e9437eb0bd95b8a70da.tar.gz
brdo-b01d96aed5004b6b07cf0e9437eb0bd95b8a70da.tar.bz2
#88202: Adding Garland theme to core.
Diffstat (limited to 'modules')
-rw-r--r--modules/color/color.css77
-rw-r--r--modules/color/color.info4
-rw-r--r--modules/color/color.js245
-rw-r--r--modules/color/color.module542
-rw-r--r--modules/color/images/hook.pngbin0 -> 140 bytes
-rw-r--r--modules/color/images/lock.pngbin0 -> 251 bytes
-rw-r--r--modules/system/system.install8
7 files changed, 872 insertions, 4 deletions
diff --git a/modules/color/color.css b/modules/color/color.css
new file mode 100644
index 000000000..0b532e966
--- /dev/null
+++ b/modules/color/color.css
@@ -0,0 +1,77 @@
+/* Farbtastic placement */
+.color-form {
+ max-width: 50em;
+ position: relative;
+}
+#placeholder {
+ position: absolute;
+ top: 0;
+ right: 0;
+}
+
+/* Palette */
+.color-form .form-item {
+ height: 2em;
+ line-height: 2em;
+ padding-left: 1em;
+ margin: 0.5em 0;
+}
+.color-form label {
+ float: left;
+ clear: left;
+ width: 10em;
+}
+.color-form .form-text, .color-form .form-select {
+ float: left;
+}
+.color-form .form-text {
+ text-align: center;
+ margin-right: 5px;
+ cursor: pointer;
+}
+
+#palette .hook {
+ float: left;
+ margin-top: 3px;
+ width: 16px;
+ height: 16px;
+}
+#palette .down, #palette .up, #palette .both {
+ background: url('images/hook.png') no-repeat 100% 0;
+}
+#palette .up {
+ background-position: 100% -27px;
+}
+#palette .both {
+ background-position: 100% -54px;
+}
+
+#palette .lock {
+ float: left;
+ position: relative;
+ top: -1.4em;
+ left: -10px;
+ width: 20px;
+ height: 25px;
+ background: url('images/lock.png') no-repeat 50% 2px;
+ cursor: pointer;
+}
+#palette .unlocked {
+ background-position: 50% -22px;
+}
+#palette .form-item {
+ width: 20em;
+}
+#palette .item-selected {
+ background: #eee;
+}
+
+/* Preview */
+#preview {
+ display: none;
+}
+html.js #preview {
+ display: block;
+ position: relative;
+ float: left;
+}
diff --git a/modules/color/color.info b/modules/color/color.info
new file mode 100644
index 000000000..642eae038
--- /dev/null
+++ b/modules/color/color.info
@@ -0,0 +1,4 @@
+; $Id$
+name = Color
+description = Allows the user to change the color scheme of certain themes.
+package = Core - optional
diff --git a/modules/color/color.js b/modules/color/color.js
new file mode 100644
index 000000000..5bf26a988
--- /dev/null
+++ b/modules/color/color.js
@@ -0,0 +1,245 @@
+if (Drupal.jsEnabled) {
+ $(document).ready(function () {
+ var form = $('#color_scheme_form .color-form');
+ var inputs = [];
+ var hooks = [];
+ var locks = [];
+ var focused = null;
+
+ // Add Farbtastic
+ $(form).prepend('<div id="placeholder"></div>');
+ var farb = $.farbtastic('#placeholder');
+
+ // Decode reference colors to HSL
+ var reference = Drupal.settings.color.reference;
+ for (i in reference) {
+ reference[i] = farb.RGBToHSL(farb.unpack(reference[i]));
+ }
+
+ // Build preview
+ $('#preview').append('<div id="gradient"></div>');
+ var gradient = $('#preview #gradient');
+ var h = parseInt(gradient.css('height')) / 10;
+ for (i = 0; i < h; ++i) {
+ gradient.append('<div class="gradient-line"></div>');
+ }
+
+ // Fix preview background in IE6
+ if (navigator.appVersion.match(/MSIE [0-6]\./)) {
+ var e = $('#preview #img')[0];
+ var image = e.currentStyle.backgroundImage;
+ e.style.backgroundImage = 'none';
+ e.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image.substring(5, image.length - 2) + "')";
+ }
+
+ // Set up colorscheme selector
+ $('#edit-scheme', form).change(function () {
+ var colors = this.options[this.selectedIndex].value;
+ if (colors != '') {
+ colors = colors.split(',');
+ for (i in colors) {
+ callback(inputs[i], colors[i], false, true);
+ }
+ preview();
+ }
+ });
+
+ /**
+ * Render the preview.
+ */
+ function preview() {
+ // Solid background
+ $('#preview', form).css('backgroundColor', inputs[0].value);
+
+ // Text preview
+ $('#text', form).css('color', inputs[4].value);
+ $('#text a, #text h2', form).css('color', inputs[1].value);
+
+ // Set up gradient
+ var top = farb.unpack(inputs[2].value);
+ var bottom = farb.unpack(inputs[3].value);
+ if (top && bottom) {
+ var delta = [];
+ for (i in top) {
+ delta[i] = (bottom[i] - top[i]) / h;
+ }
+ var accum = top;
+
+ // Render gradient lines
+ $('#gradient > div', form).each(function () {
+ for (i in accum) {
+ accum[i] += delta[i];
+ }
+ this.style.backgroundColor = farb.pack(accum);
+ });
+ }
+ }
+
+ /**
+ * Shift a given color, using a reference pair (ref in HSL).
+ *
+ * This algorithm ensures relative ordering on the saturation and luminance
+ * axes is preserved, and performs a simple hue shift.
+ *
+ * It is also symmetrical. If: shift_color(c, a, b) == d,
+ * then shift_color(d, b, a) == c.
+ */
+ function shift_color(given, ref1, ref2) {
+ // Convert to HSL
+ given = farb.RGBToHSL(farb.unpack(given));
+
+ // Hue: apply delta
+ given[0] += ref2[0] - ref1[0];
+
+ // Saturation: interpolate
+ if (ref1[1] == 0 || ref2[1] == 0) {
+ given[1] = ref2[1];
+ }
+ else {
+ var d = ref1[1] / ref2[1];
+ if (d > 1) {
+ given[1] /= d;
+ }
+ else {
+ given[1] = 1 - (1 - given[1]) * d;
+ }
+ }
+
+ // Luminance: interpolate
+ if (ref1[2] == 0 || ref2[2] == 0) {
+ given[2] = ref2[2];
+ }
+ else {
+ var d = ref1[2] / ref2[2];
+ if (d > 1) {
+ given[2] /= d;
+ }
+ else {
+ given[2] = 1 - (1 - given[2]) * d;
+ }
+ }
+
+ return farb.pack(farb.HSLToRGB(given));
+ }
+
+ /**
+ * Callback for Farbtastic when a new color is chosen.
+ */
+ function callback(input, color, propagate, colorscheme) {
+ // Set background/foreground color
+ $(input).css({
+ backgroundColor: color,
+ color: farb.RGBToHSL(farb.unpack(color))[2] > 0.5 ? '#000' : '#fff'
+ });
+
+ // Change input value
+ if (input.value && input.value != color) {
+ input.value = color;
+
+ // Update locked values
+ if (propagate) {
+ var i = input.i;
+ for (j = i + 1; ; ++j) {
+ if (!locks[j - 1] || $(locks[j - 1]).is('.unlocked')) break;
+ var matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
+ callback(inputs[j], matched, false);
+ }
+ for (j = i - 1; ; --j) {
+ if (!locks[j] || $(locks[j]).is('.unlocked')) break;
+ var matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
+ callback(inputs[j], matched, false);
+ }
+
+ // Update preview
+ preview();
+ }
+
+ // Reset colorscheme selector
+ if (!colorscheme) {
+ resetScheme();
+ }
+ }
+
+ }
+
+ /**
+ * Reset the color scheme selector.
+ */
+ function resetScheme() {
+ $('#edit-scheme', form).each(function () {
+ this.selectedIndex = this.options.length - 1;
+ });
+ }
+
+ // Focus the Farbtastic on a particular field.
+ function focus() {
+ var input = this;
+ // Remove old bindings
+ focused && $(focused).unbind('keyup', farb.updateValue)
+ .unbind('keyup', preview).unbind('keyup', resetScheme)
+ .parent().removeClass('item-selected');
+
+ // Add new bindings
+ focused = this;
+ farb.linkTo(function (color) { callback(input, color, true, false) });
+ farb.setColor(this.value);
+ $(focused).keyup(farb.updateValue).keyup(preview).keyup(resetScheme)
+ .parent().addClass('item-selected');
+ }
+
+ // Initialize color fields
+ $('#palette input.form-text', form)
+ .each(function () {
+ // Extract palette field name
+ this.key = this.id.substring(13);
+
+ // Link to color picker temporarily to initialize.
+ farb.linkTo(function () {}).setColor('#000').linkTo(this);
+
+ // Add lock
+ var i = inputs.length;
+ if (inputs.length) {
+ var lock = $('<div class="lock"></div>').toggle(
+ function () {
+ $(this).addClass('unlocked');
+ $(hooks[i - 1]).attr('class',
+ locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook up' : 'hook'
+ );
+ $(hooks[i]).attr('class',
+ locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook down' : 'hook'
+ );
+ },
+ function () {
+ $(this).removeClass('unlocked');
+ $(hooks[i - 1]).attr('class',
+ locks[i - 2] && $(locks[i - 2]).is(':not(.unlocked)') ? 'hook both' : 'hook down'
+ );
+ $(hooks[i]).attr('class',
+ locks[i] && $(locks[i]).is(':not(.unlocked)') ? 'hook both' : 'hook up'
+ );
+ }
+ );
+ $(this).after(lock);
+ locks.push(lock);
+ }
+
+ // Add hook
+ var hook = $('<div class="hook"></div>');
+ $(this).after(hook);
+ hooks.push(hook);
+
+ $(this).parent().find('.lock').click();
+ this.i = i;
+ inputs.push(this);
+ })
+ .focus(focus);
+
+ $('#palette label', form)
+
+ // Focus first color
+ focus.call(inputs[0]);
+
+ // Render preview
+ preview();
+ });
+} \ No newline at end of file
diff --git a/modules/color/color.module b/modules/color/color.module
new file mode 100644
index 000000000..98b6e337d
--- /dev/null
+++ b/modules/color/color.module
@@ -0,0 +1,542 @@
+<?php
+// $Id$
+
+/**
+ * Implementation of hook_form_alter().
+ */
+function color_form_alter($form_id, &$form) {
+ // Insert the color changer into the theme settings page.
+ if ($form_id == 'system_theme_settings' && color_get_info(arg(4))) {
+ $form['color'] = array(
+ '#type' => 'fieldset',
+ '#title' => t('Color scheme'),
+ '#weight' => -1,
+ '#attributes' => array('id' => 'color_scheme_form'),
+ '#theme' => 'color_scheme_form',
+ );
+ $form['color'] += color_scheme_form(arg(4));
+ $form['#submit']['color_scheme_form_submit'] = array();
+ }
+
+ // Use the generated screenshot in the theme list
+ if ($form_id == 'system_theme_select_form' || $form_id == 'system_themes') {
+ $themes = list_themes();
+ foreach (element_children($form) as $theme) {
+ if ($screenshot = variable_get('color_'. $theme .'_screenshot', NULL)) {
+ if (isset($form[$theme]['screenshot'])) {
+ $form[$theme]['screenshot']['#value'] = theme('image', $screenshot, '', '', array('class' => 'screenshot'), FALSE);
+ }
+ }
+ }
+ }
+}
+
+/**
+ * Callback for the theme to alter the resources used.
+ */
+function _color_page_alter(&$vars) {
+ global $theme_key;
+
+ // Override stylesheet
+ $path = variable_get('color_'. $theme_key .'_stylesheet', NULL);
+ if ($path) {
+ $vars['css']['theme'] = array($path => array('path' => $path, 'media' => 'all'));
+ $vars['styles'] = drupal_get_css($vars['css']);
+ }
+
+ // Override logo
+ $logo = variable_get('color_'. $theme_key .'_logo', NULL);
+ if ($logo && $vars['logo'] && preg_match('!'. $theme_key .'/logo.png$!', $vars['logo'])) {
+ $vars['logo'] = $logo;
+ }
+
+ return $vars;
+}
+
+/**
+ * Retrieve the color.module info for a particular theme.
+ */
+function color_get_info($theme) {
+ $path = drupal_get_path('theme', $theme);
+ $file = $path .'/color/color.inc';
+ if ($path && file_exists($file)) {
+ include $file;
+ return $info;
+ }
+}
+
+/**
+ * Helper function to retrieve the color palette for a particular theme.
+ */
+function color_get_palette($theme, $default = false) {
+ // Fetch and expand default palette
+ $fields = array('base', 'link', 'top', 'bottom', 'text');
+ $info = color_get_info($theme);
+ foreach (explode(',', array_shift(array_keys($info['schemes']))) as $k => $scheme) {
+ $palette[$fields[$k]] = $scheme;
+ }
+
+ // Load variable
+ return $default ? $palette : variable_get('color_'. $theme .'_palette', $palette);
+}
+
+/**
+ * Form callback. Returns the configuration form.
+ */
+function color_scheme_form($theme) {
+ $base = drupal_get_path('module', 'color');
+ $info = color_get_info($theme);
+
+ // Add Farbtastic color picker
+ drupal_add_css('misc/farbtastic/farbtastic.css');
+ drupal_add_js('misc/farbtastic/farbtastic.js');
+
+ // Add custom CSS/JS
+ drupal_add_css($base .'/color.css', 'module');
+ drupal_add_js($base .'/color.js');
+ drupal_add_js(array('color' => array(
+ 'reference' => color_get_palette($theme, true)
+ )), 'setting');
+
+ // See if we're using a predefined scheme
+ $current = implode(',', variable_get('color_'. $theme .'_palette', array()));
+ // Note: we use the original theme when the default scheme is chosen.
+ $current = isset($info['schemes'][$current]) ? $current : ($current == '' ? reset($info['schemes']) : '');
+
+ // Add scheme selector
+ $info['schemes'][''] = t('Custom');
+ $form['scheme'] = array(
+ '#type' => 'select',
+ '#title' => t('Color set'),
+ '#options' => $info['schemes'],
+ '#default_value' => $current,
+ );
+
+ // Add palette fields
+ $palette = color_get_palette($theme);
+ $names = array(
+ 'base' => t('Base color'),
+ 'link' => t('Link color'),
+ 'top' => t('Header top'),
+ 'bottom' => t('Header bottom'),
+ 'text' => t('Text color')
+ );
+ $form['palette']['#tree'] = true;
+ foreach ($palette as $name => $value) {
+ $form['palette'][$name] = array(
+ '#type' => 'textfield',
+ '#title' => $names[$name],
+ '#default_value' => $value,
+ '#size' => 8,
+ );
+ }
+ $form['theme'] = array('#type' => 'value', '#value' => arg(4));
+ $form['info'] = array('#type' => 'value', '#value' => $info);
+
+ return $form;
+}
+
+/**
+ * Theme color form.
+ */
+function theme_color_scheme_form($form) {
+ // Include stylesheet
+ $theme = $form['theme']['#value'];
+ $info = $form['info']['#value'];
+ $path = drupal_get_path('theme', $theme) .'/';
+ drupal_add_css($path . $info['preview_css']);
+
+ // Wrapper
+ $output .= '<div class="color-form clear-block">';
+
+ // Color Schemes
+ $output .= drupal_render($form['scheme']);
+
+ // Palette
+ $output .= '<div id="palette" class="clear-block">';
+ foreach (element_children($form['palette']) as $name) {
+ $output .= drupal_render($form['palette'][$name]);
+ }
+ $output .= '</div>';
+
+ // Preview
+ $output .= drupal_render($form);
+ $output .= '<h2>'. t('Preview') .'</h2>';
+ $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>';
+
+ $output .= '</div>';
+
+ return $output;
+}
+
+/**
+ * Submit handler for color change form.
+ */
+function color_scheme_form_submit($form_id, $values) {
+ // Get theme coloring info
+ if (!isset($values['info'])) {
+ return;
+ }
+ $theme = $values['theme'];
+ $info = $values['info'];
+
+ // Resolve palette
+ $palette = $values['palette'];
+ if ($values['scheme'] != '') {
+ $scheme = explode(',', $values['scheme']);
+ foreach ($palette as $k => $color) {
+ $palette[$k] = array_shift($scheme);
+ }
+ }
+
+ // Delete old files
+ foreach (variable_get('color_'. $theme .'_files', array()) as $file) {
+ @unlink($file);
+ }
+ if ($file = dirname($file)) {
+ @rmdir($file);
+ }
+
+ // Don't render the default colorscheme, use the standard theme instead.
+ if (implode(',', color_get_palette($theme, true)) == implode(',', $palette)
+ || $values['op'] == t('Reset to defaults')) {
+ variable_del('color_'. $theme .'_palette');
+ variable_del('color_'. $theme .'_stylesheet');
+ variable_del('color_'. $theme .'_logo');
+ variable_del('color_'. $theme .'_files');
+ variable_del('color_'. $theme .'_screenshot');
+ return;
+ }
+
+ // Prepare target locations for generated files
+ $id = $theme .'-'. substr(md5(serialize($palette) . microtime()), 0, 8);
+ $paths['target'] = variable_get('file_directory_path', 'files') .'/color/'. $id .'/';
+ foreach ($paths as $path) {
+ if (!is_dir($path)) {
+ mkdir($path);
+ }
+ }
+ $paths['id'] = $id;
+ $paths['source'] = drupal_get_path('theme', $theme) .'/';
+ $paths['stylesheet'] = $paths['target'] .'style.css';
+ $paths['files'] = $paths['map'] = array();
+
+ // Save palette and stylesheet location
+ variable_set('color_'. $theme .'_palette', $palette);
+ variable_set('color_'. $theme .'_stylesheet', $paths['stylesheet']);
+ variable_set('color_'. $theme .'_logo', $paths['target'] .'logo.png');
+
+ // Copy over neutral images
+ foreach ($info['copy'] as $file) {
+ $base = basename($file);
+ copy($paths['source'] . $file, $paths['target'] . $base);
+ $paths['map'][$file] = $base;
+ $paths['files'][] = $paths['target'] . $base;
+ }
+
+ // Render new images
+ _color_render_images($theme, $info, $paths, $palette);
+
+ // Rewrite stylesheet
+ _color_rewrite_stylesheet($theme, $info, $paths, $palette);
+
+ // Maintain list of files
+ variable_set('color_'. $theme .'_files', $paths['files']);
+}
+
+/**
+ * Rewrite the stylesheet to match the colors in the palette.
+ */
+function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette) {
+ // Load stylesheet
+ $style = file_get_contents($paths['source'] .'style.css');
+
+ // Prepare color conversion table
+ $conversion = $palette;
+ unset($conversion['base']);
+ foreach ($conversion as $k => $v) {
+ $conversion[$k] = drupal_strtolower($v);
+ }
+ $default = color_get_palette($theme, true);
+
+ // Split off the "Don't touch" section of the stylesheet.
+ list($style, $fixed) = explode("Color Module: Don't touch", $style);
+
+ // Look for @import commands and insert the referenced stylesheets.
+ $cwd = getcwd();
+ chdir(drupal_get_path('theme', $theme));
+ $style = preg_replace_callback('/@import\s*["\']([^"\']+)["\'];/', '_color_import_stylesheet', $style);
+ chdir($cwd);
+
+ // Find all colors in the stylesheet and the chunks in between.
+ $style = preg_split('/(#[0-9a-f]{6}|#[0-9a-f]{3})/i', $style, -1, PREG_SPLIT_DELIM_CAPTURE);
+ $is_color = false;
+ $output = '';
+ $base = 'base';
+
+ // Iterate over all parts
+ foreach ($style as $chunk) {
+ if ($is_color) {
+ $chunk = drupal_strtolower($chunk);
+ // Check if this is one of the colors in the default palette
+ if ($key = array_search($chunk, $default)) {
+ $chunk = $conversion[$key];
+ }
+ // Not a pre-set color. Extrapolate from the base.
+ else {
+ $chunk = _color_shift($palette[$base], $default[$base], $chunk, $info['blend_target']);
+ }
+ }
+ else {
+ // Determine the most suitable base color for the next color.
+
+ // 'a' declarations. Use link.
+ if (preg_match('@[^a-z0-9_-](a)[^a-z0-9_-][^/{]*{[^{]+$@i', $chunk)) {
+ $base = 'link';
+ }
+ // 'color:' styles. Use text.
+ else if (preg_match('/(?<!-)color[^{:]*:[^{#]*$/i', $chunk)) {
+ $base = 'text';
+ }
+ // Reset back to base.
+ else {
+ $base = 'base';
+ }
+ }
+ $output .= $chunk;
+ $is_color = !$is_color;
+ }
+ // Append fixed colors segment
+ $output .= $fixed;
+
+ // Replace paths to images
+ foreach ($paths['map'] as $before => $after) {
+ $output = str_replace($before, $after, $output);
+ }
+
+ // Write new stylesheet
+ $file = fopen($paths['stylesheet'], 'w+');
+ fwrite($file, $output);
+ fclose($file);
+ $paths['files'][] = $paths['stylesheet'];
+}
+
+/**
+ * Helper function for _color_rewrite_stylesheet.
+ */
+function _color_import_stylesheet($matches) {
+ return preg_replace('/url\(([\'"]?)(?![a-z]+:)/i', 'url(\1'. dirname($matches[1]) .'/', file_get_contents($matches[1]));
+}
+
+/**
+ * Render images that match a given palette.
+ */
+function _color_render_images($theme, &$info, &$paths, $palette) {
+
+ // Prepare template image
+ $source = $paths['source'] .'/'. $info['base_image'];
+ $source = imagecreatefrompng($source);
+
+ // Prepare target buffer
+ $width = imagesx($source);
+ $height = imagesy($source);
+ $target = imagecreatetruecolor($width, $height);
+ imagealphablending($target, true);
+
+ // Fill regions of solid color.
+ foreach ($info['fill'] as $color => $fill) {
+ imagefilledrectangle($target, $fill[0], $fill[1], $fill[0] + $fill[2], $fill[1] + $fill[3], _color_gd($target, $palette[$color]));
+ }
+
+ // Render gradient
+ for ($y = 0; $y < $info['gradient'][3]; ++$y) {
+ $color = _color_blend($target, $palette['top'], $palette['bottom'], $y / ($info['gradient'][3] - 1));
+ imagefilledrectangle($target, $info['gradient'][0], $info['gradient'][1] + $y, $info['gradient'][2], $info['gradient'][1] + $y + 1, $color);
+ }
+
+ // Blend over template
+ imagecopy($target, $source, 0, 0, 0, 0, $width, $height);
+
+ // Cut out slices
+ foreach ($info['slices'] as $file => $coord) {
+ list($x, $y, $width, $height) = $coord;
+ $base = basename($file);
+ $image = $paths['target'] . $base;
+
+ // Cut out slice
+ if ($file == 'screenshot.png') {
+ $slice = imagecreatetruecolor(150, 90);
+ imagecopyresampled($slice, $target, 0, 0, $x, $y, 150, 90, $width, $height);
+ variable_set('color_'. $theme .'_screenshot', $image);
+ }
+ else {
+ $slice = imagecreatetruecolor($width, $height);
+ imagecopy($slice, $target, 0, 0, $x, $y, $width, $height);
+ }
+
+ // Save image
+ imagepng($slice, $image);
+ imagedestroy($slice);
+ $paths['files'][] = $image;
+
+ // Build before/after map of image paths.
+ $paths['map'][$file] = $base;
+ }
+
+ // Clean up
+ imagedestroy($source);
+ imagedestroy($target);
+}
+
+/**
+ * Shift a given color, using a reference pair and a target blend color.
+ *
+ * Note: this function is significantly different from the JS version, as it
+ * is written to match the blended images perfectly.
+ *
+ * Constraint: if (ref2 == target + (ref1 - target) * delta) for some fraction delta
+ * then (return == target + (given - target) * delta)
+ *
+ * Loose constraint: Preserve relative positions in saturation and luminance
+ * space.
+ */
+function _color_shift($given, $ref1, $ref2, $target) {
+
+ // We assume that ref2 is a blend of ref1 and target and find
+ // delta based on the length of the difference vectors:
+
+ // delta = 1 - |ref2 - ref1| / |white - ref1|
+ $target = _color_unpack($target, true);
+ $ref1 = _color_unpack($ref1, true);
+ $ref2 = _color_unpack($ref2, true);
+ for ($i = 0; $i < 3; ++$i) {
+ $numerator += ($ref2[$i] - $ref1[$i]) * ($ref2[$i] - $ref1[$i]);
+ $denominator += ($target[$i] - $ref1[$i]) * ($target[$i] - $ref1[$i]);
+ }
+ $delta = ($denominator > 0) ? (1 - sqrt($numerator / $denominator)) : 0;
+
+ // Calculate the color that ref2 would be if the assumption was true.
+ for ($i = 0; $i < 3; ++$i) {
+ $ref3[$i] = $target[$i] + ($ref1[$i] - $target[$i]) * $delta;
+ }
+
+ // If the assumption is not true, there is a difference between ref2 and ref3.
+ // We measure this in HSL space. Notation: x' = hsl(x).
+ $ref2 = _color_rgb2hsl($ref2);
+ $ref3 = _color_rgb2hsl($ref3);
+ for ($i = 0; $i < 3; ++$i) {
+ $shift[$i] = $ref2[$i] - $ref3[$i];
+ }
+
+ // Take the given color, and blend it towards the target.
+ $given = _color_unpack($given, true);
+ for ($i = 0; $i < 3; ++$i) {
+ $result[$i] = $target[$i] + ($given[$i] - $target[$i]) * $delta;
+ }
+
+ // Finally, we apply the extra shift in HSL space.
+ // Note: if ref2 is a pure blend of ref1 and target, then |shift| = 0.
+ $result = _color_rgb2hsl($result);
+ for ($i = 0; $i < 3; ++$i) {
+ $result[$i] = min(1, max(0, $result[$i] + $shift[$i]));
+ }
+ $result = _color_hsl2rgb($result);
+
+ // Return hex color.
+ return _color_pack($result, true);
+}
+
+/**
+ * Convert a hex triplet into a GD color.
+ */
+function _color_gd($img, $hex) {
+ $c = array_merge(array($img), _color_unpack($hex));
+ return call_user_func_array('imagecolorallocate', $c);
+}
+
+/**
+ * Blend two hex colors and return the GD color.
+ */
+function _color_blend($img, $hex1, $hex2, $alpha) {
+ $in1 = _color_unpack($hex1);
+ $in2 = _color_unpack($hex2);
+ $out = array($img);
+ for ($i = 0; $i < 3; ++$i) {
+ $out[] = $in1[$i] + ($in2[$i] - $in1[$i]) * $alpha;
+ }
+ return call_user_func_array('imagecolorallocate', $out);
+}
+
+/**
+ * Convert a hex color into an RGB triplet.
+ */
+function _color_unpack($hex, $normalize = false) {
+ if (strlen($hex) == 4) {
+ $hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3];
+ }
+ $c = hexdec($hex);
+ for ($i = 16; $i >= 0; $i -= 8) {
+ $out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1);
+ }
+ return $out;
+}
+
+/**
+ * Convert an RGB triplet to a hex color.
+ */
+function _color_pack($rgb, $normalize = false) {
+ foreach ($rgb as $k => $v) {
+ $out |= (($v * ($normalize ? 255 : 1)) << (16 - $k * 8));
+ }
+ return '#'. str_pad(dechex($out), 6, 0, STR_PAD_LEFT);
+}
+
+/**
+ * Convert a HSL triplet into RGB
+ */
+function _color_hsl2rgb($hsl) {
+ $h = $hsl[0];
+ $s = $hsl[1];
+ $l = $hsl[2];
+ $m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l*$s;
+ $m1 = $l * 2 - $m2;
+ return array(_color_hue2rgb($m1, $m2, $h + 0.33333),
+ _color_hue2rgb($m1, $m2, $h),
+ _color_hue2rgb($m1, $m2, $h - 0.33333));
+}
+
+/**
+ * Helper function for _color_hsl2rgb().
+ */
+function _color_hue2rgb($m1, $m2, $h) {
+ $h = ($h < 0) ? $h + 1 : (($h > 1) ? $h - 1 : $h);
+ if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6;
+ if ($h * 2 < 1) return $m2;
+ if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (0.66666 - $h) * 6;
+ return $m1;
+}
+
+/**
+ * Convert an RGB triplet to HSL.
+ */
+function _color_rgb2hsl($rgb) {
+ $r = $rgb[0];
+ $g = $rgb[1];
+ $b = $rgb[2];
+ $min = min($r, min($g, $b));
+ $max = max($r, max($g, $b));
+ $delta = $max - $min;
+ $l = ($min + $max) / 2;
+ $s = 0;
+ if ($l > 0 && $l < 1) {
+ $s = $delta / ($l < 0.5 ? (2 * $l) : (2 - 2 * $l));
+ }
+ $h = 0;
+ if ($delta > 0) {
+ if ($max == $r && $max != $g) $h += ($g - $b) / $delta;
+ if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta);
+ if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta);
+ $h /= 6;
+ }
+ return array($h, $s, $l);
+} \ No newline at end of file
diff --git a/modules/color/images/hook.png b/modules/color/images/hook.png
new file mode 100644
index 000000000..664f0915b
--- /dev/null
+++ b/modules/color/images/hook.png
Binary files differ
diff --git a/modules/color/images/lock.png b/modules/color/images/lock.png
new file mode 100644
index 000000000..6903a9db7
--- /dev/null
+++ b/modules/color/images/lock.png
Binary files differ
diff --git a/modules/system/system.install b/modules/system/system.install
index f18b2ff87..c94a05234 100644
--- a/modules/system/system.install
+++ b/modules/system/system.install
@@ -1010,7 +1010,7 @@ function system_install() {
}
db_query("INSERT INTO {system} (filename, name, type, description, status, throttle, bootstrap, schema_version) VALUES ('themes/engines/phptemplate/phptemplate.engine', 'phptemplate', 'theme_engine', '', 1, 0, 0, 0)");
- db_query("INSERT INTO {system} (filename, name, type, description, status, throttle, bootstrap, schema_version) VALUES ('themes/bluemarine/page.tpl.php', 'bluemarine', 'theme', 'themes/engines/phptemplate/phptemplate.engine', 1, 0, 0, 0)");
+ db_query("INSERT INTO {system} (filename, name, type, description, status, throttle, bootstrap, schema_version) VALUES ('themes/garland/page.tpl.php', 'garland', 'theme', 'themes/engines/phptemplate/phptemplate.engine', 1, 0, 0, 0)");
db_query("INSERT INTO {users} (uid,name,mail) VALUES(0,'','')");
@@ -1020,10 +1020,10 @@ function system_install() {
db_query("INSERT INTO {permission} VALUES (1,'access content',0)");
db_query("INSERT INTO {permission} VALUES (2,'access comments, access content, post comments, post comments without approval',0)");
- db_query("INSERT INTO {variable} (name,value) VALUES('theme_default', 's:10:\"bluemarine\";')");
+ db_query("INSERT INTO {variable} (name,value) VALUES('theme_default', 's:7:\"garland\";')");
- db_query("INSERT INTO {blocks} (module,delta,theme,status) VALUES('user', 0, 'bluemarine', 1)");
- db_query("INSERT INTO {blocks} (module,delta,theme,status) VALUES('user', 1, 'bluemarine', 1)");
+ db_query("INSERT INTO {blocks} (module,delta,theme,status) VALUES('user', 0, 'garland', 1)");
+ db_query("INSERT INTO {blocks} (module,delta,theme,status) VALUES('user', 1, 'garland', 1)");
db_query("INSERT INTO {node_access} VALUES (0, 0, 'all', 1, 0, 0)");