116 if (is_array($conf)) {
117 $this->setup = $conf;
119 $this->cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
120 $this->cObj->start($this->data);
127 foreach (
$GLOBALS[
'TYPO3_CONF_VARS'][
'SC_OPTIONS'][
'tslib/class.tslib_gifbuilder.php'][
'gifbuilder-ConfPreProcess'] ?? [] as $_funcRef) {
129 $this->setup = GeneralUtility::callUserFunction($_funcRef, $_params, $this);
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)) {
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'];
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'];
152 if (!$this->setup[
'backColor']) {
153 $this->setup[
'backColor'] =
'white';
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']));
158 if (isset($this->setup[
'transparentBackground.'])) {
159 $this->setup[
'transparentBackground'] = $this->cObj->stdWrap($this->setup[
'transparentBackground'], $this->setup[
'transparentBackground.']);
161 if (isset($this->setup[
'reduceColors.'])) {
162 $this->setup[
'reduceColors'] = $this->cObj->stdWrap($this->setup[
'reduceColors'], $this->setup[
'reduceColors.']);
165 if (isset($this->setup[
'XY.'])) {
166 $this->setup[
'XY'] = $this->cObj->stdWrap($this->setup[
'XY'], $this->setup[
'XY.']);
168 if (!$this->setup[
'XY']) {
169 $this->setup[
'XY'] =
'120,50';
173 foreach ($sKeyArray as $theKey) {
174 $theValue = $this->setup[$theKey];
175 if ((
int)$theKey && ($conf = $this->setup[$theKey .
'.'])) {
179 if ($this->setup[$theKey .
'.'] = $this->
checkTextObj($conf)) {
181 $maxWidth = isset($this->setup[$theKey .
'.'][
'maxWidth.']) ? $this->cObj->stdWrap($this->setup[$theKey .
'.'][
'maxWidth'], $this->setup[$theKey .
'.'][
'maxWidth.']) : $this->setup[$theKey .
'.'][
'maxWidth'];
183 $this->setup[$theKey .
'.'][
'fontSize'] = $this->
fontResize($this->setup[$theKey .
'.']);
186 $txtInfo = $this->
calcBBox($this->setup[$theKey .
'.']);
187 $this->setup[$theKey .
'.'][
'BBOX'] = $txtInfo;
188 $this->objBB[$theKey] = $txtInfo;
189 $this->setup[$theKey .
'.'][
'imgMap'] = 0;
193 $fileInfo = $this->
getResource($conf[
'file'], $conf[
'file.']);
195 $this->combinedFileNames[] = preg_replace(
'/\\.[[:alnum:]]+$/',
'',
PathUtility::basename($fileInfo[3]));
198 $this->setup[$theKey .
'.'][
'file'] = $fileInfo[
'processedFile']->getForLocalProcessing(
false);
199 } elseif (!isset($fileInfo[
'origFile']) && $fileInfo[
'originalFile'] instanceof
File) {
202 $originalFile = $fileInfo[
'originalFile'];
203 $this->setup[$theKey .
'.'][
'file'] = $originalFile->getForLocalProcessing(
false);
206 $this->setup[$theKey .
'.'][
'file'] = $fileInfo[3];
212 $essentialFileInfo = $fileInfo;
213 unset($essentialFileInfo[
'originalFile'], $essentialFileInfo[
'processedFile']);
215 $this->setup[$theKey .
'.'][
'BBOX'] = $essentialFileInfo;
216 $this->objBB[$theKey] = $essentialFileInfo;
218 $maskInfo = $this->
getResource($conf[
'mask'], $conf[
'mask.']);
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);
228 $this->setup[$theKey .
'.'][
'mask'] = $maskInfo[3];
231 $this->setup[$theKey .
'.'][
'mask'] =
'';
235 unset($this->setup[$theKey .
'.']);
241 $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
244 unset($this->setup[$theKey]);
245 unset($this->setup[$theKey .
'.']);
246 unset($this->objBB[$theKey]);
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.']);
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.']);
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 .
'.']) {
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.']);
272 if ($this->setup[$theKey .
'.'][
'offset']) {
273 $this->setup[$theKey .
'.'][
'offset'] = $this->
calcOffset($this->setup[$theKey .
'.'][
'offset']);
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.']);
283 if ($this->setup[$theKey .
'.'][
'dimensions']) {
284 $this->setup[$theKey .
'.'][
'dimensions'] = $this->
calcOffset($this->setup[$theKey .
'.'][
'dimensions']);
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.']);
292 if ($this->setup[$theKey .
'.'][
'set']) {
293 $this->setup[$theKey .
'.'][
'set'] = $this->
calcOffset($this->setup[$theKey .
'.'][
'set']);
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.']);
301 if ($this->setup[$theKey .
'.'][
'crop']) {
302 $this->setup[$theKey .
'.'][
'crop'] = $this->
calcOffset($this->setup[$theKey .
'.'][
'crop']);
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.']);
310 if ($this->setup[$theKey .
'.'][
'width']) {
311 $this->setup[$theKey .
'.'][
'width'] = $this->
calcOffset($this->setup[$theKey .
'.'][
'width']);
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.']);
317 if ($this->setup[$theKey .
'.'][
'height']) {
318 $this->setup[$theKey .
'.'][
'height'] = $this->
calcOffset($this->setup[$theKey .
'.'][
'height']);
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'];
333 $this->OFFSET = GeneralUtility::intExplode(
',', $this->setup[
'offset']);
353 $gifFileName = $this->
fileName(
'assets/images/');
355 if (!file_exists($gifFileName)) {
377 public function make()
382 $this->saveAlphaLayer =
false;
384 $this->im = imagecreatetruecolor(
$XY[0],
$XY[1]);
388 if (!empty($this->setup[
'backColor']) && $this->setup[
'backColor'] ===
'transparent' && !$this->setup[
'reduceColors'] && (empty($this->setup[
'format']) || $this->setup[
'format'] ===
'png')) {
390 imagesavealpha($this->im,
true);
392 $transparentColor = imagecolorallocatealpha($this->im, 0, 0, 0, 127);
393 imagefill($this->im, 0, 0, $transparentColor);
395 $this->saveAlphaLayer =
true;
397 $this->setup[
'format'] =
'png';
402 $Bcolor = imagecolorallocate($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
403 imagefilledrectangle($this->im, 0, 0,
$XY[0],
$XY[1], $Bcolor);
406 if (is_array($this->setup)) {
408 foreach ($sKeyArray as $theKey) {
409 $theValue = $this->setup[$theKey];
410 if ((
int)$theKey && ($conf = $this->setup[$theKey .
'.'])) {
414 if ($theValue !==
'TEXT') {
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;
434 if (!$conf[
'hide']) {
435 if (is_array($conf[
'shadow.'])) {
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;
444 $this->
makeShadow($this->im, $conf[
'shadow.'], $this->workArea, $conf);
446 if (is_array($conf[
'emboss.'])) {
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;
455 $this->
makeEmboss($this->im, $conf[
'emboss.'], $this->workArea, $conf);
457 if (is_array($conf[
'outline.'])) {
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;
466 $this->
makeOutline($this->im, $conf[
'outline.'], $this->workArea, $conf);
469 $this->
makeText($this->im, $conf, $this->workArea);
473 if ($this->setup[$conf[
'textObjNum']] ===
'TEXT' && ($txtConf = $this->
checkTextObj($this->setup[$conf[
'textObjNum'] .
'.']))) {
474 $this->
makeOutline($this->im, $conf, $this->workArea, $txtConf);
478 if ($this->setup[$conf[
'textObjNum']] ===
'TEXT' && ($txtConf = $this->
checkTextObj($this->setup[$conf[
'textObjNum'] .
'.']))) {
479 $this->
makeEmboss($this->im, $conf, $this->workArea, $txtConf);
483 if ($this->setup[$conf[
'textObjNum']] ===
'TEXT' && ($txtConf = $this->
checkTextObj($this->setup[$conf[
'textObjNum'] .
'.']))) {
484 $this->
makeShadow($this->im, $conf, $this->workArea, $txtConf);
488 $this->
makeBox($this->im, $conf, $this->workArea);
494 $this->
adjust($this->im, $conf);
497 $this->
crop($this->im, $conf);
500 $this->
scale($this->im, $conf);
507 if (isset($conf[
'clear'])) {
520 if (!$this->saveAlphaLayer) {
521 if ($this->setup[
'transparentBackground']) {
523 $Bcolor = imagecolorclosest($this->im, $BGcols[0], $BGcols[1], $BGcols[2]);
524 imagecolortransparent($this->im, $Bcolor);
525 } elseif (is_array($this->setup[
'transparentColor_array'])) {
529 $Tcolor = $this->
unifyColors($this->im, $this->setup[
'transparentColor_array'], (
int)$this->setup[
'transparentColor.'][
'closest']);
531 imagecolortransparent($this->im, $Tcolor);
555 $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
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;
566 if (!is_null($conf[
'fontFile'])) {
567 $conf[
'fontFile'] = $this->
checkFile($conf[
'fontFile']);
569 if (!$conf[
'fontFile']) {
570 $conf[
'fontFile'] = $this->
checkFile(
'EXT:core/Resources/Private/Font/nimbus.ttf');
572 if (!$conf[
'iterations']) {
573 $conf[
'iterations'] = 1;
575 if (!$conf[
'fontSize']) {
576 $conf[
'fontSize'] = 12;
579 if ($conf[
'spacing'] || $conf[
'wordSpacing']) {
582 if (!isset($conf[
'antiAlias'])) {
583 $conf[
'antiAlias'] = 1;
585 $conf[
'fontColor'] = trim($conf[
'fontColor']);
587 if (!$conf[
'doNotStripHTML']) {
588 $conf[
'text'] = strip_tags($conf[
'text']);
590 $this->combinedTextStrings[] = strip_tags($conf[
'text']);
592 if (!isset($conf[
'breakWidth']) || !$conf[
'breakWidth']) {
593 $tlen = (int)$conf[
'textMaxLength'] ?: 100;
594 $conf[
'text'] = mb_substr($conf[
'text'], 0, $tlen,
'utf-8');
596 if ((
string)$conf[
'text'] !=
'') {
599 if (is_array($this->charRangeMap[$fontBaseName])) {
601 if (!is_array($conf[
'splitRendering.'])) {
602 $conf[
'splitRendering.'] = [];
604 $cfgK = $this->charRangeMap[$fontBaseName][
'cfgKey'];
606 if (!isset($conf[
'splitRendering.'][$cfgK])) {
608 $conf[
'splitRendering.'][$cfgK] =
'charRange';
609 $conf[
'splitRendering.'][$cfgK .
'.'] = $this->charRangeMap[$fontBaseName][
'charMapConfig'];
611 if ($this->charRangeMap[$fontBaseName][
'multiplicator']) {
612 $conf[
'splitRendering.'][$cfgK .
'.'][
'fontSize'] = round($conf[
'fontSize'] * $this->charRangeMap[$fontBaseName][
'multiplicator']);
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']));
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']);
654 foreach ($numbers as $key => $val) {
655 if ((
string)$val == (
string)(
int)$val) {
656 $value[$key] = (int)$val;
661 $string = implode(
',', $value);
676 if (!in_array($fileArray[
'ext'], $this->imageFileExt,
true)) {
680 $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
696 return GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($file);
715 $basicFileFunctions = GeneralUtility::makeInstance(BasicFileUtility::class);
716 $filePrefix = implode(
'_', array_merge($this->combinedTextStrings, $this->combinedFileNames));
717 $filePrefix = $basicFileFunctions->cleanFileName(ltrim($filePrefix,
'.'));
720 $filePrefix = substr($filePrefix, 0, 100);
722 return 'typo3temp/' . $pre . $filePrefix .
'_' . GeneralUtility::shortMD5(serialize($this->setup)) .
'.' . $this->
extension();
733 switch (strtolower($this->setup[
'format'])) {
755 $calculatedValue = 0;
756 $parts = GeneralUtility::splitCalc($string,
'+-*/%');
757 foreach ($parts as $part) {
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));
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'];
773 $theVal = (int)$theVal;
775 } elseif ((
float)$theVal) {
776 $theVal = (float)$theVal;
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;
792 return round($calculatedValue);
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);
820 $parts = GeneralUtility::trimExplode(
',', $this->
calcOffset($string),
true);
821 $maximum = !empty($parts) ? max($parts) : 0;