1 /*
2  * Copyright (c) 2021-2022 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 #ifndef FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_TRANSFORM_UTIL_H
17 #define FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_TRANSFORM_UTIL_H
18 
19 #include <utility>
20 #include <vector>
21 
22 #include "base/geometry/dimension.h"
23 #include "base/geometry/matrix4.h"
24 #include "base/geometry/quaternion.h"
25 
26 namespace OHOS::Ace {
27 namespace {
28 constexpr double epsilon = 0.000001;
29 }
30 struct ACE_EXPORT TranslateOperation {
31     TranslateOperation() = default;
32     TranslateOperation(Dimension dx, Dimension dy, Dimension dz = Dimension {}) : dx(dx), dy(dy), dz(dz) {}
33     bool operator==(const TranslateOperation& other) const
34     {
35         return dx == other.dx && dy == other.dy && dz == other.dz;
36     }
37     Dimension dx;
38     Dimension dy;
39     Dimension dz;
40 
41     static TranslateOperation Blend(const TranslateOperation& to, const TranslateOperation& from, float progress);
42 };
43 
44 struct ACE_EXPORT ScaleOperation {
45     ScaleOperation() = default;
ScaleOperationScaleOperation46     ScaleOperation(float x, float y, float z) : scaleX(x), scaleY(y), scaleZ(z) {}
47     bool operator==(const ScaleOperation& other) const
48     {
49         return NearEqual(scaleX, other.scaleX, epsilon) && NearEqual(scaleY, other.scaleY, epsilon) &&
50                NearEqual(scaleZ, other.scaleZ, epsilon);
51     }
52     float scaleX = 1.0f;
53     float scaleY = 1.0f;
54     float scaleZ = 1.0f;
55 
56     static ScaleOperation Blend(const ScaleOperation& to, const ScaleOperation& from, float progress);
57 };
58 
59 struct ACE_EXPORT SkewOperation {
60     SkewOperation() = default;
SkewOperationSkewOperation61     SkewOperation(float x, float y) : skewX(x), skewY(y) {}
62     bool operator==(const SkewOperation& other) const
63     {
64         return NearEqual(skewX, other.skewX, epsilon) && NearEqual(skewY, other.skewY, epsilon);
65     }
66     float skewX = 0.0f;
67     float skewY = 0.0f;
68 
69     static SkewOperation Blend(const SkewOperation& to, const SkewOperation& from, float progress);
70 };
71 
72 struct ACE_EXPORT RotateOperation {
73     RotateOperation() = default;
RotateOperationRotateOperation74     RotateOperation(float x, float y, float z, float angle) : dx(x), dy(y), dz(z), angle(angle) {}
75     bool operator==(const RotateOperation& other) const
76     {
77         return NearEqual(dx, other.dx, epsilon) && NearEqual(dy, other.dy, epsilon) &&
78                NearEqual(dz, other.dz, epsilon) && NearEqual(angle, other.angle, epsilon);
79     }
80     float dx = 0.0f;
81     float dy = 0.0f;
82     float dz = 0.0f;
83     float angle = 0.0f;
84 
85     static RotateOperation Blend(const RotateOperation& to, const RotateOperation& from, float progress);
86 };
87 
88 struct ACE_EXPORT PerspectiveOperation {
89     PerspectiveOperation() = default;
PerspectiveOperationPerspectiveOperation90     explicit PerspectiveOperation(const Dimension& dis) : distance(dis) {}
91     bool operator==(const PerspectiveOperation& other) const
92     {
93         return distance == other.distance;
94     }
95     Dimension distance;
96 
97     static PerspectiveOperation Blend(const PerspectiveOperation& to, const PerspectiveOperation& from, float progress);
98 };
99 
100 struct ACE_EXPORT DecomposedTransform {
101     float translate[3] = { 0.0f, 0.0f, 0.0f };
102     float scale[3] = { 1.0f, 1.0f, 1.0f };
103     float skew[3] = { 0.0f, 0.0f, 0.0f };
104     float perspective[4] = { 0.0f, 0.0f, 0.0f, 1.0f };
105     Quaternion quaternion;
106 
107     std::string ToString() const;
108 };
109 
110 enum class TransformOperationType {
111     TRANSLATE,
112     SCALE,
113     SKEW,
114     ROTATE,
115     MATRIX,
116     PERSPECTIVE,
117     UNDEFINED,
118 };
119 
120 struct ACE_EXPORT TransformOperation {
TransformOperationTransformOperation121     TransformOperation() : type_(TransformOperationType::UNDEFINED) {}
122 
123     TransformOperationType type_ = TransformOperationType::UNDEFINED;
124     Matrix4 matrix4_ = Matrix4::CreateIdentity();
125     union {
126         TranslateOperation translateOperation_;
127         ScaleOperation scaleOperation_;
128         SkewOperation skewOperation_;
129         RotateOperation rotateOperation_;
130         PerspectiveOperation perspectiveOperation_;
131     };
132 
133     bool operator==(const TransformOperation& other) const
134     {
135         if (type_ != other.type_) {
136             return false;
137         }
138         switch (type_) {
139             case TransformOperationType::MATRIX: {
140                 return matrix4_ == other.matrix4_;
141             }
142             case TransformOperationType::PERSPECTIVE: {
143                 return perspectiveOperation_ == other.perspectiveOperation_;
144             }
145             case TransformOperationType::ROTATE: {
146                 return rotateOperation_ == other.rotateOperation_;
147             }
148             case TransformOperationType::SCALE: {
149                 return scaleOperation_ == other.scaleOperation_;
150             }
151             case TransformOperationType::SKEW: {
152                 return skewOperation_ == other.skewOperation_;
153             }
154             case TransformOperationType::TRANSLATE: {
155                 return translateOperation_ == other.translateOperation_;
156             }
157             case TransformOperationType::UNDEFINED:
158                 // fall through
159             default:
160                 return true;
161         }
162     }
163 
164     static TransformOperation Blend(const TransformOperation& to, const TransformOperation& from, float progress);
165     static TransformOperation Create(TransformOperationType type);
166 
167 private:
168     static void BlendInner(
169         const TransformOperation& to, const TransformOperation& from, float progress, TransformOperation& out);
170 };
171 
172 class ACE_EXPORT TransformOperations {
173 public:
174     static void ParseOperationsToMatrix(std::vector<TransformOperation>& operations);
175 
176     static void ParseOperationToMatrix(TransformOperation& operations);
177 
178     static TransformOperations Blend(const TransformOperations& to, const TransformOperations& from, float progress);
179 
180     explicit TransformOperations(std::vector<TransformOperation> operation = std::vector<TransformOperation>())
181         : operations_(std::move(operation))
182     {}
183     ~TransformOperations() = default;
184 
GetOperations()185     std::vector<TransformOperation>& GetOperations()
186     {
187         return operations_;
188     }
189 
GetOperations()190     const std::vector<TransformOperation>& GetOperations() const
191     {
192         return operations_;
193     }
194 
195     Matrix4 ComputerRemaining(std::size_t startOffset) const;
196 
SetAlwaysRotate(bool alwaysRotate)197     void SetAlwaysRotate(bool alwaysRotate)
198     {
199         alwaysRotate_ = alwaysRotate;
200     }
201 
202     bool operator==(const TransformOperations& other) const
203     {
204         if (alwaysRotate_) {
205             return false;
206         }
207         if (operations_.size() != other.operations_.size()) {
208             return false;
209         }
210         for (size_t index = 0; index < operations_.size(); index++) {
211             if (!(operations_[index] == other.operations_[index])) {
212                 return false;
213             }
214         }
215         return true;
216     }
217 
218 protected:
219     std::vector<TransformOperation> operations_;
220     bool alwaysRotate_ = false;
221 
222 private:
223     std::size_t MatchingLength(const TransformOperations& to, const TransformOperations& from) const;
224     void BlendInner(const TransformOperations& from, float progress, TransformOperations& out) const;
225 };
226 
227 class ACE_EXPORT TransformUtil final {
228 public:
229     static bool DecomposeTransform(DecomposedTransform& out, const Matrix4& transform);
230     static DecomposedTransform BlendDecomposedTransforms(
231         const DecomposedTransform& to, const DecomposedTransform& from, double progress);
232     static Matrix4 ComposeTransform(const DecomposedTransform& decomp);
233 };
234 
235 } // namespace OHOS::Ace
236 
237 #endif // FOUNDATION_ACE_FRAMEWORKS_BASE_GEOMETRY_TRANSFORM_UTIL_H
238