From 0a20f470210b5dd671fb2d307ad90df8745908c5 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Fri, 22 Jun 2018 07:28:31 -0700 Subject: [PATCH] Fabric: Proxying `pointScaleFactor` to Yoga Config Summary: @public This diff changes how we store and manage Yoga Config in layoutable shadow nodes. Previously we have `shared_ptr` to single shared yoga config (one to many relationships); now we initiate and store yoga config with yoga node (one to one relationship). Cons: - Less memory efficient. Pros: - Much more flexible model. Configuration can be tweaked on a per-node basis. - More performant. Dealing with `shared_ptr` is expensive because of atomic ref-counter. (This is not really applicable for the previous approach but would be applicable for any alternate approach where we want to have more granular control of the configuration.) Data locality is also great in the new model which should positively impact performance. - Simplicity. Any alternate approach where we manage sets of nodes which share the same configuration is going to be quite complex. Reviewed By: fkgozali Differential Revision: D8475638 fbshipit-source-id: 5d73116718ced8e4b2d31d857bb9aac69eb69f2b --- .../view/yoga/YogaLayoutableShadowNode.cpp | 40 ++++++++++++------- .../view/yoga/YogaLayoutableShadowNode.h | 7 +++- 2 files changed, 31 insertions(+), 16 deletions(-) diff --git a/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.cpp b/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.cpp index 6840a86c4..5941baa05 100644 --- a/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.cpp +++ b/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.cpp @@ -19,26 +19,18 @@ namespace facebook { namespace react { -SharedYogaConfig YogaLayoutableShadowNode::suitableYogaConfig() { - static SharedYogaConfig sharedYogaConfig; - - if (!sharedYogaConfig) { - sharedYogaConfig = std::shared_ptr(YGConfigNew()); - sharedYogaConfig->cloneNodeCallback = YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector; - } - - return sharedYogaConfig; -} - YogaLayoutableShadowNode::YogaLayoutableShadowNode( const SharedYogaStylableProps &props, const SharedShadowNodeSharedList &children ): - yogaNode_({}) { + yogaNode_({}), + yogaConfig_(nullptr) { + assert(props); assert(children); - yogaNode_.setConfig(suitableYogaConfig().get()); + initializeYogaConfig(yogaConfig_); + yogaNode_.setConfig(&yogaConfig_); yogaNode_.setStyle(props->yogaStyle); yogaNode_.setContext(this); yogaNode_.setDirty(true); @@ -51,8 +43,11 @@ YogaLayoutableShadowNode::YogaLayoutableShadowNode( const SharedYogaStylableProps &props, const SharedShadowNodeSharedList &children ): - yogaNode_(shadowNode->yogaNode_) { - yogaNode_.setConfig(suitableYogaConfig().get()); + yogaNode_(shadowNode->yogaNode_), + yogaConfig_(nullptr) { + + initializeYogaConfig(yogaConfig_); + yogaNode_.setConfig(&yogaConfig_); yogaNode_.setContext(this); yogaNode_.setOwner(nullptr); yogaNode_.setDirty(true); @@ -110,6 +105,17 @@ void YogaLayoutableShadowNode::appendChild(SharedYogaLayoutableShadowNode child) void YogaLayoutableShadowNode::layout(LayoutContext layoutContext) { if (!getIsLayoutClean()) { ensureUnsealed(); + + /* + * In Yoga, every single Yoga Node has to have a (non-null) pointer to + * Yoga Config (this config can be shared between many nodes), + * so every node can be individually configured. This does *not* mean + * however that Yoga consults with every single Yoga Node Config for every + * config parameter. Especially in case of `pointScaleFactor`, + * the only value in the config of the root node is taken into account + * (and this is by design). + */ + yogaConfig_.pointScaleFactor = layoutContext.pointScaleFactor; YGNodeCalculateLayout(&yogaNode_, YGUndefined, YGUndefined, YGDirectionInherit); } @@ -244,5 +250,9 @@ void YogaLayoutableShadowNode::setYogaNodeChildrenBasedOnShadowNodeChildren(YGNo yogaNodeRawPtr->setChildren(yogaNodeChildren); } +void YogaLayoutableShadowNode::initializeYogaConfig(YGConfig &config) { + config.cloneNodeCallback = YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector; +} + } // namespace react } // namespace facebook diff --git a/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.h b/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.h index e0fc3b5e0..2da836d8a 100644 --- a/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.h +++ b/ReactCommon/fabric/view/yoga/YogaLayoutableShadowNode.h @@ -87,8 +87,13 @@ protected: */ mutable YGNode yogaNode_; + /* + * Yoga config associated (only) with this particular node. + */ + YGConfig yogaConfig_; + private: - static SharedYogaConfig suitableYogaConfig(); + static void initializeYogaConfig(YGConfig &config); static void setYogaNodeChildrenBasedOnShadowNodeChildren(YGNode *yogaNodeRawPtr, const SharedShadowNodeSharedList &children); static YGNode *yogaNodeCloneCallbackConnector(YGNode *oldYogaNode, YGNode *parentYogaNode, int childIndex); static YGSize yogaNodeMeasureCallbackConnector(YGNode *yogaNode, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode);