PathBounds::getLastModifier()   A
last analyzed

Complexity

Conditions 1
Paths 1

Size

Total Lines 4

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 2
CRAP Score 1

Importance

Changes 0
Metric Value
dl 0
loc 4
ccs 2
cts 2
cp 1
rs 10
c 0
b 0
f 0
cc 1
nc 1
nop 0
crap 1
1
<?php
2
namespace nstdio\svg\shape;
3
4
use nstdio\svg\util\Bezier;
5
6
/**
7
 * Class PathBounds
8
 *
9
 * @package nstdio\svg\shape
10
 * @author  Edgar Asatryan <[email protected]>
11
 */
12
class PathBounds
13
{
14
    private $index;
15
16
    private $modifier;
17
18
    /**
19
     * The path points positions
20
     *
21
     * @var array
22
     */
23
    private $data = [];
24
25
    private $current;
26
27
    private $rect;
28
29 26
    public function __construct()
30
    {
31 26
        $this->rect = [
32 26
            'width'  => 0,
33 26
            'height' => 0,
34 26
            'x'      => null,
35 26
            'y'      => null,
36
        ];
37 26
    }
38
39
    /**
40
     * @param string $modifier Path modifier e.g. V, L, C, M
41
     * @param array  $params
42
     */
43 26
    public function addData($modifier, array $params)
44
    {
45 26
        if ($this->isRelativeModifier($modifier)) {
46 10
            $this->addRelativeModifier($modifier, $params);
47 10
        } else {
48 26
            $this->addAbsoluteModifier($modifier, $params);
49
        }
50 26
    }
51
52
    /**
53
     * @return array
54
     */
55 16
    public function getBox()
56
    {
57 16
        foreach ($this->data as $key => $value) {
58 16
            $this->modifier = key($value);
59 16
            $this->index = $key;
60 16
            $this->current = $value[$this->modifier];
61
62 16
            if ($this->isAnyKindOfLine()) {
63 7
                $this->getLBox();
64 16
            } elseif ($this->modifier === 'Q' || $this->modifier === 'q') {
65 5
                $this->getQBox();
66 16
            } elseif ($this->modifier === 'C' || $this->modifier === 'c') {
67 7
                $this->getCBox();
68 7
            }
69 16
        }
70 16
        unset($this->modifier, $this->index, $this->current);
71
72 16
        return $this->rect;
73
    }
74
75 7
    private function getLBox()
76
    {
77 7
        list($x1, $y1) = $this->getStartPoint();
78 7
        list($x2, $y2) = $this->current;
79
80 7
        $this->union($x1, $y1, $x2, $y2);
81 7
    }
82
83 15
    private function getPreviousData()
84
    {
85 15
        $mod = $this->modifierAtIndex($this->index - 1);
86
87 15
        return $this->data[$this->index - 1][$mod];
88
    }
89
90 15
    private function modifierAtIndex($index)
91
    {
92 15
        return key($this->data[$index]);
93
    }
94
95 15
    private function union($x1, $y1, $x2, $y2)
96
    {
97 15
        $box = Rect::boxFromPoints($x1, $y1, $x2, $y2);
98
99 15
        if ($this->rect['x'] === null) {
100 15
            $this->rect['x'] = $box['x'];
101 15
            $this->rect['y'] = $box['y'];
102 15
        }
103 15
        $this->rect = Rect::union($this->rect, $box);
104 15
    }
105
106 5
    private function getQBox()
107
    {
108 5
        list($p0x, $p0y) = $this->getStartPoint();
109 5
        list($p1x, $p1y, $p2x, $p2y) = $this->current;
110
111 5
        list($x1, $y1, $x2, $y2) = Bezier::quadraticBBox($p0x, $p0y, $p1x, $p1y, $p2x, $p2y);
112
113 5
        $this->union($x1, $y1, $x2, $y2);
114 5
    }
115
116 7
    private function getCBox()
117
    {
118 7
        list($p0x, $p0y) = $this->getStartPoint();
119 7
        list($p1x, $p1y, $p2x, $p2y, $p3x, $p3y) = $this->current;
120
121 7
        list($x1, $y1, $x2, $y2) = Bezier::cubicBBox($p0x, $p0y, $p1x, $p1y, $p2x, $p2y, $p3x, $p3y);
122
123 7
        $this->union($x1, $y1, $x2, $y2);
124 7
    }
125
126
    /**
127
     * @return array
128
     */
129 15
    private function getStartPoint()
130
    {
131 15
        $x1 = $this->getNearest('x');
132 15
        $y1 = $this->getNearest('y');
133
134 15
        return [$x1, $y1];
135
    }
136
137 15
    private function getNearest($axis)
138
    {
139 15
        $prevData = $this->getPreviousData();
140 15
        $coordinate = $axis === 'x' ? $this->getStartX($prevData) : $this->getStartY($prevData);
141
142 15
        return $coordinate;
143
    }
144
145
    /**
146
     * @param string $mod
147
     *
148
     * @return bool
149
     */
150 26
    private function isRelativeModifier($mod)
151
    {
152 26
        return ctype_lower($mod);
153
    }
154
155
    /**
156
     * @param array $data
157
     *
158
     * @return float|false
159
     */
160 16
    private function getStartX($data)
161
    {
162 16
        return $data[count($data) - 2];
163
    }
164
165
    /**
166
     * @param array $data
167
     *
168
     * @return float
169
     */
170 18
    private function getStartY($data)
171
    {
172 18
        return $data[count($data) - 1];
173
    }
174
175
    /**
176
     * @return array
177
     */
178 26
    private function getLastData()
179
    {
180 26
        if (empty($this->data)) {
181 26
            return [];
182
        }
183 22
        $prevData = $this->data[count($this->data) - 1];
184 22
        $prevData = $prevData[key($prevData)];
185
186 22
        return $prevData;
187
    }
188
189 9
    private function getLastModifier()
190
    {
191 9
        return key($this->data[count($this->data) - 1]);
192
    }
193
194 16
    private function isAnyKindOfLine()
195
    {
196 16
        $mod = strtolower($this->modifier);
197 16
        return $mod === 'l' || $mod === 'h' || $mod === 'v';
198
    }
199
200
    /**
201
     * @param       $modifier
202
     * @param array $params
203
     */
204 10
    private function addRelativeModifier($modifier, array $params)
205
    {
206 10
        $prevData = $this->getLastData();
207
208 10
        if ($modifier === 'h') {
209 2
            $params[0] += $this->getStartX($prevData);
210 2
            $params[1] = $this->getStartY($prevData);
211 10 View Code Duplication
        } elseif ($modifier === 'v') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
212 4
            $y = $params[0];
213 4
            $params[0] = $this->getStartX($prevData);
214 4
            $params[1] = $y + $this->getStartY($prevData);
215 10
        } elseif ($modifier === 'l') {
216 1
            $params[0] += $this->getStartX($prevData);
217 1
            $params[1] += $this->getStartY($prevData);
218 8
        } elseif ($modifier === 'q') {
219 1
            $x = $this->getStartX($prevData);
220 1
            $y = $this->getStartY($prevData);
221
222 1
            $params[0] += $x;
223 1
            $params[1] += $y;
224 1
            $params[2] += $x;
225 1
            $params[3] += $y;
226 7
        } elseif ($modifier === 't') {
227 3
            $lastMod = $this->getLastModifier();
228 3
            $modifier = 'Q';
229 3
            $newParams = [];
230
231 3 View Code Duplication
            if ($lastMod === 'q') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
232 1
                $newParams[0] = 2 * $prevData[2] - $prevData[0];
233 1
                $newParams[1] = 2 * $prevData[3] - $prevData[1];
234 1
            } else {
235 2
                $newParams[0] = $this->getStartX($prevData);
236 2
                $newParams[1] = $this->getStartY($prevData);
237
            }
238
239 3
            $newParams[2] = $params[0] + $this->getStartX($prevData);
240 3
            $newParams[3] = $params[1] + $this->getStartY($prevData);
241
242 3
            $params = $newParams;
243 7
        } elseif ($modifier === 's') {
244 2
            $lastMod = $this->getLastModifier();
245 2
            $modifier = 'C';
246 2
            $newParams = [];
247 2 View Code Duplication
            if ($lastMod === 'c') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
248 1
                $newParams[0] = 2 * $prevData[4] - $prevData[2];
249 1
                $newParams[1] = 2 * $prevData[5] - $prevData[3];
250 1
            } else {
251 1
                $newParams[0] = $this->getStartX($prevData);
252 1
                $newParams[1] = $this->getStartY($prevData);
253
            }
254
255 2
            $x = $this->getStartX($prevData);
256 2
            $y = $this->getStartY($prevData);
257
258 2
            $newParams[2] = $params[0] + $x;
259 2
            $newParams[3] = $params[1] + $y;
260 2
            $newParams[4] = $params[2] + $x;
261 2
            $newParams[5] = $params[3] + $y;
262
263 2
            $params = $newParams;
264 5
        } elseif ($modifier === 'c') {
265 2
            $x = $this->getStartX($prevData);
266 2
            $y = $this->getStartY($prevData);
267
268 2
            $params[0] += $x;
269 2
            $params[1] += $y;
270 2
            $params[2] += $x;
271 2
            $params[3] += $y;
272 2
            $params[4] += $x;
273 2
            $params[5] += $y;
274 2
        }
275
276 10
        $this->data[] = [$modifier => $params];
277 10
    }
278
279
    /**
280
     * @param       $modifier
281
     * @param array $params
282
     */
283 26
    private function addAbsoluteModifier($modifier, array $params)
284
    {
285 26
        $prevData = $this->getLastData();
286 26
        if ($modifier === 'H') {
287 7
            $params[1] = $this->getStartY($prevData);
288 26 View Code Duplication
        } elseif ($modifier === 'V') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
289 1
            $y = $params[0];
290 1
            $params[0] = $this->getStartX($prevData);
291 1
            $params[1] = $y;
292 26
        } elseif ($modifier === 'T') {
293 3
            $lastMod = $this->getLastModifier();
294 3
            $modifier = 'Q';
295 3
            $newParams = [];
296 3 View Code Duplication
            if ($lastMod === 'Q') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
297 3
                $newParams[0] = 2 * $prevData[2] - $prevData[0];
298 3
                $newParams[1] = 2 * $prevData[3] - $prevData[1];
299 3
            } else {
300 1
                $newParams[0] = $this->getStartX($prevData);
301 1
                $newParams[1] = $this->getStartY($prevData);
302
            }
303
304 3
            $newParams[2] = $params[0];
305 3
            $newParams[3] = $params[1];
306
307 3
            $params = $newParams;
308 26
        } elseif ($modifier === 'S') {
309 3
            $lastMod = $this->getLastModifier();
310 3
            $modifier = 'C';
311 3
            $newParams = [];
312 3 View Code Duplication
            if ($lastMod === 'C') {
0 ignored issues
show
Duplication introduced by
This code seems to be duplicated across your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
313 2
                $newParams[0] = 2 * $prevData[4] - $prevData[2];
314 2
                $newParams[1] = 2 * $prevData[5] - $prevData[3];
315 2
            } else {
316 1
                $newParams[0] = $this->getStartX($prevData);
317 1
                $newParams[1] = $this->getStartY($prevData);
318
            }
319
320 3
            $newParams[2] = $params[0];
321 3
            $newParams[3] = $params[1];
322 3
            $newParams[4] = $params[2];
323 3
            $newParams[5] = $params[3];
324
325 3
            $params = $newParams;
326 3
        }
327
328 26
        $this->data[] = [$modifier => $params];
329 26
    }
330
}
331