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