1
|
<?php
|
2
|
/**
|
3
|
* @file
|
4
|
* Create customized CSS and images from palettes created by user input.
|
5
|
*/
|
6
|
|
7
|
/**
|
8
|
* Fetch metadata on a specific style_base plugin.
|
9
|
*
|
10
|
* @param $content type
|
11
|
* Name of a panel content type.
|
12
|
*
|
13
|
* @return
|
14
|
* An array with information about the requested stylizer style base.
|
15
|
*/
|
16
|
function ctools_get_style_base($style_base) {
|
17
|
ctools_include('plugins');
|
18
|
return ctools_get_plugins('stylizer', 'style_bases', $style_base);
|
19
|
}
|
20
|
|
21
|
/**
|
22
|
* Fetch metadata for all style_base plugins.
|
23
|
*
|
24
|
* @return
|
25
|
* An array of arrays with information about all available styleizer style bases.
|
26
|
*/
|
27
|
function ctools_get_style_bases() {
|
28
|
ctools_include('plugins');
|
29
|
return ctools_get_plugins('stylizer', 'style_bases');
|
30
|
}
|
31
|
|
32
|
/**
|
33
|
* Fetch metadata about all of the style base types that are available.
|
34
|
*/
|
35
|
function ctools_get_style_base_types() {
|
36
|
$types = array();
|
37
|
foreach (module_implements('ctools_style_base_types') as $module) {
|
38
|
$types[$module] = module_invoke($module, 'ctools_style_base_types');
|
39
|
}
|
40
|
|
41
|
return $types;
|
42
|
}
|
43
|
|
44
|
/**
|
45
|
* Render the icon for a style base.
|
46
|
*/
|
47
|
function ctools_stylizer_print_style_icon($plugin, $print_title = TRUE) {
|
48
|
$file = $plugin['path'] . '/' . $plugin['icon'];
|
49
|
$title = $print_title ? $plugin['title'] : '';
|
50
|
return theme('ctools_style_icon', array('image' => theme('image', array('path' => $file)), 'title' => $title));
|
51
|
}
|
52
|
|
53
|
/**
|
54
|
* Theme the style icon image
|
55
|
*/
|
56
|
function theme_ctools_style_icon($vars) {
|
57
|
$image = $vars['image'];
|
58
|
ctools_add_css('stylizer');
|
59
|
ctools_add_js('stylizer');
|
60
|
$output = '<div class="ctools-style-icon">';
|
61
|
$output .= $vars['image'];
|
62
|
if ($vars['title']) {
|
63
|
$output .= '<div class="caption">' . $vars['title'] . '</div>';
|
64
|
}
|
65
|
$output .= '</div>';
|
66
|
return $output;
|
67
|
}
|
68
|
|
69
|
/**
|
70
|
* Add the necessary CSS for a stylizer plugin to the page.
|
71
|
*
|
72
|
* This will check to see if the images directory and the cached CSS
|
73
|
* exists and, if not, will regenerate everything needed.
|
74
|
*/
|
75
|
function ctools_stylizer_add_css($plugin, $settings) {
|
76
|
if (!file_exists(ctools_stylizer_get_image_path($plugin, $settings, FALSE))) {
|
77
|
ctools_stylizer_build_style($plugin, $settings, TRUE);
|
78
|
return;
|
79
|
}
|
80
|
|
81
|
ctools_include('css');
|
82
|
$filename = ctools_css_retrieve(ctools_stylizer_get_css_id($plugin, $settings));
|
83
|
if (!$filename) {
|
84
|
ctools_stylizer_build_style($plugin, $settings, TRUE);
|
85
|
}
|
86
|
else {
|
87
|
drupal_add_css($filename);
|
88
|
}
|
89
|
}
|
90
|
|
91
|
/**
|
92
|
* Build the files for a stylizer given the proper settings.
|
93
|
*/
|
94
|
function ctools_stylizer_build_style($plugin, $settings, $add_css = FALSE) {
|
95
|
$path = ctools_stylizer_get_image_path($plugin, $settings);
|
96
|
if (!$path) {
|
97
|
return;
|
98
|
}
|
99
|
|
100
|
$replacements = array();
|
101
|
|
102
|
// Set up palette conversions
|
103
|
foreach ($settings['palette'] as $key => $color) {
|
104
|
$replacements['%' . $key ] = $color;
|
105
|
}
|
106
|
|
107
|
// Process image actions:
|
108
|
if (!empty($plugin['actions'])) {
|
109
|
$processor = new ctools_stylizer_image_processor;
|
110
|
$processor->execute($path, $plugin, $settings);
|
111
|
|
112
|
// @todo -- there needs to be an easier way to get at this.
|
113
|
// dsm($processor->message_log);
|
114
|
// Add filenames to our conversions.
|
115
|
}
|
116
|
|
117
|
// Convert and write the CSS file.
|
118
|
$css = file_get_contents($plugin['path'] . '/' . $plugin['css']);
|
119
|
|
120
|
// Replace %style keyword with our generated class name.
|
121
|
// @todo We need one more unique identifier I think.
|
122
|
$class = ctools_stylizer_get_css_class($plugin, $settings);
|
123
|
$replacements['%style'] = '.' . $class;
|
124
|
|
125
|
if (!empty($processor) && !empty($processor->paths)) {
|
126
|
foreach ($processor->paths as $file => $image) {
|
127
|
$replacements[$file] = file_create_url($image);
|
128
|
}
|
129
|
}
|
130
|
|
131
|
if (!empty($plugin['build']) && function_exists($plugin['build'])) {
|
132
|
$plugin['build']($plugin, $settings, $css, $replacements);
|
133
|
}
|
134
|
|
135
|
$css = strtr($css, $replacements);
|
136
|
ctools_include('css');
|
137
|
$filename = ctools_css_store(ctools_stylizer_get_css_id($plugin, $settings), $css, FALSE);
|
138
|
|
139
|
if ($add_css) {
|
140
|
drupal_add_css($filename);
|
141
|
}
|
142
|
}
|
143
|
|
144
|
/**
|
145
|
* Clean up no longer used files.
|
146
|
*
|
147
|
* To prevent excess clutter in the files directory, this should be called
|
148
|
* whenever a style is going out of use. When being deleted, but also when
|
149
|
* the palette is being changed.
|
150
|
*/
|
151
|
function ctools_stylizer_cleanup_style($plugin, $settings) {
|
152
|
ctools_include('css');
|
153
|
$path = ctools_stylizer_get_image_path($plugin, $settings, FALSE);
|
154
|
if ($path) {
|
155
|
ctools_stylizer_recursive_delete($path);
|
156
|
}
|
157
|
|
158
|
ctools_css_clear(ctools_stylizer_get_css_id($plugin, $settings));
|
159
|
}
|
160
|
|
161
|
/**
|
162
|
* Recursively delete all files and folders in the specified filepath, then
|
163
|
* delete the containing folder.
|
164
|
*
|
165
|
* Note that this only deletes visible files with write permission.
|
166
|
*
|
167
|
* @param string $path
|
168
|
* A filepath relative to file_directory_path.
|
169
|
*/
|
170
|
function ctools_stylizer_recursive_delete($path) {
|
171
|
if (empty($path)) {
|
172
|
return;
|
173
|
}
|
174
|
|
175
|
$listing = $path . '/*';
|
176
|
|
177
|
foreach (glob($listing) as $file) {
|
178
|
if (is_file($file) === TRUE) {
|
179
|
@unlink($file);
|
180
|
}
|
181
|
elseif (is_dir($file) === TRUE) {
|
182
|
ctools_stylizer_recursive_delete($file);
|
183
|
}
|
184
|
}
|
185
|
|
186
|
@rmdir($path);
|
187
|
}
|
188
|
|
189
|
/**
|
190
|
* Get a safe name for the settings.
|
191
|
*
|
192
|
* This uses an md5 of the palette if the name is temporary so
|
193
|
* that multiple temporary styles on the same page can coexist
|
194
|
* safely.
|
195
|
*/
|
196
|
function ctools_stylizer_get_settings_name($settings) {
|
197
|
if ($settings['name'] != '_temporary') {
|
198
|
return $settings['name'];
|
199
|
}
|
200
|
|
201
|
return $settings['name'] . '-' . md5(serialize($settings['palette']));
|
202
|
}
|
203
|
|
204
|
/**
|
205
|
* Get the path where images will be stored for a given style plugin and settings.
|
206
|
*
|
207
|
* This function will make sure the path exists.
|
208
|
*/
|
209
|
function ctools_stylizer_get_image_path($plugin, $settings, $check = TRUE) {
|
210
|
$path = 'public://ctools/style/' . $settings['name'] . '/' . md5(serialize($settings['palette']));
|
211
|
if (!file_prepare_directory($path, FILE_CREATE_DIRECTORY | FILE_MODIFY_PERMISSIONS)) {
|
212
|
drupal_set_message(t('Unable to create CTools styles cache directory @path. Check the permissions on your files directory.', array('@path' => $path)), 'error');
|
213
|
return;
|
214
|
}
|
215
|
|
216
|
return $path;
|
217
|
}
|
218
|
|
219
|
/**
|
220
|
* Get the id used to cache CSS for a given style plugin and settings.
|
221
|
*/
|
222
|
function ctools_stylizer_get_css_id($plugin, $settings) {
|
223
|
return 'ctools-stylizer:' . $settings['name'] . ':' . md5(serialize($settings['palette']));
|
224
|
}
|
225
|
|
226
|
/**
|
227
|
* Get the class to use for a stylizer plugin.
|
228
|
*/
|
229
|
function ctools_stylizer_get_css_class($plugin, $settings) {
|
230
|
ctools_include('cleanstring');
|
231
|
return ctools_cleanstring($plugin['name'] . '-' . ctools_stylizer_get_settings_name($settings));
|
232
|
}
|
233
|
|
234
|
class ctools_stylizer_image_processor {
|
235
|
var $workspace = NULL;
|
236
|
var $name = NULL;
|
237
|
|
238
|
var $workspaces = array();
|
239
|
|
240
|
var $message_log = array();
|
241
|
var $error_log = array();
|
242
|
|
243
|
function execute($path, $plugin, $settings) {
|
244
|
$this->path = $path;
|
245
|
$this->plugin = $plugin;
|
246
|
$this->settings = $settings;
|
247
|
$this->palette = $settings['palette'];
|
248
|
|
249
|
if (is_string($plugin['actions']) && function_exists($plugin['actions'])) {
|
250
|
$actions = $plugin['actions']($plugin, $settings);
|
251
|
}
|
252
|
else if (is_array($plugin['actions'])) {
|
253
|
$actions = $plugin['actions'];
|
254
|
}
|
255
|
|
256
|
if (!empty($actions) && is_array($actions)) {
|
257
|
foreach ($plugin['actions'] as $action) {
|
258
|
$command = 'command_' . array_shift($action);
|
259
|
if (method_exists($this, $command)) {
|
260
|
call_user_func_array(array($this, $command), $action);
|
261
|
}
|
262
|
}
|
263
|
}
|
264
|
|
265
|
// Clean up buffers.
|
266
|
foreach ($this->workspaces as $name => $workspace) {
|
267
|
imagedestroy($this->workspaces[$name]);
|
268
|
}
|
269
|
}
|
270
|
|
271
|
function log($message, $type = 'normal') {
|
272
|
$this->message_log[] = $message;
|
273
|
if ($type == 'error') {
|
274
|
$this->error_log[] = $message;
|
275
|
}
|
276
|
}
|
277
|
|
278
|
function set_current_workspace($workspace) {
|
279
|
$this->log("Set current workspace: $workspace");
|
280
|
$this->workspace = &$this->workspaces[$workspace];
|
281
|
$this->name = $workspace;
|
282
|
}
|
283
|
|
284
|
/**
|
285
|
* Create a new workspace.
|
286
|
*/
|
287
|
function command_new($name, $width, $height) {
|
288
|
$this->log("New workspace: $name ($width x $height)");
|
289
|
// Clean up if there was already a workspace there.
|
290
|
if (isset($this->workspaces[$name])) {
|
291
|
imagedestroy($this->workspaces[$name]);
|
292
|
}
|
293
|
|
294
|
$this->workspaces[$name] = imagecreatetruecolor($width, $height);
|
295
|
$this->set_current_workspace($name);
|
296
|
|
297
|
// Make sure the new workspace has a transparent color.
|
298
|
|
299
|
// Turn off transparency blending (temporarily)
|
300
|
imagealphablending($this->workspace, FALSE);
|
301
|
|
302
|
// Create a new transparent color for image
|
303
|
$color = imagecolorallocatealpha($this->workspace, 0, 0, 0, 127);
|
304
|
|
305
|
// Completely fill the background of the new image with allocated color.
|
306
|
imagefill($this->workspace, 0, 0, $color);
|
307
|
|
308
|
// Restore transparency blending
|
309
|
imagesavealpha($this->workspace, TRUE);
|
310
|
|
311
|
}
|
312
|
|
313
|
/**
|
314
|
* Create a new workspace a file.
|
315
|
*
|
316
|
* This will make the new workspace the current workspace.
|
317
|
*/
|
318
|
function command_load($name, $file) {
|
319
|
$this->log("New workspace: $name (from $file)");
|
320
|
if (!file_exists($file)) {
|
321
|
// Try it relative to the plugin
|
322
|
$file = $this->plugin['path'] . '/' . $file;
|
323
|
if (!file_exists($file)) {
|
324
|
$this->log("Unable to open $file");
|
325
|
return;
|
326
|
}
|
327
|
}
|
328
|
|
329
|
// Clean up if there was already a workspace there.
|
330
|
if (isset($this->workspaces[$name])) {
|
331
|
imagedestroy($this->workspaces[$name]);
|
332
|
}
|
333
|
|
334
|
$this->workspaces[$name] = imagecreatefrompng($file);
|
335
|
$this->set_current_workspace($name);
|
336
|
}
|
337
|
|
338
|
/**
|
339
|
* Create a new workspace using the properties of an existing workspace
|
340
|
*/
|
341
|
function command_new_from($name, $workspace) {
|
342
|
$this->log("New workspace: $name from existing $workspace");
|
343
|
if (empty($this->workspaces[$workspace])) {
|
344
|
$this->log("Workspace $name does not exist.", 'error');
|
345
|
return;
|
346
|
}
|
347
|
|
348
|
// Clean up if there was already a workspace there.
|
349
|
if (isset($this->workspaces[$name])) {
|
350
|
imagedestroy($this->workspaces[$name]);
|
351
|
}
|
352
|
|
353
|
$this->workspaces[$name] = $this->new_image($this->workspace[$workspace]);
|
354
|
$this->set_current_workspace($name);
|
355
|
}
|
356
|
|
357
|
/**
|
358
|
* Set the current workspace.
|
359
|
*/
|
360
|
function command_workspace($name) {
|
361
|
$this->log("Set workspace: $name");
|
362
|
if (empty($this->workspaces[$name])) {
|
363
|
$this->log("Workspace $name does not exist.", 'error');
|
364
|
return;
|
365
|
}
|
366
|
$this->set_current_workspace($name);
|
367
|
}
|
368
|
|
369
|
/**
|
370
|
* Copy the contents of one workspace into the current workspace.
|
371
|
*/
|
372
|
function command_merge_from($workspace, $x = 0, $y = 0) {
|
373
|
$this->log("Merge from: $workspace ($x, $y)");
|
374
|
if (empty($this->workspaces[$workspace])) {
|
375
|
$this->log("Workspace $name does not exist.", 'error');
|
376
|
return;
|
377
|
}
|
378
|
|
379
|
$this->merge($this->workspaces[$workspace], $this->workspace, $x, $y);
|
380
|
}
|
381
|
|
382
|
function command_merge_to($workspace, $x = 0, $y = 0) {
|
383
|
$this->log("Merge to: $workspace ($x, $y)");
|
384
|
if (empty($this->workspaces[$workspace])) {
|
385
|
$this->log("Workspace $name does not exist.", 'error');
|
386
|
return;
|
387
|
}
|
388
|
|
389
|
$this->merge($this->workspace, $this->workspaces[$workspace], $x, $y);
|
390
|
$this->set_current_workspace($workspace);
|
391
|
}
|
392
|
|
393
|
/**
|
394
|
* Blend an image into the current workspace.
|
395
|
*/
|
396
|
function command_merge_from_file($file, $x = 0, $y = 0) {
|
397
|
$this->log("Merge from file: $file ($x, $y)");
|
398
|
if (!file_exists($file)) {
|
399
|
// Try it relative to the plugin
|
400
|
$file = $this->plugin['path'] . '/' . $file;
|
401
|
if (!file_exists($file)) {
|
402
|
$this->log("Unable to open $file");
|
403
|
return;
|
404
|
}
|
405
|
}
|
406
|
|
407
|
$source = imagecreatefrompng($file);
|
408
|
|
409
|
$this->merge($source, $this->workspace, $x, $y);
|
410
|
|
411
|
imagedestroy($source);
|
412
|
}
|
413
|
|
414
|
function command_fill($color, $x, $y, $width, $height) {
|
415
|
$this->log("Fill: $color ($x, $y, $width, $height)");
|
416
|
imagefilledrectangle($this->workspace, $x, $y, $x + $width, $y + $height, _color_gd($this->workspace, $this->palette[$color]));
|
417
|
}
|
418
|
|
419
|
function command_gradient($from, $to, $x, $y, $width, $height, $direction = 'down') {
|
420
|
$this->log("Gradient: $from to $to ($x, $y, $width, $height) $direction");
|
421
|
|
422
|
if ($direction == 'down') {
|
423
|
for ($i = 0; $i < $height; ++$i) {
|
424
|
$color = _color_blend($this->workspace, $this->palette[$from], $this->palette[$to], $i / ($height - 1));
|
425
|
imagefilledrectangle($this->workspace, $x, $y + $i, $x + $width, $y + $i + 1, $color);
|
426
|
}
|
427
|
}
|
428
|
else {
|
429
|
for ($i = 0; $i < $width; ++$i) {
|
430
|
$color = _color_blend($this->workspace, $this->palette[$from], $this->palette[$to], $i / ($width - 1));
|
431
|
imagefilledrectangle($this->workspace, $x + $i, $y, $x + $i + 1, $y + $height, $color);
|
432
|
}
|
433
|
}
|
434
|
}
|
435
|
|
436
|
/**
|
437
|
* Colorize the current workspace with the given location.
|
438
|
*
|
439
|
* This uses simple color blending to colorize the image.
|
440
|
*
|
441
|
* @todo it is possible that this colorize could allow different methods for
|
442
|
* determining how to blend colors?
|
443
|
*/
|
444
|
function command_colorize($color, $x = NULL, $y = NULL, $width = NULL, $height = NULL) {
|
445
|
if (!isset($x)) {
|
446
|
$whole_image = TRUE;
|
447
|
$x = $y = 0;
|
448
|
$width = imagesx($this->workspace);
|
449
|
$height = imagesy($this->workspace);
|
450
|
}
|
451
|
$this->log("Colorize: $color ($x, $y, $width, $height)");
|
452
|
|
453
|
$c = _color_unpack($this->palette[$color]);
|
454
|
|
455
|
imagealphablending($this->workspace, FALSE);
|
456
|
imagesavealpha($this->workspace, TRUE);
|
457
|
|
458
|
// If PHP 5 use the nice imagefilter which is faster.
|
459
|
if (!empty($whole_image) && version_compare(phpversion(), '5.2.5', '>=') && function_exists('imagefilter')) {
|
460
|
imagefilter($this->workspace, IMG_FILTER_COLORIZE, $c[0], $c[1], $c[2]);
|
461
|
}
|
462
|
else {
|
463
|
// Otherwise we can do it the brute force way.
|
464
|
for ($j = 0; $j < $height; $j++) {
|
465
|
for ($i = 0; $i < $width; $i++) {
|
466
|
$current = imagecolorsforindex($this->workspace, imagecolorat($this->workspace, $i, $j));
|
467
|
$new_index = imagecolorallocatealpha($this->workspace, $c[0], $c[1], $c[2], $current['alpha']);
|
468
|
imagesetpixel($this->workspace, $i, $j, $new_index);
|
469
|
}
|
470
|
}
|
471
|
}
|
472
|
}
|
473
|
|
474
|
/**
|
475
|
* Colorize the current workspace with the given location.
|
476
|
*
|
477
|
* This uses a color replacement algorithm that retains luminosity but
|
478
|
* turns replaces all color with the specified color.
|
479
|
*/
|
480
|
function command_hue($color, $x = NULL, $y = NULL, $width = NULL, $height = NULL) {
|
481
|
if (!isset($x)) {
|
482
|
$whole_image = TRUE;
|
483
|
$x = $y = 0;
|
484
|
$width = imagesx($this->workspace);
|
485
|
$height = imagesy($this->workspace);
|
486
|
}
|
487
|
$this->log("Hue: $color ($x, $y, $width, $height)");
|
488
|
|
489
|
list($red, $green, $blue) = _color_unpack($this->palette[$color]);
|
490
|
|
491
|
// We will create a monochromatic palette based on the input color
|
492
|
// which will go from black to white.
|
493
|
|
494
|
// Input color luminosity: this is equivalent to the position of the
|
495
|
// input color in the monochromatic palette
|
496
|
$luminosity_input = round(255 * ($red + $green + $blue) / 765); // 765 = 255 * 3
|
497
|
|
498
|
// We fill the palette entry with the input color at itscorresponding position
|
499
|
$palette[$luminosity_input]['red'] = $red;
|
500
|
$palette[$luminosity_input]['green'] = $green;
|
501
|
$palette[$luminosity_input]['blue'] = $blue;
|
502
|
|
503
|
// Now we complete the palette, first we'll do it tothe black, and then to
|
504
|
// the white.
|
505
|
|
506
|
// From input to black
|
507
|
$steps_to_black = $luminosity_input;
|
508
|
|
509
|
// The step size for each component
|
510
|
if ($steps_to_black) {
|
511
|
$step_size_red = $red / $steps_to_black;
|
512
|
$step_size_green = $green / $steps_to_black;
|
513
|
$step_size_blue = $blue / $steps_to_black;
|
514
|
|
515
|
for ($i = $steps_to_black; $i >= 0; $i--) {
|
516
|
$palette[$steps_to_black-$i]['red'] = $red - round($step_size_red * $i);
|
517
|
$palette[$steps_to_black-$i]['green'] = $green - round($step_size_green * $i);
|
518
|
$palette[$steps_to_black-$i]['blue'] = $blue - round($step_size_blue * $i);
|
519
|
}
|
520
|
}
|
521
|
|
522
|
// From input to white
|
523
|
$steps_to_white = 255 - $luminosity_input;
|
524
|
|
525
|
if ($steps_to_white) {
|
526
|
$step_size_red = (255 - $red) / $steps_to_white;
|
527
|
$step_size_green = (255 - $green) / $steps_to_white;
|
528
|
$step_size_blue = (255 - $blue) / $steps_to_white;
|
529
|
}
|
530
|
else {
|
531
|
$step_size_red=$step_size_green=$step_size_blue=0;
|
532
|
}
|
533
|
|
534
|
// The step size for each component
|
535
|
for ($i = ($luminosity_input + 1); $i <= 255; $i++) {
|
536
|
$palette[$i]['red'] = $red + round($step_size_red * ($i - $luminosity_input));
|
537
|
$palette[$i]['green'] = $green + round($step_size_green * ($i - $luminosity_input));
|
538
|
$palette[$i]['blue']= $blue + round($step_size_blue * ($i - $luminosity_input));
|
539
|
}
|
540
|
|
541
|
// Go over the specified area of the image and update the colors.
|
542
|
for ($j = $x; $j < $height; $j++) {
|
543
|
for ($i = $y; $i < $width; $i++) {
|
544
|
$color = imagecolorsforindex($this->workspace, imagecolorat($this->workspace, $i, $j));
|
545
|
$luminosity = round(255 * ($color['red'] + $color['green'] + $color['blue']) / 765);
|
546
|
$new_color = imagecolorallocatealpha($this->workspace, $palette[$luminosity]['red'], $palette[$luminosity]['green'], $palette[$luminosity]['blue'], $color['alpha']);
|
547
|
imagesetpixel($this->workspace, $i, $j, $new_color);
|
548
|
}
|
549
|
}
|
550
|
}
|
551
|
|
552
|
/**
|
553
|
* Take a slice out of the current workspace and save it as an image.
|
554
|
*/
|
555
|
function command_slice($file, $x = NULL, $y = NULL, $width = NULL, $height = NULL) {
|
556
|
if (!isset($x)) {
|
557
|
$x = $y = 0;
|
558
|
$width = imagesx($this->workspace);
|
559
|
$height = imagesy($this->workspace);
|
560
|
}
|
561
|
|
562
|
$this->log("Slice: $file ($x, $y, $width, $height)");
|
563
|
|
564
|
$base = basename($file);
|
565
|
$image = $this->path . '/' . $base;
|
566
|
|
567
|
$slice = $this->new_image($this->workspace, $width, $height);
|
568
|
imagecopy($slice, $this->workspace, 0, 0, $x, $y, $width, $height);
|
569
|
|
570
|
// Make sure alphas are saved:
|
571
|
imagealphablending($slice, FALSE);
|
572
|
imagesavealpha($slice, TRUE);
|
573
|
|
574
|
// Save image.
|
575
|
$temp_name = drupal_tempnam('temporary://', 'file');
|
576
|
|
577
|
imagepng($slice, drupal_realpath($temp_name));
|
578
|
file_unmanaged_move($temp_name, $image);
|
579
|
imagedestroy($slice);
|
580
|
|
581
|
// Set standard file permissions for webserver-generated files
|
582
|
@chmod(realpath($image), 0664);
|
583
|
|
584
|
$this->paths[$file] = $image;
|
585
|
}
|
586
|
|
587
|
/**
|
588
|
* Prepare a new image for being copied or worked on, preserving transparency.
|
589
|
*/
|
590
|
function &new_image(&$source, $width = NULL, $height = NULL) {
|
591
|
if (!isset($width)) {
|
592
|
$width = imagesx($source);
|
593
|
}
|
594
|
|
595
|
if (!isset($height)) {
|
596
|
$height = imagesy($source);
|
597
|
}
|
598
|
|
599
|
$target = imagecreatetruecolor($width, $height);
|
600
|
imagealphablending($target, FALSE);
|
601
|
imagesavealpha($target, TRUE);
|
602
|
|
603
|
$transparency_index = imagecolortransparent($source);
|
604
|
|
605
|
// If we have a specific transparent color
|
606
|
if ($transparency_index >= 0) {
|
607
|
// Get the original image's transparent color's RGB values
|
608
|
$transparent_color = imagecolorsforindex($source, $transparency_index);
|
609
|
|
610
|
// Allocate the same color in the new image resource
|
611
|
$transparency_index = imagecolorallocate($target, $transparent_color['red'], $transparent_color['green'], $transparent_color['blue']);
|
612
|
|
613
|
// Completely fill the background of the new image with allocated color.
|
614
|
imagefill($target, 0, 0, $transparency_index);
|
615
|
|
616
|
// Set the background color for new image to transparent
|
617
|
imagecolortransparent($target, $transparency_index);
|
618
|
}
|
619
|
// Always make a transparent background color for PNGs that don't have one allocated already
|
620
|
else {
|
621
|
// Create a new transparent color for image
|
622
|
$color = imagecolorallocatealpha($target, 0, 0, 0, 127);
|
623
|
|
624
|
// Completely fill the background of the new image with allocated color.
|
625
|
imagefill($target, 0, 0, $color);
|
626
|
}
|
627
|
|
628
|
return $target;
|
629
|
}
|
630
|
|
631
|
/**
|
632
|
* Merge two images together, preserving alpha transparency.
|
633
|
*/
|
634
|
function merge(&$from, &$to, $x, $y) {
|
635
|
// Blend over template.
|
636
|
$width = imagesx($from);
|
637
|
$height = imagesy($from);
|
638
|
|
639
|
// Re-enable alpha blending to make sure transparency merges.
|
640
|
imagealphablending($to, TRUE);
|
641
|
imagecopy($to, $from, $x, $y, 0, 0, $width, $height);
|
642
|
imagealphablending($to, FALSE);
|
643
|
}
|
644
|
}
|
645
|
|
646
|
/**
|
647
|
* Get the cached changes to a given task handler.
|
648
|
*/
|
649
|
function ctools_stylizer_get_settings_cache($name) {
|
650
|
ctools_include('object-cache');
|
651
|
return ctools_object_cache_get('ctools_stylizer_settings', $name);
|
652
|
}
|
653
|
|
654
|
/**
|
655
|
* Store changes to a task handler in the object cache.
|
656
|
*/
|
657
|
function ctools_stylizer_set_settings_cache($name, $settings) {
|
658
|
ctools_include('object-cache');
|
659
|
ctools_object_cache_set('ctools_stylizer_settings', $name, $settings);
|
660
|
}
|
661
|
|
662
|
/**
|
663
|
* Remove an item from the object cache.
|
664
|
*/
|
665
|
function ctools_stylizer_clear_settings_cache($name) {
|
666
|
ctools_include('object-cache');
|
667
|
ctools_object_cache_clear('ctools_stylizer_settings', $name);
|
668
|
}
|
669
|
|
670
|
/**
|
671
|
* Add a new style of the specified type.
|
672
|
*/
|
673
|
function ctools_stylizer_edit_style(&$info, $js, $step = NULL) {
|
674
|
$name = '::new';
|
675
|
$form_info = array(
|
676
|
'id' => 'ctools_stylizer_edit_style',
|
677
|
'path' => $info['path'],
|
678
|
'show trail' => TRUE,
|
679
|
'show back' => TRUE,
|
680
|
'show return' => FALSE,
|
681
|
'next callback' => 'ctools_stylizer_edit_style_next',
|
682
|
'finish callback' => 'ctools_stylizer_edit_style_finish',
|
683
|
'return callback' => 'ctools_stylizer_edit_style_finish',
|
684
|
'cancel callback' => 'ctools_stylizer_edit_style_cancel',
|
685
|
'forms' => array(
|
686
|
'choose' => array(
|
687
|
'form id' => 'ctools_stylizer_edit_style_form_choose',
|
688
|
),
|
689
|
),
|
690
|
);
|
691
|
|
692
|
if (empty($info['settings'])) {
|
693
|
$form_info['order'] = array(
|
694
|
'choose' => t('Select base style'),
|
695
|
);
|
696
|
if (empty($step)) {
|
697
|
$step = 'choose';
|
698
|
}
|
699
|
|
700
|
if ($step != 'choose') {
|
701
|
$cache = ctools_stylizer_get_settings_cache($name);
|
702
|
if (!$cache) {
|
703
|
$output = t('Missing settings cache.');
|
704
|
if ($js) {
|
705
|
return ctools_modal_form_render($form_state, $output);
|
706
|
}
|
707
|
else {
|
708
|
return $output;
|
709
|
}
|
710
|
}
|
711
|
|
712
|
if (!empty($cache['owner settings'])) {
|
713
|
$info['owner settings'] = $cache['owner settings'];
|
714
|
}
|
715
|
$settings = $cache['settings'];
|
716
|
}
|
717
|
else {
|
718
|
$settings = array(
|
719
|
'name' => '_temporary',
|
720
|
'style_base' => NULL,
|
721
|
'palette' => array(),
|
722
|
);
|
723
|
ctools_stylizer_clear_settings_cache($name);
|
724
|
}
|
725
|
$op = 'add';
|
726
|
}
|
727
|
else {
|
728
|
$cache = ctools_stylizer_get_settings_cache($info['settings']['name']);
|
729
|
|
730
|
if (!empty($cache)) {
|
731
|
if (!empty($cache['owner settings'])) {
|
732
|
$info['owner settings'] = $cache['owner settings'];
|
733
|
}
|
734
|
$settings = $cache['settings'];
|
735
|
}
|
736
|
else {
|
737
|
$settings = $info['settings'];
|
738
|
}
|
739
|
$op = 'edit';
|
740
|
}
|
741
|
|
742
|
if (!empty($info['op'])) {
|
743
|
// Allow this to override. Necessary to allow cloning properly.
|
744
|
$op = $info['op'];
|
745
|
}
|
746
|
|
747
|
$plugin = NULL;
|
748
|
if (!empty($settings['style_base'])) {
|
749
|
$plugin = ctools_get_style_base($settings['style_base']);
|
750
|
$info['type'] = $plugin['type'];
|
751
|
ctools_stylizer_add_plugin_forms($form_info, $plugin, $op);
|
752
|
}
|
753
|
else {
|
754
|
// This is here so the 'finish' button does not show up, and because
|
755
|
// we don't have the selected style we don't know what the next form(s)
|
756
|
// will be.
|
757
|
$form_info['order']['next'] = t('Configure style');
|
758
|
}
|
759
|
|
760
|
if (count($form_info['order']) < 2 || $step == 'choose') {
|
761
|
$form_info['show trail'] = FALSE;
|
762
|
}
|
763
|
|
764
|
$form_state = array(
|
765
|
'module' => $info['module'],
|
766
|
'type' => $info['type'],
|
767
|
'owner info' => &$info,
|
768
|
'base_style_plugin' => $plugin,
|
769
|
'name' => $name,
|
770
|
'step' => $step,
|
771
|
'settings' => $settings,
|
772
|
'ajax' => $js,
|
773
|
'op' => $op,
|
774
|
);
|
775
|
|
776
|
if (!empty($info['modal'])) {
|
777
|
$form_state['modal'] = TRUE;
|
778
|
$form_state['title'] = $info['modal'];
|
779
|
$form_state['modal return'] = TRUE;
|
780
|
}
|
781
|
|
782
|
ctools_include('wizard');
|
783
|
$output = ctools_wizard_multistep_form($form_info, $step, $form_state);
|
784
|
|
785
|
if (!empty($form_state['complete'])) {
|
786
|
$info['complete'] = TRUE;
|
787
|
$info['settings'] = $form_state['settings'];
|
788
|
}
|
789
|
|
790
|
if ($js && !$output && !empty($form_state['clicked_button']['#next'])) {
|
791
|
// We have to do a separate redirect here because the formula that adds
|
792
|
// stuff to the wizard after being chosen hasn't happened. The wizard
|
793
|
// tried to go to the next step which did not exist.
|
794
|
return ctools_stylizer_edit_style($info, $js, $form_state['clicked_button']['#next']);
|
795
|
}
|
796
|
|
797
|
if ($js) {
|
798
|
return ctools_modal_form_render($form_state, $output);
|
799
|
}
|
800
|
else {
|
801
|
return $output;
|
802
|
}
|
803
|
}
|
804
|
|
805
|
/**
|
806
|
* Add wizard forms specific to a style base plugin.
|
807
|
*
|
808
|
* The plugin can store forms either as a simple 'edit form'
|
809
|
* => 'form callback' or if it needs the more complicated wizard
|
810
|
* functionality, it can set 'forms' and 'order' with values suitable
|
811
|
* for the wizard $form_info array.
|
812
|
*
|
813
|
* @param &$form_info
|
814
|
* The form info to modify.
|
815
|
* @param $plugin
|
816
|
* The plugin to use.
|
817
|
* @param $op
|
818
|
* Either 'add' or 'edit' so we can get the right forms.
|
819
|
*/
|
820
|
function ctools_stylizer_add_plugin_forms(&$form_info, $plugin, $op) {
|
821
|
if (empty($plugin['forms'])) {
|
822
|
if ($op == 'add' && isset($plugin['add form'])) {
|
823
|
$id = $plugin['add form'];
|
824
|
}
|
825
|
else if (isset($plugin['edit form'])) {
|
826
|
$id = $plugin['edit form'];
|
827
|
}
|
828
|
else {
|
829
|
$id = 'ctools_stylizer_edit_style_form_default';
|
830
|
}
|
831
|
|
832
|
$form_info['forms']['settings'] = array(
|
833
|
'form id' => $id,
|
834
|
);
|
835
|
$form_info['order']['settings'] = t('Settings');
|
836
|
}
|
837
|
else {
|
838
|
$form_info['forms'] += $plugin['forms'];
|
839
|
$form_info['order'] += $plugin['order'];
|
840
|
}
|
841
|
}
|
842
|
|
843
|
/**
|
844
|
* Callback generated when the add style process is finished.
|
845
|
*/
|
846
|
function ctools_stylizer_edit_style_finish(&$form_state) {
|
847
|
$form_state['complete'] = TRUE;
|
848
|
ctools_stylizer_clear_settings_cache($form_state['name']);
|
849
|
|
850
|
if (isset($form_state['settings']['old_settings'])) {
|
851
|
unset($form_state['settings']['old_settings']);
|
852
|
}
|
853
|
}
|
854
|
|
855
|
/**
|
856
|
* Callback generated when the 'next' button is clicked.
|
857
|
*/
|
858
|
function ctools_stylizer_edit_style_next(&$form_state) {
|
859
|
$form_state['form_info']['path'] = str_replace('%name', $form_state['name'], $form_state['form_info']['path']);
|
860
|
$form_state['redirect'] = ctools_wizard_get_path($form_state['form_info'], $form_state['clicked_button']['#next']);
|
861
|
|
862
|
// Update the cache with changes.
|
863
|
$cache = array('settings' => $form_state['settings']);
|
864
|
if (!empty($form_state['owner info']['owner settings'])) {
|
865
|
$cache['owner settings'] = $form_state['owner info']['owner settings'];
|
866
|
}
|
867
|
ctools_stylizer_set_settings_cache($form_state['name'], $cache);
|
868
|
}
|
869
|
|
870
|
/**
|
871
|
* Callback generated when the 'cancel' button is clicked.
|
872
|
*
|
873
|
* We might have some temporary data lying around. We must remove it.
|
874
|
*/
|
875
|
function ctools_stylizer_edit_style_cancel(&$form_state) {
|
876
|
if (!empty($form_state['name'])) {
|
877
|
ctools_stylizer_clear_settings_cache($form_state['name']);
|
878
|
}
|
879
|
}
|
880
|
|
881
|
/**
|
882
|
* Choose which plugin to use to create a new style.
|
883
|
*/
|
884
|
function ctools_stylizer_edit_style_form_choose($form, &$form_state) {
|
885
|
$plugins = ctools_get_style_bases();
|
886
|
$options = array();
|
887
|
|
888
|
$categories = array();
|
889
|
foreach ($plugins as $name => $plugin) {
|
890
|
if ($form_state['module'] == $plugin['module'] && $form_state['type'] == $plugin['type']) {
|
891
|
$categories[$plugin['category']] = $plugin['category'];
|
892
|
$unsorted_options[$plugin['category']][$name] = ctools_stylizer_print_style_icon($plugin, TRUE);
|
893
|
}
|
894
|
}
|
895
|
|
896
|
asort($categories);
|
897
|
|
898
|
foreach ($categories as $category) {
|
899
|
$options[$category] = $unsorted_options[$category];
|
900
|
}
|
901
|
|
902
|
$form['style_base'] = array(
|
903
|
'#prefix' => '<div class="ctools-style-icons clearfix">',
|
904
|
'#suffix' => '</div>',
|
905
|
);
|
906
|
|
907
|
ctools_include('cleanstring');
|
908
|
foreach ($options as $category => $radios) {
|
909
|
$cat = ctools_cleanstring($category);
|
910
|
$form['style_base'][$cat] = array(
|
911
|
'#prefix' => '<div class="ctools-style-category clearfix"><label>' . $category . '</label>',
|
912
|
'#suffix' => '</div>',
|
913
|
);
|
914
|
|
915
|
foreach ($radios as $key => $choice) {
|
916
|
// Generate the parents as the autogenerator does, so we will have a
|
917
|
// unique id for each radio button.
|
918
|
$form['style_base'][$cat][$key] = array(
|
919
|
'#type' => 'radio',
|
920
|
'#title' => $choice,
|
921
|
'#parents' => array('style_base'),
|
922
|
'#id' => drupal_clean_css_identifier('edit-style-base-' . $key),
|
923
|
'#return_value' => check_plain($key),
|
924
|
);
|
925
|
}
|
926
|
}
|
927
|
|
928
|
return $form;
|
929
|
}
|
930
|
|
931
|
function ctools_stylizer_edit_style_form_choose_submit($form, &$form_state) {
|
932
|
$form_state['settings']['style_base'] = $form_state['values']['style_base'];
|
933
|
|
934
|
// The 'next' form will show up as 'next' but that's not accurate now that
|
935
|
// we have a style. Figure out what next really is and update.
|
936
|
$plugin = ctools_get_style_base($form_state['settings']['style_base']);
|
937
|
if (empty($plugin['forms'])) {
|
938
|
$form_state['clicked_button']['#next'] = 'settings';
|
939
|
}
|
940
|
else {
|
941
|
$forms = array_keys($form_info['forms']);
|
942
|
$form_state['clicked_button']['#next'] = array_shift($forms);
|
943
|
}
|
944
|
|
945
|
// Fill in the defaults for the settings.
|
946
|
if (!empty($plugin['defaults'])) {
|
947
|
// @todo allow a callback
|
948
|
$form_state['settings'] += $plugin['defaults'];
|
949
|
}
|
950
|
|
951
|
return $form;
|
952
|
}
|
953
|
|
954
|
/**
|
955
|
* The default stylizer style editing form.
|
956
|
*
|
957
|
* Even when not using this, styles should call through to this form in
|
958
|
* their own edit forms.
|
959
|
*/
|
960
|
function ctools_stylizer_edit_style_form_default($form, &$form_state) {
|
961
|
ctools_add_js('stylizer');
|
962
|
ctools_add_css('stylizer');
|
963
|
drupal_add_library('system', 'farbtastic');
|
964
|
|
965
|
$plugin = &$form_state['base_style_plugin'];
|
966
|
$settings = &$form_state['settings'];
|
967
|
|
968
|
$form['top box'] = array(
|
969
|
'#prefix' => '<div id="ctools-stylizer-top-box" class="clearfix">',
|
970
|
'#suffix' => '</div>',
|
971
|
);
|
972
|
$form['top box']['left'] = array(
|
973
|
'#prefix' => '<div id="ctools-stylizer-left-box">',
|
974
|
'#suffix' => '</div>',
|
975
|
);
|
976
|
$form['top box']['preview'] = array(
|
977
|
// We have a copy of the $form_state on $form because form theme functions
|
978
|
// do not get $form_state.
|
979
|
'#theme' => 'ctools_stylizer_preview_form',
|
980
|
'#form_state' => &$form_state,
|
981
|
);
|
982
|
|
983
|
$form['top box']['preview']['submit'] = array(
|
984
|
'#type' => 'submit',
|
985
|
'#value' => t('Preview'),
|
986
|
);
|
987
|
|
988
|
if (!empty($plugin['palette'])) {
|
989
|
$form['top box']['color'] = array(
|
990
|
'#type' => 'fieldset',
|
991
|
'#title' => t('Color scheme'),
|
992
|
'#attributes' => array('id' => 'ctools_stylizer_color_scheme_form', 'class' => array('ctools-stylizer-color-edit')),
|
993
|
'#theme' => 'ctools_stylizer_color_scheme_form',
|
994
|
);
|
995
|
|
996
|
$form['top box']['color']['palette']['#tree'] = TRUE;
|
997
|
|
998
|
foreach ($plugin['palette'] as $key => $color) {
|
999
|
if (empty($settings['palette'][$key])) {
|
1000
|
$settings['palette'][$key] = $color['default_value'];
|
1001
|
}
|
1002
|
|
1003
|
$form['top box']['color']['palette'][$key] = array(
|
1004
|
'#type' => 'textfield',
|
1005
|
'#title' => $color['label'],
|
1006
|
'#default_value' => $settings['palette'][$key],
|
1007
|
'#size' => 8,
|
1008
|
);
|
1009
|
}
|
1010
|
}
|
1011
|
|
1012
|
if (!empty($plugin['settings form']) && function_exists($plugin['settings form'])) {
|
1013
|
$plugin['settings form']($form, $form_state);
|
1014
|
}
|
1015
|
|
1016
|
if (!empty($form_state['owner info']['owner form']) && function_exists($form_state['owner info']['owner form'])) {
|
1017
|
$form_state['owner info']['owner form']($form, $form_state);
|
1018
|
}
|
1019
|
|
1020
|
return $form;
|
1021
|
}
|
1022
|
|
1023
|
/**
|
1024
|
* Theme the stylizer color scheme form.
|
1025
|
*/
|
1026
|
function theme_ctools_stylizer_color_scheme_form($vars) {
|
1027
|
$form = &$vars['form'];
|
1028
|
$output = '';
|
1029
|
|
1030
|
// Wrapper
|
1031
|
$output .= '<div class="color-form clearfix">';
|
1032
|
|
1033
|
// Color schemes
|
1034
|
// $output .= drupal_render($form['scheme']);
|
1035
|
|
1036
|
// Palette
|
1037
|
$output .= '<div id="palette" class="clearfix">';
|
1038
|
foreach (element_children($form['palette']) as $name) {
|
1039
|
$output .= render($form['palette'][$name]);
|
1040
|
}
|
1041
|
$output .= '</div>'; // palette
|
1042
|
|
1043
|
$output .= '</div>'; // color form
|
1044
|
|
1045
|
return $output;
|
1046
|
}
|
1047
|
|
1048
|
/**
|
1049
|
* Theme the stylizer preview form.
|
1050
|
*/
|
1051
|
function theme_ctools_stylizer_preview_form($vars) {
|
1052
|
$form = &$vars['form'];
|
1053
|
|
1054
|
$plugin = $form['#form_state']['base_style_plugin'];
|
1055
|
$settings = $form['#form_state']['settings'];
|
1056
|
|
1057
|
if (!empty($form['#form_state']['settings']['old_settings'])) {
|
1058
|
ctools_stylizer_cleanup_style($plugin, $form['#form_state']['settings']['old_settings']);
|
1059
|
}
|
1060
|
$preview = '';
|
1061
|
if (!empty($plugin['preview'])) {
|
1062
|
$preview = $plugin['preview'];
|
1063
|
}
|
1064
|
else {
|
1065
|
$base_types = ctools_get_style_base_types();
|
1066
|
if (!empty($base_types[$plugin['module']][$plugin['type']]['preview'])) {
|
1067
|
$preview = $base_types[$plugin['module']][$plugin['type']]['preview'];
|
1068
|
}
|
1069
|
}
|
1070
|
|
1071
|
if (!empty($preview) && function_exists($preview)) {
|
1072
|
$output = '<fieldset id="preview"><legend>' . t('Preview') . '</legend>';
|
1073
|
$output .= $preview($plugin, $settings);
|
1074
|
$output .= drupal_render_children($form);
|
1075
|
$output .= '</fieldset>';
|
1076
|
|
1077
|
return $output;
|
1078
|
}
|
1079
|
}
|
1080
|
|
1081
|
function ctools_stylizer_edit_style_form_default_validate($form, &$form_state) {
|
1082
|
if (!empty($form_state['owner info']['owner form validate']) && function_exists($form_state['owner info']['owner form validate'])) {
|
1083
|
$form_state['owner info']['owner form validate']($form, $form_state);
|
1084
|
}
|
1085
|
|
1086
|
if (!empty($form_state['base_style_plugin']['settings form validate']) && function_exists($form_state['base_style_plugin']['settings form validate'])) {
|
1087
|
$form_state['base_style_plugin']['settings form validate']($form, $form_state);
|
1088
|
}
|
1089
|
}
|
1090
|
|
1091
|
function ctools_stylizer_edit_style_form_default_submit($form, &$form_state) {
|
1092
|
// Store old settings for the purposes of cleaning up.
|
1093
|
$form_state['settings']['old_settings'] = $form_state['settings'];
|
1094
|
$form_state['settings']['palette'] = $form_state['values']['palette'];
|
1095
|
|
1096
|
if (!empty($form_state['owner info']['owner form submit']) && function_exists($form_state['owner info']['owner form submit'])) {
|
1097
|
$form_state['owner info']['owner form submit']($form, $form_state);
|
1098
|
}
|
1099
|
|
1100
|
if (!empty($form_state['base_style_plugin']['settings form submit']) && function_exists($form_state['base_style_plugin']['settings form submit'])) {
|
1101
|
$form_state['base_style_plugin']['settings form submit']($form, $form_state);
|
1102
|
}
|
1103
|
|
1104
|
if ($form_state['clicked_button']['#value'] == t('Preview')) {
|
1105
|
$form_state['rerender'] = TRUE;
|
1106
|
// Update the cache with changes.
|
1107
|
if (!empty($form_state['name'])) {
|
1108
|
$cache = array('settings' => $form_state['settings']);
|
1109
|
if (!empty($form_state['owner info']['owner settings'])) {
|
1110
|
$cache['owner settings'] = $form_state['owner info']['owner settings'];
|
1111
|
}
|
1112
|
ctools_stylizer_set_settings_cache($form_state['name'], $cache);
|
1113
|
}
|
1114
|
}
|
1115
|
}
|
1116
|
|
1117
|
// --------------------------------------------------------------------------
|
1118
|
// CSS forms and tools that plugins can use.
|
1119
|
|
1120
|
/**
|
1121
|
* Font selector form
|
1122
|
*/
|
1123
|
function ctools_stylizer_font_selector_form(&$form, &$form_state, $label, $settings) {
|
1124
|
// Family
|
1125
|
$form['#prefix'] = '<div class="ctools-stylizer-spacing-form clearfix">';
|
1126
|
$form['#type'] = 'fieldset';
|
1127
|
$form['#title'] = $label;
|
1128
|
$form['#suffix'] = '</div>';
|
1129
|
$form['#tree'] = TRUE;
|
1130
|
|
1131
|
$form['font'] = array(
|
1132
|
'#title' => t('Font family'),
|
1133
|
'#type' => 'select',
|
1134
|
'#default_value' => isset($settings['font']) ? $settings['font'] : '',
|
1135
|
'#options' => array(
|
1136
|
'' => '',
|
1137
|
'Arial, Helvetica, sans-serif' => t('Arial, Helvetica, sans-serif'),
|
1138
|
'Times New Roman, Times, serif' => t('Times New Roman, Times, serif'),
|
1139
|
'Courier New, Courier, monospace' => t('Courier New, Courier, monospace'),
|
1140
|
'Georgia, Times New Roman, Times, serif' => t('Georgia, Times New Roman, Times, serif'),
|
1141
|
'Verdana, Arial, Helvetica, sans-serif' => t('Verdana, Arial, Helvetica, sans-serif'),
|
1142
|
'Geneva, Arial, Helvetica, sans-serif' => t('Geneva, Arial, Helvetica, sans-serif'),
|
1143
|
'Trebuchet MS, Trebuchet, Verdana, sans-serif' => t('Trebuchet MS, Trebuchet, Verdana, sans-serif'),
|
1144
|
),
|
1145
|
);
|
1146
|
|
1147
|
// size
|
1148
|
$form['size'] = array(
|
1149
|
'#title' => t('Size'),
|
1150
|
'#type' => 'select',
|
1151
|
'#default_value' => isset($settings['size']) ? $settings['size'] : '',
|
1152
|
'#options' => array(
|
1153
|
'' => '',
|
1154
|
'xx-small' => t('XX-Small'),
|
1155
|
'x-small' => t('X-Small'),
|
1156
|
'small' => t('Small'),
|
1157
|
'medium' => t('Medium'),
|
1158
|
'large' => t('Large'),
|
1159
|
'x-large' => t('X-Large'),
|
1160
|
'xx-large' => t('XX-Large'),
|
1161
|
),
|
1162
|
);
|
1163
|
|
1164
|
// letter spacing
|
1165
|
$form['letter_spacing'] = array(
|
1166
|
'#title' => t('Letter spacing'),
|
1167
|
'#type' => 'select',
|
1168
|
'#default_value' => isset($settings['letter_spacing']) ? $settings['letter_spacing'] : '',
|
1169
|
'#options' => array(
|
1170
|
'' => '',
|
1171
|
"-10px" => '10px',
|
1172
|
"-9px" => '9px',
|
1173
|
"-8px" => '8px',
|
1174
|
"-7px" => '7px',
|
1175
|
"-6px" => '6px',
|
1176
|
"-5px" => '5px',
|
1177
|
"-4px" => '4px',
|
1178
|
"-3px" => '3px',
|
1179
|
"-2px" => '2px',
|
1180
|
"-1px" => '1px',
|
1181
|
"0" => '0',
|
1182
|
"1px" => '1px',
|
1183
|
"2px" => '2px',
|
1184
|
"3px" => '3px',
|
1185
|
"4px" => '4px',
|
1186
|
"5px" => '5px',
|
1187
|
"6px" => '6px',
|
1188
|
"7px" => '7px',
|
1189
|
"8px" => '8px',
|
1190
|
"9px" => '9px',
|
1191
|
"10px" => '10px',
|
1192
|
"11px" => '11px',
|
1193
|
"12px" => '12px',
|
1194
|
"13px" => '13px',
|
1195
|
"14px" => '14px',
|
1196
|
"15px" => '15px',
|
1197
|
"16px" => '16px',
|
1198
|
"17px" => '17px',
|
1199
|
"18px" => '18px',
|
1200
|
"19px" => '19px',
|
1201
|
"20px" => '20px',
|
1202
|
"21px" => '21px',
|
1203
|
"22px" => '22px',
|
1204
|
"23px" => '23px',
|
1205
|
"24px" => '24px',
|
1206
|
"25px" => '25px',
|
1207
|
"26px" => '26px',
|
1208
|
"27px" => '27px',
|
1209
|
"28px" => '28px',
|
1210
|
"29px" => '29px',
|
1211
|
"30px" => '30px',
|
1212
|
"31px" => '31px',
|
1213
|
"32px" => '32px',
|
1214
|
"33px" => '33px',
|
1215
|
"34px" => '34px',
|
1216
|
"35px" => '35px',
|
1217
|
"36px" => '36px',
|
1218
|
"37px" => '37px',
|
1219
|
"38px" => '38px',
|
1220
|
"39px" => '39px',
|
1221
|
"40px" => '40px',
|
1222
|
"41px" => '41px',
|
1223
|
"42px" => '42px',
|
1224
|
"43px" => '43px',
|
1225
|
"44px" => '44px',
|
1226
|
"45px" => '45px',
|
1227
|
"46px" => '46px',
|
1228
|
"47px" => '47px',
|
1229
|
"48px" => '48px',
|
1230
|
"49px" => '49px',
|
1231
|
"50px" => '50px',
|
1232
|
),
|
1233
|
);
|
1234
|
|
1235
|
// word space
|
1236
|
$form['word_spacing'] = array(
|
1237
|
'#title' => t('Word spacing'),
|
1238
|
'#type' => 'select',
|
1239
|
'#default_value' => isset($settings['word_spacing']) ? $settings['word_spacing'] : '',
|
1240
|
'#options' => array(
|
1241
|
'' => '',
|
1242
|
"-1em" => '-1em',
|
1243
|
"-0.95em" => '-0.95em',
|
1244
|
"-0.9em" => '-0.9em',
|
1245
|
"-0.85em" => '-0.85em',
|
1246
|
"-0.8em" => '-0.8em',
|
1247
|
"-0.75em" => '-0.75em',
|
1248
|
"-0.7em" => '-0.7em',
|
1249
|
"-0.65em" => '-0.65em',
|
1250
|
"-0.6em" => '-0.6em',
|
1251
|
"-0.55em" => '-0.55em',
|
1252
|
"-0.5em" => '-0.5em',
|
1253
|
"-0.45em" => '-0.45em',
|
1254
|
"-0.4em" => '-0.4em',
|
1255
|
"-0.35em" => '-0.35em',
|
1256
|
"-0.3em" => '-0.3em',
|
1257
|
"-0.25em" => '-0.25em',
|
1258
|
"-0.2em" => '-0.2em',
|
1259
|
"-0.15em" => '-0.15em',
|
1260
|
"-0.1em" => '-0.1em',
|
1261
|
"-0.05em" => '-0.05em',
|
1262
|
"normal" => 'normal',
|
1263
|
"0.05em" => '0.05em',
|
1264
|
"0.1em" => '0.1em',
|
1265
|
"0.15em" => '0.15em',
|
1266
|
"0.2em" => '0.2em',
|
1267
|
"0.25em" => '0.25em',
|
1268
|
"0.3em" => '0.3em',
|
1269
|
"0.35em" => '0.35em',
|
1270
|
"0.4em" => '0.4em',
|
1271
|
"0.45em" => '0.45em',
|
1272
|
"0.5em" => '0.5em',
|
1273
|
"0.55em" => '0.55em',
|
1274
|
"0.6em" => '0.6em',
|
1275
|
"0.65em" => '0.65em',
|
1276
|
"0.7em" => '0.7em',
|
1277
|
"0.75em" => '0.75em',
|
1278
|
"0.8em" => '0.8em',
|
1279
|
"0.85em" => '0.85em',
|
1280
|
"0.9em" => '0.9em',
|
1281
|
"0.95em" => '0.95em',
|
1282
|
"1em" => '1em',
|
1283
|
),
|
1284
|
);
|
1285
|
|
1286
|
// decoration
|
1287
|
$form['decoration'] = array(
|
1288
|
'#title' => t('Decoration'),
|
1289
|
'#type' => 'select',
|
1290
|
'#default_value' => isset($settings['decoration']) ? $settings['decoration'] : '',
|
1291
|
'#options' => array(
|
1292
|
'' => '',
|
1293
|
'none' => t('None'),
|
1294
|
'underline' => t('Underline'),
|
1295
|
'overline' => t('Overline'),
|
1296
|
'line-through' => t('Line-through'),
|
1297
|
),
|
1298
|
);
|
1299
|
|
1300
|
// weight
|
1301
|
$form['weight'] = array(
|
1302
|
'#title' => t('Weight'),
|
1303
|
'#type' => 'select',
|
1304
|
'#default_value' => isset($settings['weight']) ? $settings['weight'] : '',
|
1305
|
'#options' => array(
|
1306
|
'' => '',
|
1307
|
'normal' => t('Normal'),
|
1308
|
'bold' => t('Bold'),
|
1309
|
'bolder' => t('Bolder'),
|
1310
|
'lighter' => t('Lighter'),
|
1311
|
),
|
1312
|
);
|
1313
|
|
1314
|
// style
|
1315
|
$form['style'] = array(
|
1316
|
'#title' => t('Style'),
|
1317
|
'#type' => 'select',
|
1318
|
'#default_value' => isset($settings['style']) ? $settings['style'] : '',
|
1319
|
'#options' => array(
|
1320
|
'' => '',
|
1321
|
'normal' => t('Normal'),
|
1322
|
'italic' => t('Italic'),
|
1323
|
'oblique' => t('Oblique'),
|
1324
|
),
|
1325
|
);
|
1326
|
|
1327
|
// variant
|
1328
|
$form['variant'] = array(
|
1329
|
'#title' => t('Variant'),
|
1330
|
'#type' => 'select',
|
1331
|
'#default_value' => isset($settings['variant']) ? $settings['variant'] : '',
|
1332
|
'#options' => array(
|
1333
|
'' => '',
|
1334
|
'normal' => t('Normal'),
|
1335
|
'small-caps' => t('Small-caps'),
|
1336
|
),
|
1337
|
);
|
1338
|
|
1339
|
// case
|
1340
|
$form['case'] = array(
|
1341
|
'#title' => t('Case'),
|
1342
|
'#type' => 'select',
|
1343
|
'#default_value' => isset($settings['case']) ? $settings['case'] : '',
|
1344
|
'#options' => array(
|
1345
|
'' => '',
|
1346
|
'capitalize' => t('Capitalize'),
|
1347
|
'uppercase' => t('Uppercase'),
|
1348
|
'lowercase' => t('Lowercase'),
|
1349
|
'none' => t('None'),
|
1350
|
),
|
1351
|
);
|
1352
|
|
1353
|
// alignment
|
1354
|
$form['alignment'] = array(
|
1355
|
'#title' => t('Align'),
|
1356
|
'#type' => 'select',
|
1357
|
'#default_value' => isset($settings['alignment']) ? $settings['alignment'] : '',
|
1358
|
'#options' => array(
|
1359
|
'' => '',
|
1360
|
'justify' => t('Justify'),
|
1361
|
'left' => t('Left'),
|
1362
|
'right' => t('Right'),
|
1363
|
'center' => t('Center'),
|
1364
|
),
|
1365
|
);
|
1366
|
}
|
1367
|
|
1368
|
/**
|
1369
|
* Copy font selector information into the settings
|
1370
|
*/
|
1371
|
function ctools_stylizer_font_selector_form_submit(&$form, &$form_state, &$values, &$settings) {
|
1372
|
$settings = $values;
|
1373
|
}
|
1374
|
|
1375
|
function ctools_stylizer_font_apply_style(&$stylesheet, $selector, $settings) {
|
1376
|
$css = '';
|
1377
|
if (isset($settings['font']) && $settings['font'] !== '') {
|
1378
|
$css .= ' font-family: ' . $settings['font'] . ";\n";
|
1379
|
}
|
1380
|
|
1381
|
if (isset($settings['size']) && $settings['size'] !== '') {
|
1382
|
$css .= ' font-size: ' . $settings['size'] . ";\n";
|
1383
|
}
|
1384
|
|
1385
|
if (isset($settings['weight']) && $settings['weight'] !== '') {
|
1386
|
$css .= ' font-weight: ' . $settings['weight'] . ";\n";
|
1387
|
}
|
1388
|
|
1389
|
if (isset($settings['style']) && $settings['style'] !== '') {
|
1390
|
$css .= ' font-style: ' . $settings['style'] . ";\n";
|
1391
|
}
|
1392
|
|
1393
|
if (isset($settings['variant']) && $settings['variant'] !== '') {
|
1394
|
$css .= ' font-variant: ' . $settings['variant'] . ";\n";
|
1395
|
}
|
1396
|
|
1397
|
if (isset($settings['case']) && $settings['case'] !== '') {
|
1398
|
$css .= ' text-transform: ' . $settings['case'] . ";\n";
|
1399
|
}
|
1400
|
|
1401
|
if (isset($settings['decoration']) && $settings['decoration'] !== '') {
|
1402
|
$css .= ' text-decoration: ' . $settings['decoration'] . ";\n";
|
1403
|
}
|
1404
|
|
1405
|
if (isset($settings['alignment']) && $settings['alignment'] !== '') {
|
1406
|
$css .= ' text-align: ' . $settings['alignment'] . ";\n";
|
1407
|
}
|
1408
|
|
1409
|
if (isset($settings['letter_spacing']) && $settings['letter_spacing'] !== '') {
|
1410
|
$css .= ' letter-spacing: ' . $settings['letter_spacing'] . ";\n";
|
1411
|
}
|
1412
|
|
1413
|
if (isset($settings['word_spacing']) && $settings['word_spacing'] !== '') {
|
1414
|
$css .= ' word-spacing: ' . $settings['word_spacing'] . ";\n";
|
1415
|
}
|
1416
|
|
1417
|
if ($css) {
|
1418
|
$stylesheet .= $selector . " {\n" . $css . "}\n";
|
1419
|
}
|
1420
|
}
|
1421
|
|
1422
|
/**
|
1423
|
* Border selector form
|
1424
|
*/
|
1425
|
function ctools_stylizer_border_selector_form(&$form, &$form_state, $label, $settings) {
|
1426
|
// Family
|
1427
|
$form['#prefix'] = '<div class="ctools-stylizer-spacing-form clearfix">';
|
1428
|
$form['#type'] = 'fieldset';
|
1429
|
$form['#title'] = $label;
|
1430
|
$form['#suffix'] = '</div>';
|
1431
|
$form['#tree'] = TRUE;
|
1432
|
|
1433
|
$form['thickness'] = array(
|
1434
|
'#title' => t('Thickness'),
|
1435
|
'#type' => 'select',
|
1436
|
'#default_value' => isset($settings['thickness']) ? $settings['thickness'] : '',
|
1437
|
'#options' => array(
|
1438
|
'' => '',
|
1439
|
"none" => t('None'),
|
1440
|
"1px" => '1px',
|
1441
|
"2px" => '2px',
|
1442
|
"3px" => '3px',
|
1443
|
"4px" => '4px',
|
1444
|
"5px" => '5px',
|
1445
|
),
|
1446
|
);
|
1447
|
|
1448
|
$form['style'] = array(
|
1449
|
'#title' => t('style'),
|
1450
|
'#type' => 'select',
|
1451
|
'#default_value' => isset($settings['style']) ? $settings['style'] : '',
|
1452
|
'#options' => array(
|
1453
|
'' => '',
|
1454
|
'solid' => t('Solid'),
|
1455
|
'dotted' => t('Dotted'),
|
1456
|
'dashed' => t('Dashed'),
|
1457
|
'double' => t('Double'),
|
1458
|
'groove' => t('Groove'),
|
1459
|
'ridge' => t('Ridge'),
|
1460
|
'inset' => t('Inset'),
|
1461
|
'outset' => t('Outset'),
|
1462
|
),
|
1463
|
);
|
1464
|
}
|
1465
|
|
1466
|
/**
|
1467
|
* Copy border selector information into the settings
|
1468
|
*/
|
1469
|
function ctools_stylizer_border_selector_form_submit(&$form, &$form_state, &$values, &$settings) {
|
1470
|
$settings = $values;
|
1471
|
}
|
1472
|
|
1473
|
function ctools_stylizer_border_apply_style(&$stylesheet, $selector, $settings, $color, $which = NULL) {
|
1474
|
$border = 'border';
|
1475
|
if ($which) {
|
1476
|
$border .= '-' . $which;
|
1477
|
}
|
1478
|
|
1479
|
$css = '';
|
1480
|
if (isset($settings['thickness']) && $settings['thickness'] !== '') {
|
1481
|
if ($settings['thickness'] == 'none') {
|
1482
|
$css .= ' ' . $border . ': none';
|
1483
|
}
|
1484
|
else {
|
1485
|
$css .= ' ' . $border . '-width: ' . $settings['thickness'] . ";\n";
|
1486
|
|
1487
|
if (isset($settings['style']) && $settings['style'] !== '') {
|
1488
|
$css .= ' ' . $border . '-style: ' . $settings['style'] . ";\n";
|
1489
|
}
|
1490
|
|
1491
|
$css .= ' ' . $border . '-color: ' . $color . ";\n";
|
1492
|
}
|
1493
|
}
|
1494
|
|
1495
|
if ($css) {
|
1496
|
$stylesheet .= $selector . " {\n" . $css . "}\n";
|
1497
|
}
|
1498
|
|
1499
|
}
|
1500
|
|
1501
|
/**
|
1502
|
* padding selector form
|
1503
|
*/
|
1504
|
function ctools_stylizer_padding_selector_form(&$form, &$form_state, $label, $settings) {
|
1505
|
// Family
|
1506
|
$form['#prefix'] = '<div class="ctools-stylizer-spacing-form clearfix">';
|
1507
|
$form['#type'] = 'fieldset';
|
1508
|
$form['#title'] = $label;
|
1509
|
$form['#suffix'] = '</div>';
|
1510
|
$form['#tree'] = TRUE;
|
1511
|
|
1512
|
$options = array(
|
1513
|
'' => '',
|
1514
|
"0.05em" => '0.05em',
|
1515
|
"0.1em" => '0.1em',
|
1516
|
"0.15em" => '0.15em',
|
1517
|
"0.2em" => '0.2em',
|
1518
|
"0.25em" => '0.25em',
|
1519
|
"0.3em" => '0.3em',
|
1520
|
"0.35em" => '0.35em',
|
1521
|
"0.4em" => '0.4em',
|
1522
|
"0.45em" => '0.45em',
|
1523
|
"0.5em" => '0.5em',
|
1524
|
"0.55em" => '0.55em',
|
1525
|
"0.6em" => '0.6em',
|
1526
|
"0.65em" => '0.65em',
|
1527
|
"0.7em" => '0.7em',
|
1528
|
"0.75em" => '0.75em',
|
1529
|
"0.8em" => '0.8em',
|
1530
|
"0.85em" => '0.85em',
|
1531
|
"0.9em" => '0.9em',
|
1532
|
"0.95em" => '0.95em',
|
1533
|
"1.0em" => '1.0em',
|
1534
|
"1.05em" => '1.05em',
|
1535
|
"1.1em" => '1.1em',
|
1536
|
"1.15em" => '1.15em',
|
1537
|
"1.2em" => '1.2em',
|
1538
|
"1.25em" => '1.25em',
|
1539
|
"1.3em" => '1.3em',
|
1540
|
"1.35em" => '1.35em',
|
1541
|
"1.4em" => '1.4em',
|
1542
|
"1.45em" => '1.45em',
|
1543
|
"1.5em" => '1.5em',
|
1544
|
"1.55em" => '1.55em',
|
1545
|
"1.6em" => '1.6em',
|
1546
|
"1.65em" => '1.65em',
|
1547
|
"1.7em" => '1.7em',
|
1548
|
"1.75em" => '1.75em',
|
1549
|
"1.8em" => '1.8em',
|
1550
|
"1.85em" => '1.85em',
|
1551
|
"1.9em" => '1.9em',
|
1552
|
"1.95em" => '1.95em',
|
1553
|
"2.0em" => '2.0em',
|
1554
|
"2.05em" => '2.05em',
|
1555
|
"2.1em" => '2.1em',
|
1556
|
"2.15em" => '2.15em',
|
1557
|
"2.2em" => '2.2em',
|
1558
|
"2.25em" => '2.25em',
|
1559
|
"2.3em" => '2.3em',
|
1560
|
"2.35em" => '2.35em',
|
1561
|
"2.4em" => '2.4em',
|
1562
|
"2.45em" => '2.45em',
|
1563
|
"2.5em" => '2.5em',
|
1564
|
"2.55em" => '2.55em',
|
1565
|
"2.6em" => '2.6em',
|
1566
|
"2.65em" => '2.65em',
|
1567
|
"2.7em" => '2.7em',
|
1568
|
"2.75em" => '2.75em',
|
1569
|
"2.8em" => '2.8em',
|
1570
|
"2.85em" => '2.85em',
|
1571
|
"2.9em" => '2.9em',
|
1572
|
"2.95em" => '2.95em',
|
1573
|
"3.0em" => '3.0em',
|
1574
|
"3.05em" => '3.05em',
|
1575
|
"3.1em" => '3.1em',
|
1576
|
"3.15em" => '3.15em',
|
1577
|
"3.2em" => '3.2em',
|
1578
|
"3.25em" => '3.25em',
|
1579
|
"3.3em" => '3.3em',
|
1580
|
"3.35em" => '3.35em',
|
1581
|
"3.4em" => '3.4em',
|
1582
|
"3.45em" => '3.45em',
|
1583
|
"3.5em" => '3.5em',
|
1584
|
"3.55em" => '3.55em',
|
1585
|
"3.6em" => '3.6em',
|
1586
|
"3.65em" => '3.65em',
|
1587
|
"3.7em" => '3.7em',
|
1588
|
"3.75em" => '3.75em',
|
1589
|
"3.8em" => '3.8em',
|
1590
|
"3.85em" => '3.85em',
|
1591
|
"3.9em" => '3.9em',
|
1592
|
"3.95em" => '3.95em',
|
1593
|
);
|
1594
|
|
1595
|
$form['top'] = array(
|
1596
|
'#title' => t('Top'),
|
1597
|
'#type' => 'select',
|
1598
|
'#default_value' => isset($settings['top']) ? $settings['top'] : '',
|
1599
|
'#options' => $options,
|
1600
|
);
|
1601
|
|
1602
|
$form['right'] = array(
|
1603
|
'#title' => t('Right'),
|
1604
|
'#type' => 'select',
|
1605
|
'#default_value' => isset($settings['right']) ? $settings['right'] : '',
|
1606
|
'#options' => $options,
|
1607
|
);
|
1608
|
|
1609
|
$form['bottom'] = array(
|
1610
|
'#title' => t('Bottom'),
|
1611
|
'#type' => 'select',
|
1612
|
'#default_value' => isset($settings['bottom']) ? $settings['bottom'] : '',
|
1613
|
'#options' => $options,
|
1614
|
);
|
1615
|
|
1616
|
$form['left'] = array(
|
1617
|
'#title' => t('Left'),
|
1618
|
'#type' => 'select',
|
1619
|
'#default_value' => isset($settings['left']) ? $settings['left'] : '',
|
1620
|
'#options' => $options,
|
1621
|
);
|
1622
|
}
|
1623
|
|
1624
|
/**
|
1625
|
* Copy padding selector information into the settings
|
1626
|
*/
|
1627
|
function ctools_stylizer_padding_selector_form_submit(&$form, &$form_state, &$values, &$settings) {
|
1628
|
$settings = $values;
|
1629
|
}
|
1630
|
|
1631
|
function ctools_stylizer_padding_apply_style(&$stylesheet, $selector, $settings) {
|
1632
|
$css = '';
|
1633
|
|
1634
|
if (isset($settings['top']) && $settings['top'] !== '') {
|
1635
|
$css .= ' padding-top: ' . $settings['top'] . ";\n";
|
1636
|
}
|
1637
|
|
1638
|
if (isset($settings['right']) && $settings['right'] !== '') {
|
1639
|
$css .= ' padding-right: ' . $settings['right'] . ";\n";
|
1640
|
}
|
1641
|
|
1642
|
if (isset($settings['bottom']) && $settings['bottom'] !== '') {
|
1643
|
$css .= ' padding-bottom: ' . $settings['bottom'] . ";\n";
|
1644
|
}
|
1645
|
|
1646
|
if (isset($settings['left']) && $settings['left'] !== '') {
|
1647
|
$css .= ' padding-left: ' . $settings['left'] . ";\n";
|
1648
|
}
|
1649
|
|
1650
|
if ($css) {
|
1651
|
$stylesheet .= $selector . " {\n" . $css . "}\n";
|
1652
|
}
|
1653
|
|
1654
|
}
|