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