Passed
Push — refactor_render ( 1be99d...7e011e )
by Mattia
09:18
created

BaseSkinSection::startingPoints()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 9
Code Lines 7

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 1
Metric Value
eloc 7
c 1
b 0
f 1
dl 0
loc 9
rs 10
cc 1
nc 1
nop 0
1
<?php
2
3
declare(strict_types=1);
4
5
namespace Minepic\Image\Sections;
6
7
use Minepic\Image\Components\Component;
8
use Minepic\Image\Exceptions\ImageResourceCreationFailedException;
9
use Minepic\Image\ImageSection;
10
use Minepic\Image\LayerValidator;
11
use Minepic\Image\Point;
12
13
abstract class BaseSkinSection extends ImageSection
14
{
15
    protected string $side;
16
    protected int $baseImageWidth = 16;
17
    protected int $baseImageHeight = 32;
18
19
    /**
20
     * @param int $skinHeight
21
     * @throws ImageResourceCreationFailedException
22
     * @throws \Exception
23
     */
24
    public function render(int $skinHeight = 256): void
25
    {
26
        $skinHeight = $this->checkHeight($skinHeight);
27
28
        $tmpImageResource = $this->emptyBaseImage($this->baseImageWidth, $this->baseImageHeight);
29
        foreach ($this->getAllComponents() as $componentName => $componentsData) {
30
            $this->copyComponent($tmpImageResource, $componentName, $componentsData[0], $componentsData[1] ?? null);
31
        }
32
33
        $this->patchOldSkin($tmpImageResource);
34
35
        $scale = $skinHeight / $this->baseImageHeight;
36
        if ($scale === 0) {
37
            $scale = 1;
38
        }
39
        $skinWidth = (int) \round($scale * ($this->baseImageWidth));
40
41
        $this->imgResource = $this->emptyBaseImage($skinWidth, $skinHeight);
42
        \imagecopyresized($this->imgResource, $tmpImageResource, 0, 0, 0, 0, $skinWidth, $skinHeight, $this->baseImageWidth, $this->baseImageHeight);
43
    }
44
45
    /**
46
     * In old skins (pre 1.8) left arm/leg are right arm/leg flipped
47
     * @param $tmpImageResource
48
     * @throws \Exception
49
     */
50
    protected function patchOldSkin($tmpImageResource): void
51
    {
52
        if ($this->is64x64()) {
53
            return;
54
        }
55
56
        if (\array_key_exists(Component::LEFT_ARM, $this->startingPoints())) {
57
            $this->flipComponent(
58
                $tmpImageResource,
59
                Component::getLeftArm(),
60
                Component::getRightArm(),
61
                $this->startingPoints()[Component::LEFT_ARM]
62
            );
63
        }
64
65
        if (\array_key_exists(Component::LEFT_LEG, $this->startingPoints())) {
66
            $this->flipComponent(
67
                $tmpImageResource,
68
                Component::getLeftLeg(),
69
                Component::getRightLeg(),
70
                $this->startingPoints()[Component::LEFT_LEG]
71
            );
72
        }
73
    }
74
75
    /**
76
     * @param $tmpImageResource
77
     * @param Component $dstComponent
78
     * @param Component $srcComponent
79
     * @param Point $startingPoint
80
     * @throws \Exception
81
     */
82
    protected function flipComponent($tmpImageResource, Component $dstComponent, Component $srcComponent, Point $startingPoint): void
83
    {
84
        $leftArmData = $dstComponent->getSideByIdentifier($this->side);
85
        $rightArmData = $srcComponent->getSideByIdentifier($this->side);
86
        $width = $leftArmData->getWidth();
87
        $height = $leftArmData->getHeight();
88
        $leftArm = \imagecreatetruecolor($width, $height);
89
        for ($x = 0; $x < 4; ++$x) {
90
            \imagecopy($leftArm,
91
                $this->skinResource,
92
                $x,
93
                0,
94
                $rightArmData->getBottomRight()->getX() - $x - 1,
95
                $rightArmData->getTopLeft()->getY(),
96
                1,
97
                $height
98
            );
99
        }
100
        \imagecopymerge($tmpImageResource,
101
            $leftArm,
102
            $startingPoint->getX(),
103
            $startingPoint->getY(),
104
            0,
105
            0,
106
            $width,
107
            $height,
108
        100
109
        );
110
    }
111
112
    /**
113
     * @param $skinHeight
114
     *
115
     * @return int
116
     */
117
    protected function checkHeight($skinHeight): int
118
    {
119
        if ($skinHeight === 0 || $skinHeight < 0 || $skinHeight > (int) env('MAX_SKINS_SIZE')) {
120
            $skinHeight = (int) env('DEFAULT_SKIN_SIZE');
121
        }
122
123
        return $skinHeight;
124
    }
125
126
    /**
127
     * @return Point[]
128
     */
129
    protected function startingPoints(): array
130
    {
131
        return [
132
            Component::HEAD => new Point(0, 0),
133
            Component::TORSO => new Point(0, 0),
134
            Component::RIGHT_ARM => new Point(0, 0),
135
            Component::LEFT_ARM => new Point(0, 0),
136
            Component::RIGHT_LEG => new Point(0, 0),
137
            Component::LEFT_LEG => new Point(0, 0),
138
        ];
139
    }
140
141
    /**
142
     * @return array[]
143
     */
144
    protected function getAllComponents(): array
145
    {
146
        if ($this->is64x64()) {
147
            return [
148
                Component::HEAD => [Component::getHead(), Component::getHeadLayer()],
149
                Component::TORSO => [Component::getTorso(), Component::getTorsoLayer()],
150
                Component::RIGHT_ARM => [Component::getRightArm(), Component::getRightArmLayer()],
151
                Component::LEFT_ARM => [Component::getLeftArm(), Component::getLeftArmLayer()],
152
                Component::RIGHT_LEG => [Component::getRightLeg(), Component::getRightLegLayer()],
153
                Component::LEFT_LEG => [Component::getLeftLeg(), Component::getLeftLegLayer()],
154
            ];
155
        }
156
157
        return [
158
            Component::HEAD => [Component::getHead(), Component::getHeadLayer()],
159
            Component::TORSO => [Component::getTorso()],
160
            Component::RIGHT_ARM => [Component::getRightArm()],
161
            Component::RIGHT_LEG => [Component::getRightLeg()],
162
        ];
163
    }
164
165
    /**
166
     * @param $tmpImageResource
167
     * @param string $componentName
168
     * @param Component $base
169
     * @param null|Component $layer
170
     * @throws \Exception
171
     */
172
    protected function copyComponent($tmpImageResource, string $componentName, Component $base, ?Component $layer): void
173
    {
174
        $sideBase = $base->getSideByIdentifier($this->side);
175
        $width = $sideBase->getWidth();
176
        $height = $sideBase->getHeight();
177
178
        $startingPoint = $this->startingPoints()[$componentName] ?? new Point(0, 0);
179
        \imagecopy(
180
            $tmpImageResource,
181
            $this->skinResource,
182
            $startingPoint->getX(),
183
            $startingPoint->getY(),
184
            $sideBase->getTopLeft()->getX(),
185
            $sideBase->getTopLeft()->getY(),
186
            $width,
187
            $height
188
        );
189
        if ($layer !== null && (new LayerValidator())->check($this->skinResource, $layer->getSideByIdentifier($this->side))) {
190
            $sideLayer = $layer->getSideByIdentifier($this->side);
191
            \imagecopymerge_alpha(
192
                $tmpImageResource,
193
                $this->skinResource,
194
                $startingPoint->getX(),
195
                $startingPoint->getY(),
196
                $sideLayer->getTopLeft()->getX(),
197
                $sideLayer->getTopLeft()->getY(),
198
                $width,
199
                $height,
200
                100
201
            );
202
        }
203
    }
204
}
205