• 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.h"
17 
18 #include "frameworks/bridge/declarative_frontend/jsview/js_utils.h"
19 #include "frameworks/bridge/declarative_frontend/view_stack_processor.h"
20 
21 namespace OHOS::Ace::Framework {
22 namespace {
23 constexpr double DEFAULT_OPACITY = 1.0;
24 }
25 
Create(const JSCallbackInfo & info)26 void JSShape::Create(const JSCallbackInfo& info)
27 {
28     std::list<RefPtr<OHOS::Ace::Component>> componentChildren;
29     RefPtr<OHOS::Ace::ShapeContainerComponent> component =
30         AceType::MakeRefPtr<OHOS::Ace::ShapeContainerComponent>(componentChildren);
31     ViewStackProcessor::GetInstance()->Push(component);
32     JSInteractableView::SetFocusable(true);
33     InitBox(info);
34 }
35 
InitBox(const JSCallbackInfo & info)36 void JSShape::InitBox(const JSCallbackInfo& info)
37 {
38     auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
39     box->SetOverflow(Overflow::FORCE_CLIP);
40     auto clipPath = AceType::MakeRefPtr<ClipPath>();
41     clipPath->SetGeometryBoxType(GeometryBoxType::BORDER_BOX);
42     box->SetClipPath(clipPath);
43     if (info.Length() == 1 && info[0]->IsObject()) {
44 #if !defined(WINDOWS_PLATFORM) and !defined(MAC_PLATFORM)
45         box->SetPixelMap(CreatePixelMapFromNapiValue(info[0]));
46 #endif
47     }
48 }
49 
SetViewPort(const JSCallbackInfo & info)50 void JSShape::SetViewPort(const JSCallbackInfo& info)
51 {
52     if (info.Length() < 1) {
53         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
54         return;
55     }
56     auto stack = ViewStackProcessor::GetInstance();
57     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
58     if (!component) {
59         LOGE("shape is null");
60         return;
61     }
62     if (info[0]->IsObject()) {
63         JSRef<JSObject> obj = JSRef<JSObject>::Cast(info[0]);
64         JSRef<JSVal> leftValue = obj->GetProperty("x");
65         JSRef<JSVal> topValue = obj->GetProperty("y");
66         JSRef<JSVal> widthValue = obj->GetProperty("width");
67         JSRef<JSVal> heightValue = obj->GetProperty("height");
68         AnimationOption option = stack->GetImplicitAnimationOption();
69         ShapeViewBox viewBox;
70         Dimension dimLeft;
71         if (ParseJsDimensionVp(leftValue, dimLeft)) {
72             viewBox.SetLeft(dimLeft, option);
73         }
74         Dimension dimTop;
75         if (ParseJsDimensionVp(topValue, dimTop)) {
76             viewBox.SetTop(dimTop, option);
77         }
78         Dimension dimWidth;
79         if (ParseJsDimensionVp(widthValue, dimWidth)) {
80             viewBox.SetWidth(dimWidth, option);
81         }
82         Dimension dimHeight;
83         if (ParseJsDimensionVp(heightValue, dimHeight)) {
84             viewBox.SetHeight(dimHeight, option);
85         }
86         component->SetViewBox(viewBox);
87     }
88     info.SetReturnValue(info.This());
89 }
90 
JsWidth(const JSCallbackInfo & info)91 void JSShape::JsWidth(const JSCallbackInfo& info)
92 {
93     if (info.Length() < 1) {
94         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
95         return;
96     }
97 
98     JsWidth(info[0]);
99 }
100 
JsWidth(const JSRef<JSVal> & jsValue)101 void JSShape::JsWidth(const JSRef<JSVal>& jsValue)
102 {
103     JSViewAbstract::JsWidth(jsValue);
104     auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
105     if (!box->GetWidth().IsValid()) {
106         return;
107     }
108     auto stack = ViewStackProcessor::GetInstance();
109     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
110     if (component) {
111         component->SetWidthFlag(true);
112     }
113 }
114 
JsHeight(const JSCallbackInfo & info)115 void JSShape::JsHeight(const JSCallbackInfo& info)
116 {
117     if (info.Length() < 1) {
118         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
119         return;
120     }
121 
122     JsHeight(info[0]);
123 }
124 
JsHeight(const JSRef<JSVal> & jsValue)125 void JSShape::JsHeight(const JSRef<JSVal>& jsValue)
126 {
127     JSViewAbstract::JsHeight(jsValue);
128     auto box = ViewStackProcessor::GetInstance()->GetBoxComponent();
129     if (!box->GetHeight().IsValid()) {
130         return;
131     }
132     auto stack = ViewStackProcessor::GetInstance();
133     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
134     if (component) {
135         component->SetHeightFlag(true);
136     }
137 }
138 
JsSize(const JSCallbackInfo & info)139 void JSShape::JsSize(const JSCallbackInfo& info)
140 {
141     if (info.Length() < 1) {
142         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
143         return;
144     }
145 
146     if (!info[0]->IsObject()) {
147         LOGE("arg is not Object or String.");
148         return;
149     }
150 
151     JSRef<JSObject> sizeObj = JSRef<JSObject>::Cast(info[0]);
152     JsWidth(sizeObj->GetProperty("width"));
153     JsHeight(sizeObj->GetProperty("height"));
154 }
155 
SetStrokeDashArray(const JSCallbackInfo & info)156 void JSShape::SetStrokeDashArray(const JSCallbackInfo& info)
157 {
158     if (info.Length() < 1 || !info[0]->IsArray()) {
159         LOGE("info is not array");
160         return;
161     }
162     auto stack = ViewStackProcessor::GetInstance();
163     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
164     if (!component) {
165         LOGE("component is null");
166         return;
167     }
168 
169     JSRef<JSArray> array = JSRef<JSArray>::Cast(info[0]);
170     int32_t length = static_cast<int32_t>(array->Length());
171     if (length <= 0) {
172         LOGE("info is invalid");
173         return;
174     }
175     std::vector<Dimension> dashArray;
176     for (int32_t i = 0; i < length; i++) {
177         JSRef<JSVal> value = array->GetValueAt(i);
178         Dimension dim;
179         if (ParseJsDimensionVp(value, dim)) {
180             dashArray.emplace_back(dim);
181         }
182     }
183     if (length != static_cast<int32_t>(dashArray.size())) {
184         LOGE("ParseJsDimensionVp failed");
185         return;
186     }
187     // if odd,add twice
188     if ((static_cast<uint32_t>(length) & 1)) {
189         for (int32_t i = 0; i < length; i++) {
190             dashArray.emplace_back(dashArray[i]);
191         }
192     }
193     component->SetStrokeDashArray(dashArray);
194     info.SetReturnValue(info.This());
195 }
196 
SetStroke(const JSCallbackInfo & info)197 void JSShape::SetStroke(const JSCallbackInfo& info)
198 {
199     if (info.Length() < 1) {
200         LOGE("The argv is wrong, it is supposed to have at least 1 argument");
201         return;
202     }
203     Color strokeColor = Color::TRANSPARENT;
204     ParseJsColor(info[0], strokeColor);
205     auto stack = ViewStackProcessor::GetInstance();
206     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
207     if (component) {
208         AnimationOption option = stack->GetImplicitAnimationOption();
209         component->SetStroke(strokeColor, option);
210     }
211 }
212 
SetFill(const JSCallbackInfo & info)213 void JSShape::SetFill(const JSCallbackInfo& info)
214 {
215     if (info.Length() < 1) {
216         LOGE("The arg is wrong, it is supposed to have atleast 1 arguments");
217         return;
218     }
219     auto stack = ViewStackProcessor::GetInstance();
220     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
221     if (!component) {
222         LOGE("component is null");
223         return;
224     }
225     AnimationOption option = stack->GetImplicitAnimationOption();
226     if (info[0]->IsString() && info[0]->ToString() == "none") {
227         component->SetFill(Color::TRANSPARENT, option);
228     } else {
229         Color fillColor;
230         if (ParseJsColor(info[0], fillColor)) {
231             component->SetFill(fillColor, option);
232         }
233     }
234 }
235 
SetStrokeDashOffset(const JSCallbackInfo & info)236 void JSShape::SetStrokeDashOffset(const JSCallbackInfo& info)
237 {
238     if (info.Length() < 1) {
239         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
240         return;
241     }
242     Dimension offset;
243     if (!ParseJsDimensionVp(info[0], offset)) {
244         return;
245     }
246     auto stack = ViewStackProcessor::GetInstance();
247     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
248     if (component) {
249         AnimationOption option = stack->GetImplicitAnimationOption();
250         component->SetStrokeDashOffset(offset, option);
251     }
252 }
253 
SetStrokeLineCap(int lineCap)254 void JSShape::SetStrokeLineCap(int lineCap)
255 {
256     auto stack = ViewStackProcessor::GetInstance();
257     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
258     if (!component) {
259         LOGE("ShapeComponent is null");
260         return;
261     }
262     if (static_cast<int>(LineCapStyle::SQUARE) == lineCap) {
263         component->SetStrokeLineCap(LineCapStyle::SQUARE);
264     } else if (static_cast<int>(LineCapStyle::ROUND) == lineCap) {
265         component->SetStrokeLineCap(LineCapStyle::ROUND);
266     } else {
267         component->SetStrokeLineCap(LineCapStyle::BUTT);
268     }
269 }
270 
SetStrokeLineJoin(int lineJoin)271 void JSShape::SetStrokeLineJoin(int lineJoin)
272 {
273     auto stack = ViewStackProcessor::GetInstance();
274     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
275     if (!component) {
276         LOGE("ShapeComponent is null");
277         return;
278     }
279     if (static_cast<int>(LineJoinStyle::BEVEL) == lineJoin) {
280         component->SetStrokeLineJoin(LineJoinStyle::BEVEL);
281     } else if (static_cast<int>(LineJoinStyle::ROUND) == lineJoin) {
282         component->SetStrokeLineJoin(LineJoinStyle::ROUND);
283     } else {
284         component->SetStrokeLineJoin(LineJoinStyle::MITER);
285     }
286 }
287 
SetStrokeMiterLimit(const JSCallbackInfo & info)288 void JSShape::SetStrokeMiterLimit(const JSCallbackInfo& info)
289 {
290     if (info.Length() < 1) {
291         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
292         return;
293     }
294     double miterLimit;
295     if (!ParseJsDouble(info[0], miterLimit)) {
296         return;
297     }
298     auto stack = ViewStackProcessor::GetInstance();
299     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
300     if (!component) {
301         LOGE("ShapeComponent is null");
302         return;
303     }
304     if (GreatOrEqual(miterLimit, 1.0)) {
305         component->SetStrokeMiterLimit(miterLimit);
306     }
307 }
308 
SetStrokeOpacity(const JSCallbackInfo & info)309 void JSShape::SetStrokeOpacity(const JSCallbackInfo& info)
310 {
311     if (info.Length() < 1) {
312         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
313         return;
314     }
315     double strokeOpacity = DEFAULT_OPACITY;
316     ParseJsDouble(info[0], strokeOpacity);
317     auto stack = ViewStackProcessor::GetInstance();
318     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
319     if (component) {
320         AnimationOption option = stack->GetImplicitAnimationOption();
321         component->SetStrokeOpacity(strokeOpacity, option);
322     }
323 }
324 
SetFillOpacity(const JSCallbackInfo & info)325 void JSShape::SetFillOpacity(const JSCallbackInfo& info)
326 {
327     if (info.Length() < 1) {
328         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
329         return;
330     }
331     double fillOpacity = DEFAULT_OPACITY;
332     ParseJsDouble(info[0], fillOpacity);
333     auto stack = ViewStackProcessor::GetInstance();
334     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
335     if (component) {
336         AnimationOption option = stack->GetImplicitAnimationOption();
337         component->SetFillOpacity(fillOpacity, option);
338     }
339 }
340 
SetStrokeWidth(const JSCallbackInfo & info)341 void JSShape::SetStrokeWidth(const JSCallbackInfo& info)
342 {
343     if (info.Length() < 1) {
344         LOGE("The arg is wrong, it is supposed to have at least 1 argument");
345         return;
346     }
347     Dimension lineWidth;
348     if (!ParseJsDimensionVp(info[0], lineWidth)) {
349         return;
350     }
351     auto stack = ViewStackProcessor::GetInstance();
352     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
353     if (!component) {
354         LOGE("ShapeComponent is null");
355         return;
356     }
357     if (GreatOrEqual(lineWidth.Value(), 0.0)) {
358         AnimationOption option = stack->GetImplicitAnimationOption();
359         component->SetStrokeWidth(lineWidth, option);
360     }
361 }
362 
SetAntiAlias(bool antiAlias)363 void JSShape::SetAntiAlias(bool antiAlias)
364 {
365     auto stack = ViewStackProcessor::GetInstance();
366     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
367     if (component) {
368         component->SetAntiAlias(antiAlias);
369     }
370 }
371 
SetBitmapMesh(const JSCallbackInfo & info)372 void JSShape::SetBitmapMesh(const JSCallbackInfo& info)
373 {
374     if (info.Length() != 3) {
375         LOGE("The arg is wrong, it is supposed to have at least 3 argument");
376         return;
377     }
378     std::vector<double> mesh;
379     JSRef<JSVal> meshValue = info[0];
380 
381     if (meshValue->IsObject()) {
382         JSRef<JSObject> meshObj = JSRef<JSObject>::Cast(meshValue);
383         JSRef<JSArray> array = meshObj->GetPropertyNames();
384         for (size_t i = 0; i < array->Length(); i++) {
385             JSRef<JSVal> value = array->GetValueAt(i);
386             if (value->IsString()) {
387                 std::string valueStr;
388                 if (ParseJsString(value, valueStr)) {
389                     double vert;
390                     if (ParseJsDouble(meshObj->GetProperty(valueStr.c_str()), vert)) {
391                         mesh.push_back(vert);
392                     }
393                 }
394             }
395         }
396     }
397     uint32_t column = 0;
398     uint32_t row = 0;
399     JSRef<JSVal> columnValue = info[1];
400     JSRef<JSVal> rowValue = info[2];
401     if (!ParseJsInteger(columnValue, column)) {
402         return;
403     }
404     if (!ParseJsInteger(rowValue, row)) {
405         return;
406     }
407     auto stack = ViewStackProcessor::GetInstance();
408     auto component = AceType::DynamicCast<OHOS::Ace::ShapeContainerComponent>(stack->GetMainComponent());
409     if (component) {
410         component->SetBitmapMesh(mesh, (int32_t)column, (int32_t)row);
411     }
412 }
413 
JSBind(BindingTarget globalObj)414 void JSShape::JSBind(BindingTarget globalObj)
415 {
416     JSClass<JSShape>::Declare("Shape");
417     JSClass<JSShape>::StaticMethod("create", &JSShape::Create);
418     JSClass<JSShape>::StaticMethod("viewPort", &JSShape::SetViewPort);
419 
420     JSClass<JSShape>::StaticMethod("width", &JSShape::JsWidth);
421     JSClass<JSShape>::StaticMethod("height", &JSShape::JsHeight);
422     JSClass<JSShape>::StaticMethod("size", &JSShape::JsSize);
423 
424     JSClass<JSShape>::StaticMethod("stroke", &JSShape::SetStroke);
425     JSClass<JSShape>::StaticMethod("fill", &JSShape::SetFill);
426     JSClass<JSShape>::StaticMethod("strokeDashOffset", &JSShape::SetStrokeDashOffset);
427     JSClass<JSShape>::StaticMethod("strokeDashArray", &JSShape::SetStrokeDashArray);
428     JSClass<JSShape>::StaticMethod("strokeLineCap", &JSShape::SetStrokeLineCap);
429     JSClass<JSShape>::StaticMethod("strokeLineJoin", &JSShape::SetStrokeLineJoin);
430     JSClass<JSShape>::StaticMethod("strokeMiterLimit", &JSShape::SetStrokeMiterLimit);
431     JSClass<JSShape>::StaticMethod("strokeOpacity", &JSShape::SetStrokeOpacity);
432     JSClass<JSShape>::StaticMethod("fillOpacity", &JSShape::SetFillOpacity);
433     JSClass<JSShape>::StaticMethod("strokeWidth", &JSShape::SetStrokeWidth);
434     JSClass<JSShape>::StaticMethod("antiAlias", &JSShape::SetAntiAlias);
435     JSClass<JSShape>::StaticMethod("mesh", &JSShape::SetBitmapMesh);
436 
437     JSClass<JSShape>::StaticMethod("onTouch", &JSInteractableView::JsOnTouch);
438     JSClass<JSShape>::StaticMethod("onHover", &JSInteractableView::JsOnHover);
439     JSClass<JSShape>::StaticMethod("onKeyEvent", &JSInteractableView::JsOnKey);
440     JSClass<JSShape>::StaticMethod("onDeleteEvent", &JSInteractableView::JsOnDelete);
441     JSClass<JSShape>::StaticMethod("onClick", &JSInteractableView::JsOnClick);
442     JSClass<JSShape>::StaticMethod("onAppear", &JSInteractableView::JsOnAppear);
443     JSClass<JSShape>::StaticMethod("onDisAppear", &JSInteractableView::JsOnDisAppear);
444     JSClass<JSShape>::StaticMethod("remoteMessage", &JSInteractableView::JsCommonRemoteMessage);
445     JSClass<JSShape>::Inherit<JSContainerBase>();
446     JSClass<JSShape>::Inherit<JSViewAbstract>();
447     JSClass<JSShape>::Bind<>(globalObj);
448 }
449 
450 } // namespace OHOS::Ace::Framework
451