TYPO3 CMS  TYPO3_7-6
GifBuilder.php
Go to the documentation of this file.
1 <?php
3 
4 /*
5  * This file is part of the TYPO3 CMS project.
6  *
7  * It is free software; you can redistribute it and/or modify it under
8  * the terms of the GNU General Public License, either version 2
9  * of the License, or any later version.
10  *
11  * For the full copyright and license information, please read the
12  * LICENSE.txt file that was distributed with this source code.
13  *
14  * The TYPO3 project - inspiring people to share!
15  */
16 
26 
50 {
56  public $im = '';
57 
63  public $w = 0;
64 
70  public $h = 0;
71 
77  public $map;
78 
82  public $workArea;
83 
89  public $setup = [];
90 
96  public $combinedTextStrings = [];
97 
103  public $combinedFileNames = [];
104 
110  public $data = [];
111 
115  public $objBB = [];
116 
120  public $myClassName = 'gifbuilder';
121 
125  public $charRangeMap = [];
126 
130  public $XY = [];
131 
135  public $OFFSET = [];
136 
140  public $cObj;
141 
145  public $defaultWorkArea = [];
146 
158  public function start($conf, $data)
159  {
160  if (is_array($conf)) {
161  $this->setup = $conf;
162  $this->data = $data;
163  $this->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
164  $this->cObj->start($this->data);
165  // Hook preprocess gifbuilder conf
166  // Added by Julle for 3.8.0
167  //
168  // Let's you pre-process the gifbuilder configuration. for
169  // example you can split a string up into lines and render each
170  // line as TEXT obj, see extension julle_gifbconf
171  if (is_array($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess'])) {
172  foreach ($GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess'] as $_funcRef) {
173  $_params = $this->setup;
174  $this->setup = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
175  }
176  }
177  // Initializing global Char Range Map
178  $this->charRangeMap = [];
179  if (is_array($GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'])) {
180  foreach ($GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'] as $cRMcfgkey => $cRMcfg) {
181  if (is_array($cRMcfg)) {
182  // Initializing:
183  $cRMkey = $GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'][substr($cRMcfgkey, 0, -1)];
184  $this->charRangeMap[$cRMkey] = [];
185  $this->charRangeMap[$cRMkey]['charMapConfig'] = $cRMcfg['charMapConfig.'];
186  $this->charRangeMap[$cRMkey]['cfgKey'] = substr($cRMcfgkey, 0, -1);
187  $this->charRangeMap[$cRMkey]['multiplicator'] = (double) $cRMcfg['fontSizeMultiplicator'];
188  $this->charRangeMap[$cRMkey]['pixelSpace'] = (int)$cRMcfg['pixelSpaceFontSizeRef'];
189  }
190  }
191  }
192  // Getting sorted list of TypoScript keys from setup.
193  $sKeyArray = TemplateService::sortedKeyList($this->setup);
194  // Setting the background color, passing it through stdWrap
195  if ($conf['backColor.'] || $conf['backColor']) {
196  $this->setup['backColor'] = isset($this->setup['backColor.']) ? trim($this->cObj->stdWrap($this->setup['backColor'], $this->setup['backColor.'])) : $this->setup['backColor'];
197  }
198  if (!$this->setup['backColor']) {
199  $this->setup['backColor'] = 'white';
200  }
201  if ($conf['transparentColor.'] || $conf['transparentColor']) {
202  $this->setup['transparentColor_array'] = isset($this->setup['transparentColor.']) ? explode('|', trim($this->cObj->stdWrap($this->setup['transparentColor'], $this->setup['transparentColor.']))) : explode('|', trim($this->setup['transparentColor']));
203  }
204  if (isset($this->setup['transparentBackground.'])) {
205  $this->setup['transparentBackground'] = $this->cObj->stdWrap($this->setup['transparentBackground'], $this->setup['transparentBackground.']);
206  }
207  if (isset($this->setup['reduceColors.'])) {
208  $this->setup['reduceColors'] = $this->cObj->stdWrap($this->setup['reduceColors'], $this->setup['reduceColors.']);
209  }
210  // Set default dimensions
211  if (isset($this->setup['XY.'])) {
212  $this->setup['XY'] = $this->cObj->stdWrap($this->setup['XY'], $this->setup['XY.']);
213  }
214  if (!$this->setup['XY']) {
215  $this->setup['XY'] = '120,50';
216  }
217  // Checking TEXT and IMAGE objects for files. If any errors the objects are cleared.
218  // The Bounding Box for the objects is stored in an array
219  foreach ($sKeyArray as $theKey) {
220  $theValue = $this->setup[$theKey];
221  if ((int)$theKey && ($conf = $this->setup[$theKey . '.'])) {
222  // Swipes through TEXT and IMAGE-objects
223  switch ($theValue) {
224  case 'TEXT':
225  if ($this->setup[$theKey . '.'] = $this->checkTextObj($conf)) {
226  // Adjust font width if max size is set:
227  $maxWidth = isset($this->setup[$theKey . '.']['maxWidth.']) ? $this->cObj->stdWrap($this->setup[$theKey . '.']['maxWidth'], $this->setup[$theKey . '.']['maxWidth.']) : $this->setup[$theKey . '.']['maxWidth'];
228  if ($maxWidth) {
229  $this->setup[$theKey . '.']['fontSize'] = $this->fontResize($this->setup[$theKey . '.']);
230  }
231  // Calculate bounding box:
232  $txtInfo = $this->calcBBox($this->setup[$theKey . '.']);
233  $this->setup[$theKey . '.']['BBOX'] = $txtInfo;
234  $this->objBB[$theKey] = $txtInfo;
235  $this->setup[$theKey . '.']['imgMap'] = 0;
236  }
237  break;
238  case 'IMAGE':
239  $fileInfo = $this->getResource($conf['file'], $conf['file.']);
240  if ($fileInfo) {
241  $this->combinedFileNames[] = preg_replace('/\\.[[:alnum:]]+$/', '', basename($fileInfo[3]));
242  if ($fileInfo['processedFile'] instanceof ProcessedFile) {
243  // Use processed file, if a FAL file has been processed by GIFBUILDER (e.g. scaled/cropped)
244  $this->setup[$theKey . '.']['file'] = $fileInfo['processedFile']->getForLocalProcessing(false);
245  } elseif (!isset($fileInfo['origFile']) && $fileInfo['originalFile'] instanceof File) {
246  // Use FAL file with getForLocalProcessing to circumvent problems with umlauts, if it is a FAL file (origFile not set)
248  $originalFile = $fileInfo['originalFile'];
249  $this->setup[$theKey . '.']['file'] = $originalFile->getForLocalProcessing(false);
250  } else {
251  // Use normal path from fileInfo if it is a non-FAL file (even non-FAL files have originalFile set, but only non-FAL files have origFile set)
252  $this->setup[$theKey . '.']['file'] = $fileInfo[3];
253  }
254  $this->setup[$theKey . '.']['BBOX'] = $fileInfo;
255  $this->objBB[$theKey] = $fileInfo;
256  if ($conf['mask']) {
257  $maskInfo = $this->getResource($conf['mask'], $conf['mask.']);
258  if ($maskInfo) {
259  // the same selection criteria as regarding fileInfo above apply here
260  if ($maskInfo['processedFile'] instanceof ProcessedFile) {
261  $this->setup[$theKey . '.']['mask'] = $maskInfo['processedFile']->getForLocalProcessing(false);
262  } elseif (!isset($maskInfo['origFile']) && $maskInfo['originalFile'] instanceof File) {
264  $originalFile = $maskInfo['originalFile'];
265  $this->setup[$theKey . '.']['mask'] = $originalFile->getForLocalProcessing(false);
266  } else {
267  $this->setup[$theKey . '.']['mask'] = $maskInfo[3];
268  }
269  } else {
270  $this->setup[$theKey . '.']['mask'] = '';
271  }
272  }
273  } else {
274  unset($this->setup[$theKey . '.']);
275  }
276  break;
277  }
278  // Checks if disabled is set... (this is also done in menu.php / imgmenu!!)
279  if ($conf['if.']) {
280  $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
281  $cObj->start($this->data);
282  if (!$cObj->checkIf($conf['if.'])) {
283  unset($this->setup[$theKey]);
284  unset($this->setup[$theKey . '.']);
285  unset($this->objBB[$theKey]);
286  }
287  }
288  }
289  }
290  // Calculate offsets on elements
291  $this->setup['XY'] = $this->calcOffset($this->setup['XY']);
292  if (isset($this->setup['offset.'])) {
293  $this->setup['offset'] = $this->cObj->stdWrap($this->setup['offset'], $this->setup['offset.']);
294  }
295  $this->setup['offset'] = $this->calcOffset($this->setup['offset']);
296  if (isset($this->setup['workArea.'])) {
297  $this->setup['workArea'] = $this->cObj->stdWrap($this->setup['workArea'], $this->setup['workArea.']);
298  }
299  $this->setup['workArea'] = $this->calcOffset($this->setup['workArea']);
300  foreach ($sKeyArray as $theKey) {
301  $theValue = $this->setup[$theKey];
302  if ((int)$theKey && ($conf = $this->setup[$theKey . '.'])) {
303  switch ($theValue) {
304  case 'TEXT':
305 
306  case 'IMAGE':
307  if (isset($this->setup[$theKey . '.']['offset.'])) {
308  $this->setup[$theKey . '.']['offset'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['offset'], $this->setup[$theKey . '.']['offset.']);
309  unset($this->setup[$theKey . '.']['offset.']);
310  }
311  if ($this->setup[$theKey . '.']['offset']) {
312  $this->setup[$theKey . '.']['offset'] = $this->calcOffset($this->setup[$theKey . '.']['offset']);
313  }
314  break;
315  case 'BOX':
316 
317  case 'ELLIPSE':
318  if (isset($this->setup[$theKey . '.']['dimensions.'])) {
319  $this->setup[$theKey . '.']['dimensions'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['dimensions'], $this->setup[$theKey . '.']['dimensions.']);
320  unset($this->setup[$theKey . '.']['dimensions.']);
321  }
322  if ($this->setup[$theKey . '.']['dimensions']) {
323  $this->setup[$theKey . '.']['dimensions'] = $this->calcOffset($this->setup[$theKey . '.']['dimensions']);
324  }
325  break;
326  case 'WORKAREA':
327  if (isset($this->setup[$theKey . '.']['set.'])) {
328  $this->setup[$theKey . '.']['set'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['set'], $this->setup[$theKey . '.']['set.']);
329  unset($this->setup[$theKey . '.']['set.']);
330  }
331  if ($this->setup[$theKey . '.']['set']) {
332  $this->setup[$theKey . '.']['set'] = $this->calcOffset($this->setup[$theKey . '.']['set']);
333  }
334  break;
335  case 'CROP':
336  if (isset($this->setup[$theKey . '.']['crop.'])) {
337  $this->setup[$theKey . '.']['crop'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['crop'], $this->setup[$theKey . '.']['crop.']);
338  unset($this->setup[$theKey . '.']['crop.']);
339  }
340  if ($this->setup[$theKey . '.']['crop']) {
341  $this->setup[$theKey . '.']['crop'] = $this->calcOffset($this->setup[$theKey . '.']['crop']);
342  }
343  break;
344  case 'SCALE':
345  if (isset($this->setup[$theKey . '.']['width.'])) {
346  $this->setup[$theKey . '.']['width'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['width'], $this->setup[$theKey . '.']['width.']);
347  unset($this->setup[$theKey . '.']['width.']);
348  }
349  if ($this->setup[$theKey . '.']['width']) {
350  $this->setup[$theKey . '.']['width'] = $this->calcOffset($this->setup[$theKey . '.']['width']);
351  }
352  if (isset($this->setup[$theKey . '.']['height.'])) {
353  $this->setup[$theKey . '.']['height'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['height'], $this->setup[$theKey . '.']['height.']);
354  unset($this->setup[$theKey . '.']['height.']);
355  }
356  if ($this->setup[$theKey . '.']['height']) {
357  $this->setup[$theKey . '.']['height'] = $this->calcOffset($this->setup[$theKey . '.']['height']);
358  }
359  break;
360  }
361  }
362  }
363  // Get trivial data
364  $XY = GeneralUtility::intExplode(',', $this->setup['XY']);
365  $maxWidth = isset($this->setup['maxWidth.']) ? (int)$this->cObj->stdWrap($this->setup['maxWidth'], $this->setup['maxWidth.']) : (int)$this->setup['maxWidth'];
366  $maxHeight = isset($this->setup['maxHeight.']) ? (int)$this->cObj->stdWrap($this->setup['maxHeight'], $this->setup['maxHeight.']) : (int)$this->setup['maxHeight'];
367  $XY[0] = MathUtility::forceIntegerInRange($XY[0], 1, $maxWidth ?: 2000);
368  $XY[1] = MathUtility::forceIntegerInRange($XY[1], 1, $maxHeight ?: 2000);
369  $this->XY = $XY;
370  $this->w = $XY[0];
371  $this->h = $XY[1];
372  $this->OFFSET = GeneralUtility::intExplode(',', $this->setup['offset']);
373  // this sets the workArea
374  $this->setWorkArea($this->setup['workArea']);
375  // this sets the default to the current;
376  $this->defaultWorkArea = $this->workArea;
377  }
378  }
379 
388  public function gifBuild()
389  {
390  if ($this->setup) {
391  // Relative to PATH_site
392  $gifFileName = $this->fileName('GB/');
393  // File exists
394  if (!file_exists($gifFileName)) {
395  // Create temporary directory if not done:
396  $this->createTempSubDir('GB/');
397  // Create file:
398  $this->make();
399  $this->output($gifFileName);
400  $this->destroy();
401  }
402  return $gifFileName;
403  }
404  return '';
405  }
406 
417  public function make()
418  {
419  // Get trivial data
420  $XY = $this->XY;
421  // Reset internal properties
422  $this->saveAlphaLayer = false;
423  // Gif-start
424  $this->im = imagecreatetruecolor($XY[0], $XY[1]);
425  $this->w = $XY[0];
426  $this->h = $XY[1];
427  // Transparent layer as background if set and requirements are met
428  if (!empty($this->setup['backColor']) && $this->setup['backColor'] === 'transparent' && $this->png_truecolor && !$this->setup['reduceColors'] && (empty($this->setup['format']) || $this->setup['format'] === 'png')) {
429  // Set transparency properties
430  imagesavealpha($this->im, true);
431  // Fill with a transparent background
432  $transparentColor = imagecolorallocatealpha($this->im, 0, 0, 0, 127);
433  imagefill($this->im, 0, 0, $transparentColor);
434  // Set internal properties to keep the transparency over the rendering process
435  $this->saveAlphaLayer = true;
436  // Force PNG in case no format is set
437  $this->setup['format'] = 'png';
438  $BGcols = [];
439  } else {
440  // Fill the background with the given color
441  $BGcols = $this->convertColor($this->setup['backColor']);
442  $Bcolor = imagecolorallocate($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
443  imagefilledrectangle($this->im, 0, 0, $XY[0], $XY[1], $Bcolor);
444  }
445  // Traverse the GIFBUILDER objects an render each one:
446  if (is_array($this->setup)) {
447  $sKeyArray = TemplateService::sortedKeyList($this->setup);
448  foreach ($sKeyArray as $theKey) {
449  $theValue = $this->setup[$theKey];
450  if ((int)$theKey && ($conf = $this->setup[$theKey . '.'])) {
451  // apply stdWrap to all properties, except for TEXT objects
452  // all properties of the TEXT sub-object have already been stdWrap-ped
453  // before in ->checkTextObj()
454  if ($theValue !== 'TEXT') {
455  $isStdWrapped = [];
456  foreach ($conf as $key => $value) {
457  $parameter = rtrim($key, '.');
458  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
459  $conf[$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
460  $isStdWrapped[$parameter] = 1;
461  }
462  }
463  }
464 
465  switch ($theValue) {
466  case 'IMAGE':
467  if ($conf['mask']) {
468  $this->maskImageOntoImage($this->im, $conf, $this->workArea);
469  } else {
470  $this->copyImageOntoImage($this->im, $conf, $this->workArea);
471  }
472  break;
473  case 'TEXT':
474  if (!$conf['hide']) {
475  if (is_array($conf['shadow.'])) {
476  $isStdWrapped = [];
477  foreach ($conf['shadow.'] as $key => $value) {
478  $parameter = rtrim($key, '.');
479  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
480  $conf['shadow.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
481  $isStdWrapped[$parameter] = 1;
482  }
483  }
484  $this->makeShadow($this->im, $conf['shadow.'], $this->workArea, $conf);
485  }
486  if (is_array($conf['emboss.'])) {
487  $isStdWrapped = [];
488  foreach ($conf['emboss.'] as $key => $value) {
489  $parameter = rtrim($key, '.');
490  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
491  $conf['emboss.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
492  $isStdWrapped[$parameter] = 1;
493  }
494  }
495  $this->makeEmboss($this->im, $conf['emboss.'], $this->workArea, $conf);
496  }
497  if (is_array($conf['outline.'])) {
498  $isStdWrapped = [];
499  foreach ($conf['outline.'] as $key => $value) {
500  $parameter = rtrim($key, '.');
501  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
502  $conf['outline.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
503  $isStdWrapped[$parameter] = 1;
504  }
505  }
506  $this->makeOutline($this->im, $conf['outline.'], $this->workArea, $conf);
507  }
508  $conf['imgMap'] = 1;
509  $this->makeText($this->im, $conf, $this->workArea);
510  }
511  break;
512  case 'OUTLINE':
513  if ($this->setup[$conf['textObjNum']] == 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
514  $this->makeOutline($this->im, $conf, $this->workArea, $txtConf);
515  }
516  break;
517  case 'EMBOSS':
518  if ($this->setup[$conf['textObjNum']] == 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
519  $this->makeEmboss($this->im, $conf, $this->workArea, $txtConf);
520  }
521  break;
522  case 'SHADOW':
523  if ($this->setup[$conf['textObjNum']] == 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
524  $this->makeShadow($this->im, $conf, $this->workArea, $txtConf);
525  }
526  break;
527  case 'BOX':
528  $this->makeBox($this->im, $conf, $this->workArea);
529  break;
530  case 'EFFECT':
531  $this->makeEffect($this->im, $conf);
532  break;
533  case 'ADJUST':
534  $this->adjust($this->im, $conf);
535  break;
536  case 'CROP':
537  $this->crop($this->im, $conf);
538  break;
539  case 'SCALE':
540  $this->scale($this->im, $conf);
541  break;
542  case 'WORKAREA':
543  if ($conf['set']) {
544  // this sets the workArea
545  $this->setWorkArea($conf['set']);
546  }
547  if (isset($conf['clear'])) {
548  // This sets the current to the default;
549  $this->workArea = $this->defaultWorkArea;
550  }
551  break;
552  case 'ELLIPSE':
553  $this->makeEllipse($this->im, $conf, $this->workArea);
554  break;
555  }
556  }
557  }
558  }
559  // Preserve alpha transparency
560  if (!$this->saveAlphaLayer) {
561  if ($this->setup['transparentBackground']) {
562  // Auto transparent background is set
563  $Bcolor = imagecolorclosest($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
564  imagecolortransparent($this->im, $Bcolor);
565  } elseif (is_array($this->setup['transparentColor_array'])) {
566  // Multiple transparent colors are set. This is done via the trick that all transparent colors get
567  // converted to one color and then this one gets set as transparent as png/gif can just have one
568  // transparent color.
569  $Tcolor = $this->unifyColors($this->im, $this->setup['transparentColor_array'], (int)$this->setup['transparentColor.']['closest']);
570  if ($Tcolor >= 0) {
571  imagecolortransparent($this->im, $Tcolor);
572  }
573  }
574  }
575  }
576 
577  /*********************************************
578  *
579  * Various helper functions
580  *
581  ********************************************/
593  public function checkTextObj($conf)
594  {
595  $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
596  $cObj->start($this->data);
597  $isStdWrapped = [];
598  foreach ($conf as $key => $value) {
599  $parameter = rtrim($key, '.');
600  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
601  $conf[$parameter] = $cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
602  $isStdWrapped[$parameter] = 1;
603  }
604  }
605  $conf['fontFile'] = $this->checkFile($conf['fontFile']);
606  if (!$conf['fontFile']) {
607  $conf['fontFile'] = ExtensionManagementUtility::siteRelPath('core') . 'Resources/Private/Font/nimbus.ttf';
608  }
609  if (!$conf['iterations']) {
610  $conf['iterations'] = 1;
611  }
612  if (!$conf['fontSize']) {
613  $conf['fontSize'] = 12;
614  }
615  // If any kind of spacing applys, we cannot use angles!!
616  if ($conf['spacing'] || $conf['wordSpacing']) {
617  $conf['angle'] = 0;
618  }
619  if (!isset($conf['antiAlias'])) {
620  $conf['antiAlias'] = 1;
621  }
622  $conf['fontColor'] = trim($conf['fontColor']);
623  // Strip HTML
624  if (!$conf['doNotStripHTML']) {
625  $conf['text'] = strip_tags($conf['text']);
626  }
627  $this->combinedTextStrings[] = strip_tags($conf['text']);
628  // Max length = 100 if automatic line braks are not defined:
629  if (!isset($conf['breakWidth']) || !$conf['breakWidth']) {
630  $tlen = (int)$conf['textMaxLength'] ?: 100;
631  if ($this->nativeCharset) {
632  $conf['text'] = $this->csConvObj->substr($this->nativeCharset, $conf['text'], 0, $tlen);
633  } else {
634  $conf['text'] = substr($conf['text'], 0, $tlen);
635  }
636  }
637  if ((string)$conf['text'] != '') {
638  // Char range map thingie:
639  $fontBaseName = basename($conf['fontFile']);
640  if (is_array($this->charRangeMap[$fontBaseName])) {
641  // Initialize splitRendering array:
642  if (!is_array($conf['splitRendering.'])) {
643  $conf['splitRendering.'] = [];
644  }
645  $cfgK = $this->charRangeMap[$fontBaseName]['cfgKey'];
646  // Do not impose settings if a splitRendering object already exists:
647  if (!isset($conf['splitRendering.'][$cfgK])) {
648  // Set configuration:
649  $conf['splitRendering.'][$cfgK] = 'charRange';
650  $conf['splitRendering.'][$cfgK . '.'] = $this->charRangeMap[$fontBaseName]['charMapConfig'];
651  // Multiplicator of fontsize:
652  if ($this->charRangeMap[$fontBaseName]['multiplicator']) {
653  $conf['splitRendering.'][$cfgK . '.']['fontSize'] = round($conf['fontSize'] * $this->charRangeMap[$fontBaseName]['multiplicator']);
654  }
655  // Multiplicator of pixelSpace:
656  if ($this->charRangeMap[$fontBaseName]['pixelSpace']) {
657  $travKeys = ['xSpaceBefore', 'xSpaceAfter', 'ySpaceBefore', 'ySpaceAfter'];
658  foreach ($travKeys as $pxKey) {
659  if (isset($conf['splitRendering.'][$cfgK . '.'][$pxKey])) {
660  $conf['splitRendering.'][$cfgK . '.'][$pxKey] = round($conf['splitRendering.'][$cfgK . '.'][$pxKey] * ($conf['fontSize'] / $this->charRangeMap[$fontBaseName]['pixelSpace']));
661  }
662  }
663  }
664  }
665  }
666  if (is_array($conf['splitRendering.'])) {
667  foreach ($conf['splitRendering.'] as $key => $value) {
668  if (is_array($conf['splitRendering.'][$key])) {
669  if (isset($conf['splitRendering.'][$key]['fontFile'])) {
670  $conf['splitRendering.'][$key]['fontFile'] = $this->checkFile($conf['splitRendering.'][$key]['fontFile']);
671  }
672  }
673  }
674  }
675  return $conf;
676  }
677  return null;
678  }
679 
691  public function calcOffset($string)
692  {
693  $value = [];
694  $numbers = GeneralUtility::trimExplode(',', $this->calculateFunctions($string));
695  foreach ($numbers as $key => $val) {
696  if ((string)$val == (string)(int)$val) {
697  $value[$key] = (int)$val;
698  } else {
699  $value[$key] = $this->calculateValue($val);
700  }
701  }
702  $string = implode(',', $value);
703  return $string;
704  }
705 
715  public function getResource($file, $fileArray)
716  {
717  if (!GeneralUtility::inList($this->imageFileExt, $fileArray['ext'])) {
718  $fileArray['ext'] = $this->gifExtension;
719  }
721  $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
722  $cObj->start($this->data);
723  return $cObj->getImgResource($file, $fileArray);
724  }
725 
734  public function checkFile($file)
735  {
736  return $GLOBALS['TSFE']->tmpl->getFileName($file);
737  }
738 
749  public function fileName($pre)
750  {
752  $basicFileFunctions = GeneralUtility::makeInstance(BasicFileUtility::class);
753  $filePrefix = implode('_', array_merge($this->combinedTextStrings, $this->combinedFileNames));
754  $filePrefix = $basicFileFunctions->cleanFileName($filePrefix);
755 
756  // shorten prefix to avoid overly long file names
757  $filePrefix = substr($filePrefix, 0, 100);
758 
759  return $this->tempPath . $pre . $filePrefix . '_' . GeneralUtility::shortMD5(serialize($this->setup)) . '.' . $this->extension();
760  }
761 
768  public function extension()
769  {
770  switch (strtolower($this->setup['format'])) {
771  case 'jpg':
772 
773  case 'jpeg':
774  return 'jpg';
775  break;
776  case 'png':
777  return 'png';
778  break;
779  case 'gif':
780  return 'gif';
781  break;
782  default:
783  return $this->gifExtension;
784  }
785  }
786 
794  protected function calculateValue($string)
795  {
796  $calculatedValue = 0;
797  $parts = GeneralUtility::splitCalc($string, '+-*/%');
798  foreach ($parts as $part) {
799  $theVal = $part[1];
800  $sign = $part[0];
801  if (((string)(int)$theVal) == ((string)$theVal)) {
802  $theVal = (int)$theVal;
803  } elseif ('[' . substr($theVal, 1, -1) . ']' == $theVal) {
804  $objParts = explode('.', substr($theVal, 1, -1));
805  $theVal = 0;
806  if (isset($this->objBB[$objParts[0]])) {
807  if ($objParts[1] == 'w') {
808  $theVal = $this->objBB[$objParts[0]][0];
809  } elseif ($objParts[1] == 'h') {
810  $theVal = $this->objBB[$objParts[0]][1];
811  } elseif ($objParts[1] == 'lineHeight') {
812  $theVal = $this->objBB[$objParts[0]][2]['lineHeight'];
813  }
814  $theVal = (int)$theVal;
815  }
816  } elseif (floatval($theVal)) {
817  $theVal = floatval($theVal);
818  } else {
819  $theVal = 0;
820  }
821  if ($sign == '-') {
822  $calculatedValue -= $theVal;
823  } elseif ($sign == '+') {
824  $calculatedValue += $theVal;
825  } elseif ($sign == '/' && $theVal) {
826  $calculatedValue = $calculatedValue / $theVal;
827  } elseif ($sign == '*') {
828  $calculatedValue = $calculatedValue * $theVal;
829  } elseif ($sign == '%' && $theVal) {
830  $calculatedValue %= $theVal;
831  }
832  }
833  return round($calculatedValue);
834  }
835 
843  protected function calculateFunctions($string)
844  {
845  if (preg_match_all('#max\\(([^)]+)\\)#', $string, $matches)) {
846  foreach ($matches[1] as $index => $maxExpression) {
847  $string = str_replace($matches[0][$index], $this->calculateMaximum($maxExpression), $string);
848  }
849  }
850  return $string;
851  }
852 
859  protected function calculateMaximum($string)
860  {
861  $parts = GeneralUtility::trimExplode(',', $this->calcOffset($string), true);
862  $maximum = !empty($parts) ? max($parts) : 0;
863  return $maximum;
864  }
865 }
static intExplode($delimiter, $string, $removeEmptyValues=false, $limit=0)
unifyColors(&$img, $colArr, $closest=false)
makeEmboss(&$im, $conf, $workArea, $txtConf)
static forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
makeEllipse(&$im, array $conf, array $workArea)
static sortedKeyList($setupArr, $acceptOnlyProperties=false)
static trimExplode($delim, $string, $removeEmptyValues=false, $limit=0)
static callUserFunction($funcName, &$params, &$ref, $checkPrefix='', $errorMode=0)
makeShadow(&$im, $conf, $workArea, $txtConf)
makeOutline(&$im, $conf, $workArea, $txtConf)
static splitCalc($string, $operators)
if(TYPO3_MODE==='BE') $GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['t3lib/class.t3lib_tsfebeuserauth.php']['frontendEditingController']['default']