• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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