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