Index: fivestar.css
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fivestar/fivestar.css,v
retrieving revision 1.1.2.10
diff -u -r1.1.2.10 fivestar.css
--- fivestar.css 7 Jan 2008 08:37:16 -0000 1.1.2.10
+++ fivestar.css 10 Mar 2008 01:30:20 -0000
@@ -86,31 +86,3 @@
div.fivestar-widget div.hover a, div.rating div a:hover {
background-position: 0 -32px;
}
-
-/* Fivestar Settings Preview */
-iframe.fivestar-preview {
- border: none;
- width: 200px;
- height: 32px;
-}
-div.fivestar-widgets div.form-item {
- float: left;
-}
-
-/* Fivestar Node Type Preview */
-#fivestar-comment-form,
-#fivestar-direct-form {
- float: left;
-}
-#fivestar-comment-preview,
-#fivestar-direct-preview {
- float: left;
- margin-left: 40px;
-}
-#fivestar-node-type-form fieldset {
- background: transparent;
-}
-.fivestar-preview {
- border: 1px solid #CCC;
- padding: 10px;
-}
Index: fivestar.module
===================================================================
RCS file: /cvs/drupal-contrib/contributions/modules/fivestar/fivestar.module,v
retrieving revision 1.2.2.69
diff -u -r1.2.2.69 fivestar.module
--- fivestar.module 26 Feb 2008 20:15:27 -0000 1.2.2.69
+++ fivestar.module 10 Mar 2008 01:30:21 -0000
@@ -299,6 +299,7 @@
function theme_fivestar_node_type_form($form) {
drupal_add_js(drupal_get_path('module', 'fivestar') .'/fivestar-admin.js');
drupal_add_js(array('fivestar' => array('preview_url' => url('fivestar/preview/node'))), 'setting');
+ drupal_add_css(drupal_get_path('module', 'fivestar') .'/fivestar-admin.css');
$output = '';
$output .= drupal_render($form['fivestar']);
@@ -372,7 +373,10 @@
* Callback function for admin/settings/fivestar. Display the settings form.
*/
function fivestar_settings() {
- $form = array();
+ include_once(drupal_get_path('module', 'fivestar') .'/fivestar_color.inc');
+
+ $form = fivestar_color_form();
+
$form['fivestar_widget'] = array(
'#type' => 'radios',
'#title' => t('Widget display'),
@@ -393,16 +397,17 @@
function theme_fivestar_settings($form) {
fivestar_add_css();
+ drupal_add_css(drupal_get_path('module', 'fivestar') .'/fivestar-admin.css');
drupal_set_title(t('Fivestar Settings'));
// Default preview.
- $form['fivestar_widget']['default']['#description'] = 'Default '. t('Preview') .':
';
+ //$form['fivestar_widget']['default']['#description'] = 'Default '. t('Preview') .':
';
// Preview for each widget.
$widget_number = 0;
foreach (element_children($form['fivestar_widget']) as $widget_key) {
if ($widget_key != 'default') {
- $form['fivestar_widget'][$widget_key]['#description'] = $form['fivestar_widget'][$widget_key]['#title'] .' '. t('Preview') .':
';
+ //$form['fivestar_widget'][$widget_key]['#description'] = $form['fivestar_widget'][$widget_key]['#title'] .' '. t('Preview') .':
';
$widget_number++;
}
}
Index: fivestar-admin.css
===================================================================
RCS file: fivestar-admin.css
diff -N fivestar-admin.css
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ fivestar-admin.css 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,27 @@
+/* Fivestar Settings Preview */
+iframe.fivestar-preview {
+ border: none;
+ width: 200px;
+ height: 32px;
+}
+div.fivestar-widgets div.form-item {
+ float: left;
+}
+
+/* Fivestar Node Type Preview */
+#fivestar-comment-form,
+#fivestar-direct-form {
+ float: left;
+}
+#fivestar-comment-preview,
+#fivestar-direct-preview {
+ float: left;
+ margin-left: 40px;
+}
+#fivestar-node-type-form fieldset {
+ background: transparent;
+}
+.fivestar-preview {
+ border: 1px solid #CCC;
+ padding: 10px;
+}
Index: fivestar_color.inc
===================================================================
RCS file: fivestar_color.inc
diff -N fivestar_color.inc
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ fivestar_color.inc 1 Jan 1970 00:00:00 -0000
@@ -0,0 +1,507 @@
+name;
+
+ // See if we're using a predefined scheme.
+ $current = implode(',', variable_get('fivestar_color_palette', array()));
+
+ $options = array('fivestar_yellow' => t('Yellow'), 'fivestar_red' => t('Red'), 'fivestar_blue' => t('Blue'), 'fivestar_green' => t('Green'));
+ if (!empty($theme_info['schemes'])) {
+ foreach ($theme_info['schemes'] as $key => $theme_scheme) {
+ $colors = explode(',', $theme_scheme);
+ unset($colors[1], $colors[2], $colors[5]);
+ }
+ $options = array(t('Fivestar schemes') => $options, t('@theme_name schemes', array('@theme_name' => drupal_ucfirst($theme_name))) => $theme_info['schemes']);
+ }
+
+ $form = array('#submit' => array('fivestar_color_form_submit'));
+
+ // Add scheme selector.
+ $info['schemes'][''] = t('Custom');
+ $form['scheme'] = array(
+ '#type' => 'select',
+ '#title' => t('Color set'),
+ '#options' => $options,
+ '#default_value' => $current,
+ );
+
+ // Add palette fields.
+ $names = array(
+ 'off1' => t('Off 1 color'),
+ 'off2' => t('Off 2 color'),
+ 'hover1' => t('Hover 1 color'),
+ 'hover2' => t('Hover 2 color'),
+ 'on1' => t('On 1 color'),
+ 'on2' => t('On 2 color'),
+ );
+
+ $default_colors = array(
+ 'off1' => '#cccccc',
+ 'off2' => '#cccccc',
+ 'hover1' => '#cccccc',
+ 'hover2' => '#cccccc',
+ 'on1' => '#cccccc',
+ 'on2' => '#cccccc',
+ );
+ $color_scheme = variable_get('fivestar_colors', $default_colors);
+
+ $form['palette']['#tree'] = true;
+ $form['palette']['#theme'] = 'fivestar_color_palette';
+ foreach ($names as $key => $name) {
+ $form['palette'][$key] = array(
+ '#type' => 'textfield',
+ '#title' => $name,
+ '#default_value' => $color_scheme[$key],
+ '#size' => 8,
+ );
+ }
+
+ return $form;
+}
+
+/**
+ * Theme color form.
+ */
+function theme_fivestar_color_palette($form) {
+ // Add Farbtastic color picker.
+ drupal_add_js(drupal_get_path('module', 'color') .'/color.js');
+ drupal_add_css(drupal_get_path('module', 'color') .'/color.css');
+ drupal_add_css('misc/farbtastic/farbtastic.css', 'module', 'all', FALSE);
+ drupal_add_js('misc/farbtastic/farbtastic.js');
+
+ // Add custom CSS/JS.
+ $default_colors = array(
+ 'off1' => '#cccccc',
+ 'off2' => '#cccccc',
+ 'hover1' => '#cccccc',
+ 'hover2' => '#cccccc',
+ 'on1' => '#cccccc',
+ 'on2' => '#cccccc',
+ );
+ $color_scheme = variable_get('fivestar_colors', $default_colors);
+ drupal_add_js(array('color' => array('reference' => $color_scheme)), 'setting');
+
+ // Wrapper
+ $output .= '
';
+
+ return $output;
+}
+
+/**
+ * Submit handler for color change form.
+ */
+function fivstar_color_form_submit($form_id, $values) {
+ $theme = variable_get('theme_default', 'garland');
+
+ // Resolve palette
+ $palette = $values['palette'];
+ if ($values['scheme'] != '') {
+ $scheme = explode(',', $values['scheme']);
+ foreach ($palette as $k => $color) {
+ $palette[$k] = array_shift($scheme);
+ }
+ }
+
+ // Make sure enough memory is available, if PHP's memory limit is compiled in.
+ if (function_exists('memory_get_usage')) {
+ // Fetch source image dimensions.
+ $source = drupal_get_path('theme', $theme) .'/'. $info['base_image'];
+ list($width, $height) = getimagesize($source);
+
+ // We need at least a copy of the source and a target buffer of the same
+ // size (both at 32bpp).
+ $required = $width * $height * 8;
+ $usage = memory_get_usage();
+ $limit = parse_size(ini_get('memory_limit'));
+ if ($usage + $required > $limit) {
+ 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 PHP documentation 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');
+ return;
+ }
+ }
+
+ // 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['color'] = file_directory_path() .'/color';
+ $paths['target'] = $paths['color'] .'/'. $id;
+ foreach ($paths as $path) {
+ file_check_directory($path, FILE_CREATE_DIRECTORY);
+ }
+ $paths['target'] = $paths['target'] .'/';
+ $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);
+ $source = $paths['source'] . $file;
+ file_copy($source, $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 _fivestar_color_rewrite_stylesheet($theme, $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('/(? $after) {
+ $output = str_replace($before, $after, $output);
+ }
+
+ // Write new stylesheet
+ $file = fopen($paths['stylesheet'], 'w+');
+ fwrite($file, $output);
+ fclose($file);
+ $paths['files'][] = $paths['stylesheet'];
+
+ // Set standard file permissions for webserver-generated files
+ @chmod($paths['stylesheet'], 0664);
+}
+
+/**
+ * Helper function for _color_rewrite_stylesheet.
+ */
+function _fivestar_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 _fivestar_color_render_images($theme, &$info, &$paths, $palette) {
+
+ // Prepare template image.
+ $source = $paths['source'] .'/'. $info['base_image'];
+ $source = imagecreatefrompng($source);
+ $width = imagesx($source);
+ $height = imagesy($source);
+
+ // Prepare target buffer.
+ $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'][0] + $info['gradient'][2], $info['gradient'][1] + $y + 1, $color);
+ }
+
+ // Blend over template.
+ imagecopy($target, $source, 0, 0, 0, 0, $width, $height);
+
+ // Clean up template image.
+ imagedestroy($source);
+
+ // 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;
+
+ // Set standard file permissions for webserver-generated files
+ @chmod(realpath($image), 0664);
+
+ // Build before/after map of image paths.
+ $paths['map'][$file] = $base;
+ }
+
+ // Clean up target buffer.
+ 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 _fivestar_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 _fivestar_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 _fivestar_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 _fivestar_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 _fivestar_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 _fivestar_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 _fivestar_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 _fivestar_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);
+}
+