1 /*
2 * Copyright (c) 2024 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/jsview/js_rect_shape.h"
17 #include "core/components_ng/base/view_stack_model.h"
18
19 namespace OHOS::Ace::Framework {
20 namespace {
21 const int32_t LENGTH_RADIUS_ARRAY = 2;
22 const int32_t LENGTH_ARRAY = 4;
23 }
ObjectRadiusWidth(const JSCallbackInfo & info)24 void JSRectShape::ObjectRadiusWidth(const JSCallbackInfo& info)
25 {
26 info.ReturnSelf();
27 if (info.Length() < 1) {
28 return;
29 }
30
31 CalcDimension radiusWidth;
32 if (!ParseJsDimensionVp(info[0], radiusWidth)) {
33 return;
34 }
35 if (LessNotEqual(radiusWidth.Value(), 0.0)) {
36 return;
37 }
38
39 auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
40 if (rect) {
41 rect->SetRadiusWidth(radiusWidth);
42 }
43 }
44
ObjectRadiusHeight(const JSCallbackInfo & info)45 void JSRectShape::ObjectRadiusHeight(const JSCallbackInfo& info)
46 {
47 info.ReturnSelf();
48 if (info.Length() < 1) {
49 return;
50 }
51
52 CalcDimension radiusHeight;
53 if (!ParseJsDimensionVp(info[0], radiusHeight)) {
54 return;
55 }
56 if (LessNotEqual(radiusHeight.Value(), 0.0)) {
57 return;
58 }
59
60 auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
61 if (rect) {
62 rect->SetRadiusHeight(radiusHeight);
63 }
64 }
65
ObjectRadius(const JSCallbackInfo & info)66 void JSRectShape::ObjectRadius(const JSCallbackInfo& info)
67 {
68 info.ReturnSelf();
69 if (info.Length() < 1) {
70 return;
71 }
72
73 auto rect = AceType::DynamicCast<ShapeRect>(basicShape_);
74 if (!rect) {
75 return;
76 }
77
78 if (info[0]->IsNumber() || info[0]->IsString()) {
79 SetRadiusWithJsVal(rect, info[0]);
80 }
81
82 if (info[0]->IsArray()) {
83 SetRadiusWithArrayValue(rect, info[0]);
84 }
85 }
86
SetRadiusWithJsVal(const RefPtr<ShapeRect> & shapeRect,const JSRef<JSVal> & jsVal)87 void JSRectShape::SetRadiusWithJsVal(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)
88 {
89 CalcDimension value(0.0f);
90 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
91 ParseJsDimensionVp(jsVal, value);
92 } else {
93 if (!ParseJsDimensionVpNG(jsVal, value)) {
94 value.SetValue(0.0f);
95 }
96 }
97
98 if (shapeRect) {
99 AnimationOption option = ViewStackModel::GetInstance()->GetImplicitAnimationOption();
100 shapeRect->SetRadiusWidth(value, option);
101 shapeRect->SetRadiusHeight(value, option);
102 return;
103 }
104 }
105
SetRadiusWithArrayValue(const RefPtr<ShapeRect> & shapeRect,const JSRef<JSVal> & jsVal)106 void JSRectShape::SetRadiusWithArrayValue(const RefPtr<ShapeRect>& shapeRect, const JSRef<JSVal>& jsVal)
107 {
108 if (!jsVal->IsArray() || !shapeRect) {
109 return;
110 }
111
112 JSRef<JSArray> array = JSRef<JSArray>::Cast(jsVal);
113
114 auto length = static_cast<int32_t>(array->Length());
115 if (length <= 0) {
116 return;
117 }
118 length = std::min(length, LENGTH_ARRAY);
119
120 for (int32_t i = 0; i < length; i++) {
121 JSRef<JSVal> radiusItem = array->GetValueAt(i);
122 if (!radiusItem->IsArray()) {
123 CalcDimension radiusXYValue(0.0f);
124 if (!ParseJsDimensionVpNG(radiusItem, radiusXYValue)) {
125 radiusXYValue.SetValue(0.0f);
126 }
127 SetRadiusValue(shapeRect, radiusXYValue, radiusXYValue, i);
128 continue;
129 }
130
131 JSRef<JSArray> radiusArray = JSRef<JSArray>::Cast(radiusItem);
132 if (radiusArray->Length() != LENGTH_RADIUS_ARRAY) {
133 break;
134 }
135 JSRef<JSVal> radiusX = radiusArray->GetValueAt(0);
136 JSRef<JSVal> radiusY = radiusArray->GetValueAt(1);
137 CalcDimension radiusXValue(0.0f);
138 CalcDimension radiusYValue(0.0f);
139
140 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
141 if (ParseJsDimensionVp(radiusX, radiusXValue)) {
142 ParseJsDimensionVp(radiusY, radiusYValue);
143 }
144 } else {
145 if (!ParseJsDimensionVpNG(radiusX, radiusXValue)) {
146 radiusXValue.SetValue(0.0f);
147 }
148 if (!ParseJsDimensionVpNG(radiusY, radiusYValue)) {
149 radiusYValue.SetValue(0.0f);
150 }
151 }
152
153 SetRadiusValue(shapeRect, radiusXValue, radiusYValue, i);
154 }
155 }
156
SetRadiusValue(const RefPtr<ShapeRect> & shapeRect,const CalcDimension & radiusX,const CalcDimension & radiusY,int32_t index)157 void JSRectShape::SetRadiusValue(
158 const RefPtr<ShapeRect>& shapeRect, const CalcDimension& radiusX, const CalcDimension& radiusY, int32_t index)
159 {
160 CHECK_NULL_VOID(shapeRect);
161 auto newRadius = Ace::Radius(Dimension(radiusX), Dimension(radiusY));
162 switch (index) {
163 case TOP_LEFT_RADIUS:
164 shapeRect->SetTopLeftRadius(newRadius);
165 break;
166 case TOP_RIGHT_RADIUS:
167 shapeRect->SetTopRightRadius(newRadius);
168 break;
169 case BOTTOM_RIGHT_RADIUS:
170 shapeRect->SetBottomRightRadius(newRadius);
171 break;
172 case BOTTOM_LEFT_RADIUS:
173 shapeRect->SetBottomLeftRadius(newRadius);
174 break;
175 default:
176 break;
177 }
178 }
179
ConstructorCallback(const JSCallbackInfo & info)180 void JSRectShape::ConstructorCallback(const JSCallbackInfo& info)
181 {
182 auto jsRectShape = AceType::MakeRefPtr<JSRectShape>();
183 auto rect = AceType::MakeRefPtr<ShapeRect>();
184
185 if (info.Length() > 0 && info[0]->IsObject()) {
186 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
187 CalcDimension width;
188 if (ParseJsDimensionVpNG(obj->GetProperty("width"), width) && width.IsValid()) {
189 rect->SetWidth(width);
190 }
191
192 CalcDimension height;
193 if (ParseJsDimensionVpNG(obj->GetProperty("height"), height) && height.IsValid()) {
194 rect->SetHeight(height);
195 }
196
197 CalcDimension radiusWidth;
198 if (ParseJsDimensionVpNG(obj->GetProperty("radiusWidth"), radiusWidth) && radiusWidth.IsValid()) {
199 rect->SetRadiusWidth(radiusWidth);
200 }
201
202 CalcDimension radiusHeight;
203 if (ParseJsDimensionVpNG(obj->GetProperty("radiusHeight"), radiusHeight) && radiusHeight.IsValid()) {
204 rect->SetRadiusHeight(radiusHeight);
205 }
206
207 JSRef<JSVal> radius = obj->GetProperty("radius");
208 if (radius->IsNumber() || radius->IsString()) {
209 SetRadiusWithJsVal(rect, radius);
210 }
211 if (radius->IsArray()) {
212 SetRadiusWithArrayValue(rect, radius);
213 }
214 info.SetReturnValue(info.This());
215 }
216
217 jsRectShape->SetBasicShape(rect);
218 jsRectShape->IncRefCount();
219 info.SetReturnValue(AceType::RawPtr(jsRectShape));
220 }
221
DestructorCallback(JSRectShape * jsRectShape)222 void JSRectShape::DestructorCallback(JSRectShape* jsRectShape)
223 {
224 if (jsRectShape != nullptr) {
225 jsRectShape->DecRefCount();
226 }
227 }
228
JSBind(BindingTarget globalObj)229 void JSRectShape::JSBind(BindingTarget globalObj)
230 {
231 JSClass<JSRectShape>::Declare("__RectShape__");
232
233 JSClass<JSRectShape>::CustomMethod("width", &JSShapeAbstract::ObjectWidth);
234 JSClass<JSRectShape>::CustomMethod("height", &JSShapeAbstract::ObjectHeight);
235 JSClass<JSRectShape>::CustomMethod("size", &JSShapeAbstract::ObjectSize);
236 JSClass<JSRectShape>::CustomMethod("offset", &JSShapeAbstract::ObjectOffset);
237 JSClass<JSRectShape>::CustomMethod("radiusWidth", &JSRectShape::ObjectRadiusWidth);
238 JSClass<JSRectShape>::CustomMethod("radiusHeight", &JSRectShape::ObjectRadiusHeight);
239 JSClass<JSRectShape>::CustomMethod("radius", &JSRectShape::ObjectRadius);
240 JSClass<JSRectShape>::CustomMethod("fill", &JSShapeAbstract::ObjectFill);
241 JSClass<JSRectShape>::CustomMethod("position", &JSShapeAbstract::ObjectPosition);
242
243 JSClass<JSRectShape>::InheritAndBind<JSShapeAbstract>(
244 globalObj, JSRectShape::ConstructorCallback, JSRectShape::DestructorCallback);
245 }
246
247 } // namespace OHOS::Ace::Framework
248