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