1 /*
2 * Copyright (c) 2021-2023 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 "bridge/declarative_frontend/jsview/canvas/js_matrix2d.h"
17
18 #include "bridge/declarative_frontend/jsview/js_view_common_def.h"
19 #include "core/components/common/properties/paint_state.h"
20 #include "core/components_ng/render/adapter/matrix2d.h"
21
22 namespace OHOS::Ace::Framework {
23 constexpr int JS_MATRIX2D_PARAMETER_COUNTS_0 = 0;
24 constexpr int JS_MATRIX2D_PARAMETER_COUNTS_1 = 1;
25 constexpr int JS_MATRIX2D_PARAMETER_COUNTS_2 = 2;
26 constexpr int JS_MATRIX2D_PARAMETER_COUNTS_3 = 3;
27
Constructor(const JSCallbackInfo & info)28 void JSMatrix2d::Constructor(const JSCallbackInfo& info)
29 {
30 auto matrix2d = Referenced::MakeRefPtr<JSMatrix2d>();
31 matrix2d->IncRefCount();
32 info.SetReturnValue(Referenced::RawPtr(matrix2d));
33 int32_t unit = 0;
34 if (info.GetInt32Arg(0, unit) && (static_cast<CanvasUnit>(unit) == CanvasUnit::PX)) {
35 matrix2d->SetUnit(CanvasUnit::PX);
36 }
37 }
38
Destructor(JSMatrix2d * matrix2d)39 void JSMatrix2d::Destructor(JSMatrix2d* matrix2d)
40 {
41 if (matrix2d != nullptr) {
42 matrix2d->DecRefCount();
43 }
44 }
45
GetTransformInfo(const JSRef<JSObject> & obj)46 TransformParam JSMatrix2d::GetTransformInfo(const JSRef<JSObject>& obj)
47 {
48 auto scaleXVal = obj->GetProperty("scaleX");
49 auto rotateXVal = obj->GetProperty("rotateX");
50 auto rotateYVal = obj->GetProperty("rotateY");
51 auto scaleYVal = obj->GetProperty("scaleY");
52 auto translateXVal = obj->GetProperty("translateX");
53 auto translateYVal = obj->GetProperty("translateY");
54
55 TransformParam param;
56 JSViewAbstract::ParseJsDouble(scaleXVal, param.scaleX);
57 JSViewAbstract::ParseJsDouble(rotateXVal, param.skewX);
58 JSViewAbstract::ParseJsDouble(rotateYVal, param.skewY);
59 JSViewAbstract::ParseJsDouble(scaleYVal, param.scaleY);
60 JSViewAbstract::ParseJsDouble(translateXVal, param.translateX);
61 JSViewAbstract::ParseJsDouble(translateYVal, param.translateY);
62 return param;
63 }
64
JSBind(BindingTarget globalObj)65 void JSMatrix2d::JSBind(BindingTarget globalObj)
66 {
67 JSClass<JSMatrix2d>::Declare("Matrix2D");
68 JSClass<JSMatrix2d>::CustomProperty("scaleX", &JSMatrix2d::JsGetScaleX, &JSMatrix2d::JsSetScaleX);
69 JSClass<JSMatrix2d>::CustomProperty("rotateY", &JSMatrix2d::JsGetRotateY, &JSMatrix2d::JsSetRotateY);
70 JSClass<JSMatrix2d>::CustomProperty("rotateX", &JSMatrix2d::JsGetRotateX, &JSMatrix2d::JsSetRotateX);
71 JSClass<JSMatrix2d>::CustomProperty("scaleY", &JSMatrix2d::JsGetScaleY, &JSMatrix2d::JsSetScaleY);
72 JSClass<JSMatrix2d>::CustomProperty("translateX", &JSMatrix2d::JsGetTranslateX, &JSMatrix2d::JsSetTranslateX);
73 JSClass<JSMatrix2d>::CustomProperty("translateY", &JSMatrix2d::JsGetTranslateY, &JSMatrix2d::JsSetTranslateY);
74 JSClass<JSMatrix2d>::CustomMethod("identity", &JSMatrix2d::JsIdentity);
75 JSClass<JSMatrix2d>::CustomMethod("invert", &JSMatrix2d::JsInvert);
76 JSClass<JSMatrix2d>::CustomMethod("rotate", &JSMatrix2d::JsRotate);
77 JSClass<JSMatrix2d>::CustomMethod("translate", &JSMatrix2d::JsTranslate);
78 JSClass<JSMatrix2d>::CustomMethod("scale", &JSMatrix2d::JsScale);
79 JSClass<JSMatrix2d>::CustomMethod("multiply", &JSMatrix2d::JSMultiply);
80
81 JSClass<JSMatrix2d>::Bind(globalObj, JSMatrix2d::Constructor, JSMatrix2d::Destructor);
82 }
83
JsSetScaleX(const JSCallbackInfo & info)84 void JSMatrix2d::JsSetScaleX(const JSCallbackInfo& info)
85 {
86 if (info.Length() != JS_MATRIX2D_PARAMETER_COUNTS_1) {
87 return;
88 }
89 if (info[JS_MATRIX2D_PARAMETER_COUNTS_0]->IsNumber()) {
90 double scaleX = 0;
91 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_0], scaleX);
92 transform_.scaleX = scaleX;
93 }
94 }
95
JsSetRotateY(const JSCallbackInfo & info)96 void JSMatrix2d::JsSetRotateY(const JSCallbackInfo& info)
97 {
98 if (info.Length() != JS_MATRIX2D_PARAMETER_COUNTS_1) {
99 return;
100 }
101 if (info[JS_MATRIX2D_PARAMETER_COUNTS_0]->IsNumber()) {
102 double rotateY = 0;
103 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_0], rotateY);
104 transform_.skewY = rotateY;
105 }
106 }
107
JsSetRotateX(const JSCallbackInfo & info)108 void JSMatrix2d::JsSetRotateX(const JSCallbackInfo& info)
109 {
110 if (info.Length() != JS_MATRIX2D_PARAMETER_COUNTS_1) {
111 return;
112 }
113 if (info[JS_MATRIX2D_PARAMETER_COUNTS_0]->IsNumber()) {
114 double rotateX = 0;
115 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_0], rotateX);
116 transform_.skewX = rotateX;
117 }
118 }
119
JsSetScaleY(const JSCallbackInfo & info)120 void JSMatrix2d::JsSetScaleY(const JSCallbackInfo& info)
121 {
122 if (info.Length() != JS_MATRIX2D_PARAMETER_COUNTS_1) {
123 return;
124 }
125 if (info[JS_MATRIX2D_PARAMETER_COUNTS_0]->IsNumber()) {
126 double scaleY = 0;
127 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_0], scaleY);
128 transform_.scaleY = scaleY;
129 }
130 }
131
JsSetTranslateX(const JSCallbackInfo & info)132 void JSMatrix2d::JsSetTranslateX(const JSCallbackInfo& info)
133 {
134 if (info.Length() != JS_MATRIX2D_PARAMETER_COUNTS_1) {
135 return;
136 }
137 if (info[JS_MATRIX2D_PARAMETER_COUNTS_0]->IsNumber()) {
138 double translateX = 0;
139 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_0], translateX);
140 double density = GetDensity();
141 translateX *= density;
142 transform_.translateX = translateX;
143 }
144 }
145
JsSetTranslateY(const JSCallbackInfo & info)146 void JSMatrix2d::JsSetTranslateY(const JSCallbackInfo& info)
147 {
148 if (info.Length() != JS_MATRIX2D_PARAMETER_COUNTS_1) {
149 return;
150 }
151 if (info[JS_MATRIX2D_PARAMETER_COUNTS_0]->IsNumber()) {
152 double translateY = 0;
153 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_0], translateY);
154 double density = GetDensity();
155 translateY *= density;
156 transform_.translateY = translateY;
157 }
158 }
159
JsGetScaleX(const JSCallbackInfo & info)160 void JSMatrix2d::JsGetScaleX(const JSCallbackInfo& info)
161 {
162 auto returnValue = JSVal(ToJSValue(transform_.scaleX));
163 auto returnPtr = JSRef<JSVal>::Make(returnValue);
164 info.SetReturnValue(returnPtr);
165 }
166
JsGetRotateY(const JSCallbackInfo & info)167 void JSMatrix2d::JsGetRotateY(const JSCallbackInfo& info)
168 {
169 auto returnValue = JSVal(ToJSValue(transform_.skewY));
170 auto returnPtr = JSRef<JSVal>::Make(returnValue);
171 info.SetReturnValue(returnPtr);
172 }
173
JsGetRotateX(const JSCallbackInfo & info)174 void JSMatrix2d::JsGetRotateX(const JSCallbackInfo& info)
175 {
176 auto returnValue = JSVal(ToJSValue(transform_.skewX));
177 auto returnPtr = JSRef<JSVal>::Make(returnValue);
178 info.SetReturnValue(returnPtr);
179 }
180
JsGetScaleY(const JSCallbackInfo & info)181 void JSMatrix2d::JsGetScaleY(const JSCallbackInfo& info)
182 {
183 auto returnValue = JSVal(ToJSValue(transform_.scaleY));
184 auto returnPtr = JSRef<JSVal>::Make(returnValue);
185 info.SetReturnValue(returnPtr);
186 }
187
JsGetTranslateX(const JSCallbackInfo & info)188 void JSMatrix2d::JsGetTranslateX(const JSCallbackInfo& info)
189 {
190 double translateX = transform_.translateX;
191 double density = GetDensity();
192 translateX /= density;
193 auto returnValue = JSVal(ToJSValue(translateX));
194 auto returnPtr = JSRef<JSVal>::Make(returnValue);
195 info.SetReturnValue(returnPtr);
196 }
197
JsGetTranslateY(const JSCallbackInfo & info)198 void JSMatrix2d::JsGetTranslateY(const JSCallbackInfo& info)
199 {
200 double translateY = transform_.translateY;
201 double density = GetDensity();
202 translateY /= density;
203 auto returnValue = JSVal(ToJSValue(translateY));
204 auto returnPtr = JSRef<JSVal>::Make(returnValue);
205 info.SetReturnValue(returnPtr);
206 }
207
JsIdentity(const JSCallbackInfo & info)208 void JSMatrix2d::JsIdentity(const JSCallbackInfo& info)
209 {
210 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_0) {
211 return;
212 }
213 NG::Matrix2D::Identity(transform_);
214 info.SetReturnValue(info.This());
215 }
216
JsInvert(const JSCallbackInfo & info)217 void JSMatrix2d::JsInvert(const JSCallbackInfo& info)
218 {
219 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_0) {
220 return;
221 }
222 bool retValue = NG::Matrix2D::Invert(transform_);
223 if (!retValue) {
224 transform_.scaleX = NAN;
225 transform_.scaleY = NAN;
226 transform_.skewX = NAN;
227 transform_.skewY = NAN;
228 transform_.translateX = NAN;
229 transform_.translateY = NAN;
230 }
231 info.SetReturnValue(info.This());
232 }
233
JsRotate(const JSCallbackInfo & info)234 void JSMatrix2d::JsRotate(const JSCallbackInfo& info)
235 {
236 if (info.Length() < JS_MATRIX2D_PARAMETER_COUNTS_1 || info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_3) {
237 return;
238 }
239 double degree = 0;
240 double rx = 0;
241 double ry = 0;
242 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_0 && info[JS_MATRIX2D_PARAMETER_COUNTS_0]->IsNumber()) {
243 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_0], degree);
244 }
245 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_1 && info[JS_MATRIX2D_PARAMETER_COUNTS_1]->IsNumber()) {
246 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_1], rx);
247 }
248 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_2 && info[JS_MATRIX2D_PARAMETER_COUNTS_2]->IsNumber()) {
249 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_2], ry);
250 }
251 double density = GetDensity();
252 rx *= density;
253 ry *= density;
254 NG::Matrix2D::Rotate(transform_, degree, rx, ry);
255 info.SetReturnValue(info.This());
256 }
257
JsTranslate(const JSCallbackInfo & info)258 void JSMatrix2d::JsTranslate(const JSCallbackInfo& info)
259 {
260 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_2) {
261 return;
262 }
263 double tx = 0;
264 double ty = 0;
265 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_0 && info[JS_MATRIX2D_PARAMETER_COUNTS_0]->IsNumber()) {
266 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_0], tx);
267 }
268 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_1 && info[JS_MATRIX2D_PARAMETER_COUNTS_1]->IsNumber()) {
269 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_1], ty);
270 }
271 double density = GetDensity();
272 tx *= density;
273 ty *= density;
274 NG::Matrix2D::Translate(transform_, tx, ty);
275 info.SetReturnValue(info.This());
276 }
277
JsScale(const JSCallbackInfo & info)278 void JSMatrix2d::JsScale(const JSCallbackInfo& info)
279 {
280 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_2) {
281 return;
282 }
283 double sx = 1.0f;
284 double sy = 1.0f;
285 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_0 && info[JS_MATRIX2D_PARAMETER_COUNTS_0]->IsNumber()) {
286 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_0], sx);
287 }
288 if (info.Length() > JS_MATRIX2D_PARAMETER_COUNTS_1 && info[JS_MATRIX2D_PARAMETER_COUNTS_1]->IsNumber()) {
289 JSViewAbstract::ParseJsDouble(info[JS_MATRIX2D_PARAMETER_COUNTS_1], sy);
290 }
291 NG::Matrix2D::Scale(transform_, sx, sy);
292 info.SetReturnValue(info.This());
293 }
294
ToString() const295 std::string JSMatrix2d::ToString() const
296 {
297 auto jsonValue = JsonUtil::Create(true);
298 jsonValue->Put("scaleX", transform_.scaleX);
299 jsonValue->Put("scaleY", transform_.scaleY);
300 jsonValue->Put("skewX", transform_.skewX);
301 jsonValue->Put("skewY", transform_.skewY);
302 jsonValue->Put("translateX", transform_.translateX);
303 jsonValue->Put("translateY", transform_.translateY);
304 return jsonValue->ToString();
305 }
306 } // namespace OHOS::Ace::Framework
307