<?php
/**
 * Author: lang
 * Email: 732853989@qq.com
 * Date: 2023/3/27
 * Time: 11:10
 */

namespace Kkokk\Poster\Image\Traits;

use Kkokk\Poster\Exception\PosterException;
use Kkokk\Poster\Html\Drivers\HtmlDriverInterface;
use Kkokk\Poster\Image\Graphics\GdImageGraphicsEngine;
use Kkokk\Poster\Image\Graphics\ImagickImageGraphicsEngine;

trait GdTrait
{
    /**
     * 返回图片流或者图片
     * User: lang
     * Date: 2023/8/4
     * Time: 17:53
     * @param $type
     * @param $outfile
     * @return false|string|string[]|void
     * @throws PosterException
     */
    protected function returnImage($type, $outfile = true)
    {
        if (empty($this->image)) {
            throw new PosterException('没有创建任何资源');
        }
        if ($outfile) {
            dir_exists($this->path . $this->pathname);
            if (strripos($this->filename, '.') === false) {
                $this->filename = $this->filename . '.' . $this->getType();
            }
            gd_image_save(
                $this->image,
                $type,
                $this->path . $this->pathname . DIRECTORY_SEPARATOR . $this->filename,
                $this->getQuantity()
            );
            return ['url' => $this->pathname . DIRECTORY_SEPARATOR . $this->filename];
        }
        if (PHP_SAPI === 'cli') {
            return $this->getBlob($type, $this->image);
        }

        header('Content-Type:Image/' . $this->getType());
        gd_image_save($this->image, $type, null, $this->getQuantity());
    }

    protected function getBlob($type, $image)
    {
        ob_start();
        gd_image_save($image, $type, null, $this->getQuantity());
        return ob_get_clean();
    }

    protected function getTmp($type, $image)
    {
        $output = tempnam(sys_get_temp_dir(), uniqid('gdImage'));
        gd_image_save($image, $type, $output, $this->getQuantity());
        return $output;
    }

    protected function setImage($source)
    {
        if (strpos($source, 'http') === 0) {
            throw new PosterException("Unable to set the remote source {$source}");
        }

        if (!empty($source)) {
            return gd_image_save($this->image, $this->getType(), $source, $this->getQuantity());
        }

        throw new PosterException("Source not found {$source}");
    }

    protected function createImage($src = '')
    {
        if ($src instanceof HtmlDriverInterface) {
            return $this->returnImageInfoByBlob($src->getImageBlob());
        } elseif ($src instanceof GdImageGraphicsEngine) {
            return [$src->getImage(), $src->getWidth(), $src->getHeight(), $src->getType()];
        } elseif ($src instanceof ImagickImageGraphicsEngine) {
            return $this->returnImageInfoByBlob($src->blob());
        } elseif (strpos($src, 'http') === 0) {
            return $this->returnImageInfoBySrc($src);
        } elseif (is_file_path($src)) {
            if (!file_exists($src)) {
                throw new PosterException('Image resources not found (' . $src . ')');
            }
            return $this->returnImageInfoBySrc($src);
        } else {
            return $this->returnImageInfoByBlob($src);
        }
    }

    protected function returnImageInfoByBlob($blob)
    {
        list($width, $height, $bgType) = @getimagesizefromstring($blob);

        if (empty($bgType)) {
            throw new PosterException('Image resources cannot be empty (blob)');
        }

        $bgType = image_type_to_extension($bgType, false);

        $pic = imagecreatefromstring($blob);
        return [$pic, $width, $height, $bgType];
    }

    protected function returnImageInfoBySrc($src)
    {
        list($width, $height, $bgType) = @getimagesize($src);

        if (empty($bgType)) {
            throw new PosterException('Image resources cannot be empty (' . $src . ')');
        }

        $bgType = image_type_to_extension($bgType, false);

        $getGdVersion = preg_match('~\((.*) ~', gd_info()['GD Version'], $matches);
        if ($getGdVersion && (float)$matches[1] < 2 && $bgType == 'gif') {
            $pic = imagecreatefromstring(file_get_contents($src));
        } else {
            $fun = 'imagecreatefrom' . $bgType;
            $pic = @$fun($src);
        }

        return [$pic, $width, $height, $bgType];
    }

    /**
     * 创建画布
     */
    protected function createIm($w, $h, $rgba, $alpha = false)
    {
        $cut = imagecreatetruecolor($w, $h);
        $color = $this->createColor($cut, $rgba);
        if ($alpha) {
            imagesavealpha($cut, true);
        }
        imagefill($cut, 0, 0, $color);

        return $cut;
    }

    /**
     * 获取颜色值
     */
    public function createColor($image, $rgba = [255, 255, 255])
    {
        if (empty($rgba)) {
            $rgba = [255, 255, 255];
        }
        if (!is_array($rgba)) {
            $rgba = parse_color($rgba);
        }
        if (isset($rgba[3]) && !is_null($rgba[3])) {
            return imagecolorallocatealpha($image, $rgba[0], $rgba[1], $rgba[2], $rgba[3]);
        }
        return imagecolorallocate($image, $rgba[0], $rgba[1], $rgba[2]);
    }

    /**
     * 计算渐变颜色值
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/10/18
     * Time: 16:08
     * @param $h
     * @param $i
     * @param $c1
     * @param $c2
     * @return array
     */
    protected function calcColor($h, $i, $c1, $c2)
    {
        $res = [];
        $r = abs($c2[0] - $c1[0]);
        $rr = $c2[0] - $c1[0];
        $b = abs($c2[1] - $c1[1]);
        $bb = $c2[1] - $c1[1];
        $g = abs($c2[2] - $c1[2]);
        $gg = $c2[2] - $c1[2];

        if ($r == 0) {
            $res[] = $c2[0];
        } else {
            $res[] = $rr > 0 ? ($c1[0] + $r / $h * $i) : ($c1[0] - $r / $h * $i);
        }

        if ($b == 0) {
            $res[] = $c2[1];
        } else {
            $res[] = $bb > 0 ? ($c1[1] + $b / $h * $i) : ($c1[1] - $b / $h * $i);
        }

        if ($g == 0) {
            $res[] = $c2[2];
        } else {
            $res[] = $gg > 0 ? ($c1[2] + $g / $h * $i) : ($c1[2] - $g / $h * $i);
        }

        return array_map(function ($v) {
            return intval($v);
        }, $res);
    }

    /**
     * 计算颜色渐变区块->等比分配
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/10/18
     * Time: 10:56
     * @param $rgba
     * @param $h
     * @param $i
     * @return array
     */
    protected function calcColorArea($rgbaColor, $rgbaCount, $h, $i)
    {
        // 单色
        if ($rgbaCount == 1) {
            $colorRgb = $this->calcColor($h, $i, $rgbaColor[0], $rgbaColor[0]);
        } elseif ($rgbaCount == 2) {
            // 两种颜色
            $colorRgb = $this->calcColor($h, $i, $rgbaColor[0], $rgbaColor[1]);
        } else {
            // 多种颜色 计算距离并分配颜色
            $rgbaCount = $rgbaCount - 1;
            $d = ceil($h / $rgbaCount);
            $index1 = 0;
            $index2 = 1;
            $di = 0;
            for ($j = $rgbaCount; $j > 0; $j--) {

                if ($i >= ceil((($j - 1) * $d)) && $i <= ceil($j * $d)) {
                    $index1 = $j - 1;
                    $index2 = $j;
                    $di = $i - (($j - 1) * $d);
                    break;
                }
            }
            $colorRgb = $this->calcColor($d, $di, $rgbaColor[$index1], $rgbaColor[$index2]);
        }

        return $colorRgb;
    }

    /**
     * 计算颜色渐变方向
     * @Author lang
     * @Email  : 732853989@qq.com
     * Date: 2022/10/20
     * Time: 上午12:17
     * @param $im
     * @param $rgbaColor
     * @param $rgbaCount
     * @param $to
     * @param $w
     * @param $h
     * @return mixed
     */
    protected function calcColorDirection($im, $rgbaColor, $rgbaCount, $to, $w, $h)
    {
        $to = preg_replace('~\s+~', ' ', trim($to, ' '));

        switch ($to) {
            case '':
            case 'bottom':
                $toi = $h;
                $toj = $w;
                $im = $this->linearGradientDefault($im, $toi, $toj, $rgbaColor, $rgbaCount);
                break;
            case 'top':
                $toi = $h;
                $toj = $w;
                $rgbaColor = array_reverse($rgbaColor);
                $im = $this->linearGradientDefault($im, $toi, $toj, $rgbaColor, $rgbaCount);
                break;
            case 'left':
                $toi = $w;
                $toj = $h;
                $rgbaColor = array_reverse($rgbaColor);
                $im = $this->linearGradientDefault($im, $toi, $toj, $rgbaColor, $rgbaCount, 'j', 'i');
                break;
            case 'right':
                $toi = $w;
                $toj = $h;
                $im = $this->linearGradientDefault($im, $toi, $toj, $rgbaColor, $rgbaCount, 'j', 'i');
                break;
            case 'right bottom':
            case 'bottom right':
                $toi = $w;
                $toj = $h;
                $rgbaColor = array_reverse($rgbaColor);
                $im = $this->linearGradientLeftTopRightBottomDiagonal($im, $toi, $toj, $rgbaColor, $rgbaCount);
                break;
            case 'right top':
            case 'top right':
                $toi = $w;
                $toj = $h;
                $rgbaColor = array_reverse($rgbaColor);
                $im = $this->linearGradientLeftTopRightBottomDiagonal($im, $toi, $toj, $rgbaColor, $rgbaCount, 0, $toj);
                break;
            case 'left bottom':
            case 'bottom left':
                $toi = $w;
                $toj = $h;
                $im = $this->linearGradientLeftTopRightBottomDiagonal($im, $toi, $toj, $rgbaColor, $rgbaCount, 0, $toj);
                break;
            case 'left top':
            case 'top left':
                $toi = $w;
                $toj = $h;
                $im = $this->linearGradientLeftTopRightBottomDiagonal($im, $toi, $toj, $rgbaColor, $rgbaCount);
                break;
            default:
                // code...
                break;
        }

        return $im;
    }

    /**
     * 获取渐变颜色值
     * @Author lang
     * @Email  : 732853989@qq.com
     * Date: 2022/10/20
     * Time: 上午12:15
     * @param $im
     * @param $rgbaColor
     * @param $rgbaCount
     * @param $length
     * @param $i
     * @return false|int
     */
    protected function getGradientColor($im, $rgbaColor, $rgbaCount, $length, $i)
    {
        $colorRgb = $this->calcColorArea($rgbaColor, $rgbaCount, $length, $i);
        return imagecolorallocate($im, $colorRgb[0], $colorRgb[1], $colorRgb[2]);
    }

    /**
     * 获取透明颜色值
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/10/20
     * Time: 9:37
     * @param $im
     * @param $colorRgb
     * @param $alphas
     * @return false|int
     */
    protected function getAlphasColor($im, $colorRgb, $alphas)
    {
        return imagecolorallocatealpha($im, $colorRgb[0], $colorRgb[1], $colorRgb[2], $alphas);
    }

    /**
     * 渐变处理方法
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/10/20
     * Time: 10:04
     * @param        $im        resource 画布资源
     * @param        $toi       double 宽或高
     * @param        $toj       double 高或宽
     * @param        $rgbaColor array 渐变色值
     * @param        $rgbaCount int 渐变色数量
     * @param string $ii        string x,y 变量取值替换
     * @param string $jj        string x,y 变量取值替换
     * @return resource
     */
    protected function linearGradientDefault($im, $toi, $toj, $rgbaColor, $rgbaCount, $ii = 'i', $jj = 'j')
    {

        for ($i = $toi; $i >= 0; $i--) {
            // 获取颜色
            $color = $this->getGradientColor($im, $rgbaColor, $rgbaCount, $toi, $i);
            for ($j = 0; $j < $toj; $j++) {
                imagesetpixel($im, $$jj, $$ii, $color);
            }

        }

        return $im;
    }

    /**
     * 画圆角
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/10/20
     * Time: 9:55
     * @param $im     resource 画布资源
     * @param $w      double 宽
     * @param $h      double 高
     * @param $radius int 圆角
     * @return false|\GdImage|resource
     */
    protected function setPixelRadius($im, $w, $h, $radius)
    {
        $newImage = $this->createCanvas($w, $h);;

        $maxRadius = $w > $h ? $h / 2 : $w / 2;

        list($leftTopRadius, $rightTopRadius, $leftBottomRadius, $rightBottomRadius) = poster_radius_type($radius,
            $maxRadius);

        for ($x = 0; $x < $w; $x++) {
            for ($y = 0; $y < $h; $y++) {
                $color = imagecolorat($im, $x, $y);
                if (($x >= $leftTopRadius || $y >= $leftTopRadius)
                    && (($x <= ($w - $rightTopRadius) || $y >= $rightTopRadius))
                    && (($x >= $leftBottomRadius || $y <= ($h - $leftBottomRadius)))
                    && (($x <= ($w - $rightBottomRadius)) || $y <= ($h - $rightBottomRadius))) {
                    //不在四角的范围内,直接画
                    imagesetpixel($newImage, $x, $y, $color);
                } else {
                    // 上左
                    $y_x = $leftTopRadius;
                    $y_y = $leftTopRadius;
                    if (((($x - $y_x) * ($x - $y_x) + ($y - $y_y) * ($y - $y_y)) <= ($leftTopRadius * $leftTopRadius))) {
                        imagesetpixel($newImage, $x, $y, $color);
                    }

                    // 上右
                    $y_x = $w - $rightTopRadius;
                    $y_y = $rightTopRadius;
                    if (((($x - $y_x) * ($x - $y_x) + ($y - $y_y) * ($y - $y_y)) <= ($rightTopRadius * $rightTopRadius))) {
                        imagesetpixel($newImage, $x, $y, $color);
                    }

                    //下左
                    $y_x = $leftBottomRadius;
                    $y_y = $h - $leftBottomRadius;
                    if (((($x - $y_x) * ($x - $y_x) + ($y - $y_y) * ($y - $y_y)) <= ($leftBottomRadius * $leftBottomRadius))) {
                        imagesetpixel($newImage, $x, $y, $color);
                    }

                    //下右
                    $y_x = $w - $rightBottomRadius;
                    $y_y = $h - $rightBottomRadius;
                    if (((($x - $y_x) * ($x - $y_x) + ($y - $y_y) * ($y - $y_y)) <= ($rightBottomRadius * $rightBottomRadius))) {
                        imagesetpixel($newImage, $x, $y, $color);
                    }
                }
            }
        }

        return $newImage;
    }

    /**
     * 渐变处理方法 对角 分两段循环
     * @Author lang
     * @Email  : 732853989@qq.com
     * Date: 2022/10/20
     * Time: 上午12:13
     * @param     $im
     * @param     $toi
     * @param     $toj
     * @param     $rgbaColor
     * @param     $rgbaCount
     * @param int $x
     * @param int $y
     * @return mixed
     */
    protected function linearGradientLeftTopRightBottom($im, $toi, $toj, $rgbaColor, $rgbaCount, $x = 0, $y = 0)
    {

        $toLen = max($toi, $toj);

        $len = $toi + $toj;

        $ii = $len - 1;

        if ($x == 0 && $y == 0) {
            // 从 0,0 开始
            for ($i = 0; $i < $toLen + 1; $i++) {
                //设$i为y轴坐标
                $f = 0;
                $color = $this->getGradientColor($im, $rgbaColor, $rgbaCount, $len, $ii--);
                for ($j = 0; $j <= $i; $j++) {
                    if ($j <= $toi && ($i - $j) <= $toj) {
                        if (!$f) {
                            $x = $j;
                            $y = $i - $j;
                            $f = 1;
                        }
                        imagesetpixel($im, $j, $i - $j, $color);
                    }
                }
            }
            //加入右半段
            for ($i = $x + 1; $i <= $toi; $i++) {
                $color = $this->getGradientColor($im, $rgbaColor, $rgbaCount, $len, $ii--);
                for ($j = 0; $j <= $y; $j++) {
                    if (($i + $j) <= $toi && ($y - $j) <= $toj) {
                        imagesetpixel($im, $i + $j, $y - $j, $color);
                    }
                }
            }
        } else {
            // 从 0,y 开始
            for ($i = 0; $i < $toLen + 1; $i++) {
                //设$i为y轴坐标
                $f = false;
                $color = $this->getGradientColor($im, $rgbaColor, $rgbaCount, $len, $ii--);
                for ($j = 0; $j <= $i; $j++) {
                    if ($j <= $toi && ($i - $j) <= $toj) {
                        if (!$f) {
                            $x = $j;
                            $y = $i - $j;
                            $f = true;
                        }
                        imagesetpixel($im, $j, $toj - ($i - $j), $color);
                    }
                }
            }

            //加入后半段
            for ($i = $x + 1; $i <= $toi; $i++) {
                $color = $this->getGradientColor($im, $rgbaColor, $rgbaCount, $len, $ii--);
                for ($j = 0; $j <= $y; $j++) {
                    if (($i + $j) <= $toi && ($y - $j) <= $toj) {
                        imagesetpixel($im, $i + $j, $j, $color);
                    }
                }
            }
        }

        return $im;
    }

    /**
     * 根据对角线长度循环
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/11/23
     * Time: 11:35
     * @param     $im
     * @param     $toi
     * @param     $toj
     * @param     $rgbaColor
     * @param     $rgbaCount
     * @param int $x
     * @param int $y
     * @return mixed
     */
    protected function linearGradientLeftTopRightBottomDiagonal($im, $toi, $toj, $rgbaColor, $rgbaCount, $x = 0, $y = 0)
    {
        $total = $toi + $toj + 1;    // 对角线最大循环次数
        $isRectangle = $toi != $toj; // 判断是否是长方形
        // 获取中间位置数值
        $centerNum = !$isRectangle ? $this->centerNumSquare($total) : $this->centerNumRectangle($toi, $toj);

        $ii = $total; // 颜色计算递减数值

        $toiTag = 'ii'; // 默认宽大于长
        $tojTag = 'jj'; // 默认宽大于长
        if ($toj > $toi) {  // 长大于宽
            $toiTag = 'jj';
            $tojTag = 'ii';
        }

        if ($isRectangle) { // 长方形
            for ($i = 0; $i < $total; $i++) {
                $color = $this->getGradientColor($im, $rgbaColor, $rgbaCount, $total, $ii--);
                $im = $this->getPointRectangle($im, $i, $centerNum, $total, $color, $toiTag, $tojTag, $x, $y);
            }
        } else {
            // 正方形
            for ($i = 0; $i < $total; $i++) {
                $color = $this->getGradientColor($im, $rgbaColor, $rgbaCount, $total, $ii--);
                $im = $this->getPointSquare($im, $i, $centerNum, $color, $x, $y);
            }
        }

        return $im;
    }

    /**
     * 正方形获取中间位置数值
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/11/23
     * Time: 10:38
     * @param $num
     * @return float|int
     */
    protected function centerNumSquare($num)
    {
        return $num / 2;
    }

    /**
     * 长方形获取中间位置数值
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/11/23
     * Time: 10:39
     * @param $x
     * @param $y
     * @return int
     */
    protected function centerNumRectangle($x, $y)
    {
        return $x > $y ? $y + 1 : $x + 1;
    }

    /**
     * 长方形通过对角线循环绘画
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/12/12
     * Time: 9:51
     * @param     $im
     * @param     $num
     * @param     $centerNum
     * @param     $total
     * @param     $color
     * @param     $toiTag
     * @param     $tojTag
     * @param int $x
     * @param int $y
     * @return mixed
     */
    protected function getPointRectangle($im, $num, $centerNum, $total, $color, $toiTag, $tojTag, $x = 0, $y = 0)
    {

        $len = $total - $centerNum * 2; // 求取对角线上相交线坐标到边的最大宽度数量

        $min = $centerNum;  // 从第几次循环开始保持最大宽度
        $max = $min + $len; // 到第几结束

        if ($num >= $min && $num <= $max) {
            $ii = $num - $centerNum + 1;
            for ($jj = $centerNum - 1; $jj >= 0; $jj--) {
                imagesetpixel($im, ceil($$toiTag), abs($y - floor($$tojTag)), $color);
                $ii++;
            }

        } elseif ($num > $max) {

            $num = $num - $centerNum;
            $ii = $num + 1;
            $jj = $max - $len - 1;
            for ($i = $max; $i > $num; $i--) {
                imagesetpixel($im, ceil($$toiTag), abs($y - floor($$tojTag)), $color);
                $ii++;
                $jj--;
            }

        } else {

            for ($i = 0; $i <= $num; $i++) {
                imagesetpixel($im, $i, abs($y - ($num - $i)), $color);
            }

        }

        return $im;
    }

    /**
     * 正方形通过对角线循环绘画
     * Author: lang
     * Email: 732853989@qq.com
     * Date: 2022/12/12
     * Time: 9:52
     * @param     $im
     * @param     $num
     * @param     $centerNum
     * @param     $color
     * @param int $x
     * @param int $y
     * @return mixed
     */
    protected function getPointSquare($im, $num, $centerNum, $color, $x = 0, $y = 0)
    {
        if ($num > $centerNum) {
            $num = $num - $centerNum;
            $ii = $num;
            for ($i = $centerNum; $i >= $num; $i--) {
                // $arr[] = [ceil($ii) , floor($i)];
                imagesetpixel($im, ceil($ii), abs($y - floor($i)), $color);
                $ii++;
            }
        } else {

            for ($i = 0; $i <= $num; $i++) {
                // $arr[] = [$i , $num-$i];
                imagesetpixel($im, $i, abs($y - ($num - $i)), $color);
            }
        }
        return $im;
    }

    /** 设置背景透明 */
    protected function setImageAlpha($pic, $w, $h, $transparency)
    {
        $mask = $this->createCanvas($w, $h, [255, 255, 255, $transparency]);

        for ($x = 0; $x < $w; $x++) {
            for ($y = 0; $y < $h; $y++) {
                $rgbColor = imagecolorat($pic, $x, $y);
                $thisColor = imagecolorsforindex($pic, $rgbColor);
                $color = $this->createColor($pic,
                    [$thisColor['red'], $thisColor['green'], $thisColor['blue'], $transparency]);
                imagesetpixel($mask, $x, $y, $color);
            }
        }

        return $mask;
    }

    protected function cropHandle($image, $x = 0, $y = 0, $width = 0, $height = 0)
    {
        return imagecrop($image, ['x' => $x, 'y' => $y, 'width' => $width, 'height' => $height]);
    }

    /**
     * 释放资源
     */
    public function destroyImage($resource = null)
    {
        if (is_null($resource)) {
            $resource = $this->image;
        }
        !is_resource($resource) || imagedestroy($resource);
    }

    public function createCanvas($w, $h, $rgba = [])
    {
        $image = imagecreatetruecolor($w, $h);
        if (!is_null($rgba)) {
            $rgba = empty($rgba) ? [255, 255, 255, 127] : $rgba;
            $rgba = parse_color($rgba);
            if (!empty($rgba[3])) {
                imagesavealpha($image, true);
            }
            $color = $this->createColor($image, $rgba);
            imagefill($image, 0, 0, $color);
        }

        return $image;
    }

    public function imageFontBox($text, $fontSize, $font, $angle = 0)
    {
        return imagettfbbox($fontSize, $angle, $font, $text);
    }

    public function calculateTextBox($text, $fontSize, $font, $angle)
    {
        $rect = imagettfbbox($fontSize, $angle, $font, $text);
        $minX = min([$rect[0], $rect[2], $rect[4], $rect[6]]);
        $maxX = max([$rect[0], $rect[2], $rect[4], $rect[6]]);
        $minY = min([$rect[1], $rect[3], $rect[5], $rect[7]]);
        $maxY = max([$rect[1], $rect[3], $rect[5], $rect[7]]);

        return [
            "left"   => abs($minX) - 1,
            "top"    => abs($minY) - 1,
            "width"  => abs($maxX - $minX),
            "height" => abs($maxY - $minY),
            "box"    => $rect
        ];
    }

    public function textWidth($text, $fontSize, $font, $angle = 0)
    {
        $calculateTextBox = $this->calculateTextBox($text, $fontSize, $font, $angle);
        return $calculateTextBox['width'];
    }

    public function textHeight($text, $fontSize, $font, $angle = 0)
    {
        $calculateTextBox = $this->calculateTextBox($text, $fontSize, $font ?: $this->font, $angle);
        return $calculateTextBox['height'];
    }
}