1
|
|
|
<?php |
2
|
|
|
namespace nstdio\svg\util\transform; |
3
|
|
|
|
4
|
|
|
/** |
5
|
|
|
* Class Packer |
6
|
|
|
* |
7
|
|
|
* @package nstdio\svg\util\transform |
8
|
|
|
* @author Edgar Asatryan <[email protected]> |
9
|
|
|
*/ |
10
|
|
|
class Packer implements PackerInterface |
11
|
|
|
{ |
12
|
|
|
|
13
|
|
|
public function pack(array $data) |
14
|
|
|
{ |
15
|
|
|
$count = count($data); |
16
|
|
|
if ($count === 1) { |
17
|
|
|
return $data; |
18
|
|
|
} |
19
|
|
|
|
20
|
|
|
for ($i = 0; $i < $count; $i++) { |
21
|
|
|
list($first, $transform) = $this->transformAndParams($data, $i); |
22
|
|
|
|
23
|
|
|
if ($i + 1 >= $count) { |
24
|
|
|
break; |
25
|
|
|
} |
26
|
|
|
|
27
|
|
|
list($second, $transform2) = $this->transformAndParams($data, $i + 1); |
28
|
|
|
|
29
|
|
|
if ($transform === $transform2) { |
30
|
|
|
$method = "sum" . ucfirst($transform); |
31
|
|
|
|
32
|
|
|
$data[$i][$transform] = $this->$method($first, $second); |
33
|
|
|
|
34
|
|
|
unset($data[$i + 1]); |
35
|
|
|
$data = array_values($data); |
36
|
|
|
$count--; |
37
|
|
|
$i--; |
38
|
|
|
} |
39
|
|
|
} |
40
|
|
|
|
41
|
|
|
return $data; |
42
|
|
|
} |
43
|
|
|
|
44
|
|
|
/** |
45
|
|
|
* @param array $data |
46
|
|
|
* @param $idx |
47
|
|
|
* |
48
|
|
|
* @return array |
49
|
|
|
*/ |
50
|
|
|
private function transformAndParams(array $data, $idx) |
51
|
|
|
{ |
52
|
|
|
$first = $data[$idx]; |
53
|
|
|
$transform = array_keys($first)[0]; |
54
|
|
|
$first = $first[$transform]; |
55
|
|
|
|
56
|
|
|
return [$first, $transform]; |
57
|
|
|
} |
58
|
|
|
|
59
|
|
|
/** |
60
|
|
|
* @param array $data |
61
|
|
|
* |
62
|
|
|
* @return mixed |
63
|
|
|
*/ |
64
|
|
|
public function toMatrix(array $data) |
65
|
|
|
{ |
66
|
|
|
foreach ($data as $key => $transformParams) { |
67
|
|
|
list($params, $transformation) = $this->transformAndParams($data, $key); |
68
|
|
|
if ($transformation === 'matrix') { // we don't need to convert matrix to matrix |
69
|
|
|
continue; |
70
|
|
|
} |
71
|
|
|
|
72
|
|
|
$method = $transformation . "ToMatrix"; |
73
|
|
|
$matrix = $this->$method($params); |
74
|
|
|
|
75
|
|
|
unset($data[$key][$transformation]); |
76
|
|
|
$data[$key]['matrix'] = $matrix; |
77
|
|
|
} |
78
|
|
|
|
79
|
|
|
return $data; |
80
|
|
|
} |
81
|
|
|
|
82
|
|
|
/** |
83
|
|
|
* @param array $scale |
84
|
|
|
* |
85
|
|
|
* @return array |
86
|
|
|
*/ |
87
|
|
|
private function scaleToMatrix(array $scale) |
88
|
|
|
{ |
89
|
|
|
$sx = $scale[0]; |
90
|
|
|
$sy = $scale[1] === null ? $sx : $scale[1]; |
91
|
|
|
|
92
|
|
|
return [$sx, 0, 0, $sy, 0, 0]; |
93
|
|
|
} |
94
|
|
|
|
95
|
|
|
private function rotateToMatrix(array $rotate) |
96
|
|
|
{ |
97
|
|
|
$angle = deg2rad($rotate[0]); |
98
|
|
|
|
99
|
|
|
$cos = cos($angle); |
100
|
|
|
$sin = sin($angle); |
101
|
|
|
|
102
|
|
|
return [$cos, $sin, -$sin, $cos, 0, 0]; |
103
|
|
|
} |
104
|
|
|
|
105
|
|
|
private function skewXToMatrix(array $skewX) |
106
|
|
|
{ |
107
|
|
|
$angle = deg2rad($skewX[0]); |
108
|
|
|
|
109
|
|
|
return [1, 0, tan($angle), 1, 0, 0]; |
110
|
|
|
} |
111
|
|
|
|
112
|
|
|
private function skewYToMatrix(array $skewY) |
113
|
|
|
{ |
114
|
|
|
$angle = deg2rad($skewY[0]); |
115
|
|
|
|
116
|
|
|
return [1, tan($angle), 0, 1, 0, 0]; |
117
|
|
|
} |
118
|
|
|
|
119
|
|
|
private function translateToMatrix(array $translate) |
120
|
|
|
{ |
121
|
|
|
$tx = $translate[0]; |
122
|
|
|
$ty = $translate[1] === null ? $tx : $translate[1]; |
123
|
|
|
|
124
|
|
|
return [1, 0, 0, 1, $tx, $ty]; |
125
|
|
|
} |
126
|
|
|
|
127
|
|
|
private function sumSkewX(array $first, array $second) |
128
|
|
|
{ |
129
|
|
|
return ['skewX' => $this->sumSkew($first, $second)]; |
130
|
|
|
} |
131
|
|
|
|
132
|
|
|
private function sumSkew(array $first, array $second) |
133
|
|
|
{ |
134
|
|
|
return $first[0] + $second[0]; |
135
|
|
|
} |
136
|
|
|
|
137
|
|
|
private function sumSkewY(array $first, array $second) |
138
|
|
|
{ |
139
|
|
|
return ['skewY' => $this->sumSkew($first, $second)]; |
140
|
|
|
} |
141
|
|
|
|
142
|
|
|
private function sumTranslate(array $first, array $second) |
143
|
|
|
{ |
144
|
|
|
$y = null; |
145
|
|
View Code Duplication |
if ($first[1] !== null || $second[1] !== null) { |
|
|
|
|
146
|
|
|
$y = $first[1] + $second[1]; |
147
|
|
|
} |
148
|
|
|
|
149
|
|
|
return [ |
150
|
|
|
$first[0] + $second[0], |
151
|
|
|
$y, |
152
|
|
|
]; |
153
|
|
|
} |
154
|
|
|
|
155
|
|
|
private function sumScale($first, $second) |
156
|
|
|
{ |
157
|
|
|
$firstY = $this->scaleY($first); |
158
|
|
|
$secondY = $this->scaleY($second); |
159
|
|
|
|
160
|
|
|
$resultXScale = $first[0] * $second[0]; |
161
|
|
|
$resultYScale = $firstY * $secondY; |
162
|
|
|
|
163
|
|
|
return [ |
164
|
|
|
$resultXScale, |
165
|
|
|
$resultYScale, |
166
|
|
|
]; |
167
|
|
|
} |
168
|
|
|
|
169
|
|
|
/** |
170
|
|
|
* @param array $scaleParams |
171
|
|
|
* |
172
|
|
|
* @return mixed |
173
|
|
|
*/ |
174
|
|
|
private function scaleY(array $scaleParams) |
175
|
|
|
{ |
176
|
|
|
return $scaleParams[1] === null ? $scaleParams[0] : $scaleParams[1]; |
177
|
|
|
} |
178
|
|
|
|
179
|
|
|
private function sumRotate(array $first, array $second) |
180
|
|
|
{ |
181
|
|
|
$sumRotate = $first[0] + $second[0]; |
182
|
|
|
|
183
|
|
|
$rotateCx = null; |
184
|
|
View Code Duplication |
if ($first[1] !== null || $second[1] !== null) { |
|
|
|
|
185
|
|
|
$rotateCx = ($first[1] + $second[1]) / 2; |
186
|
|
|
} |
187
|
|
|
|
188
|
|
|
$rotateCy = null; |
189
|
|
View Code Duplication |
if ($first[2] !== null || $second[2] !== null) { |
|
|
|
|
190
|
|
|
$rotateCy = ($first[2] + $second[2]) / 2; |
191
|
|
|
} |
192
|
|
|
|
193
|
|
|
return [ |
194
|
|
|
$sumRotate, |
195
|
|
|
$rotateCx, |
196
|
|
|
$rotateCy, |
197
|
|
|
]; |
198
|
|
|
} |
199
|
|
|
|
200
|
|
|
private function sumMatrix(array $first, array $second) |
201
|
|
|
{ |
202
|
|
|
$first = $this->matrixFromVector($first); |
203
|
|
|
$second = $this->matrixFromVector($second); |
204
|
|
|
|
205
|
|
|
$result = []; |
206
|
|
|
for ($i = 0; $i < 3; $i++) { |
207
|
|
|
for ($j = 0; $j < 3; $j++) { |
208
|
|
|
$t = 0; |
209
|
|
|
for ($k = 0; $k < 3; $k++) { |
210
|
|
|
$t += $first[$i][$k] * $second[$k][$j]; |
211
|
|
|
} |
212
|
|
|
$result[$i][$j] = $t; |
213
|
|
|
} |
214
|
|
|
} |
215
|
|
|
|
216
|
|
|
return [ |
217
|
|
|
$result[0][0], $result[1][0], $result[0][1], |
218
|
|
|
$result[1][1], $result[0][2], $result[1][2], |
219
|
|
|
]; |
220
|
|
|
} |
221
|
|
|
|
222
|
|
|
private function matrixFromVector(array $vector) |
223
|
|
|
{ |
224
|
|
|
return [ |
225
|
|
|
[$vector[0], $vector[2], $vector[4]], |
226
|
|
|
[$vector[1], $vector[3], $vector[5]], |
227
|
|
|
[0, 0, 1], |
228
|
|
|
]; |
229
|
|
|
} |
230
|
|
|
} |
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.