mirror of
https://github.com/zhigang1992/react-native.git
synced 2026-04-28 20:25:33 +08:00
Summary: These default implementations are never being used. Removing them allowing to ensure that flags inside YGNode have same values as flags in YogaLayoutableShadowNode. That also saves a couple of bytes in size of ShadowNode. Reviewed By: JoshuaGross Differential Revision: D14496938 fbshipit-source-id: c43f9c8a2eec054f728ff54a6573668eccda55fb
268 lines
8.0 KiB
C++
268 lines
8.0 KiB
C++
/**
|
|
* Copyright (c) Facebook, Inc. and its affiliates.
|
|
*
|
|
* This source code is licensed under the MIT license found in the
|
|
* LICENSE file in the root directory of this source tree.
|
|
*/
|
|
|
|
#include "YogaLayoutableShadowNode.h"
|
|
|
|
#include <algorithm>
|
|
#include <memory>
|
|
|
|
#include <react/components/view/conversions.h>
|
|
#include <react/core/LayoutConstraints.h>
|
|
#include <react/core/LayoutContext.h>
|
|
#include <react/debug/DebugStringConvertibleItem.h>
|
|
#include <react/debug/SystraceSection.h>
|
|
#include <yoga/Yoga.h>
|
|
|
|
namespace facebook {
|
|
namespace react {
|
|
|
|
YogaLayoutableShadowNode::YogaLayoutableShadowNode()
|
|
: yogaNode_({}), yogaConfig_(nullptr) {
|
|
initializeYogaConfig(yogaConfig_);
|
|
|
|
yogaNode_.setConfig(&yogaConfig_);
|
|
yogaNode_.setContext(this);
|
|
}
|
|
|
|
YogaLayoutableShadowNode::YogaLayoutableShadowNode(
|
|
const YogaLayoutableShadowNode &layoutableShadowNode)
|
|
: LayoutableShadowNode(layoutableShadowNode),
|
|
yogaNode_(layoutableShadowNode.yogaNode_),
|
|
yogaConfig_(nullptr) {
|
|
initializeYogaConfig(yogaConfig_);
|
|
|
|
yogaNode_.setConfig(&yogaConfig_);
|
|
yogaNode_.setContext(this);
|
|
yogaNode_.setOwner(nullptr);
|
|
// Yoga node must inherit dirty flag.
|
|
assert(layoutableShadowNode.yogaNode_.isDirty() == yogaNode_.isDirty());
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::cleanLayout() {
|
|
yogaNode_.setDirty(false);
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::dirtyLayout() {
|
|
yogaNode_.setDirty(true);
|
|
}
|
|
|
|
bool YogaLayoutableShadowNode::getIsLayoutClean() const {
|
|
return !yogaNode_.isDirty();
|
|
}
|
|
|
|
bool YogaLayoutableShadowNode::getHasNewLayout() const {
|
|
return yogaNode_.getHasNewLayout();
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::setHasNewLayout(bool hasNewLayout) {
|
|
yogaNode_.setHasNewLayout(hasNewLayout);
|
|
}
|
|
|
|
#pragma mark - Mutating Methods
|
|
|
|
void YogaLayoutableShadowNode::enableMeasurement() {
|
|
ensureUnsealed();
|
|
|
|
yogaNode_.setMeasureFunc(
|
|
YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector);
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::appendChild(YogaLayoutableShadowNode *child) {
|
|
ensureUnsealed();
|
|
|
|
yogaNode_.setDirty(true);
|
|
|
|
auto yogaNodeRawPtr = &yogaNode_;
|
|
auto childYogaNodeRawPtr = &child->yogaNode_;
|
|
|
|
if (childYogaNodeRawPtr->getOwner() != nullptr) {
|
|
child = static_cast<YogaLayoutableShadowNode *>(
|
|
cloneAndReplaceChild(child, yogaNode_.getChildren().size()));
|
|
childYogaNodeRawPtr = &child->yogaNode_;
|
|
assert(childYogaNodeRawPtr->getOwner() == nullptr);
|
|
}
|
|
|
|
child->ensureUnsealed();
|
|
childYogaNodeRawPtr->setOwner(yogaNodeRawPtr);
|
|
|
|
yogaNodeRawPtr->insertChild(
|
|
childYogaNodeRawPtr, yogaNodeRawPtr->getChildren().size());
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::setChildren(
|
|
YogaLayoutableShadowNode::UnsharedList children) {
|
|
ensureUnsealed();
|
|
|
|
// Optimization:
|
|
// If the new list of child nodes consists of clean nodes, and if their styles
|
|
// are identical to styles of old children, we don't dirty the node.
|
|
bool isClean = !yogaNode_.getDirtied() &&
|
|
children.size() == yogaNode_.getChildren().size();
|
|
auto oldChildren = isClean ? yogaNode_.getChildren() : YGVector{};
|
|
|
|
yogaNode_.setChildren({});
|
|
|
|
auto i = int{0};
|
|
for (auto const &child : children) {
|
|
appendChild(child);
|
|
|
|
isClean = isClean && !child->yogaNode_.isDirty() &&
|
|
child->yogaNode_.getStyle() == oldChildren[i++]->getStyle();
|
|
}
|
|
|
|
yogaNode_.setDirty(!isClean);
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::setProps(const YogaStylableProps &props) {
|
|
ensureUnsealed();
|
|
|
|
// Resetting `dirty` flag only if `yogaStyle` portion of `Props` was changed.
|
|
if (!yogaNode_.isDirty() && (props.yogaStyle != yogaNode_.getStyle())) {
|
|
yogaNode_.setDirty(true);
|
|
}
|
|
|
|
yogaNode_.setStyle(props.yogaStyle);
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::setSize(Size size) const {
|
|
auto style = yogaNode_.getStyle();
|
|
style.dimensions[YGDimensionWidth] = yogaStyleValueFromFloat(size.width);
|
|
style.dimensions[YGDimensionHeight] = yogaStyleValueFromFloat(size.height);
|
|
yogaNode_.setStyle(style);
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::setPositionType(
|
|
YGPositionType positionType) const {
|
|
auto style = yogaNode_.getStyle();
|
|
style.positionType = positionType;
|
|
yogaNode_.setStyle(style);
|
|
}
|
|
|
|
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;
|
|
|
|
{
|
|
SystraceSection s("YogaLayoutableShadowNode::YGNodeCalculateLayout");
|
|
|
|
YGNodeCalculateLayout(
|
|
&yogaNode_, YGUndefined, YGUndefined, YGDirectionInherit);
|
|
}
|
|
}
|
|
|
|
LayoutableShadowNode::layout(layoutContext);
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::layoutChildren(LayoutContext layoutContext) {
|
|
for (const auto &childYogaNode : yogaNode_.getChildren()) {
|
|
auto childNode =
|
|
static_cast<YogaLayoutableShadowNode *>(childYogaNode->getContext());
|
|
|
|
LayoutMetrics childLayoutMetrics =
|
|
layoutMetricsFromYogaNode(childNode->yogaNode_);
|
|
childLayoutMetrics.pointScaleFactor = layoutContext.pointScaleFactor;
|
|
childNode->setLayoutMetrics(childLayoutMetrics);
|
|
}
|
|
}
|
|
|
|
LayoutableShadowNode::UnsharedList
|
|
YogaLayoutableShadowNode::getLayoutableChildNodes() const {
|
|
LayoutableShadowNode::UnsharedList yogaLayoutableChildNodes;
|
|
yogaLayoutableChildNodes.reserve(yogaNode_.getChildren().size());
|
|
|
|
for (const auto &childYogaNode : yogaNode_.getChildren()) {
|
|
auto childNode =
|
|
static_cast<YogaLayoutableShadowNode *>(childYogaNode->getContext());
|
|
yogaLayoutableChildNodes.push_back(childNode);
|
|
}
|
|
|
|
return yogaLayoutableChildNodes;
|
|
}
|
|
|
|
#pragma mark - Yoga Connectors
|
|
|
|
YGNode *YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector(
|
|
YGNode *oldYogaNode,
|
|
YGNode *parentYogaNode,
|
|
int childIndex) {
|
|
SystraceSection s("YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector");
|
|
|
|
// At this point it is garanteed that all shadow nodes associated with yoga
|
|
// nodes are `YogaLayoutableShadowNode` subclasses.
|
|
auto parentNode =
|
|
static_cast<YogaLayoutableShadowNode *>(parentYogaNode->getContext());
|
|
auto oldNode =
|
|
static_cast<YogaLayoutableShadowNode *>(oldYogaNode->getContext());
|
|
auto clonedNode = static_cast<YogaLayoutableShadowNode *>(
|
|
parentNode->cloneAndReplaceChild(oldNode, childIndex));
|
|
return &clonedNode->yogaNode_;
|
|
}
|
|
|
|
YGSize YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector(
|
|
YGNode *yogaNode,
|
|
float width,
|
|
YGMeasureMode widthMode,
|
|
float height,
|
|
YGMeasureMode heightMode) {
|
|
SystraceSection s(
|
|
"YogaLayoutableShadowNode::yogaNodeMeasureCallbackConnector");
|
|
|
|
auto shadowNodeRawPtr =
|
|
static_cast<YogaLayoutableShadowNode *>(yogaNode->getContext());
|
|
|
|
auto minimumSize = Size{0, 0};
|
|
auto maximumSize = Size{kFloatMax, kFloatMax};
|
|
|
|
switch (widthMode) {
|
|
case YGMeasureModeUndefined:
|
|
break;
|
|
case YGMeasureModeExactly:
|
|
minimumSize.width = floatFromYogaFloat(width);
|
|
maximumSize.width = floatFromYogaFloat(width);
|
|
break;
|
|
case YGMeasureModeAtMost:
|
|
maximumSize.width = floatFromYogaFloat(width);
|
|
break;
|
|
}
|
|
|
|
switch (heightMode) {
|
|
case YGMeasureModeUndefined:
|
|
break;
|
|
case YGMeasureModeExactly:
|
|
minimumSize.height = floatFromYogaFloat(height);
|
|
maximumSize.height = floatFromYogaFloat(height);
|
|
break;
|
|
case YGMeasureModeAtMost:
|
|
maximumSize.height = floatFromYogaFloat(height);
|
|
break;
|
|
}
|
|
|
|
auto size = shadowNodeRawPtr->measure({minimumSize, maximumSize});
|
|
|
|
return YGSize{yogaFloatFromFloat(size.width),
|
|
yogaFloatFromFloat(size.height)};
|
|
}
|
|
|
|
void YogaLayoutableShadowNode::initializeYogaConfig(YGConfig &config) {
|
|
config.setCloneNodeCallback(
|
|
YogaLayoutableShadowNode::yogaNodeCloneCallbackConnector);
|
|
}
|
|
|
|
} // namespace react
|
|
} // namespace facebook
|