1 /*
2 * Copyright (c) 2022 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/js_view_measure_layout.h"
17
18 #include "jsnapi.h"
19
20 #include "base/geometry/dimension.h"
21 #include "frameworks/bridge/declarative_frontend/jsview/js_view_abstract.h"
22 #include "frameworks/core/components_ng/base/frame_node.h"
23
24 namespace OHOS::Ace::Framework {
25
26 #ifdef USE_ARK_ENGINE
27
28 thread_local std::list<RefPtr<NG::LayoutWrapper>> ViewMeasureLayout::measureChildren_;
29 thread_local std::list<RefPtr<NG::LayoutWrapper>>::iterator ViewMeasureLayout::iterMeasureChildren_;
30 thread_local std::list<RefPtr<NG::LayoutWrapper>> ViewMeasureLayout::layoutChildren_;
31 thread_local std::list<RefPtr<NG::LayoutWrapper>>::iterator ViewMeasureLayout::iterLayoutChildren_;
32 thread_local NG::LayoutConstraintF ViewMeasureLayout::measureDefaultConstraint_;
33
JSMeasure(panda::JsiRuntimeCallInfo * runtimeCallInfo)34 panda::Local<panda::JSValueRef> ViewMeasureLayout::JSMeasure(panda::JsiRuntimeCallInfo* runtimeCallInfo)
35 {
36 ACE_SCOPED_TRACE("ViewMeasureLayout::JSMeasure");
37 EcmaVM* vm = runtimeCallInfo->GetVM();
38
39 if (iterMeasureChildren_ == measureChildren_.end()) {
40 LOGE("Call measure exceed limit");
41 return panda::JSValueRef::Undefined(vm);
42 }
43
44 auto info = runtimeCallInfo;
45 if (info->GetArgsNumber() != 1 || !info->GetCallArgRef(0)->IsObject()) {
46 LOGE("JSMeasure arg is wrong");
47 (*iterMeasureChildren_)->Measure(measureDefaultConstraint_);
48 iterMeasureChildren_++;
49 return panda::JSValueRef::Undefined(vm);
50 }
51
52 auto jsObject = JsiObject(info->GetCallArgRef(0)->ToObject(vm));
53 JSRef<JSObject> sizeObj = JSRef<JSObject>::Make(jsObject);
54 JSRef<JSVal> minWidthValue = sizeObj->GetProperty("minWidth");
55 CalcDimension minWidth;
56 JSRef<JSVal> maxWidthValue = sizeObj->GetProperty("maxWidth");
57 CalcDimension maxWidth;
58 JSRef<JSVal> minHeightValue = sizeObj->GetProperty("minHeight");
59 CalcDimension minHeight;
60 JSRef<JSVal> maxHeightValue = sizeObj->GetProperty("maxHeight");
61 CalcDimension maxHeight;
62
63 if (JSViewAbstract::ParseJsDimensionVp(minWidthValue, minWidth)) {
64 (*iterMeasureChildren_)
65 ->GetLayoutProperty()
66 ->UpdateCalcMinSize(NG::CalcSize(NG::CalcLength(minWidth), std::nullopt));
67 }
68 if (JSViewAbstract::ParseJsDimensionVp(maxWidthValue, maxWidth)) {
69 (*iterMeasureChildren_)
70 ->GetLayoutProperty()
71 ->UpdateCalcMaxSize(NG::CalcSize(NG::CalcLength(maxWidth), std::nullopt));
72 }
73 if (JSViewAbstract::ParseJsDimensionVp(minHeightValue, minHeight)) {
74 (*iterMeasureChildren_)
75 ->GetLayoutProperty()
76 ->UpdateCalcMinSize(NG::CalcSize(std::nullopt, NG::CalcLength(minHeight)));
77 }
78 if (JSViewAbstract::ParseJsDimensionVp(maxHeightValue, maxHeight)) {
79 (*iterMeasureChildren_)
80 ->GetLayoutProperty()
81 ->UpdateCalcMaxSize(NG::CalcSize(std::nullopt, NG::CalcLength(maxHeight)));
82 }
83 (*iterMeasureChildren_)->Measure(measureDefaultConstraint_);
84
85 Dimension measureWidth((*iterMeasureChildren_)->GetGeometryNode()->GetFrameRect().Width(), DimensionUnit::PX);
86 Dimension measureHeight((*iterMeasureChildren_)->GetGeometryNode()->GetFrameRect().Height(), DimensionUnit::PX);
87 Local<ObjectRef> measureResultObject = ObjectRef::New(vm);
88 measureResultObject->Set(vm, ToJSValue("width"), ToJSValue(measureWidth.ConvertToVp()));
89 measureResultObject->Set(vm, ToJSValue("height"), ToJSValue(measureHeight.ConvertToVp()));
90
91 iterMeasureChildren_++;
92 return measureResultObject;
93 }
94
JSLayout(panda::JsiRuntimeCallInfo * runtimeCallInfo)95 panda::Local<panda::JSValueRef> ViewMeasureLayout::JSLayout(panda::JsiRuntimeCallInfo* runtimeCallInfo)
96 {
97 ACE_SCOPED_TRACE("ViewMeasureLayout::JSLayout");
98 EcmaVM* vm = runtimeCallInfo->GetVM();
99
100 if (iterLayoutChildren_ == layoutChildren_.end()) {
101 LOGE("Call layout exceed limit");
102 return panda::JSValueRef::Undefined(vm);
103 }
104
105 auto info = runtimeCallInfo;
106 if (info->GetArgsNumber() != 1 || !info->GetCallArgRef(0)->IsObject()) {
107 LOGE("JSLayout arg is wrong");
108 (*iterLayoutChildren_)->Layout();
109 iterLayoutChildren_++;
110 return panda::JSValueRef::Undefined(vm);
111 }
112
113 auto jsObject = JsiObject(info->GetCallArgRef(0)->ToObject(vm));
114 JSRef<JSObject> layoutInfo = JSRef<JSObject>::Make(jsObject);
115 JSRef<JSObject> sizeObj = layoutInfo->GetProperty("position");
116 JSRef<JSVal> xVal = sizeObj->GetProperty("x");
117 JSRef<JSVal> yVal = sizeObj->GetProperty("y");
118 CalcDimension dimenX;
119 CalcDimension dimenY;
120 auto xResult = JSViewAbstract::ParseJsDimensionVp(xVal, dimenX);
121 auto yResult = JSViewAbstract::ParseJsDimensionVp(yVal, dimenY);
122 if (!(xResult || yResult)) {
123 LOGE("the position prop is illegal");
124 } else {
125 (*iterLayoutChildren_)->GetGeometryNode()->SetFrameOffset({ dimenX.ConvertToPx(), dimenY.ConvertToPx() });
126 }
127 (*iterLayoutChildren_)->Layout();
128 iterLayoutChildren_++;
129
130 return panda::JSValueRef::Undefined(vm);
131 }
132
JSPlaceChildren(panda::JsiRuntimeCallInfo * runtimeCallInfo)133 panda::Local<panda::JSValueRef> ViewMeasureLayout::JSPlaceChildren(panda::JsiRuntimeCallInfo* runtimeCallInfo)
134 {
135 ACE_SCOPED_TRACE("ViewMeasureLayout::JSPlaceChildren");
136 EcmaVM* vm = runtimeCallInfo->GetVM();
137
138 if (iterLayoutChildren_ == layoutChildren_.end()) {
139 LOGE("Call layout exceed limit");
140 return panda::JSValueRef::Undefined(vm);
141 }
142
143 auto info = runtimeCallInfo;
144 if (info->GetArgsNumber() != 1 || !info->GetCallArgRef(0)->IsObject()) {
145 LOGE("JSPlaceChildren arg is wrong");
146 (*iterLayoutChildren_)->Layout();
147 iterLayoutChildren_++;
148 return panda::JSValueRef::Undefined(vm);
149 }
150
151 auto jsObject = JsiObject(info->GetCallArgRef(0)->ToObject(vm));
152 JSRef<JSObject> layoutInfo = JSRef<JSObject>::Make(jsObject);
153 JSRef<JSVal> xVal = layoutInfo->GetProperty("x");
154 JSRef<JSVal> yVal = layoutInfo->GetProperty("y");
155 CalcDimension dimenX;
156 CalcDimension dimenY;
157 auto xResult = JSViewAbstract::ParseJsDimensionVp(xVal, dimenX);
158 auto yResult = JSViewAbstract::ParseJsDimensionVp(yVal, dimenY);
159 if (!(xResult || yResult)) {
160 LOGE("the position prop is illegal");
161 } else {
162 (*iterLayoutChildren_)->GetGeometryNode()->SetFrameOffset({ dimenX.ConvertToPx(), dimenY.ConvertToPx() });
163 }
164 (*iterLayoutChildren_)->Layout();
165 iterLayoutChildren_++;
166 return panda::JSValueRef::Undefined(vm);
167 }
168
169 #endif
170
171 } // namespace OHOS::Ace::Framework
172