• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2025 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 "base/utils/string_utils.h"
17 #include "base/utils/linear_map.h"
18 #include "core/components_ng/svg/parse/svg_node.h"
19 #include "core/components_ng/svg/parse/svg_transform.h"
20 #include "core/components_ng/svg/base/svg_length_scale_rule.h"
21 
22 namespace OHOS::Ace::NG {
23 namespace {
24 
25 const char TRANSFORM_MATRIX[] = "matrix";
26 const char TRANSFORM_ROTATE[] = "rotate";
27 const char TRANSFORM_SCALE[] = "scale";
28 const char TRANSFORM_SKEWX[] = "skewX";
29 const char TRANSFORM_SKEWY[] = "skewY";
30 const char TRANSFORM_TRANSLATE[] = "translate";
31 constexpr int32_t PARAM_COUNT1 = 1;
32 constexpr int32_t PARAM_COUNT2 = 2;
33 constexpr int32_t PARAM_COUNT3 = 3;
34 constexpr int32_t TRANSFORM_MATRIX_PARA_AMOUNT = 6;
35 constexpr int32_t NUM0 = 0;
36 constexpr int32_t NUM1 = 1;
37 constexpr int32_t NUM2 = 2;
38 constexpr int32_t NUM3 = 3;
39 constexpr int32_t NUM4 = 4;
40 constexpr int32_t NUM5 = 5;
41 } // namespace
42 
43 using namespace StringUtils;
44 
ApplyTransformPivot(const std::string & funcType,const Offset & finalPivot,Matrix4 & matrix)45 void NGSvgTransform::ApplyTransformPivot(const std::string& funcType, const Offset& finalPivot, Matrix4& matrix)
46 {
47     /* move to final pivot to transform.
48        effect = translate(finalPivot) -> transform -> translate(-finalPivot) */
49     double x = finalPivot.GetX();
50     double y = finalPivot.GetY();
51     matrix = Matrix4::CreateTranslate(x, y, 0) * matrix * Matrix4::CreateTranslate(-x, -y, 0);
52 }
53 
ObjectBoundingBoxTransform(double srcLength,const SvgLengthScaleRule & rule,SvgLengthType lengthType)54 double NGSvgTransform::ObjectBoundingBoxTransform(double srcLength, const SvgLengthScaleRule& rule,
55     SvgLengthType lengthType)
56 {
57     double length = 0;
58     switch (lengthType) {
59         case SvgLengthType::HORIZONTAL:
60             length = (rule.GetLengthScaleUnit() == SvgLengthScaleUnit::USER_SPACE_ON_USE) ?
61                      srcLength :
62                      srcLength * rule.GetContainerRect().Width();
63             break;
64         case SvgLengthType::VERTICAL:
65             length = (rule.GetLengthScaleUnit() == SvgLengthScaleUnit::USER_SPACE_ON_USE) ?
66                      srcLength :
67                      srcLength * rule.GetContainerRect().Height();
68             break;
69         default:
70             break;
71     }
72     return length;
73 }
74 
CreateFromTranslate(const std::vector<std::string> & paramVec,Matrix4 & matrix,const SvgLengthScaleRule & lengthRule)75 bool CreateFromTranslate(const std::vector<std::string>& paramVec, Matrix4& matrix,
76     const SvgLengthScaleRule& lengthRule)
77 {
78     double tx = 0.0f;
79     double ty = 0.0f;
80     if (paramVec.size() == PARAM_COUNT1) {
81         tx = StringToDouble(paramVec[NUM0]);
82     } else if (paramVec.size() == PARAM_COUNT2) {
83         tx = StringToDouble(paramVec[NUM0]);
84         ty = StringToDouble(paramVec[NUM1]);
85     } else {
86         return false;
87     }
88     auto x = NGSvgTransform::ObjectBoundingBoxTransform(tx, lengthRule, SvgLengthType::HORIZONTAL);
89     auto y = NGSvgTransform::ObjectBoundingBoxTransform(ty, lengthRule, SvgLengthType::VERTICAL);
90     matrix = Matrix4::CreateTranslate(x, y, 0);
91     return true;
92 }
93 
CreateFromScale(const std::vector<std::string> & paramVec,Matrix4 & matrix,const SvgLengthScaleRule & lengthRule)94 bool CreateFromScale(const std::vector<std::string>& paramVec, Matrix4& matrix,
95     const SvgLengthScaleRule& lengthRule)
96 {
97     double sx = 0.0f;
98     double sy = 0.0f;
99     if (paramVec.size() == PARAM_COUNT1) {
100         sx = StringToDouble(paramVec[NUM0]);
101         sy = sx;
102     } else if (paramVec.size() == PARAM_COUNT2) {
103         sx = StringToDouble(paramVec[NUM0]);
104         sy = StringToDouble(paramVec[NUM1]);
105     } else {
106         return false;
107     }
108     auto scaleX = NGSvgTransform::ObjectBoundingBoxTransform(sx, lengthRule, SvgLengthType::HORIZONTAL);
109     auto scaleY = NGSvgTransform::ObjectBoundingBoxTransform(sy, lengthRule, SvgLengthType::VERTICAL);
110     matrix = Matrix4::CreateScale(scaleX, scaleY, 1);
111     return true;
112 }
113 
CreateFromRotate(const std::vector<std::string> & paramVec,Matrix4 & matrix,const SvgLengthScaleRule & lengthRule)114 bool CreateFromRotate(const std::vector<std::string>& paramVec, Matrix4& matrix,
115     const SvgLengthScaleRule& lengthRule)
116 {
117     if ((paramVec.size() != PARAM_COUNT1) && (paramVec.size() != PARAM_COUNT3)) {
118         return false;
119     }
120     double rotateAngle = StringToDouble(paramVec[NUM0]);
121     matrix = Matrix4::CreateRotate(rotateAngle, 0, 0, 1);
122     return true;
123 }
124 
CreateFromSkewx(const std::vector<std::string> & paramVec,Matrix4 & matrix,const SvgLengthScaleRule & lengthRule)125 bool CreateFromSkewx(const std::vector<std::string>& paramVec, Matrix4& matrix,
126     const SvgLengthScaleRule& lengthRule)
127 {
128     if (paramVec.size() != PARAM_COUNT1) {
129         return false;
130     }
131     double skewAngleAxisX = StringToDouble(paramVec[NUM0]);
132     double skewAngleAxisY = 0.0f;
133     matrix = Matrix4::CreateSkew(skewAngleAxisX, skewAngleAxisY);
134     return true;
135 }
136 
CreateFromSkewy(const std::vector<std::string> & paramVec,Matrix4 & matrix,const SvgLengthScaleRule & lengthRule)137 bool CreateFromSkewy(const std::vector<std::string>& paramVec, Matrix4& matrix,
138     const SvgLengthScaleRule& lengthRule)
139 {
140     if (paramVec.size() != PARAM_COUNT1) {
141         return false;
142     }
143     double skewAngleAxisX = 0.0f;
144     double skewAngleAxisY = StringToDouble(paramVec[NUM0]);
145     matrix = Matrix4::CreateSkew(skewAngleAxisX, skewAngleAxisY);
146     return true;
147 }
148 
CreateFromMatrix(const std::vector<std::string> & paramVec,Matrix4 & matrix,const SvgLengthScaleRule & lengthRule)149 bool CreateFromMatrix(const std::vector<std::string>& paramVec, Matrix4& matrix,
150     const SvgLengthScaleRule& lengthRule)
151 {
152     if (paramVec.size() != TRANSFORM_MATRIX_PARA_AMOUNT) {
153         return false;
154     }
155     double a = StringToDouble(paramVec[NUM0]);
156     double b = StringToDouble(paramVec[NUM1]);
157     double c = StringToDouble(paramVec[NUM2]);
158     double d = StringToDouble(paramVec[NUM3]);
159     double e = StringToDouble(paramVec[NUM4]);
160     double f = StringToDouble(paramVec[NUM5]);
161     matrix = Matrix4::CreateMatrix2D(a, b, c, d, e, f);
162     return true;
163 }
164 
165 using TransformMatrixCreator = bool (*)(const std::vector<std::string>& paramVec, Matrix4& matrix,
166     const SvgLengthScaleRule& lengthRule);
167 
UpdateSingleTransform(const std::string & funcType,const std::vector<std::string> & paramVec,Matrix4 & matrix,const SvgLengthScaleRule & lengthRule)168 bool NGSvgTransform::UpdateSingleTransform(
169     const std::string& funcType, const std::vector<std::string>& paramVec, Matrix4& matrix,
170     const SvgLengthScaleRule& lengthRule)
171 {
172     static const LinearMapNode<TransformMatrixCreator> matrix4Creator[] = {
173         { TRANSFORM_MATRIX, CreateFromMatrix },
174         { TRANSFORM_ROTATE, CreateFromRotate },
175         { TRANSFORM_SCALE, CreateFromScale },
176         { TRANSFORM_SKEWX, CreateFromSkewx },
177         { TRANSFORM_SKEWY, CreateFromSkewy },
178         { TRANSFORM_TRANSLATE, CreateFromTranslate },
179     };
180     int64_t index = BinarySearchFindIndex(matrix4Creator, ArraySize(matrix4Creator), funcType.c_str());
181     if (index < 0) {
182         return false;
183     }
184     return matrix4Creator[index].value(paramVec, matrix, lengthRule);
185 }
186 
UpdateTransformPivot(const std::string & funcType,const std::vector<std::string> & paramVec,Offset & finalPivot)187 void UpdateTransformPivot(const std::string& funcType, const std::vector<std::string>& paramVec, Offset& finalPivot)
188 {
189     if ((funcType == TRANSFORM_ROTATE) && (paramVec.size() == PARAM_COUNT3)) {
190         Offset localPivot = Offset(StringToDouble(paramVec[NUM1]), StringToDouble(paramVec[NUM2]));
191         finalPivot += localPivot;
192     }
193 }
194 
CreateMatrix4(const std::vector<NG::TransformInfo> & transformVec,const Offset & globalPivot,const SvgLengthScaleRule & lengthRule)195 Matrix4 NGSvgTransform::CreateMatrix4(const std::vector<NG::TransformInfo>& transformVec, const Offset& globalPivot,
196     const SvgLengthScaleRule& lengthRule)
197 {
198     Matrix4 retMatrix;
199     for (auto& attr : transformVec) {
200         Matrix4 funcMatrix;
201         Offset finalPivot = globalPivot;
202         bool isUpdated = UpdateSingleTransform(attr.funcType, attr.paramVec, funcMatrix, lengthRule);
203         if (!isUpdated) {
204             TAG_LOGW(AceLogTag::ACE_IMAGE, "CreateMatrix4 failed. funcType:[%{public}s], param cnt:%{public}zu",
205                 attr.funcType.c_str(), attr.paramVec.size());
206             return Matrix4();
207         }
208         UpdateTransformPivot(attr.funcType, attr.paramVec, finalPivot);
209         ApplyTransformPivot(attr.funcType, finalPivot, funcMatrix);
210         retMatrix = retMatrix * funcMatrix;
211     }
212     return retMatrix;
213 }
214 
CreateTranslate(const std::vector<std::string> & paramVec,RSMatrix & matrix)215 bool NGSvgTransform::CreateTranslate(const std::vector<std::string>& paramVec, RSMatrix& matrix)
216 {
217     if (paramVec.size() > PARAM_COUNT2 || paramVec.size() == 0) {
218         return false;
219     }
220     double tx = 0.0f;
221     double ty = 0.0f;
222     tx = StringToDouble(paramVec[NUM0]);
223     if (paramVec.size() > PARAM_COUNT1) {
224         ty = StringToDouble(paramVec[NUM1]);
225     }
226     matrix.Translate(tx, ty);
227     return true;
228 }
229 } // namespace OHOS::Ace::NG