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
This commit is contained in:
Valentin Shergin 2018-06-22 07:28:31 -07:00 committed by Facebook Github Bot
parent a3f9ff4f93
commit 0a20f47021
2 changed files with 31 additions and 16 deletions

View File

@ -19,26 +19,18 @@
namespace facebook {
namespace react {
SharedYogaConfig YogaLayoutableShadowNode::suitableYogaConfig() {
static SharedYogaConfig sharedYogaConfig;
if (!sharedYogaConfig) {
sharedYogaConfig = std::shared_ptr<YGConfig>(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

View File

@ -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);