• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (c) 2021 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_shape_abstract.h"
17 
18 #include "base/utils/utils.h"
19 #include "bridge/declarative_frontend/jsview/models/shape_abstract_model_impl.h"
20 #include "core/common/container.h"
21 #include "core/components_ng/pattern/shape/shape_abstract_model.h"
22 #include "core/components_ng/pattern/shape/shape_abstract_model_ng.h"
23 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
24 
25 namespace OHOS::Ace {
26 
27 std::unique_ptr<ShapeAbstractModel> ShapeAbstractModel::instance_ = nullptr;
28 
GetInstance()29 ShapeAbstractModel* ShapeAbstractModel::GetInstance()
30 {
31     if (!instance_) {
32 #ifdef NG_BUILD
33         instance_.reset(new NG::ShapeAbstractModelNG());
34 #else
35         if (Container::IsCurrentUseNewPipeline()) {
36             instance_.reset(new NG::ShapeAbstractModelNG());
37         } else {
38             instance_.reset(new Framework::ShapeAbstractModelImpl());
39         }
40 #endif
41     }
42     return instance_.get();
43 }
44 
45 } // namespace OHOS::Ace
46 
47 namespace OHOS::Ace::Framework {
48 namespace {
49     constexpr double DEFAULT_OPACITY = 1.0;
50     constexpr double MIN_OPACITY = 0.0;
51 } // namespace
52 
SetStrokeDashArray(const JSCallbackInfo & info)53 void JSShapeAbstract::SetStrokeDashArray(const JSCallbackInfo& info)
54 {
55     if (info.Length() < 1 || !info[0]->IsArray()) {
56         LOGE("info is not array");
57         return;
58     }
59     JSRef<JSArray> array = JSRef<JSArray>::Cast(info[0]);
60     int32_t length = static_cast<int32_t>(array->Length());
61     std::vector<Dimension> dashArray;
62     for (int32_t i = 0; i < length; i++) {
63         JSRef<JSVal> value = array->GetValueAt(i);
64         Dimension dim;
65         if (ParseJsDimensionVp(value, dim)) {
66             dashArray.emplace_back(dim);
67         }
68     }
69     if (length != static_cast<int32_t>(dashArray.size())) {
70         LOGE("ParseJsDimensionVp failed");
71         return;
72     }
73     // if odd,add twice
74     if ((static_cast<uint32_t>(length) & 1)) {
75         for (int32_t i = 0; i < length; i++) {
76             dashArray.emplace_back(dashArray[i]);
77         }
78     }
79     ShapeAbstractModel::GetInstance()->SetStrokeDashArray(dashArray);
80 }
81 
SetStroke(const JSCallbackInfo & info)82 void JSShapeAbstract::SetStroke(const JSCallbackInfo& info)
83 {
84     if (info.Length() < 1) {
85         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
86         return;
87     }
88     Color strokeColor;
89     if (!ParseJsColor(info[0], strokeColor)) {
90         ShapeAbstractModel::GetInstance()->SetStroke(Color::TRANSPARENT);
91         return;
92     }
93     ShapeAbstractModel::GetInstance()->SetStroke(strokeColor);
94 }
95 
SetFill(const JSCallbackInfo & info)96 void JSShapeAbstract::SetFill(const JSCallbackInfo& info)
97 {
98     if (info.Length() < 1) {
99         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
100         return;
101     }
102     if (info[0]->IsString() && info[0]->ToString() == "none") {
103         ShapeAbstractModel::GetInstance()->SetFill(Color::TRANSPARENT);
104     } else {
105         Color fillColor = Color::BLACK;
106         if (ParseJsColor(info[0], fillColor)) {
107             ShapeAbstractModel::GetInstance()->SetFill(fillColor);
108         } else {
109             ShapeAbstractModel::GetInstance()->SetFill(fillColor);
110         }
111     }
112 }
113 
SetStrokeDashOffset(const JSCallbackInfo & info)114 void JSShapeAbstract::SetStrokeDashOffset(const JSCallbackInfo& info)
115 {
116     if (info.Length() < 1) {
117         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
118         return;
119     }
120     Dimension offset;
121     if (!ParseJsDimensionVp(info[0], offset)) {
122         return;
123     }
124     ShapeAbstractModel::GetInstance()->SetStrokeDashOffset(offset);
125 }
126 
SetStrokeLineCap(int lineCap)127 void JSShapeAbstract::SetStrokeLineCap(int lineCap)
128 {
129     ShapeAbstractModel::GetInstance()->SetStrokeLineCap(lineCap);
130 }
131 
SetStrokeLineJoin(int lineJoin)132 void JSShapeAbstract::SetStrokeLineJoin(int lineJoin)
133 {
134     ShapeAbstractModel::GetInstance()->SetStrokeLineJoin(lineJoin);
135 }
136 
SetStrokeMiterLimit(const JSCallbackInfo & info)137 void JSShapeAbstract::SetStrokeMiterLimit(const JSCallbackInfo& info)
138 {
139     if (info.Length() < 1) {
140         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
141         return;
142     }
143     double miterLimit;
144     if (!ParseJsDouble(info[0], miterLimit)) {
145         return;
146     }
147     if (GreatOrEqual(miterLimit, 1.0)) {
148         ShapeAbstractModel::GetInstance()->SetStrokeMiterLimit(miterLimit);
149     }
150 }
151 
SetStrokeOpacity(const JSCallbackInfo & info)152 void JSShapeAbstract::SetStrokeOpacity(const JSCallbackInfo& info)
153 {
154     if (info.Length() < 1) {
155         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
156         return;
157     }
158     double strokeOpacity = DEFAULT_OPACITY;
159     ParseJsDouble(info[0], strokeOpacity);
160     if (GreatOrEqual(strokeOpacity, 1.0)) {
161         strokeOpacity = DEFAULT_OPACITY;
162     }
163     if (LessOrEqual(strokeOpacity, 0.0)) {
164         strokeOpacity = MIN_OPACITY;
165     }
166     ShapeAbstractModel::GetInstance()->SetStrokeOpacity(strokeOpacity);
167 }
168 
SetFillOpacity(const JSCallbackInfo & info)169 void JSShapeAbstract::SetFillOpacity(const JSCallbackInfo& info)
170 {
171     if (info.Length() < 1) {
172         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
173         return;
174     }
175     double fillOpacity = DEFAULT_OPACITY;
176     ParseJsDouble(info[0], fillOpacity);
177     ShapeAbstractModel::GetInstance()->SetFillOpacity(fillOpacity);
178 }
179 
SetStrokeWidth(const JSCallbackInfo & info)180 void JSShapeAbstract::SetStrokeWidth(const JSCallbackInfo& info)
181 {
182     if (info.Length() < 1) {
183         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
184         return;
185     }
186     // the default value is 1.0_vp
187     Dimension lineWidth = 1.0_vp;
188     if (info[0]->IsString()) {
189         const std::string& value = info[0]->ToString();
190         lineWidth = StringUtils::StringToDimensionWithUnit(value, DimensionUnit::VP, 1.0);
191     } else {
192         ParseJsDimensionVp(info[0], lineWidth);
193     }
194     if (lineWidth.IsNegative()) {
195         lineWidth = 1.0_vp;
196     }
197     ShapeAbstractModel::GetInstance()->SetStrokeWidth(lineWidth);
198 }
199 
SetAntiAlias(bool antiAlias)200 void JSShapeAbstract::SetAntiAlias(bool antiAlias)
201 {
202     ShapeAbstractModel::GetInstance()->SetAntiAlias(antiAlias);
203 }
204 
JsWidth(const JSCallbackInfo & info)205 void JSShapeAbstract::JsWidth(const JSCallbackInfo& info)
206 {
207     if (info.Length() < 1) {
208         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
209         return;
210     }
211 
212     SetWidth(info[0]);
213 }
214 
SetWidth(const JSRef<JSVal> & jsValue)215 void JSShapeAbstract::SetWidth(const JSRef<JSVal>& jsValue)
216 {
217     Dimension dimWidth;
218     if (!ParseJsDimensionVp(jsValue, dimWidth)) {
219         return;
220     }
221     ShapeAbstractModel::GetInstance()->SetWidth(dimWidth);
222 }
223 
JsHeight(const JSCallbackInfo & info)224 void JSShapeAbstract::JsHeight(const JSCallbackInfo& info)
225 {
226     if (info.Length() < 1) {
227         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
228         return;
229     }
230 
231     SetHeight(info[0]);
232 }
233 
SetHeight(const JSRef<JSVal> & jsValue)234 void JSShapeAbstract::SetHeight(const JSRef<JSVal>& jsValue)
235 {
236     Dimension dimHeight;
237     if (!ParseJsDimensionVp(jsValue, dimHeight)) {
238         return;
239     }
240     ShapeAbstractModel::GetInstance()->SetHeight(dimHeight);
241 }
242 
JsSize(const JSCallbackInfo & info)243 void JSShapeAbstract::JsSize(const JSCallbackInfo& info)
244 {
245     if (info.Length() < 1) {
246         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
247         return;
248     }
249 
250     if (!info[0]->IsObject()) {
251         LOGE("arg is not Object or String.");
252         return;
253     }
254 
255     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
256     SetWidth(sizeObj->GetProperty("width"));
257     SetHeight(sizeObj->GetProperty("height"));
258 }
259 
ObjectWidth(const JSCallbackInfo & info)260 void JSShapeAbstract::ObjectWidth(const JSCallbackInfo& info)
261 {
262     info.ReturnSelf();
263     if (info.Length() < 1) {
264         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
265         return;
266     }
267 
268     ObjectWidth(info[0]);
269 }
270 
ObjectWidth(const JSRef<JSVal> & jsValue)271 void JSShapeAbstract::ObjectWidth(const JSRef<JSVal>& jsValue)
272 {
273     Dimension value;
274     if (!ParseJsDimensionVp(jsValue, value)) {
275         return;
276     }
277     if (LessNotEqual(value.Value(), 0.0)) {
278         LOGE("Value is less than zero");
279         return;
280     }
281     if (basicShape_) {
282         basicShape_->SetWidth(value);
283     }
284 }
285 
ObjectHeight(const JSCallbackInfo & info)286 void JSShapeAbstract::ObjectHeight(const JSCallbackInfo& info)
287 {
288     info.ReturnSelf();
289     if (info.Length() < 1) {
290         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
291         return;
292     }
293 
294     ObjectHeight(info[0]);
295 }
296 
ObjectHeight(const JSRef<JSVal> & jsValue)297 void JSShapeAbstract::ObjectHeight(const JSRef<JSVal>& jsValue)
298 {
299     Dimension value;
300     if (!ParseJsDimensionVp(jsValue, value)) {
301         return;
302     }
303     if (LessNotEqual(value.Value(), 0.0)) {
304         LOGE("Value is less than zero");
305         return;
306     }
307     if (basicShape_) {
308         basicShape_->SetHeight(value);
309     }
310 }
311 
ObjectSize(const JSCallbackInfo & info)312 void JSShapeAbstract::ObjectSize(const JSCallbackInfo& info)
313 {
314     if (info.Length() < 1) {
315         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
316         return;
317     }
318 
319     if (!info[0]->IsObject()) {
320         LOGE("arg is not Object or String.");
321         return;
322     }
323 
324     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
325     ObjectWidth(sizeObj->GetProperty("width"));
326     ObjectHeight(sizeObj->GetProperty("height"));
327 }
328 
ObjectOffset(const JSCallbackInfo & info)329 void JSShapeAbstract::ObjectOffset(const JSCallbackInfo& info)
330 {
331     info.ReturnSelf();
332     if (info.Length() > 0 && info[0]->IsObject()) {
333         JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
334         JSRef<JSVal> xVal = sizeObj->GetProperty("x");
335         JSRef<JSVal> yVal = sizeObj->GetProperty("y");
336         Dimension x;
337         Dimension y;
338         if (basicShape_ && ParseJsDimensionVp(xVal, x) && ParseJsDimensionVp(yVal, y)) {
339             basicShape_->SetOffset(DimensionOffset(x, y));
340         }
341     }
342 }
343 
ObjectFill(const JSCallbackInfo & info)344 void JSShapeAbstract::ObjectFill(const JSCallbackInfo& info)
345 {
346     info.ReturnSelf();
347     if (info.Length() < 1) {
348         LOGE("The arg is wrong, it is supposed to have at least 1 arguments");
349         return;
350     }
351 
352     Color color;
353     if (ParseJsColor(info[0], color) && basicShape_) {
354         basicShape_->SetColor(color);
355     }
356 }
357 
JSBind()358 void JSShapeAbstract::JSBind()
359 {
360     JSClass<JSShapeAbstract>::Declare("JSShapeAbstract");
361     MethodOptions opt = MethodOptions::NONE;
362     JSClass<JSShapeAbstract>::StaticMethod("stroke", &JSShapeAbstract::SetStroke, opt);
363     JSClass<JSShapeAbstract>::StaticMethod("fill", &JSShapeAbstract::SetFill, opt);
364     JSClass<JSShapeAbstract>::StaticMethod("strokeDashOffset", &JSShapeAbstract::SetStrokeDashOffset, opt);
365     JSClass<JSShapeAbstract>::StaticMethod("strokeDashArray", &JSShapeAbstract::SetStrokeDashArray);
366     JSClass<JSShapeAbstract>::StaticMethod("strokeLineCap", &JSShapeAbstract::SetStrokeLineCap, opt);
367     JSClass<JSShapeAbstract>::StaticMethod("strokeLineJoin", &JSShapeAbstract::SetStrokeLineJoin, opt);
368     JSClass<JSShapeAbstract>::StaticMethod("strokeMiterLimit", &JSShapeAbstract::SetStrokeMiterLimit, opt);
369     JSClass<JSShapeAbstract>::StaticMethod("strokeOpacity", &JSShapeAbstract::SetStrokeOpacity, opt);
370     JSClass<JSShapeAbstract>::StaticMethod("fillOpacity", &JSShapeAbstract::SetFillOpacity, opt);
371     JSClass<JSShapeAbstract>::StaticMethod("strokeWidth", &JSShapeAbstract::SetStrokeWidth, opt);
372     JSClass<JSShapeAbstract>::StaticMethod("antiAlias", &JSShapeAbstract::SetAntiAlias, opt);
373     JSClass<JSShapeAbstract>::StaticMethod("width", &JSShapeAbstract::JsWidth, opt);
374     JSClass<JSShapeAbstract>::StaticMethod("height", &JSShapeAbstract::JsHeight, opt);
375     JSClass<JSShapeAbstract>::StaticMethod("size", &JSShapeAbstract::JsSize, opt);
376     JSClass<JSShapeAbstract>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
377     JSClass<JSShapeAbstract>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
378     JSClass<JSShapeAbstract>::Inherit<JSViewAbstract>();
379 }
380 
SetSize(const JSCallbackInfo & info)381 void JSShapeAbstract::SetSize(const JSCallbackInfo& info)
382 {
383     if (info.Length() > 0 && info[0]->IsObject()) {
384         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
385         JSRef<JSVal> width = obj->GetProperty("width");
386         JSRef<JSVal> height = obj->GetProperty("height");
387         Dimension dimWidth;
388         if (ParseJsDimensionVp(width, dimWidth)) {
389             ShapeAbstractModel::GetInstance()->SetWidth(dimWidth);
390         }
391         Dimension dimHeight;
392         if (ParseJsDimensionVp(height, dimHeight)) {
393             ShapeAbstractModel::GetInstance()->SetHeight(dimHeight);
394         }
395     }
396 }
397 
398 } // namespace OHOS::Ace::Framework
399