Back out Stack D13119110..D13236159

Summary: backout, causes failures

Reviewed By: adityasharat

Differential Revision: D13376210

fbshipit-source-id: 1fa8823f2dce601c47738f34ddb2674288197e79
This commit is contained in:
David Aurelio
2018-12-07 12:37:12 -08:00
committed by Facebook Github Bot
parent 6b7f6980f9
commit b26e637c81
19 changed files with 612 additions and 701 deletions

View File

@@ -1,4 +1,4 @@
/** /**
* Copyright (c) Facebook, Inc. and its affiliates. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the * This source code is licensed under the MIT license found in the
@@ -9,11 +9,28 @@ namespace Facebook.Yoga
{ {
public static class YogaConstants public static class YogaConstants
{ {
public const float Undefined = float.NaN; /**
* Large positive number signifies that the property(float) is undefined. Earlier we used to have
* YGundefined as NAN, but the downside of this is that we can't use -ffast-math compiler flag as
* it assumes all floating-point calculation involve and result into finite numbers. For more
* information regarding -ffast-math compiler flag in clang, have a look at
* https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math
*/
public const float Undefined = 10E20F;
public static bool IsUndefined(float value) public static bool IsUndefined(float value)
{ {
return float.IsNaN(value); // Value of a float in the case of it being not defined is 10.1E20. Earlier it used to be NAN,
// the benefit of which
// was that if NAN is involved in any mathematical expression the result was NAN. But since we
// want to have `-ffast-math`
// flag being used by compiler which assumes that the floating point values are not NAN and Inf,
// we represent YGUndefined as 10.1E20.
// But now if YGUndefined is involved in any mathematical operations this value(10.1E20) would
// change.
// So the following check makes sure that if the value is outside a range (-10E8, 10E8) then it
// is undefined.
return value >= 10E8F || value <= -10E8;
} }
public static bool IsUndefined(YogaValue value) public static bool IsUndefined(YogaValue value)

View File

@@ -1,17 +1,35 @@
/** /*
* Copyright (c) Facebook, Inc. and its affiliates. * Copyright (c) Facebook, Inc. and its affiliates.
* *
* This source code is licensed under the MIT license found in the LICENSE * This source code is licensed under the MIT license found in the LICENSE
* file in the root directory of this source tree. * file in the root directory of this source tree.
*
*/ */
package com.facebook.yoga; package com.facebook.yoga;
public class YogaConstants { public class YogaConstants {
public static final float UNDEFINED = Float.NaN; /**
* Large positive number signifies that the property(float) is undefined. Earlier we used to have
* YGundefined as NAN, but the downside of this is that we can't use -ffast-math compiler flag as
* it assumes all floating-point calculation involve and result into finite numbers. For more
* information regarding -ffast-math compiler flag in clang, have a look at
* https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math
*/
public static final float UNDEFINED = (float) (10E20);
public static boolean isUndefined(float value) { public static boolean isUndefined(float value) {
return Float.compare(value, UNDEFINED) == 0; // Value of a float in the case of it being not defined is 10.1E20. Earlier it used to be NAN,
// the benefit of which
// was that if NAN is involved in any mathematical expression the result was NAN. But since we
// want to have `-ffast-math`
// flag being used by compiler which assumes that the floating point values are not NAN and Inf,
// we represent YGUndefined as 10.1E20.
// But now if YGUndefined is involved in any mathematical operations this value(10.1E20) would
// change.
// So the following check makes sure that if the value is outside a range (-10E8, 10E8) then it
// is undefined.
return (Float.compare(value, (float) 10E8) >= 0 || Float.compare(value, (float) -10E8) <= 0);
} }
public static boolean isUndefined(YogaValue value) { public static boolean isUndefined(YogaValue value) {

View File

@@ -1,205 +0,0 @@
/**
* 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 <yoga/YGFloatOptional.h>
#include <gtest/gtest.h>
#include <yoga/YGFloatOptional.h>
#include <yoga/Yoga.h>
constexpr auto empty = YGFloatOptional{};
constexpr auto zero = YGFloatOptional{0.0f};
constexpr auto one = YGFloatOptional{1.0f};
constexpr auto positive = YGFloatOptional{1234.5f};
constexpr auto negative = YGFloatOptional{-9876.5f};
TEST(YGFloatOptional, value) {
ASSERT_EQ(zero.unwrap(), 0.0f);
ASSERT_EQ(positive.unwrap(), 1234.5f);
ASSERT_EQ(negative.unwrap(), -9876.5f);
ASSERT_TRUE(YGFloatIsUndefined(empty.unwrap()));
ASSERT_TRUE(empty.isUndefined());
ASSERT_FALSE(zero.isUndefined());
ASSERT_FALSE(negative.isUndefined());
}
TEST(YGFloatOptional, equality) {
ASSERT_TRUE(empty == empty);
ASSERT_TRUE(empty == YGUndefined);
ASSERT_FALSE(empty == zero);
ASSERT_FALSE(empty == negative);
ASSERT_FALSE(empty == 12.3f);
ASSERT_TRUE(zero == zero);
ASSERT_TRUE(zero == 0.0f);
ASSERT_FALSE(zero == positive);
ASSERT_FALSE(zero == -5555.5f);
ASSERT_TRUE(one == one);
ASSERT_TRUE(one == 1.0f);
ASSERT_FALSE(one == positive);
ASSERT_TRUE(negative == negative);
ASSERT_TRUE(negative == negative.unwrap());
ASSERT_FALSE(negative == zero);
}
TEST(YGFloatOptional, inequality) {
ASSERT_FALSE(empty != empty);
ASSERT_FALSE(empty != YGUndefined);
ASSERT_TRUE(empty != zero);
ASSERT_TRUE(empty != negative);
ASSERT_TRUE(empty != 12.3f);
ASSERT_FALSE(zero != zero);
ASSERT_FALSE(zero != 0.0f);
ASSERT_TRUE(zero != positive);
ASSERT_TRUE(zero != -5555.5f);
ASSERT_FALSE(one != one);
ASSERT_FALSE(one != 1.0f);
ASSERT_TRUE(one != positive);
ASSERT_FALSE(negative != negative);
ASSERT_FALSE(negative != negative.unwrap());
ASSERT_TRUE(negative != zero);
}
TEST(YGFloatOptional, greater) {
ASSERT_FALSE(empty > empty);
ASSERT_FALSE(empty > zero);
ASSERT_FALSE(empty > one);
ASSERT_FALSE(empty > positive);
ASSERT_FALSE(empty > negative);
ASSERT_FALSE(zero > empty);
ASSERT_FALSE(one > empty);
ASSERT_FALSE(positive > empty);
ASSERT_FALSE(negative > empty);
ASSERT_TRUE(zero > negative);
ASSERT_FALSE(zero > zero);
ASSERT_FALSE(zero > positive);
ASSERT_FALSE(zero > one);
ASSERT_TRUE(one > negative);
ASSERT_TRUE(one > zero);
ASSERT_FALSE(one > empty);
ASSERT_FALSE(one > positive);
ASSERT_TRUE(negative > YGFloatOptional{-INFINITY});
ASSERT_FALSE(negative > empty);
}
TEST(YGFloatOptional, lower) {
ASSERT_FALSE(empty < empty);
ASSERT_FALSE(empty < zero);
ASSERT_FALSE(empty < one);
ASSERT_FALSE(empty < positive);
ASSERT_FALSE(empty < negative);
ASSERT_FALSE(zero < empty);
ASSERT_FALSE(one < empty);
ASSERT_FALSE(positive < empty);
ASSERT_FALSE(negative < empty);
ASSERT_TRUE(negative < zero);
ASSERT_FALSE(zero < zero);
ASSERT_FALSE(positive < zero);
ASSERT_FALSE(one < zero);
ASSERT_TRUE(negative < one);
ASSERT_TRUE(zero < one);
ASSERT_FALSE(empty < one);
ASSERT_FALSE(positive < one);
ASSERT_TRUE(YGFloatOptional{-INFINITY} < negative);
ASSERT_FALSE(empty < negative);
}
TEST(YGFloatOptional, greater_equals) {
ASSERT_TRUE(empty >= empty);
ASSERT_FALSE(empty >= zero);
ASSERT_FALSE(empty >= one);
ASSERT_FALSE(empty >= positive);
ASSERT_FALSE(empty >= negative);
ASSERT_TRUE(zero >= negative);
ASSERT_TRUE(zero >= zero);
ASSERT_FALSE(zero >= positive);
ASSERT_FALSE(zero >= one);
ASSERT_TRUE(one >= negative);
ASSERT_TRUE(one >= zero);
ASSERT_FALSE(one >= empty);
ASSERT_FALSE(one >= positive);
ASSERT_TRUE(negative >= YGFloatOptional{-INFINITY});
ASSERT_TRUE(negative >= negative);
ASSERT_FALSE(negative >= empty);
}
TEST(YGFloatOptional, lower_equals) {
ASSERT_TRUE(empty <= empty);
ASSERT_FALSE(zero <= empty);
ASSERT_FALSE(one <= empty);
ASSERT_FALSE(positive <= empty);
ASSERT_FALSE(negative <= empty);
ASSERT_TRUE(negative <= zero);
ASSERT_TRUE(zero <= zero);
ASSERT_FALSE(positive <= zero);
ASSERT_FALSE(one <= zero);
ASSERT_TRUE(negative <= one);
ASSERT_TRUE(zero <= one);
ASSERT_FALSE(empty <= one);
ASSERT_FALSE(positive <= one);
ASSERT_TRUE(YGFloatOptional{-INFINITY} <= negative);
ASSERT_TRUE(negative <= negative);
ASSERT_FALSE(empty <= negative);
}
TEST(YGFloatOptional, addition) {
ASSERT_EQ(zero + one, one);
ASSERT_EQ(
negative + positive,
YGFloatOptional{negative.unwrap() + positive.unwrap()});
ASSERT_EQ(empty + zero, empty);
ASSERT_EQ(empty + empty, empty);
ASSERT_EQ(negative + empty, empty);
}
TEST(YGFloatOptional, subtraction) {
ASSERT_EQ(zero - one, YGFloatOptional{-1.0f});
ASSERT_EQ(
negative - positive,
YGFloatOptional{negative.unwrap() - positive.unwrap()});
ASSERT_EQ(empty - zero, empty);
ASSERT_EQ(empty - empty, empty);
ASSERT_EQ(negative - empty, empty);
}
TEST(YGFloatOptional, unary_minus) {
ASSERT_EQ(-zero, zero);
ASSERT_EQ(-negative, YGFloatOptional{-negative.unwrap()});
ASSERT_EQ(-positive, YGFloatOptional{-positive.unwrap()});
ASSERT_EQ(-empty, empty);
}
TEST(YGFloatOptional, orElse) {
ASSERT_EQ(empty.orElse(1.23f), 1.23f);
ASSERT_TRUE(YGFloatIsUndefined(empty.orElse(YGUndefined)));
ASSERT_EQ(one.orElse(1.23f), 1.0f);
}
TEST(YGFloatOptional, orElseGet) {
auto x = empty.orElseGet([] { return 1.23f; });
ASSERT_EQ(x, 1.23f);
ASSERT_TRUE(YGFloatIsUndefined(empty.orElseGet([] { return YGUndefined; })));
auto y = one.orElseGet([] { return 1.23f; });
ASSERT_EQ(y, 1.0f);
}

View File

@@ -58,6 +58,7 @@ BASE_COMPILER_FLAGS = [
"-Wall", "-Wall",
"-Werror", "-Werror",
"-O3", "-O3",
"-ffast-math",
] ]
LIBRARY_COMPILER_FLAGS = BASE_COMPILER_FLAGS + [ LIBRARY_COMPILER_FLAGS = BASE_COMPILER_FLAGS + [

View File

@@ -55,14 +55,15 @@ float YGFloatSanitize(const float val) {
return yoga::isUndefined(val) ? 0 : val; return yoga::isUndefined(val) ? 0 : val;
} }
YGFloatOptional YGFloatOptionalMax( float YGUnwrapFloatOptional(const YGFloatOptional& op) {
const YGFloatOptional op1, return op.isUndefined() ? YGUndefined : op.getValue();
const YGFloatOptional op2) {
if (op1 > op2) {
return op1;
} }
if (op2 > op1) {
return op2; YGFloatOptional YGFloatOptionalMax(
const YGFloatOptional& op1,
const YGFloatOptional& op2) {
if (!op1.isUndefined() && !op2.isUndefined()) {
return op1.getValue() > op2.getValue() ? op1 : op2;
} }
return op1.isUndefined() ? op2 : op1; return op1.isUndefined() ? op2 : op1;
} }

View File

@@ -57,12 +57,22 @@ bool YGValueEqual(const YGValue a, const YGValue b);
// difference between two floats is less than 0.0001f or both are undefined. // difference between two floats is less than 0.0001f or both are undefined.
bool YGFloatsEqual(const float a, const float b); bool YGFloatsEqual(const float a, const float b);
// We need custom max function, since we want that, if one argument is
// YGUndefined then the max funtion should return the other argument as the max
// value. We wouldn't have needed a custom max function if YGUndefined was NAN
// as fmax has the same behaviour, but with NAN we cannot use `-ffast-math`
// compiler flag.
float YGFloatMax(const float a, const float b); float YGFloatMax(const float a, const float b);
YGFloatOptional YGFloatOptionalMax( YGFloatOptional YGFloatOptionalMax(
const YGFloatOptional op1, const YGFloatOptional& op1,
const YGFloatOptional op2); const YGFloatOptional& op2);
// We need custom min function, since we want that, if one argument is
// YGUndefined then the min funtion should return the other argument as the min
// value. We wouldn't have needed a custom min function if YGUndefined was NAN
// as fmin has the same behaviour, but with NAN we cannot use `-ffast-math`
// compiler flag.
float YGFloatMin(const float a, const float b); float YGFloatMin(const float a, const float b);
// This custom float comparision function compares the array of float with // This custom float comparision function compares the array of float with
@@ -82,6 +92,11 @@ bool YGFloatArrayEqual(
// This function returns 0 if YGFloatIsUndefined(val) is true and val otherwise // This function returns 0 if YGFloatIsUndefined(val) is true and val otherwise
float YGFloatSanitize(const float val); float YGFloatSanitize(const float val);
// This function unwraps optional and returns YGUndefined if not defined or
// op.value otherwise
// TODO: Get rid off this function
float YGUnwrapFloatOptional(const YGFloatOptional& op);
YGFlexDirection YGFlexDirectionCross( YGFlexDirection YGFlexDirectionCross(
const YGFlexDirection flexDirection, const YGFlexDirection flexDirection,
const YGDirection direction); const YGDirection direction);
@@ -91,17 +106,18 @@ inline bool YGFlexDirectionIsRow(const YGFlexDirection flexDirection) {
flexDirection == YGFlexDirectionRowReverse; flexDirection == YGFlexDirectionRowReverse;
} }
inline YGFloatOptional YGResolveValue( inline YGFloatOptional YGResolveValue(const YGValue value, const float ownerSize) {
const YGValue value,
const float ownerSize) {
switch (value.unit) { switch (value.unit) {
case YGUnitUndefined:
case YGUnitAuto:
return YGFloatOptional();
case YGUnitPoint: case YGUnitPoint:
return YGFloatOptional{value.value}; return YGFloatOptional(value.value);
case YGUnitPercent: case YGUnitPercent:
return YGFloatOptional{value.value * ownerSize * 0.01f}; return YGFloatOptional(
default: static_cast<float>(value.value * ownerSize * 0.01));
return YGFloatOptional{};
} }
return YGFloatOptional();
} }
inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) { inline bool YGFlexDirectionIsColumn(const YGFlexDirection flexDirection) {
@@ -123,7 +139,7 @@ inline YGFlexDirection YGResolveFlexDirection(
return flexDirection; return flexDirection;
} }
inline YGFloatOptional YGResolveValueMargin( static inline YGFloatOptional YGResolveValueMargin(
const YGValue value, const YGValue value,
const float ownerSize) { const float ownerSize) {
return value.unit == YGUnitAuto ? YGFloatOptional(0) return value.unit == YGUnitAuto ? YGFloatOptional(0)

83
yoga/YGFloatOptional.cpp Normal file
View File

@@ -0,0 +1,83 @@
/**
* 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 "YGFloatOptional.h"
#include <cstdlib>
#include <iostream>
#include "Yoga.h"
#include "Yoga-internal.h"
using namespace facebook;
YGFloatOptional::YGFloatOptional(float value) {
if (yoga::isUndefined(value)) {
isUndefined_ = true;
value_ = 0;
} else {
value_ = value;
isUndefined_ = false;
}
}
float YGFloatOptional::getValue() const {
if (isUndefined_) {
// Abort, accessing a value of an undefined float optional
std::cerr << "Tried to get value of an undefined YGFloatOptional\n";
std::exit(EXIT_FAILURE);
}
return value_;
}
bool YGFloatOptional::operator==(const YGFloatOptional& op) const {
if (isUndefined_ == op.isUndefined()) {
return isUndefined_ || value_ == op.getValue();
}
return false;
}
bool YGFloatOptional::operator!=(const YGFloatOptional& op) const {
return !(*this == op);
}
bool YGFloatOptional::operator==(float val) const {
if (yoga::isUndefined(val) == isUndefined_) {
return isUndefined_ || val == value_;
}
return false;
}
bool YGFloatOptional::operator!=(float val) const {
return !(*this == val);
}
YGFloatOptional YGFloatOptional::operator+(const YGFloatOptional& op) {
if (!isUndefined_ && !op.isUndefined_) {
return YGFloatOptional(value_ + op.value_);
}
return YGFloatOptional();
}
bool YGFloatOptional::operator>(const YGFloatOptional& op) const {
if (isUndefined_ || op.isUndefined_) {
return false;
}
return value_ > op.value_;
}
bool YGFloatOptional::operator<(const YGFloatOptional& op) const {
if (isUndefined_ || op.isUndefined_) {
return false;
}
return value_ < op.value_;
}
bool YGFloatOptional::operator>=(const YGFloatOptional& op) const {
return *this == op || *this > op;
}
bool YGFloatOptional::operator<=(const YGFloatOptional& op) const {
return *this == op || *this < op;
}

View File

@@ -6,68 +6,38 @@
*/ */
#pragma once #pragma once
#include <limits>
#include "Yoga-internal.h"
struct YGFloatOptional { struct YGFloatOptional {
private: private:
float value_ = std::numeric_limits<float>::quiet_NaN(); float value_ = 0;
bool isUndefined_ = true;
public: public:
explicit constexpr YGFloatOptional(float value) : value_(value) {} explicit YGFloatOptional(float value);
constexpr YGFloatOptional() = default; YGFloatOptional() = default;
// returns the wrapped value, or a value x with YGIsUndefined(x) == true // Program will terminate if the value of an undefined is accessed. Please
constexpr float unwrap() const { // make sure to check if the optional is defined before calling this function.
return value_; // To check if float optional is defined, use `isUndefined()`.
float getValue() const;
// Sets the value of float optional, and thus isUndefined is assigned false.
void setValue(float val) {
value_ = val;
isUndefined_ = false;
} }
constexpr bool isUndefined() const { bool isUndefined() const {
// std::isnan is not constexpr return isUndefined_;
return !(value_ == value_);
} }
constexpr float orElse(float other) const { YGFloatOptional operator+(const YGFloatOptional& op);
return isUndefined() ? other : value_; bool operator>(const YGFloatOptional& op) const;
} bool operator<(const YGFloatOptional& op) const;
bool operator>=(const YGFloatOptional& op) const;
bool operator<=(const YGFloatOptional& op) const;
bool operator==(const YGFloatOptional& op) const;
bool operator!=(const YGFloatOptional& op) const;
template <typename Factory> bool operator==(float val) const;
constexpr float orElseGet(Factory&& f) const { bool operator!=(float val) const;
return isUndefined() ? f() : value_;
}
YGFloatOptional operator-() const {
return YGFloatOptional{-value_};
}
YGFloatOptional operator+(YGFloatOptional op) const {
return YGFloatOptional{value_ + op.value_};
}
YGFloatOptional operator-(YGFloatOptional op) const {
return YGFloatOptional{value_ - op.value_};
}
bool operator>(YGFloatOptional op) const {
return value_ > op.value_;
}
bool operator<(YGFloatOptional op) const {
return value_ < op.value_;
}
bool operator>=(YGFloatOptional op) const {
return *this > op || *this == op;
}
bool operator<=(YGFloatOptional op) const {
return *this < op || *this == op;
}
bool operator==(YGFloatOptional op) const {
return value_ == op.value_ || (isUndefined() && op.isUndefined());
}
bool operator!=(YGFloatOptional op) const {
return !(*this == op);
}
bool operator==(float val) const {
return value_ == val || (isUndefined() && yoga::isUndefined(val));
}
bool operator!=(float val) const {
return !(*this == val);
}
}; };

View File

@@ -175,7 +175,7 @@ void YGNode::setLayoutLastOwnerDirection(YGDirection direction) {
} }
void YGNode::setLayoutComputedFlexBasis( void YGNode::setLayoutComputedFlexBasis(
const YGFloatOptional computedFlexBasis) { const YGFloatOptional& computedFlexBasis) {
layout_.computedFlexBasis = computedFlexBasis; layout_.computedFlexBasis = computedFlexBasis;
} }
@@ -209,7 +209,11 @@ YGFloatOptional YGNode::relativePosition(
return getLeadingPosition(axis, axisSize); return getLeadingPosition(axis, axisSize);
} }
return -getTrailingPosition(axis, axisSize); YGFloatOptional trailingPosition = getTrailingPosition(axis, axisSize);
if (!trailingPosition.isUndefined()) {
trailingPosition.setValue(-1 * trailingPosition.getValue());
}
return trailingPosition;
} }
void YGNode::setPosition( void YGNode::setPosition(
@@ -232,18 +236,20 @@ void YGNode::setPosition(
relativePosition(crossAxis, crossSize); relativePosition(crossAxis, crossSize);
setLayoutPosition( setLayoutPosition(
(getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), YGUnwrapFloatOptional(
getLeadingMargin(mainAxis, ownerWidth) + relativePositionMain),
leading[mainAxis]); leading[mainAxis]);
setLayoutPosition( setLayoutPosition(
(getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain).unwrap(), YGUnwrapFloatOptional(
getTrailingMargin(mainAxis, ownerWidth) + relativePositionMain),
trailing[mainAxis]); trailing[mainAxis]);
setLayoutPosition( setLayoutPosition(
(getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross) YGUnwrapFloatOptional(
.unwrap(), getLeadingMargin(crossAxis, ownerWidth) + relativePositionCross),
leading[crossAxis]); leading[crossAxis]);
setLayoutPosition( setLayoutPosition(
(getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross) YGUnwrapFloatOptional(
.unwrap(), getTrailingMargin(crossAxis, ownerWidth) + relativePositionCross),
trailing[crossAxis]); trailing[crossAxis]);
} }
@@ -298,7 +304,7 @@ YGValue YGNode::resolveFlexBasisPtr() const {
if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) { if (flexBasis.unit != YGUnitAuto && flexBasis.unit != YGUnitUndefined) {
return flexBasis; return flexBasis;
} }
if (style_.flex > YGFloatOptional{0.0f}) { if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) {
return config_->useWebDefaults ? YGValueAuto : YGValueZero; return config_->useWebDefaults ? YGValueAuto : YGValueZero;
} }
return YGValueAuto; return YGValueAuto;
@@ -388,23 +394,27 @@ float YGNode::resolveFlexGrow() {
if (owner_ == nullptr) { if (owner_ == nullptr) {
return 0.0; return 0.0;
} }
if (!style_.flexGrow.isUndefined()) {
return style_.flexGrow.orElseGet( return style_.flexGrow.getValue();
[this] { return style_.flex.orElse(kDefaultFlexGrow); }); }
if (!style_.flex.isUndefined() && style_.flex.getValue() > 0.0f) {
return style_.flex.getValue();
}
return kDefaultFlexGrow;
} }
float YGNode::resolveFlexShrink() { float YGNode::resolveFlexShrink() {
if (owner_ == nullptr) { if (owner_ == nullptr) {
return 0.0; return 0.0;
} }
return style_.flexShrink.orElseGet([this] { if (!style_.flexShrink.isUndefined()) {
if (style_.flex < YGFloatOptional{0.0f} && !config_->useWebDefaults) { return style_.flexShrink.getValue();
return -style_.flex.unwrap();
} else {
return config_->useWebDefaults ? kWebDefaultFlexShrink
: kDefaultFlexShrink;
} }
}); if (!config_->useWebDefaults && !style_.flex.isUndefined() &&
style_.flex.getValue() < 0.0f) {
return -style_.flex.getValue();
}
return config_->useWebDefaults ? kWebDefaultFlexShrink : kDefaultFlexShrink;
} }
bool YGNode::isNodeFlexible() { bool YGNode::isNodeFlexible() {
@@ -443,9 +453,11 @@ float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) const {
YGFloatOptional YGNode::getLeadingPadding( YGFloatOptional YGNode::getLeadingPadding(
const YGFlexDirection axis, const YGFlexDirection axis,
const float widthSize) const { const float widthSize) const {
const YGFloatOptional paddingEdgeStart = const YGFloatOptional& paddingEdgeStart =
YGResolveValue(style_.padding[YGEdgeStart], widthSize); YGResolveValue(style_.padding[YGEdgeStart], widthSize);
if (YGFlexDirectionIsRow(axis) && paddingEdgeStart >= YGFloatOptional{0.0f}) { if (YGFlexDirectionIsRow(axis) &&
style_.padding[YGEdgeStart].unit != YGUnitUndefined &&
!paddingEdgeStart.isUndefined() && paddingEdgeStart.getValue() >= 0.0f) {
return paddingEdgeStart; return paddingEdgeStart;
} }
@@ -458,10 +470,11 @@ YGFloatOptional YGNode::getLeadingPadding(
YGFloatOptional YGNode::getTrailingPadding( YGFloatOptional YGNode::getTrailingPadding(
const YGFlexDirection axis, const YGFlexDirection axis,
const float widthSize) const { const float widthSize) const {
const YGFloatOptional paddingEdgeEnd = if (YGFlexDirectionIsRow(axis) &&
YGResolveValue(style_.padding[YGEdgeEnd], widthSize); style_.padding[YGEdgeEnd].unit != YGUnitUndefined &&
if (YGFlexDirectionIsRow(axis) && paddingEdgeEnd >= YGFloatOptional{0.0f}) { !YGResolveValue(style_.padding[YGEdgeEnd], widthSize).isUndefined() &&
return paddingEdgeEnd; YGResolveValue(style_.padding[YGEdgeEnd], widthSize).getValue() >= 0.0f) {
return YGResolveValue(style_.padding[YGEdgeEnd], widthSize);
} }
YGFloatOptional resolvedValue = YGResolveValue( YGFloatOptional resolvedValue = YGResolveValue(

View File

@@ -235,7 +235,7 @@ struct YGNode {
void setDirty(bool isDirty); void setDirty(bool isDirty);
void setLayoutLastOwnerDirection(YGDirection direction); void setLayoutLastOwnerDirection(YGDirection direction);
void setLayoutComputedFlexBasis(const YGFloatOptional computedFlexBasis); void setLayoutComputedFlexBasis(const YGFloatOptional& computedFlexBasis);
void setLayoutComputedFlexBasisGeneration( void setLayoutComputedFlexBasisGeneration(
uint32_t computedFlexBasisGeneration); uint32_t computedFlexBasisGeneration);
void setLayoutMeasuredDimension(float measuredDimension, int index); void setLayoutMeasuredDimension(float measuredDimension, int index);

View File

@@ -14,9 +14,9 @@ namespace facebook {
namespace yoga { namespace yoga {
typedef std::string string; typedef std::string string;
static void indent(string& base, uint32_t level) { static void indent(string* base, uint32_t level) {
for (uint32_t i = 0; i < level; ++i) { for (uint32_t i = 0; i < level; ++i) {
base.append(" "); base->append(" ");
} }
} }
@@ -25,7 +25,7 @@ static bool areFourValuesEqual(const std::array<YGValue, YGEdgeCount>& four) {
YGValueEqual(four[0], four[3]); YGValueEqual(four[0], four[3]);
} }
static void appendFormatedString(string& str, const char* fmt, ...) { static void appendFormatedString(string* str, const char* fmt, ...) {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
va_list argsCopy; va_list argsCopy;
@@ -35,25 +35,25 @@ static void appendFormatedString(string& str, const char* fmt, ...) {
vsnprintf(buf.data(), buf.size(), fmt, argsCopy); vsnprintf(buf.data(), buf.size(), fmt, argsCopy);
va_end(argsCopy); va_end(argsCopy);
string result = string(buf.begin(), buf.end() - 1); string result = string(buf.begin(), buf.end() - 1);
str.append(result); str->append(result);
} }
static void appendFloatOptionalIfDefined( static void appendFloatOptionalIfDefined(
string& base, string* base,
const string key, const string key,
const YGFloatOptional num) { const YGFloatOptional num) {
if (!num.isUndefined()) { if (!num.isUndefined()) {
appendFormatedString(base, "%s: %g; ", key.c_str(), num.unwrap()); appendFormatedString(base, "%s: %g; ", key.c_str(), num.getValue());
} }
} }
static void appendNumberIfNotUndefined( static void appendNumberIfNotUndefined(
string& base, string* base,
const string key, const string key,
const YGValue number) { const YGValue number) {
if (number.unit != YGUnitUndefined) { if (number.unit != YGUnitUndefined) {
if (number.unit == YGUnitAuto) { if (number.unit == YGUnitAuto) {
base.append(key + ": auto; "); base->append(key + ": auto; ");
} else { } else {
string unit = number.unit == YGUnitPoint ? "px" : "%%"; string unit = number.unit == YGUnitPoint ? "px" : "%%";
appendFormatedString( appendFormatedString(
@@ -63,23 +63,24 @@ static void appendNumberIfNotUndefined(
} }
static void static void
appendNumberIfNotAuto(string& base, const string& key, const YGValue number) { appendNumberIfNotAuto(string* base, const string& key, const YGValue number) {
if (number.unit != YGUnitAuto) { if (number.unit != YGUnitAuto) {
appendNumberIfNotUndefined(base, key, number); appendNumberIfNotUndefined(base, key, number);
} }
} }
static void static void
appendNumberIfNotZero(string& base, const string& str, const YGValue number) { appendNumberIfNotZero(string* base, const string& str, const YGValue number) {
if (number.unit == YGUnitAuto) { if (number.unit == YGUnitAuto) {
base.append(str + ": auto; "); base->append(str + ": auto; ");
} else if (!YGFloatsEqual(number.value, 0)) { } else if (!YGFloatsEqual(number.value, 0)) {
appendNumberIfNotUndefined(base, str, number); appendNumberIfNotUndefined(base, str, number);
} }
} }
static void appendEdges( static void appendEdges(
string& base, string* base,
const string& key, const string& key,
const std::array<YGValue, YGEdgeCount>& edges) { const std::array<YGValue, YGEdgeCount>& edges) {
if (areFourValuesEqual(edges)) { if (areFourValuesEqual(edges)) {
@@ -93,7 +94,7 @@ static void appendEdges(
} }
static void appendEdgeIfNotUndefined( static void appendEdgeIfNotUndefined(
string& base, string* base,
const string& str, const string& str,
const std::array<YGValue, YGEdgeCount>& edges, const std::array<YGValue, YGEdgeCount>& edges,
const YGEdge edge) { const YGEdge edge) {
@@ -102,7 +103,7 @@ static void appendEdgeIfNotUndefined(
} }
void YGNodeToString( void YGNodeToString(
std::string& str, std::string* str,
YGNodeRef node, YGNodeRef node,
YGPrintOptions options, YGPrintOptions options,
uint32_t level) { uint32_t level) {

View File

@@ -13,7 +13,7 @@ namespace facebook {
namespace yoga { namespace yoga {
void YGNodeToString( void YGNodeToString(
std::string& str, std::string* str,
YGNodeRef node, YGNodeRef node,
YGPrintOptions options, YGPrintOptions options,
uint32_t level); uint32_t level);

View File

@@ -8,8 +8,8 @@
// Yoga specific properties, not compatible with flexbox specification // Yoga specific properties, not compatible with flexbox specification
bool YGStyle::operator==(const YGStyle& style) { bool YGStyle::operator==(const YGStyle& style) {
return ( bool areNonFloatValuesEqual = direction == style.direction &&
direction == style.direction && flexDirection == style.flexDirection && flexDirection == style.flexDirection &&
justifyContent == style.justifyContent && justifyContent == style.justifyContent &&
alignContent == style.alignContent && alignItems == style.alignItems && alignContent == style.alignContent && alignItems == style.alignItems &&
alignSelf == style.alignSelf && positionType == style.positionType && alignSelf == style.alignSelf && positionType == style.positionType &&
@@ -21,7 +21,34 @@ bool YGStyle::operator==(const YGStyle& style) {
YGValueArrayEqual(border, style.border) && YGValueArrayEqual(border, style.border) &&
YGValueArrayEqual(dimensions, style.dimensions) && YGValueArrayEqual(dimensions, style.dimensions) &&
YGValueArrayEqual(minDimensions, style.minDimensions) && YGValueArrayEqual(minDimensions, style.minDimensions) &&
YGValueArrayEqual(maxDimensions, style.maxDimensions) && YGValueArrayEqual(maxDimensions, style.maxDimensions);
flex == style.flex && flexGrow == style.flexGrow &&
flexShrink == style.flexShrink && aspectRatio == style.aspectRatio); areNonFloatValuesEqual =
areNonFloatValuesEqual && flex.isUndefined() == style.flex.isUndefined();
if (areNonFloatValuesEqual && !flex.isUndefined() &&
!style.flex.isUndefined()) {
areNonFloatValuesEqual =
areNonFloatValuesEqual && flex.getValue() == style.flex.getValue();
}
areNonFloatValuesEqual = areNonFloatValuesEqual &&
flexGrow.isUndefined() == style.flexGrow.isUndefined();
if (areNonFloatValuesEqual && !flexGrow.isUndefined()) {
areNonFloatValuesEqual = areNonFloatValuesEqual &&
flexGrow.getValue() == style.flexGrow.getValue();
}
areNonFloatValuesEqual = areNonFloatValuesEqual &&
flexShrink.isUndefined() == style.flexShrink.isUndefined();
if (areNonFloatValuesEqual && !style.flexShrink.isUndefined()) {
areNonFloatValuesEqual = areNonFloatValuesEqual &&
flexShrink.getValue() == style.flexShrink.getValue();
}
if (!(aspectRatio.isUndefined() && style.aspectRatio.isUndefined())) {
areNonFloatValuesEqual = areNonFloatValuesEqual &&
aspectRatio.getValue() == style.aspectRatio.getValue();
}
return areNonFloatValuesEqual;
} }

View File

@@ -30,16 +30,16 @@ constexpr std::array<YGValue, 2> kYGDefaultDimensionValuesUnit = {
struct YGStyle { struct YGStyle {
using Dimensions = std::array<YGValue, 2>; using Dimensions = std::array<YGValue, 2>;
YGDirection direction : 2; YGDirection direction = YGDirectionInherit;
YGFlexDirection flexDirection : 2; YGFlexDirection flexDirection = YGFlexDirectionColumn;
YGJustify justifyContent : 3; YGJustify justifyContent = YGJustifyFlexStart;
YGAlign alignContent : 3; YGAlign alignContent = YGAlignFlexStart;
YGAlign alignItems : 3; YGAlign alignItems = YGAlignStretch;
YGAlign alignSelf : 3; YGAlign alignSelf = YGAlignAuto;
YGPositionType positionType : 1; YGPositionType positionType = YGPositionTypeRelative;
YGWrap flexWrap : 2; YGWrap flexWrap = YGWrapNoWrap;
YGOverflow overflow : 2; YGOverflow overflow = YGOverflowVisible;
YGDisplay display : 1; YGDisplay display = YGDisplayFlex;
YGFloatOptional flex = {}; YGFloatOptional flex = {};
YGFloatOptional flexGrow = {}; YGFloatOptional flexGrow = {};
YGFloatOptional flexShrink = {}; YGFloatOptional flexShrink = {};
@@ -54,17 +54,7 @@ struct YGStyle {
// Yoga specific properties, not compatible with flexbox specification // Yoga specific properties, not compatible with flexbox specification
YGFloatOptional aspectRatio = {}; YGFloatOptional aspectRatio = {};
YGStyle() YGStyle() = default;
: direction(YGDirectionInherit),
flexDirection(YGFlexDirectionColumn),
justifyContent(YGJustifyFlexStart),
alignContent(YGAlignFlexStart),
alignItems(YGAlignStretch),
alignSelf(YGAlignAuto),
positionType(YGPositionTypeRelative),
flexWrap(YGWrapNoWrap),
overflow(YGOverflowVisible),
display(YGDisplayFlex) {}
bool operator==(const YGStyle& style); bool operator==(const YGStyle& style);
bool operator!=(YGStyle style) { bool operator!=(YGStyle style) {

View File

@@ -1,11 +0,0 @@
/**
* 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 "YGValue.h"
const YGValue YGValueZero = {0, YGUnitPoint};
const YGValue YGValueUndefined = {YGUndefined, YGUnitUndefined};
const YGValue YGValueAuto = {YGUndefined, YGUnitAuto};

View File

@@ -1,56 +0,0 @@
/**
* 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.
*/
#pragma once
#include <math.h>
#include "YGEnums.h"
#include "YGMacros.h"
YG_EXTERN_C_BEGIN
// Not defined in MSVC++
#ifndef NAN
static const uint32_t __nan = 0x7fc00000;
#define NAN (*(const float*)__nan)
#endif
#define YGUndefined NAN
typedef struct YGValue {
float value;
YGUnit unit;
} YGValue;
extern const YGValue YGValueAuto;
extern const YGValue YGValueUndefined;
extern const YGValue YGValueZero;
YG_EXTERN_C_END
#ifdef __cplusplus
inline bool operator==(const YGValue& lhs, const YGValue& rhs) {
if (lhs.unit != rhs.unit) {
return false;
}
switch (lhs.unit) {
case YGUnitUndefined:
case YGUnitAuto:
return true;
case YGUnitPoint:
case YGUnitPercent:
default:
return lhs.value == rhs.value;
}
}
inline bool operator!=(const YGValue& lhs, const YGValue& rhs) {
return !(lhs == rhs);
}
#endif

View File

@@ -27,7 +27,15 @@ namespace facebook {
namespace yoga { namespace yoga {
inline bool isUndefined(float value) { inline bool isUndefined(float value) {
return std::isnan(value); // Value of a float in the case of it being not defined is 10.1E20. Earlier
// it used to be NAN, the benefit of which was that if NAN is involved in any
// mathematical expression the result was NAN. But since we want to have
// `-ffast-math` flag being used by compiler which assumes that the floating
// point values are not NAN and Inf, we represent YGUndefined as 10.1E20. But
// now if YGUndefined is involved in any mathematical operations this
// value(10.1E20) would change. So the following check makes sure that if the
// value is outside a range (-10E8, 10E8) then it is undefined.
return value >= 10E8 || value <= -10E8;
} }
} // namespace yoga } // namespace yoga

File diff suppressed because it is too large Load Diff

View File

@@ -17,9 +17,17 @@
#include <stdbool.h> #include <stdbool.h>
#endif #endif
/** Large positive number signifies that the property(float) is undefined.
*Earlier we used to have YGundefined as NAN, but the downside of this is that
*we can't use -ffast-math compiler flag as it assumes all floating-point
*calculation involve and result into finite numbers. For more information
*regarding -ffast-math compiler flag in clang, have a look at
*https://clang.llvm.org/docs/UsersManual.html#cmdoption-ffast-math
**/
#define YGUndefined 10E20F
#include "YGEnums.h" #include "YGEnums.h"
#include "YGMacros.h" #include "YGMacros.h"
#include "YGValue.h"
YG_EXTERN_C_BEGIN YG_EXTERN_C_BEGIN
@@ -28,6 +36,25 @@ typedef struct YGSize {
float height; float height;
} YGSize; } YGSize;
typedef struct YGValue {
float value;
YGUnit unit;
} YGValue;
extern const YGValue YGValueUndefined;
extern const YGValue YGValueAuto;
#ifdef __cplusplus
YG_EXTERN_C_END
extern bool operator==(const YGValue& lhs, const YGValue& rhs);
extern bool operator!=(const YGValue& lhs, const YGValue& rhs);
YG_EXTERN_C_BEGIN
#endif
typedef struct YGConfig* YGConfigRef; typedef struct YGConfig* YGConfigRef;
typedef struct YGNode* YGNodeRef; typedef struct YGNode* YGNodeRef;