--- modules/color/color.js
+++ modules/color/color.js
@@ -1,6 +1,7 @@
 // $Id: color.js,v 1.6 2007/09/12 18:29:32 goba Exp $
 
 Drupal.behaviors.color = function (context) {
+  var i, colors, field_name;
   // This behavior attaches by ID, so is only valid once on a page.
   if ($('#color_scheme_form .color-form.color-processed').size()) {
     return;
@@ -22,14 +23,25 @@
   }
 
   // Build preview
-  $('#preview:not(.color-processed)')
-    .append('<div id="gradient"></div>')
-    .addClass('color-processed');
-  var gradient = $('#preview #gradient');
-  var h = parseInt(gradient.css('height')) / 10;
-  for (i = 0; i < h; ++i) {
+  var height = [];
+  var width = [];
+  // Loop through all defined gradients.
+  for (i in Drupal.settings.gradients) {
+    // Add element to display the gradient.
+    $('#preview:not(.color-processed)').append('<div id="gradient-' + i + '"></div>');
+    var gradient = $('#preview #gradient-' + i);
+    // Add height of current gradient to the list (divided by 10).
+    height.push(parseInt(gradient.css('height'), 10) / 10);
+    // Add width of current gradient to the list (divided by 10).
+    width.push(parseInt(gradient.css('width'), 10) / 10);
+    // Add rows (or columns for horizontal gradients).
+    // Each gradient line should have a height (or width for horizontal
+    // gradients) of 10px (because we divided the height/width by 10 above).
+    for (j = 0; j < (Drupal.settings.gradients[i]['direction'] == 'vertical' ? height[i] : width[i]); ++j) {
     gradient.append('<div class="gradient-line"></div>');
   }
+  }
+  $('#preview:not(.color-processed)').addClass('color-processed');
 
   // Fix preview background in IE6
   if (navigator.appVersion.match(/MSIE [0-6]\./)) {
@@ -39,13 +51,14 @@
     e.style.filter = "progid:DXImageTransform.Microsoft.AlphaImageLoader(enabled=true, sizingMethod=crop, src='" + image.substring(5, image.length - 2) + "')";
   }
 
-  // Set up colorscheme selector
+  // 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);
+    var schemes = Drupal.settings.color.schemes, colorScheme = this.options[this.selectedIndex].value;
+    if (colorScheme != '' && schemes[colorScheme]) {
+      // Get colors of active scheme.
+      colors = schemes[colorScheme];
+      for (field_name in colors) {
+        callback($('#edit-palette-' + field_name), colors[field_name], false, true);
       }
       preview();
     }
@@ -56,31 +69,34 @@
    */
   function preview() {
     // Solid background
-    $('#preview', form).css('backgroundColor', inputs[0].value);
+    $('#preview', form).css('backgroundColor', $('#palette input[name="palette[base]"]', form).val());
 
     // Text preview
-    $('#text', form).css('color', inputs[4].value);
-    $('#text a, #text h2', form).css('color', inputs[1].value);
+    $('#text', form).css('color', $('#palette input[name="palette[text]"]', form).val());
+    $('#text a, #text h2', form).css('color', $('#palette input[name="palette[link]"]', form).val());
 
-    // Set up gradient
-    var top = farb.unpack(inputs[2].value);
-    var bottom = farb.unpack(inputs[3].value);
-    if (top && bottom) {
+    // Set up gradients if there are some.
+    var color_start, color_end;
+    for (i in Drupal.settings.gradients) {
+      color_start = farb.unpack($('#palette input[name="palette[' + Drupal.settings.gradients[i]['colors'][0] + ']"]', form).val());
+      color_end = farb.unpack($('#palette input[name="palette[' + Drupal.settings.gradients[i]['colors'][1] + ']"]', form).val());
+      if (color_start && color_end) {
       var delta = [];
-      for (i in top) {
-        delta[i] = (bottom[i] - top[i]) / h;
-      }
-      var accum = top;
+        for (j in color_start) {
+          delta[j] = (color_end[j] - color_start[j]) / (Drupal.settings.gradients[i]['vertical'] ? height[i] : width[i]);
 
-      // Render gradient lines
-      $('#gradient > div', form).each(function () {
-        for (i in accum) {
-          accum[i] += delta[i];
         }
+        var accum = color_start;
+        // Render gradient lines.
+        $('#gradient-' + i + ' > div', form).each(function () {
+          for (j in accum) {
+            accum[j] += delta[j];
+          }
         this.style.backgroundColor = farb.pack(accum);
       });
     }
   }
+  }
 
   /**
    * Shift a given color, using a reference pair (ref in HSL).
@@ -132,7 +148,8 @@
   /**
    * Callback for Farbtastic when a new color is chosen.
    */
-  function callback(input, color, propagate, colorscheme) {
+  function callback(input, color, propagate, colorScheme) {
+    var i, j, matched;
     // Set background/foreground color
     $(input).css({
       backgroundColor: color,
@@ -140,20 +157,20 @@
     });
 
     // Change input value
-    if (input.value && input.value != color) {
-      input.value = color;
+    if ($(input).val() && $(input).val() != color) {
+      $(input).val(color);
 
       // Update locked values
       if (propagate) {
-        var i = input.i;
+        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]);
+          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]);
+          matched = shift_color(color, reference[input.key], reference[inputs[j].key]);
           callback(inputs[j], matched, false);
         }
 
@@ -161,8 +178,8 @@
         preview();
       }
 
-      // Reset colorscheme selector
-      if (!colorscheme) {
+      // Reset colorScheme selector
+      if (!colorScheme) {
         resetScheme();
       }
     }
@@ -188,7 +205,9 @@
 
     // Add new bindings
     focused = this;
-    farb.linkTo(function (color) { callback(input, color, true, false); });
+    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');
@@ -228,7 +247,7 @@
       );
       $(this).after(lock);
       locks.push(lock);
-    };
+    }
 
     // Add hook
     var hook = $('<div class="hook"></div>');

--- modules/color/color.module
+++ modules/color/color.module
@@ -133,12 +133,8 @@
  */
 function color_get_palette($theme, $default = false) {
   // Fetch and expand default palette
-  $fields = array('base', 'link', 'top', 'bottom', 'text');
   $info = color_get_info($theme);
-  $keys = array_keys($info['schemes']);
-  foreach (explode(',', array_shift($keys)) as $k => $scheme) {
-    $palette[$fields[$k]] = $scheme;
-  }
+  $palette = $info['schemes']['default']['colors'];

   // Load variable
   return $default ? $palette : variable_get('color_'. $theme .'_palette', $palette);
@@ -151,42 +147,60 @@
   $base = drupal_get_path('module', 'color');
   $info = color_get_info($theme);

+  $info['schemes'][''] = array('title' => t('Custom'), 'colors' => array());
+  $color_sets = array();
+  $schemes = array();
+  foreach ($info['schemes'] as $key => $scheme) {
+    $color_sets[$key] = $scheme['title'];
+    $schemes[$key] = $scheme['colors'];
+    $schemes[$key] += $info['schemes']['default']['colors'];
+  }
+
   // Add Farbtastic color picker
   drupal_add_css('misc/farbtastic/farbtastic.css', 'module', 'all', FALSE);
   drupal_add_js('misc/farbtastic/farbtastic.js');
+  drupal_add_js('misc/jquery.once.js');

   // Add custom CSS/JS
   drupal_add_css($base .'/color.css', 'module', 'all', FALSE);
   drupal_add_js($base .'/color.js');
   drupal_add_js(array('color' => array(
-    'reference' => color_get_palette($theme, true)
-  )), 'setting');
+    'reference' => color_get_palette($theme, true),
+    'schemes' => $schemes)), 'setting');
+  drupal_add_js(array('gradients' => $info['gradients']), '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']) : '');
+  $current_scheme = variable_get('color_' . $theme . '_palette', array());
+  foreach ($schemes as $key => $scheme) {
+    if ($current_scheme == $scheme) {
+      $scheme_name = $key;
+      break;
+    }
+  }
+  if (empty($scheme_name)) {
+    if (empty($current_scheme)) {
+      $scheme_name = 'default';
+    }
+    else {
+      $scheme_name = '';
+    }
+  }

   // Add scheme selector
-  $info['schemes'][''] = t('Custom');
   $form['scheme'] = array(
     '#type' => 'select',
     '#title' => t('Color set'),
-    '#options' => $info['schemes'],
-    '#default_value' => $current,
+    '#options' => $color_sets,
+    '#default_value' => $scheme_name,
   );

   // 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')
-  );
+  $names = $info['fields'];
   $form['palette']['#tree'] = true;
   foreach ($palette as $name => $value) {
+    if (isset($names[$name])) {
     $form['palette'][$name] = array(
       '#type' => 'textfield',
       '#title' => $names[$name],
@@ -194,6 +208,7 @@
       '#size' => 8,
     );
   }
+  }
   $form['theme'] = array('#type' => 'value', '#value' => arg(4));
   $form['info'] = array('#type' => 'value', '#value' => $info);

@@ -250,11 +265,13 @@
   // Resolve palette
   $palette = $form_state['values']['palette'];
   if ($form_state['values']['scheme'] != '') {
-    $scheme = explode(',', $form_state['values']['scheme']);
-    foreach ($palette as $k => $color) {
-      $palette[$k] = array_shift($scheme);
+    foreach ($palette as $key => $color) {
+      if (isset($info['schemes'][$form_state['values']['scheme']]['colors'][$key])) {
+        $palette[$key] = $info['schemes'][$form_state['values']['scheme']]['colors'][$key];
     }
   }
+    $palette += $info['schemes']['default']['colors'];
+  }

   // Make sure enough memory is available, if PHP's memory limit is compiled in.
   if (function_exists('memory_get_usage')) {
@@ -469,11 +486,24 @@
     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'][0] + $info['gradient'][2], $info['gradient'][1] + $y + 1, $color);
+  // Render gradients.
+  foreach ($info['gradients'] as $gradient) {
+    // Get direction of the gradient.
+    if (isset($gradient['direction']) && $gradient['direction'] == 'horizontal') {
+      // Horizontal gradient.
+      for ($x = 0; $x < $gradient['dimension'][2]; $x++) {
+        $color = _color_blend($target, $palette[$gradient['colors'][0]], $palette[$gradient['colors'][1]], $x / ($gradient['dimension'][2] - 1));
+        imagefilledrectangle($target, ($gradient['dimension'][0] + $x), $gradient['dimension'][1], ($gradient['dimension'][0] + $x + 1), ($gradient['dimension'][1] + $gradient['dimension'][3]), $color);
   }
+    }
+    else {
+      // Vertical gradient.
+      for ($y = 0; $y < $gradient['dimension'][3]; $y++) {
+        $color = _color_blend($target, $palette[$gradient['colors'][0]], $palette[$gradient['colors'][1]], $y / ($gradient['dimension'][3] - 1));
+        imagefilledrectangle($target, $gradient['dimension'][0], $gradient['dimension'][1] + $y, $gradient['dimension'][0] + $gradient['dimension'][2], $gradient['dimension'][1] + $y + 1, $color);
+      }
+    }
+  }

   // Blend over template.
   imagecopy($target, $source, 0, 0, 0, 0, $width, $height);

--- themes/garland/color/color.inc
+++ themes/garland/color/color.inc
@@ -3,23 +3,160 @@

 $info = array(

+  // Available colors and color labels used in theme.
+  'fields' => array(
+    'base' => t('Base color'),
+    'link' => t('Link color'),
+    'top' => t('Header top'),
+    'bottom' => t('Header bottom'),
+    'text' => t('Text color'),
+  ),
   // Pre-defined color schemes.
   'schemes' => array(
-    '#0072b9,#027ac6,#2385c2,#5ab5ee,#494949' => t('Blue Lagoon (Default)'),
-    '#464849,#2f416f,#2a2b2d,#5d6779,#494949' => t('Ash'),
-    '#55c0e2,#000000,#085360,#007e94,#696969' => t('Aquamarine'),
-    '#d5b048,#6c420e,#331900,#971702,#494949' => t('Belgian Chocolate'),
-    '#3f3f3f,#336699,#6598cb,#6598cb,#000000' => t('Bluemarine'),
-    '#d0cb9a,#917803,#efde01,#e6fb2d,#494949' => t('Citrus Blast'),
-    '#0f005c,#434f8c,#4d91ff,#1a1575,#000000' => t('Cold Day'),
-    '#c9c497,#0c7a00,#03961e,#7be000,#494949' => t('Greenbeam'),
-    '#ffe23d,#a9290a,#fc6d1d,#a30f42,#494949' => t('Mediterrano'),
-    '#788597,#3f728d,#a9adbc,#d4d4d4,#707070' => t('Mercury'),
-    '#5b5fa9,#5b5faa,#0a2352,#9fa8d5,#494949' => t('Nocturnal'),
-    '#7db323,#6a9915,#b5d52a,#7db323,#191a19' => t('Olivia'),
-    '#12020b,#1b1a13,#f391c6,#f41063,#898080' => t('Pink Plastic'),
-    '#b7a0ba,#c70000,#a1443a,#f21107,#515d52' => t('Shiny Tomato'),
-    '#18583d,#1b5f42,#34775a,#52bf90,#2d2d2d' => t('Teal Top'),
+    'default' => array(
+      'title' => t('Blue Lagoon (Default)'),
+      'colors' => array(
+        'base' => '#0072b9',
+        'link' => '#027ac6',
+        'top' => '#2385c2',
+        'bottom' => '#5ab5ee',
+        'text' => '#494949',
+      ),
+    ),
+    'ash' => array(
+      'title' => t('Ash'),
+      'colors' => array(
+        'base' => '#464849',
+        'link' => '#2f416f',
+        'top' => '#2a2b2d',
+        'bottom' => '#5d6779',
+      ),
+    ),
+    'aquamarine' => array(
+      'title' => t('Aquamarine'),
+      'colors' => array(
+        'base' => '#55c0e2',
+        'link' => '#000000',
+        'text' => '#696969',
+        'top' => '#085360',
+        'bottom' => '#007e94',
+      ),
+    ),
+    'chocolate' => array(
+      'title' => t('Belgian Chocolate'),
+      'colors' => array(
+        'base' => '#d5b048',
+        'link' => '#6c420e',
+        'top' => '#331900',
+        'bottom' => '#971702',
+      ),
+    ),
+    'bluemarine' => array(
+      'title' => t('Bluemarine'),
+      'colors' => array(
+        'base' => '#3f3f3f',
+        'link' => '#336699',
+        'text' => '#000000',
+        'top' => '#6598cb',
+        'bottom' => '#6598cb',
+      ),
+    ),
+    'citrus' => array(
+      'title' => t('Citrus Blast'),
+      'colors' => array(
+        'base' => '#d0cb9a',
+        'link' => '#917803',
+        'top' => '#efde01',
+        'bottom' => '#e6fb2d',
+      ),
+    ),
+    'cold' => array(
+      'title' => t('Cold Day'),
+      'colors' => array(
+        'base' => '#0f005c',
+        'link' => '#434f8c',
+        'text' => '#000000',
+        'top' => '#4d91ff',
+        'bottom' => '#1a1575',
+      ),
+    ),
+    'greenbeam' => array(
+      'title' => t('Greenbeam'),
+      'colors' => array(
+        'base' => '#c9c497',
+        'link' => '#0c7a00',
+        'top' => '#03961e',
+        'bottom' => '#7be000',
+      ),
+    ),
+    'mediterrano' => array(
+      'title' => t('Mediterrano'),
+      'colors' => array(
+        'base' => '#ffe23d',
+        'link' => '#a9290a',
+        'top' => '#fc6d1d',
+        'bottom' => '#a30f42',
+      ),
+    ),
+    'mercury' => array(
+      'title' => t('Mercury'),
+      'colors' => array(
+        'base' => '#788597',
+        'link' => '#3f728d',
+        'top' => '#a9adbc',
+        'bottom' => '#d4d4d4',
+        'text' => '#707070',
+      ),
+    ),
+    'nocturnal' => array(
+      'title' => t('Nocturnal'),
+      'colors' => array(
+        'base' => '#5b5fa9',
+        'link' => '#5b5faa',
+        'top' => '#0a2352',
+        'bottom' => '#9fa8d5',
+      ),
+    ),
+    'olivia' => array(
+      'title' => t('Olivia'),
+      'colors' => array(
+        'base' => '#7db323',
+        'link' => '#6a9915',
+        'top' => '#b5d52a',
+        'bottom' => '#7db323',
+        'text' => '#191a19',
+      ),
+    ),
+    'pink_plastic' => array(
+      'title' => t('Pink Plastic'),
+      'colors' => array(
+        'base' => '#12020b',
+        'link' => '#1b1a13',
+        'top' => '#f391c6',
+        'bottom' => '#f41063',
+        'text' => '#898080',
+      ),
+    ),
+    'shiny_tomato' => array(
+      'title' => t('Shiny Tomato'),
+      'colors' => array(
+        'base' => '#b7a0ba',
+        'link' => '#c70000',
+        'top' => '#a1443a',
+        'bottom' => '#f21107',
+        'text' => '#515d52',
+      ),
+    ),
+    'teal_top' => array(
+      'title' => t('Teal Top'),
+      'colors' => array(
+        'base' => '#18583d',
+        'link' => '#1b5f42',
+        'top' => '#34775a',
+        'bottom' => '#52bf90',
+        'text' => '#2d2d2d',
+      ),
+    ),
   ),

   // Images to copy over.
@@ -35,8 +172,17 @@ $info = array(
     'style.css',
   ),

-  // Coordinates of gradient (x, y, width, height).
-  'gradient' => array(0, 37, 760, 121),
+  // Gradient definitions.
+  'gradients' => array(
+    array(
+      // (x, y, width, height).
+      'dimension' => array(0, 38, 760, 121),
+      // Direction of gradient ('vertical' or 'horizontal').
+      'direction' => 'vertical',
+      // Keys of colors to use for the gradient.
+      'colors' => array('top', 'bottom'),
+    ),
+  ),

   // Color areas to fill (x, y, width, height).
   'fill' => array(

--- themes/garland/color/preview.css
+++ themes/garland/color/preview.css
@@ -6,10 +6,10 @@
   max-width: 100%;
 }
 #preview, #preview #img {
-  width: 596px;
+  width: 600px;
   height: 371px;
 }
-#preview #gradient {
+#preview #gradient-0 {
   position: absolute;
   left: 0;
   right: 0;
@@ -29,7 +29,7 @@
   position: relative;
   z-index: 3;
 }
-#preview #gradient .gradient-line {
+#preview #gradient-0 .gradient-line {
   height: 10px;
   overflow: hidden;
 }
