From df0d34a14d7753741c557ab3857d82def145463a Mon Sep 17 00:00:00 2001
From: Benni Mack <benni@typo3.org>
Date: Tue, 7 Nov 2023 17:38:46 +0100
Subject: [PATCH] [TASK] Use native PHP types in protected/internal GifBuilder
 methods
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit

This change cleans up GifBuilder class
further by adding types to all internal
or protected methods.

In addition, some cleanups are done:
* Renaming of `$OFFSET` to `$offset`
* Remove superfluous checks of `is_array()`

Resolves: #102347
Releases: main
Change-Id: I7888a4240f7702e3177011847f6c63a587c40c2a
Reviewed-on: https://review.typo3.org/c/Packages/TYPO3.CMS/+/81705
Tested-by: Oliver Klee <typo3-coding@oliverklee.de>
Tested-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: Benni Mack <benni@typo3.org>
Reviewed-by: Benni Mack <benni@typo3.org>
Reviewed-by: Oliver Klee <typo3-coding@oliverklee.de>
Reviewed-by: Stefan Bürk <stefan@buerk.tech>
Tested-by: core-ci <typo3@b13.com>
---
 .../frontend/Classes/Imaging/GifBuilder.php   | 552 +++++++++---------
 1 file changed, 264 insertions(+), 288 deletions(-)

diff --git a/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php b/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php
index 90d0dd46863f..7cc1e10c86ed 100644
--- a/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php
+++ b/typo3/sysext/frontend/Classes/Imaging/GifBuilder.php
@@ -90,6 +90,7 @@ class GifBuilder
      * @var list<int>
      */
     protected array $workArea = [];
+
     /**
      * @var list<int>
      */
@@ -144,7 +145,7 @@ class GifBuilder
     /**
      * @var list<int>
      */
-    protected array $OFFSET;
+    protected array $offset;
 
     /**
      * File formats supported by gdlib. This variable gets filled in the constructor
@@ -245,10 +246,7 @@ class GifBuilder
         // Getting sorted list of TypoScript keys from setup.
         $sKeyArray = ArrayUtility::filterAndSortByNumericKeys($this->setup);
         // Setting the background color, passing it through stdWrap
-        $this->setup['backColor'] = $this->cObj->stdWrapValue('backColor', $this->setup);
-        if (!$this->setup['backColor']) {
-            $this->setup['backColor'] = 'white';
-        }
+        $this->setup['backColor'] = $this->cObj->stdWrapValue('backColor', $this->setup, 'white');
         $this->setup['transparentColor_array'] = explode('|', trim((string)$this->cObj->stdWrapValue('transparentColor', $this->setup)));
         $this->setup['transparentBackground'] = $this->cObj->stdWrapValue('transparentBackground', $this->setup);
         // Set default dimensions
@@ -411,7 +409,7 @@ class GifBuilder
         $this->XY = $XY;
         $this->w = $XY[0];
         $this->h = $XY[1];
-        $this->OFFSET = GeneralUtility::intExplode(',', $this->setup['offset']);
+        $this->offset = GeneralUtility::intExplode(',', $this->setup['offset']);
         // this sets the workArea
         $this->setWorkArea($this->setup['workArea']);
         // this sets the default to the current
@@ -528,115 +526,113 @@ class GifBuilder
             imagefilledrectangle($im, 0, 0, $XY[0], $XY[1], $Bcolor);
         }
         // Traverse the GIFBUILDER objects and render each one:
-        if (is_array($this->setup)) {
-            $sKeyArray = ArrayUtility::filterAndSortByNumericKeys($this->setup);
-            foreach ($sKeyArray as $theKey) {
-                $theValue = $this->setup[$theKey];
-                if ((int)$theKey && ($conf = $this->setup[$theKey . '.'] ?? [])) {
-                    // apply stdWrap to all properties, except for TEXT objects
-                    // all properties of the TEXT sub-object have already been stdWrap-ped
-                    // before in ->checkTextObj()
-                    if ($theValue !== 'TEXT') {
-                        $isStdWrapped = [];
-                        foreach ($conf as $key => $value) {
-                            $parameter = rtrim($key, '.');
-                            if (!($isStdWrapped[$parameter] ?? false) && isset($conf[$parameter . '.'])) {
-                                $conf[$parameter] = $this->cObj->stdWrapValue($parameter, $conf);
-                                $isStdWrapped[$parameter] = 1;
-                            }
+        $sKeyArray = ArrayUtility::filterAndSortByNumericKeys($this->setup);
+        foreach ($sKeyArray as $theKey) {
+            $theValue = $this->setup[$theKey];
+            if ((int)$theKey && ($conf = $this->setup[$theKey . '.'] ?? [])) {
+                // apply stdWrap to all properties, except for TEXT objects
+                // all properties of the TEXT sub-object have already been stdWrap-ped
+                // before in ->checkTextObj()
+                if ($theValue !== 'TEXT') {
+                    $isStdWrapped = [];
+                    foreach ($conf as $key => $value) {
+                        $parameter = rtrim($key, '.');
+                        if (!($isStdWrapped[$parameter] ?? false) && isset($conf[$parameter . '.'])) {
+                            $conf[$parameter] = $this->cObj->stdWrapValue($parameter, $conf);
+                            $isStdWrapped[$parameter] = 1;
                         }
                     }
+                }
 
-                    switch ($theValue) {
-                        case 'IMAGE':
-                            if ($conf['mask'] ?? false) {
-                                $this->maskImageOntoImage($im, $conf, $this->workArea);
-                            } else {
-                                $this->copyImageOntoImage($im, $conf, $this->workArea);
-                            }
-                            break;
-                        case 'TEXT':
-                            if (!($conf['hide'] ?? false)) {
-                                if (is_array($conf['shadow.'] ?? null)) {
-                                    $isStdWrapped = [];
-                                    foreach ($conf['shadow.'] as $key => $value) {
-                                        $parameter = rtrim($key, '.');
-                                        if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
-                                            $conf['shadow.'][$parameter] = $this->cObj->stdWrapValue($parameter, $conf);
-                                            $isStdWrapped[$parameter] = 1;
-                                        }
+                switch ($theValue) {
+                    case 'IMAGE':
+                        if ($conf['mask'] ?? false) {
+                            $this->maskImageOntoImage($im, $conf, $this->workArea);
+                        } else {
+                            $this->copyImageOntoImage($im, $conf, $this->workArea);
+                        }
+                        break;
+                    case 'TEXT':
+                        if (!($conf['hide'] ?? false)) {
+                            if (is_array($conf['shadow.'] ?? null)) {
+                                $isStdWrapped = [];
+                                foreach ($conf['shadow.'] as $key => $value) {
+                                    $parameter = rtrim($key, '.');
+                                    if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
+                                        $conf['shadow.'][$parameter] = $this->cObj->stdWrapValue($parameter, $conf);
+                                        $isStdWrapped[$parameter] = 1;
                                     }
-                                    $this->makeShadow($im, $conf['shadow.'], $this->workArea, $conf);
                                 }
-                                if (is_array($conf['emboss.'] ?? null)) {
-                                    $isStdWrapped = [];
-                                    foreach ($conf['emboss.'] as $key => $value) {
-                                        $parameter = rtrim($key, '.');
-                                        if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
-                                            $conf['emboss.'][$parameter] = $this->cObj->stdWrapValue($parameter, $conf);
-                                            $isStdWrapped[$parameter] = 1;
-                                        }
+                                $this->makeShadow($im, $conf['shadow.'], $this->workArea, $conf);
+                            }
+                            if (is_array($conf['emboss.'] ?? null)) {
+                                $isStdWrapped = [];
+                                foreach ($conf['emboss.'] as $key => $value) {
+                                    $parameter = rtrim($key, '.');
+                                    if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
+                                        $conf['emboss.'][$parameter] = $this->cObj->stdWrapValue($parameter, $conf);
+                                        $isStdWrapped[$parameter] = 1;
                                     }
-                                    $this->makeEmboss($im, $conf['emboss.'], $this->workArea, $conf);
                                 }
-                                if (is_array($conf['outline.'] ?? null)) {
-                                    $isStdWrapped = [];
-                                    foreach ($conf['outline.'] as $key => $value) {
-                                        $parameter = rtrim($key, '.');
-                                        if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
-                                            $conf['outline.'][$parameter] = $this->cObj->stdWrapValue($parameter, $conf);
-                                            $isStdWrapped[$parameter] = 1;
-                                        }
+                                $this->makeEmboss($im, $conf['emboss.'], $this->workArea, $conf);
+                            }
+                            if (is_array($conf['outline.'] ?? null)) {
+                                $isStdWrapped = [];
+                                foreach ($conf['outline.'] as $key => $value) {
+                                    $parameter = rtrim($key, '.');
+                                    if (!$isStdWrapped[$parameter] && isset($conf[$parameter . '.'])) {
+                                        $conf['outline.'][$parameter] = $this->cObj->stdWrapValue($parameter, $conf);
+                                        $isStdWrapped[$parameter] = 1;
                                     }
-                                    $this->makeOutline($im, $conf['outline.'], $this->workArea, $conf);
                                 }
-                                $this->makeText($im, $conf, $this->workArea);
-                            }
-                            break;
-                        case 'OUTLINE':
-                            if ($this->setup[$conf['textObjNum']] === 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
-                                $this->makeOutline($im, $conf, $this->workArea, $txtConf);
+                                $this->makeOutline($im, $conf['outline.'], $this->workArea, $conf);
                             }
-                            break;
-                        case 'EMBOSS':
-                            if ($this->setup[$conf['textObjNum']] === 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
-                                $this->makeEmboss($im, $conf, $this->workArea, $txtConf);
-                            }
-                            break;
-                        case 'SHADOW':
-                            if ($this->setup[$conf['textObjNum']] === 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
-                                $this->makeShadow($im, $conf, $this->workArea, $txtConf);
-                            }
-                            break;
-                        case 'BOX':
-                            $this->makeBox($im, $conf, $this->workArea);
-                            break;
-                        case 'EFFECT':
-                            $this->makeEffect($im, $conf);
-                            break;
-                        case 'ADJUST':
-                            $this->adjust($im, $conf);
-                            break;
-                        case 'CROP':
-                            $this->crop($im, $conf);
-                            break;
-                        case 'SCALE':
-                            $this->scale($im, $conf);
-                            break;
-                        case 'WORKAREA':
-                            if ($conf['set']) {
-                                // this sets the workArea
-                                $this->setWorkArea($conf['set']);
-                            }
-                            if (isset($conf['clear'])) {
-                                // This sets the current to the default;
-                                $this->workArea = $this->defaultWorkArea;
-                            }
-                            break;
-                        case 'ELLIPSE':
-                            $this->makeEllipse($im, $conf, $this->workArea);
-                            break;
-                    }
+                            $this->makeText($im, $conf, $this->workArea);
+                        }
+                        break;
+                    case 'OUTLINE':
+                        if ($this->setup[$conf['textObjNum']] === 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
+                            $this->makeOutline($im, $conf, $this->workArea, $txtConf);
+                        }
+                        break;
+                    case 'EMBOSS':
+                        if ($this->setup[$conf['textObjNum']] === 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
+                            $this->makeEmboss($im, $conf, $this->workArea, $txtConf);
+                        }
+                        break;
+                    case 'SHADOW':
+                        if ($this->setup[$conf['textObjNum']] === 'TEXT' && ($txtConf = $this->checkTextObj($this->setup[$conf['textObjNum'] . '.']))) {
+                            $this->makeShadow($im, $conf, $this->workArea, $txtConf);
+                        }
+                        break;
+                    case 'BOX':
+                        $this->makeBox($im, $conf, $this->workArea);
+                        break;
+                    case 'EFFECT':
+                        $this->makeEffect($im, $conf);
+                        break;
+                    case 'ADJUST':
+                        $this->adjust($im, $conf);
+                        break;
+                    case 'CROP':
+                        $this->crop($im, $conf);
+                        break;
+                    case 'SCALE':
+                        $this->scale($im, $conf);
+                        break;
+                    case 'WORKAREA':
+                        if ($conf['set']) {
+                            // this sets the workArea
+                            $this->setWorkArea($conf['set']);
+                        }
+                        if (isset($conf['clear'])) {
+                            // This sets the current to the default;
+                            $this->workArea = $this->defaultWorkArea;
+                        }
+                        break;
+                    case 'ELLIPSE':
+                        $this->makeEllipse($im, $conf, $this->workArea);
+                        break;
                 }
             }
         }
@@ -669,7 +665,7 @@ class GifBuilder
      * @param array $workArea The current working area coordinates.
      * @see make()
      */
-    protected function maskImageOntoImage(\GdImage &$im, $conf, $workArea)
+    protected function maskImageOntoImage(\GdImage &$im, array $conf, array $workArea): void
     {
         if ($conf['file'] && $conf['mask']) {
             $imgInf = pathinfo($conf['file']);
@@ -754,7 +750,7 @@ class GifBuilder
      * @see make()
      * @see maskImageOntoImage()
      */
-    protected function copyImageOntoImage(\GdImage &$im, $conf, $workArea)
+    protected function copyImageOntoImage(\GdImage &$im, array $conf, array $workArea): void
     {
         if ($conf['file']) {
             if (!in_array($conf['BBOX'][2], $this->gdlibExtensions, true)) {
@@ -776,7 +772,7 @@ class GifBuilder
      * @see make()
      * @internal
      */
-    public function makeText(\GdImage &$im, $conf, $workArea)
+    public function makeText(\GdImage &$im, array $conf, array $workArea): void
     {
         // Spacing
         [$spacing, $wordSpacing] = $this->calcWordSpacing($conf);
@@ -870,7 +866,7 @@ class GifBuilder
      * @see make()
      * @see makeText()
      */
-    protected function makeOutline(\GdImage &$im, $conf, $workArea, $txtConf)
+    protected function makeOutline(\GdImage &$im, array $conf, array $workArea, array $txtConf): void
     {
         $thickness = (int)$conf['thickness'];
         if ($thickness) {
@@ -900,7 +896,7 @@ class GifBuilder
      * @see make()
      * @see makeShadow()
      */
-    protected function makeEmboss(\GdImage &$im, $conf, $workArea, $txtConf)
+    protected function makeEmboss(\GdImage &$im, array $conf, array $workArea, array $txtConf): void
     {
         $conf['color'] = $conf['highColor'];
         $this->makeShadow($im, $conf, $workArea, $txtConf);
@@ -925,7 +921,7 @@ class GifBuilder
      * @see makeEmboss()
      * @internal
      */
-    public function makeShadow(\GdImage &$im, $conf, $workArea, $txtConf)
+    public function makeShadow(\GdImage &$im, array $conf, array $workArea, array $txtConf): void
     {
         $workArea = $this->applyOffset($workArea, GeneralUtility::intExplode(',', (string)($conf['offset'])));
         $blurRate = MathUtility::forceIntegerInRange((int)$conf['blur'], 0, 99);
@@ -1019,7 +1015,7 @@ class GifBuilder
      * @see make()
      * @internal
      */
-    public function makeBox(\GdImage &$im, $conf, $workArea)
+    public function makeBox(\GdImage &$im, array $conf, array $workArea): void
     {
         $cords = GeneralUtility::intExplode(',', $conf['dimensions'] . ',,,');
         $conf['offset'] = $cords[0] . ',' . $cords[1];
@@ -1058,7 +1054,7 @@ class GifBuilder
      * @param array $workArea The current working area coordinates.
      * @see make()
      */
-    public function makeEllipse(\GdImage &$im, array $conf, array $workArea)
+    public function makeEllipse(\GdImage &$im, array $conf, array $workArea): void
     {
         $ellipseConfiguration = GeneralUtility::intExplode(',', $conf['dimensions'] . ',,,');
         // Ellipse offset inside workArea (x/y)
@@ -1079,7 +1075,7 @@ class GifBuilder
      * @see make()
      * @see applyImageMagickToPHPGif()
      */
-    protected function makeEffect(\GdImage &$im, $conf)
+    protected function makeEffect(\GdImage &$im, array $conf): void
     {
         $commands = $this->IMparams($conf['value']);
         if ($commands) {
@@ -1097,7 +1093,7 @@ class GifBuilder
      * @see outputLevels()
      * @see inputLevels()
      */
-    protected function adjust(\GdImage &$im, $conf)
+    protected function adjust(\GdImage &$im, array $conf): void
     {
         $setup = $conf['value'];
         if (!trim($setup)) {
@@ -1132,7 +1128,7 @@ class GifBuilder
      * @param array $conf TypoScript array with configuration for the GIFBUILDER object.
      * @see make()
      */
-    protected function crop(\GdImage &$im, $conf)
+    protected function crop(\GdImage &$im, array $conf): void
     {
         // Clears workArea to total image
         $this->setWorkArea('');
@@ -1170,7 +1166,7 @@ class GifBuilder
      * @param array $conf TypoScript array with configuration for the GIFBUILDER object.
      * @see make()
      */
-    protected function scale(\GdImage &$im, $conf)
+    protected function scale(\GdImage &$im, array $conf): void
     {
         if ($conf['width'] || $conf['height'] || $conf['params']) {
             $tmpStr = $this->imageService->randomName();
@@ -1201,10 +1197,10 @@ class GifBuilder
      * @internal
      * @see make()
      */
-    protected function setWorkArea($workArea)
+    protected function setWorkArea(string $workArea): void
     {
         $this->workArea = GeneralUtility::intExplode(',', $workArea);
-        $this->workArea = $this->applyOffset($this->workArea, $this->OFFSET);
+        $this->workArea = $this->applyOffset($this->workArea, $this->offset);
         if (!($this->workArea[2] ?? false)) {
             $this->workArea[2] = $this->w;
         }
@@ -1228,7 +1224,7 @@ class GifBuilder
      * @param array $conf GIFBUILDER object TypoScript properties
      * @return array|null Modified $conf array IF the "text" property is not blank
      */
-    protected function checkTextObj($conf)
+    protected function checkTextObj(array $conf): ?array
     {
         $cObj = GeneralUtility::makeInstance(ContentObjectRenderer::class);
         $cObj->start($this->data);
@@ -1325,7 +1321,7 @@ class GifBuilder
      * @return string The resolved string with each part (separated by comma) returned separated by comma
      * @internal
      */
-    public function calcOffset($string)
+    public function calcOffset(string $string): string
     {
         $value = [];
         $numbers = GeneralUtility::trimExplode(',', $this->calculateFunctions($string));
@@ -1343,12 +1339,12 @@ class GifBuilder
     /**
      * Returns an "imgResource" creating an instance of the ContentObjectRenderer class and calling ContentObjectRenderer::getImgResource
      *
-     * @param string $file Filename value OR the string "GIFBUILDER", see documentation in TSref for the "datatype" called "imgResource
+     * @param string|File $file Filename value OR the string "GIFBUILDER", see documentation in TSref for the "datatype" called "imgResource" - can also be a FAL file
      * @param array $fileArray 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)
      * @return array|null Returns an array with file information from ContentObjectRenderer::getImgResource()
      * @see ContentObjectRenderer::getImgResource()
      */
-    protected function getResource($file, $fileArray)
+    protected function getResource(string|File $file, array $fileArray): ?array
     {
         $context = GeneralUtility::makeInstance(Context::class);
         $deferProcessing = !$context->hasAspect('fileProcessing') || $context->getPropertyFromAspect('fileProcessing', 'deferProcessing');
@@ -1371,7 +1367,7 @@ class GifBuilder
      * @param string $file The resource value.
      * @return string|null Returns the relative filepath or null if it's invalid
      */
-    protected function checkFile($file)
+    protected function checkFile(string $file): ?string
     {
         try {
             return GeneralUtility::makeInstance(FilePathSanitizer::class)->sanitize($file, true);
@@ -1405,7 +1401,7 @@ class GifBuilder
             $this->XY,
             $this->w,
             $this->h,
-            $this->OFFSET,
+            $this->offset,
             $this->workArea,
             $this->combinedTextStrings,
             $this->combinedFileNames,
@@ -1434,7 +1430,7 @@ class GifBuilder
      * @return int The calculated value (e.g. "23")
      * @see calcOffset()
      */
-    protected function calculateValue($string)
+    protected function calculateValue(string $string): int
     {
         $calculatedValue = 0;
         $parts = GeneralUtility::splitCalc($string, '+-*/%');
@@ -1483,7 +1479,7 @@ class GifBuilder
      * @param string $string The raw string with functions to be calculated
      * @return string The calculated values
      */
-    protected function calculateFunctions($string)
+    protected function calculateFunctions(string $string): string
     {
         if (preg_match_all('#max\\(([^)]+)\\)#', $string, $matches)) {
             foreach ($matches[1] as $index => $maxExpression) {
@@ -1496,14 +1492,13 @@ class GifBuilder
     /**
      * Calculates the maximum of a set of values defined like "[10.h],[20.h],1000"
      *
-     * @param string $string The string to be used to calculate the maximum (e.g. "[10.h],[20.h],1000")
+     * @param string $value The string to be used to calculate the maximum (e.g. "[10.h],[20.h],1000")
      * @return int The maximum value of the given comma separated and calculated values
      */
-    protected function calculateMaximum($string)
+    protected function calculateMaximum(string $value): int
     {
-        $parts = GeneralUtility::trimExplode(',', $this->calcOffset($string), true);
-        $maximum = !empty($parts) ? max($parts) : 0;
-        return $maximum;
+        $parts = GeneralUtility::trimExplode(',', $this->calcOffset($value), true);
+        return $parts !== [] ? (int)max($parts) : 0;
     }
 
     /**
@@ -1518,7 +1513,7 @@ class GifBuilder
      * @see makeBox()
      * @see crop()
      */
-    protected function objPosition($conf, $workArea, $BB)
+    protected function objPosition(array $conf, array $workArea, array $BB): array
     {
         // offset, align, valign, workarea
         $result = [];
@@ -1560,13 +1555,13 @@ class GifBuilder
      * Basically the value of key 0/1 of $OFFSET is added to keys 0/1 of $cords
      *
      * @param array $cords Integer coordinates in key 0/1
-     * @param array $OFFSET Offset values in key 0/1
+     * @param array $offset Offset values in key 0/1
      * @return array Modified $cords array
      */
-    protected function applyOffset($cords, $OFFSET)
+    protected function applyOffset(array $cords, array $offset): array
     {
-        $cords[0] = (int)$cords[0] + (int)$OFFSET[0];
-        $cords[1] = (int)($cords[1] ?? 0) + (int)($OFFSET[1] ?? 0);
+        $cords[0] = (int)$cords[0] + (int)$offset[0];
+        $cords[1] = (int)($cords[1] ?? 0) + (int)($offset[1] ?? 0);
         return $cords;
     }
 
@@ -1578,7 +1573,7 @@ class GifBuilder
      * @param array $conf TypoScript array with the properties for the IMAGE GIFBUILDER object. Only used for the "tile" property value.
      * @param array $workArea Work area
      */
-    protected function copyGifOntoGif(\GdImage &$im, \GdImage &$cpImg, $conf, $workArea)
+    protected function copyGifOntoGif(\GdImage &$im, \GdImage &$cpImg, array $conf, array $workArea): void
     {
         $cpW = imagesx($cpImg);
         $cpH = imagesy($cpImg);
@@ -1656,7 +1651,7 @@ class GifBuilder
      * @param int $srcWidth Source width
      * @param int $srcHeight Source height
      */
-    protected function imagecopyresized(\GdImage &$dstImg, \GdImage &$srcImg, $dstX, $dstY, $srcX, $srcY, $dstWidth, $dstHeight, $srcWidth, $srcHeight)
+    protected function imagecopyresized(\GdImage &$dstImg, \GdImage &$srcImg, int $dstX, int $dstY, int $srcX, int $srcY, int $dstWidth, int $dstHeight, int $srcWidth, int $srcHeight): void
     {
         if (!$this->saveAlphaLayer) {
             // Make true color image
@@ -1677,10 +1672,9 @@ class GifBuilder
      *
      * @param int $distance Distance
      * @param int $iterations Iterations.
-     * @return array
      * @see makeOutline()
      */
-    protected function circleOffset($distance, $iterations)
+    protected function circleOffset(int $distance, int $iterations): array
     {
         $res = [];
         if ($distance && $iterations) {
@@ -1706,7 +1700,7 @@ class GifBuilder
      * @return string ImageMagick prepared parameters.
      * @see makeEffect()
      */
-    protected function IMparams($setup)
+    protected function IMparams(string $setup): string
     {
         if (!trim($setup)) {
             return '';
@@ -1782,7 +1776,7 @@ class GifBuilder
      * @param array $color RGB color array
      * @return string HEX color value
      */
-    protected function hexColor($color)
+    protected function hexColor(array $color): string
     {
         $r = dechex($color[0]);
         if (strlen($r) < 2) {
@@ -1804,13 +1798,12 @@ class GifBuilder
      *
      * @param \GdImage $img Image resource
      * @param array $colArr Array containing RGB color arrays
-     * @param bool $closest
      * @return int The index of the unified color
      */
-    protected function unifyColors(\GdImage &$img, $colArr, $closest = false)
+    protected function unifyColors(\GdImage &$img, array $colArr, bool $closest): int
     {
         $retCol = -1;
-        if (is_array($colArr) && !empty($colArr) && function_exists('imagepng') && function_exists('imagecreatefrompng')) {
+        if ($colArr !== [] && function_exists('imagepng') && function_exists('imagecreatefrompng')) {
             $firstCol = array_shift($colArr);
             $firstColArr = $this->convertColor($firstCol);
             $origName = $preName = $this->imageService->randomName() . '.png';
@@ -1859,7 +1852,7 @@ class GifBuilder
      * @param string $string "HTML-color" data type string, eg. 'red', '#ffeedd' or '255,0,255'. You can also add a modifying operator afterwards. There are two options: "255,0,255 : 20" - will add 20 to values, result is "255,20,255". Or "255,0,255 : *1.23" which will multiply all RGB values with 1.23
      * @return array RGB values in key 0/1/2 of the array
      */
-    protected function convertColor($string)
+    protected function convertColor(string $string): array
     {
         $col = [];
         $cParts = explode(':', $string, 2);
@@ -1911,7 +1904,7 @@ class GifBuilder
      * @return array [0]=x, [1]=y, [2]=w, [3]=h
      * @see makeText()
      */
-    protected function txtPosition($conf, $workArea, $BB)
+    protected function txtPosition(array $conf, array $workArea, array $BB): array
     {
         $angle = (int)($conf['angle'] ?? 0) / 180 * M_PI;
         $conf['angle'] = 0;
@@ -1964,7 +1957,7 @@ class GifBuilder
      * @see txtPosition()
      * @see start()
      */
-    public function calcBBox($conf)
+    public function calcBBox(array $conf): array
     {
         $sF = $this->getTextScalFactor($conf);
         [$spacing, $wordSpacing] = $this->calcWordSpacing($conf, $sF);
@@ -2054,9 +2047,8 @@ class GifBuilder
      * @param int $wordSpacing The spacing of words in pixels
      * @param array $splitRenderingConf Array
      * @param int $sF Scale factor
-     * @internal
      */
-    protected function SpacedImageTTFText(\GdImage &$im, $fontSize, $angle, $x, $y, $Fcolor, $fontFile, $text, $spacing, $wordSpacing, $splitRenderingConf, $sF = 1)
+    protected function SpacedImageTTFText(\GdImage &$im, int $fontSize, int $angle, int $x, int $y, int $Fcolor, string $fontFile, string $text, int $spacing, int $wordSpacing, array $splitRenderingConf, int $sF = 1): void
     {
         $spacing *= $sF;
         $wordSpacing *= $sF;
@@ -2088,7 +2080,7 @@ class GifBuilder
      * @return int The new fontSize
      * @see start()
      */
-    protected function fontResize($conf)
+    protected function fontResize(array $conf): int
     {
         // You have to use +calc options like [10.h] in 'offset' to get the right position of your text-image, if you use +calc in XY height!!!!
         $maxWidth = (int)$conf['maxWidth'];
@@ -2129,7 +2121,7 @@ class GifBuilder
      * @param int $sF Scale factor
      * @return array Information array.
      */
-    protected function ImageTTFBBoxWrapper($fontSize, $angle, $fontFile, $string, $splitRendering, $sF = 1)
+    protected function ImageTTFBBoxWrapper(int $fontSize, int $angle, string $fontFile, string $string, array $splitRendering, int $sF = 1): array
     {
         // Initialize:
         $offsetInfo = [];
@@ -2171,7 +2163,7 @@ class GifBuilder
      * @param array $splitRendering Split-rendering configuration
      * @param int $sF Scale factor
      */
-    protected function ImageTTFTextWrapper(\GdImage &$im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering, $sF = 1)
+    protected function ImageTTFTextWrapper(\GdImage &$im, int $fontSize, int $angle, int $x, int $y, int $color, string $fontFile, string $string, array $splitRendering, int $sF = 1): void
     {
         // Initialize:
         $stringParts = $this->splitString($string, $splitRendering, $fontSize, $fontFile);
@@ -2215,7 +2207,7 @@ class GifBuilder
      * @param string $fontFile Current font file
      * @return array Array with input string splitted according to configuration
      */
-    protected function splitString($string, $splitRendering, $fontSize, $fontFile)
+    protected function splitString(string $string, array $splitRendering, int $fontSize, string $fontFile): array
     {
         // Initialize by setting the whole string and default configuration as the first entry.
         $result = [];
@@ -2226,119 +2218,117 @@ class GifBuilder
         ];
         // Traverse the split-rendering configuration:
         // Splitting will create more entries in $result with individual configurations.
-        if (is_array($splitRendering)) {
-            $sKeyArray = ArrayUtility::filterAndSortByNumericKeys($splitRendering);
-            // Traverse configured options:
-            foreach ($sKeyArray as $key) {
-                $cfg = $splitRendering[$key . '.'];
-                // Process each type of split rendering keyword:
-                switch ((string)$splitRendering[$key]) {
-                    case 'highlightWord':
-                        if ((string)$cfg['value'] !== '') {
-                            $newResult = [];
-                            // Traverse the current parts of the result array:
-                            foreach ($result as $part) {
-                                // Explode the string value by the word value to highlight:
-                                $explodedParts = explode($cfg['value'], $part['str']);
-                                foreach ($explodedParts as $c => $expValue) {
-                                    if ((string)$expValue !== '') {
-                                        $newResult[] = array_merge($part, ['str' => $expValue]);
-                                    }
-                                    if ($c + 1 < count($explodedParts)) {
-                                        $newResult[] = [
-                                            'str' => $cfg['value'],
-                                            'fontSize' => $cfg['fontSize'] ?: $part['fontSize'],
-                                            'fontFile' => $cfg['fontFile'] ?: $part['fontFile'],
-                                            'color' => $cfg['color'],
-                                            'xSpaceBefore' => $cfg['xSpaceBefore'],
-                                            'xSpaceAfter' => $cfg['xSpaceAfter'],
-                                            'ySpaceBefore' => $cfg['ySpaceBefore'],
-                                            'ySpaceAfter' => $cfg['ySpaceAfter'],
-                                        ];
-                                    }
+        $sKeyArray = ArrayUtility::filterAndSortByNumericKeys($splitRendering);
+        // Traverse configured options:
+        foreach ($sKeyArray as $key) {
+            $cfg = $splitRendering[$key . '.'];
+            // Process each type of split rendering keyword:
+            switch ((string)$splitRendering[$key]) {
+                case 'highlightWord':
+                    if ((string)$cfg['value'] !== '') {
+                        $newResult = [];
+                        // Traverse the current parts of the result array:
+                        foreach ($result as $part) {
+                            // Explode the string value by the word value to highlight:
+                            $explodedParts = explode($cfg['value'], $part['str']);
+                            foreach ($explodedParts as $c => $expValue) {
+                                if ((string)$expValue !== '') {
+                                    $newResult[] = array_merge($part, ['str' => $expValue]);
+                                }
+                                if ($c + 1 < count($explodedParts)) {
+                                    $newResult[] = [
+                                        'str' => $cfg['value'],
+                                        'fontSize' => $cfg['fontSize'] ?: $part['fontSize'],
+                                        'fontFile' => $cfg['fontFile'] ?: $part['fontFile'],
+                                        'color' => $cfg['color'],
+                                        'xSpaceBefore' => $cfg['xSpaceBefore'],
+                                        'xSpaceAfter' => $cfg['xSpaceAfter'],
+                                        'ySpaceBefore' => $cfg['ySpaceBefore'],
+                                        'ySpaceAfter' => $cfg['ySpaceAfter'],
+                                    ];
                                 }
-                            }
-                            // Set the new result as result array:
-                            if (!empty($newResult)) {
-                                $result = $newResult;
                             }
                         }
-                        break;
-                    case 'charRange':
-                        if ((string)$cfg['value'] !== '') {
-                            // Initialize range:
-                            $ranges = GeneralUtility::trimExplode(',', $cfg['value'], true);
-                            foreach ($ranges as $i => $rangeDef) {
-                                $ranges[$i] = GeneralUtility::intExplode('-', $rangeDef);
-                                if (!isset($ranges[$i][1])) {
-                                    $ranges[$i][1] = $ranges[$i][0];
-                                }
+                        // Set the new result as result array:
+                        if (!empty($newResult)) {
+                            $result = $newResult;
+                        }
+                    }
+                    break;
+                case 'charRange':
+                    if ((string)$cfg['value'] !== '') {
+                        // Initialize range:
+                        $ranges = GeneralUtility::trimExplode(',', $cfg['value'], true);
+                        foreach ($ranges as $i => $rangeDef) {
+                            $ranges[$i] = GeneralUtility::intExplode('-', $rangeDef);
+                            if (!isset($ranges[$i][1])) {
+                                $ranges[$i][1] = $ranges[$i][0];
                             }
-                            $newResult = [];
-                            // Traverse the current parts of the result array:
-                            foreach ($result as $part) {
-                                // Initialize:
-                                $currentState = -1;
-                                $bankAccum = '';
-                                // Explode the string value by the word value to highlight:
-                                $utf8Chars = $this->csConvObj->utf8_to_numberarray($part['str']);
-                                foreach ($utf8Chars as $utfChar) {
-                                    // Find number and evaluate position:
-                                    $uNumber = (int)$this->csConvObj->utf8CharToUnumber($utfChar);
-                                    $inRange = 0;
-                                    foreach ($ranges as $rangeDef) {
-                                        if ($uNumber >= $rangeDef[0] && (!$rangeDef[1] || $uNumber <= $rangeDef[1])) {
-                                            $inRange = 1;
-                                            break;
-                                        }
-                                    }
-                                    if ($currentState == -1) {
-                                        $currentState = $inRange;
-                                    }
-                                    // Initialize first char
-                                    // Switch bank:
-                                    if ($inRange != $currentState && $uNumber !== 9 && $uNumber !== 10 && $uNumber !== 13 && $uNumber !== 32) {
-                                        // Set result:
-                                        if ($bankAccum !== '') {
-                                            $newResult[] = [
-                                                'str' => $bankAccum,
-                                                'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
-                                                'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
-                                                'color' => $currentState ? $cfg['color'] : '',
-                                                'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
-                                                'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
-                                                'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
-                                                'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
-                                            ];
-                                        }
-                                        // Initialize new settings:
-                                        $currentState = $inRange;
-                                        $bankAccum = '';
+                        }
+                        $newResult = [];
+                        // Traverse the current parts of the result array:
+                        foreach ($result as $part) {
+                            // Initialize:
+                            $currentState = -1;
+                            $bankAccum = '';
+                            // Explode the string value by the word value to highlight:
+                            $utf8Chars = $this->csConvObj->utf8_to_numberarray($part['str']);
+                            foreach ($utf8Chars as $utfChar) {
+                                // Find number and evaluate position:
+                                $uNumber = (int)$this->csConvObj->utf8CharToUnumber($utfChar);
+                                $inRange = 0;
+                                foreach ($ranges as $rangeDef) {
+                                    if ($uNumber >= $rangeDef[0] && (!$rangeDef[1] || $uNumber <= $rangeDef[1])) {
+                                        $inRange = 1;
+                                        break;
                                     }
-                                    // Add char to bank:
-                                    $bankAccum .= $utfChar;
                                 }
-                                // Set result for FINAL part:
-                                if ($bankAccum !== '') {
-                                    $newResult[] = [
-                                        'str' => $bankAccum,
-                                        'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
-                                        'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
-                                        'color' => $currentState ? $cfg['color'] : '',
-                                        'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
-                                        'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
-                                        'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
-                                        'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
-                                    ];
+                                if ($currentState == -1) {
+                                    $currentState = $inRange;
+                                }
+                                // Initialize first char
+                                // Switch bank:
+                                if ($inRange != $currentState && $uNumber !== 9 && $uNumber !== 10 && $uNumber !== 13 && $uNumber !== 32) {
+                                    // Set result:
+                                    if ($bankAccum !== '') {
+                                        $newResult[] = [
+                                            'str' => $bankAccum,
+                                            'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
+                                            'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
+                                            'color' => $currentState ? $cfg['color'] : '',
+                                            'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
+                                            'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
+                                            'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
+                                            'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
+                                        ];
+                                    }
+                                    // Initialize new settings:
+                                    $currentState = $inRange;
+                                    $bankAccum = '';
                                 }
+                                // Add char to bank:
+                                $bankAccum .= $utfChar;
                             }
-                            // Set the new result as result array:
-                            if (!empty($newResult)) {
-                                $result = $newResult;
+                            // Set result for FINAL part:
+                            if ($bankAccum !== '') {
+                                $newResult[] = [
+                                    'str' => $bankAccum,
+                                    'fontSize' => $currentState && $cfg['fontSize'] ? $cfg['fontSize'] : $part['fontSize'],
+                                    'fontFile' => $currentState && $cfg['fontFile'] ? $cfg['fontFile'] : $part['fontFile'],
+                                    'color' => $currentState ? $cfg['color'] : '',
+                                    'xSpaceBefore' => $currentState ? $cfg['xSpaceBefore'] : '',
+                                    'xSpaceAfter' => $currentState ? $cfg['xSpaceAfter'] : '',
+                                    'ySpaceBefore' => $currentState ? $cfg['ySpaceBefore'] : '',
+                                    'ySpaceAfter' => $currentState ? $cfg['ySpaceAfter'] : '',
+                                ];
                             }
                         }
-                        break;
-                }
+                        // Set the new result as result array:
+                        if (!empty($newResult)) {
+                            $result = $newResult;
+                        }
+                    }
+                    break;
             }
         }
         return $result;
@@ -2352,7 +2342,7 @@ class GifBuilder
      * @return array Array with two keys [0]/[1] being array($spacing,$wordSpacing)
      * @see calcBBox()
      */
-    protected function calcWordSpacing($conf, $scaleFactor = 1)
+    protected function calcWordSpacing(array $conf, int $scaleFactor = 1): array
     {
         $spacing = (int)($conf['spacing'] ?? 0);
         $wordSpacing = (int)($conf['wordSpacing'] ?? 0);
@@ -2368,12 +2358,11 @@ class GifBuilder
      * @param array $conf TypoScript array for the TEXT GIFBUILDER object
      * @return int TypoScript value from eg $conf['niceText.']['scaleFactor']
      */
-    protected function getTextScalFactor($conf)
+    protected function getTextScalFactor(array $conf): int
     {
         if (!($conf['niceText'] ?? false)) {
             $sF = 1;
         } else {
-            // NICETEXT::
             $sF = MathUtility::forceIntegerInRange(($conf['niceText.']['scaleFactor'] ?? 2), 2, 5);
         }
         return $sF;
@@ -2394,7 +2383,7 @@ class GifBuilder
      * @param array $conf The configuration
      * @param int $sF Scale factor
      */
-    protected function renderTTFText(\GdImage &$im, $fontSize, $angle, $x, $y, $color, $fontFile, $string, $splitRendering, $conf, $sF = 1)
+    protected function renderTTFText(\GdImage &$im, int $fontSize, int $angle, int $x, int $y, int $color, string $fontFile, string $string, array $splitRendering, array $conf, int $sF = 1): void
     {
         if (isset($conf['breakWidth']) && $conf['breakWidth'] && $this->getRenderedTextWidth($string, $conf) > $conf['breakWidth']) {
             $phrase = '';
@@ -2429,11 +2418,8 @@ class GifBuilder
 
     /**
      * Gets the word pairs used for automatic line breaks.
-     *
-     * @param string $string
-     * @return array
      */
-    protected function getWordPairsForLineBreak($string)
+    protected function getWordPairsForLineBreak(string $string): array
     {
         $wordPairs = [];
         $wordsArray = preg_split('#([- .,!:]+)#', $string, -1, PREG_SPLIT_DELIM_CAPTURE);
@@ -2447,12 +2433,8 @@ class GifBuilder
 
     /**
      * Gets the rendered text width
-     *
-     * @param string $text
-     * @param array $conf
-     * @return int
      */
-    protected function getRenderedTextWidth($text, $conf)
+    protected function getRenderedTextWidth(string $text, array $conf): int
     {
         $bounds = $this->ImageTTFBBoxWrapper($conf['fontSize'], $conf['angle'], $conf['fontFile'], $text, $conf['splitRendering.']);
         if ($conf['angle'] < 0) {
@@ -2462,19 +2444,19 @@ class GifBuilder
         } else {
             $pixelWidth = abs($bounds[4] - $bounds[6]);
         }
-        return $pixelWidth;
+        return (int)$pixelWidth;
     }
 
     /**
      * Gets the break space for each new line.
      *
      * @param array $conf TypoScript configuration for the currently rendered object
-     * @param array $boundingBox The bounding box the the currently rendered object
+     * @param array $boundingBox The bounding box for the currently rendered object
      * @return int The break space
      */
-    protected function getBreakSpace($conf, array $boundingBox = null)
+    protected function getBreakSpace(array $conf, array $boundingBox = []): int
     {
-        if (!isset($boundingBox)) {
+        if ($boundingBox === []) {
             $boundingBox = $this->calcBBox($conf);
             $boundingBox = $boundingBox[2];
         }
@@ -2483,7 +2465,7 @@ class GifBuilder
         } else {
             $breakSpace = $boundingBox['lineHeight'];
         }
-        return $breakSpace;
+        return (int)$breakSpace;
     }
 
     /**
@@ -2493,7 +2475,7 @@ class GifBuilder
      * @param float $fontSize font size for freetype function call
      * @return float compensated font size based on 96 dpi
      */
-    protected function compensateFontSizeiBasedOnFreetypeDpi($fontSize)
+    protected function compensateFontSizeiBasedOnFreetypeDpi(float $fontSize): float
     {
         return $fontSize / 96.0 * 72;
     }
@@ -2508,7 +2490,7 @@ class GifBuilder
      *
      * @param \GdImage $im GDlib Image Pointer
      */
-    protected function autolevels(\GdImage &$im)
+    protected function autolevels(\GdImage &$im): void
     {
         $totalCols = imagecolorstotal($im);
         $grayArr = [];
@@ -2536,18 +2518,12 @@ class GifBuilder
      * @param \GdImage $im GDlib Image Pointer
      * @param int $low The "low" value (close to 0)
      * @param int $high The "high" value (close to 255)
-     * @param bool $swap If swap, then low and high are swapped. (Useful for negated masks...)
      */
-    protected function outputLevels(\GdImage &$im, $low, $high, $swap = false)
+    protected function outputLevels(\GdImage &$im, int $low, int $high): void
     {
         if ($low < $high) {
             $low = MathUtility::forceIntegerInRange($low, 0, 255);
             $high = MathUtility::forceIntegerInRange($high, 0, 255);
-            if ($swap) {
-                $temp = $low;
-                $low = 255 - $high;
-                $high = 255 - $temp;
-            }
             $delta = $high - $low;
             $totalCols = imagecolorstotal($im);
             for ($c = 0; $c < $totalCols; $c++) {
@@ -2567,7 +2543,7 @@ class GifBuilder
      * @param int $low The "low" value (close to 0)
      * @param int $high The "high" value (close to 255)
      */
-    protected function inputLevels(\GdImage &$im, $low, $high)
+    protected function inputLevels(\GdImage &$im, int $low, int $high): void
     {
         if ($low < $high) {
             $low = MathUtility::forceIntegerInRange($low, 0, 255);
@@ -2591,7 +2567,7 @@ class GifBuilder
      * @param \GdImage $im The image pointer (reference)
      * @param string $command The ImageMagick parameters. Like effects, scaling etc.
      */
-    protected function applyImageMagickToPHPGif(\GdImage &$im, $command)
+    protected function applyImageMagickToPHPGif(\GdImage &$im, string $command): void
     {
         $tmpStr = $this->imageService->randomName();
         $theFile = $tmpStr . '.png';
@@ -2711,7 +2687,7 @@ class GifBuilder
      * @throws \RuntimeException
      * @internal will soon be renamed
      */
-    public function getTemporaryImageWithText($filename, $textline1, $textline2 = '', $textline3 = '')
+    public function getTemporaryImageWithText(string $filename, string $textline1, string $textline2 = '', string $textline3 = ''): void
     {
         if (!class_exists(\GdImage::class)) {
             throw new \RuntimeException('TYPO3 Fatal Error: No gdlib. ' . $textline1 . ' ' . $textline2 . ' ' . $textline3, 1270853952);
-- 
GitLab