mirror of
https://github.com/Tencent/Hippy.git
synced 2026-10-18 21:50:54 +08:00
206 lines
7.9 KiB
C++
Executable File
206 lines
7.9 KiB
C++
Executable File
/* Tencent is pleased to support the open source community by making Hippy
|
|
* available. Copyright (C) 2018 THL A29 Limited, a Tencent company. All rights
|
|
* reserved.
|
|
*
|
|
* Licensed under the Apache License, Version 2.0 (the "License");
|
|
* you may not use this file except in compliance with the License.
|
|
* You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "HPLayoutCache.h"
|
|
|
|
#include "HPUtil.h"
|
|
|
|
#ifdef __DEBUG__
|
|
#include <iostream>
|
|
#include <string>
|
|
#endif
|
|
|
|
HPLayoutCache::HPLayoutCache() {
|
|
initCache();
|
|
}
|
|
|
|
HPLayoutCache::~HPLayoutCache() {}
|
|
|
|
void HPLayoutCache::cacheResult(HPSize availableSize,
|
|
HPSize resultSize,
|
|
HPSizeMode measureMode,
|
|
FlexLayoutAction layoutAction) {
|
|
if (layoutAction == LayoutActionLayout) {
|
|
cachedLayout.availableSize = availableSize;
|
|
cachedLayout.widthMeasureMode = measureMode.widthMeasureMode;
|
|
cachedLayout.heightMeasureMode = measureMode.heightMeasureMode;
|
|
cachedLayout.resultSize = resultSize;
|
|
cachedLayout.layoutAction = layoutAction;
|
|
} else {
|
|
cachedMeasures[nextMeasureIndex].availableSize = availableSize;
|
|
cachedMeasures[nextMeasureIndex].widthMeasureMode = measureMode.widthMeasureMode;
|
|
cachedMeasures[nextMeasureIndex].heightMeasureMode = measureMode.heightMeasureMode;
|
|
cachedMeasures[nextMeasureIndex].resultSize = resultSize;
|
|
cachedMeasures[nextMeasureIndex].layoutAction = layoutAction;
|
|
nextMeasureIndex = (nextMeasureIndex + 1) % MAX_MEASURES_COUNT;
|
|
}
|
|
}
|
|
|
|
static inline bool SizeIsExactAndMatchesOldMeasuredSize(MeasureMode sizeMode,
|
|
float size,
|
|
float lastResultSize) {
|
|
return sizeMode == MeasureModeExactly && FloatIsEqual(size, lastResultSize);
|
|
}
|
|
|
|
static inline bool OldSizeIsUndefinedAndStillFits(MeasureMode sizeMode,
|
|
float size,
|
|
MeasureMode lastSizeMode,
|
|
float lastResultSize) {
|
|
return sizeMode == MeasureModeAtMost && lastSizeMode == MeasureModeUndefined &&
|
|
(size >= lastResultSize || FloatIsEqual(size, lastResultSize));
|
|
}
|
|
|
|
static inline bool NewMeasureSizeIsStricterAndStillValid(MeasureMode sizeMode,
|
|
float size,
|
|
MeasureMode lastSizeMode,
|
|
float lastSize,
|
|
float lastResultSize) {
|
|
return lastSizeMode == MeasureModeAtMost && sizeMode == MeasureModeAtMost && lastSize > size &&
|
|
(lastResultSize <= size || FloatIsEqual(size, lastResultSize));
|
|
}
|
|
|
|
MeasureResult* HPLayoutCache::useMeasureCacheIfPossible(HPSize availableSize,
|
|
HPSizeMode measureMode,
|
|
FlexLayoutAction layoutAction,
|
|
bool isMeasureNode) {
|
|
if (nextMeasureIndex <= 0) {
|
|
return nullptr;
|
|
}
|
|
|
|
for (uint32_t i = 0; i < nextMeasureIndex; i++) {
|
|
MeasureResult& cacheMeasure = cachedMeasures[i];
|
|
if (layoutAction != cacheMeasure.layoutAction && !isMeasureNode) {
|
|
continue;
|
|
}
|
|
|
|
bool widthCanUse = false;
|
|
widthCanUse = cacheMeasure.widthMeasureMode == measureMode.widthMeasureMode &&
|
|
FloatIsEqual(cacheMeasure.availableSize.width, availableSize.width);
|
|
|
|
if (isMeasureNode) {
|
|
if (!widthCanUse) {
|
|
widthCanUse = SizeIsExactAndMatchesOldMeasuredSize(
|
|
measureMode.widthMeasureMode, availableSize.width, cacheMeasure.resultSize.width);
|
|
}
|
|
|
|
if (!widthCanUse) {
|
|
widthCanUse = OldSizeIsUndefinedAndStillFits(
|
|
measureMode.widthMeasureMode, availableSize.width, cacheMeasure.widthMeasureMode,
|
|
cacheMeasure.resultSize.width);
|
|
}
|
|
|
|
if (!widthCanUse) {
|
|
widthCanUse = NewMeasureSizeIsStricterAndStillValid(
|
|
measureMode.widthMeasureMode, availableSize.width, cacheMeasure.widthMeasureMode,
|
|
cacheMeasure.availableSize.width, cacheMeasure.resultSize.width);
|
|
}
|
|
}
|
|
|
|
bool heightCanUse = false;
|
|
heightCanUse = cacheMeasure.heightMeasureMode == measureMode.heightMeasureMode &&
|
|
FloatIsEqual(cacheMeasure.availableSize.height, availableSize.height);
|
|
|
|
if (isMeasureNode) {
|
|
if (!heightCanUse) {
|
|
heightCanUse = SizeIsExactAndMatchesOldMeasuredSize(
|
|
measureMode.heightMeasureMode, availableSize.height, cacheMeasure.resultSize.height);
|
|
}
|
|
|
|
if (!heightCanUse) {
|
|
heightCanUse = OldSizeIsUndefinedAndStillFits(
|
|
measureMode.heightMeasureMode, availableSize.height, cacheMeasure.heightMeasureMode,
|
|
cacheMeasure.resultSize.height);
|
|
}
|
|
|
|
if (!heightCanUse) {
|
|
heightCanUse = NewMeasureSizeIsStricterAndStillValid(
|
|
measureMode.heightMeasureMode, availableSize.height, cacheMeasure.heightMeasureMode,
|
|
cacheMeasure.availableSize.height, cacheMeasure.resultSize.height);
|
|
}
|
|
}
|
|
|
|
if (widthCanUse && heightCanUse) {
|
|
#ifdef __DEBUG__
|
|
HPLogd("cache: action:%d\n", cacheMeasure.layoutAction);
|
|
#endif
|
|
return &cacheMeasure;
|
|
}
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
MeasureResult* HPLayoutCache::useLayoutCacheIfPossible(HPSize availableSize,
|
|
HPSizeMode measureMode) {
|
|
if (isUndefined(cachedLayout.availableSize.width) ||
|
|
isUndefined(cachedLayout.availableSize.height)) {
|
|
return nullptr;
|
|
}
|
|
|
|
if (HPSizeIsEqual(cachedLayout.availableSize, availableSize) &&
|
|
cachedLayout.widthMeasureMode == measureMode.widthMeasureMode &&
|
|
cachedLayout.heightMeasureMode == measureMode.heightMeasureMode) {
|
|
#ifdef __DEBUG__
|
|
HPLogd("cache: action:%d\n", LayoutActionLayout);
|
|
#endif
|
|
return &cachedLayout;
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
MeasureResult* HPLayoutCache::getCachedMeasureResult(HPSize availableSize,
|
|
HPSizeMode measureMode,
|
|
FlexLayoutAction layoutAction,
|
|
bool isMeasureNode) {
|
|
if (isMeasureNode) {
|
|
MeasureResult* result = useLayoutCacheIfPossible(availableSize, measureMode);
|
|
if (result != nullptr) {
|
|
return result;
|
|
}
|
|
return useMeasureCacheIfPossible(availableSize, measureMode, layoutAction, isMeasureNode);
|
|
} else if (layoutAction == LayoutActionLayout) {
|
|
return useLayoutCacheIfPossible(availableSize, measureMode);
|
|
} else {
|
|
return useMeasureCacheIfPossible(availableSize, measureMode, layoutAction, isMeasureNode);
|
|
}
|
|
|
|
return nullptr;
|
|
}
|
|
|
|
MeasureResult* HPLayoutCache::getCachedLayout() {
|
|
return &cachedLayout;
|
|
}
|
|
|
|
void HPLayoutCache::initCache() {
|
|
cachedLayout.availableSize = {VALUE_UNDEFINED, VALUE_UNDEFINED};
|
|
cachedLayout.resultSize = {VALUE_UNDEFINED, VALUE_UNDEFINED};
|
|
cachedLayout.widthMeasureMode = MeasureModeUndefined;
|
|
cachedLayout.heightMeasureMode = MeasureModeUndefined;
|
|
for (uint32_t i = 0; i < MAX_MEASURES_COUNT; i++) {
|
|
cachedMeasures[i].availableSize = {VALUE_UNDEFINED, VALUE_UNDEFINED};
|
|
cachedMeasures[i].resultSize = {VALUE_UNDEFINED, VALUE_UNDEFINED};
|
|
cachedMeasures[i].widthMeasureMode = MeasureModeUndefined;
|
|
cachedMeasures[i].heightMeasureMode = MeasureModeUndefined;
|
|
}
|
|
nextMeasureIndex = 0;
|
|
}
|
|
|
|
void HPLayoutCache::clearCache() {
|
|
initCache();
|
|
}
|