danielebarchiesi@0
|
1 <?php
|
danielebarchiesi@0
|
2 /**
|
danielebarchiesi@0
|
3 * @file
|
danielebarchiesi@0
|
4 * Allows users to change the color scheme of themes.
|
danielebarchiesi@0
|
5 */
|
danielebarchiesi@0
|
6
|
danielebarchiesi@0
|
7 /**
|
danielebarchiesi@0
|
8 * Implements hook_help().
|
danielebarchiesi@0
|
9 */
|
danielebarchiesi@0
|
10 function color_help($path, $arg) {
|
danielebarchiesi@0
|
11 switch ($path) {
|
danielebarchiesi@0
|
12 case 'admin/help#color':
|
danielebarchiesi@0
|
13 $output = '<h3>' . t('About') . '</h3>';
|
danielebarchiesi@0
|
14 $output .= '<p>' . t('The Color module allows users with the <em>Administer site configuration</em> permission to quickly and easily change the color scheme of themes that have been built to be compatible with it. For more information, see the online handbook entry for <a href="@color">Color module</a>.', array('@color' => 'http://drupal.org/documentation/modules/color')) . '</p>';
|
danielebarchiesi@0
|
15 $output .= '<h3>' . t('Uses') . '</h3>';
|
danielebarchiesi@0
|
16 $output .= '<dl>';
|
danielebarchiesi@0
|
17 $output .= '<dt>' . t('Changing colors') . '</dt>';
|
danielebarchiesi@0
|
18 $output .= '<dd>' . t("Using the Color module allows you to easily change the color of links, backgrounds, text, and other theme elements. To change the color settings for a compatible theme, select the <em>Settings</em> link for your theme on the <a href='@configure'>Themes administration page</a>. If you don't see a color picker on that page, then your theme is not compatible with the color module. If you are sure that the theme does indeed support the color module, but the color picker does not appear, then <a href='@troubleshoot'>follow these troubleshooting procedures</a>.", array('@configure' => url('admin/appearance'), '@troubleshoot' => 'http://drupal.org/node/109457')) . '</dd>';
|
danielebarchiesi@0
|
19 $output .= '<dd>' . t("The 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, <em>you must save your color settings again, even if they haven't changed</em>. This step is required because the module stylesheets (in the files directory) need to be recreated to include your changes.") . '</dd>';
|
danielebarchiesi@0
|
20 $output .= '</dl>';
|
danielebarchiesi@0
|
21 return $output;
|
danielebarchiesi@0
|
22 }
|
danielebarchiesi@0
|
23 }
|
danielebarchiesi@0
|
24
|
danielebarchiesi@0
|
25 /**
|
danielebarchiesi@0
|
26 * Implements hook_theme().
|
danielebarchiesi@0
|
27 */
|
danielebarchiesi@0
|
28 function color_theme() {
|
danielebarchiesi@0
|
29 return array(
|
danielebarchiesi@0
|
30 'color_scheme_form' => array(
|
danielebarchiesi@0
|
31 'render element' => 'form',
|
danielebarchiesi@0
|
32 ),
|
danielebarchiesi@0
|
33 );
|
danielebarchiesi@0
|
34 }
|
danielebarchiesi@0
|
35
|
danielebarchiesi@0
|
36 /**
|
danielebarchiesi@0
|
37 * Implements hook_form_FORM_ID_alter().
|
danielebarchiesi@0
|
38 */
|
danielebarchiesi@0
|
39 function color_form_system_theme_settings_alter(&$form, &$form_state) {
|
danielebarchiesi@0
|
40 if (isset($form_state['build_info']['args'][0]) && ($theme = $form_state['build_info']['args'][0]) && color_get_info($theme) && function_exists('gd_info')) {
|
danielebarchiesi@0
|
41 $form['color'] = array(
|
danielebarchiesi@0
|
42 '#type' => 'fieldset',
|
danielebarchiesi@0
|
43 '#title' => t('Color scheme'),
|
danielebarchiesi@0
|
44 '#weight' => -1,
|
danielebarchiesi@0
|
45 '#attributes' => array('id' => 'color_scheme_form'),
|
danielebarchiesi@0
|
46 '#theme' => 'color_scheme_form',
|
danielebarchiesi@0
|
47 );
|
danielebarchiesi@0
|
48 $form['color'] += color_scheme_form($form, $form_state, $theme);
|
danielebarchiesi@0
|
49 $form['#validate'][] = 'color_scheme_form_validate';
|
danielebarchiesi@0
|
50 $form['#submit'][] = 'color_scheme_form_submit';
|
danielebarchiesi@0
|
51 }
|
danielebarchiesi@0
|
52 }
|
danielebarchiesi@0
|
53
|
danielebarchiesi@0
|
54 /**
|
danielebarchiesi@0
|
55 * Implements hook_form_FORM_ID_alter().
|
danielebarchiesi@0
|
56 */
|
danielebarchiesi@0
|
57 function color_form_system_themes_alter(&$form, &$form_state) {
|
danielebarchiesi@0
|
58 _color_theme_select_form_alter($form, $form_state);
|
danielebarchiesi@0
|
59 }
|
danielebarchiesi@0
|
60
|
danielebarchiesi@0
|
61 /**
|
danielebarchiesi@0
|
62 * Helper for hook_form_FORM_ID_alter() implementations.
|
danielebarchiesi@0
|
63 */
|
danielebarchiesi@0
|
64 function _color_theme_select_form_alter(&$form, &$form_state) {
|
danielebarchiesi@0
|
65 // Use the generated screenshot in the theme list.
|
danielebarchiesi@0
|
66 $themes = list_themes();
|
danielebarchiesi@0
|
67 foreach (element_children($form) as $theme) {
|
danielebarchiesi@0
|
68 if ($screenshot = variable_get('color_' . $theme . '_screenshot')) {
|
danielebarchiesi@0
|
69 if (isset($form[$theme]['screenshot'])) {
|
danielebarchiesi@0
|
70 $form[$theme]['screenshot']['#markup'] = theme('image', array('path' => $screenshot, 'title' => '', 'attributes' => array('class' => array('screenshot'))));
|
danielebarchiesi@0
|
71 }
|
danielebarchiesi@0
|
72 }
|
danielebarchiesi@0
|
73 }
|
danielebarchiesi@0
|
74 }
|
danielebarchiesi@0
|
75
|
danielebarchiesi@0
|
76 /**
|
danielebarchiesi@0
|
77 * Replaces style sheets with color-altered style sheets.
|
danielebarchiesi@0
|
78 *
|
danielebarchiesi@0
|
79 * A theme that supports the color module should call this function from its
|
danielebarchiesi@0
|
80 * THEME_process_html() function, so that the correct style sheets are
|
danielebarchiesi@0
|
81 * included when html.tpl.php is rendered.
|
danielebarchiesi@0
|
82 *
|
danielebarchiesi@0
|
83 * @see theme()
|
danielebarchiesi@0
|
84 */
|
danielebarchiesi@0
|
85 function _color_html_alter(&$vars) {
|
danielebarchiesi@0
|
86 global $theme_key;
|
danielebarchiesi@0
|
87 $themes = list_themes();
|
danielebarchiesi@0
|
88
|
danielebarchiesi@0
|
89 // Override stylesheets.
|
danielebarchiesi@0
|
90 $color_paths = variable_get('color_' . $theme_key . '_stylesheets', array());
|
danielebarchiesi@0
|
91 if (!empty($color_paths)) {
|
danielebarchiesi@0
|
92
|
danielebarchiesi@0
|
93 foreach ($themes[$theme_key]->stylesheets['all'] as $base_filename => $old_path) {
|
danielebarchiesi@0
|
94 // Loop over the path array with recolored CSS files to find matching
|
danielebarchiesi@0
|
95 // paths which could replace the non-recolored paths.
|
danielebarchiesi@0
|
96 foreach ($color_paths as $color_path) {
|
danielebarchiesi@0
|
97 // Color module currently requires unique file names to be used,
|
danielebarchiesi@0
|
98 // which allows us to compare different file paths.
|
danielebarchiesi@0
|
99 if (drupal_basename($old_path) == drupal_basename($color_path)) {
|
danielebarchiesi@0
|
100 // Replace the path to the new css file.
|
danielebarchiesi@0
|
101 // This keeps the order of the stylesheets intact.
|
danielebarchiesi@0
|
102 $vars['css'][$old_path]['data'] = $color_path;
|
danielebarchiesi@0
|
103 }
|
danielebarchiesi@0
|
104 }
|
danielebarchiesi@0
|
105 }
|
danielebarchiesi@0
|
106
|
danielebarchiesi@0
|
107 $vars['styles'] = drupal_get_css($vars['css']);
|
danielebarchiesi@0
|
108 }
|
danielebarchiesi@0
|
109 }
|
danielebarchiesi@0
|
110
|
danielebarchiesi@0
|
111 /**
|
danielebarchiesi@0
|
112 * Replaces the logo with a color-altered logo.
|
danielebarchiesi@0
|
113 *
|
danielebarchiesi@0
|
114 * A theme that supports the color module should call this function from its
|
danielebarchiesi@0
|
115 * THEME_process_page() function, so that the correct logo is included when
|
danielebarchiesi@0
|
116 * page.tpl.php is rendered.
|
danielebarchiesi@0
|
117 *
|
danielebarchiesi@0
|
118 * @see theme()
|
danielebarchiesi@0
|
119 */
|
danielebarchiesi@0
|
120 function _color_page_alter(&$vars) {
|
danielebarchiesi@0
|
121 global $theme_key;
|
danielebarchiesi@0
|
122
|
danielebarchiesi@0
|
123 // Override logo.
|
danielebarchiesi@0
|
124 $logo = variable_get('color_' . $theme_key . '_logo');
|
danielebarchiesi@0
|
125 if ($logo && $vars['logo'] && preg_match('!' . $theme_key . '/logo.png$!', $vars['logo'])) {
|
danielebarchiesi@0
|
126 $vars['logo'] = file_create_url($logo);
|
danielebarchiesi@0
|
127 }
|
danielebarchiesi@0
|
128 }
|
danielebarchiesi@0
|
129
|
danielebarchiesi@0
|
130 /**
|
danielebarchiesi@0
|
131 * Retrieves the Color module information for a particular theme.
|
danielebarchiesi@0
|
132 */
|
danielebarchiesi@0
|
133 function color_get_info($theme) {
|
danielebarchiesi@0
|
134 static $theme_info = array();
|
danielebarchiesi@0
|
135
|
danielebarchiesi@0
|
136 if (isset($theme_info[$theme])) {
|
danielebarchiesi@0
|
137 return $theme_info[$theme];
|
danielebarchiesi@0
|
138 }
|
danielebarchiesi@0
|
139
|
danielebarchiesi@0
|
140 $path = drupal_get_path('theme', $theme);
|
danielebarchiesi@0
|
141 $file = DRUPAL_ROOT . '/' . $path . '/color/color.inc';
|
danielebarchiesi@0
|
142 if ($path && file_exists($file)) {
|
danielebarchiesi@0
|
143 include $file;
|
danielebarchiesi@0
|
144 $theme_info[$theme] = $info;
|
danielebarchiesi@0
|
145 return $info;
|
danielebarchiesi@0
|
146 }
|
danielebarchiesi@0
|
147 }
|
danielebarchiesi@0
|
148
|
danielebarchiesi@0
|
149 /**
|
danielebarchiesi@0
|
150 * Retrieves the color palette for a particular theme.
|
danielebarchiesi@0
|
151 */
|
danielebarchiesi@0
|
152 function color_get_palette($theme, $default = FALSE) {
|
danielebarchiesi@0
|
153 // Fetch and expand default palette.
|
danielebarchiesi@0
|
154 $info = color_get_info($theme);
|
danielebarchiesi@0
|
155 $palette = $info['schemes']['default']['colors'];
|
danielebarchiesi@0
|
156
|
danielebarchiesi@0
|
157 // Load variable.
|
danielebarchiesi@0
|
158 return $default ? $palette : variable_get('color_' . $theme . '_palette', $palette);
|
danielebarchiesi@0
|
159 }
|
danielebarchiesi@0
|
160
|
danielebarchiesi@0
|
161 /**
|
danielebarchiesi@0
|
162 * Form constructor for the color configuration form for a particular theme.
|
danielebarchiesi@0
|
163 *
|
danielebarchiesi@0
|
164 * @param $theme
|
danielebarchiesi@0
|
165 * The machine name of the theme whose color settings are being configured.
|
danielebarchiesi@0
|
166 *
|
danielebarchiesi@0
|
167 * @see color_scheme_form_validate()
|
danielebarchiesi@0
|
168 * @see color_scheme_form_submit()
|
danielebarchiesi@0
|
169 * @ingroup forms
|
danielebarchiesi@0
|
170 */
|
danielebarchiesi@0
|
171 function color_scheme_form($complete_form, &$form_state, $theme) {
|
danielebarchiesi@0
|
172 $base = drupal_get_path('module', 'color');
|
danielebarchiesi@0
|
173 $info = color_get_info($theme);
|
danielebarchiesi@0
|
174
|
danielebarchiesi@0
|
175 $info['schemes'][''] = array('title' => t('Custom'), 'colors' => array());
|
danielebarchiesi@0
|
176 $color_sets = array();
|
danielebarchiesi@0
|
177 $schemes = array();
|
danielebarchiesi@0
|
178 foreach ($info['schemes'] as $key => $scheme) {
|
danielebarchiesi@0
|
179 $color_sets[$key] = $scheme['title'];
|
danielebarchiesi@0
|
180 $schemes[$key] = $scheme['colors'];
|
danielebarchiesi@0
|
181 $schemes[$key] += $info['schemes']['default']['colors'];
|
danielebarchiesi@0
|
182 }
|
danielebarchiesi@0
|
183
|
danielebarchiesi@0
|
184 // See if we're using a predefined scheme.
|
danielebarchiesi@0
|
185 // Note: we use the original theme when the default scheme is chosen.
|
danielebarchiesi@0
|
186 $current_scheme = variable_get('color_' . $theme . '_palette', array());
|
danielebarchiesi@0
|
187 foreach ($schemes as $key => $scheme) {
|
danielebarchiesi@0
|
188 if ($current_scheme == $scheme) {
|
danielebarchiesi@0
|
189 $scheme_name = $key;
|
danielebarchiesi@0
|
190 break;
|
danielebarchiesi@0
|
191 }
|
danielebarchiesi@0
|
192 }
|
danielebarchiesi@0
|
193 if (empty($scheme_name)) {
|
danielebarchiesi@0
|
194 if (empty($current_scheme)) {
|
danielebarchiesi@0
|
195 $scheme_name = 'default';
|
danielebarchiesi@0
|
196 }
|
danielebarchiesi@0
|
197 else {
|
danielebarchiesi@0
|
198 $scheme_name = '';
|
danielebarchiesi@0
|
199 }
|
danielebarchiesi@0
|
200 }
|
danielebarchiesi@0
|
201
|
danielebarchiesi@0
|
202 // Add scheme selector.
|
danielebarchiesi@0
|
203 $form['scheme'] = array(
|
danielebarchiesi@0
|
204 '#type' => 'select',
|
danielebarchiesi@0
|
205 '#title' => t('Color set'),
|
danielebarchiesi@0
|
206 '#options' => $color_sets,
|
danielebarchiesi@0
|
207 '#default_value' => $scheme_name,
|
danielebarchiesi@0
|
208 '#attached' => array(
|
danielebarchiesi@0
|
209 // Add Farbtastic color picker.
|
danielebarchiesi@0
|
210 'library' => array(
|
danielebarchiesi@0
|
211 array('system', 'farbtastic'),
|
danielebarchiesi@0
|
212 ),
|
danielebarchiesi@0
|
213 // Add custom CSS.
|
danielebarchiesi@0
|
214 'css' => array(
|
danielebarchiesi@0
|
215 $base . '/color.css' => array(),
|
danielebarchiesi@0
|
216 ),
|
danielebarchiesi@0
|
217 // Add custom JavaScript.
|
danielebarchiesi@0
|
218 'js' => array(
|
danielebarchiesi@0
|
219 $base . '/color.js',
|
danielebarchiesi@0
|
220 array(
|
danielebarchiesi@0
|
221 'data' => array(
|
danielebarchiesi@0
|
222 'color' => array(
|
danielebarchiesi@0
|
223 'reference' => color_get_palette($theme, TRUE),
|
danielebarchiesi@0
|
224 'schemes' => $schemes,
|
danielebarchiesi@0
|
225 ),
|
danielebarchiesi@0
|
226 'gradients' => $info['gradients'],
|
danielebarchiesi@0
|
227 ),
|
danielebarchiesi@0
|
228 'type' => 'setting',
|
danielebarchiesi@0
|
229 ),
|
danielebarchiesi@0
|
230 ),
|
danielebarchiesi@0
|
231 ),
|
danielebarchiesi@0
|
232 );
|
danielebarchiesi@0
|
233
|
danielebarchiesi@0
|
234 // Add palette fields.
|
danielebarchiesi@0
|
235 $palette = color_get_palette($theme);
|
danielebarchiesi@0
|
236 $names = $info['fields'];
|
danielebarchiesi@0
|
237 $form['palette']['#tree'] = TRUE;
|
danielebarchiesi@0
|
238 foreach ($palette as $name => $value) {
|
danielebarchiesi@0
|
239 if (isset($names[$name])) {
|
danielebarchiesi@0
|
240 $form['palette'][$name] = array(
|
danielebarchiesi@0
|
241 '#type' => 'textfield',
|
danielebarchiesi@0
|
242 '#title' => check_plain($names[$name]),
|
danielebarchiesi@0
|
243 '#default_value' => $value,
|
danielebarchiesi@0
|
244 '#size' => 8,
|
danielebarchiesi@0
|
245 );
|
danielebarchiesi@0
|
246 }
|
danielebarchiesi@0
|
247 }
|
danielebarchiesi@0
|
248 $form['theme'] = array('#type' => 'value', '#value' => $theme);
|
danielebarchiesi@0
|
249 $form['info'] = array('#type' => 'value', '#value' => $info);
|
danielebarchiesi@0
|
250
|
danielebarchiesi@0
|
251 return $form;
|
danielebarchiesi@0
|
252 }
|
danielebarchiesi@0
|
253
|
danielebarchiesi@0
|
254 /**
|
danielebarchiesi@0
|
255 * Returns HTML for a theme's color form.
|
danielebarchiesi@0
|
256 *
|
danielebarchiesi@0
|
257 * @param $variables
|
danielebarchiesi@0
|
258 * An associative array containing:
|
danielebarchiesi@0
|
259 * - form: A render element representing the form.
|
danielebarchiesi@0
|
260 *
|
danielebarchiesi@0
|
261 * @ingroup themeable
|
danielebarchiesi@0
|
262 */
|
danielebarchiesi@0
|
263 function theme_color_scheme_form($variables) {
|
danielebarchiesi@0
|
264 $form = $variables['form'];
|
danielebarchiesi@0
|
265
|
danielebarchiesi@0
|
266 $theme = $form['theme']['#value'];
|
danielebarchiesi@0
|
267 $info = $form['info']['#value'];
|
danielebarchiesi@0
|
268 $path = drupal_get_path('theme', $theme) . '/';
|
danielebarchiesi@0
|
269 drupal_add_css($path . $info['preview_css']);
|
danielebarchiesi@0
|
270
|
danielebarchiesi@0
|
271 $preview_js_path = isset($info['preview_js']) ? $path . $info['preview_js'] : drupal_get_path('module', 'color') . '/' . 'preview.js';
|
danielebarchiesi@0
|
272 // Add the JS at a weight below color.js.
|
danielebarchiesi@0
|
273 drupal_add_js($preview_js_path, array('weight' => -1));
|
danielebarchiesi@0
|
274
|
danielebarchiesi@0
|
275 $output = '';
|
danielebarchiesi@0
|
276 $output .= '<div class="color-form clearfix">';
|
danielebarchiesi@0
|
277 // Color schemes
|
danielebarchiesi@0
|
278 $output .= drupal_render($form['scheme']);
|
danielebarchiesi@0
|
279 // Palette
|
danielebarchiesi@0
|
280 $output .= '<div id="palette" class="clearfix">';
|
danielebarchiesi@0
|
281 foreach (element_children($form['palette']) as $name) {
|
danielebarchiesi@0
|
282 $output .= drupal_render($form['palette'][$name]);
|
danielebarchiesi@0
|
283 }
|
danielebarchiesi@0
|
284 $output .= '</div>';
|
danielebarchiesi@0
|
285 // Preview
|
danielebarchiesi@0
|
286 $output .= drupal_render_children($form);
|
danielebarchiesi@0
|
287 $output .= '<h2>' . t('Preview') . '</h2>';
|
danielebarchiesi@0
|
288 // Attempt to load preview HTML if the theme provides it.
|
danielebarchiesi@0
|
289 $preview_html_path = DRUPAL_ROOT . '/' . (isset($info['preview_html']) ? drupal_get_path('theme', $theme) . '/' . $info['preview_html'] : drupal_get_path('module', 'color') . '/preview.html');
|
danielebarchiesi@0
|
290 $output .= file_get_contents($preview_html_path);
|
danielebarchiesi@0
|
291 // Close the wrapper div.
|
danielebarchiesi@0
|
292 $output .= '</div>';
|
danielebarchiesi@0
|
293
|
danielebarchiesi@0
|
294 return $output;
|
danielebarchiesi@0
|
295 }
|
danielebarchiesi@0
|
296
|
danielebarchiesi@0
|
297 /**
|
danielebarchiesi@0
|
298 * Form validation handler for color_scheme_form().
|
danielebarchiesi@0
|
299 *
|
danielebarchiesi@0
|
300 * @see color_scheme_form_submit()
|
danielebarchiesi@0
|
301 */
|
danielebarchiesi@0
|
302 function color_scheme_form_validate($form, &$form_state) {
|
danielebarchiesi@0
|
303 // Only accept hexadecimal CSS color strings to avoid XSS upon use.
|
danielebarchiesi@0
|
304 foreach ($form_state['values']['palette'] as $key => $color) {
|
danielebarchiesi@0
|
305 if (!preg_match('/^#([a-f0-9]{3}){1,2}$/iD', $color)) {
|
danielebarchiesi@0
|
306 form_set_error('palette][' . $key, t('%name must be a valid hexadecimal CSS color value.', array('%name' => $form['color']['palette'][$key]['#title'])));
|
danielebarchiesi@0
|
307 }
|
danielebarchiesi@0
|
308 }
|
danielebarchiesi@0
|
309 }
|
danielebarchiesi@0
|
310
|
danielebarchiesi@0
|
311 /**
|
danielebarchiesi@0
|
312 * Form submission handler for color_scheme_form().
|
danielebarchiesi@0
|
313 *
|
danielebarchiesi@0
|
314 * @see color_scheme_form_validate()
|
danielebarchiesi@0
|
315 */
|
danielebarchiesi@0
|
316 function color_scheme_form_submit($form, &$form_state) {
|
danielebarchiesi@0
|
317 // Get theme coloring info.
|
danielebarchiesi@0
|
318 if (!isset($form_state['values']['info'])) {
|
danielebarchiesi@0
|
319 return;
|
danielebarchiesi@0
|
320 }
|
danielebarchiesi@0
|
321 $theme = $form_state['values']['theme'];
|
danielebarchiesi@0
|
322 $info = $form_state['values']['info'];
|
danielebarchiesi@0
|
323
|
danielebarchiesi@0
|
324 // Resolve palette.
|
danielebarchiesi@0
|
325 $palette = $form_state['values']['palette'];
|
danielebarchiesi@0
|
326 if ($form_state['values']['scheme'] != '') {
|
danielebarchiesi@0
|
327 foreach ($palette as $key => $color) {
|
danielebarchiesi@0
|
328 if (isset($info['schemes'][$form_state['values']['scheme']]['colors'][$key])) {
|
danielebarchiesi@0
|
329 $palette[$key] = $info['schemes'][$form_state['values']['scheme']]['colors'][$key];
|
danielebarchiesi@0
|
330 }
|
danielebarchiesi@0
|
331 }
|
danielebarchiesi@0
|
332 $palette += $info['schemes']['default']['colors'];
|
danielebarchiesi@0
|
333 }
|
danielebarchiesi@0
|
334
|
danielebarchiesi@0
|
335 // Make sure enough memory is available, if PHP's memory limit is compiled in.
|
danielebarchiesi@0
|
336 if (function_exists('memory_get_usage')) {
|
danielebarchiesi@0
|
337 // Fetch source image dimensions.
|
danielebarchiesi@0
|
338 $source = drupal_get_path('theme', $theme) . '/' . $info['base_image'];
|
danielebarchiesi@0
|
339 list($width, $height) = getimagesize($source);
|
danielebarchiesi@0
|
340
|
danielebarchiesi@0
|
341 // We need at least a copy of the source and a target buffer of the same
|
danielebarchiesi@0
|
342 // size (both at 32bpp).
|
danielebarchiesi@0
|
343 $required = $width * $height * 8;
|
danielebarchiesi@0
|
344 // We intend to prevent color scheme changes if there isn't enough memory
|
danielebarchiesi@0
|
345 // available. memory_get_usage(TRUE) returns a more accurate number than
|
danielebarchiesi@0
|
346 // memory_get_usage(), therefore we won't inadvertently reject a color
|
danielebarchiesi@0
|
347 // scheme change based on a faulty memory calculation.
|
danielebarchiesi@0
|
348 $usage = memory_get_usage(TRUE);
|
danielebarchiesi@0
|
349 $memory_limit = ini_get('memory_limit');
|
danielebarchiesi@0
|
350 $size = parse_size($memory_limit);
|
danielebarchiesi@0
|
351 if (!drupal_check_memory_limit($usage + $required, $memory_limit)) {
|
danielebarchiesi@0
|
352 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 - $size), '@url' => 'http://www.php.net/manual/ini.core.php#ini.sect.resource-limits')), 'error');
|
danielebarchiesi@0
|
353 return;
|
danielebarchiesi@0
|
354 }
|
danielebarchiesi@0
|
355 }
|
danielebarchiesi@0
|
356
|
danielebarchiesi@0
|
357 // Delete old files.
|
danielebarchiesi@0
|
358 foreach (variable_get('color_' . $theme . '_files', array()) as $file) {
|
danielebarchiesi@0
|
359 @drupal_unlink($file);
|
danielebarchiesi@0
|
360 }
|
danielebarchiesi@0
|
361 if (isset($file) && $file = dirname($file)) {
|
danielebarchiesi@0
|
362 @drupal_rmdir($file);
|
danielebarchiesi@0
|
363 }
|
danielebarchiesi@0
|
364
|
danielebarchiesi@0
|
365 // Don't render the default colorscheme, use the standard theme instead.
|
danielebarchiesi@0
|
366 if (implode(',', color_get_palette($theme, TRUE)) == implode(',', $palette)) {
|
danielebarchiesi@0
|
367 variable_del('color_' . $theme . '_palette');
|
danielebarchiesi@0
|
368 variable_del('color_' . $theme . '_stylesheets');
|
danielebarchiesi@0
|
369 variable_del('color_' . $theme . '_logo');
|
danielebarchiesi@0
|
370 variable_del('color_' . $theme . '_files');
|
danielebarchiesi@0
|
371 variable_del('color_' . $theme . '_screenshot');
|
danielebarchiesi@0
|
372 return;
|
danielebarchiesi@0
|
373 }
|
danielebarchiesi@0
|
374
|
danielebarchiesi@0
|
375 // Prepare target locations for generated files.
|
danielebarchiesi@0
|
376 $id = $theme . '-' . substr(hash('sha256', serialize($palette) . microtime()), 0, 8);
|
danielebarchiesi@0
|
377 $paths['color'] = 'public://color';
|
danielebarchiesi@0
|
378 $paths['target'] = $paths['color'] . '/' . $id;
|
danielebarchiesi@0
|
379 foreach ($paths as $path) {
|
danielebarchiesi@0
|
380 file_prepare_directory($path, FILE_CREATE_DIRECTORY);
|
danielebarchiesi@0
|
381 }
|
danielebarchiesi@0
|
382 $paths['target'] = $paths['target'] . '/';
|
danielebarchiesi@0
|
383 $paths['id'] = $id;
|
danielebarchiesi@0
|
384 $paths['source'] = drupal_get_path('theme', $theme) . '/';
|
danielebarchiesi@0
|
385 $paths['files'] = $paths['map'] = array();
|
danielebarchiesi@0
|
386
|
danielebarchiesi@0
|
387 // Save palette and logo location.
|
danielebarchiesi@0
|
388 variable_set('color_' . $theme . '_palette', $palette);
|
danielebarchiesi@0
|
389 variable_set('color_' . $theme . '_logo', $paths['target'] . 'logo.png');
|
danielebarchiesi@0
|
390
|
danielebarchiesi@0
|
391 // Copy over neutral images.
|
danielebarchiesi@0
|
392 foreach ($info['copy'] as $file) {
|
danielebarchiesi@0
|
393 $base = drupal_basename($file);
|
danielebarchiesi@0
|
394 $source = $paths['source'] . $file;
|
danielebarchiesi@0
|
395 $filepath = file_unmanaged_copy($source, $paths['target'] . $base);
|
danielebarchiesi@0
|
396 $paths['map'][$file] = $base;
|
danielebarchiesi@0
|
397 $paths['files'][] = $filepath;
|
danielebarchiesi@0
|
398 }
|
danielebarchiesi@0
|
399
|
danielebarchiesi@0
|
400 // Render new images, if image has been provided.
|
danielebarchiesi@0
|
401 if ($info['base_image']) {
|
danielebarchiesi@0
|
402 _color_render_images($theme, $info, $paths, $palette);
|
danielebarchiesi@0
|
403 }
|
danielebarchiesi@0
|
404
|
danielebarchiesi@0
|
405 // Rewrite theme stylesheets.
|
danielebarchiesi@0
|
406 $css = array();
|
danielebarchiesi@0
|
407 foreach ($info['css'] as $stylesheet) {
|
danielebarchiesi@0
|
408 // Build a temporary array with LTR and RTL files.
|
danielebarchiesi@0
|
409 $files = array();
|
danielebarchiesi@0
|
410 if (file_exists($paths['source'] . $stylesheet)) {
|
danielebarchiesi@0
|
411 $files[] = $stylesheet;
|
danielebarchiesi@0
|
412
|
danielebarchiesi@0
|
413 $rtl_file = str_replace('.css', '-rtl.css', $stylesheet);
|
danielebarchiesi@0
|
414 if (file_exists($paths['source'] . $rtl_file)) {
|
danielebarchiesi@0
|
415 $files[] = $rtl_file;
|
danielebarchiesi@0
|
416 }
|
danielebarchiesi@0
|
417 }
|
danielebarchiesi@0
|
418
|
danielebarchiesi@0
|
419 foreach ($files as $file) {
|
danielebarchiesi@0
|
420 // Aggregate @imports recursively for each configured top level CSS file
|
danielebarchiesi@0
|
421 // without optimization. Aggregation and optimization will be
|
danielebarchiesi@0
|
422 // handled by drupal_build_css_cache() only.
|
danielebarchiesi@0
|
423 $style = drupal_load_stylesheet($paths['source'] . $file, FALSE);
|
danielebarchiesi@0
|
424
|
danielebarchiesi@0
|
425 // Return the path to where this CSS file originated from, stripping
|
danielebarchiesi@0
|
426 // off the name of the file at the end of the path.
|
danielebarchiesi@0
|
427 $base = base_path() . dirname($paths['source'] . $file) . '/';
|
danielebarchiesi@0
|
428 _drupal_build_css_path(NULL, $base);
|
danielebarchiesi@0
|
429
|
danielebarchiesi@0
|
430 // Prefix all paths within this CSS file, ignoring absolute paths.
|
danielebarchiesi@0
|
431 $style = preg_replace_callback('/url\([\'"]?(?![a-z]+:|\/+)([^\'")]+)[\'"]?\)/i', '_drupal_build_css_path', $style);
|
danielebarchiesi@0
|
432
|
danielebarchiesi@0
|
433 // Rewrite stylesheet with new colors.
|
danielebarchiesi@0
|
434 $style = _color_rewrite_stylesheet($theme, $info, $paths, $palette, $style);
|
danielebarchiesi@0
|
435 $base_file = drupal_basename($file);
|
danielebarchiesi@0
|
436 $css[] = $paths['target'] . $base_file;
|
danielebarchiesi@0
|
437 _color_save_stylesheet($paths['target'] . $base_file, $style, $paths);
|
danielebarchiesi@0
|
438 }
|
danielebarchiesi@0
|
439 }
|
danielebarchiesi@0
|
440
|
danielebarchiesi@0
|
441 // Maintain list of files.
|
danielebarchiesi@0
|
442 variable_set('color_' . $theme . '_stylesheets', $css);
|
danielebarchiesi@0
|
443 variable_set('color_' . $theme . '_files', $paths['files']);
|
danielebarchiesi@0
|
444 }
|
danielebarchiesi@0
|
445
|
danielebarchiesi@0
|
446 /**
|
danielebarchiesi@0
|
447 * Rewrites the stylesheet to match the colors in the palette.
|
danielebarchiesi@0
|
448 */
|
danielebarchiesi@0
|
449 function _color_rewrite_stylesheet($theme, &$info, &$paths, $palette, $style) {
|
danielebarchiesi@0
|
450 $themes = list_themes();
|
danielebarchiesi@0
|
451 // Prepare color conversion table.
|
danielebarchiesi@0
|
452 $conversion = $palette;
|
danielebarchiesi@0
|
453 foreach ($conversion as $k => $v) {
|
danielebarchiesi@0
|
454 $conversion[$k] = drupal_strtolower($v);
|
danielebarchiesi@0
|
455 }
|
danielebarchiesi@0
|
456 $default = color_get_palette($theme, TRUE);
|
danielebarchiesi@0
|
457
|
danielebarchiesi@0
|
458 // Split off the "Don't touch" section of the stylesheet.
|
danielebarchiesi@0
|
459 $split = "Color Module: Don't touch";
|
danielebarchiesi@0
|
460 if (strpos($style, $split) !== FALSE) {
|
danielebarchiesi@0
|
461 list($style, $fixed) = explode($split, $style);
|
danielebarchiesi@0
|
462 }
|
danielebarchiesi@0
|
463
|
danielebarchiesi@0
|
464 // Find all colors in the stylesheet and the chunks in between.
|
danielebarchiesi@0
|
465 $style = preg_split('/(#[0-9a-f]{6}|#[0-9a-f]{3})/i', $style, -1, PREG_SPLIT_DELIM_CAPTURE);
|
danielebarchiesi@0
|
466 $is_color = FALSE;
|
danielebarchiesi@0
|
467 $output = '';
|
danielebarchiesi@0
|
468 $base = 'base';
|
danielebarchiesi@0
|
469
|
danielebarchiesi@0
|
470 // Iterate over all the parts.
|
danielebarchiesi@0
|
471 foreach ($style as $chunk) {
|
danielebarchiesi@0
|
472 if ($is_color) {
|
danielebarchiesi@0
|
473 $chunk = drupal_strtolower($chunk);
|
danielebarchiesi@0
|
474 // Check if this is one of the colors in the default palette.
|
danielebarchiesi@0
|
475 if ($key = array_search($chunk, $default)) {
|
danielebarchiesi@0
|
476 $chunk = $conversion[$key];
|
danielebarchiesi@0
|
477 }
|
danielebarchiesi@0
|
478 // Not a pre-set color. Extrapolate from the base.
|
danielebarchiesi@0
|
479 else {
|
danielebarchiesi@0
|
480 $chunk = _color_shift($palette[$base], $default[$base], $chunk, $info['blend_target']);
|
danielebarchiesi@0
|
481 }
|
danielebarchiesi@0
|
482 }
|
danielebarchiesi@0
|
483 else {
|
danielebarchiesi@0
|
484 // Determine the most suitable base color for the next color.
|
danielebarchiesi@0
|
485
|
danielebarchiesi@0
|
486 // 'a' declarations. Use link.
|
danielebarchiesi@0
|
487 if (preg_match('@[^a-z0-9_-](a)[^a-z0-9_-][^/{]*{[^{]+$@i', $chunk)) {
|
danielebarchiesi@0
|
488 $base = 'link';
|
danielebarchiesi@0
|
489 }
|
danielebarchiesi@0
|
490 // 'color:' styles. Use text.
|
danielebarchiesi@0
|
491 elseif (preg_match('/(?<!-)color[^{:]*:[^{#]*$/i', $chunk)) {
|
danielebarchiesi@0
|
492 $base = 'text';
|
danielebarchiesi@0
|
493 }
|
danielebarchiesi@0
|
494 // Reset back to base.
|
danielebarchiesi@0
|
495 else {
|
danielebarchiesi@0
|
496 $base = 'base';
|
danielebarchiesi@0
|
497 }
|
danielebarchiesi@0
|
498 }
|
danielebarchiesi@0
|
499 $output .= $chunk;
|
danielebarchiesi@0
|
500 $is_color = !$is_color;
|
danielebarchiesi@0
|
501 }
|
danielebarchiesi@0
|
502 // Append fixed colors segment.
|
danielebarchiesi@0
|
503 if (isset($fixed)) {
|
danielebarchiesi@0
|
504 $output .= $fixed;
|
danielebarchiesi@0
|
505 }
|
danielebarchiesi@0
|
506
|
danielebarchiesi@0
|
507 // Replace paths to images.
|
danielebarchiesi@0
|
508 foreach ($paths['map'] as $before => $after) {
|
danielebarchiesi@0
|
509 $before = base_path() . $paths['source'] . $before;
|
danielebarchiesi@0
|
510 $before = preg_replace('`(^|/)(?!../)([^/]+)/../`', '$1', $before);
|
danielebarchiesi@0
|
511 $output = str_replace($before, $after, $output);
|
danielebarchiesi@0
|
512 }
|
danielebarchiesi@0
|
513
|
danielebarchiesi@0
|
514 return $output;
|
danielebarchiesi@0
|
515 }
|
danielebarchiesi@0
|
516
|
danielebarchiesi@0
|
517 /**
|
danielebarchiesi@0
|
518 * Saves the rewritten stylesheet to disk.
|
danielebarchiesi@0
|
519 */
|
danielebarchiesi@0
|
520 function _color_save_stylesheet($file, $style, &$paths) {
|
danielebarchiesi@0
|
521 $filepath = file_unmanaged_save_data($style, $file, FILE_EXISTS_REPLACE);
|
danielebarchiesi@0
|
522 $paths['files'][] = $filepath;
|
danielebarchiesi@0
|
523
|
danielebarchiesi@0
|
524 // Set standard file permissions for webserver-generated files.
|
danielebarchiesi@0
|
525 drupal_chmod($file);
|
danielebarchiesi@0
|
526 }
|
danielebarchiesi@0
|
527
|
danielebarchiesi@0
|
528 /**
|
danielebarchiesi@0
|
529 * Renders images that match a given palette.
|
danielebarchiesi@0
|
530 */
|
danielebarchiesi@0
|
531 function _color_render_images($theme, &$info, &$paths, $palette) {
|
danielebarchiesi@0
|
532 // Prepare template image.
|
danielebarchiesi@0
|
533 $source = $paths['source'] . '/' . $info['base_image'];
|
danielebarchiesi@0
|
534 $source = imagecreatefrompng($source);
|
danielebarchiesi@0
|
535 $width = imagesx($source);
|
danielebarchiesi@0
|
536 $height = imagesy($source);
|
danielebarchiesi@0
|
537
|
danielebarchiesi@0
|
538 // Prepare target buffer.
|
danielebarchiesi@0
|
539 $target = imagecreatetruecolor($width, $height);
|
danielebarchiesi@0
|
540 imagealphablending($target, TRUE);
|
danielebarchiesi@0
|
541
|
danielebarchiesi@0
|
542 // Fill regions of solid color.
|
danielebarchiesi@0
|
543 foreach ($info['fill'] as $color => $fill) {
|
danielebarchiesi@0
|
544 imagefilledrectangle($target, $fill[0], $fill[1], $fill[0] + $fill[2], $fill[1] + $fill[3], _color_gd($target, $palette[$color]));
|
danielebarchiesi@0
|
545 }
|
danielebarchiesi@0
|
546
|
danielebarchiesi@0
|
547 // Render gradients.
|
danielebarchiesi@0
|
548 foreach ($info['gradients'] as $gradient) {
|
danielebarchiesi@0
|
549 // Get direction of the gradient.
|
danielebarchiesi@0
|
550 if (isset($gradient['direction']) && $gradient['direction'] == 'horizontal') {
|
danielebarchiesi@0
|
551 // Horizontal gradient.
|
danielebarchiesi@0
|
552 for ($x = 0; $x < $gradient['dimension'][2]; $x++) {
|
danielebarchiesi@0
|
553 $color = _color_blend($target, $palette[$gradient['colors'][0]], $palette[$gradient['colors'][1]], $x / ($gradient['dimension'][2] - 1));
|
danielebarchiesi@0
|
554 imagefilledrectangle($target, ($gradient['dimension'][0] + $x), $gradient['dimension'][1], ($gradient['dimension'][0] + $x + 1), ($gradient['dimension'][1] + $gradient['dimension'][3]), $color);
|
danielebarchiesi@0
|
555 }
|
danielebarchiesi@0
|
556 }
|
danielebarchiesi@0
|
557 else {
|
danielebarchiesi@0
|
558 // Vertical gradient.
|
danielebarchiesi@0
|
559 for ($y = 0; $y < $gradient['dimension'][3]; $y++) {
|
danielebarchiesi@0
|
560 $color = _color_blend($target, $palette[$gradient['colors'][0]], $palette[$gradient['colors'][1]], $y / ($gradient['dimension'][3] - 1));
|
danielebarchiesi@0
|
561 imagefilledrectangle($target, $gradient['dimension'][0], $gradient['dimension'][1] + $y, $gradient['dimension'][0] + $gradient['dimension'][2], $gradient['dimension'][1] + $y + 1, $color);
|
danielebarchiesi@0
|
562 }
|
danielebarchiesi@0
|
563 }
|
danielebarchiesi@0
|
564 }
|
danielebarchiesi@0
|
565
|
danielebarchiesi@0
|
566 // Blend over template.
|
danielebarchiesi@0
|
567 imagecopy($target, $source, 0, 0, 0, 0, $width, $height);
|
danielebarchiesi@0
|
568
|
danielebarchiesi@0
|
569 // Clean up template image.
|
danielebarchiesi@0
|
570 imagedestroy($source);
|
danielebarchiesi@0
|
571
|
danielebarchiesi@0
|
572 // Cut out slices.
|
danielebarchiesi@0
|
573 foreach ($info['slices'] as $file => $coord) {
|
danielebarchiesi@0
|
574 list($x, $y, $width, $height) = $coord;
|
danielebarchiesi@0
|
575 $base = drupal_basename($file);
|
danielebarchiesi@0
|
576 $image = drupal_realpath($paths['target'] . $base);
|
danielebarchiesi@0
|
577
|
danielebarchiesi@0
|
578 // Cut out slice.
|
danielebarchiesi@0
|
579 if ($file == 'screenshot.png') {
|
danielebarchiesi@0
|
580 $slice = imagecreatetruecolor(150, 90);
|
danielebarchiesi@0
|
581 imagecopyresampled($slice, $target, 0, 0, $x, $y, 150, 90, $width, $height);
|
danielebarchiesi@0
|
582 variable_set('color_' . $theme . '_screenshot', $image);
|
danielebarchiesi@0
|
583 }
|
danielebarchiesi@0
|
584 else {
|
danielebarchiesi@0
|
585 $slice = imagecreatetruecolor($width, $height);
|
danielebarchiesi@0
|
586 imagecopy($slice, $target, 0, 0, $x, $y, $width, $height);
|
danielebarchiesi@0
|
587 }
|
danielebarchiesi@0
|
588
|
danielebarchiesi@0
|
589 // Save image.
|
danielebarchiesi@0
|
590 imagepng($slice, $image);
|
danielebarchiesi@0
|
591 imagedestroy($slice);
|
danielebarchiesi@0
|
592 $paths['files'][] = $image;
|
danielebarchiesi@0
|
593
|
danielebarchiesi@0
|
594 // Set standard file permissions for webserver-generated files
|
danielebarchiesi@0
|
595 drupal_chmod($image);
|
danielebarchiesi@0
|
596
|
danielebarchiesi@0
|
597 // Build before/after map of image paths.
|
danielebarchiesi@0
|
598 $paths['map'][$file] = $base;
|
danielebarchiesi@0
|
599 }
|
danielebarchiesi@0
|
600
|
danielebarchiesi@0
|
601 // Clean up target buffer.
|
danielebarchiesi@0
|
602 imagedestroy($target);
|
danielebarchiesi@0
|
603 }
|
danielebarchiesi@0
|
604
|
danielebarchiesi@0
|
605 /**
|
danielebarchiesi@0
|
606 * Shifts a given color, using a reference pair and a target blend color.
|
danielebarchiesi@0
|
607 *
|
danielebarchiesi@0
|
608 * Note: this function is significantly different from the JS version, as it
|
danielebarchiesi@0
|
609 * is written to match the blended images perfectly.
|
danielebarchiesi@0
|
610 *
|
danielebarchiesi@0
|
611 * Constraint: if (ref2 == target + (ref1 - target) * delta) for some fraction
|
danielebarchiesi@0
|
612 * delta then (return == target + (given - target) * delta).
|
danielebarchiesi@0
|
613 *
|
danielebarchiesi@0
|
614 * Loose constraint: Preserve relative positions in saturation and luminance
|
danielebarchiesi@0
|
615 * space.
|
danielebarchiesi@0
|
616 */
|
danielebarchiesi@0
|
617 function _color_shift($given, $ref1, $ref2, $target) {
|
danielebarchiesi@0
|
618 // We assume that ref2 is a blend of ref1 and target and find
|
danielebarchiesi@0
|
619 // delta based on the length of the difference vectors.
|
danielebarchiesi@0
|
620
|
danielebarchiesi@0
|
621 // delta = 1 - |ref2 - ref1| / |white - ref1|
|
danielebarchiesi@0
|
622 $target = _color_unpack($target, TRUE);
|
danielebarchiesi@0
|
623 $ref1 = _color_unpack($ref1, TRUE);
|
danielebarchiesi@0
|
624 $ref2 = _color_unpack($ref2, TRUE);
|
danielebarchiesi@0
|
625 $numerator = 0;
|
danielebarchiesi@0
|
626 $denominator = 0;
|
danielebarchiesi@0
|
627 for ($i = 0; $i < 3; ++$i) {
|
danielebarchiesi@0
|
628 $numerator += ($ref2[$i] - $ref1[$i]) * ($ref2[$i] - $ref1[$i]);
|
danielebarchiesi@0
|
629 $denominator += ($target[$i] - $ref1[$i]) * ($target[$i] - $ref1[$i]);
|
danielebarchiesi@0
|
630 }
|
danielebarchiesi@0
|
631 $delta = ($denominator > 0) ? (1 - sqrt($numerator / $denominator)) : 0;
|
danielebarchiesi@0
|
632
|
danielebarchiesi@0
|
633 // Calculate the color that ref2 would be if the assumption was true.
|
danielebarchiesi@0
|
634 for ($i = 0; $i < 3; ++$i) {
|
danielebarchiesi@0
|
635 $ref3[$i] = $target[$i] + ($ref1[$i] - $target[$i]) * $delta;
|
danielebarchiesi@0
|
636 }
|
danielebarchiesi@0
|
637
|
danielebarchiesi@0
|
638 // If the assumption is not true, there is a difference between ref2 and ref3.
|
danielebarchiesi@0
|
639 // We measure this in HSL space. Notation: x' = hsl(x).
|
danielebarchiesi@0
|
640 $ref2 = _color_rgb2hsl($ref2);
|
danielebarchiesi@0
|
641 $ref3 = _color_rgb2hsl($ref3);
|
danielebarchiesi@0
|
642 for ($i = 0; $i < 3; ++$i) {
|
danielebarchiesi@0
|
643 $shift[$i] = $ref2[$i] - $ref3[$i];
|
danielebarchiesi@0
|
644 }
|
danielebarchiesi@0
|
645
|
danielebarchiesi@0
|
646 // Take the given color, and blend it towards the target.
|
danielebarchiesi@0
|
647 $given = _color_unpack($given, TRUE);
|
danielebarchiesi@0
|
648 for ($i = 0; $i < 3; ++$i) {
|
danielebarchiesi@0
|
649 $result[$i] = $target[$i] + ($given[$i] - $target[$i]) * $delta;
|
danielebarchiesi@0
|
650 }
|
danielebarchiesi@0
|
651
|
danielebarchiesi@0
|
652 // Finally, we apply the extra shift in HSL space.
|
danielebarchiesi@0
|
653 // Note: if ref2 is a pure blend of ref1 and target, then |shift| = 0.
|
danielebarchiesi@0
|
654 $result = _color_rgb2hsl($result);
|
danielebarchiesi@0
|
655 for ($i = 0; $i < 3; ++$i) {
|
danielebarchiesi@0
|
656 $result[$i] = min(1, max(0, $result[$i] + $shift[$i]));
|
danielebarchiesi@0
|
657 }
|
danielebarchiesi@0
|
658 $result = _color_hsl2rgb($result);
|
danielebarchiesi@0
|
659
|
danielebarchiesi@0
|
660 // Return hex color.
|
danielebarchiesi@0
|
661 return _color_pack($result, TRUE);
|
danielebarchiesi@0
|
662 }
|
danielebarchiesi@0
|
663
|
danielebarchiesi@0
|
664 /**
|
danielebarchiesi@0
|
665 * Converts a hex triplet into a GD color.
|
danielebarchiesi@0
|
666 */
|
danielebarchiesi@0
|
667 function _color_gd($img, $hex) {
|
danielebarchiesi@0
|
668 $c = array_merge(array($img), _color_unpack($hex));
|
danielebarchiesi@0
|
669 return call_user_func_array('imagecolorallocate', $c);
|
danielebarchiesi@0
|
670 }
|
danielebarchiesi@0
|
671
|
danielebarchiesi@0
|
672 /**
|
danielebarchiesi@0
|
673 * Blends two hex colors and returns the GD color.
|
danielebarchiesi@0
|
674 */
|
danielebarchiesi@0
|
675 function _color_blend($img, $hex1, $hex2, $alpha) {
|
danielebarchiesi@0
|
676 $in1 = _color_unpack($hex1);
|
danielebarchiesi@0
|
677 $in2 = _color_unpack($hex2);
|
danielebarchiesi@0
|
678 $out = array($img);
|
danielebarchiesi@0
|
679 for ($i = 0; $i < 3; ++$i) {
|
danielebarchiesi@0
|
680 $out[] = $in1[$i] + ($in2[$i] - $in1[$i]) * $alpha;
|
danielebarchiesi@0
|
681 }
|
danielebarchiesi@0
|
682
|
danielebarchiesi@0
|
683 return call_user_func_array('imagecolorallocate', $out);
|
danielebarchiesi@0
|
684 }
|
danielebarchiesi@0
|
685
|
danielebarchiesi@0
|
686 /**
|
danielebarchiesi@0
|
687 * Converts a hex color into an RGB triplet.
|
danielebarchiesi@0
|
688 */
|
danielebarchiesi@0
|
689 function _color_unpack($hex, $normalize = FALSE) {
|
danielebarchiesi@0
|
690 if (strlen($hex) == 4) {
|
danielebarchiesi@0
|
691 $hex = $hex[1] . $hex[1] . $hex[2] . $hex[2] . $hex[3] . $hex[3];
|
danielebarchiesi@0
|
692 }
|
danielebarchiesi@0
|
693 $c = hexdec($hex);
|
danielebarchiesi@0
|
694 for ($i = 16; $i >= 0; $i -= 8) {
|
danielebarchiesi@0
|
695 $out[] = (($c >> $i) & 0xFF) / ($normalize ? 255 : 1);
|
danielebarchiesi@0
|
696 }
|
danielebarchiesi@0
|
697
|
danielebarchiesi@0
|
698 return $out;
|
danielebarchiesi@0
|
699 }
|
danielebarchiesi@0
|
700
|
danielebarchiesi@0
|
701 /**
|
danielebarchiesi@0
|
702 * Converts an RGB triplet to a hex color.
|
danielebarchiesi@0
|
703 */
|
danielebarchiesi@0
|
704 function _color_pack($rgb, $normalize = FALSE) {
|
danielebarchiesi@0
|
705 $out = 0;
|
danielebarchiesi@0
|
706 foreach ($rgb as $k => $v) {
|
danielebarchiesi@0
|
707 $out |= (($v * ($normalize ? 255 : 1)) << (16 - $k * 8));
|
danielebarchiesi@0
|
708 }
|
danielebarchiesi@0
|
709
|
danielebarchiesi@0
|
710 return '#' . str_pad(dechex($out), 6, 0, STR_PAD_LEFT);
|
danielebarchiesi@0
|
711 }
|
danielebarchiesi@0
|
712
|
danielebarchiesi@0
|
713 /**
|
danielebarchiesi@0
|
714 * Converts an HSL triplet into RGB.
|
danielebarchiesi@0
|
715 */
|
danielebarchiesi@0
|
716 function _color_hsl2rgb($hsl) {
|
danielebarchiesi@0
|
717 $h = $hsl[0];
|
danielebarchiesi@0
|
718 $s = $hsl[1];
|
danielebarchiesi@0
|
719 $l = $hsl[2];
|
danielebarchiesi@0
|
720 $m2 = ($l <= 0.5) ? $l * ($s + 1) : $l + $s - $l*$s;
|
danielebarchiesi@0
|
721 $m1 = $l * 2 - $m2;
|
danielebarchiesi@0
|
722
|
danielebarchiesi@0
|
723 return array(
|
danielebarchiesi@0
|
724 _color_hue2rgb($m1, $m2, $h + 0.33333),
|
danielebarchiesi@0
|
725 _color_hue2rgb($m1, $m2, $h),
|
danielebarchiesi@0
|
726 _color_hue2rgb($m1, $m2, $h - 0.33333),
|
danielebarchiesi@0
|
727 );
|
danielebarchiesi@0
|
728 }
|
danielebarchiesi@0
|
729
|
danielebarchiesi@0
|
730 /**
|
danielebarchiesi@0
|
731 * Helper function for _color_hsl2rgb().
|
danielebarchiesi@0
|
732 */
|
danielebarchiesi@0
|
733 function _color_hue2rgb($m1, $m2, $h) {
|
danielebarchiesi@0
|
734 $h = ($h < 0) ? $h + 1 : (($h > 1) ? $h - 1 : $h);
|
danielebarchiesi@0
|
735 if ($h * 6 < 1) return $m1 + ($m2 - $m1) * $h * 6;
|
danielebarchiesi@0
|
736 if ($h * 2 < 1) return $m2;
|
danielebarchiesi@0
|
737 if ($h * 3 < 2) return $m1 + ($m2 - $m1) * (0.66666 - $h) * 6;
|
danielebarchiesi@0
|
738
|
danielebarchiesi@0
|
739 return $m1;
|
danielebarchiesi@0
|
740 }
|
danielebarchiesi@0
|
741
|
danielebarchiesi@0
|
742 /**
|
danielebarchiesi@0
|
743 * Converts an RGB triplet to HSL.
|
danielebarchiesi@0
|
744 */
|
danielebarchiesi@0
|
745 function _color_rgb2hsl($rgb) {
|
danielebarchiesi@0
|
746 $r = $rgb[0];
|
danielebarchiesi@0
|
747 $g = $rgb[1];
|
danielebarchiesi@0
|
748 $b = $rgb[2];
|
danielebarchiesi@0
|
749 $min = min($r, min($g, $b));
|
danielebarchiesi@0
|
750 $max = max($r, max($g, $b));
|
danielebarchiesi@0
|
751 $delta = $max - $min;
|
danielebarchiesi@0
|
752 $l = ($min + $max) / 2;
|
danielebarchiesi@0
|
753 $s = 0;
|
danielebarchiesi@0
|
754
|
danielebarchiesi@0
|
755 if ($l > 0 && $l < 1) {
|
danielebarchiesi@0
|
756 $s = $delta / ($l < 0.5 ? (2 * $l) : (2 - 2 * $l));
|
danielebarchiesi@0
|
757 }
|
danielebarchiesi@0
|
758
|
danielebarchiesi@0
|
759 $h = 0;
|
danielebarchiesi@0
|
760 if ($delta > 0) {
|
danielebarchiesi@0
|
761 if ($max == $r && $max != $g) $h += ($g - $b) / $delta;
|
danielebarchiesi@0
|
762 if ($max == $g && $max != $b) $h += (2 + ($b - $r) / $delta);
|
danielebarchiesi@0
|
763 if ($max == $b && $max != $r) $h += (4 + ($r - $g) / $delta);
|
danielebarchiesi@0
|
764 $h /= 6;
|
danielebarchiesi@0
|
765 }
|
danielebarchiesi@0
|
766
|
danielebarchiesi@0
|
767 return array($h, $s, $l);
|
danielebarchiesi@0
|
768 }
|