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 #include "frameworks/core/components_ng/pattern/custom/custom_measure_layout_node.h"
24
25 namespace OHOS::Ace::Framework {
26
27 #ifdef USE_ARK_ENGINE
28
29 namespace {
30 using OHOS::Ace::NG::LayoutConstraintF;
31 using OHOS::Ace::NG::LayoutProperty;
32 using OHOS::Ace::NG::SizeF;
GenConstraint(const std::optional<NG::LayoutConstraintF> & parentConstraint)33 JSRef<JSObject> GenConstraint(const std::optional<NG::LayoutConstraintF>& parentConstraint)
34 {
35 auto minSize = parentConstraint->minSize;
36 auto maxSize = parentConstraint->maxSize;
37 JSRef<JSObject> constraint = JSRef<JSObject>::New();
38 constraint->SetProperty<double>("minWidth", minSize.Width());
39 constraint->SetProperty<double>("minHeight", minSize.Height());
40 constraint->SetProperty<double>("maxWidth", maxSize.Width());
41 constraint->SetProperty<double>("maxHeight", maxSize.Height());
42 return constraint;
43 }
44
GenConstraintNG(const NG::LayoutConstraintF & parentConstraint)45 JSRef<JSObject> GenConstraintNG(const NG::LayoutConstraintF& parentConstraint)
46 {
47 auto minSize = parentConstraint.minSize;
48 auto maxSize = parentConstraint.maxSize;
49 JSRef<JSObject> constraint = JSRef<JSObject>::New();
50 constraint->SetProperty<double>("minWidth", 0.0f);
51 constraint->SetProperty<double>("minHeight", 0.0f);
52 constraint->SetProperty<double>("maxWidth", 0.0f);
53 constraint->SetProperty<double>("maxHeight", 0.0f);
54 auto pipeline = PipelineBase::GetCurrentContext();
55 if (!pipeline) {
56 return constraint;
57 }
58 constraint->SetProperty<double>("minWidth", minSize.Width() / pipeline->GetDipScale());
59 constraint->SetProperty<double>("minHeight", minSize.Height() / pipeline->GetDipScale());
60 constraint->SetProperty<double>("maxWidth", maxSize.Width() / pipeline->GetDipScale());
61 constraint->SetProperty<double>("maxHeight", maxSize.Height() / pipeline->GetDipScale());
62 return constraint;
63 }
64
GenPlaceChildrenConstraintNG(const NG::SizeF & size,RefPtr<NG::LayoutProperty> layoutProperty)65 JSRef<JSObject> GenPlaceChildrenConstraintNG(const NG::SizeF& size, RefPtr<NG::LayoutProperty> layoutProperty)
66 {
67 JSRef<JSObject> constraint = JSRef<JSObject>::New();
68 auto pipeline = PipelineBase::GetCurrentContext();
69 if (!layoutProperty || !pipeline) {
70 constraint->SetProperty<double>("minWidth", 0.0f);
71 constraint->SetProperty<double>("minHeight", 0.0f);
72 constraint->SetProperty<double>("maxWidth", 0.0f);
73 constraint->SetProperty<double>("maxHeight", 0.0f);
74 return constraint;
75 }
76 auto minSize = layoutProperty->GetLayoutConstraint().value().minSize;
77 constraint->SetProperty<double>("minWidth", minSize.Width() / pipeline->GetDipScale());
78 constraint->SetProperty<double>("minHeight", minSize.Height() / pipeline->GetDipScale());
79 auto parentNode = AceType::DynamicCast<NG::FrameNode>(layoutProperty->GetHost()->GetParent());
80 if (parentNode && parentNode->GetTag() == V2::COMMON_VIEW_ETS_TAG) {
81 layoutProperty = parentNode->GetLayoutProperty();
82 }
83 const std::unique_ptr<NG::PaddingProperty>& padding = layoutProperty->GetPaddingProperty();
84 const std::unique_ptr<NG::BorderWidthProperty>& borderWidth = layoutProperty->GetBorderWidthProperty();
85 auto topPadding = padding ? padding->top->GetDimension().ConvertToVp() : 0.0f;
86 auto bottomPadding = padding ? padding->bottom->GetDimension().ConvertToVp() : 0.0f;
87 auto leftPadding = padding ? padding->left->GetDimension().ConvertToVp() : 0.0f;
88 auto rightPadding = padding ? padding->right->GetDimension().ConvertToVp() : 0.0f;
89 auto topBorder = borderWidth ? borderWidth->topDimen->ConvertToVp() : 0.0f;
90 auto bottomBorder = borderWidth ? borderWidth->bottomDimen->ConvertToVp() : 0.0f;
91 auto leftBorder = borderWidth ? borderWidth->leftDimen->ConvertToVp() : 0.0f;
92 auto rightBorder = borderWidth ? borderWidth->rightDimen->ConvertToVp() : 0.0f;
93 constraint->SetProperty<double>("maxWidth", size.Width() / pipeline->GetDipScale() - leftPadding - rightPadding -
94 leftBorder - rightBorder);
95 constraint->SetProperty<double>("maxHeight", size.Height() / pipeline->GetDipScale() - topPadding - bottomPadding -
96 topBorder - bottomBorder);
97 return constraint;
98 }
99
GenPadding(const std::unique_ptr<NG::PaddingProperty> & paddingNative)100 JSRef<JSObject> GenPadding(const std::unique_ptr<NG::PaddingProperty>& paddingNative)
101 {
102 JSRef<JSObject> padding = JSRef<JSObject>::New();
103 padding->SetProperty("top", paddingNative->top->GetDimension().ConvertToVp());
104 padding->SetProperty("right", paddingNative->right->GetDimension().ConvertToVp());
105 padding->SetProperty("bottom", paddingNative->bottom->GetDimension().ConvertToVp());
106 padding->SetProperty("left", paddingNative->left->GetDimension().ConvertToVp());
107 return padding;
108 }
109
GenMargin(const std::unique_ptr<NG::MarginProperty> & marginNative)110 JSRef<JSObject> GenMargin(const std::unique_ptr<NG::MarginProperty>& marginNative)
111 {
112 JSRef<JSObject> margin = JSRef<JSObject>::New();
113 margin->SetProperty("top", marginNative->top->GetDimension().ConvertToVp());
114 margin->SetProperty("right", marginNative->right->GetDimension().ConvertToVp());
115 margin->SetProperty("bottom", marginNative->bottom->GetDimension().ConvertToVp());
116 margin->SetProperty("left", marginNative->left->GetDimension().ConvertToVp());
117 return margin;
118 }
119
GenEdgeWidths(const std::unique_ptr<NG::BorderWidthProperty> & edgeWidthsNative)120 JSRef<JSObject> GenEdgeWidths(const std::unique_ptr<NG::BorderWidthProperty>& edgeWidthsNative)
121 {
122 JSRef<JSObject> edgeWidths = JSRef<JSObject>::New();
123 edgeWidths->SetProperty("top", edgeWidthsNative->topDimen->ConvertToVp());
124 edgeWidths->SetProperty("right", edgeWidthsNative->rightDimen->ConvertToVp());
125 edgeWidths->SetProperty("bottom", edgeWidthsNative->bottomDimen->ConvertToVp());
126 edgeWidths->SetProperty("left", edgeWidthsNative->leftDimen->ConvertToVp());
127 return edgeWidths;
128 }
129
GenEdgesGlobalized(const NG::PaddingPropertyT<float> & edgeNative,TextDirection direction)130 JSRef<JSObject> GenEdgesGlobalized(const NG::PaddingPropertyT<float>& edgeNative, TextDirection direction)
131 {
132 JSRef<JSObject> edges = JSRef<JSObject>::New();
133 auto pipeline = PipelineBase::GetCurrentContext();
134 double px2vpScale = pipeline ? 1.0 / pipeline->GetDipScale() : 1.0;
135 edges->SetProperty("top", edgeNative.top.value_or(0) * px2vpScale);
136 edges->SetProperty("bottom", edgeNative.bottom.value_or(0) * px2vpScale);
137 if (direction != TextDirection::RTL) {
138 edges->SetProperty("start", edgeNative.left.value_or(0) * px2vpScale);
139 edges->SetProperty("end", edgeNative.right.value_or(0) * px2vpScale);
140 } else {
141 edges->SetProperty("start", edgeNative.right.value_or(0) * px2vpScale);
142 edges->SetProperty("end", edgeNative.left.value_or(0) * px2vpScale);
143 }
144 return edges;
145 }
146
GenBorderWidthGlobalized(const NG::BorderWidthPropertyT<float> & edgeNative,TextDirection direction)147 JSRef<JSObject> GenBorderWidthGlobalized(const NG::BorderWidthPropertyT<float>& edgeNative, TextDirection direction)
148 {
149 JSRef<JSObject> edges = JSRef<JSObject>::New();
150 auto pipeline = PipelineBase::GetCurrentContext();
151 double px2vpScale = pipeline ? 1.0 / pipeline->GetDipScale() : 1.0;
152 edges->SetProperty("top", edgeNative.topDimen.value_or(0) * px2vpScale);
153 edges->SetProperty("bottom", edgeNative.bottomDimen.value_or(0) * px2vpScale);
154 if (direction != TextDirection::RTL) {
155 edges->SetProperty("start", edgeNative.leftDimen.value_or(0) * px2vpScale);
156 edges->SetProperty("end", edgeNative.rightDimen.value_or(0) * px2vpScale);
157 } else {
158 edges->SetProperty("start", edgeNative.rightDimen.value_or(0) * px2vpScale);
159 edges->SetProperty("end", edgeNative.leftDimen.value_or(0) * px2vpScale);
160 }
161 return edges;
162 }
163
GenBorderInfo(const RefPtr<NG::LayoutWrapper> & layoutWrapper)164 JSRef<JSObject> GenBorderInfo(const RefPtr<NG::LayoutWrapper>& layoutWrapper)
165 {
166 JSRef<JSObject> borderInfo = JSRef<JSObject>::New();
167 auto layoutProperty = layoutWrapper->GetLayoutProperty();
168 const std::unique_ptr<NG::PaddingProperty> defaultPadding = std::make_unique<NG::PaddingProperty>();
169 const std::unique_ptr<NG::PaddingProperty> defaultMargin = std::make_unique<NG::MarginProperty>();
170 const std::unique_ptr<NG::BorderWidthProperty>& defaultEdgeWidth = std::make_unique<NG::BorderWidthProperty>();
171 if (!layoutProperty) {
172 borderInfo->SetPropertyObject("borderWidth", GenEdgeWidths(defaultEdgeWidth));
173 borderInfo->SetPropertyObject("margin", GenMargin(defaultPadding));
174 borderInfo->SetPropertyObject("padding", GenPadding(defaultPadding));
175 return borderInfo;
176 }
177
178 borderInfo->SetPropertyObject("borderWidth",
179 GenEdgeWidths(
180 layoutProperty->GetBorderWidthProperty() ? layoutProperty->GetBorderWidthProperty() : defaultEdgeWidth));
181
182 borderInfo->SetPropertyObject("margin",
183 GenMargin(layoutProperty->GetMarginProperty() ? layoutProperty->GetMarginProperty() : defaultMargin));
184 borderInfo->SetPropertyObject("padding",
185 GenPadding(layoutProperty->GetPaddingProperty() ? layoutProperty->GetPaddingProperty() : defaultPadding));
186
187 return borderInfo;
188 }
189
GenPositionInfo(const RefPtr<NG::LayoutWrapper> & layoutWrapper)190 JSRef<JSObject> GenPositionInfo(const RefPtr<NG::LayoutWrapper>& layoutWrapper)
191 {
192 auto offset = layoutWrapper->GetGeometryNode()->GetFrameOffset();
193 JSRef<JSObject> position = JSRef<JSObject>::New();
194 position->SetProperty("x", offset.GetX());
195 position->SetProperty("y", offset.GetY());
196 return position;
197 }
198
GenSelfLayoutInfo(RefPtr<NG::LayoutProperty> layoutProperty)199 JSRef<JSObject> GenSelfLayoutInfo(RefPtr<NG::LayoutProperty> layoutProperty)
200 {
201 JSRef<JSObject> selfLayoutInfo = JSRef<JSObject>::New();
202 const std::unique_ptr<NG::PaddingProperty> defaultPadding = std::make_unique<NG::PaddingProperty>();
203 const std::unique_ptr<NG::PaddingProperty> defaultMargin = std::make_unique<NG::MarginProperty>();
204 const std::unique_ptr<NG::BorderWidthProperty>& defaultEdgeWidth = std::make_unique<NG::BorderWidthProperty>();
205 auto pipeline = PipelineBase::GetCurrentContext();
206 if (!layoutProperty || !pipeline) {
207 selfLayoutInfo->SetPropertyObject("borderWidth", GenEdgeWidths(defaultEdgeWidth));
208 selfLayoutInfo->SetPropertyObject("margin", GenMargin(defaultPadding));
209 selfLayoutInfo->SetPropertyObject("padding", GenPadding(defaultPadding));
210 selfLayoutInfo->SetProperty("width", 0.0f);
211 selfLayoutInfo->SetProperty("height", 0.0f);
212 return selfLayoutInfo;
213 }
214 auto parentNode = AceType::DynamicCast<NG::FrameNode>(layoutProperty->GetHost()->GetParent());
215 if (parentNode && parentNode->GetTag() == V2::COMMON_VIEW_ETS_TAG) {
216 layoutProperty = parentNode->GetLayoutProperty();
217 }
218 auto host = layoutProperty->GetHost();
219 NG::RectF originGeoRect;
220 if (host) {
221 originGeoRect = host->GetGeometryNode()->GetFrameRect();
222 }
223 auto width =
224 GreatNotEqual(originGeoRect.Width(), 0.0f) ? originGeoRect.Width() / pipeline->GetDipScale()
225 : layoutProperty->GetLayoutConstraint()
226 ? layoutProperty->GetLayoutConstraint()->selfIdealSize.Width().value_or(0.0) / pipeline->GetDipScale()
227 : 0.0f;
228 auto height =
229 GreatNotEqual(originGeoRect.Height(), 0.0f) ? originGeoRect.Height() / pipeline->GetDipScale()
230 : layoutProperty->GetLayoutConstraint()
231 ? layoutProperty->GetLayoutConstraint()->selfIdealSize.Height().value_or(0.0) / pipeline->GetDipScale()
232 : 0.0f;
233
234 selfLayoutInfo->SetPropertyObject("borderWidth",
235 GenEdgeWidths(
236 layoutProperty->GetBorderWidthProperty() ? layoutProperty->GetBorderWidthProperty() : defaultEdgeWidth));
237 selfLayoutInfo->SetPropertyObject("margin",
238 GenMargin(layoutProperty->GetMarginProperty() ? layoutProperty->GetMarginProperty() : defaultPadding));
239 selfLayoutInfo->SetPropertyObject("padding",
240 GenPadding(layoutProperty->GetPaddingProperty() ? layoutProperty->GetPaddingProperty() : defaultPadding));
241 selfLayoutInfo->SetProperty(
242 "width", NearEqual(width, 0.0f)
243 ? layoutProperty->GetLayoutConstraint()->percentReference.Width() / pipeline->GetDipScale()
244 : width);
245 selfLayoutInfo->SetProperty(
246 "height", NearEqual(height, 0.0f)
247 ? layoutProperty->GetLayoutConstraint()->percentReference.Height() / pipeline->GetDipScale()
248 : height);
249 return selfLayoutInfo;
250 }
251
FillSubComponentProperty(JSRef<JSObjTemplate> & info,const RefPtr<NG::LayoutWrapper> & layoutWrapper,const size_t & index)252 void FillSubComponentProperty(
253 JSRef<JSObjTemplate>& info, const RefPtr<NG::LayoutWrapper>& layoutWrapper, const size_t& index)
254 {
255 info->SetProperty<std::string>("name", layoutWrapper->GetHostNode()->GetTag());
256 info->SetProperty<std::string>("id", std::to_string(layoutWrapper->GetHostNode()->GetId()));
257 const auto& layoutProperty = layoutWrapper->GetLayoutProperty();
258 if (layoutProperty) {
259 info->SetPropertyObject("constraint", GenConstraint(layoutProperty->GetLayoutConstraint()));
260 }
261 info->SetPropertyObject("borderInfo", GenBorderInfo(layoutWrapper));
262 info->SetPropertyObject("position", GenPositionInfo(layoutWrapper));
263 }
264
FillPlaceSizeProperty(JSRef<JSObjTemplate> & info,const NG::SizeF & size)265 void FillPlaceSizeProperty(JSRef<JSObjTemplate>& info, const NG::SizeF& size)
266 {
267 JSRef<JSObject> measureResult = JSRef<JSObject>::New();
268 Dimension measureWidth(size.Width(), DimensionUnit::PX);
269 Dimension measureHeight(size.Height(), DimensionUnit::PX);
270 measureResult->SetProperty("width", measureWidth.ConvertToVp());
271 measureResult->SetProperty("height", measureHeight.ConvertToVp());
272 info->SetPropertyObject("measureResult", measureResult);
273 }
274 } // namespace
275
JSMeasureLayoutParam(NG::LayoutWrapper * layoutWrapper)276 JSMeasureLayoutParam::JSMeasureLayoutParam(NG::LayoutWrapper* layoutWrapper) : MeasureLayoutParam(layoutWrapper)
277 {
278 Init();
279 }
280
Init()281 void JSMeasureLayoutParam::Init()
282 {
283 int32_t count = GetTotalChildCount();
284 childArray_ = JSRef<JSArray>::New(count);
285 GenChildArray(0, count);
286 }
287
GenChildArray(int32_t start,int32_t end)288 void JSMeasureLayoutParam::GenChildArray(int32_t start, int32_t end)
289 {
290 JSRef<JSFunc> measureFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSMeasure);
291 JSRef<JSFunc> layoutFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSLayout);
292 for (int32_t index = start; index < end; index++) {
293 JSRef<JSObjTemplate> info = JSRef<JSObjTemplate>::New();
294 info->SetInternalFieldCount(1);
295 FillSubComponentProperty(info, GetOrCreateChildByIndex(index), index);
296 info->Wrap<NG::MeasureLayoutChild>(&Get(index));
297 info->SetPropertyObject("measure", measureFunc);
298 info->SetPropertyObject("layout", layoutFunc);
299 childArray_->SetValueAt(index, info);
300 }
301 }
302
GetConstraint()303 JSRef<JSObject> JSMeasureLayoutParam::GetConstraint()
304 {
305 auto layoutWrapper = GetLayoutWrapper();
306 if (layoutWrapper && layoutWrapper->GetGeometryNode() &&
307 layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint()) {
308 auto parentConstraint = layoutWrapper->GetGeometryNode()->GetParentLayoutConstraint();
309 return GenConstraint(parentConstraint);
310 }
311 return GenConstraint(LayoutConstraintF());
312 }
313
Update(NG::LayoutWrapper * layoutWrapper)314 void JSMeasureLayoutParam::Update(NG::LayoutWrapper* layoutWrapper)
315 {
316 NG::MeasureLayoutChild* addr = nullptr;
317 int32_t count = GetTotalChildCount();
318 if (count > 0) {
319 addr = &Get(0);
320 }
321 MeasureLayoutParam::Update(layoutWrapper);
322 int32_t newCount = GetTotalChildCount();
323 if (count == newCount) {
324 return;
325 }
326 childArray_->SetLength(newCount);
327 if (count < newCount) {
328 GenChildArray(count, newCount);
329 }
330 if (addr != &Get(0)) {
331 for (int32_t index = 0; index < count; index++) {
332 auto info = JSRef<JSObjTemplate>::Cast(childArray_->GetValueAt(index));
333 info->Wrap<NG::MeasureLayoutChild>(&Get(index));
334 }
335 }
336 }
337
GetInstance(NG::LayoutWrapper * layoutWrapper)338 RefPtr<JSMeasureLayoutParam> JSMeasureLayoutParam::GetInstance(NG::LayoutWrapper* layoutWrapper)
339 {
340 auto host = AceType::DynamicCast<NG::CustomMeasureLayoutNode>(layoutWrapper->GetHostNode());
341 CHECK_NULL_RETURN(host, nullptr);
342 auto jsParam = AceType::DynamicCast<JSMeasureLayoutParam>(host->GetMeasureLayoutParam());
343 if (!jsParam) {
344 jsParam = AceType::MakeRefPtr<JSMeasureLayoutParam>(layoutWrapper);
345 host->SetMeasureLayoutParam(jsParam);
346 } else {
347 jsParam->Update(layoutWrapper);
348 }
349 return jsParam;
350 }
351
JSMeasureLayoutParamNG(NG::LayoutWrapper * layoutWrapper)352 JSMeasureLayoutParamNG::JSMeasureLayoutParamNG(NG::LayoutWrapper* layoutWrapper) : MeasureLayoutParam(layoutWrapper)
353 {
354 Init();
355 }
356
Init()357 void JSMeasureLayoutParamNG::Init()
358 {
359 int32_t count = GetTotalChildCount();
360 childArray_ = JSRef<JSArray>::New(count);
361 GenChildArray(0, count);
362 }
363
GenChildArray(int32_t start,int32_t end)364 void JSMeasureLayoutParamNG::GenChildArray(int32_t start, int32_t end)
365 {
366 JSRef<JSObject> size = JSRef<JSObject>::New();
367 size->SetProperty("width", 0);
368 size->SetProperty("height", 0);
369 JSRef<JSFunc> measureFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSMeasure);
370 JSRef<JSFunc> layoutFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSPlaceChildren);
371 JSRef<JSFunc> getMarginFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSGetMargin);
372 JSRef<JSFunc> getPaddingFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSGetPadding);
373 JSRef<JSFunc> getBorderWidthFunc = JSRef<JSFunc>::New<FunctionCallback>(ViewMeasureLayout::JSGetBorderWidth);
374 for (int32_t index = start; index < end; index++) {
375 JSRef<JSObjTemplate> info = JSRef<JSObjTemplate>::New();
376 info->SetInternalFieldCount(1);
377 auto child = GetChildByIndex(index);
378 if (child && child->GetHostNode()) {
379 auto uniqueId = child->GetHostNode()->GetId();
380 info->SetProperty("uniqueId", uniqueId);
381 }
382 info->SetPropertyObject("measureResult", size);
383 info->Wrap<NG::MeasureLayoutChild>(&Get(index));
384 info->SetPropertyObject("measure", measureFunc);
385 info->SetPropertyObject("layout", layoutFunc);
386 info->SetPropertyObject("getMargin", getMarginFunc);
387 info->SetPropertyObject("getPadding", getPaddingFunc);
388 info->SetPropertyObject("getBorderWidth", getBorderWidthFunc);
389 childArray_->SetValueAt(index, info);
390 }
391 }
392
GetConstraint()393 JSRef<JSObject> JSMeasureLayoutParamNG::GetConstraint()
394 {
395 auto layoutWrapper = GetLayoutWrapper();
396 if (layoutWrapper && layoutWrapper->GetLayoutProperty() &&
397 layoutWrapper->GetLayoutProperty()->GetLayoutConstraint()) {
398 auto layoutConstraint = layoutWrapper->GetLayoutProperty()->GetLayoutConstraint().value();
399 return GenConstraintNG(layoutConstraint);
400 }
401 return GenConstraintNG(LayoutConstraintF());
402 }
403
GetPlaceChildrenConstraint()404 JSRef<JSObject> JSMeasureLayoutParamNG::GetPlaceChildrenConstraint()
405 {
406 auto layoutWrapper = GetLayoutWrapper();
407 if (layoutWrapper && layoutWrapper->GetLayoutProperty() && layoutWrapper->GetGeometryNode()) {
408 auto layoutFrameSize = layoutWrapper->GetGeometryNode()->GetFrameSize();
409 return GenPlaceChildrenConstraintNG(layoutFrameSize, layoutWrapper->GetLayoutProperty());
410 }
411 return GenPlaceChildrenConstraintNG(SizeF(), MakeRefPtr<LayoutProperty>());
412 }
413
GetSelfLayoutInfo()414 JSRef<JSObject> JSMeasureLayoutParamNG::GetSelfLayoutInfo()
415 {
416 auto layoutWrapper = GetLayoutWrapper();
417 return GenSelfLayoutInfo(layoutWrapper && layoutWrapper->GetLayoutProperty() ? layoutWrapper->GetLayoutProperty()
418 : MakeRefPtr<LayoutProperty>());
419 }
420
UpdateSize(int32_t index,const NG::SizeF & size)421 void JSMeasureLayoutParamNG::UpdateSize(int32_t index, const NG::SizeF& size)
422 {
423 auto info = JSRef<JSObjTemplate>::Cast(childArray_->GetValueAt(index));
424 auto layoutWrapper = GetChildByIndex(index);
425 FillPlaceSizeProperty(info, size);
426 }
427
Update(NG::LayoutWrapper * layoutWrapper)428 void JSMeasureLayoutParamNG::Update(NG::LayoutWrapper* layoutWrapper)
429 {
430 NG::MeasureLayoutChild* addr = nullptr;
431 int32_t count = GetTotalChildCount();
432 if (count > 0) {
433 addr = &Get(0);
434 }
435 MeasureLayoutParam::Update(layoutWrapper);
436 int32_t newCount = GetTotalChildCount();
437 if (count == newCount) {
438 return;
439 }
440 childArray_->SetLength(newCount);
441 if (count < newCount) {
442 GenChildArray(count, newCount);
443 }
444 if (addr != &Get(0)) {
445 for (int32_t index = 0; index < count; index++) {
446 auto info = JSRef<JSObjTemplate>::Cast(childArray_->GetValueAt(index));
447 info->Wrap<NG::MeasureLayoutChild>(&Get(index));
448 }
449 }
450 }
451
GetInstance(NG::LayoutWrapper * layoutWrapper)452 RefPtr<JSMeasureLayoutParamNG> JSMeasureLayoutParamNG::GetInstance(NG::LayoutWrapper* layoutWrapper)
453 {
454 auto host = AceType::DynamicCast<NG::CustomMeasureLayoutNode>(layoutWrapper->GetHostNode());
455 CHECK_NULL_RETURN(host, nullptr);
456 auto jsParam = AceType::DynamicCast<JSMeasureLayoutParamNG>(host->GetMeasureLayoutParam());
457 if (!jsParam) {
458 jsParam = AceType::MakeRefPtr<JSMeasureLayoutParamNG>(layoutWrapper);
459 host->SetMeasureLayoutParam(jsParam);
460 } else {
461 jsParam->Update(layoutWrapper);
462 }
463 return jsParam;
464 }
465
JSMeasure(panda::JsiRuntimeCallInfo * runtimeCallInfo)466 panda::Local<panda::JSValueRef> ViewMeasureLayout::JSMeasure(panda::JsiRuntimeCallInfo* runtimeCallInfo)
467 {
468 ACE_SCOPED_TRACE("ViewMeasureLayout::JSMeasure");
469 EcmaVM* vm = runtimeCallInfo->GetVM();
470 Local<JSValueRef> thisObj = runtimeCallInfo->GetThisRef();
471 auto ptr = static_cast<NG::MeasureLayoutChild*>(panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(
472 vm, 0));
473 CHECK_NULL_RETURN(ptr, panda::JSValueRef::Undefined(vm));
474 auto child = ptr->GetOrCreateChild();
475 if (!child) {
476 return panda::JSValueRef::Undefined(vm);
477 }
478
479 auto childLayoutConstraint = ptr->CreateChildConstraint();
480 auto layoutProperty = child->GetLayoutProperty();
481 auto info = runtimeCallInfo;
482 if (info->GetArgsNumber() >= 1 && info->GetCallArgRef(0)->IsObject(vm)) {
483 auto jsObject = JsiObject(info->GetCallArgRef(0)->ToObject(vm));
484 JSRef<JSObject> sizeObj = JSRef<JSObject>::Make(jsObject);
485 CalcDimension minWidth;
486 if (JSViewAbstract::ParseJsDimensionVp(sizeObj->GetProperty("minWidth"), minWidth)) {
487 if (layoutProperty) {
488 layoutProperty->UpdateCalcMinSize(NG::CalcSize(NG::CalcLength(minWidth), std::nullopt));
489 } else {
490 auto length = ConvertToPx(NG::CalcLength(minWidth), childLayoutConstraint.scaleProperty,
491 childLayoutConstraint.percentReference.Width());
492 if (length) {
493 childLayoutConstraint.minSize.SetWidth(length.value());
494 }
495 }
496 }
497
498 CalcDimension maxWidth;
499 if (JSViewAbstract::ParseJsDimensionVp(sizeObj->GetProperty("maxWidth"), maxWidth)) {
500 if (layoutProperty) {
501 layoutProperty->UpdateCalcMaxSize(NG::CalcSize(NG::CalcLength(maxWidth), std::nullopt));
502 } else {
503 auto length = ConvertToPx(NG::CalcLength(maxWidth), childLayoutConstraint.scaleProperty,
504 childLayoutConstraint.percentReference.Width());
505 if (length) {
506 childLayoutConstraint.maxSize.SetWidth(length.value());
507 }
508 }
509 }
510
511 CalcDimension minHeight;
512 if (JSViewAbstract::ParseJsDimensionVp(sizeObj->GetProperty("minHeight"), minHeight)) {
513 if (layoutProperty) {
514 layoutProperty->UpdateCalcMinSize(NG::CalcSize(std::nullopt, NG::CalcLength(minHeight)));
515 } else {
516 auto length = ConvertToPx(NG::CalcLength(minHeight), childLayoutConstraint.scaleProperty,
517 childLayoutConstraint.percentReference.Height());
518 if (length) {
519 childLayoutConstraint.minSize.SetHeight(length.value());
520 }
521 }
522 }
523
524 CalcDimension maxHeight;
525 if (JSViewAbstract::ParseJsDimensionVp(sizeObj->GetProperty("maxHeight"), maxHeight)) {
526 if (layoutProperty) {
527 layoutProperty->UpdateCalcMaxSize(NG::CalcSize(std::nullopt, NG::CalcLength(maxHeight)));
528 } else {
529 auto length = ConvertToPx(NG::CalcLength(maxHeight), childLayoutConstraint.scaleProperty,
530 childLayoutConstraint.percentReference.Height());
531 if (length) {
532 childLayoutConstraint.maxSize.SetHeight(length.value());
533 }
534 }
535 }
536 }
537 child->Measure(childLayoutConstraint);
538
539 auto size = child->GetGeometryNode()->GetFrameSize();
540 ptr->UpdateSize(size);
541 Dimension measureWidth(size.Width(), DimensionUnit::PX);
542 Dimension measureHeight(size.Height(), DimensionUnit::PX);
543 Local<ObjectRef> measureResultObject = ObjectRef::New(vm);
544 measureResultObject->Set(vm, ToJSValue("width"), ToJSValue(measureWidth.ConvertToVp()));
545 measureResultObject->Set(vm, ToJSValue("height"), ToJSValue(measureHeight.ConvertToVp()));
546 return measureResultObject;
547 }
548
JSLayout(panda::JsiRuntimeCallInfo * runtimeCallInfo)549 panda::Local<panda::JSValueRef> ViewMeasureLayout::JSLayout(panda::JsiRuntimeCallInfo* runtimeCallInfo)
550 {
551 ACE_SCOPED_TRACE("ViewMeasureLayout::JSLayout");
552 EcmaVM* vm = runtimeCallInfo->GetVM();
553 Local<JSValueRef> thisObj = runtimeCallInfo->GetThisRef();
554 auto ptr = static_cast<NG::MeasureLayoutChild*>(panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(
555 vm, 0));
556 CHECK_NULL_RETURN(ptr, panda::JSValueRef::Undefined(vm));
557 auto child = ptr->GetChild();
558 if (!child) {
559 return panda::JSValueRef::Undefined(vm);
560 }
561
562 auto info = runtimeCallInfo;
563 if (info->GetArgsNumber() != 1 || !info->GetCallArgRef(0)->IsObject(vm)) {
564 LOGE("JSLayout arg is wrong");
565 child->Layout();
566 return panda::JSValueRef::Undefined(vm);
567 }
568
569 auto jsObject = JsiObject(info->GetCallArgRef(0)->ToObject(vm));
570 JSRef<JSObject> layoutInfo = JSRef<JSObject>::Make(jsObject);
571 JSRef<JSObject> sizeObj = layoutInfo->GetProperty("position");
572 JSRef<JSVal> xVal = sizeObj->GetProperty("x");
573 JSRef<JSVal> yVal = sizeObj->GetProperty("y");
574 CalcDimension dimenX;
575 CalcDimension dimenY;
576 auto xResult = JSViewAbstract::ParseJsDimensionVp(xVal, dimenX);
577 auto yResult = JSViewAbstract::ParseJsDimensionVp(yVal, dimenY);
578 if (!(xResult || yResult)) {
579 LOGE("the position prop is illegal");
580 } else {
581 child->GetGeometryNode()->SetMarginFrameOffset({ static_cast<float>(dimenX.ConvertToPx()),
582 static_cast<float>(dimenY.ConvertToPx()) });
583 }
584 child->Layout();
585
586 return panda::JSValueRef::Undefined(vm);
587 }
588
JSPlaceChildren(panda::JsiRuntimeCallInfo * runtimeCallInfo)589 panda::Local<panda::JSValueRef> ViewMeasureLayout::JSPlaceChildren(panda::JsiRuntimeCallInfo* runtimeCallInfo)
590 {
591 ACE_SCOPED_TRACE("ViewMeasureLayout::JSPlaceChildren");
592 EcmaVM* vm = runtimeCallInfo->GetVM();
593 Local<JSValueRef> thisObj = runtimeCallInfo->GetThisRef();
594 auto ptr = static_cast<NG::MeasureLayoutChild*>(panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(
595 vm, 0));
596 CHECK_NULL_RETURN(ptr, panda::JSValueRef::Undefined(vm));
597 auto child = ptr->GetChild();
598 if (!child) {
599 return panda::JSValueRef::Undefined(vm);
600 }
601
602 auto info = runtimeCallInfo;
603 if (info->GetArgsNumber() != 1 || !info->GetCallArgRef(0)->IsObject(vm)) {
604 LOGE("JSPlaceChildren arg is wrong");
605 child->Layout();
606 return panda::JSValueRef::Undefined(vm);
607 }
608
609 auto jsObject = JsiObject(info->GetCallArgRef(0)->ToObject(vm));
610 JSRef<JSObject> layoutInfo = JSRef<JSObject>::Make(jsObject);
611 JSRef<JSVal> xVal = layoutInfo->GetProperty("x");
612 JSRef<JSVal> yVal = layoutInfo->GetProperty("y");
613 CalcDimension dimenX;
614 CalcDimension dimenY;
615 auto xResult = JSViewAbstract::ParseJsDimensionVp(xVal, dimenX);
616 auto yResult = JSViewAbstract::ParseJsDimensionVp(yVal, dimenY);
617 if (!(xResult || yResult)) {
618 LOGE("the position prop is illegal");
619 } else {
620 child->GetGeometryNode()->SetMarginFrameOffset({ static_cast<float>(dimenX.ConvertToPx()),
621 static_cast<float>(dimenY.ConvertToPx()) });
622 }
623 child->Layout();
624 return panda::JSValueRef::Undefined(vm);
625 }
626
JSGetMargin(panda::JsiRuntimeCallInfo * runtimeCallInfo)627 panda::Local<panda::JSValueRef> ViewMeasureLayout::JSGetMargin(panda::JsiRuntimeCallInfo* runtimeCallInfo)
628 {
629 EcmaVM* vm = runtimeCallInfo->GetVM();
630 Local<JSValueRef> thisObj = runtimeCallInfo->GetThisRef();
631 auto ptr = static_cast<NG::MeasureLayoutChild*>(panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(
632 vm, 0));
633 CHECK_NULL_RETURN(ptr, panda::JSValueRef::Undefined(vm));
634 auto child = ptr->GetOrCreateChild();
635 if (!(child && child->GetLayoutProperty())) {
636 return GenEdgesGlobalized({}, TextDirection::LTR).Get().GetLocalHandle();
637 }
638 auto layoutProperty = child->GetLayoutProperty();
639 auto direction = layoutProperty->GetNonAutoLayoutDirection();
640 return GenEdgesGlobalized(layoutProperty->CreateMarginWithoutCache(), direction).Get().GetLocalHandle();
641 }
642
JSGetPadding(panda::JsiRuntimeCallInfo * runtimeCallInfo)643 panda::Local<panda::JSValueRef> ViewMeasureLayout::JSGetPadding(panda::JsiRuntimeCallInfo* runtimeCallInfo)
644 {
645 EcmaVM* vm = runtimeCallInfo->GetVM();
646 Local<JSValueRef> thisObj = runtimeCallInfo->GetThisRef();
647 auto ptr = static_cast<NG::MeasureLayoutChild*>(panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(
648 vm, 0));
649 CHECK_NULL_RETURN(ptr, panda::JSValueRef::Undefined(vm));
650 auto child = ptr->GetOrCreateChild();
651 if (!(child && child->GetLayoutProperty())) {
652 return GenEdgesGlobalized({}, TextDirection::LTR).Get().GetLocalHandle();
653 }
654 auto layoutProperty = child->GetLayoutProperty();
655 auto direction = layoutProperty->GetNonAutoLayoutDirection();
656 return GenEdgesGlobalized(layoutProperty->CreatePaddingWithoutBorder(false, false), direction)
657 .Get()
658 .GetLocalHandle();
659 }
660
JSGetBorderWidth(panda::JsiRuntimeCallInfo * runtimeCallInfo)661 panda::Local<panda::JSValueRef> ViewMeasureLayout::JSGetBorderWidth(panda::JsiRuntimeCallInfo* runtimeCallInfo)
662 {
663 EcmaVM* vm = runtimeCallInfo->GetVM();
664 Local<JSValueRef> thisObj = runtimeCallInfo->GetThisRef();
665 auto ptr = static_cast<NG::MeasureLayoutChild*>(panda::Local<panda::ObjectRef>(thisObj)->GetNativePointerField(
666 vm, 0));
667 CHECK_NULL_RETURN(ptr, panda::JSValueRef::Undefined(vm));
668 auto child = ptr->GetOrCreateChild();
669 if (!(child && child->GetLayoutProperty())) {
670 return GenBorderWidthGlobalized({}, TextDirection::LTR).Get().GetLocalHandle();
671 }
672 auto layoutProperty = child->GetLayoutProperty();
673 auto direction = layoutProperty->GetNonAutoLayoutDirection();
674 return GenBorderWidthGlobalized(layoutProperty->CreateBorder(), direction).Get().GetLocalHandle();
675 }
676 #endif
677
678 } // namespace OHOS::Ace::Framework