From 19af9e6450da2d6544d5b6c5ea5e61f75ca1b889 Mon Sep 17 00:00:00 2001 From: Joe Vilches Date: Fri, 2 Feb 2024 15:44:23 -0800 Subject: [PATCH] Move NodeToString.cpp to benchmark and remove interal usages (#1568) Summary: X-link: https://github.com/facebook/react-native/pull/42710 Pull Request resolved: https://github.com/facebook/yoga/pull/1568 This is no longer going to be built with normal yoga so we are going to switch to a public API Reviewed By: NickGerleman Differential Revision: D53141235 fbshipit-source-id: 259270a4cd91ef0dab91cefba9c41953b6340d78 --- .github/workflows/validate-cpp.yml | 21 +++ capture/CMakeLists.txt | 19 +++ capture/NodeToString.cpp | 228 +++++++++++++++++++++++++ {yoga/debug => capture}/NodeToString.h | 13 +- yoga/algorithm/CalculateLayout.cpp | 9 - yoga/config/Config.cpp | 8 - yoga/config/Config.h | 4 - yoga/debug/NodeToString.cpp | 210 ----------------------- 8 files changed, 271 insertions(+), 241 deletions(-) create mode 100644 capture/CMakeLists.txt create mode 100644 capture/NodeToString.cpp rename {yoga/debug => capture}/NodeToString.h (63%) delete mode 100644 yoga/debug/NodeToString.cpp diff --git a/.github/workflows/validate-cpp.yml b/.github/workflows/validate-cpp.yml index 9750bb9d..4e019b31 100644 --- a/.github/workflows/validate-cpp.yml +++ b/.github/workflows/validate-cpp.yml @@ -76,6 +76,27 @@ jobs: run: ./build/benchmark working-directory: benchmark + capture: + name: Capture [${{ matrix.toolchain }}] + runs-on: ${{ (matrix.toolchain == 'MSVC') && 'windows-latest' || 'ubuntu-latest' }} + strategy: + matrix: + toolchain: [Clang, GCC, MSVC] + + steps: + - uses: actions/checkout@v3 + + - name: Setup + uses: ./.github/actions/setup-cpp + with: + toolchain: ${{ matrix.toolchain }} + + - name: Build capture + run: | + cmake -S . -B build -G Ninja -D CMAKE_BUILD_TYPE=Release + cmake --build build + working-directory: capture + clang-format: name: Format runs-on: ubuntu-latest diff --git a/capture/CMakeLists.txt b/capture/CMakeLists.txt new file mode 100644 index 00000000..e4d8b7ce --- /dev/null +++ b/capture/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (c) Meta Platforms, Inc. and affiliates. +# +# This source code is licensed under the MIT license found in the +# LICENSE file in the root directory of this source tree. + +cmake_minimum_required(VERSION 3.13...3.26) +project(capture) +set(CMAKE_VERBOSE_MAKEFILE on) + +set(YOGA_ROOT ${CMAKE_CURRENT_SOURCE_DIR}/..) +include(${YOGA_ROOT}/cmake/project-defaults.cmake) + +add_subdirectory(${YOGA_ROOT}/yoga ${CMAKE_CURRENT_BINARY_DIR}/yoga) + +file(GLOB SOURCES CONFIGURE_DEPENDS + ${CMAKE_CURRENT_SOURCE_DIR}/*.cpp) +add_library(capture STATIC ${SOURCES}) + +target_link_libraries(capture yogacore) diff --git a/capture/NodeToString.cpp b/capture/NodeToString.cpp new file mode 100644 index 00000000..1cedfadb --- /dev/null +++ b/capture/NodeToString.cpp @@ -0,0 +1,228 @@ +/* + * Copyright (c) Meta Platforms, Inc. and affiliates. + * + * This source code is licensed under the MIT license found in the + * LICENSE file in the root directory of this source tree. + */ + +#include + +#include +#include + +namespace facebook::yoga { + +static void indent(std::string& base, uint32_t level) { + for (uint32_t i = 0; i < level; ++i) { + base.append(" "); + } +} + +static void appendFormattedString(std::string& str, const char* fmt, ...) { + va_list args; + va_start(args, fmt); + va_list argsCopy; + va_copy(argsCopy, args); + std::vector buf(1 + static_cast(vsnprintf(NULL, 0, fmt, args))); + va_end(args); + vsnprintf(buf.data(), buf.size(), fmt, argsCopy); + va_end(argsCopy); + std::string result = std::string(buf.begin(), buf.end() - 1); + str.append(result); +} + +static void appendFloatOptionalIfDefined( + std::string& base, + const std::string key, + const float num) { + if (num != YGUndefined) { + appendFormattedString(base, "%s: %g; ", key.c_str(), num); + } +} + +static void appendNumberIfNotUndefined( + std::string& base, + const std::string key, + const YGValue& number) { + if (number.unit != YGUnitUndefined) { + if (number.unit == YGUnitAuto) { + base.append(key + ": auto; "); + } else { + std::string unit = number.unit == YGUnitPoint ? "px" : "%%"; + appendFormattedString( + base, "%s: %g%s; ", key.c_str(), number.value, unit.c_str()); + } + } +} + +static void appendNumberIfNotAuto( + std::string& base, + const std::string& key, + const YGValue& number) { + if (number.unit != YGUnitAuto) { + appendNumberIfNotUndefined(base, key, number); + } +} + +static void appendNumberIfNotZero( + std::string& base, + const std::string& str, + const YGValue& number) { + if (number.unit == YGUnitAuto) { + base.append(str + ": auto; "); + } else if (number.value != 0) { + appendNumberIfNotUndefined(base, str, number); + } +} + +template +static void +appendEdges(std::string& base, const std::string& key, YGNodeRef node) { + appendNumberIfNotZero(base, key + "-left", (*Field)(node, YGEdgeLeft)); + appendNumberIfNotZero(base, key + "-right", (*Field)(node, YGEdgeRight)); + appendNumberIfNotZero(base, key + "-top", (*Field)(node, YGEdgeTop)); + appendNumberIfNotZero(base, key + "-bottom", (*Field)(node, YGEdgeBottom)); + appendNumberIfNotZero(base, key + "-all", (*Field)(node, YGEdgeAll)); + appendNumberIfNotZero(base, key + "-start", (*Field)(node, YGEdgeStart)); + appendNumberIfNotZero(base, key + "-end", (*Field)(node, YGEdgeEnd)); + appendNumberIfNotZero( + base, key + "-horizontal", (*Field)(node, YGEdgeHorizontal)); + appendNumberIfNotZero( + base, key + "-vertical", (*Field)(node, YGEdgeVertical)); +} + +YGValue borderFloatToYGValue(YGNodeRef node, YGEdge edge) { + float val = YGNodeStyleGetBorder(node, edge); + YGUnit unit = val == YGUndefined ? YGUnitUndefined : YGUnitPoint; + return YGValue{val, unit}; +} + +void nodeToString( + std::string& str, + YGNodeRef node, + YGPrintOptions options, + uint32_t level) { + indent(str, level); + appendFormattedString(str, "
(str, "margin", node); + appendEdges<&YGNodeStyleGetPadding>(str, "padding", node); + appendEdges<&borderFloatToYGValue>(str, "border", node); + + if (YGNodeStyleGetGap(node, YGGutterAll) != YGUndefined) { + appendFloatOptionalIfDefined( + str, "gap", YGNodeStyleGetGap(node, YGGutterAll)); + } else { + appendFloatOptionalIfDefined( + str, "column-gap", YGNodeStyleGetGap(node, YGGutterColumn)); + appendFloatOptionalIfDefined( + str, "row-gap", YGNodeStyleGetGap(node, YGGutterRow)); + } + + appendNumberIfNotAuto(str, "width", YGNodeStyleGetWidth(node)); + appendNumberIfNotAuto(str, "height", YGNodeStyleGetHeight(node)); + appendNumberIfNotAuto(str, "max-width", YGNodeStyleGetMaxWidth(node)); + appendNumberIfNotAuto(str, "max-height", YGNodeStyleGetMaxHeight(node)); + appendNumberIfNotAuto(str, "min-width", YGNodeStyleGetMinWidth(node)); + appendNumberIfNotAuto(str, "min-height", YGNodeStyleGetMinHeight(node)); + + if (YGNodeStyleGetPositionType(node) != + YGNodeStyleGetPositionType(defaultNode)) { + appendFormattedString( + str, + "position: %s; ", + YGPositionTypeToString(YGNodeStyleGetPositionType(node))); + } + + appendEdges<&YGNodeStyleGetPosition>(str, "position", node); + appendFormattedString(str, "\" "); + + if (YGNodeHasMeasureFunc(node)) { + appendFormattedString(str, "has-custom-measure=\"true\""); + } + } + appendFormattedString(str, ">"); + + const size_t childCount = YGNodeGetChildCount(node); + if ((options & YGPrintOptionsChildren) == YGPrintOptionsChildren && + childCount > 0) { + for (size_t i = 0; i < childCount; i++) { + appendFormattedString(str, "\n"); + nodeToString(str, YGNodeGetChild(node, i), options, level + 1); + } + appendFormattedString(str, "\n"); + indent(str, level); + } + appendFormattedString(str, "
"); +} + +} // namespace facebook::yoga diff --git a/yoga/debug/NodeToString.h b/capture/NodeToString.h similarity index 63% rename from yoga/debug/NodeToString.h rename to capture/NodeToString.h index 268d5ac9..e9a3cc47 100644 --- a/yoga/debug/NodeToString.h +++ b/capture/NodeToString.h @@ -5,25 +5,18 @@ * LICENSE file in the root directory of this source tree. */ -#ifdef DEBUG - #pragma once #include -#include -#include +#include namespace facebook::yoga { void nodeToString( std::string& str, - const yoga::Node* node, - PrintOptions options, + YGNodeRef node, + YGPrintOptions options, uint32_t level); -void print(const yoga::Node* node, PrintOptions options); - } // namespace facebook::yoga - -#endif diff --git a/yoga/algorithm/CalculateLayout.cpp b/yoga/algorithm/CalculateLayout.cpp index e1a28040..9b214cf5 100644 --- a/yoga/algorithm/CalculateLayout.cpp +++ b/yoga/algorithm/CalculateLayout.cpp @@ -26,7 +26,6 @@ #include #include #include -#include #include #include #include @@ -2366,14 +2365,6 @@ void calculateLayout( node->setPosition( node->getLayout().direction(), ownerWidth, ownerHeight, ownerWidth); roundLayoutResultsToPixelGrid(node, 0.0f, 0.0f); - -#ifdef DEBUG - if (node->getConfig()->shouldPrintTree()) { - yoga::print( - node, - PrintOptions::Layout | PrintOptions::Children | PrintOptions::Style); - } -#endif } Event::publish(node, {&markerData}); diff --git a/yoga/config/Config.cpp b/yoga/config/Config.cpp index b717d974..607e5774 100644 --- a/yoga/config/Config.cpp +++ b/yoga/config/Config.cpp @@ -32,14 +32,6 @@ bool Config::useWebDefaults() const { return useWebDefaults_; } -void Config::setShouldPrintTree(bool printTree) { - printTree_ = printTree; -} - -bool Config::shouldPrintTree() const { - return printTree_; -} - void Config::setExperimentalFeatureEnabled( ExperimentalFeature feature, bool enabled) { diff --git a/yoga/config/Config.h b/yoga/config/Config.h index 1bdc0469..e902bd0d 100644 --- a/yoga/config/Config.h +++ b/yoga/config/Config.h @@ -37,9 +37,6 @@ class YG_EXPORT Config : public ::YGConfig { void setUseWebDefaults(bool useWebDefaults); bool useWebDefaults() const; - void setShouldPrintTree(bool printTree); - bool shouldPrintTree() const; - void setExperimentalFeatureEnabled(ExperimentalFeature feature, bool enabled); bool isExperimentalFeatureEnabled(ExperimentalFeature feature) const; ExperimentalFeatureSet getEnabledExperiments() const; @@ -74,7 +71,6 @@ class YG_EXPORT Config : public ::YGConfig { YGLogger logger_; bool useWebDefaults_ : 1 = false; - bool printTree_ : 1 = false; ExperimentalFeatureSet experimentalFeatures_{}; Errata errata_ = Errata::None; diff --git a/yoga/debug/NodeToString.cpp b/yoga/debug/NodeToString.cpp deleted file mode 100644 index 39264fea..00000000 --- a/yoga/debug/NodeToString.cpp +++ /dev/null @@ -1,210 +0,0 @@ -/* - * Copyright (c) Meta Platforms, Inc. and affiliates. - * - * This source code is licensed under the MIT license found in the - * LICENSE file in the root directory of this source tree. - */ - -#ifdef DEBUG - -#include - -#include -#include -#include - -namespace facebook::yoga { - -static void indent(std::string& base, uint32_t level) { - for (uint32_t i = 0; i < level; ++i) { - base.append(" "); - } -} - -static void appendFormattedString(std::string& str, const char* fmt, ...) { - va_list args; - va_start(args, fmt); - va_list argsCopy; - va_copy(argsCopy, args); - std::vector buf(1 + static_cast(vsnprintf(NULL, 0, fmt, args))); - va_end(args); - vsnprintf(buf.data(), buf.size(), fmt, argsCopy); - va_end(argsCopy); - std::string result = std::string(buf.begin(), buf.end() - 1); - str.append(result); -} - -static void appendFloatOptionalIfDefined( - std::string& base, - const std::string key, - const FloatOptional num) { - if (num.isDefined()) { - appendFormattedString(base, "%s: %g; ", key.c_str(), num.unwrap()); - } -} - -static void appendNumberIfNotUndefined( - std::string& base, - const std::string key, - const Style::Length& number) { - if (number.unit() != Unit::Undefined) { - if (number.unit() == Unit::Auto) { - base.append(key + ": auto; "); - } else { - std::string unit = number.unit() == Unit::Point ? "px" : "%%"; - appendFormattedString( - base, - "%s: %g%s; ", - key.c_str(), - number.value().unwrap(), - unit.c_str()); - } - } -} - -static void appendNumberIfNotAuto( - std::string& base, - const std::string& key, - const Style::Length& number) { - if (number.unit() != Unit::Auto) { - appendNumberIfNotUndefined(base, key, number); - } -} - -static void appendNumberIfNotZero( - std::string& base, - const std::string& str, - const Style::Length& number) { - if (number.unit() == Unit::Auto) { - base.append(str + ": auto; "); - } else if (!yoga::inexactEquals(number.value().unwrap(), 0)) { - appendNumberIfNotUndefined(base, str, number); - } -} - -template -static void -appendEdges(std::string& base, const std::string& key, const Style& style) { - for (auto edge : ordinals()) { - std::string str = key + "-" + toString(edge); - appendNumberIfNotZero(base, str, (style.*Field)(edge)); - } -} - -void nodeToString( - std::string& str, - const yoga::Node* node, - PrintOptions options, - uint32_t level) { - indent(str, level); - appendFormattedString(str, "
getLayout().dimension(Dimension::Width)); - appendFormattedString( - str, "height: %g; ", node->getLayout().dimension(Dimension::Height)); - appendFormattedString( - str, "top: %g; ", node->getLayout().position(PhysicalEdge::Top)); - appendFormattedString( - str, "left: %g;", node->getLayout().position(PhysicalEdge::Left)); - appendFormattedString(str, "\" "); - } - - if ((options & PrintOptions::Style) == PrintOptions::Style) { - appendFormattedString(str, "style=\""); - const auto& style = node->style(); - if (style.flexDirection() != yoga::Style{}.flexDirection()) { - appendFormattedString( - str, "flex-direction: %s; ", toString(style.flexDirection())); - } - if (style.justifyContent() != yoga::Style{}.justifyContent()) { - appendFormattedString( - str, "justify-content: %s; ", toString(style.justifyContent())); - } - if (style.alignItems() != yoga::Style{}.alignItems()) { - appendFormattedString( - str, "align-items: %s; ", toString(style.alignItems())); - } - if (style.alignContent() != yoga::Style{}.alignContent()) { - appendFormattedString( - str, "align-content: %s; ", toString(style.alignContent())); - } - if (style.alignSelf() != yoga::Style{}.alignSelf()) { - appendFormattedString( - str, "align-self: %s; ", toString(style.alignSelf())); - } - appendFloatOptionalIfDefined(str, "flex-grow", style.flexGrow()); - appendFloatOptionalIfDefined(str, "flex-shrink", style.flexShrink()); - appendNumberIfNotAuto(str, "flex-basis", style.flexBasis()); - appendFloatOptionalIfDefined(str, "flex", style.flex()); - - if (style.flexWrap() != yoga::Style{}.flexWrap()) { - appendFormattedString(str, "flex-wrap: %s; ", toString(style.flexWrap())); - } - - if (style.overflow() != yoga::Style{}.overflow()) { - appendFormattedString(str, "overflow: %s; ", toString(style.overflow())); - } - - if (style.display() != yoga::Style{}.display()) { - appendFormattedString(str, "display: %s; ", toString(style.display())); - } - appendEdges<&Style::margin>(str, "margin", style); - appendEdges<&Style::padding>(str, "padding", style); - appendEdges<&Style::border>(str, "border", style); - - if (style.gap(Gutter::All).isDefined()) { - appendNumberIfNotUndefined(str, "gap", style.gap(Gutter::All)); - } else { - appendNumberIfNotUndefined(str, "column-gap", style.gap(Gutter::Column)); - appendNumberIfNotUndefined(str, "row-gap", style.gap(Gutter::Row)); - } - - appendNumberIfNotAuto(str, "width", style.dimension(Dimension::Width)); - appendNumberIfNotAuto(str, "height", style.dimension(Dimension::Height)); - appendNumberIfNotAuto( - str, "max-width", style.maxDimension(Dimension::Width)); - appendNumberIfNotAuto( - str, "max-height", style.maxDimension(Dimension::Height)); - appendNumberIfNotAuto( - str, "min-width", style.minDimension(Dimension::Width)); - appendNumberIfNotAuto( - str, "min-height", style.minDimension(Dimension::Height)); - - if (style.positionType() != yoga::Style{}.positionType()) { - appendFormattedString( - str, "position: %s; ", toString(style.positionType())); - } - - appendEdges<&Style::position>(str, "position", style); - appendFormattedString(str, "\" "); - - if (node->hasMeasureFunc()) { - appendFormattedString(str, "has-custom-measure=\"true\""); - } - } - appendFormattedString(str, ">"); - - const size_t childCount = node->getChildCount(); - if ((options & PrintOptions::Children) == PrintOptions::Children && - childCount > 0) { - for (size_t i = 0; i < childCount; i++) { - appendFormattedString(str, "\n"); - nodeToString(str, node->getChild(i), options, level + 1); - } - appendFormattedString(str, "\n"); - indent(str, level); - } - appendFormattedString(str, "
"); -} - -void print(const yoga::Node* node, PrintOptions options) { - std::string str; - yoga::nodeToString(str, node, options, 0); - yoga::log(node, LogLevel::Debug, str.c_str()); -} - -} // namespace facebook::yoga -#endif