void YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector(YGNode *oldYogaNode, YGNode *newYogaNode, YGNode *parentYogaNode, int childIndex) { // We have only raw pointer to the parent shadow node, but that's enough for now. YogaLayoutableShadowNode *parentShadowNodeRawPtr = (YogaLayoutableShadowNode *)parentYogaNode->getContext(); assert(parentShadowNodeRawPtr); // Old child shadow node already exists but we have only raw pointer to it... YogaLayoutableShadowNode *oldShadowNodeRawPtr = (YogaLayoutableShadowNode *)oldYogaNode->getContext(); assert(oldShadowNodeRawPtr); // ... but we have to address this by `shared_ptr`. We cannot create a new `shared_ptr` for it because we will end up with two shared pointers to // single object which will cause preluminary destroyng the object. // Another approaches to consider: // * Create a new `shared_ptr` with empty deleter. // * Using `childIndex` to find exact node. SharedLayoutableShadowNode oldShadowNode = nullptr; for (auto child : parentShadowNodeRawPtr->getChildren()) { if (child.get() == oldShadowNodeRawPtr) { oldShadowNode = child; break; } } assert(oldShadowNode); // The new one does not exist yet. So, we have to clone and replace this using `cloneAndReplaceChild`. SharedYogaLayoutableShadowNode newShadowNode = std::dynamic_pointer_cast<const YogaLayoutableShadowNode>(parentShadowNodeRawPtr->cloneAndReplaceChild(oldShadowNode)); assert(newShadowNode); // And finally, we have to replace underline yoga node with the new one provided by Yoga. newYogaNode->setContext((void *)newShadowNode.get()); newShadowNode->yogaNode_ = std::shared_ptr<YGNode>(newYogaNode); }
YGNode *YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector(YGNode *oldYogaNode, YGNode *parentYogaNode, int childIndex) { // We have only raw pointer to the parent shadow node, but that's enough for now. YogaLayoutableShadowNode *parentShadowNodeRawPtr = (YogaLayoutableShadowNode *)parentYogaNode->getContext(); assert(parentShadowNodeRawPtr); // Old child shadow node already exists but we have only raw pointer to it... YogaLayoutableShadowNode *oldShadowNodeRawPtr = (YogaLayoutableShadowNode *)oldYogaNode->getContext(); assert(oldShadowNodeRawPtr); // ... but we have to address this by `shared_ptr`. We cannot create a new `shared_ptr` for it because we will end up with two shared pointers to // single object which will cause preluminary destroyng the object. auto &&layoutableChildNodes = parentShadowNodeRawPtr->getLayoutableChildNodes(); SharedLayoutableShadowNode oldShadowNode = nullptr; // We cannot rely on `childIndex` all the time because `childNodes` can // contain non-layoutable shadow nodes, however chances are good that // `childIndex` points to the right shadow node. // Optimistic attempt (in case if `childIndex` is valid): if (childIndex < layoutableChildNodes.size()) { oldShadowNode = layoutableChildNodes[childIndex]; if (oldShadowNode.get() == oldShadowNodeRawPtr) { goto found; } else { oldShadowNode = nullptr; } } // General solution: for (auto child : layoutableChildNodes) { if (child.get() == oldShadowNodeRawPtr) { oldShadowNode = child; break; } } assert(oldShadowNode); found: // The new one does not exist yet. So, we have to clone and replace this using `cloneAndReplaceChild`. SharedYogaLayoutableShadowNode newShadowNode = std::dynamic_pointer_cast<const YogaLayoutableShadowNode>(parentShadowNodeRawPtr->cloneAndReplaceChild(oldShadowNode)); assert(newShadowNode); return &newShadowNode->yogaNode_; }
YGSize YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector(YGNode *yogaNode, float width, YGMeasureMode widthMode, float height, YGMeasureMode heightMode) { YogaLayoutableShadowNode *shadowNodeRawPtr = (YogaLayoutableShadowNode *)yogaNode->getContext(); assert(shadowNodeRawPtr); Size minimumSize = Size {0, 0}; Size maximumSize = Size {kFloatMax, kFloatMax}; switch (widthMode) { case YGMeasureModeUndefined: break; case YGMeasureModeExactly: minimumSize.width = fabricFloatFromYogaFloat(width); maximumSize.width = fabricFloatFromYogaFloat(width); break; case YGMeasureModeAtMost: maximumSize.width = fabricFloatFromYogaFloat(width); break; } switch (heightMode) { case YGMeasureModeUndefined: break; case YGMeasureModeExactly: minimumSize.height = fabricFloatFromYogaFloat(height); maximumSize.height = fabricFloatFromYogaFloat(height); break; case YGMeasureModeAtMost: maximumSize.height = fabricFloatFromYogaFloat(height); break; } Size size = shadowNodeRawPtr->measure(LayoutConstraints {minimumSize, maximumSize}); return YGSize { yogaFloatFromFabricFloat(size.width), yogaFloatFromFabricFloat(size.height) }; }