From c2b0f34533874c450007645827208259bbfbbbd1 Mon Sep 17 00:00:00 2001 From: Valentin Shergin Date: Wed, 10 Jan 2018 09:45:08 -0800 Subject: [PATCH] Introducing on-dirty handler (aka `YGNodeSetDirtiedFunc`) Summary: Currently, we can dirty leaf nodes with `measure` function, we also can get `dirty` status for any node, but we cannot handle a moment when this change happen. This diff introduces a new call-back-manner handler for it. We need this to plug Yoga inside and outside other layout systems without maintaining own dirty propagation infrastructure. Consider using Yoga for flex-box layout in React Native where we can have deeply nested layout like `` where all content of all nodes are laid out using native text/inline (not flex-box!) layout system. In this case, when some change dirties some deeply nested Yoga node, we have to propagate the dirty state down to outer one. Having this handler makes possible to wire up `on-dirty` handler on the root node and `setDirtied` for the leaf node. Removing custom dirting mechanism from React Native should drastically simplify rendering layer and bring a huge performance win. Reviewed By: emilsjolander Differential Revision: D6597856 fbshipit-source-id: 6588cd712f9c1dede4af32f3d326f90103e48ff0 --- ReactCommon/yoga/yoga/YGNode.cpp | 21 ++++++++++++++++++++- ReactCommon/yoga/yoga/YGNode.h | 4 ++++ ReactCommon/yoga/yoga/Yoga.h | 1 + 3 files changed, 25 insertions(+), 1 deletion(-) diff --git a/ReactCommon/yoga/yoga/YGNode.cpp b/ReactCommon/yoga/yoga/YGNode.cpp index d09394dbd..9ee729b56 100644 --- a/ReactCommon/yoga/yoga/YGNode.cpp +++ b/ReactCommon/yoga/yoga/YGNode.cpp @@ -35,6 +35,10 @@ YGBaselineFunc YGNode::getBaseline() const { return baseline_; } +YGDirtiedFunc YGNode::getDirtied() const { + return dirtied_; +} + YGStyle& YGNode::getStyle() { return style_; } @@ -128,6 +132,10 @@ void YGNode::setBaseLineFunc(YGBaselineFunc baseLineFunc) { baseline_ = baseLineFunc; } +void YGNode::setDirtiedFunc(YGDirtiedFunc dirtiedFunc) { + dirtied_ = dirtiedFunc; +} + void YGNode::setStyle(YGStyle style) { style_ = style; } @@ -169,7 +177,13 @@ void YGNode::setConfig(YGConfigRef config) { } void YGNode::setDirty(bool isDirty) { + if (isDirty == isDirty_) { + return; + } isDirty_ = isDirty; + if (isDirty && dirtied_) { + dirtied_(this); + } } bool YGNode::removeChild(YGNodeRef child) { @@ -238,6 +252,7 @@ YGNode::YGNode() nodeType_(YGNodeTypeDefault), measure_(nullptr), baseline_(nullptr), + dirtied_(nullptr), style_(gYGNodeStyleDefaults), layout_(gYGNodeLayoutDefaults), lineIndex_(0), @@ -255,6 +270,7 @@ YGNode::YGNode(const YGNode& node) nodeType_(node.nodeType_), measure_(node.measure_), baseline_(node.baseline_), + dirtied_(node.dirtied_), style_(node.style_), layout_(node.layout_), lineIndex_(node.lineIndex_), @@ -276,6 +292,7 @@ YGNode::YGNode( YGNodeType nodeType, YGMeasureFunc measure, YGBaselineFunc baseline, + YGDirtiedFunc dirtied, YGStyle style, YGLayout layout, uint32_t lineIndex, @@ -291,6 +308,7 @@ YGNode::YGNode( nodeType_(nodeType), measure_(measure), baseline_(baseline), + dirtied_(dirtied), style_(style), layout_(layout), lineIndex_(lineIndex), @@ -316,6 +334,7 @@ YGNode& YGNode::operator=(const YGNode& node) { nodeType_ = node.getNodeType(); measure_ = node.getMeasure(); baseline_ = node.getBaseline(); + dirtied_ = node.getDirtied(); style_ = node.style_; layout_ = node.layout_; lineIndex_ = node.getLineIndex(); @@ -415,7 +434,7 @@ void YGNode::cloneChildrenIfNeeded() { void YGNode::markDirtyAndPropogate() { if (!isDirty_) { - isDirty_ = true; + setDirty(true); setLayoutComputedFlexBasis(YGUndefined); if (parent_) { parent_->markDirtyAndPropogate(); diff --git a/ReactCommon/yoga/yoga/YGNode.h b/ReactCommon/yoga/yoga/YGNode.h index 46e0c2f7f..79947e713 100644 --- a/ReactCommon/yoga/yoga/YGNode.h +++ b/ReactCommon/yoga/yoga/YGNode.h @@ -20,6 +20,7 @@ struct YGNode { YGNodeType nodeType_; YGMeasureFunc measure_; YGBaselineFunc baseline_; + YGDirtiedFunc dirtied_; YGStyle style_; YGLayout layout_; uint32_t lineIndex_; @@ -43,6 +44,7 @@ struct YGNode { YGNodeType nodeType, YGMeasureFunc measure, YGBaselineFunc baseline, + YGDirtiedFunc dirtied, YGStyle style, YGLayout layout, uint32_t lineIndex, @@ -60,6 +62,7 @@ struct YGNode { YGNodeType getNodeType() const; YGMeasureFunc getMeasure() const; YGBaselineFunc getBaseline() const; + YGDirtiedFunc getDirtied() const; // For Perfomance reasons passing as reference. YGStyle& getStyle(); // For Perfomance reasons passing as reference. @@ -82,6 +85,7 @@ struct YGNode { void setNodeType(YGNodeType nodeTye); void setMeasureFunc(YGMeasureFunc measureFunc); void setBaseLineFunc(YGBaselineFunc baseLineFunc); + void setDirtiedFunc(YGDirtiedFunc dirtiedFunc); void setStyle(YGStyle style); void setStyleFlexDirection(YGFlexDirection direction); void setStyleAlignContent(YGAlign alignContent); diff --git a/ReactCommon/yoga/yoga/Yoga.h b/ReactCommon/yoga/yoga/Yoga.h index 90f1f5fc0..28326019f 100644 --- a/ReactCommon/yoga/yoga/Yoga.h +++ b/ReactCommon/yoga/yoga/Yoga.h @@ -56,6 +56,7 @@ typedef YGSize (*YGMeasureFunc)(YGNodeRef node, float height, YGMeasureMode heightMode); typedef float (*YGBaselineFunc)(YGNodeRef node, const float width, const float height); +typedef void (*YGDirtiedFunc)(YGNodeRef node); typedef void (*YGPrintFunc)(YGNodeRef node); typedef int (*YGLogger)(const YGConfigRef config, const YGNodeRef node,