Optimize edge value resolution
Summary: Noticed in simpleperf this was a very hot method, showing 8ms spent in these methods in our sample application. By splitting the method out in a horizontal and vertical variant we can simplify cases enormously and check for begin/end in one go. Changelog: [Internal] Reviewed By: SidharthGuglani Differential Revision: D27010008 fbshipit-source-id: 22fed58c7476e1d716b0191b55997c7a06e63223
This commit is contained in:
committed by
Facebook GitHub Bot
parent
342aebe1d7
commit
41384fab7b
215
yoga/YGNode.cpp
215
yoga/YGNode.cpp
@@ -50,89 +50,111 @@ void YGNode::print(void* printContext) {
|
||||
}
|
||||
}
|
||||
|
||||
CompactValue YGNode::computeEdgeValueForRow(
|
||||
const YGStyle::Edges& edges,
|
||||
YGEdge rowEdge,
|
||||
YGEdge edge,
|
||||
CompactValue defaultValue) {
|
||||
if (!edges[rowEdge].isUndefined()) {
|
||||
return edges[rowEdge];
|
||||
} else if (!edges[edge].isUndefined()) {
|
||||
return edges[edge];
|
||||
} else if (!edges[YGEdgeHorizontal].isUndefined()) {
|
||||
return edges[YGEdgeHorizontal];
|
||||
} else if (!edges[YGEdgeAll].isUndefined()) {
|
||||
return edges[YGEdgeAll];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
CompactValue YGNode::computeEdgeValueForColumn(
|
||||
const YGStyle::Edges& edges,
|
||||
YGEdge edge,
|
||||
CompactValue defaultValue) {
|
||||
if (!edges[edge].isUndefined()) {
|
||||
return edges[edge];
|
||||
} else if (!edges[YGEdgeVertical].isUndefined()) {
|
||||
return edges[YGEdgeVertical];
|
||||
} else if (!edges[YGEdgeAll].isUndefined()) {
|
||||
return edges[YGEdgeAll];
|
||||
} else {
|
||||
return defaultValue;
|
||||
}
|
||||
}
|
||||
|
||||
YGFloatOptional YGNode::getLeadingPosition(
|
||||
const YGFlexDirection axis,
|
||||
const float axisSize) const {
|
||||
if (YGFlexDirectionIsRow(axis)) {
|
||||
auto leadingPosition = YGComputedEdgeValue(
|
||||
style_.position(), YGEdgeStart, CompactValue::ofUndefined());
|
||||
if (!leadingPosition.isUndefined()) {
|
||||
auto leadingPosition = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.position(),
|
||||
YGEdgeStart,
|
||||
leading[axis],
|
||||
CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.position(), leading[axis], CompactValue::ofZero());
|
||||
return YGResolveValue(leadingPosition, axisSize);
|
||||
}
|
||||
}
|
||||
|
||||
auto leadingPosition = YGComputedEdgeValue(
|
||||
style_.position(), leading[axis], CompactValue::ofUndefined());
|
||||
|
||||
return leadingPosition.isUndefined()
|
||||
? YGFloatOptional{0}
|
||||
: YGResolveValue(leadingPosition, axisSize);
|
||||
}
|
||||
|
||||
YGFloatOptional YGNode::getTrailingPosition(
|
||||
const YGFlexDirection axis,
|
||||
const float axisSize) const {
|
||||
if (YGFlexDirectionIsRow(axis)) {
|
||||
auto trailingPosition = YGComputedEdgeValue(
|
||||
style_.position(), YGEdgeEnd, CompactValue::ofUndefined());
|
||||
if (!trailingPosition.isUndefined()) {
|
||||
auto trailingPosition = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.position(),
|
||||
YGEdgeEnd,
|
||||
trailing[axis],
|
||||
CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.position(), trailing[axis], CompactValue::ofZero());
|
||||
return YGResolveValue(trailingPosition, axisSize);
|
||||
}
|
||||
}
|
||||
|
||||
auto trailingPosition = YGComputedEdgeValue(
|
||||
style_.position(), trailing[axis], CompactValue::ofUndefined());
|
||||
|
||||
return trailingPosition.isUndefined()
|
||||
? YGFloatOptional{0}
|
||||
: YGResolveValue(trailingPosition, axisSize);
|
||||
}
|
||||
|
||||
bool YGNode::isLeadingPositionDefined(const YGFlexDirection axis) const {
|
||||
return (YGFlexDirectionIsRow(axis) &&
|
||||
!YGComputedEdgeValue(
|
||||
style_.position(), YGEdgeStart, CompactValue::ofUndefined())
|
||||
.isUndefined()) ||
|
||||
!YGComputedEdgeValue(
|
||||
style_.position(), leading[axis], CompactValue::ofUndefined())
|
||||
.isUndefined();
|
||||
auto leadingPosition = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.position(),
|
||||
YGEdgeStart,
|
||||
leading[axis],
|
||||
CompactValue::ofUndefined())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.position(), leading[axis], CompactValue::ofUndefined());
|
||||
return !leadingPosition.isUndefined();
|
||||
}
|
||||
|
||||
bool YGNode::isTrailingPosDefined(const YGFlexDirection axis) const {
|
||||
return (YGFlexDirectionIsRow(axis) &&
|
||||
!YGComputedEdgeValue(
|
||||
style_.position(), YGEdgeEnd, CompactValue::ofUndefined())
|
||||
.isUndefined()) ||
|
||||
!YGComputedEdgeValue(
|
||||
style_.position(), trailing[axis], CompactValue::ofUndefined())
|
||||
.isUndefined();
|
||||
auto trailingPosition = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.position(),
|
||||
YGEdgeEnd,
|
||||
trailing[axis],
|
||||
CompactValue::ofUndefined())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.position(), trailing[axis], CompactValue::ofUndefined());
|
||||
return !trailingPosition.isUndefined();
|
||||
}
|
||||
|
||||
YGFloatOptional YGNode::getLeadingMargin(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
if (YGFlexDirectionIsRow(axis) &&
|
||||
!style_.margin()[YGEdgeStart].isUndefined()) {
|
||||
return YGResolveValueMargin(style_.margin()[YGEdgeStart], widthSize);
|
||||
}
|
||||
|
||||
return YGResolveValueMargin(
|
||||
YGComputedEdgeValue(
|
||||
style_.margin(), leading[axis], CompactValue::ofZero()),
|
||||
widthSize);
|
||||
auto leadingMargin = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.margin(), YGEdgeStart, leading[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.margin(), leading[axis], CompactValue::ofZero());
|
||||
return YGResolveValueMargin(leadingMargin, widthSize);
|
||||
}
|
||||
|
||||
YGFloatOptional YGNode::getTrailingMargin(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
if (YGFlexDirectionIsRow(axis) && !style_.margin()[YGEdgeEnd].isUndefined()) {
|
||||
return YGResolveValueMargin(style_.margin()[YGEdgeEnd], widthSize);
|
||||
}
|
||||
|
||||
return YGResolveValueMargin(
|
||||
YGComputedEdgeValue(
|
||||
style_.margin(), trailing[axis], CompactValue::ofZero()),
|
||||
widthSize);
|
||||
auto trailingMargin = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.margin(), YGEdgeEnd, trailing[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.margin(), trailing[axis], CompactValue::ofZero());
|
||||
return YGResolveValueMargin(trailingMargin, widthSize);
|
||||
}
|
||||
|
||||
YGFloatOptional YGNode::getMarginForAxis(
|
||||
@@ -147,7 +169,6 @@ YGSize YGNode::measure(
|
||||
float height,
|
||||
YGMeasureMode heightMode,
|
||||
void* layoutContext) {
|
||||
|
||||
return facebook::yoga::detail::getBooleanData(flags, measureUsesContext_)
|
||||
? measure_.withContext(
|
||||
this, width, widthMode, height, heightMode, layoutContext)
|
||||
@@ -448,68 +469,48 @@ bool YGNode::isNodeFlexible() {
|
||||
}
|
||||
|
||||
float YGNode::getLeadingBorder(const YGFlexDirection axis) const {
|
||||
YGValue leadingBorder;
|
||||
if (YGFlexDirectionIsRow(axis) &&
|
||||
!style_.border()[YGEdgeStart].isUndefined()) {
|
||||
leadingBorder = style_.border()[YGEdgeStart];
|
||||
if (leadingBorder.value >= 0) {
|
||||
return leadingBorder.value;
|
||||
}
|
||||
}
|
||||
|
||||
leadingBorder = YGComputedEdgeValue(
|
||||
YGValue leadingBorder = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.border(), YGEdgeStart, leading[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.border(), leading[axis], CompactValue::ofZero());
|
||||
return YGFloatMax(leadingBorder.value, 0.0f);
|
||||
return fmaxf(leadingBorder.value, 0.0f);
|
||||
}
|
||||
|
||||
float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const {
|
||||
YGValue trailingBorder;
|
||||
if (YGFlexDirectionIsRow(flexDirection) &&
|
||||
!style_.border()[YGEdgeEnd].isUndefined()) {
|
||||
trailingBorder = style_.border()[YGEdgeEnd];
|
||||
if (trailingBorder.value >= 0.0f) {
|
||||
return trailingBorder.value;
|
||||
}
|
||||
}
|
||||
|
||||
trailingBorder = YGComputedEdgeValue(
|
||||
style_.border(), trailing[flexDirection], CompactValue::ofZero());
|
||||
return YGFloatMax(trailingBorder.value, 0.0f);
|
||||
float YGNode::getTrailingBorder(const YGFlexDirection axis) const {
|
||||
YGValue trailingBorder = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.border(), YGEdgeEnd, trailing[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.border(), trailing[axis], CompactValue::ofZero());
|
||||
return fmaxf(trailingBorder.value, 0.0f);
|
||||
}
|
||||
|
||||
YGFloatOptional YGNode::getLeadingPadding(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
const YGFloatOptional paddingEdgeStart =
|
||||
YGResolveValue(style_.padding()[YGEdgeStart], widthSize);
|
||||
if (YGFlexDirectionIsRow(axis) &&
|
||||
!style_.padding()[YGEdgeStart].isUndefined() &&
|
||||
!paddingEdgeStart.isUndefined() && paddingEdgeStart.unwrap() >= 0.0f) {
|
||||
return paddingEdgeStart;
|
||||
}
|
||||
|
||||
YGFloatOptional resolvedValue = YGResolveValue(
|
||||
YGComputedEdgeValue(
|
||||
style_.padding(), leading[axis], CompactValue::ofZero()),
|
||||
widthSize);
|
||||
return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f));
|
||||
auto leadingPadding = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.padding(),
|
||||
YGEdgeStart,
|
||||
leading[axis],
|
||||
CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.padding(), leading[axis], CompactValue::ofZero());
|
||||
return YGFloatOptionalMax(
|
||||
YGResolveValue(leadingPadding, widthSize), YGFloatOptional(0.0f));
|
||||
}
|
||||
|
||||
YGFloatOptional YGNode::getTrailingPadding(
|
||||
const YGFlexDirection axis,
|
||||
const float widthSize) const {
|
||||
const YGFloatOptional paddingEdgeEnd =
|
||||
YGResolveValue(style_.padding()[YGEdgeEnd], widthSize);
|
||||
if (YGFlexDirectionIsRow(axis) && paddingEdgeEnd >= YGFloatOptional{0.0f}) {
|
||||
return paddingEdgeEnd;
|
||||
}
|
||||
|
||||
YGFloatOptional resolvedValue = YGResolveValue(
|
||||
YGComputedEdgeValue(
|
||||
style_.padding(), trailing[axis], CompactValue::ofZero()),
|
||||
widthSize);
|
||||
|
||||
return YGFloatOptionalMax(resolvedValue, YGFloatOptional(0.0f));
|
||||
auto trailingPadding = YGFlexDirectionIsRow(axis)
|
||||
? computeEdgeValueForRow(
|
||||
style_.padding(), YGEdgeEnd, trailing[axis], CompactValue::ofZero())
|
||||
: computeEdgeValueForColumn(
|
||||
style_.padding(), trailing[axis], CompactValue::ofZero());
|
||||
return YGFloatOptionalMax(
|
||||
YGResolveValue(trailingPadding, widthSize), YGFloatOptional(0.0f));
|
||||
}
|
||||
|
||||
YGFloatOptional YGNode::getLeadingPaddingAndBorder(
|
||||
|
@@ -193,6 +193,17 @@ public:
|
||||
return resolvedDimensions_[index];
|
||||
}
|
||||
|
||||
static CompactValue computeEdgeValueForColumn(
|
||||
const YGStyle::Edges& edges,
|
||||
YGEdge edge,
|
||||
CompactValue defaultValue);
|
||||
|
||||
static CompactValue computeEdgeValueForRow(
|
||||
const YGStyle::Edges& edges,
|
||||
YGEdge rowEdge,
|
||||
YGEdge edge,
|
||||
CompactValue defaultValue);
|
||||
|
||||
// Methods related to positions, margin, padding and border
|
||||
YGFloatOptional getLeadingPosition(
|
||||
const YGFlexDirection axis,
|
||||
|
@@ -104,10 +104,13 @@ static void appendEdgeIfNotUndefined(
|
||||
const string& str,
|
||||
const YGStyle::Edges& edges,
|
||||
const YGEdge edge) {
|
||||
appendNumberIfNotUndefined(
|
||||
base,
|
||||
str,
|
||||
YGComputedEdgeValue(edges, edge, detail::CompactValue::ofUndefined()));
|
||||
// TODO: this doesn't take RTL / YGEdgeStart / YGEdgeEnd into account
|
||||
auto value = (edge == YGEdgeLeft || edge == YGEdgeRight)
|
||||
? YGNode::computeEdgeValueForRow(
|
||||
edges, edge, edge, detail::CompactValue::ofUndefined())
|
||||
: YGNode::computeEdgeValueForColumn(
|
||||
edges, edge, detail::CompactValue::ofUndefined());
|
||||
appendNumberIfNotUndefined(base, str, value);
|
||||
}
|
||||
|
||||
void YGNodeToString(
|
||||
|
@@ -144,8 +144,3 @@ static const float kDefaultFlexShrink = 0.0f;
|
||||
static const float kWebDefaultFlexShrink = 1.0f;
|
||||
|
||||
extern bool YGFloatsEqual(const float a, const float b);
|
||||
extern facebook::yoga::detail::CompactValue YGComputedEdgeValue(
|
||||
const facebook::yoga::detail::Values<
|
||||
facebook::yoga::enums::count<YGEdge>()>& edges,
|
||||
YGEdge edge,
|
||||
facebook::yoga::detail::CompactValue defaultValue);
|
||||
|
@@ -110,36 +110,6 @@ YOGA_EXPORT bool YGFloatIsUndefined(const float value) {
|
||||
return facebook::yoga::isUndefined(value);
|
||||
}
|
||||
|
||||
detail::CompactValue YGComputedEdgeValue(
|
||||
const YGStyle::Edges& edges,
|
||||
YGEdge edge,
|
||||
detail::CompactValue defaultValue) {
|
||||
if (!edges[edge].isUndefined()) {
|
||||
return edges[edge];
|
||||
}
|
||||
|
||||
if ((edge == YGEdgeTop || edge == YGEdgeBottom) &&
|
||||
!edges[YGEdgeVertical].isUndefined()) {
|
||||
return edges[YGEdgeVertical];
|
||||
}
|
||||
|
||||
if ((edge == YGEdgeLeft || edge == YGEdgeRight || edge == YGEdgeStart ||
|
||||
edge == YGEdgeEnd) &&
|
||||
!edges[YGEdgeHorizontal].isUndefined()) {
|
||||
return edges[YGEdgeHorizontal];
|
||||
}
|
||||
|
||||
if (!edges[YGEdgeAll].isUndefined()) {
|
||||
return edges[YGEdgeAll];
|
||||
}
|
||||
|
||||
if (edge == YGEdgeStart || edge == YGEdgeEnd) {
|
||||
return detail::CompactValue::ofUndefined();
|
||||
}
|
||||
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
YOGA_EXPORT void* YGNodeGetContext(YGNodeRef node) {
|
||||
return node->getContext();
|
||||
}
|
||||
|
Reference in New Issue
Block a user