diff --git a/benchmark/Benchmark.cpp b/benchmark/Benchmark.cpp index 7efa1954..c0ae3690 100644 --- a/benchmark/Benchmark.cpp +++ b/benchmark/Benchmark.cpp @@ -21,7 +21,7 @@ constexpr uint32_t kNumRepititions = 1000; using SteadyClockDurations = std::array; -std::shared_ptr buildConfigFromJson(json& j) { +std::shared_ptr buildConfigFromJson(const json& j) { json jsonConfig = j["config"]; std::shared_ptr config(YGConfigNew(), YGConfigFree); for (json::iterator it = jsonConfig.begin(); it != jsonConfig.end(); it++) { @@ -51,150 +51,165 @@ std::string edgeStringFromPropertyName( return key.substr(propertyName.length() + 1); } -void setStylesFromJson(json& j, std::shared_ptr node) { +void setStylesFromJson(const json& j, YGNodeRef node) { json style = j["style"]; for (const auto& [key, value] : style.items()) { if (key == "flex-direction") { - YGNodeStyleSetFlexDirection(node.get(), flexDirectionFromString(value)); + YGNodeStyleSetFlexDirection(node, flexDirectionFromString(value)); } else if (key == "justify-content") { - YGNodeStyleSetJustifyContent(node.get(), justifyContentFromString(value)); + YGNodeStyleSetJustifyContent(node, justifyContentFromString(value)); } else if (key == "align-items") { - YGNodeStyleSetAlignItems(node.get(), alignFromString(value)); + YGNodeStyleSetAlignItems(node, alignFromString(value)); } else if (key == "align-content") { - YGNodeStyleSetAlignContent(node.get(), alignFromString(value)); + YGNodeStyleSetAlignContent(node, alignFromString(value)); } else if (key == "align-self") { - YGNodeStyleSetAlignSelf(node.get(), alignFromString(value)); + YGNodeStyleSetAlignSelf(node, alignFromString(value)); } else if (key == "flex-wrap") { - YGNodeStyleSetFlexWrap(node.get(), wrapFromString(value)); + YGNodeStyleSetFlexWrap(node, wrapFromString(value)); } else if (key == "overflow") { - YGNodeStyleSetOverflow(node.get(), overflowFromString(value)); + YGNodeStyleSetOverflow(node, overflowFromString(value)); } else if (key == "display") { - YGNodeStyleSetDisplay(node.get(), displayFromString(value)); + YGNodeStyleSetDisplay(node, displayFromString(value)); } else if (key == "position-type") { - YGNodeStyleSetPositionType(node.get(), positionTypeFromString(value)); + YGNodeStyleSetPositionType(node, positionTypeFromString(value)); } else if (key == "flex-grow") { - YGNodeStyleSetFlexGrow(node.get(), value); + YGNodeStyleSetFlexGrow(node, value); } else if (key == "flex-shrink") { - YGNodeStyleSetFlexShrink(node.get(), value); + YGNodeStyleSetFlexShrink(node, value); } else if (key == "flex") { - YGNodeStyleSetFlex(node.get(), value); + YGNodeStyleSetFlex(node, value); } else if (key == "flex-basis") { YGUnit unit = unitFromJson(value); if (unit == YGUnitAuto) { - YGNodeStyleSetFlexBasisAuto(node.get()); + YGNodeStyleSetFlexBasisAuto(node); } else if (unit == YGUnitPoint) { - YGNodeStyleSetFlexBasis(node.get(), value["value"]); + YGNodeStyleSetFlexBasis(node, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetFlexBasisPercent(node.get(), value["value"]); + YGNodeStyleSetFlexBasisPercent(node, value["value"]); } } else if (key.starts_with("position")) { YGEdge edge = edgeFromString(edgeStringFromPropertyName(key, "position")); YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetPosition(node.get(), edge, value["value"]); + YGNodeStyleSetPosition(node, edge, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetPositionPercent(node.get(), edge, value["value"]); + YGNodeStyleSetPositionPercent(node, edge, value["value"]); } } else if (key.starts_with("padding")) { YGEdge edge = edgeFromString(edgeStringFromPropertyName(key, "padding")); YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetPadding(node.get(), edge, value["value"]); + YGNodeStyleSetPadding(node, edge, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetPaddingPercent(node.get(), edge, value["value"]); + YGNodeStyleSetPaddingPercent(node, edge, value["value"]); } } else if (key.starts_with("border")) { YGEdge edge = edgeFromString(edgeStringFromPropertyName(key, "border")); YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetBorder(node.get(), edge, value["value"]); + YGNodeStyleSetBorder(node, edge, value["value"]); } } else if (key.starts_with("margin")) { YGEdge edge = edgeFromString(edgeStringFromPropertyName(key, "margin")); YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetMargin(node.get(), edge, value["value"]); + YGNodeStyleSetMargin(node, edge, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetMarginPercent(node.get(), edge, value["value"]); + YGNodeStyleSetMarginPercent(node, edge, value["value"]); } else if (unit == YGUnitAuto) { - YGNodeStyleSetMarginAuto(node.get(), edge); + YGNodeStyleSetMarginAuto(node, edge); } } else if (key == "gap") { YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetGap(node.get(), YGGutterAll, value["value"]); + YGNodeStyleSetGap(node, YGGutterAll, value["value"]); } } else if (key == "column-gap") { YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetGap(node.get(), YGGutterColumn, value["value"]); + YGNodeStyleSetGap(node, YGGutterColumn, value["value"]); } } else if (key == "row-gap") { YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetGap(node.get(), YGGutterRow, value["value"]); + YGNodeStyleSetGap(node, YGGutterRow, value["value"]); } } else if (key == "height") { YGUnit unit = unitFromJson(value); if (unit == YGUnitAuto) { - YGNodeStyleSetHeightAuto(node.get()); + YGNodeStyleSetHeightAuto(node); } else if (unit == YGUnitPoint) { - YGNodeStyleSetHeight(node.get(), value["value"]); + YGNodeStyleSetHeight(node, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetHeightPercent(node.get(), value["value"]); + YGNodeStyleSetHeightPercent(node, value["value"]); } } else if (key == "width") { YGUnit unit = unitFromJson(value); if (unit == YGUnitAuto) { - YGNodeStyleSetWidthAuto(node.get()); + YGNodeStyleSetWidthAuto(node); } else if (unit == YGUnitPoint) { - YGNodeStyleSetWidth(node.get(), value["value"]); + YGNodeStyleSetWidth(node, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetWidthPercent(node.get(), value["value"]); + YGNodeStyleSetWidthPercent(node, value["value"]); } } else if (key == "min-height") { YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetMinHeight(node.get(), value["value"]); + YGNodeStyleSetMinHeight(node, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetMinHeightPercent(node.get(), value["value"]); + YGNodeStyleSetMinHeightPercent(node, value["value"]); } } else if (key == "min-width") { YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetMinWidth(node.get(), value["value"]); + YGNodeStyleSetMinWidth(node, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetMinWidthPercent(node.get(), value["value"]); + YGNodeStyleSetMinWidthPercent(node, value["value"]); } } else if (key == "max-height") { YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetMaxHeight(node.get(), value["value"]); + YGNodeStyleSetMaxHeight(node, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetMaxHeightPercent(node.get(), value["value"]); + YGNodeStyleSetMaxHeightPercent(node, value["value"]); } } else if (key == "max-width") { YGUnit unit = unitFromJson(value); if (unit == YGUnitPoint) { - YGNodeStyleSetMaxWidth(node.get(), value["value"]); + YGNodeStyleSetMaxWidth(node, value["value"]); } else if (unit == YGUnitPercent) { - YGNodeStyleSetMaxWidthPercent(node.get(), value["value"]); + YGNodeStyleSetMaxWidthPercent(node, value["value"]); } } } } -YogaNodeAndConfig -buildTreeFromJson(json& j, YogaNodeAndConfig* parent, size_t index) { - std::shared_ptr config = buildConfigFromJson(j); +std::shared_ptr buildNodeFromJson( + const json& j, + std::shared_ptr config) { std::shared_ptr node(YGNodeNewWithConfig(config.get()), YGNodeFree); + json nodeState = j["node"]; + + for (json::iterator it = nodeState.begin(); it != nodeState.end(); it++) { + if (it.key() == "always-forms-containing-block") { + YGNodeSetAlwaysFormsContainingBlock(node.get(), it.value()); + } + } + + return node; +} + +YogaNodeAndConfig +buildTreeFromJson(const json& j, YogaNodeAndConfig* parent, size_t index) { + std::shared_ptr config = buildConfigFromJson(j); + std::shared_ptr node = buildNodeFromJson(j, config); YogaNodeAndConfig wrapper{node, config, std::vector{}}; if (parent != nullptr) { YGNodeInsertChild(parent->node_.get(), node.get(), index); parent->children_.push_back(wrapper); } - setStylesFromJson(j, node); + setStylesFromJson(j, node.get()); json children = j["children"]; size_t childIndex = 0; diff --git a/benchmark/Benchmark.h b/benchmark/Benchmark.h index c24a06dc..2d5097b1 100644 --- a/benchmark/Benchmark.h +++ b/benchmark/Benchmark.h @@ -18,7 +18,7 @@ namespace facebook::yoga { struct YogaNodeAndConfig { std::shared_ptr node_; - std::shared_ptr config_; + std::shared_ptr config_; std::vector children_; }; diff --git a/capture/CaptureTree.cpp b/capture/CaptureTree.cpp index 7fb12624..67e3993f 100644 --- a/capture/CaptureTree.cpp +++ b/capture/CaptureTree.cpp @@ -17,7 +17,8 @@ void captureTree(YGNodeRef node, const std::filesystem::path& path) { nodeToString( str, node, - PrintOptions::Style | PrintOptions::Children | PrintOptions::Config); + PrintOptions::Style | PrintOptions::Children | PrintOptions::Config | + PrintOptions::Node); std::ofstream file(path); file << str; } diff --git a/capture/NodeToString.cpp b/capture/NodeToString.cpp index 314a5937..a44c8383 100644 --- a/capture/NodeToString.cpp +++ b/capture/NodeToString.cpp @@ -5,6 +5,8 @@ * LICENSE file in the root directory of this source tree. */ +#include + #include #include @@ -126,131 +128,130 @@ static void nodeToStringImpl(json& j, YGNodeRef node, PrintOptions options) { j["layout"]["top"] = YGNodeStyleGetPosition(node, YGEdgeTop).value; j["layout"]["left"] = YGNodeStyleGetPosition(node, YGEdgeLeft).value; } + std::unique_ptr defaultNode( + YGNodeNew(), YGNodeFree); if ((options & PrintOptions::Style) == PrintOptions::Style) { - const YGNodeRef defaultNode = YGNodeNew(); appendEnumValueIfNotDefault( j["style"], "flex-direction", YGFlexDirectionToString(YGNodeStyleGetFlexDirection(node)), - YGFlexDirectionToString(YGNodeStyleGetFlexDirection(defaultNode))); + YGFlexDirectionToString( + YGNodeStyleGetFlexDirection(defaultNode.get()))); appendEnumValueIfNotDefault( j["style"], "justify-content", YGJustifyToString(YGNodeStyleGetJustifyContent(node)), - YGJustifyToString(YGNodeStyleGetJustifyContent(defaultNode))); + YGJustifyToString(YGNodeStyleGetJustifyContent(defaultNode.get()))); appendEnumValueIfNotDefault( j["style"], "align-items", YGAlignToString(YGNodeStyleGetAlignItems(node)), - YGAlignToString(YGNodeStyleGetAlignItems(defaultNode))); + YGAlignToString(YGNodeStyleGetAlignItems(defaultNode.get()))); appendEnumValueIfNotDefault( j["style"], "align-content", YGAlignToString(YGNodeStyleGetAlignContent(node)), - YGAlignToString(YGNodeStyleGetAlignContent(defaultNode))); + YGAlignToString(YGNodeStyleGetAlignContent(defaultNode.get()))); appendEnumValueIfNotDefault( j["style"], "align-self", YGAlignToString(YGNodeStyleGetAlignSelf(node)), - YGAlignToString(YGNodeStyleGetAlignSelf(defaultNode))); + YGAlignToString(YGNodeStyleGetAlignSelf(defaultNode.get()))); appendEnumValueIfNotDefault( j["style"], "flex-wrap", YGWrapToString(YGNodeStyleGetFlexWrap(node)), - YGWrapToString(YGNodeStyleGetFlexWrap(defaultNode))); + YGWrapToString(YGNodeStyleGetFlexWrap(defaultNode.get()))); appendEnumValueIfNotDefault( j["style"], "overflow", YGOverflowToString(YGNodeStyleGetOverflow(node)), - YGOverflowToString(YGNodeStyleGetOverflow(defaultNode))); + YGOverflowToString(YGNodeStyleGetOverflow(defaultNode.get()))); appendEnumValueIfNotDefault( j["style"], "display", YGDisplayToString(YGNodeStyleGetDisplay(node)), - YGDisplayToString(YGNodeStyleGetDisplay(defaultNode))); + YGDisplayToString(YGNodeStyleGetDisplay(defaultNode.get()))); appendEnumValueIfNotDefault( j["style"], "position-type", YGPositionTypeToString(YGNodeStyleGetPositionType(node)), - YGPositionTypeToString(YGNodeStyleGetPositionType(defaultNode))); + YGPositionTypeToString(YGNodeStyleGetPositionType(defaultNode.get()))); appendFloatIfNotDefault( j["style"], "flex-grow", YGNodeStyleGetFlexGrow(node), - YGNodeStyleGetFlexGrow(defaultNode)); + YGNodeStyleGetFlexGrow(defaultNode.get())); appendFloatIfNotDefault( j["style"], "flex-shrink", YGNodeStyleGetFlexShrink(node), - YGNodeStyleGetFlexShrink(defaultNode)); + YGNodeStyleGetFlexShrink(defaultNode.get())); appendFloatIfNotDefault( j["style"], "flex", YGNodeStyleGetFlex(node), - YGNodeStyleGetFlex(defaultNode)); + YGNodeStyleGetFlex(defaultNode.get())); appendYGValueIfNotDefault( j["style"], "flex-basis", YGNodeStyleGetFlexBasis(node), - YGNodeStyleGetFlexBasis(defaultNode)); + YGNodeStyleGetFlexBasis(defaultNode.get())); - appendEdges<&YGNodeStyleGetMargin>(j, "margin", node, defaultNode); - appendEdges<&YGNodeStyleGetPadding>(j, "padding", node, defaultNode); - appendEdges<&borderFloatToYGValue>(j, "border", node, defaultNode); - appendEdges<&YGNodeStyleGetPosition>(j, "position", node, defaultNode); + appendEdges<&YGNodeStyleGetMargin>(j, "margin", node, defaultNode.get()); + appendEdges<&YGNodeStyleGetPadding>(j, "padding", node, defaultNode.get()); + appendEdges<&borderFloatToYGValue>(j, "border", node, defaultNode.get()); + appendEdges<&YGNodeStyleGetPosition>( + j, "position", node, defaultNode.get()); appendFloatIfNotDefault( j["style"], "gap", YGNodeStyleGetGap(node, YGGutterAll), - YGNodeStyleGetGap(defaultNode, YGGutterAll)); + YGNodeStyleGetGap(defaultNode.get(), YGGutterAll)); appendFloatIfNotDefault( j["style"], "column-gap", YGNodeStyleGetGap(node, YGGutterColumn), - YGNodeStyleGetGap(defaultNode, YGGutterColumn)); + YGNodeStyleGetGap(defaultNode.get(), YGGutterColumn)); appendFloatIfNotDefault( j["style"], "row-gap", YGNodeStyleGetGap(node, YGGutterRow), - YGNodeStyleGetGap(defaultNode, YGGutterRow)); + YGNodeStyleGetGap(defaultNode.get(), YGGutterRow)); appendYGValueIfNotDefault( j["style"], "width", YGNodeStyleGetWidth(node), - YGNodeStyleGetWidth(defaultNode)); + YGNodeStyleGetWidth(defaultNode.get())); appendYGValueIfNotDefault( j["style"], "height", YGNodeStyleGetHeight(node), - YGNodeStyleGetHeight(defaultNode)); + YGNodeStyleGetHeight(defaultNode.get())); appendYGValueIfNotDefault( j["style"], "max-width", YGNodeStyleGetMaxWidth(node), - YGNodeStyleGetMaxWidth(defaultNode)); + YGNodeStyleGetMaxWidth(defaultNode.get())); appendYGValueIfNotDefault( j["style"], "max-height", YGNodeStyleGetMaxHeight(node), - YGNodeStyleGetMaxHeight(defaultNode)); + YGNodeStyleGetMaxHeight(defaultNode.get())); appendYGValueIfNotDefault( j["style"], "min-width", YGNodeStyleGetMinWidth(node), - YGNodeStyleGetMinWidth(defaultNode)); + YGNodeStyleGetMinWidth(defaultNode.get())); appendYGValueIfNotDefault( j["style"], "min-height", YGNodeStyleGetMinHeight(node), - YGNodeStyleGetMinHeight(defaultNode)); - - if (YGNodeHasMeasureFunc(node)) { - j["style"]["has-custom-measure"] = true; - } + YGNodeStyleGetMinHeight(defaultNode.get())); } if ((options & PrintOptions::Config) == PrintOptions::Config) { @@ -286,6 +287,17 @@ static void nodeToStringImpl(json& j, YGNodeRef node, PrintOptions options) { } } + if ((options & PrintOptions::Node) == PrintOptions::Node) { + appendBoolIfNotDefault( + j["node"], + "always-forms-containing-block", + YGNodeGetAlwaysFormsContainingBlock(node), + YGNodeGetAlwaysFormsContainingBlock(defaultNode.get())); + if (YGNodeHasMeasureFunc(node)) { + j["node"]["has-custom-measure"] = true; + } + } + const size_t childCount = YGNodeGetChildCount(node); if ((options & PrintOptions::Children) == PrintOptions::Children && childCount > 0) { diff --git a/capture/NodeToString.h b/capture/NodeToString.h index e9d668ae..95afd18b 100644 --- a/capture/NodeToString.h +++ b/capture/NodeToString.h @@ -18,6 +18,7 @@ enum class PrintOptions : uint8_t { Children = 1 << 1, Style = 1 << 2, Config = 1 << 3, + Node = 1 << 4, }; YG_DEFINE_ENUM_FLAG_OPERATORS(PrintOptions); diff --git a/yoga/YGNode.cpp b/yoga/YGNode.cpp index d3265e01..57f0473b 100644 --- a/yoga/YGNode.cpp +++ b/yoga/YGNode.cpp @@ -329,6 +329,10 @@ void YGNodeSetAlwaysFormsContainingBlock( resolveRef(node)->setAlwaysFormsContainingBlock(alwaysFormsContainingBlock); } +bool YGNodeGetAlwaysFormsContainingBlock(YGNodeConstRef node) { + return resolveRef(node)->alwaysFormsContainingBlock(); +} + // TODO: This leaks internal details to the public API. Remove after removing // ComponentKit usage of it. bool YGNodeCanUseCachedMeasurement( diff --git a/yoga/YGNode.h b/yoga/YGNode.h index e6f233ac..448000eb 100644 --- a/yoga/YGNode.h +++ b/yoga/YGNode.h @@ -273,6 +273,14 @@ YG_EXPORT void YGNodeSetAlwaysFormsContainingBlock( YGNodeRef node, bool alwaysFormsContainingBlock); +/** + * Whether the node will always form a containing block for any descendant. This + * can happen in situation where the client implements something like a + * transform that can affect containing blocks but is not handled by Yoga + * directly. + */ +YG_EXPORT bool YGNodeGetAlwaysFormsContainingBlock(YGNodeConstRef node); + /** * @deprecated */