1 /*
2 * Copyright (c) 2021 Huawei Device Co., Ltd.
3 * Licensed under the Apache License, Version 2.0 (the "License");
4 * you may not use this file except in compliance with the License.
5 * You may obtain a copy of the License at
6 *
7 * http://www.apache.org/licenses/LICENSE-2.0
8 *
9 * Unless required by applicable law or agreed to in writing, software
10 * distributed under the License is distributed on an "AS IS" BASIS,
11 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12 * See the License for the specific language governing permissions and
13 * limitations under the License.
14 */
15
16 #include "core/components/svg/svg_transform.h"
17
18 #include "base/utils/string_utils.h"
19
20 namespace OHOS::Ace {
21 namespace {
22
23 const char TRANSFORM_MATRIX[] = "matrix";
24 const char TRANSFORM_ROTATE[] = "rotate";
25 const char TRANSFORM_SCALE[] = "scale";
26 const char TRANSFORM_SKEW[] = "skew";
27 const char TRANSFORM_SKEWX[] = "skewX";
28 const char TRANSFORM_SKEWY[] = "skewY";
29 const char TRANSFORM_TRANSLATE[] = "translate";
30
31 } // namespace
32
33 using namespace StringUtils;
34
CreateMatrix4(const std::string & transform)35 Matrix4 SvgTransform::CreateMatrix4(const std::string& transform)
36 {
37 auto retMat = Matrix4::CreateIdentity();
38 std::vector<std::string> attrs;
39 SplitStr(transform, ")", attrs);
40 for (auto& attr : attrs) {
41 std::string type = attr.substr(0, attr.find_first_of("("));
42 std::string values = attr.substr(attr.find_first_of("(") + 1);
43 std::vector<std::string> numVec;
44 std::string tag = (values.find(",") != std::string::npos) ? "," : " ";
45 SplitStr(values, tag, numVec);
46 if (numVec.empty()) {
47 continue;
48 }
49
50 Matrix4 mat = Matrix4::CreateIdentity();
51 TrimStr(attr);
52 if (type == TRANSFORM_TRANSLATE) {
53 if (numVec.size() == 1) {
54 mat = Matrix4::CreateTranslate(StringToFloat(numVec[0].c_str()), 0, 0);
55 } else {
56 mat = Matrix4::CreateTranslate(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), 0);
57 }
58 } else if (type == TRANSFORM_SCALE) {
59 if (numVec.size() == 1) {
60 mat = Matrix4::CreateScale(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[0].c_str()), 1);
61 } else {
62 mat = Matrix4::CreateScale(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), 1);
63 }
64 } else if (type == TRANSFORM_ROTATE) {
65 mat = Matrix4::CreateRotate(StringToFloat(numVec[0].c_str()), 0, 0, 1);
66 } else if (type == TRANSFORM_SKEWX) {
67 mat = Matrix4::CreateSkew(StringToFloat(numVec[0].c_str()), 0);
68 } else if (type == TRANSFORM_SKEWY) {
69 mat = Matrix4::CreateSkew(0, StringToFloat(numVec[0].c_str()));
70 } else if (type == TRANSFORM_MATRIX && numVec.size() == 6) {
71 mat = Matrix4::CreateMatrix2D(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()),
72 StringToFloat(numVec[2].c_str()), StringToFloat(numVec[3].c_str()),
73 StringToFloat(numVec[4].c_str()), StringToFloat(numVec[5].c_str()));
74 } else {
75 continue;
76 }
77 retMat = retMat * mat;
78 }
79 return retMat;
80 }
81
CreateInfoFromString(const std::string & transform)82 TransformInfo SvgTransform::CreateInfoFromString(const std::string& transform)
83 {
84 auto retMat = Matrix4::CreateIdentity();
85 std::vector<std::string> attrs;
86 SplitStr(transform, ")", attrs);
87 TransformInfo transformInfo;
88 for (auto& attr : attrs) {
89 std::string type = attr.substr(0, attr.find_first_of("("));
90 std::string values = attr.substr(attr.find_first_of("(") + 1);
91 std::vector<std::string> numVec;
92 std::string tag = (values.find(",") != std::string::npos) ? "," : " ";
93 SplitStr(values, tag, numVec);
94 if (numVec.empty()) {
95 continue;
96 }
97
98 Matrix4 mat = Matrix4::CreateIdentity();
99 TrimStr(attr);
100 if (type == TRANSFORM_TRANSLATE) {
101 if (numVec.size() == 1) {
102 mat = Matrix4::CreateTranslate(StringToFloat(numVec[0].c_str()), 0, 0);
103 } else {
104 mat = Matrix4::CreateTranslate(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), 0);
105 }
106 } else if (type == TRANSFORM_SCALE) {
107 if (numVec.size() == 1) {
108 mat = Matrix4::CreateScale(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[0].c_str()), 1);
109 } else {
110 mat = Matrix4::CreateScale(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), 1);
111 }
112 } else if (type == TRANSFORM_ROTATE) {
113 mat = Matrix4::CreateRotate(StringToFloat(numVec[0].c_str()), 0, 0, 1);
114 if (numVec.size() >= 3) {
115 transformInfo.hasRotateCenter = true;
116 transformInfo.rotateCenter = Offset(StringToFloat(numVec[1]), StringToFloat(numVec[2]));
117 }
118 } else if (type == TRANSFORM_SKEWX) {
119 mat = Matrix4::CreateSkew(StringToFloat(numVec[0].c_str()), 0);
120 } else if (type == TRANSFORM_SKEWY) {
121 mat = Matrix4::CreateSkew(0, StringToFloat(numVec[0].c_str()));
122 } else if (type == TRANSFORM_MATRIX && numVec.size() == 6) {
123 mat = Matrix4::CreateMatrix2D(StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()),
124 StringToFloat(numVec[2].c_str()), StringToFloat(numVec[3].c_str()),
125 StringToFloat(numVec[4].c_str()), StringToFloat(numVec[5].c_str()));
126 } else {
127 continue;
128 }
129 retMat = retMat * mat;
130 }
131 transformInfo.matrix4 = retMat;
132 return transformInfo;
133 }
134
CreateInfoFromMap(const std::map<std::string,std::vector<float>> & transform)135 TransformInfo SvgTransform::CreateInfoFromMap(const std::map<std::string, std::vector<float>>& transform)
136 {
137 auto retMat = Matrix4::CreateIdentity();
138 auto mat = Matrix4::CreateIdentity();
139 TransformInfo transformInfo;
140 for (auto& [type, values] : transform) {
141 if (values.empty()) {
142 continue;
143 }
144 if (type == TRANSFORM_TRANSLATE && values.size() >= 2) {
145 mat = Matrix4::CreateTranslate(values[0], values[1], 0);
146 } else if (type == TRANSFORM_SCALE && values.size() >= 2) {
147 mat = Matrix4::CreateScale(values[0], values[1], 1);
148 } else if (type == TRANSFORM_ROTATE) {
149 mat = Matrix4::CreateRotate(values[0], 0, 0, 1);
150 if (values.size() >= 3) {
151 transformInfo.hasRotateCenter = true;
152 transformInfo.rotateCenter = Offset(values[1], values[2]);
153 }
154 } else if (type == TRANSFORM_SKEW && values.size() >= 2) {
155 mat = Matrix4::CreateSkew(values[0], values[1]);
156 } else {
157 continue;
158 }
159 retMat = retMat * mat;
160 }
161 transformInfo.matrix4 = retMat;
162 return transformInfo;
163 }
164
CreateMap(const std::string & transform)165 std::map<std::string, std::vector<float>> SvgTransform::CreateMap(const std::string& transform)
166 {
167 std::map<std::string, std::vector<float>> mapTrans;
168 std::vector<std::string> attrs;
169 SplitStr(transform, ")", attrs);
170 for (auto& attr : attrs) {
171 std::string type = attr.substr(0, attr.find_first_of("("));
172 std::string values = attr.substr(attr.find_first_of("(") + 1);
173 std::vector<std::string> numVec;
174 std::string tag = (values.find(",") != std::string::npos) ? "," : " ";
175 SplitStr(values, tag, numVec);
176 if (numVec.empty()) {
177 continue;
178 }
179 TrimStr(attr);
180 if (type == TRANSFORM_TRANSLATE) {
181 if (numVec.size() == 1) {
182 mapTrans[TRANSFORM_TRANSLATE] = { StringToFloat(numVec[0].c_str()), 0, 0 };
183 } else {
184 mapTrans[TRANSFORM_TRANSLATE] = {
185 StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), 0
186 };
187 }
188 } else if (type == TRANSFORM_SCALE) {
189 if (numVec.size() == 1) {
190 mapTrans[TRANSFORM_SCALE] = { StringToFloat(numVec[0].c_str()), StringToFloat(numVec[0].c_str()), 1 };
191 } else {
192 mapTrans[TRANSFORM_SCALE] = { StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), 1 };
193 }
194 } else if (type == TRANSFORM_ROTATE) {
195 if (numVec.size() == 1) {
196 mapTrans[TRANSFORM_ROTATE] = { StringToFloat(numVec[0].c_str())};
197 } else if (numVec.size() >= 3) {
198 mapTrans[TRANSFORM_ROTATE] = {
199 StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), StringToFloat(numVec[2].c_str())
200 };
201 }
202 } else if (type == TRANSFORM_SKEWX) {
203 if (mapTrans.find(TRANSFORM_SKEW) != mapTrans.end()) {
204 mapTrans[TRANSFORM_SKEW][0] += StringToFloat(numVec[0].c_str());
205 continue;
206 }
207 mapTrans[TRANSFORM_SKEW] = { StringToFloat(numVec[0].c_str()), 0 };
208 } else if (type == TRANSFORM_SKEWY) {
209 if (mapTrans.find(TRANSFORM_SKEW) != mapTrans.end()) {
210 mapTrans[TRANSFORM_SKEW][1] += StringToFloat(numVec[0].c_str());
211 continue;
212 }
213 mapTrans[TRANSFORM_SKEW] = { 0, StringToFloat(numVec[0].c_str()) };
214 } else if (type == TRANSFORM_MATRIX && numVec.size() >= 6) {
215 mapTrans[TRANSFORM_MATRIX] = {
216 StringToFloat(numVec[0].c_str()), StringToFloat(numVec[1].c_str()), StringToFloat(numVec[2].c_str()),
217 StringToFloat(numVec[3].c_str()), StringToFloat(numVec[4].c_str()), StringToFloat(numVec[5].c_str())
218 };
219 }
220 }
221 return mapTrans;
222 }
223
SetProperty(const std::string & type,const std::vector<float> & from,const std::vector<float> & to,double value,std::map<std::string,std::vector<float>> & transformAttrs)224 bool SvgTransform::SetProperty(const std::string& type, const std::vector<float>& from, const std::vector<float>& to,
225 double value, std::map<std::string, std::vector<float>>& transformAttrs)
226 {
227 if ((type == TRANSFORM_SCALE || type == TRANSFORM_TRANSLATE) && from.size() >= 2 && to.size() >= 2) {
228 float x = from[0] + (to[0] - from[0]) * value;
229 float y = from[1] + (to[1] - from[1]) * value;
230 transformAttrs[type] = { x, y, 1};
231 } else if (type == TRANSFORM_ROTATE && from.size() >= 3 && to.size() >= 3) {
232 float rotate = from[0] + (to[0] - from[0]) * value;
233 float centerX = from[1] + (to[1] - from[1]) * value;
234 float centerY = from[2] + (to[2] - from[2]) * value;
235 transformAttrs[TRANSFORM_ROTATE] = { rotate, centerX, centerY};
236 } else if (type == TRANSFORM_SKEWX && from.size() >= 1 && to.size() >= 1) {
237 float skewX = from[0] + (to[0] - from[0]) * value;
238 if (transformAttrs.find(TRANSFORM_SKEW) != transformAttrs.end()) {
239 transformAttrs[TRANSFORM_SKEW][0] = skewX;
240 } else {
241 transformAttrs[TRANSFORM_SKEW] = { skewX, 0.0f};
242 }
243 } else if (type == TRANSFORM_SKEWY && from.size() >= 1 && to.size() >= 1) {
244 float skewY = from[0] + (to[0] - from[0]) * value;
245 if (transformAttrs.find(TRANSFORM_SKEW) != transformAttrs.end()) {
246 transformAttrs[TRANSFORM_SKEW][1] = skewY;
247 } else {
248 transformAttrs[TRANSFORM_SKEW] = { 0.0f, skewY };
249 }
250 } else {
251 return false;
252 }
253
254 return true;
255 }
256
AlignmentValues(const std::string & type,std::vector<float> & from,std::vector<float> & to)257 bool SvgTransform::AlignmentValues(const std::string& type, std::vector<float>& from, std::vector<float>& to)
258 {
259 auto fromSize = from.size();
260 auto toSize = to.size();
261 if (type == TRANSFORM_SCALE) {
262 if (fromSize == 0) {
263 from = { 0.0f, 0.0f };
264 } else if (fromSize == 1) {
265 from.push_back(from[0]);
266 }
267 if (toSize == 1) {
268 to.push_back(to[0]);
269 }
270 } else if (type == TRANSFORM_SKEWX || type == TRANSFORM_SKEWY) {
271 if (fromSize == 0) {
272 from = { 0.0f };
273 }
274 } else if (type == TRANSFORM_TRANSLATE) {
275 if (fromSize == 0) {
276 from = { 0.0f, 0.0f };
277 } else if (fromSize == 1) {
278 from.push_back(0.0f);
279 }
280 if (toSize == 1) {
281 to.push_back(0.0f);
282 }
283 } else if (type == TRANSFORM_ROTATE) {
284 if (fromSize == 0) {
285 from = { 0.0f, 0.0f, 0.0f };
286 } else if (fromSize < 3) {
287 from = { from[0], 0.0f, 0.0f };
288 }
289 if (toSize < 3) {
290 to = { to[0], 0.0f, 0.0f };
291 }
292 } else {
293 return false;
294 }
295 return true;
296 }
297
AlignmentFrame(const std::string & type,std::vector<float> & frame)298 bool SvgTransform::AlignmentFrame(const std::string& type, std::vector<float>& frame)
299 {
300 auto size = frame.size();
301 if (size == 0) {
302 return false;
303 }
304
305 if (type == TRANSFORM_SCALE) {
306 if (size == 1) {
307 frame.push_back(frame[0]);
308 }
309 } else if (type == TRANSFORM_TRANSLATE) {
310 if (size == 1) {
311 frame.push_back(0.0f);
312 }
313 } else if (type == TRANSFORM_ROTATE) {
314 if (size < 3) {
315 frame = { frame[0], 0.0f, 0.0f };
316 }
317 } else if (type == TRANSFORM_SKEWX || type == TRANSFORM_SKEWY) {
318 } else {
319 return false;
320 }
321 return true;
322 }
323
324 } // namespace OHOS::Ace
325
326