[TASK] Remove superfluous parenthesis in sysext frontend
[Packages/TYPO3.CMS.git] / typo3 / sysext / frontend / Classes / Imaging / GifBuilder.php
1 <?php
2 namespace TYPO3\CMS\Frontend\Imaging;
3
4 /***************************************************************
5 * Copyright notice
6 *
7 * (c) 1999-2011 Kasper Skårhøj (kasperYYYY@typo3.com)
8 * All rights reserved
9 *
10 * This script is part of the TYPO3 project. The TYPO3 project is
11 * free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * The GNU General Public License can be found at
17 * http://www.gnu.org/copyleft/gpl.html.
18 * A copy is found in the textfile GPL.txt and important notices to the license
19 * from the author is found in LICENSE.txt distributed with these scripts.
20 *
21 *
22 * This script is distributed in the hope that it will be useful,
23 * but WITHOUT ANY WARRANTY; without even the implied warranty of
24 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
25 * GNU General Public License for more details.
26 *
27 * This copyright notice MUST APPEAR in all copies of the script!
28 ***************************************************************/
29 /**
30 * Generating gif/png-files from TypoScript
31 * Used by the menu-objects and imgResource in TypoScript.
32 *
33 * Revised for TYPO3 3.6 June/2003 by Kasper Skårhøj
34 *
35 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
36 */
37 /**
38 * GIFBUILDER extension class.
39 * This class allows for advanced rendering of images with various layers of images, text and graphical primitives.
40 * The concept is known from TypoScript as "GIFBUILDER" where you can define a "numerical array" (TypoScript term as well) of "GIFBUILDER OBJECTS" (like "TEXT", "IMAGE", etc.) and they will be rendered onto an image one by one.
41 * The name "GIFBUILDER" comes from the time where GIF was the only file format supported. PNG is just as well to create today (configured with TYPO3_CONF_VARS[GFX])
42 * Not all instances of this class is truely building gif/png files by layers; You may also see the class instantiated for the purpose of using the scaling functions in the parent class, t3lib_stdGraphic.
43 *
44 * Here is an example of how to use this class (from tslib_content.php, function getImgResource):
45 *
46 * $gifCreator = t3lib_div::makeInstance('tslib_gifbuilder');
47 * $gifCreator->init();
48 * $theImage='';
49 * if ($GLOBALS['TYPO3_CONF_VARS']['GFX']['gdlib']) {
50 * $gifCreator->start($fileArray, $this->data);
51 * $theImage = $gifCreator->gifBuild();
52 * }
53 * return $gifCreator->getImageDimensions($theImage);
54 *
55 * @author Kasper Skårhøj <kasperYYYY@typo3.com>
56 * @package TYPO3
57 * @subpackage tslib
58 */
59 class GifBuilder extends \TYPO3\CMS\Core\Imaging\GraphicalFunctions {
60
61 // Internal
62 // the main image
63 /**
64 * @todo Define visibility
65 */
66 public $im = '';
67
68 // the image-width
69 /**
70 * @todo Define visibility
71 */
72 public $w = 0;
73
74 // the image-height
75 /**
76 * @todo Define visibility
77 */
78 public $h = 0;
79
80 // map-data
81 /**
82 * @todo Define visibility
83 */
84 public $map;
85
86 /**
87 * @todo Define visibility
88 */
89 public $workArea;
90
91 // This holds the operational setup for gifbuilder. Basically this is a TypoScript array with properties.
92 /**
93 * @todo Define visibility
94 */
95 public $setup = array();
96
97 // Contains all text strings used on this image
98 /**
99 * @todo Define visibility
100 */
101 public $combinedTextStrings = array();
102
103 // Contains all filenames (basename without extension) used on this image
104 /**
105 * @todo Define visibility
106 */
107 public $combinedFileNames = array();
108
109 // This is the array from which data->field: [key] is fetched. So this is the current record!
110 /**
111 * @todo Define visibility
112 */
113 public $data = array();
114
115 /**
116 * @todo Define visibility
117 */
118 public $objBB = array();
119
120 /**
121 * @todo Define visibility
122 */
123 public $myClassName = 'gifbuilder';
124
125 /**
126 * @todo Define visibility
127 */
128 public $charRangeMap = array();
129
130 /**
131 * Initialization of the GIFBUILDER objects, in particular TEXT and IMAGE. This includes finding the bounding box, setting dimensions and offset values before the actual rendering is started.
132 * Modifies the ->setup, ->objBB internal arrays
133 * Should be called after the ->init() function which initializes the parent class functions/variables in general.
134 * The class tslib_gmenu also uses gifbuilder and here there is an interesting use since the function findLargestDims() from that class calls the init() and start() functions to find the total dimensions before starting the rendering of the images.
135 *
136 * @param array $conf TypoScript properties for the GIFBUILDER session. Stored internally in the variable ->setup
137 * @param array $data The current data record from tslib_cObj. Stored internally in the variable ->data
138 * @return void
139 * @see tslib_cObj::getImgResource(), tslib_gmenu::makeGifs(), tslib_gmenu::findLargestDims()
140 * @todo Define visibility
141 */
142 public function start($conf, $data) {
143 if (is_array($conf)) {
144 $this->setup = $conf;
145 $this->data = $data;
146 $this->cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
147 $this->cObj->start($this->data);
148 // Hook preprocess gifbuilder conf
149 // Added by Julle for 3.8.0
150 //
151 // Let's you pre-process the gifbuilder configuration. for
152 // example you can split a string up into lines and render each
153 // line as TEXT obj, see extension julle_gifbconf
154 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess'])) {
155 foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess'] as $_funcRef) {
156 $_params = $this->setup;
157 $this->setup = \TYPO3\CMS\Core\Utility\GeneralUtility::callUserFunction($_funcRef, $_params, $this);
158 }
159 }
160 // Initializing global Char Range Map
161 $this->charRangeMap = array();
162 if (is_array($GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'])) {
163 foreach ($GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'] as $cRMcfgkey => $cRMcfg) {
164 if (is_array($cRMcfg)) {
165 // Initializing:
166 $cRMkey = $GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'][substr($cRMcfgkey, 0, -1)];
167 $this->charRangeMap[$cRMkey] = array();
168 $this->charRangeMap[$cRMkey]['charMapConfig'] = $cRMcfg['charMapConfig.'];
169 $this->charRangeMap[$cRMkey]['cfgKey'] = substr($cRMcfgkey, 0, -1);
170 $this->charRangeMap[$cRMkey]['multiplicator'] = (double) $cRMcfg['fontSizeMultiplicator'];
171 $this->charRangeMap[$cRMkey]['pixelSpace'] = intval($cRMcfg['pixelSpaceFontSizeRef']);
172 }
173 }
174 }
175 // Getting sorted list of TypoScript keys from setup.
176 $sKeyArray = \TYPO3\CMS\Core\TypoScript\TemplateService::sortedKeyList($this->setup);
177 // Setting the background color, passing it through stdWrap
178 if ($conf['backColor.'] || $conf['backColor']) {
179 $this->setup['backColor'] = isset($this->setup['backColor.']) ? trim($this->cObj->stdWrap($this->setup['backColor'], $this->setup['backColor.'])) : $this->setup['backColor'];
180 }
181 if (!$this->setup['backColor']) {
182 $this->setup['backColor'] = 'white';
183 }
184 if ($conf['transparentColor.'] || $conf['transparentColor']) {
185 $this->setup['transparentColor_array'] = isset($this->setup['transparentColor.']) ? explode('|', trim($this->cObj->stdWrap($this->setup['transparentColor'], $this->setup['transparentColor.']))) : explode('|', trim($this->setup['transparentColor']));
186 }
187 if (isset($this->setup['transparentBackground.'])) {
188 $this->setup['transparentBackground'] = $this->cObj->stdWrap($this->setup['transparentBackground'], $this->setup['transparentBackground.']);
189 }
190 if (isset($this->setup['reduceColors.'])) {
191 $this->setup['reduceColors'] = $this->cObj->stdWrap($this->setup['reduceColors'], $this->setup['reduceColors.']);
192 }
193 // Set default dimensions
194 if (isset($this->setup['XY.'])) {
195 $this->setup['XY'] = $this->cObj->stdWrap($this->setup['XY'], $this->setup['XY.']);
196 }
197 if (!$this->setup['XY']) {
198 $this->setup['XY'] = '120,50';
199 }
200 // Checking TEXT and IMAGE objects for files. If any errors the objects are cleared.
201 // The Bounding Box for the objects is stored in an array
202 foreach ($sKeyArray as $theKey) {
203 $theValue = $this->setup[$theKey];
204 if (intval($theKey) && ($conf = $this->setup[$theKey . '.'])) {
205 // Swipes through TEXT and IMAGE-objects
206 switch ($theValue) {
207 case 'TEXT':
208 if ($this->setup[$theKey . '.'] = $this->checkTextObj($conf)) {
209 // Adjust font width if max size is set:
210 $maxWidth = isset($this->setup[$theKey . '.']['maxWidth.']) ? $this->cObj->stdWrap($this->setup[$theKey . '.']['maxWidth'], $this->setup[$theKey . '.']['maxWidth.']) : $this->setup[$theKey . '.']['maxWidth'];
211 if ($maxWidth) {
212 $this->setup[$theKey . '.']['fontSize'] = $this->fontResize($this->setup[$theKey . '.']);
213 }
214 // Calculate bounding box:
215 $txtInfo = $this->calcBBox($this->setup[$theKey . '.']);
216 $this->setup[$theKey . '.']['BBOX'] = $txtInfo;
217 $this->objBB[$theKey] = $txtInfo;
218 $this->setup[$theKey . '.']['imgMap'] = 0;
219 }
220 break;
221 case 'IMAGE':
222 $fileInfo = $this->getResource($conf['file'], $conf['file.']);
223 if ($fileInfo) {
224 $this->combinedFileNames[] = preg_replace('/\\.[[:alnum:]]+$/', '', basename($fileInfo[3]));
225 $this->setup[$theKey . '.']['file'] = $fileInfo[3];
226 $this->setup[$theKey . '.']['BBOX'] = $fileInfo;
227 $this->objBB[$theKey] = $fileInfo;
228 if ($conf['mask']) {
229 $maskInfo = $this->getResource($conf['mask'], $conf['mask.']);
230 if ($maskInfo) {
231 $this->setup[$theKey . '.']['mask'] = $maskInfo[3];
232 } else {
233 $this->setup[$theKey . '.']['mask'] = '';
234 }
235 }
236 } else {
237 unset($this->setup[$theKey . '.']);
238 }
239 break;
240 }
241 // Checks if disabled is set... (this is also done in menu.php / imgmenu!!)
242 if ($conf['if.']) {
243 $cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
244 $cObj->start($this->data);
245 if (!$cObj->checkIf($conf['if.'])) {
246 unset($this->setup[$theKey]);
247 unset($this->setup[$theKey . '.']);
248 }
249 }
250 }
251 }
252 // Calculate offsets on elements
253 $this->setup['XY'] = $this->calcOffset($this->setup['XY']);
254 if (isset($this->setup['offset.'])) {
255 $this->setup['offset'] = $this->cObj->stdWrap($this->setup['offset'], $this->setup['offset.']);
256 }
257 $this->setup['offset'] = $this->calcOffset($this->setup['offset']);
258 if (isset($this->setup['workArea.'])) {
259 $this->setup['workArea'] = $this->cObj->stdWrap($this->setup['workArea'], $this->setup['workArea.']);
260 }
261 $this->setup['workArea'] = $this->calcOffset($this->setup['workArea']);
262 foreach ($sKeyArray as $theKey) {
263 $theValue = $this->setup[$theKey];
264 if (intval($theKey) && ($conf = $this->setup[$theKey . '.'])) {
265 switch ($theValue) {
266 case 'TEXT':
267
268 case 'IMAGE':
269 if (isset($this->setup[$theKey . '.']['offset.'])) {
270 $this->setup[$theKey . '.']['offset'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['offset'], $this->setup[$theKey . '.']['offset.']);
271 }
272 if ($this->setup[$theKey . '.']['offset']) {
273 $this->setup[$theKey . '.']['offset'] = $this->calcOffset($this->setup[$theKey . '.']['offset']);
274 }
275 break;
276 case 'BOX':
277
278 case 'ELLIPSE':
279 if (isset($this->setup[$theKey . '.']['dimensions.'])) {
280 $this->setup[$theKey . '.']['dimensions'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['dimensions'], $this->setup[$theKey . '.']['dimensions.']);
281 }
282 if ($this->setup[$theKey . '.']['dimensions']) {
283 $this->setup[$theKey . '.']['dimensions'] = $this->calcOffset($this->setup[$theKey . '.']['dimensions']);
284 }
285 break;
286 case 'WORKAREA':
287 if (isset($this->setup[$theKey . '.']['set.'])) {
288 $this->setup[$theKey . '.']['set'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['set'], $this->setup[$theKey . '.']['set.']);
289 }
290 if ($this->setup[$theKey . '.']['set']) {
291 $this->setup[$theKey . '.']['set'] = $this->calcOffset($this->setup[$theKey . '.']['set']);
292 }
293 break;
294 case 'CROP':
295 if (isset($this->setup[$theKey . '.']['crop.'])) {
296 $this->setup[$theKey . '.']['crop'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['crop'], $this->setup[$theKey . '.']['crop.']);
297 }
298 if ($this->setup[$theKey . '.']['crop']) {
299 $this->setup[$theKey . '.']['crop'] = $this->calcOffset($this->setup[$theKey . '.']['crop']);
300 }
301 break;
302 case 'SCALE':
303 if (isset($this->setup[$theKey . '.']['width.'])) {
304 $this->setup[$theKey . '.']['width'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['width'], $this->setup[$theKey . '.']['width.']);
305 }
306 if ($this->setup[$theKey . '.']['width']) {
307 $this->setup[$theKey . '.']['width'] = $this->calcOffset($this->setup[$theKey . '.']['width']);
308 }
309 if (isset($this->setup[$theKey . '.']['height.'])) {
310 $this->setup[$theKey . '.']['height'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['height'], $this->setup[$theKey . '.']['height.']);
311 }
312 if ($this->setup[$theKey . '.']['height']) {
313 $this->setup[$theKey . '.']['height'] = $this->calcOffset($this->setup[$theKey . '.']['height']);
314 }
315 break;
316 }
317 }
318 }
319 // Get trivial data
320 $XY = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $this->setup['XY']);
321 $maxWidth = isset($this->setup['maxWidth.']) ? intval($this->cObj->stdWrap($this->setup['maxWidth'], $this->setup['maxWidth.'])) : intval($this->setup['maxWidth']);
322 $maxHeight = isset($this->setup['maxHeight.']) ? intval($this->cObj->stdWrap($this->setup['maxHeight'], $this->setup['maxHeight.'])) : intval($this->setup['maxHeight']);
323 $XY[0] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($XY[0], 1, $maxWidth ? $maxWidth : 2000);
324 $XY[1] = \TYPO3\CMS\Core\Utility\MathUtility::forceIntegerInRange($XY[1], 1, $maxHeight ? $maxHeight : 2000);
325 $this->XY = $XY;
326 $this->w = $XY[0];
327 $this->h = $XY[1];
328 $this->OFFSET = \TYPO3\CMS\Core\Utility\GeneralUtility::intExplode(',', $this->setup['offset']);
329 // this sets the workArea
330 $this->setWorkArea($this->setup['workArea']);
331 // this sets the default to the current;
332 $this->defaultWorkArea = $this->workArea;
333 }
334 }
335
336 /**
337 * Initiates the image file generation if ->setup is TRUE and if the file did not exist already.
338 * Gets filename from fileName() and if file exists in typo3temp/ dir it will - of course - not be rendered again.
339 * Otherwise rendering means calling ->make(), then ->output(), then ->destroy()
340 *
341 * @return string The filename for the created GIF/PNG file. The filename will be prefixed "GB_
342 * @see make(), fileName()
343 * @todo Define visibility
344 */
345 public function gifBuild() {
346 if ($this->setup) {
347 // Relative to PATH_site
348 $gifFileName = $this->fileName('GB/');
349 // File exists
350 if (!file_exists($gifFileName)) {
351 // Create temporary directory if not done:
352 $this->createTempSubDir('GB/');
353 // Create file:
354 $this->make();
355 $this->output($gifFileName);
356 $this->destroy();
357 }
358 return $gifFileName;
359 }
360 }
361
362 /**
363 * The actual rendering of the image file.
364 * Basically sets the dimensions, the background color, the traverses the array of GIFBUILDER objects and finally setting the transparent color if defined.
365 * Creates a GDlib resource in $this->im and works on that
366 * Called by gifBuild()
367 *
368 * @return void
369 * @access private
370 * @see gifBuild()
371 * @todo Define visibility
372 */
373 public function make() {
374 // Get trivial data
375 $XY = $this->XY;
376 // Reset internal properties
377 $this->saveAlphaLayer = FALSE;
378 // Gif-start
379 $this->im = imagecreatetruecolor($XY[0], $XY[1]);
380 $this->w = $XY[0];
381 $this->h = $XY[1];
382 // Transparent layer as background if set and requirements are met
383 if (!empty($this->setup['backColor']) && $this->setup['backColor'] === 'transparent' && $this->png_truecolor && !$this->setup['reduceColors'] && (empty($this->setup['format']) || $this->setup['format'] === 'png')) {
384 // Set transparency properties
385 imagesavealpha($this->im, TRUE);
386 // Fill with a transparent background
387 $transparentColor = imagecolorallocatealpha($this->im, 0, 0, 0, 127);
388 imagefill($this->im, 0, 0, $transparentColor);
389 // Set internal properties to keep the transparency over the rendering process
390 $this->saveAlphaLayer = TRUE;
391 // Force PNG in case no format is set
392 $this->setup['format'] = 'png';
393 } else {
394 // Fill the background with the given color
395 $BGcols = $this->convertColor($this->setup['backColor']);
396 $Bcolor = ImageColorAllocate($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
397 ImageFilledRectangle($this->im, 0, 0, $XY[0], $XY[1], $Bcolor);
398 }
399 // Traverse the GIFBUILDER objects an render each one:
400 if (is_array($this->setup)) {
401 $sKeyArray = \TYPO3\CMS\Core\TypoScript\TemplateService::sortedKeyList($this->setup);
402 foreach ($sKeyArray as $theKey) {
403 $theValue = $this->setup[$theKey];
404 if (intval($theKey) && ($conf = $this->setup[$theKey . '.'])) {
405 $isStdWrapped = array();
406 foreach ($conf as $key => $value) {
407 $parameter = rtrim($key, '.');
408 if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
409 $conf[$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
410 $isStdWrapped[$parameter] = 1;
411 }
412 }
413 switch ($theValue) {
414 case 'IMAGE':
415 if ($conf['mask']) {
416 $this->maskImageOntoImage($this->im, $conf, $this->workArea);
417 } else {
418 $this->copyImageOntoImage($this->im, $conf, $this->workArea);
419 }
420 break;
421 case 'TEXT':
422 if (!$conf['hide']) {
423 if (is_array($conf['shadow.'])) {
424 $isStdWrapped = array();
425 foreach ($conf['shadow.'] as $key => $value) {
426 $parameter = rtrim($key, '.');
427 if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
428 $conf['shadow.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
429 $isStdWrapped[$parameter] = 1;
430 }
431 }
432 $this->makeShadow($this->im, $conf['shadow.'], $this->workArea, $conf);
433 }
434 if (is_array($conf['emboss.'])) {
435 $isStdWrapped = array();
436 foreach ($conf['emboss.'] as $key => $value) {
437 $parameter = rtrim($key, '.');
438 if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
439 $conf['emboss.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
440 $isStdWrapped[$parameter] = 1;
441 }
442 }
443 $this->makeEmboss($this->im, $conf['emboss.'], $this->workArea, $conf);
444 }
445 if (is_array($conf['outline.'])) {
446 $isStdWrapped = array();
447 foreach ($conf['outline.'] as $key => $value) {
448 $parameter = rtrim($key, '.');
449 if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
450 $conf['outline.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
451 $isStdWrapped[$parameter] = 1;
452 }
453 }
454 $this->makeOutline($this->im, $conf['outline.'], $this->workArea, $conf);
455 }
456 $conf['imgMap'] = 1;
457 $this->makeText($this->im, $conf, $this->workArea);
458 }
459 break;
460 case 'OUTLINE':
461 if ($this->setup[$conf['textObjNum']] == 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
462 $this->makeOutline($this->im, $conf, $this->workArea, $txtConf);
463 }
464 break;
465 case 'EMBOSS':
466 if ($this->setup[$conf['textObjNum']] == 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
467 $this->makeEmboss($this->im, $conf, $this->workArea, $txtConf);
468 }
469 break;
470 case 'SHADOW':
471 if ($this->setup[$conf['textObjNum']] == 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
472 $this->makeShadow($this->im, $conf, $this->workArea, $txtConf);
473 }
474 break;
475 case 'BOX':
476 $this->makeBox($this->im, $conf, $this->workArea);
477 break;
478 case 'EFFECT':
479 $this->makeEffect($this->im, $conf);
480 break;
481 case 'ADJUST':
482 $this->adjust($this->im, $conf);
483 break;
484 case 'CROP':
485 $this->crop($this->im, $conf);
486 break;
487 case 'SCALE':
488 $this->scale($this->im, $conf);
489 break;
490 case 'WORKAREA':
491 if ($conf['set']) {
492 // this sets the workArea
493 $this->setWorkArea($conf['set']);
494 }
495 if (isset($conf['clear'])) {
496 // This sets the current to the default;
497 $this->workArea = $this->defaultWorkArea;
498 }
499 break;
500 case 'ELLIPSE':
501 $this->makeEllipse($this->im, $conf, $this->workArea);
502 break;
503 }
504 }
505 }
506 }
507 // Preserve alpha transparency
508 if (!$this->saveAlphaLayer) {
509 if ($this->setup['transparentBackground']) {
510 // Auto transparent background is set
511 $Bcolor = ImageColorClosest($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
512 imagecolortransparent($this->im, $Bcolor);
513 } elseif (is_array($this->setup['transparentColor_array'])) {
514 // Multiple transparent colors are set. This is done via the trick that all transparent colors get
515 // converted to one color and then this one gets set as transparent as png/gif can just have one
516 // transparent color.
517 $Tcolor = $this->unifyColors($this->im, $this->setup['transparentColor_array'], intval($this->setup['transparentColor.']['closest']));
518 if ($Tcolor >= 0) {
519 imagecolortransparent($this->im, $Tcolor);
520 }
521 }
522 }
523 }
524
525 /*********************************************
526 *
527 * Various helper functions
528 *
529 ********************************************/
530 /**
531 * Initializing/Cleaning of TypoScript properties for TEXT GIFBUILDER objects
532 *
533 * 'cleans' TEXT-object; Checks fontfile and other vital setup
534 * Finds the title if its a 'variable' (instantiates a cObj and loads it with the ->data record)
535 * Performs caseshift if any.
536 *
537 * @param array $conf GIFBUILDER object TypoScript properties
538 * @return array Modified $conf array IF the "text" property is not blank
539 * @access private
540 * @todo Define visibility
541 */
542 public function checkTextObj($conf) {
543 $cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
544 $cObj->start($this->data);
545 $isStdWrapped = array();
546 foreach ($conf as $key => $value) {
547 $parameter = rtrim($key, '.');
548 if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
549 $conf[$parameter] = $cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
550 $isStdWrapped[$parameter] = 1;
551 }
552 }
553 $conf['fontFile'] = $this->checkFile($conf['fontFile']);
554 if (!$conf['fontFile']) {
555 $conf['fontFile'] = 't3lib/fonts/nimbus.ttf';
556 }
557 if (!$conf['iterations']) {
558 $conf['iterations'] = 1;
559 }
560 if (!$conf['fontSize']) {
561 $conf['fontSize'] = 12;
562 }
563 // If any kind of spacing applys, we cannot use angles!!
564 if ($conf['spacing'] || $conf['wordSpacing']) {
565 $conf['angle'] = 0;
566 }
567 if (!isset($conf['antiAlias'])) {
568 $conf['antiAlias'] = 1;
569 }
570 $conf['fontColor'] = trim($conf['fontColor']);
571 // Strip HTML
572 if (!$conf['doNotStripHTML']) {
573 $conf['text'] = strip_tags($conf['text']);
574 }
575 $this->combinedTextStrings[] = strip_tags($conf['text']);
576 // Max length = 100 if automatic line braks are not defined:
577 if (!isset($conf['breakWidth']) || !$conf['breakWidth']) {
578 $tlen = intval($conf['textMaxLength']) ? intval($conf['textMaxLength']) : 100;
579 if ($this->nativeCharset) {
580 $conf['text'] = $this->csConvObj->substr($this->nativeCharset, $conf['text'], 0, $tlen);
581 } else {
582 $conf['text'] = substr($conf['text'], 0, $tlen);
583 }
584 }
585 if ((string) $conf['text'] != '') {
586 // Char range map thingie:
587 $fontBaseName = basename($conf['fontFile']);
588 if (is_array($this->charRangeMap[$fontBaseName])) {
589 // Initialize splitRendering array:
590 if (!is_array($conf['splitRendering.'])) {
591 $conf['splitRendering.'] = array();
592 }
593 $cfgK = $this->charRangeMap[$fontBaseName]['cfgKey'];
594 // Do not impose settings if a splitRendering object already exists:
595 if (!isset($conf['splitRendering.'][$cfgK])) {
596 // Set configuration:
597 $conf['splitRendering.'][$cfgK] = 'charRange';
598 $conf['splitRendering.'][$cfgK . '.'] = $this->charRangeMap[$fontBaseName]['charMapConfig'];
599 // Multiplicator of fontsize:
600 if ($this->charRangeMap[$fontBaseName]['multiplicator']) {
601 $conf['splitRendering.'][$cfgK . '.']['fontSize'] = round($conf['fontSize'] * $this->charRangeMap[$fontBaseName]['multiplicator']);
602 }
603 // Multiplicator of pixelSpace:
604 if ($this->charRangeMap[$fontBaseName]['pixelSpace']) {
605 $travKeys = array('xSpaceBefore', 'xSpaceAfter', 'ySpaceBefore', 'ySpaceAfter');
606 foreach ($travKeys as $pxKey) {
607 if (isset($conf['splitRendering.'][$cfgK . '.'][$pxKey])) {
608 $conf['splitRendering.'][$cfgK . '.'][$pxKey] = round($conf['splitRendering.'][($cfgK . '.')][$pxKey] * ($conf['fontSize'] / $this->charRangeMap[$fontBaseName]['pixelSpace']));
609 }
610 }
611 }
612 }
613 }
614 if (is_array($conf['splitRendering.'])) {
615 foreach ($conf['splitRendering.'] as $key => $value) {
616 if (is_array($conf['splitRendering.'][$key])) {
617 if (isset($conf['splitRendering.'][$key]['fontFile'])) {
618 $conf['splitRendering.'][$key]['fontFile'] = $this->checkFile($conf['splitRendering.'][$key]['fontFile']);
619 }
620 }
621 }
622 }
623 return $conf;
624 }
625 }
626
627 /**
628 * Calculation of offset using "splitCalc" and insertion of dimensions from other GIFBUILDER objects.
629 *
630 * Example:
631 * Input: 2+2, 2*3, 123, [10.w]
632 * Output: 4,6,123,45 (provided that the width of object in position 10 was 45 pixels wide)
633 *
634 * @param string $string The string to resolve/calculate the result of. The string is divided by a comma first and each resulting part is calculated into an integer.
635 * @return string The resolved string with each part (separated by comma) returned separated by comma
636 * @access private
637 * @todo Define visibility
638 */
639 public function calcOffset($string) {
640 $value = array();
641 $numbers = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->calculateFunctions($string));
642 foreach ($numbers as $key => $val) {
643 if ((string) $val == (string) intval($val)) {
644 $value[$key] = intval($val);
645 } else {
646 $value[$key] = $this->calculateValue($val);
647 }
648 }
649 $string = implode(',', $value);
650 return $string;
651 }
652
653 /**
654 * Returns an "imgResource" creating an instance of the tslib_cObj class and calling tslib_cObj::getImgResource
655 *
656 * @param string $file Filename value OR the string "GIFBUILDER", see documentation in TSref for the "datatype" called "imgResource
657 * @param array $fileArray TypoScript properties passed to the function. Either GIFBUILDER properties or imgResource properties, depending on the value of $file (whether that is "GIFBUILDER" or a file reference)
658 * @return array Returns an array with file information if an image was returned. Otherwise FALSE.
659 * @access private
660 * @see tslib_cObj::getImgResource()
661 * @todo Define visibility
662 */
663 public function getResource($file, $fileArray) {
664 if (!\TYPO3\CMS\Core\Utility\GeneralUtility::inList($this->imageFileExt, $fileArray['ext'])) {
665 $fileArray['ext'] = $this->gifExtension;
666 }
667 $cObj = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Frontend\\ContentObject\\ContentObjectRenderer');
668 $cObj->start($this->data);
669 return $cObj->getImgResource($file, $fileArray);
670 }
671
672 /**
673 * Returns the reference to a "resource" in TypoScript.
674 *
675 * @param string $file The resource value.
676 * @return string Returns the relative filepath
677 * @access private
678 * @see t3lib_TStemplate::getFileName()
679 * @todo Define visibility
680 */
681 public function checkFile($file) {
682 return $GLOBALS['TSFE']->tmpl->getFileName($file);
683 }
684
685 /**
686 * Calculates the GIFBUILDER output filename/path based on a serialized, hashed value of this->setup
687 *
688 * @param string $pre Filename prefix, eg. "GB_
689 * @return string The relative filepath (relative to PATH_site)
690 * @access private
691 * @todo Define visibility
692 */
693 public function fileName($pre) {
694 $meaningfulPrefix = '';
695 if ($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']) {
696 /** @var $basicFileFunctions \TYPO3\CMS\Core\Utility\File\BasicFileUtility */
697 $basicFileFunctions = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Utility\\File\\BasicFileUtility');
698 $meaningfulPrefix = implode('_', array_merge($this->combinedTextStrings, $this->combinedFileNames));
699 $meaningfulPrefix = $basicFileFunctions->cleanFileName($meaningfulPrefix);
700 $meaningfulPrefixLength = intval($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']);
701 if ($GLOBALS['TYPO3_CONF_VARS']['SYS']['UTF8filesystem']) {
702 /** @var $t3libCsInstance \TYPO3\CMS\Core\Charset\CharsetConverter */
703 $t3libCsInstance = \TYPO3\CMS\Core\Utility\GeneralUtility::makeInstance('TYPO3\\CMS\\Core\\Charset\\CharsetConverter');
704 $meaningfulPrefix = $t3libCsInstance->substr('utf-8', $meaningfulPrefix, 0, $meaningfulPrefixLength);
705 } else {
706 $meaningfulPrefix = substr($meaningfulPrefix, 0, $meaningfulPrefixLength);
707 }
708 $meaningfulPrefix .= '_';
709 }
710 // WARNING: In PHP5 I discovered that rendering with freetype of Japanese letters was totally corrupt.
711 // Not only the wrong glyphs are printed but also some memory stack overflow resulted in strange additional
712 // chars - and finally the reason for this investigation: The Bounding box data was changing all the time
713 // resulting in new images being generated all the time. With PHP4 it works fine.
714 return $this->tempPath . $pre . $meaningfulPrefix . \TYPO3\CMS\Core\Utility\GeneralUtility::shortMD5(serialize($this->setup)) . '.' . $this->extension();
715 }
716
717 /**
718 * Returns the file extension used in the filename
719 *
720 * @return string Extension; "jpg" or "gif"/"png
721 * @access private
722 * @todo Define visibility
723 */
724 public function extension() {
725 switch (strtolower($this->setup['format'])) {
726 case 'jpg':
727
728 case 'jpeg':
729 return 'jpg';
730 break;
731 case 'png':
732 return 'png';
733 break;
734 case 'gif':
735 return 'gif';
736 break;
737 default:
738 return $this->gifExtension;
739 break;
740 }
741 }
742
743 /**
744 * Calculates the value concerning the dimensions of objects.
745 *
746 * @param string $string The string to be calculated (e.g. "[20.h]+13")
747 * @return integer The calculated value (e.g. "23")
748 * @see calcOffset()
749 */
750 protected function calculateValue($string) {
751 $calculatedValue = 0;
752 $parts = \TYPO3\CMS\Core\Utility\GeneralUtility::splitCalc($string, '+-*/%');
753 foreach ($parts as $part) {
754 $theVal = $part[1];
755 $sign = $part[0];
756 if ((string) intval($theVal) == (string) $theVal) {
757 $theVal = intval($theVal);
758 } elseif ('[' . substr($theVal, 1, -1) . ']' == $theVal) {
759 $objParts = explode('.', substr($theVal, 1, -1));
760 $theVal = 0;
761 if (isset($this->objBB[$objParts[0]])) {
762 if ($objParts[1] == 'w') {
763 $theVal = $this->objBB[$objParts[0]][0];
764 } elseif ($objParts[1] == 'h') {
765 $theVal = $this->objBB[$objParts[0]][1];
766 } elseif ($objParts[1] == 'lineHeight') {
767 $theVal = $this->objBB[$objParts[0]][2]['lineHeight'];
768 }
769 $theVal = intval($theVal);
770 }
771 } elseif (floatval($theVal)) {
772 $theVal = floatval($theVal);
773 } else {
774 $theVal = 0;
775 }
776 if ($sign == '-') {
777 $calculatedValue -= $theVal;
778 } elseif ($sign == '+') {
779 $calculatedValue += $theVal;
780 } elseif ($sign == '/' && $theVal) {
781 $calculatedValue = $calculatedValue / $theVal;
782 } elseif ($sign == '*') {
783 $calculatedValue = $calculatedValue * $theVal;
784 } elseif ($sign == '%' && $theVal) {
785 $calculatedValue %= $theVal;
786 }
787 }
788 return round($calculatedValue);
789 }
790
791 /**
792 * Calculates special functions:
793 * + max([10.h], [20.h]) -> gets the maximum of the given values
794 *
795 * @param string $string The raw string with functions to be calculated
796 * @return string The calculated values
797 */
798 protected function calculateFunctions($string) {
799 if (preg_match_all('#max\\(([^)]+)\\)#', $string, $matches)) {
800 foreach ($matches[1] as $index => $maxExpression) {
801 $string = str_replace($matches[0][$index], $this->calculateMaximum($maxExpression), $string);
802 }
803 }
804 return $string;
805 }
806
807 /**
808 * Calculates the maximum of a set of values defined like "[10.h],[20.h],1000"
809 *
810 * @param string $string The string to be used to calculate the maximum (e.g. "[10.h],[20.h],1000")
811 * @return integer The maxium value of the given comma separated and calculated values
812 */
813 protected function calculateMaximum($string) {
814 $parts = \TYPO3\CMS\Core\Utility\GeneralUtility::trimExplode(',', $this->calcOffset($string), TRUE);
815 $maximum = count($parts) ? max($parts) : 0;
816 return $maximum;
817 }
818
819 }
820
821
822 ?>