Fixed bug #17663: Remove deprecated reduceColors() from t3lib_stdGraphic
[Packages/TYPO3.CMS.git] / typo3 / sysext / cms / tslib / class.tslib_gifbuilder.php
1 <?php
2 /***************************************************************
3 * Copyright notice
4 *
5 * (c) 1999-2011 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 */
101 class tslib_gifBuilder extends t3lib_stdGraphic {
102
103 // Internal
104 var $im = ''; // the main image
105 var $w = 0; // the image-width
106 var $h = 0; // the image-height
107 var $map; // map-data
108 var $workArea;
109 var $setup = Array (); // This holds the operational setup for gifbuilder. Basically this is a TypoScript array with properties.
110 var $combinedTextStrings = array(); // Contains all text strings used on this image
111 var $combinedFileNames = array(); // Contains all filenames (basename without extension) used on this image
112 var $data = Array(); // This is the array from which data->field: [key] is fetched. So this is the current record!
113 var $objBB = Array();
114 var $myClassName = 'gifbuilder';
115 var $charRangeMap=array();
116
117 /**
118 * 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.
119 * Modifies the ->setup, ->objBB internal arrays
120 * Should be called after the ->init() function which initializes the parent class functions/variables in general.
121 * 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.
122 *
123 * @param array TypoScript properties for the GIFBUILDER session. Stored internally in the variable ->setup
124 * @param array The current data record from tslib_cObj. Stored internally in the variable ->data
125 * @return void
126 * @see tslib_cObj::getImgResource(), tslib_gmenu::makeGifs(), tslib_gmenu::findLargestDims()
127 */
128 function start($conf,$data) {
129
130 if (is_array($conf)) {
131 $this->setup = $conf;
132 $this->data = $data;
133 $this->cObj =t3lib_div::makeInstance('tslib_cObj');
134 $this->cObj->start($this->data);
135
136
137 /* Hook preprocess gifbuilder conf
138 * Added by Julle for 3.8.0
139 *
140 * Let's you pre-process the gifbuilder configuration. for
141 * example you can split a string up into lines and render each
142 * line as TEXT obj, see extension julle_gifbconf
143 */
144
145 if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess'])) {
146 foreach($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess'] as $_funcRef) {
147 $_params = $this->setup;
148 $this->setup = t3lib_div::callUserFunction($_funcRef,$_params,$this);
149 }
150 }
151
152 // Initializing global Char Range Map
153 $this->charRangeMap = array();
154 if (is_array($GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'])) {
155 foreach($GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'] as $cRMcfgkey => $cRMcfg) {
156 if (is_array($cRMcfg)) {
157
158 // Initializing:
159 $cRMkey = $GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'][substr($cRMcfgkey,0,-1)];
160 $this->charRangeMap[$cRMkey] = array();
161 $this->charRangeMap[$cRMkey]['charMapConfig'] = $cRMcfg['charMapConfig.'];
162 $this->charRangeMap[$cRMkey]['cfgKey'] = substr($cRMcfgkey,0,-1);
163 $this->charRangeMap[$cRMkey]['multiplicator'] = (double)$cRMcfg['fontSizeMultiplicator'];
164 $this->charRangeMap[$cRMkey]['pixelSpace'] = intval($cRMcfg['pixelSpaceFontSizeRef']);
165 }
166 }
167 }
168
169 // Getting sorted list of TypoScript keys from setup.
170 $sKeyArray=t3lib_TStemplate::sortedKeyList($this->setup);
171
172 // Setting the background color, passing it through stdWrap
173 if ($conf['backColor.'] || $conf['backColor']) {
174 $this->setup['backColor'] = isset($this->setup['backColor.'])
175 ? trim($this->cObj->stdWrap($this->setup['backColor'], $this->setup['backColor.']))
176 : $this->setup['backColor'];
177 }
178 if (!$this->setup['backColor']) { $this->setup['backColor']='white'; }
179
180 if ($conf['transparentColor.'] || $conf['transparentColor']) {
181 $this->setup['transparentColor_array'] = isset($this->setup['transparentColor.'])
182 ? explode('|', trim($this->cObj->stdWrap($this->setup['transparentColor'], $this->setup['transparentColor.'])))
183 : explode('|', trim($this->setup['transparentColor']));
184 }
185
186 if(isset($this->setup['transparentBackground.'])) {
187 $this->setup['transparentBackground'] = $this->cOjb->stdWrap($this->setup['transparentBackground'], $this->setup['transparentBackground.']);
188 }
189 if(isset($this->setup['reduceColors.'])) {
190 $this->setup['reduceColors'] = $this->cOjb->stdWrap($this->setup['reduceColors'], $this->setup['reduceColors.']);
191 }
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']) {$this->setup['XY']='120,50';}
198
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
205 if (intval($theKey) && $conf=$this->setup[$theKey.'.']) {
206 // Swipes through TEXT and IMAGE-objects
207 switch($theValue) {
208 case 'TEXT':
209 if ($this->setup[$theKey.'.'] = $this->checkTextObj($conf)) {
210
211 // Adjust font width if max size is set:
212 $maxWidth = isset($this->setup[$theKey.'.']['maxWidth.'])
213 ? $this->cObj->stdWrap($this->setup[$theKey.'.']['maxWidth'], $this->setup[$theKey.'.']['maxWidth.'])
214 : $this->setup[$theKey.'.']['maxWidth'];
215 if ($maxWidth) {
216 $this->setup[$theKey.'.']['fontSize'] = $this->fontResize($this->setup[$theKey.'.']); //RTF - this has to be done before calcBBox
217 }
218
219 // Calculate bounding box:
220 $txtInfo=$this->calcBBox($this->setup[$theKey.'.']);
221 $this->setup[$theKey.'.']['BBOX'] = $txtInfo;
222 $this->objBB[$theKey] = $txtInfo;
223 $this->setup[$theKey.'.']['imgMap'] = 0;
224 }
225 break;
226 case 'IMAGE':
227 $fileInfo = $this->getResource($conf['file'],$conf['file.']);
228 if ($fileInfo) {
229 $this->combinedFileNames[] = preg_replace('/\.[[:alnum:]]+$/','',basename($fileInfo[3]));
230 $this->setup[$theKey.'.']['file'] = $fileInfo[3];
231 $this->setup[$theKey.'.']['BBOX'] = $fileInfo;
232 $this->objBB[$theKey] = $fileInfo;
233 if ($conf['mask']) {
234 $maskInfo = $this->getResource($conf['mask'],$conf['mask.']);
235 if ($maskInfo) {
236 $this->setup[$theKey.'.']['mask'] = $maskInfo[3];
237 } else {
238 $this->setup[$theKey.'.']['mask'] = '';
239 }
240 }
241 } else {
242 unset($this->setup[$theKey.'.']);
243 }
244 break;
245 }
246 // Checks if disabled is set... (this is also done in menu.php / imgmenu!!)
247 if ($conf['if.']) {
248 $cObj =t3lib_div::makeInstance('tslib_cObj');
249 $cObj->start($this->data);
250
251 if (!$cObj->checkIf($conf['if.'])) {
252 unset($this->setup[$theKey]);
253 unset($this->setup[$theKey.'.']);
254 }
255 }
256 }
257 }
258
259 // Calculate offsets on elements
260 $this->setup['XY'] = $this->calcOffset($this->setup['XY']);
261
262 if(isset($this->setup['offset.'])) {
263 $this->setup['offset'] = $this->cObj->stdWrap($this->setup['offset'], $this->setup['offset.']);
264 }
265 $this->setup['offset'] = $this->calcOffset($this->setup['offset']);
266
267 if(isset($this->setup['workArea.'])) {
268 $this->setup['workArea'] = $this->cObj->stdWrap($this->setup['workArea'], $this->setup['workArea.']);
269 }
270 $this->setup['workArea'] = $this->calcOffset($this->setup['workArea']);
271
272 foreach ($sKeyArray as $theKey) {
273 $theValue=$this->setup[$theKey];
274
275 if (intval($theKey) && $conf=$this->setup[$theKey.'.']) {
276 switch($theValue) {
277 case 'TEXT':
278 case 'IMAGE':
279 if(isset($this->setup[$theKey.'.']['offset.'])) {
280 $this->setup[$theKey.'.']['offset'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['offset'], $this->setup[$theKey.'.']['offset.']);
281 }
282 if ($this->setup[$theKey.'.']['offset']) {
283 $this->setup[$theKey.'.']['offset'] = $this->calcOffset($this->setup[$theKey.'.']['offset']);
284 }
285 break;
286 case 'BOX':
287 case 'ELLIPSE':
288 if(isset($this->setup[$theKey.'.']['dimensions.'])) {
289 $this->setup[$theKey.'.']['dimensions'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['dimensions'], $this->setup[$theKey.'.']['dimensions.']);
290 }
291 if ($this->setup[$theKey.'.']['dimensions']) {
292 $this->setup[$theKey.'.']['dimensions'] = $this->calcOffset($this->setup[$theKey.'.']['dimensions']);
293 }
294 break;
295 case 'WORKAREA':
296 if(isset($this->setup[$theKey.'.']['set.'])) {
297 $this->setup[$theKey.'.']['set'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['set'], $this->setup[$theKey.'.']['set.']);
298 }
299 if ($this->setup[$theKey.'.']['set']) {
300 $this->setup[$theKey.'.']['set'] = $this->calcOffset($this->setup[$theKey.'.']['set']);
301 }
302 break;
303 case 'CROP':
304 if(isset($this->setup[$theKey.'.']['crop.'])) {
305 $this->setup[$theKey.'.']['crop'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['crop'], $this->setup[$theKey.'.']['crop.']);
306 }
307 if ($this->setup[$theKey.'.']['crop']) {
308 $this->setup[$theKey.'.']['crop'] = $this->calcOffset($this->setup[$theKey.'.']['crop']);
309 }
310 break;
311 case 'SCALE':
312 if(isset($this->setup[$theKey.'.']['width.'])) {
313 $this->setup[$theKey.'.']['width'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['width'], $this->setup[$theKey.'.']['width.']);
314 }
315 if ($this->setup[$theKey.'.']['width']) {
316 $this->setup[$theKey.'.']['width'] = $this->calcOffset($this->setup[$theKey.'.']['width']);
317 }
318 if(isset($this->setup[$theKey.'.']['height.'])) {
319 $this->setup[$theKey.'.']['height'] = $this->cObj->stdWrap($this->setup[$theKey.'.']['height'], $this->setup[$theKey.'.']['height.']);
320 }
321 if ($this->setup[$theKey.'.']['height']) {
322 $this->setup[$theKey.'.']['height'] = $this->calcOffset($this->setup[$theKey.'.']['height']);
323 }
324 break;
325 }
326 }
327 }
328 // Get trivial data
329 $XY = t3lib_div::intExplode(',',$this->setup['XY']);
330 $maxWidth = isset($this->setup['maxWidth.'])
331 ? intval($this->cObj->stdWrap($this->setup['maxWidth'], $this->setup['maxWidth.']))
332 : intval($this->setup['maxWidth']);
333 $maxHeight = isset($this->setup['maxHeight.'])
334 ? intval($this->cObj->stdWrap($this->setup['maxHeight'], $this->setup['maxHeight.']))
335 : intval($this->setup['maxHeight']);
336
337 $XY[0] = t3lib_div::intInRange($XY[0],1, $maxWidth?$maxWidth:2000);
338 $XY[1] = t3lib_div::intInRange($XY[1],1, $maxHeight?$maxHeight:2000);
339 $this->XY = $XY;
340 $this->w = $XY[0];
341 $this->h = $XY[1];
342 $this->OFFSET = t3lib_div::intExplode(',',$this->setup['offset']);
343
344 $this->setWorkArea($this->setup['workArea']); // this sets the workArea
345 $this->defaultWorkArea = $this->workArea; // this sets the default to the current;
346 }
347 }
348
349 /**
350 * Initiates the image file generation if ->setup is true and if the file did not exist already.
351 * Gets filename from fileName() and if file exists in typo3temp/ dir it will - of course - not be rendered again.
352 * Otherwise rendering means calling ->make(), then ->output(), then ->destroy()
353 *
354 * @return string The filename for the created GIF/PNG file. The filename will be prefixed "GB_"
355 * @see make(), fileName()
356 */
357 function gifBuild() {
358 if ($this->setup) {
359 $gifFileName = $this->fileName('GB/'); // Relative to PATH_site
360 if (!file_exists($gifFileName)) { // File exists
361
362 // Create temporary directory if not done:
363 $this->createTempSubDir('GB/');
364
365 // Create file:
366 $this->make();
367 $this->output($gifFileName);
368 $this->destroy();
369 }
370 return $gifFileName;
371 }
372 }
373
374 /**
375 * The actual rendering of the image file.
376 * Basically sets the dimensions, the background color, the traverses the array of GIFBUILDER objects and finally setting the transparent color if defined.
377 * Creates a GDlib resource in $this->im and works on that
378 * Called by gifBuild()
379 *
380 * @return void
381 * @access private
382 * @see gifBuild()
383 */
384 function make() {
385 // Get trivial data
386 $XY = $this->XY;
387
388 // Gif-start
389 $this->im = imagecreatetruecolor($XY[0], $XY[1]);
390 $this->w = $XY[0];
391 $this->h = $XY[1];
392
393 // backColor is set
394 $BGcols = $this->convertColor($this->setup['backColor']);
395 $Bcolor = ImageColorAllocate($this->im, $BGcols[0],$BGcols[1],$BGcols[2]);
396 ImageFilledRectangle($this->im, 0, 0, $XY[0], $XY[1], $Bcolor);
397
398 // Traverse the GIFBUILDER objects an render each one:
399 if (is_array($this->setup)) {
400 $sKeyArray=t3lib_TStemplate::sortedKeyList($this->setup);
401 foreach($sKeyArray as $theKey) {
402 $theValue=$this->setup[$theKey];
403 if (intval($theKey) && $conf=$this->setup[$theKey.'.']) {
404 $isStdWrapped = array();
405 foreach($conf as $key => $value) {
406 $parameter = rtrim($key,'.');
407 if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
408 $conf[$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
409 $isStdWrapped[$parameter] = 1;
410 }
411 }
412 switch($theValue) {
413 // Images
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
422 // Text
423 case 'TEXT':
424 if (!$conf['hide']) {
425 if (is_array($conf['shadow.'])) {
426 $isStdWrapped = array();
427 foreach($conf['shadow.'] as $key => $value) {
428 $parameter = rtrim($key,'.');
429 if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
430 $conf['shadow.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
431 $isStdWrapped[$parameter] = 1;
432 }
433 }
434 $this->makeShadow($this->im,$conf['shadow.'],$this->workArea,$conf);
435 }
436 if (is_array($conf['emboss.'])) {
437 $isStdWrapped = array();
438 foreach($conf['emboss.'] as $key => $value) {
439 $parameter = rtrim($key,'.');
440 if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
441 $conf['emboss.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
442 $isStdWrapped[$parameter] = 1;
443 }
444 }
445 $this->makeEmboss($this->im,$conf['emboss.'],$this->workArea,$conf);
446 }
447 if (is_array($conf['outline.'])) {
448 $isStdWrapped = array();
449 foreach($conf['outline.'] as $key => $value) {
450 $parameter = rtrim($key,'.');
451 if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
452 $conf['outline.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
453 $isStdWrapped[$parameter] = 1;
454 }
455 }
456 $this->makeOutline($this->im,$conf['outline.'],$this->workArea,$conf);
457 }
458 $conf['imgMap']=1;
459 $this->makeText($this->im,$conf,$this->workArea);
460 }
461 break;
462
463 // Text effects:
464 case 'OUTLINE':
465 if ($this->setup[$conf['textObjNum']]=='TEXT' && $txtConf=$this->checkTextObj($this->setup[$conf['textObjNum'].'.'])) {
466 $this->makeOutline($this->im,$conf,$this->workArea,$txtConf);
467 }
468 break;
469 case 'EMBOSS':
470 if ($this->setup[$conf['textObjNum']]=='TEXT' && $txtConf=$this->checkTextObj($this->setup[$conf['textObjNum'].'.'])) {
471 $this->makeEmboss($this->im,$conf,$this->workArea,$txtConf);
472 }
473 break;
474 case 'SHADOW':
475 if ($this->setup[$conf['textObjNum']]=='TEXT' && $txtConf=$this->checkTextObj($this->setup[$conf['textObjNum'].'.'])) {
476 $this->makeShadow($this->im,$conf,$this->workArea,$txtConf);
477 }
478 break;
479
480 // Other
481 case 'BOX':
482 $this->makeBox($this->im,$conf,$this->workArea);
483 break;
484 case 'EFFECT':
485 $this->makeEffect($this->im,$conf);
486 break;
487 case 'ADJUST':
488 $this->adjust($this->im,$conf);
489 break;
490 case 'CROP':
491 $this->crop($this->im,$conf);
492 break;
493 case 'SCALE':
494 $this->scale($this->im,$conf);
495 break;
496 case 'WORKAREA':
497 if ($conf['set']) {
498 $this->setWorkArea($conf['set']); // this sets the workArea
499 }
500 if (isset($conf['clear'])) {
501 $this->workArea = $this->defaultWorkArea; // this sets the current to the default;
502 }
503 break;
504 case 'ELLIPSE':
505 $this->makeEllipse($this->im, $conf, $this->workArea);
506 break;
507 }
508 }
509 }
510 }
511
512
513 if ($this->setup['transparentBackground']) {
514 // Auto transparent background is set
515 $Bcolor = ImageColorClosest($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
516 imagecolortransparent($this->im, $Bcolor);
517 } elseif (is_array($this->setup['transparentColor_array'])) {
518 // 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.
519 $Tcolor = $this->unifyColors($this->im, $this->setup['transparentColor_array'], intval($this->setup['transparentColor.']['closest']));
520 if ($Tcolor>=0) {
521 imagecolortransparent($this->im, $Tcolor);
522 }
523 }
524
525 }
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544 /*********************************************
545 *
546 * Various helper functions
547 *
548 ********************************************/
549
550
551 /**
552 * Initializing/Cleaning of TypoScript properties for TEXT GIFBUILDER objects
553 *
554 * 'cleans' TEXT-object; Checks fontfile and other vital setup
555 * Finds the title if its a 'variable' (instantiates a cObj and loads it with the ->data record)
556 * Performs caseshift if any.
557 *
558 * @param array GIFBUILDER object TypoScript properties
559 * @return array Modified $conf array IF the "text" property is not blank
560 * @access private
561 */
562 function checkTextObj($conf) {
563 $isStdWrapped = array();
564 foreach($conf as $key => $value) {
565 $parameter = rtrim($key,'.');
566 if(!$isStdWrapped[$parameter] && isset($conf[$parameter.'.'])) {
567 $conf[$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter.'.']);
568 $isStdWrapped[$parameter] = 1;
569 }
570 }
571 $conf['fontFile']=$this->checkFile($conf['fontFile']);
572 if (!$conf['fontFile']){$conf['fontFile']='t3lib/fonts/nimbus.ttf';}
573 if (!$conf['iterations']){$conf['iterations'] = 1;}
574 if (!$conf['fontSize']){$conf['fontSize']=12;}
575 if ($conf['spacing'] || $conf['wordSpacing']) { // If any kind of spacing applys, we cannot use angles!!
576 $conf['angle']=0;
577 }
578 if (!isset($conf['antiAlias'])){$conf['antiAlias']=1;}
579 $cObj =t3lib_div::makeInstance('tslib_cObj');
580 $cObj->start($this->data);
581
582 $conf['fontColor'] = trim($conf['fontColor']);
583 // Strip HTML
584 if (!$conf['doNotStripHTML']) {
585 $conf['text'] = strip_tags($conf['text']);
586 }
587 $this->combinedTextStrings[] = strip_tags($conf['text']);
588
589 // Max length = 100 if automatic line braks are not defined:
590 if (!isset($conf['breakWidth']) || !$conf['breakWidth']) {
591 $tlen = (intval($conf['textMaxLength']) ? intval($conf['textMaxLength']) : 100);
592 if ($this->nativeCharset) {
593 $conf['text'] = $this->csConvObj->substr($this->nativeCharset, $conf['text'], 0, $tlen);
594 } else {
595 $conf['text'] = substr($conf['text'], 0 , $tlen);
596 }
597 }
598 if ((string)$conf['text']!='') {
599
600 // Char range map thingie:
601 $fontBaseName = basename($conf['fontFile']);
602 if (is_array($this->charRangeMap[$fontBaseName])) {
603
604 // Initialize splitRendering array:
605 if (!is_array($conf['splitRendering.'])) {
606 $conf['splitRendering.'] = array();
607 }
608
609 $cfgK = $this->charRangeMap[$fontBaseName]['cfgKey'];
610 if (!isset($conf['splitRendering.'][$cfgK])) { // Do not impose settings if a splitRendering object already exists:
611 // Set configuration:
612 $conf['splitRendering.'][$cfgK] = 'charRange';
613 $conf['splitRendering.'][$cfgK.'.'] = $this->charRangeMap[$fontBaseName]['charMapConfig'];
614
615 // multiplicator of fontsize:
616 if ($this->charRangeMap[$fontBaseName]['multiplicator']) {
617 $conf['splitRendering.'][$cfgK.'.']['fontSize'] = round($conf['fontSize'] * $this->charRangeMap[$fontBaseName]['multiplicator']);
618 }
619 // multiplicator of pixelSpace:
620 if ($this->charRangeMap[$fontBaseName]['pixelSpace']) {
621 $travKeys = array('xSpaceBefore','xSpaceAfter','ySpaceBefore','ySpaceAfter');
622 foreach($travKeys as $pxKey) {
623 if (isset($conf['splitRendering.'][$cfgK.'.'][$pxKey])) {
624 $conf['splitRendering.'][$cfgK.'.'][$pxKey] = round($conf['splitRendering.'][$cfgK.'.'][$pxKey] * ($conf['fontSize'] / $this->charRangeMap[$fontBaseName]['pixelSpace']));
625 }
626 }
627 }
628 }
629 }
630 if (is_array($conf['splitRendering.'])) {
631 foreach($conf['splitRendering.'] as $key => $value) {
632 if (is_array($conf['splitRendering.'][$key])) {
633 if (isset($conf['splitRendering.'][$key]['fontFile'])) {
634 $conf['splitRendering.'][$key]['fontFile'] = $this->checkFile($conf['splitRendering.'][$key]['fontFile']);
635 }
636 }
637 }
638 }
639
640 return $conf;
641 }
642 }
643
644 /**
645 * Calculation of offset using "splitCalc" and insertion of dimensions from other GIFBUILDER objects.
646 *
647 * Example:
648 * Input: 2+2, 2*3, 123, [10.w]
649 * Output: 4,6,123,45 (provided that the width of object in position 10 was 45 pixels wide)
650 *
651 * @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.
652 * @return string The resolved string with each part (separated by comma) returned separated by comma
653 * @access private
654 */
655 function calcOffset($string) {
656 $value = array();
657 $numbers = t3lib_div::trimExplode(',', $this->calculateFunctions($string));
658
659 foreach ($numbers as $key => $val) {
660 if ((string)$val == (string)intval($val)) {
661 $value[$key] = intval($val);
662 } else {
663 $value[$key] = $this->calculateValue($val);
664 }
665 }
666
667 $string = implode(',', $value);
668 return $string;
669 }
670
671 /**
672 * Returns an "imgResource" creating an instance of the tslib_cObj class and calling tslib_cObj::getImgResource
673 *
674 * @param string Filename value OR the string "GIFBUILDER", see documentation in TSref for the "datatype" called "imgResource"
675 * @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)
676 * @return array Returns an array with file information if an image was returned. Otherwise false.
677 * @access private
678 * @see tslib_cObj::getImgResource()
679 */
680 function getResource($file,$fileArray) {
681 if (!t3lib_div::inList($this->imageFileExt, $fileArray['ext'])) {
682 $fileArray['ext'] = $this->gifExtension;
683 }
684 $cObj =t3lib_div::makeInstance('tslib_cObj');
685 $cObj->start($this->data);
686 return $cObj->getImgResource($file,$fileArray);
687 }
688
689 /**
690 * Returns the reference to a "resource" in TypoScript.
691 *
692 * @param string The resource value.
693 * @return string Returns the relative filepath
694 * @access private
695 * @see t3lib_TStemplate::getFileName()
696 */
697 function checkFile($file) {
698 return $GLOBALS['TSFE']->tmpl->getFileName($file);
699 }
700
701 /**
702 * Calculates the GIFBUILDER output filename/path based on a serialized, hashed value of this->setup
703 *
704 * @param string Filename prefix, eg. "GB_"
705 * @return string The relative filepath (relative to PATH_site)
706 * @access private
707 */
708 function fileName($pre) {
709
710 $meaningfulPrefix = '';
711
712 if ($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix']) {
713 /** @var $basicFileFunctions t3lib_basicFileFunctions */
714 $basicFileFunctions = t3lib_div::makeInstance('t3lib_basicFileFunctions');
715
716 $meaningfulPrefix = implode('_', array_merge($this->combinedTextStrings, $this->combinedFileNames));
717 $meaningfulPrefix = $basicFileFunctions->cleanFileName($meaningfulPrefix);
718 $meaningfulPrefix = substr($meaningfulPrefix, 0, intval($GLOBALS['TSFE']->config['config']['meaningfulTempFilePrefix'])) . '_';
719 }
720
721 // 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.
722 return $this->tempPath .
723 $pre .
724 $meaningfulPrefix .
725 t3lib_div::shortMD5(serialize($this->setup)) .
726 '.' . $this->extension();
727 }
728
729 /**
730 * Returns the file extension used in the filename
731 *
732 * @return string Extension; "jpg" or "gif"/"png"
733 * @access private
734 */
735 function extension() {
736 switch(strtolower($this->setup['format'])) {
737 case 'jpg':
738 case 'jpeg':
739 return 'jpg';
740 break;
741 case 'png':
742 return 'png';
743 break;
744 case 'gif':
745 return 'gif';
746 break;
747 default:
748 return $this->gifExtension;
749 break;
750 }
751 }
752
753 /**
754 * Calculates the value concerning the dimensions of objects.
755 *
756 * @param string $string: The string to be calculated (e.g. "[20.h]+13")
757 * @return integer The calculated value (e.g. "23")
758 * @see calcOffset()
759 */
760 protected function calculateValue($string) {
761 $calculatedValue = 0;
762 $parts = t3lib_div::splitCalc($string, '+-*/%');
763
764 foreach ($parts as $part) {
765 $theVal = $part[1];
766 $sign = $part[0];
767
768 if ((string)intval($theVal) == (string)$theVal) {
769 $theVal = intval($theVal);
770 } elseif ('[' . substr($theVal, 1, -1) . ']' == $theVal) {
771 $objParts = explode('.', substr($theVal, 1, -1));
772 $theVal = 0;
773 if (isset($this->objBB[$objParts[0]])) {
774 if ($objParts[1] == 'w') {
775 $theVal = $this->objBB[$objParts[0]][0];
776 } elseif ($objParts[1] == 'h') {
777 $theVal = $this->objBB[$objParts[0]][1];
778 } elseif ($objParts[1] == 'lineHeight') {
779 $theVal = $this->objBB[$objParts[0]][2]['lineHeight'];
780 }
781 $theVal = intval($theVal);
782 }
783 } elseif (floatval($theVal)) {
784 $theVal = floatval($theVal);
785 } else {
786 $theVal = 0;
787 }
788
789 if ($sign == '-') {
790 $calculatedValue-= $theVal;
791 } elseif ($sign == '+') {
792 $calculatedValue+= $theVal;
793 } elseif ($sign == '/' && $theVal) {
794 $calculatedValue = $calculatedValue / $theVal;
795 } elseif ($sign == '*') {
796 $calculatedValue = $calculatedValue * $theVal;
797 } elseif ($sign == '%' && $theVal) {
798 $calculatedValue%= $theVal;
799 }
800 }
801
802 return round($calculatedValue);
803 }
804
805 /**
806 * Calculates special functions:
807 * + max([10.h], [20.h]) -> gets the maximum of the given values
808 *
809 * @param string $string: The raw string with functions to be calculated
810 * @return string The calculated values
811 */
812 protected function calculateFunctions($string) {
813 if (preg_match_all('#max\(([^)]+)\)#', $string, $matches)) {
814 foreach ($matches[1] as $index => $maxExpression) {
815 $string = str_replace(
816 $matches[0][$index],
817 $this->calculateMaximum(
818 $maxExpression
819 ),
820 $string
821 );
822 }
823 }
824
825 return $string;
826 }
827
828 /**
829 * Calculates the maximum of a set of values defined like "[10.h],[20.h],1000"
830 *
831 * @param string $string: The string to be used to calculate the maximum (e.g. "[10.h],[20.h],1000")
832 * @return integer The maxium value of the given comma separated and calculated values
833 */
834 protected function calculateMaximum($string) {
835 $parts = t3lib_div::trimExplode(',', $this->calcOffset($string), true);
836 $maximum = (count($parts) ? max($parts) : 0);
837 return $maximum;
838 }
839 }
840
841
842 if (defined('TYPO3_MODE') && isset($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_gifbuilder.php'])) {
843 include_once($GLOBALS['TYPO3_CONF_VARS'][TYPO3_MODE]['XCLASS']['tslib/class.tslib_gifbuilder.php']);
844 }
845
846 ?>