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 #include "frameworks/bridge/declarative_frontend/engine/jsi/modules/jsi_curves_module.h"
17
18 #include "base/json/json_util.h"
19 #include "base/log/log.h"
20 #include "frameworks/bridge/common/utils/utils.h"
21 #include "frameworks/bridge/declarative_frontend/engine/jsi/jsi_declarative_engine.h"
22 #include "frameworks/bridge/js_frontend/engine/common/js_constants.h"
23 #include "frameworks/core/animation/curve.h"
24 #include "frameworks/core/common/container.h"
25
26 namespace OHOS::Ace::Framework {
27
CurvesInterpolate(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)28 shared_ptr<JsValue> CurvesInterpolate(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
29 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
30 {
31 auto jsCurveString = thisObj->GetProperty(runtime, "__curveString");
32 auto curveString = jsCurveString->ToString(runtime);
33
34 if (argv.size() == 0) {
35 return runtime->NewNull();
36 }
37 double time = argv[0]->ToDouble(runtime);
38 auto animationCurve = CreateCurve(curveString, false);
39 if (!animationCurve) {
40 LOGW("created animationCurve is null, curveString:%{public}s", curveString.c_str());
41 return runtime->NewNull();
42 }
43 double curveValue = animationCurve->Move(time);
44 return runtime->NewNumber(curveValue);
45 }
46
CurvesInitInternal(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)47 shared_ptr<JsValue> CurvesInitInternal(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
48 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
49 {
50 auto curveObj = runtime->NewObject();
51 curveObj->SetProperty(runtime, CURVE_INTERPOLATE, runtime->NewFunction(CurvesInterpolate));
52 if (argc != 1 && argc != 0) {
53 LOGE("CurvesInit args count is invalid");
54 return runtime->NewNull();
55 }
56 RefPtr<Curve> curve;
57 std::string curveString;
58 if (argc == 1) {
59 curveString = argv[0]->ToString(runtime);
60 } else {
61 curveString = "linear";
62 }
63 curve = CreateCurve(curveString);
64 curveObj->SetProperty(runtime, "__curveString", runtime->NewString(curveString));
65 if (Container::IsCurrentUseNewPipeline()) {
66 return curveObj;
67 }
68
69 auto page = JsiDeclarativeEngineInstance::GetStagingPage(Container::CurrentId());
70 int32_t pageId = -1;
71 if (page == nullptr) {
72 LOGW("page is nullptr");
73 } else {
74 pageId = page->GetPageId();
75 }
76 curveObj->SetProperty(runtime, "__pageId", runtime->NewInt32(pageId));
77 return curveObj;
78 }
79
CurvesInit(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)80 shared_ptr<JsValue> CurvesInit(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
81 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
82 {
83 return CurvesInitInternal(runtime, thisObj, argv, argc);
84 }
85
InitCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)86 shared_ptr<JsValue> InitCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
87 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
88 {
89 return CurvesInitInternal(runtime, thisObj, argv, argc);
90 }
91
CreateSpringCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc,RefPtr<Curve> & curve)92 bool CreateSpringCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
93 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc, RefPtr<Curve>& curve)
94 {
95 if (argc != 4) {
96 LOGE("Spring curve: the number of parameters is illegal");
97 return false;
98 }
99 double x0 = argv[0]->ToDouble(runtime);
100 double y0 = argv[1]->ToDouble(runtime);
101 double x1 = argv[2]->ToDouble(runtime);
102 double y1 = argv[3]->ToDouble(runtime);
103 if (y0 > 0 && x1 > 0 && y1 > 0) {
104 curve = AceType::MakeRefPtr<SpringCurve>(x0, y0, x1, y1);
105 return true;
106 } else {
107 LOGE("Spring curve: the value of the parameters are illegal");
108 return false;
109 }
110 }
111
CreateCubicCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc,RefPtr<Curve> & curve)112 bool CreateCubicCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
113 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc, RefPtr<Curve>& curve)
114 {
115 if (argc != 4) {
116 LOGE("Cubic curve: the number of parameters is illegal");
117 return false;
118 }
119 double x0 = argv[0]->ToDouble(runtime);
120 double y0 = argv[1]->ToDouble(runtime);
121 double x1 = argv[2]->ToDouble(runtime);
122 double y1 = argv[3]->ToDouble(runtime);
123
124 curve = AceType::MakeRefPtr<CubicCurve>(x0, y0, x1, y1);
125 return true;
126 }
127
CreateStepsCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc,RefPtr<Curve> & curve)128 bool CreateStepsCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
129 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc, RefPtr<Curve>& curve)
130 {
131 if (argc != 1 && argc != 2) {
132 LOGE("Steps curve: the number of parameters is illegal");
133 return false;
134 }
135 int32_t stepSize;
136 if (argc == 2) {
137 stepSize = argv[0]->ToInt32(runtime);
138 if (stepSize < 0) {
139 LOGE("Steps curve: When two parameters, the value of the stepSize is illegal");
140 return false;
141 }
142 bool isEnd = argv[1]->ToBoolean(runtime);
143 if (isEnd) {
144 curve = AceType::MakeRefPtr<StepsCurve>(stepSize, StepsCurvePosition::END);
145 } else {
146 curve = AceType::MakeRefPtr<StepsCurve>(stepSize, StepsCurvePosition::START);
147 }
148 } else {
149 stepSize = argv[0]->ToInt32(runtime);
150 if (stepSize < 0) {
151 LOGE("Steps curve: When one parameter, the value of the stepSize is illegal");
152 return false;
153 }
154 curve = AceType::MakeRefPtr<StepsCurve>(stepSize);
155 }
156 return true;
157 }
158
CreateSpringMotionCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc,RefPtr<Curve> & curve)159 bool CreateSpringMotionCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
160 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc, RefPtr<Curve>& curve)
161 {
162 if (argc > 3) {
163 LOGW("SpringMotionCurve: the number of parameters is illegal");
164 return false;
165 }
166 float response = argc > 0 ? static_cast<float>(argv[0]->ToDouble(runtime))
167 : ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_RESPONSE;
168 float dampingRatio = argc > 1 ? static_cast<float>(argv[1]->ToDouble(runtime))
169 : ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_DAMPING_RATIO;
170 float blendDuration = argc > 2 ? static_cast<float>(argv[2]->ToDouble(runtime))
171 : ResponsiveSpringMotion::DEFAULT_SPRING_MOTION_BLEND_DURATION;
172 curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingRatio, blendDuration);
173 return true;
174 }
175
CreateResponsiveSpringMotionCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc,RefPtr<Curve> & curve)176 bool CreateResponsiveSpringMotionCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
177 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc, RefPtr<Curve>& curve)
178 {
179 if (argc > 3) {
180 LOGW("ResponsiveSpringMotionCurve: the number of parameters is illegal");
181 return false;
182 }
183 float response = argc > 0 ? static_cast<float>(argv[0]->ToDouble(runtime))
184 : ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_RESPONSE;
185 float dampingRatio = argc > 1 ? static_cast<float>(argv[1]->ToDouble(runtime))
186 : ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_DAMPING_RATIO;
187 float blendDuration = argc > 2 ? static_cast<float>(argv[2]->ToDouble(runtime))
188 : ResponsiveSpringMotion::DEFAULT_RESPONSIVE_SPRING_MOTION_BLEND_DURATION;
189 curve = AceType::MakeRefPtr<ResponsiveSpringMotion>(response, dampingRatio, blendDuration);
190 return true;
191 }
192
ParseCurves(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc,std::string & curveString)193 shared_ptr<JsValue> ParseCurves(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
194 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc, std::string& curveString)
195 {
196 auto curveObj = runtime->NewObject();
197 curveObj->SetProperty(runtime, CURVE_INTERPOLATE, runtime->NewFunction(CurvesInterpolate));
198 RefPtr<Curve> curve;
199 bool curveCreated;
200 if (curveString == CURVES_SPRING || curveString == SPRING_CURVE) {
201 curveCreated = CreateSpringCurve(runtime, thisObj, argv, argc, curve);
202 } else if (curveString == CURVES_CUBIC_BEZIER || curveString == CUBIC_BEZIER_CURVE) {
203 curveCreated = CreateCubicCurve(runtime, thisObj, argv, argc, curve);
204 } else if (curveString == CURVES_STEPS || curveString == STEPS_CURVE) {
205 curveCreated = CreateStepsCurve(runtime, thisObj, argv, argc, curve);
206 } else if (curveString == SPRING_MOTION) {
207 curveCreated = CreateSpringMotionCurve(runtime, thisObj, argv, argc, curve);
208 } else if (curveString == RESPONSIVE_SPRING_MOTION) {
209 curveCreated = CreateResponsiveSpringMotionCurve(runtime, thisObj, argv, argc, curve);
210 } else {
211 LOGE("curve params: %{public}s is illegal", curveString.c_str());
212 return runtime->NewNull();
213 }
214 if (!curveCreated) {
215 return runtime->NewNull();
216 }
217 auto customCurve = curve->ToString();
218 curveObj->SetProperty(runtime, "__curveString", runtime->NewString(customCurve));
219 if (Container::IsCurrentUseNewPipeline()) {
220 return curveObj;
221 }
222 auto page = JsiDeclarativeEngineInstance::GetStagingPage(Container::CurrentId());
223 int32_t pageId = -1;
224 if (page == nullptr) {
225 LOGW("page is nullptr");
226 } else {
227 pageId = page->GetPageId();
228 }
229 curveObj->SetProperty(runtime, "__pageId", runtime->NewInt32(pageId));
230 return curveObj;
231 }
232
CurvesBezier(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)233 shared_ptr<JsValue> CurvesBezier(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
234 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
235 {
236 std::string curveString(CURVES_CUBIC_BEZIER);
237 return ParseCurves(runtime, thisObj, argv, argc, curveString);
238 }
239
BezierCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)240 shared_ptr<JsValue> BezierCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
241 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
242 {
243 std::string curveString(CUBIC_BEZIER_CURVE);
244 return ParseCurves(runtime, thisObj, argv, argc, curveString);
245 }
246
CurvesSpring(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)247 shared_ptr<JsValue> CurvesSpring(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
248 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
249 {
250 std::string curveString(CURVES_SPRING);
251 return ParseCurves(runtime, thisObj, argv, argc, curveString);
252 }
253
SpringCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)254 shared_ptr<JsValue> SpringCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
255 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
256 {
257 std::string curveString(SPRING_CURVE);
258 return ParseCurves(runtime, thisObj, argv, argc, curveString);
259 }
260
CurvesSteps(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)261 shared_ptr<JsValue> CurvesSteps(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
262 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
263 {
264 std::string curveString(CURVES_STEPS);
265 return ParseCurves(runtime, thisObj, argv, argc, curveString);
266 }
267
StepsCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)268 shared_ptr<JsValue> StepsCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
269 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
270 {
271 std::string curveString(STEPS_CURVE);
272 return ParseCurves(runtime, thisObj, argv, argc, curveString);
273 }
274
SpringMotionCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)275 shared_ptr<JsValue> SpringMotionCurve(const shared_ptr<JsRuntime>& runtime, const shared_ptr<JsValue>& thisObj,
276 const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
277 {
278 std::string curveString(SPRING_MOTION);
279 return ParseCurves(runtime, thisObj, argv, argc, curveString);
280 }
281
ResponsiveSpringMotionCurve(const shared_ptr<JsRuntime> & runtime,const shared_ptr<JsValue> & thisObj,const std::vector<shared_ptr<JsValue>> & argv,int32_t argc)282 shared_ptr<JsValue> ResponsiveSpringMotionCurve(const shared_ptr<JsRuntime>& runtime,
283 const shared_ptr<JsValue>& thisObj, const std::vector<shared_ptr<JsValue>>& argv, int32_t argc)
284 {
285 std::string curveString(RESPONSIVE_SPRING_MOTION);
286 return ParseCurves(runtime, thisObj, argv, argc, curveString);
287 }
288
InitCurvesModule(const shared_ptr<JsRuntime> & runtime,shared_ptr<JsValue> & moduleObj)289 void InitCurvesModule(const shared_ptr<JsRuntime>& runtime, shared_ptr<JsValue>& moduleObj)
290 {
291 moduleObj->SetProperty(runtime, CURVES_INIT, runtime->NewFunction(CurvesInit));
292 moduleObj->SetProperty(runtime, INIT_CURVE, runtime->NewFunction(InitCurve));
293 moduleObj->SetProperty(runtime, CURVES_CUBIC_BEZIER, runtime->NewFunction(CurvesBezier));
294 moduleObj->SetProperty(runtime, CUBIC_BEZIER_CURVE, runtime->NewFunction(BezierCurve));
295 moduleObj->SetProperty(runtime, CURVES_SPRING, runtime->NewFunction(CurvesSpring));
296 moduleObj->SetProperty(runtime, SPRING_CURVE, runtime->NewFunction(SpringCurve));
297 moduleObj->SetProperty(runtime, CURVES_STEPS, runtime->NewFunction(CurvesSteps));
298 moduleObj->SetProperty(runtime, STEPS_CURVE, runtime->NewFunction(StepsCurve));
299 moduleObj->SetProperty(runtime, SPRING_MOTION, runtime->NewFunction(SpringMotionCurve));
300 moduleObj->SetProperty(runtime, RESPONSIVE_SPRING_MOTION, runtime->NewFunction(ResponsiveSpringMotionCurve));
301 }
302
303 } // namespace OHOS::Ace::Framework