From 42d5517c7a42526f903a0b41e6b95df2ff601df9 Mon Sep 17 00:00:00 2001 From: David Aurelio Date: Tue, 19 Feb 2019 09:54:45 -0800 Subject: [PATCH] Call measure and baseline fns within `YGNode` MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Summary: @public Stricter encapsulation of baseline and measure callbacks withing `YGNode`. Instead of invoking these callbacks directly (`node->getBaseline()(...)`), they are invoked via methods on `YGNode` (`node->baseline(...)`). This change will allow us to add the concept of a *Layout Context,* where measure and baseline functions will be able to receive an additional `void *` argument if configured accordingly. This API will be used internally for Yoga’s JNI bindings, to avoid storing a weak JNI reference for each node, and avoid reference table overflows. Changed API: - `YGNodeGetMeasureFunc()` -> `YGNodeHasMeasureFunc()` - `YGNodeGetBaselineFunc()` -> `YGNodeHasBaselineFunc()` - `YGNode::getMeasure()` -> `YGNode::hasMeasureFunc()` + `YGNode::measure()` - `YGNpde::getBaseline()` -> `YGNode::hasBaselineFunc()` + `YGNode::baseline()` Reviewed By: SidharthGuglani Differential Revision: D14099550 fbshipit-source-id: 2653ab36acc252a9747986bc88d21dac22d8c91b --- ReactCommon/yoga/yoga/YGNode.cpp | 4 ++-- ReactCommon/yoga/yoga/YGNode.h | 20 +++++++++++++++---- ReactCommon/yoga/yoga/YGNodePrint.cpp | 2 +- ReactCommon/yoga/yoga/Yoga.cpp | 26 ++++++++++++------------- ReactCommon/yoga/yoga/Yoga.h | 4 ++-- ReactCommon/yoga/yoga/instrumentation.h | 7 +++++-- 6 files changed, 38 insertions(+), 25 deletions(-) diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index 0b7fc3c7e29..9b06cb9c7a0 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -270,8 +270,8 @@ YGNode& YGNode::operator=(const YGNode& node) { print_ = node.getPrintFunc(); hasNewLayout_ = node.getHasNewLayout(); nodeType_ = node.getNodeType(); - measure_ = node.getMeasure(); - baseline_ = node.getBaseline(); + measure_ = node.measure_; + baseline_ = node.baseline_; dirtied_ = node.getDirtied(); style_ = node.style_; layout_ = node.layout_; diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index ffb01832319..776af0f97ed 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -63,12 +63,24 @@ public: return nodeType_; } - YGMeasureFunc getMeasure() const { - return measure_; + bool hasMeasureFunc() const noexcept { + return measure_ != nullptr; } - YGBaselineFunc getBaseline() const { - return baseline_; + YGSize measure( + float width, + YGMeasureMode widthMode, + float height, + YGMeasureMode heightMode) { + return measure_(this, width, widthMode, height, heightMode); + } + + bool hasBaselineFunc() const noexcept { + return baseline_ != nullptr; + } + + float baseline(float width, float height) { + return baseline_(this, width, height); } YGDirtiedFunc getDirtied() const { diff --git a/ReactCommon/yoga/yoga/YGNodePrint.cpp b/ReactCommon/yoga/yoga/YGNodePrint.cpp index 28b1c47ee7f..5e51a405527 100644 --- a/ReactCommon/yoga/yoga/YGNodePrint.cpp +++ b/ReactCommon/yoga/yoga/YGNodePrint.cpp @@ -214,7 +214,7 @@ void YGNodeToString( str, "bottom", node->getStyle().position, YGEdgeBottom); appendFormatedString(str, "\" "); - if (node->getMeasure() != nullptr) { + if (node->hasMeasureFunc()) { appendFormatedString(str, "has-custom-measure=\"true\""); } } diff --git a/ReactCommon/yoga/yoga/Yoga.cpp b/ReactCommon/yoga/yoga/Yoga.cpp index f15864db8c3..2559b80b004 100644 --- a/ReactCommon/yoga/yoga/Yoga.cpp +++ b/ReactCommon/yoga/yoga/Yoga.cpp @@ -145,16 +145,16 @@ void YGNodeSetContext(YGNodeRef node, void* context) { return node->setContext(context); } -YGMeasureFunc YGNodeGetMeasureFunc(YGNodeRef node) { - return node->getMeasure(); +bool YGNodeHasMeasureFunc(YGNodeRef node) { + return node->hasMeasureFunc(); } void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc) { node->setMeasureFunc(measureFunc); } -YGBaselineFunc YGNodeGetBaselineFunc(YGNodeRef node) { - return node->getBaseline(); +bool YGNodeHasBaselineFunc(YGNodeRef node) { + return node->hasBaselineFunc(); } void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc) { @@ -395,7 +395,7 @@ void YGNodeInsertChild( YGAssertWithNode( node, - node->getMeasure() == nullptr, + !node->hasMeasureFunc(), "Cannot add child: Nodes with measure functions cannot have children."); node->cloneChildrenIfNeeded(); @@ -555,7 +555,7 @@ YGNodeRef YGNodeGetParent(const YGNodeRef node) { void YGNodeMarkDirty(const YGNodeRef node) { YGAssertWithNode( node, - node->getMeasure() != nullptr, + node->hasMeasureFunc(), "Only leaf nodes with custom measure functions" "should manually mark themselves as dirty"); @@ -1075,11 +1075,10 @@ static inline YGAlign YGNodeAlignItem( } static float YGBaseline(const YGNodeRef node) { - if (node->getBaseline() != nullptr) { + if (node->hasBaselineFunc()) { const float baseline = marker::MarkerSection::wrap( node, - node->getBaseline(), - node, + &YGNode::baseline, node->getLayout().measuredDimensions[YGDimensionWidth], node->getLayout().measuredDimensions[YGDimensionHeight]); YGAssertWithNode( @@ -1650,7 +1649,7 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions( const float ownerHeight) { YGAssertWithNode( node, - node->getMeasure() != nullptr, + node->hasMeasureFunc(), "Expected node to have custom measure function"); const float paddingAndBorderAxisRow = @@ -1694,8 +1693,7 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions( // Measure the text under the current constraints. const YGSize measuredSize = marker::MarkerSection::wrap( node, - node->getMeasure(), - node, + &YGNode::measure, innerWidth, widthMeasureMode, innerHeight, @@ -2737,7 +2735,7 @@ static void YGNodelayoutImpl( node->getTrailingPadding(flexColumnDirection, ownerWidth).unwrap(), YGEdgeBottom); - if (node->getMeasure() != nullptr) { + if (node->hasMeasureFunc()) { YGNodeWithMeasureFuncSetMeasuredDimensions( node, availableWidth, @@ -3741,7 +3739,7 @@ bool YGLayoutNodeInternal( // dimensions. We handle nodes with measure functions specially here because // they are the most expensive to measure, so it's worth avoiding redundant // measurements if at all possible. - if (node->getMeasure() != nullptr) { + if (node->hasMeasureFunc()) { const float marginAxisRow = node->getMarginForAxis(YGFlexDirectionRow, ownerWidth).unwrap(); const float marginAxisColumn = diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index e3ca1fea6c2..86aa152ae1a 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -132,9 +132,9 @@ WIN_EXPORT void YGNodeCopyStyle( WIN_EXPORT void* YGNodeGetContext(YGNodeRef node); WIN_EXPORT void YGNodeSetContext(YGNodeRef node, void* context); void YGConfigSetPrintTreeFlag(YGConfigRef config, bool enabled); -YGMeasureFunc YGNodeGetMeasureFunc(YGNodeRef node); +bool YGNodeHasMeasureFunc(YGNodeRef node); WIN_EXPORT void YGNodeSetMeasureFunc(YGNodeRef node, YGMeasureFunc measureFunc); -YGBaselineFunc YGNodeGetBaselineFunc(YGNodeRef node); +bool YGNodeHasBaselineFunc(YGNodeRef node); void YGNodeSetBaselineFunc(YGNodeRef node, YGBaselineFunc baselineFunc); YGDirtiedFunc YGNodeGetDirtiedFunc(YGNodeRef node); void YGNodeSetDirtiedFunc(YGNodeRef node, YGDirtiedFunc dirtiedFunc); diff --git a/ReactCommon/yoga/yoga/instrumentation.h b/ReactCommon/yoga/yoga/instrumentation.h index 5cc544c5fdd..b8691c1865b 100644 --- a/ReactCommon/yoga/yoga/instrumentation.h +++ b/ReactCommon/yoga/yoga/instrumentation.h @@ -28,9 +28,12 @@ public: typename Data::type data = {}; template - static Ret wrap(YGNodeRef node, Ret (*fn)(Args...), Args... args) { + static Ret wrap( + YGNodeRef node, + Ret (YGNode::*method)(Args...), + Args... args) { MarkerSection section{node}; - return fn(std::forward(args)...); + return (node->*method)(std::forward(args)...); } private: