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 JSRef<JSArray> radiusArray = JSRef<JSArray>::Cast(radiusItem);
131 if (radiusArray->Length() != LENGTH_RADIUS_ARRAY) {
132 break;
133 }
134 JSRef<JSVal> radiusX = radiusArray->GetValueAt(0);
135 JSRef<JSVal> radiusY = radiusArray->GetValueAt(1);
136 CalcDimension radiusXValue(0.0f);
137 CalcDimension radiusYValue(0.0f);
138
139 if (Container::LessThanAPIVersion(PlatformVersion::VERSION_TEN)) {
140 if (ParseJsDimensionVp(radiusX, radiusXValue)) {
141 ParseJsDimensionVp(radiusY, radiusYValue);
142 }
143 } else {
144 if (!ParseJsDimensionVpNG(radiusX, radiusXValue)) {
145 radiusXValue.SetValue(0.0f);
146 }
147 if (!ParseJsDimensionVpNG(radiusY, radiusYValue)) {
148 radiusYValue.SetValue(0.0f);
149 }
150 }
151
152 SetRadiusValue(shapeRect, radiusXValue, radiusYValue, i);
153 }
154 }
155
SetRadiusValue(const RefPtr<ShapeRect> & shapeRect,const CalcDimension & radiusX,const CalcDimension & radiusY,int32_t index)156 void JSRectShape::SetRadiusValue(
157 const RefPtr<ShapeRect>& shapeRect, const CalcDimension& radiusX, const CalcDimension& radiusY, int32_t index)
158 {
159 CHECK_NULL_VOID(shapeRect);
160 auto newRadius = Ace::Radius(Dimension(radiusX), Dimension(radiusY));
161 switch (index) {
162 case TOP_LEFT_RADIUS:
163 shapeRect->SetTopLeftRadius(newRadius);
164 break;
165 case TOP_RIGHT_RADIUS:
166 shapeRect->SetTopRightRadius(newRadius);
167 break;
168 case BOTTOM_RIGHT_RADIUS:
169 shapeRect->SetBottomRightRadius(newRadius);
170 break;
171 case BOTTOM_LEFT_RADIUS:
172 shapeRect->SetBottomLeftRadius(newRadius);
173 break;
174 default:
175 break;
176 }
177 }
178
ConstructorCallback(const JSCallbackInfo & info)179 void JSRectShape::ConstructorCallback(const JSCallbackInfo& info)
180 {
181 auto jsRectShape = AceType::MakeRefPtr<JSRectShape>();
182 auto rect = AceType::MakeRefPtr<ShapeRect>();
183
184 if (info.Length() > 0 && info[0]->IsObject()) {
185 JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
186 CalcDimension width;
187 if (ParseJsDimensionVpNG(obj->GetProperty("width"), width) && width.IsValid()) {
188 rect->SetWidth(width);
189 }
190
191 CalcDimension height;
192 if (ParseJsDimensionVpNG(obj->GetProperty("height"), height) && height.IsValid()) {
193 rect->SetHeight(height);
194 }
195
196 CalcDimension radiusWidth;
197 if (ParseJsDimensionVpNG(obj->GetProperty("radiusWidth"), radiusWidth) && radiusWidth.IsValid()) {
198 rect->SetRadiusWidth(radiusWidth);
199 }
200
201 CalcDimension radiusHeight;
202 if (ParseJsDimensionVpNG(obj->GetProperty("radiusHeight"), radiusHeight) && radiusHeight.IsValid()) {
203 rect->SetRadiusHeight(radiusHeight);
204 }
205
206 JSRef<JSVal> radius = obj->GetProperty("radius");
207 if (radius->IsNumber() || radius->IsString()) {
208 SetRadiusWithJsVal(rect, radius);
209 }
210 if (radius->IsArray()) {
211 SetRadiusWithArrayValue(rect, radius);
212 }
213 info.SetReturnValue(info.This());
214 }
215
216 jsRectShape->SetBasicShape(rect);
217 jsRectShape->IncRefCount();
218 info.SetReturnValue(AceType::RawPtr(jsRectShape));
219 }
220
DestructorCallback(JSRectShape * jsRectShape)221 void JSRectShape::DestructorCallback(JSRectShape* jsRectShape)
222 {
223 if (jsRectShape != nullptr) {
224 jsRectShape->DecRefCount();
225 }
226 }
227
JSBind(BindingTarget globalObj)228 void JSRectShape::JSBind(BindingTarget globalObj)
229 {
230 JSClass<JSRectShape>::Declare("__RectShape__");
231
232 JSClass<JSRectShape>::CustomMethod("width", &JSShapeAbstract::ObjectWidth);
233 JSClass<JSRectShape>::CustomMethod("height", &JSShapeAbstract::ObjectHeight);
234 JSClass<JSRectShape>::CustomMethod("size", &JSShapeAbstract::ObjectSize);
235 JSClass<JSRectShape>::CustomMethod("offset", &JSShapeAbstract::ObjectOffset);
236 JSClass<JSRectShape>::CustomMethod("radiusWidth", &JSRectShape::ObjectRadiusWidth);
237 JSClass<JSRectShape>::CustomMethod("radiusHeight", &JSRectShape::ObjectRadiusHeight);
238 JSClass<JSRectShape>::CustomMethod("radius", &JSRectShape::ObjectRadius);
239 JSClass<JSRectShape>::CustomMethod("fill", &JSShapeAbstract::ObjectFill);
240 JSClass<JSRectShape>::CustomMethod("position", &JSShapeAbstract::ObjectPosition);
241
242 JSClass<JSRectShape>::InheritAndBind<JSShapeAbstract>(
243 globalObj, JSRectShape::ConstructorCallback, JSRectShape::DestructorCallback);
244 }
245
246 } // namespace OHOS::Ace::Framework
247