implement preload measure/layout

Signed-off-by: Tianer Zhou <zhoutianer@huawei.com>
Change-Id: I2f7c83c88f4b0c745d4cfd4117c5c956a2027787
This commit is contained in:
Tianer Zhou 2024-08-06 15:28:13 +08:00
parent df131ffff4
commit 484c04f4fc
8 changed files with 90 additions and 42 deletions

View File

@ -13,6 +13,7 @@
* limitations under the License.
*/
#include "core/components_ng/pattern/grid/grid_layout_info.h"
#include <numeric>
#include "base/utils/utils.h"
@ -701,6 +702,20 @@ MatIter GridLayoutInfo::FindInMatrix(int32_t index) const
return SearchInReverse(gridMatrix_, index, crossCount_);
}
std::pair<int32_t, int32_t> GridLayoutInfo::GetItemPos(int32_t itemIdx) const
{
auto it = FindInMatrix(itemIdx);
if (it == gridMatrix_.end()) {
return { -1, -1 };
}
for (auto col : it->second) {
if (col.second == itemIdx) {
return { col.first, it->first };
}
}
return { -1, -1 };
}
GridLayoutInfo::EndIndexInfo GridLayoutInfo::FindEndIdx(int32_t endLine) const
{
if (gridMatrix_.find(endLine) == gridMatrix_.end()) {
@ -714,9 +729,7 @@ GridLayoutInfo::EndIndexInfo GridLayoutInfo::FindEndIdx(int32_t endLine) const
}
}
}
return {
.itemIdx = 0, .y = 0, .x = 0
};
return { .itemIdx = 0, .y = 0, .x = 0 };
}
void GridLayoutInfo::ClearMapsToEnd(int32_t idx)

View File

@ -188,6 +188,12 @@ struct GridLayoutInfo {
*/
std::map<int32_t, std::map<int32_t, int32_t>>::const_iterator FindInMatrix(int32_t index) const;
/**
* @param itemIdx
* @return position [col, row] of the item. [-1, -1] if item is not in matrix.
*/
std::pair<int32_t, int32_t> GetItemPos(int32_t itemIdx) const;
/**
* @brief Tries to find the item between startMainLine and endMainLine.
*

View File

@ -127,7 +127,13 @@ public:
return false;
}
GridLayoutInfo GetGridLayoutInfo() const
const GridLayoutInfo& GetGridLayoutInfo() const
{
return gridLayoutInfo_;
}
/* caution when using mutable reference */
GridLayoutInfo& GetMutableLayoutInfo()
{
return gridLayoutInfo_;
}

View File

@ -198,21 +198,19 @@ bool GridIrregularFiller::UpdateLength(float& len, float targetLen, int32_t& row
return false;
}
void GridIrregularFiller::MeasureItem(const FillParameters& params, int32_t itemIdx, int32_t col, int32_t row)
LayoutConstraintF GridIrregularFiller::MeasureItem(const FillParameters& params, int32_t itemIdx, int32_t col, int32_t row)
{
auto child = wrapper_->GetOrCreateChildByIndex(itemIdx);
CHECK_NULL_VOID(child);
auto props = AceType::DynamicCast<GridLayoutProperty>(wrapper_->GetLayoutProperty());
auto constraint = props->CreateChildConstraint();
auto child = wrapper_->GetOrCreateChildByIndex(itemIdx);
CHECK_NULL_RETURN(child, constraint);
const auto itemSize = GridLayoutUtils::GetItemSize(info_, wrapper_, itemIdx);
// should cache child constraint result
float crossLen = 0.0f;
for (int32_t i = 0; i < itemSize.columns; ++i) {
crossLen += params.crossLens[i + col];
}
crossLen += params.crossGap * (itemSize.columns - 1);
constraint.percentReference.SetCrossSize(crossLen, info_->axis_);
if (info_->axis_ == Axis::VERTICAL) {
constraint.maxSize = SizeF { crossLen, Infinity<float>() };
@ -231,6 +229,7 @@ void GridIrregularFiller::MeasureItem(const FillParameters& params, int32_t item
for (int32_t i = 0; i < itemSize.rows; ++i) {
info_->lineHeightMap_[row + i] = std::max(info_->lineHeightMap_[row + i], heightPerRow);
}
return constraint;
}
int32_t GridIrregularFiller::InitPosToLastItem(int32_t lineIdx)

View File

@ -125,6 +125,16 @@ public:
*/
void MeasureLineWithIrregulars(const FillParameters& params, int32_t line);
/**
* @brief Measures a GridItem and updates the grid layout information.
*
* @param params The FillParameters object containing the fill parameters.
* @param itemIdx The index of the GridItem.
* @param col The column index where the item is being added.
* @param row The row index where the item is being added.
*/
LayoutConstraintF MeasureItem(const FillParameters& params, int32_t itemIdx, int32_t col, int32_t row);
private:
/**
* @brief Fills one GridItem into the Grid.
@ -144,16 +154,6 @@ private:
*/
bool UpdateLength(float& len, float targetLen, int32_t& row, int32_t rowBound, float mainGap) const;
/**
* @brief Measures a GridItem at endIndex_ and updates the grid layout information.
*
* @param params The FillParameters object containing the fill parameters.
* @param itemIdx The index of the GridItem.
* @param col The column index where the item is being added.
* @param row The row index where the item is being added.
*/
void MeasureItem(const FillParameters& params, int32_t itemIdx, int32_t col, int32_t row);
/**
* @brief Initializes the position of the filler in the grid to GridLayoutInfo::startIndex_.
*

View File

@ -55,7 +55,6 @@ void GridIrregularLayoutAlgorithm::Measure(LayoutWrapper* layoutWrapper)
}
UpdateLayoutInfo();
wrapper_->SetCacheCount(static_cast<int32_t>(props->GetCachedCountValue(1) * info_.crossCount_));
}
void GridIrregularLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
@ -72,25 +71,8 @@ void GridIrregularLayoutAlgorithm::Layout(LayoutWrapper* layoutWrapper)
CHECK_NULL_VOID(props);
const int32_t cacheCnt = props->GetCachedCountValue(1) * info.crossCount_;
wrapper_->SetActiveChildRange(std::min(info.startIndex_, info.endIndex_), info.endIndex_, cacheCnt, cacheCnt);
std::list<int32_t> itemsToPreload;
for (int32_t i = 1; i <= cacheCnt; ++i) {
const int32_t l = info.startIndex_ - i;
if (l >= 0 && !wrapper_->GetChildByIndex(l)) {
itemsToPreload.push_back(l);
}
const int32_t r = info.endIndex_ + i;
if (r < info.childrenCount_ && !wrapper_->GetChildByIndex(r)) {
itemsToPreload.push_back(r);
}
}
GridLayoutUtils::PreloadGridItems(wrapper_->GetHostNode()->GetPattern<GridPattern>(), std::move(itemsToPreload),
[](const RefPtr<FrameNode>& host, int32_t itemIdx) {
if (host) {
host->GetOrCreateChildByIndex(itemIdx);
};
return false;
});
wrapper_->SetCacheCount(cacheCnt);
PreloadItems(cacheCnt);
}
float GridIrregularLayoutAlgorithm::MeasureSelf(const RefPtr<GridLayoutProperty>& props)
@ -415,7 +397,7 @@ void GridIrregularLayoutAlgorithm::LayoutChildren(float mainOffset)
if (itemIdx == 0 && (it->first > 0 || c > 0)) {
continue;
}
auto child = wrapper_->GetOrCreateChildByIndex(itemIdx);
auto child = wrapper_->GetChildByIndex(itemIdx);
if (!child) {
continue;
}
@ -474,6 +456,7 @@ int32_t GridIrregularLayoutAlgorithm::FindJumpLineIdx(int32_t jumpIdx)
return jumpLine;
}
using FillParams = GridIrregularFiller::FillParameters;
void GridIrregularLayoutAlgorithm::PrepareLineHeight(float mainSize, int32_t& jumpLineIdx)
{
/* When mainSize can't be filled, adjust parameters and call function again. The maximum length of
@ -482,7 +465,7 @@ void GridIrregularLayoutAlgorithm::PrepareLineHeight(float mainSize, int32_t& ju
GridIrregularFiller filler(&info_, wrapper_);
switch (info_.scrollAlign_) {
case ScrollAlign::START: {
const GridIrregularFiller::FillParameters params { crossLens_, crossGap_, mainGap_ };
const FillParams params { crossLens_, crossGap_, mainGap_ };
// call this to ensure irregular items on the first line are measured, not skipped
filler.MeasureLineWithIrregulars(params, jumpLineIdx);
@ -570,7 +553,7 @@ int32_t GridIrregularLayoutAlgorithm::SkipLinesBackward() const
void GridIrregularLayoutAlgorithm::MeasureToTarget()
{
GridIrregularFiller filler(&info_, wrapper_);
GridIrregularFiller::FillParameters param { crossLens_, crossGap_, mainGap_ };
FillParams param { crossLens_, crossGap_, mainGap_ };
if (info_.targetIndex_ < info_.startIndex_) {
auto it = info_.FindInMatrix(*info_.targetIndex_);
filler.MeasureBackwardToTarget(param, it->first, info_.startMainLineIndex_);
@ -590,4 +573,41 @@ bool GridIrregularLayoutAlgorithm::IsIrregularLine(int32_t lineIndex) const
return std::any_of(line->second.begin(), line->second.end(),
[opts](const auto& item) { return opts.irregularIndexes.count(std::abs(item.second)); });
}
void GridIrregularLayoutAlgorithm::PreloadItems(int32_t cacheCnt)
{
std::list<int32_t> itemsToPreload;
for (int32_t i = 1; i <= cacheCnt; ++i) {
const int32_t l = info_.startIndex_ - i;
if (l >= 0 && !wrapper_->GetChildByIndex(l)) {
itemsToPreload.push_back(l);
}
const int32_t r = info_.endIndex_ + i;
if (r < info_.childrenCount_ && !wrapper_->GetChildByIndex(r)) {
itemsToPreload.push_back(r);
}
}
GridIrregularFiller filler(&info_, wrapper_);
filler.FillMatrixOnly(std::min(info_.childrenCount_, info_.endIndex_ + cacheCnt));
GridLayoutUtils::PreloadGridItems(wrapper_->GetHostNode()->GetPattern<GridPattern>(), std::move(itemsToPreload),
[crossLens = crossLens_, crossGap = crossGap_, mainGap = mainGap_](
const RefPtr<FrameNode>& host, int32_t itemIdx) {
CHECK_NULL_RETURN(host, false);
auto pattern = host->GetPattern<GridPattern>();
CHECK_NULL_RETURN(pattern, false);
auto& info = pattern->GetMutableLayoutInfo();
GridIrregularFiller filler(&info, RawPtr(host));
const auto pos = info.GetItemPos(itemIdx);
auto constraint = filler.MeasureItem(GridIrregularFiller::FillParameters { crossLens, crossGap, mainGap }, itemIdx,
pos.first, pos.second);
auto item = DynamicCast<FrameNode>(host->GetChildByIndex(itemIdx));
CHECK_NULL_RETURN(item, false);
item->GetGeometryNode()->SetParentLayoutConstraint(constraint);
FrameNode::ProcessOffscreenNode(item);
return false;
});
}
} // namespace OHOS::Ace::NG

View File

@ -144,6 +144,8 @@ private:
bool IsIrregularLine(int32_t lineIndex) const override;
void PreloadItems(int32_t cacheCnt);
GridLayoutInfo& info_;
LayoutWrapper* wrapper_ = nullptr;

View File

@ -563,6 +563,8 @@ HWTEST_F(GridLayoutRangeTest, Cache001, TestSize.Level1)
EXPECT_TRUE(pattern_->preloadItemList_.empty());
for (const int32_t i : preloadList) {
EXPECT_TRUE(frameNode_->GetChildByIndex(i));
EXPECT_EQ(GetChildWidth(frameNode_, i), (GRID_WIDTH - 20.0f) / 3.0f);
EXPECT_EQ(GetChildHeight(frameNode_, i), 200.0f);
}
pattern_->ScrollToIndex(49);
FlushLayoutTask(frameNode_);