‪TYPO3CMS  9.5
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 
28 
52 {
58  public ‪$combinedTextStrings = [];
59 
65  public ‪$combinedFileNames = [];
66 
72  public ‪$data = [];
73 
77  public ‪$objBB = [];
78 
82  public ‪$myClassName = 'gifbuilder';
83 
87  public ‪$charRangeMap = [];
88 
92  public ‪$XY = [];
93 
97  public ‪$cObj;
98 
102  public ‪$defaultWorkArea = [];
103 
114  public function ‪start($conf, ‪$data)
115  {
116  if (is_array($conf)) {
117  $this->setup = $conf;
118  $this->data = ‪$data;
119  $this->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
120  $this->cObj->start($this->data);
121  // Hook preprocess gifbuilder conf
122  // Added by Julle for 3.8.0
123  //
124  // Let's you pre-process the gifbuilder configuration. for
125  // example you can split a string up into lines and render each
126  // line as TEXT obj, see extension julle_gifbconf
127  foreach (‪$GLOBALS['TYPO3_CONF_VARS']['SC_OPTIONS']['tslib/class.tslib_gifbuilder.php']['gifbuilder-ConfPreProcess'] ?? [] as $_funcRef) {
128  $_params = ‪$this->setup;
129  $this->setup = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
130  }
131  // Initializing global Char Range Map
132  $this->charRangeMap = [];
133  if (is_array(‪$GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'])) {
134  foreach (‪$GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'] as $cRMcfgkey => $cRMcfg) {
135  if (is_array($cRMcfg)) {
136  // Initializing:
137  $cRMkey = ‪$GLOBALS['TSFE']->tmpl->setup['_GIFBUILDER.']['charRangeMap.'][substr($cRMcfgkey, 0, -1)];
138  $this->charRangeMap[$cRMkey] = [];
139  $this->charRangeMap[$cRMkey]['charMapConfig'] = $cRMcfg['charMapConfig.'];
140  $this->charRangeMap[$cRMkey]['cfgKey'] = substr($cRMcfgkey, 0, -1);
141  $this->charRangeMap[$cRMkey]['multiplicator'] = (double)$cRMcfg['fontSizeMultiplicator'];
142  $this->charRangeMap[$cRMkey]['pixelSpace'] = (int)$cRMcfg['pixelSpaceFontSizeRef'];
143  }
144  }
145  }
146  // Getting sorted list of TypoScript keys from setup.
147  $sKeyArray = ‪ArrayUtility::filterAndSortByNumericKeys($this->setup);
148  // Setting the background color, passing it through stdWrap
149  if ($conf['backColor.'] || $conf['backColor']) {
150  $this->setup['backColor'] = isset($this->setup['backColor.']) ? trim($this->cObj->stdWrap($this->setup['backColor'], $this->setup['backColor.'])) : $this->setup['backColor'];
151  }
152  if (!$this->setup['backColor']) {
153  $this->setup['backColor'] = 'white';
154  }
155  if ($conf['transparentColor.'] || $conf['transparentColor']) {
156  $this->setup['transparentColor_array'] = isset($this->setup['transparentColor.']) ? explode('|', trim($this->cObj->stdWrap($this->setup['transparentColor'], $this->setup['transparentColor.']))) : explode('|', trim($this->setup['transparentColor']));
157  }
158  if (isset($this->setup['transparentBackground.'])) {
159  $this->setup['transparentBackground'] = $this->cObj->stdWrap($this->setup['transparentBackground'], $this->setup['transparentBackground.']);
160  }
161  if (isset($this->setup['reduceColors.'])) {
162  $this->setup['reduceColors'] = $this->cObj->stdWrap($this->setup['reduceColors'], $this->setup['reduceColors.']);
163  }
164  // Set default dimensions
165  if (isset($this->setup['XY.'])) {
166  $this->setup['XY'] = $this->cObj->stdWrap($this->setup['XY'], $this->setup['XY.']);
167  }
168  if (!$this->setup['XY']) {
169  $this->setup['XY'] = '120,50';
170  }
171  // Checking TEXT and IMAGE objects for files. If any errors the objects are cleared.
172  // The Bounding Box for the objects is stored in an array
173  foreach ($sKeyArray as $theKey) {
174  $theValue = $this->setup[$theKey];
175  if ((int)$theKey && ($conf = $this->setup[$theKey . '.'])) {
176  // Swipes through TEXT and IMAGE-objects
177  switch ($theValue) {
178  case 'TEXT':
179  if ($this->setup[$theKey . '.'] = $this->‪checkTextObj($conf)) {
180  // Adjust font width if max size is set:
181  $maxWidth = isset($this->setup[$theKey . '.']['maxWidth.']) ? $this->cObj->stdWrap($this->setup[$theKey . '.']['maxWidth'], $this->setup[$theKey . '.']['maxWidth.']) : $this->setup[$theKey . '.']['maxWidth'];
182  if ($maxWidth) {
183  $this->setup[$theKey . '.']['fontSize'] = $this->‪fontResize($this->setup[$theKey . '.']);
184  }
185  // Calculate bounding box:
186  $txtInfo = $this->‪calcBBox($this->setup[$theKey . '.']);
187  $this->setup[$theKey . '.']['BBOX'] = $txtInfo;
188  $this->objBB[$theKey] = $txtInfo;
189  $this->setup[$theKey . '.']['imgMap'] = 0;
190  }
191  break;
192  case 'IMAGE':
193  $fileInfo = $this->‪getResource($conf['file'], $conf['file.']);
194  if ($fileInfo) {
195  $this->combinedFileNames[] = preg_replace('/\\.[[:alnum:]]+$/', '', ‪PathUtility::basename($fileInfo[3]));
196  if ($fileInfo['processedFile'] instanceof ‪ProcessedFile) {
197  // Use processed file, if a FAL file has been processed by GIFBUILDER (e.g. scaled/cropped)
198  $this->setup[$theKey . '.']['file'] = $fileInfo['processedFile']->getForLocalProcessing(false);
199  } elseif (!isset($fileInfo['origFile']) && $fileInfo['originalFile'] instanceof ‪File) {
200  // Use FAL file with getForLocalProcessing to circumvent problems with umlauts, if it is a FAL file (origFile not set)
202  $originalFile = $fileInfo['originalFile'];
203  $this->setup[$theKey . '.']['file'] = $originalFile->getForLocalProcessing(false);
204  } else {
205  // 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)
206  $this->setup[$theKey . '.']['file'] = $fileInfo[3];
207  }
208 
209  // only pass necessary parts of fileInfo further down, to not incorporate facts as
210  // CropScaleMask runs in this request, that may not occur in subsequent calls and change
211  // the md5 of the generated file name
212  $essentialFileInfo = $fileInfo;
213  unset($essentialFileInfo['originalFile'], $essentialFileInfo['processedFile']);
214 
215  $this->setup[$theKey . '.']['BBOX'] = $essentialFileInfo;
216  $this->objBB[$theKey] = $essentialFileInfo;
217  if ($conf['mask']) {
218  $maskInfo = $this->‪getResource($conf['mask'], $conf['mask.']);
219  if ($maskInfo) {
220  // the same selection criteria as regarding fileInfo above apply here
221  if ($maskInfo['processedFile'] instanceof ‪ProcessedFile) {
222  $this->setup[$theKey . '.']['mask'] = $maskInfo['processedFile']->getForLocalProcessing(false);
223  } elseif (!isset($maskInfo['origFile']) && $maskInfo['originalFile'] instanceof ‪File) {
225  $originalFile = $maskInfo['originalFile'];
226  $this->setup[$theKey . '.']['mask'] = $originalFile->getForLocalProcessing(false);
227  } else {
228  $this->setup[$theKey . '.']['mask'] = $maskInfo[3];
229  }
230  } else {
231  $this->setup[$theKey . '.']['mask'] = '';
232  }
233  }
234  } else {
235  unset($this->setup[$theKey . '.']);
236  }
237  break;
238  }
239  // Checks if disabled is set... (this is also done in menu.php / imgmenu!!)
240  if ($conf['if.']) {
241  ‪$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
242  ‪$cObj->‪start($this->data);
243  if (!‪$cObj->‪checkIf($conf['if.'])) {
244  unset($this->setup[$theKey]);
245  unset($this->setup[$theKey . '.']);
246  unset($this->objBB[$theKey]);
247  }
248  }
249  }
250  }
251  // Calculate offsets on elements
252  $this->setup['XY'] = $this->‪calcOffset($this->setup['XY']);
253  if (isset($this->setup['offset.'])) {
254  $this->setup['offset'] = $this->cObj->stdWrap($this->setup['offset'], $this->setup['offset.']);
255  }
256  $this->setup['offset'] = $this->‪calcOffset($this->setup['offset']);
257  if (isset($this->setup['workArea.'])) {
258  $this->setup['workArea'] = $this->cObj->stdWrap($this->setup['workArea'], $this->setup['workArea.']);
259  }
260  $this->setup['workArea'] = $this->‪calcOffset($this->setup['workArea']);
261  foreach ($sKeyArray as $theKey) {
262  $theValue = $this->setup[$theKey];
263  if ((int)$theKey && $this->setup[$theKey . '.']) {
264  switch ($theValue) {
265  case 'TEXT':
266 
267  case 'IMAGE':
268  if (isset($this->setup[$theKey . '.']['offset.'])) {
269  $this->setup[$theKey . '.']['offset'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['offset'], $this->setup[$theKey . '.']['offset.']);
270  unset($this->setup[$theKey . '.']['offset.']);
271  }
272  if ($this->setup[$theKey . '.']['offset']) {
273  $this->setup[$theKey . '.']['offset'] = $this->‪calcOffset($this->setup[$theKey . '.']['offset']);
274  }
275  break;
276  case 'BOX':
277 
278  case 'ELLIPSE':
279  if (isset($this->setup[$theKey . '.']['dimensions.'])) {
280  $this->setup[$theKey . '.']['dimensions'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['dimensions'], $this->setup[$theKey . '.']['dimensions.']);
281  unset($this->setup[$theKey . '.']['dimensions.']);
282  }
283  if ($this->setup[$theKey . '.']['dimensions']) {
284  $this->setup[$theKey . '.']['dimensions'] = $this->‪calcOffset($this->setup[$theKey . '.']['dimensions']);
285  }
286  break;
287  case 'WORKAREA':
288  if (isset($this->setup[$theKey . '.']['set.'])) {
289  $this->setup[$theKey . '.']['set'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['set'], $this->setup[$theKey . '.']['set.']);
290  unset($this->setup[$theKey . '.']['set.']);
291  }
292  if ($this->setup[$theKey . '.']['set']) {
293  $this->setup[$theKey . '.']['set'] = $this->‪calcOffset($this->setup[$theKey . '.']['set']);
294  }
295  break;
296  case 'CROP':
297  if (isset($this->setup[$theKey . '.']['crop.'])) {
298  $this->setup[$theKey . '.']['crop'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['crop'], $this->setup[$theKey . '.']['crop.']);
299  unset($this->setup[$theKey . '.']['crop.']);
300  }
301  if ($this->setup[$theKey . '.']['crop']) {
302  $this->setup[$theKey . '.']['crop'] = $this->‪calcOffset($this->setup[$theKey . '.']['crop']);
303  }
304  break;
305  case 'SCALE':
306  if (isset($this->setup[$theKey . '.']['width.'])) {
307  $this->setup[$theKey . '.']['width'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['width'], $this->setup[$theKey . '.']['width.']);
308  unset($this->setup[$theKey . '.']['width.']);
309  }
310  if ($this->setup[$theKey . '.']['width']) {
311  $this->setup[$theKey . '.']['width'] = $this->‪calcOffset($this->setup[$theKey . '.']['width']);
312  }
313  if (isset($this->setup[$theKey . '.']['height.'])) {
314  $this->setup[$theKey . '.']['height'] = $this->cObj->stdWrap($this->setup[$theKey . '.']['height'], $this->setup[$theKey . '.']['height.']);
315  unset($this->setup[$theKey . '.']['height.']);
316  }
317  if ($this->setup[$theKey . '.']['height']) {
318  $this->setup[$theKey . '.']['height'] = $this->‪calcOffset($this->setup[$theKey . '.']['height']);
319  }
320  break;
321  }
322  }
323  }
324  // Get trivial data
325  ‪$XY = GeneralUtility::intExplode(',', $this->setup['XY']);
326  $maxWidth = isset($this->setup['maxWidth.']) ? (int)$this->cObj->stdWrap($this->setup['maxWidth'], $this->setup['maxWidth.']) : (int)$this->setup['maxWidth'];
327  $maxHeight = isset($this->setup['maxHeight.']) ? (int)$this->cObj->stdWrap($this->setup['maxHeight'], $this->setup['maxHeight.']) : (int)$this->setup['maxHeight'];
328  ‪$XY[0] = ‪MathUtility::forceIntegerInRange(‪$XY[0], 1, $maxWidth ?: 2000);
329  ‪$XY[1] = ‪MathUtility::forceIntegerInRange(‪$XY[1], 1, $maxHeight ?: 2000);
330  $this->XY = ‪$XY;
331  $this->w = ‪$XY[0];
332  $this->h = ‪$XY[1];
333  $this->OFFSET = GeneralUtility::intExplode(',', $this->setup['offset']);
334  // this sets the workArea
335  $this->‪setWorkArea($this->setup['workArea']);
336  // this sets the default to the current;
337  $this->defaultWorkArea = ‪$this->workArea;
338  }
339  }
340 
349  public function ‪gifBuild()
350  {
351  if ($this->setup) {
352  // Relative to Environment::getPublicPath()
353  $gifFileName = $this->‪fileName('assets/images/');
354  // File exists
355  if (!file_exists($gifFileName)) {
356  // Create temporary directory if not done:
357  GeneralUtility::mkdir_deep(‪Environment::getPublicPath() . '/typo3temp/assets/images/');
358  // Create file:
359  $this->‪make();
360  $this->‪output($gifFileName);
361  $this->‪destroy();
362  }
363  return $gifFileName;
364  }
365  return '';
366  }
367 
377  public function ‪make()
378  {
379  // Get trivial data
381  // Reset internal properties
382  $this->saveAlphaLayer = false;
383  // Gif-start
384  $this->im = imagecreatetruecolor(‪$XY[0], ‪$XY[1]);
385  $this->w = ‪$XY[0];
386  $this->h = ‪$XY[1];
387  // Transparent layer as background if set and requirements are met
388  if (!empty($this->setup['backColor']) && $this->setup['backColor'] === 'transparent' && !$this->setup['reduceColors'] && (empty($this->setup['format']) || $this->setup['format'] === 'png')) {
389  // Set transparency properties
390  imagesavealpha($this->im, true);
391  // Fill with a transparent background
392  $transparentColor = imagecolorallocatealpha($this->im, 0, 0, 0, 127);
393  imagefill($this->im, 0, 0, $transparentColor);
394  // Set internal properties to keep the transparency over the rendering process
395  $this->saveAlphaLayer = true;
396  // Force PNG in case no format is set
397  $this->setup['format'] = 'png';
398  $BGcols = [];
399  } else {
400  // Fill the background with the given color
401  $BGcols = $this->‪convertColor($this->setup['backColor']);
402  $Bcolor = imagecolorallocate($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
403  imagefilledrectangle($this->im, 0, 0, ‪$XY[0], ‪$XY[1], $Bcolor);
404  }
405  // Traverse the GIFBUILDER objects an render each one:
406  if (is_array($this->setup)) {
407  $sKeyArray = ‪ArrayUtility::filterAndSortByNumericKeys($this->setup);
408  foreach ($sKeyArray as $theKey) {
409  $theValue = $this->setup[$theKey];
410  if ((int)$theKey && ($conf = $this->setup[$theKey . '.'])) {
411  // apply stdWrap to all properties, except for TEXT objects
412  // all properties of the TEXT sub-object have already been stdWrap-ped
413  // before in ->checkTextObj()
414  if ($theValue !== 'TEXT') {
415  $isStdWrapped = [];
416  foreach ($conf as $key => $value) {
417  $parameter = rtrim($key, '.');
418  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
419  $conf[$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
420  $isStdWrapped[$parameter] = 1;
421  }
422  }
423  }
424 
425  switch ($theValue) {
426  case 'IMAGE':
427  if ($conf['mask']) {
428  $this->‪maskImageOntoImage($this->im, $conf, $this->workArea);
429  } else {
430  $this->‪copyImageOntoImage($this->im, $conf, $this->workArea);
431  }
432  break;
433  case 'TEXT':
434  if (!$conf['hide']) {
435  if (is_array($conf['shadow.'])) {
436  $isStdWrapped = [];
437  foreach ($conf['shadow.'] as $key => $value) {
438  $parameter = rtrim($key, '.');
439  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
440  $conf['shadow.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
441  $isStdWrapped[$parameter] = 1;
442  }
443  }
444  $this->‪makeShadow($this->im, $conf['shadow.'], $this->workArea, $conf);
445  }
446  if (is_array($conf['emboss.'])) {
447  $isStdWrapped = [];
448  foreach ($conf['emboss.'] as $key => $value) {
449  $parameter = rtrim($key, '.');
450  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
451  $conf['emboss.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
452  $isStdWrapped[$parameter] = 1;
453  }
454  }
455  $this->‪makeEmboss($this->im, $conf['emboss.'], $this->workArea, $conf);
456  }
457  if (is_array($conf['outline.'])) {
458  $isStdWrapped = [];
459  foreach ($conf['outline.'] as $key => $value) {
460  $parameter = rtrim($key, '.');
461  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
462  $conf['outline.'][$parameter] = $this->cObj->stdWrap($conf[$parameter], $conf[$parameter . '.']);
463  $isStdWrapped[$parameter] = 1;
464  }
465  }
466  $this->‪makeOutline($this->im, $conf['outline.'], $this->workArea, $conf);
467  }
468  $conf['imgMap'] = 1;
469  $this->‪makeText($this->im, $conf, $this->workArea);
470  }
471  break;
472  case 'OUTLINE':
473  if ($this->setup[$conf['textObjNum']] === 'TEXT' && ($txtConf = $this->‪checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
474  $this->‪makeOutline($this->im, $conf, $this->workArea, $txtConf);
475  }
476  break;
477  case 'EMBOSS':
478  if ($this->setup[$conf['textObjNum']] === 'TEXT' && ($txtConf = $this->‪checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
479  $this->‪makeEmboss($this->im, $conf, $this->workArea, $txtConf);
480  }
481  break;
482  case 'SHADOW':
483  if ($this->setup[$conf['textObjNum']] === 'TEXT' && ($txtConf = $this->‪checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
484  $this->‪makeShadow($this->im, $conf, $this->workArea, $txtConf);
485  }
486  break;
487  case 'BOX':
488  $this->‪makeBox($this->im, $conf, $this->workArea);
489  break;
490  case 'EFFECT':
491  $this->‪makeEffect($this->im, $conf);
492  break;
493  case 'ADJUST':
494  $this->‪adjust($this->im, $conf);
495  break;
496  case 'CROP':
497  $this->‪crop($this->im, $conf);
498  break;
499  case 'SCALE':
500  $this->‪scale($this->im, $conf);
501  break;
502  case 'WORKAREA':
503  if ($conf['set']) {
504  // this sets the workArea
505  $this->‪setWorkArea($conf['set']);
506  }
507  if (isset($conf['clear'])) {
508  // This sets the current to the default;
509  $this->workArea = ‪$this->defaultWorkArea;
510  }
511  break;
512  case 'ELLIPSE':
513  $this->‪makeEllipse($this->im, $conf, $this->workArea);
514  break;
515  }
516  }
517  }
518  }
519  // Preserve alpha transparency
520  if (!$this->saveAlphaLayer) {
521  if ($this->setup['transparentBackground']) {
522  // Auto transparent background is set
523  $Bcolor = imagecolorclosest($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
524  imagecolortransparent($this->im, $Bcolor);
525  } elseif (is_array($this->setup['transparentColor_array'])) {
526  // Multiple transparent colors are set. This is done via the trick that all transparent colors get
527  // converted to one color and then this one gets set as transparent as png/gif can just have one
528  // transparent color.
529  $Tcolor = $this->‪unifyColors($this->im, $this->setup['transparentColor_array'], (int)$this->setup['transparentColor.']['closest']);
530  if ($Tcolor >= 0) {
531  imagecolortransparent($this->im, $Tcolor);
532  }
533  }
534  }
535  }
536 
537  /*********************************************
538  *
539  * Various helper functions
540  *
541  ********************************************/
553  public function ‪checkTextObj($conf)
554  {
555  ‪$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
556  ‪$cObj->‪start($this->data);
557  $isStdWrapped = [];
558  foreach ($conf as $key => $value) {
559  $parameter = rtrim($key, '.');
560  if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
561  $conf[$parameter] = ‪$cObj->‪stdWrap($conf[$parameter], $conf[$parameter . '.']);
562  $isStdWrapped[$parameter] = 1;
563  }
564  }
565 
566  if (!is_null($conf['fontFile'])) {
567  $conf['fontFile'] = $this->‪checkFile($conf['fontFile']);
568  }
569  if (!$conf['fontFile']) {
570  $conf['fontFile'] = $this->‪checkFile('EXT:core/Resources/Private/Font/nimbus.ttf');
571  }
572  if (!$conf['iterations']) {
573  $conf['iterations'] = 1;
574  }
575  if (!$conf['fontSize']) {
576  $conf['fontSize'] = 12;
577  }
578  // If any kind of spacing applys, we cannot use angles!!
579  if ($conf['spacing'] || $conf['wordSpacing']) {
580  $conf['angle'] = 0;
581  }
582  if (!isset($conf['antiAlias'])) {
583  $conf['antiAlias'] = 1;
584  }
585  $conf['fontColor'] = trim($conf['fontColor']);
586  // Strip HTML
587  if (!$conf['doNotStripHTML']) {
588  $conf['text'] = strip_tags($conf['text']);
589  }
590  $this->combinedTextStrings[] = strip_tags($conf['text']);
591  // Max length = 100 if automatic line braks are not defined:
592  if (!isset($conf['breakWidth']) || !$conf['breakWidth']) {
593  $tlen = (int)$conf['textMaxLength'] ?: 100;
594  $conf['text'] = mb_substr($conf['text'], 0, $tlen, 'utf-8');
595  }
596  if ((string)$conf['text'] != '') {
597  // Char range map thingie:
598  $fontBaseName = ‪PathUtility::basename($conf['fontFile']);
599  if (is_array($this->charRangeMap[$fontBaseName])) {
600  // Initialize splitRendering array:
601  if (!is_array($conf['splitRendering.'])) {
602  $conf['splitRendering.'] = [];
603  }
604  $cfgK = $this->charRangeMap[$fontBaseName]['cfgKey'];
605  // Do not impose settings if a splitRendering object already exists:
606  if (!isset($conf['splitRendering.'][$cfgK])) {
607  // Set configuration:
608  $conf['splitRendering.'][$cfgK] = 'charRange';
609  $conf['splitRendering.'][$cfgK . '.'] = $this->charRangeMap[$fontBaseName]['charMapConfig'];
610  // Multiplicator of fontsize:
611  if ($this->charRangeMap[$fontBaseName]['multiplicator']) {
612  $conf['splitRendering.'][$cfgK . '.']['fontSize'] = round($conf['fontSize'] * $this->charRangeMap[$fontBaseName]['multiplicator']);
613  }
614  // Multiplicator of pixelSpace:
615  if ($this->charRangeMap[$fontBaseName]['pixelSpace']) {
616  $travKeys = ['xSpaceBefore', 'xSpaceAfter', 'ySpaceBefore', 'ySpaceAfter'];
617  foreach ($travKeys as $pxKey) {
618  if (isset($conf['splitRendering.'][$cfgK . '.'][$pxKey])) {
619  $conf['splitRendering.'][$cfgK . '.'][$pxKey] = round($conf['splitRendering.'][$cfgK . '.'][$pxKey] * ($conf['fontSize'] / $this->charRangeMap[$fontBaseName]['pixelSpace']));
620  }
621  }
622  }
623  }
624  }
625  if (is_array($conf['splitRendering.'])) {
626  foreach ($conf['splitRendering.'] as $key => $value) {
627  if (is_array($conf['splitRendering.'][$key])) {
628  if (isset($conf['splitRendering.'][$key]['fontFile'])) {
629  $conf['splitRendering.'][$key]['fontFile'] = $this->‪checkFile($conf['splitRendering.'][$key]['fontFile']);
630  }
631  }
632  }
633  }
634  return $conf;
635  }
636  return null;
637  }
638 
650  public function ‪calcOffset($string)
651  {
652  $value = [];
653  $numbers = GeneralUtility::trimExplode(',', $this->‪calculateFunctions($string));
654  foreach ($numbers as $key => $val) {
655  if ((string)$val == (string)(int)$val) {
656  $value[$key] = (int)$val;
657  } else {
658  $value[$key] = $this->‪calculateValue($val);
659  }
660  }
661  $string = implode(',', $value);
662  return $string;
663  }
664 
674  public function ‪getResource($file, $fileArray)
675  {
676  if (!in_array($fileArray['ext'], $this->imageFileExt, true)) {
677  $fileArray['ext'] = ‪$this->gifExtension;
678  }
680  ‪$cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
681  ‪$cObj->‪start($this->data);
682  return ‪$cObj->‪getImgResource($file, $fileArray);
683  }
684 
693  public function ‪checkFile($file)
694  {
695  try {
696  return GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($file);
697  } catch (\‪TYPO3\CMS\Core\Resource\‪Exception $e) {
698  return null;
699  }
700  }
701 
712  public function ‪fileName($pre)
713  {
715  $basicFileFunctions = GeneralUtility::makeInstance(BasicFileUtility::class);
716  $filePrefix = implode('_', array_merge($this->combinedTextStrings, $this->combinedFileNames));
717  $filePrefix = $basicFileFunctions->cleanFileName(ltrim($filePrefix, '.'));
718 
719  // shorten prefix to avoid overly long file names
720  $filePrefix = substr($filePrefix, 0, 100);
721 
722  return 'typo3temp/' . $pre . $filePrefix . '_' . GeneralUtility::shortMD5(serialize($this->setup)) . '.' . $this->‪extension();
723  }
724 
731  public function ‪extension()
732  {
733  switch (strtolower($this->setup['format'])) {
734  case 'jpg':
735  case 'jpeg':
736  return 'jpg';
737  case 'png':
738  return 'png';
739  case 'gif':
740  return 'gif';
741  default:
742  return ‪$this->gifExtension;
743  }
744  }
745 
753  protected function ‪calculateValue($string)
754  {
755  $calculatedValue = 0;
756  $parts = GeneralUtility::splitCalc($string, '+-*/%');
757  foreach ($parts as $part) {
758  $theVal = $part[1];
759  $sign = $part[0];
760  if (((string)(int)$theVal) == ((string)$theVal)) {
761  $theVal = (int)$theVal;
762  } elseif ('[' . substr($theVal, 1, -1) . ']' == $theVal) {
763  $objParts = explode('.', substr($theVal, 1, -1));
764  $theVal = 0;
765  if (isset($this->objBB[$objParts[0]])) {
766  if ($objParts[1] === 'w') {
767  $theVal = $this->objBB[$objParts[0]][0];
768  } elseif ($objParts[1] === 'h') {
769  $theVal = $this->objBB[$objParts[0]][1];
770  } elseif ($objParts[1] === 'lineHeight') {
771  $theVal = $this->objBB[$objParts[0]][2]['lineHeight'];
772  }
773  $theVal = (int)$theVal;
774  }
775  } elseif ((float)$theVal) {
776  $theVal = (float)$theVal;
777  } else {
778  $theVal = 0;
779  }
780  if ($sign === '-') {
781  $calculatedValue -= $theVal;
782  } elseif ($sign === '+') {
783  $calculatedValue += $theVal;
784  } elseif ($sign === '/' && $theVal) {
785  $calculatedValue = $calculatedValue / $theVal;
786  } elseif ($sign === '*') {
787  $calculatedValue = $calculatedValue * $theVal;
788  } elseif ($sign === '%' && $theVal) {
789  $calculatedValue %= $theVal;
790  }
791  }
792  return round($calculatedValue);
793  }
794 
802  protected function ‪calculateFunctions($string)
803  {
804  if (preg_match_all('#max\\(([^)]+)\\)#', $string, $matches)) {
805  foreach ($matches[1] as $index => $maxExpression) {
806  $string = str_replace($matches[0][$index], $this->‪calculateMaximum($maxExpression), $string);
807  }
808  }
809  return $string;
810  }
811 
818  protected function ‪calculateMaximum($string)
819  {
820  $parts = GeneralUtility::trimExplode(',', $this->‪calcOffset($string), true);
821  $maximum = !empty($parts) ? max($parts) : 0;
822  return $maximum;
823  }
824 }
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\calcOffset
‪string calcOffset($string)
Definition: GifBuilder.php:641
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\fontResize
‪int fontResize($conf)
Definition: GraphicalFunctions.php:909
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\checkFile
‪string null checkFile($file)
Definition: GifBuilder.php:684
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\extension
‪string extension()
Definition: GifBuilder.php:722
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\makeEffect
‪makeEffect(&$im, $conf)
Definition: GraphicalFunctions.php:1559
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\fileName
‪string fileName($pre)
Definition: GifBuilder.php:703
‪TYPO3\CMS\Core\Utility\PathUtility
Definition: PathUtility.php:23
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\convertColor
‪array convertColor($string)
Definition: GraphicalFunctions.php:1958
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\scale
‪scale(&$im, $conf)
Definition: GraphicalFunctions.php:1725
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\makeShadow
‪makeShadow(&$im, $conf, $workArea, $txtConf)
Definition: GraphicalFunctions.php:1402
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\checkTextObj
‪array checkTextObj($conf)
Definition: GifBuilder.php:544
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\setWorkArea
‪setWorkArea($workArea)
Definition: GraphicalFunctions.php:1756
‪TYPO3\CMS\Core\Core\Environment\getPublicPath
‪static string getPublicPath()
Definition: Environment.php:153
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\makeOutline
‪makeOutline(&$im, $conf, $workArea, $txtConf)
Definition: GraphicalFunctions.php:1322
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\calculateFunctions
‪string calculateFunctions($string)
Definition: GifBuilder.php:793
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\makeBox
‪makeBox(&$im, $conf, $workArea)
Definition: GraphicalFunctions.php:1500
‪TYPO3\CMS\Core\Utility\File\BasicFileUtility
Definition: BasicFileUtility.php:32
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\start
‪start($data, $table='')
Definition: ContentObjectRenderer.php:532
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\stdWrap
‪string stdWrap($content='', $conf=[])
Definition: ContentObjectRenderer.php:1542
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\output
‪string output($file)
Definition: GraphicalFunctions.php:2671
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\$myClassName
‪string $myClassName
Definition: GifBuilder.php:77
‪TYPO3
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\maskImageOntoImage
‪maskImageOntoImage(&$im, $conf, $workArea)
Definition: GraphicalFunctions.php:377
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\$workArea
‪array $workArea
Definition: GraphicalFunctions.php:176
‪TYPO3\CMS\Frontend\Resource\FilePathSanitizer
Definition: FilePathSanitizer.php:37
‪TYPO3\CMS\Core\Utility\MathUtility\forceIntegerInRange
‪static int forceIntegerInRange($theInt, $min, $max=2000000000, $defaultValue=0)
Definition: MathUtility.php:31
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\make
‪make()
Definition: GifBuilder.php:368
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\calculateValue
‪int calculateValue($string)
Definition: GifBuilder.php:744
‪TYPO3\CMS\Core\Utility\PathUtility\basename
‪static string basename($path)
Definition: PathUtility.php:164
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\$XY
‪int[] $XY
Definition: GifBuilder.php:85
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\makeEmboss
‪makeEmboss(&$im, $conf, $workArea, $txtConf)
Definition: GraphicalFunctions.php:1380
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions
Definition: GraphicalFunctions.php:35
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\calcBBox
‪array calcBBox($conf)
Definition: GraphicalFunctions.php:741
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\adjust
‪adjust(&$im, $conf)
Definition: GraphicalFunctions.php:1652
‪TYPO3\CMS\Frontend\Exception
Definition: Exception.php:23
‪TYPO3\CMS\Frontend\Imaging
Definition: GifBuilder.php:2
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\makeText
‪makeText(&$im, $conf, $workArea)
Definition: GraphicalFunctions.php:591
‪TYPO3\CMS\Core\Resource\File
Definition: File.php:23
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\$defaultWorkArea
‪array $defaultWorkArea
Definition: GifBuilder.php:93
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\unifyColors
‪int unifyColors(&$img, $colArr, $closest=false)
Definition: GraphicalFunctions.php:2843
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\destroy
‪destroy()
Definition: GraphicalFunctions.php:2713
‪TYPO3\CMS\Frontend\Imaging\GifBuilder
Definition: GifBuilder.php:52
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\getResource
‪array null getResource($file, $fileArray)
Definition: GifBuilder.php:665
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\$data
‪array $data
Definition: GifBuilder.php:69
‪TYPO3\CMS\Core\Resource\ProcessedFile
Definition: ProcessedFile.php:42
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\$objBB
‪array $objBB
Definition: GifBuilder.php:73
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\$gifExtension
‪string $gifExtension
Definition: GraphicalFunctions.php:46
‪TYPO3\CMS\Core\Utility\ArrayUtility
Definition: ArrayUtility.php:23
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\start
‪start($conf, $data)
Definition: GifBuilder.php:105
‪$GLOBALS
‪$GLOBALS['TYPO3_CONF_VARS']['EXTCONF']['adminpanel']['modules']
Definition: ext_localconf.php:5
‪TYPO3\CMS\Core\Core\Environment
Definition: Environment.php:39
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\$setup
‪array $setup
Definition: GraphicalFunctions.php:250
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\$cObj
‪ContentObjectRenderer $cObj
Definition: GifBuilder.php:89
‪TYPO3\CMS\Core\Utility\MathUtility
Definition: MathUtility.php:21
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer
Definition: ContentObjectRenderer.php:91
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\$combinedTextStrings
‪array $combinedTextStrings
Definition: GifBuilder.php:57
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\gifBuild
‪string gifBuild()
Definition: GifBuilder.php:340
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\getImgResource
‪array null getImgResource($file, $fileArray)
Definition: ContentObjectRenderer.php:4669
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\$charRangeMap
‪array $charRangeMap
Definition: GifBuilder.php:81
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\$combinedFileNames
‪array $combinedFileNames
Definition: GifBuilder.php:63
‪TYPO3\CMS\Core\Utility\GeneralUtility
Definition: GeneralUtility.php:45
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\makeEllipse
‪makeEllipse(&$im, array $conf, array $workArea)
Definition: GraphicalFunctions.php:1539
‪TYPO3\CMS\Core\Utility\ArrayUtility\filterAndSortByNumericKeys
‪static array filterAndSortByNumericKeys($setupArr, $acceptAnyKeys=false)
Definition: ArrayUtility.php:772
‪TYPO3\CMS\Frontend\Imaging\GifBuilder\calculateMaximum
‪int calculateMaximum($string)
Definition: GifBuilder.php:809
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\copyImageOntoImage
‪copyImageOntoImage(&$im, $conf, $workArea)
Definition: GraphicalFunctions.php:461
‪TYPO3\CMS\Frontend\ContentObject\ContentObjectRenderer\checkIf
‪bool checkIf($conf)
Definition: ContentObjectRenderer.php:3059
‪TYPO3\CMS\Core\Imaging\GraphicalFunctions\crop
‪crop(&$im, $conf)
Definition: GraphicalFunctions.php:1687