mirror of
https://github.com/status-im/react-native.git
synced 2025-01-27 01:40:08 +00:00
Change NaN with large number
Reviewed By: emilsjolander Differential Revision: D6969537 fbshipit-source-id: bdc09eaf703e0d313ca65c25a4fb44c99203d9bf
This commit is contained in:
parent
af9d6479e5
commit
d174ab8a7a
@ -9,12 +9,29 @@ package com.facebook.yoga;
|
||||
|
||||
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 shouldUseFastMath = false;
|
||||
|
||||
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) {
|
||||
|
@ -652,11 +652,11 @@ public class YogaNode implements Cloneable {
|
||||
}
|
||||
|
||||
return mMeasureFunction.measure(
|
||||
this,
|
||||
width,
|
||||
YogaMeasureMode.fromInt(widthMode),
|
||||
height,
|
||||
YogaMeasureMode.fromInt(heightMode));
|
||||
this,
|
||||
width,
|
||||
YogaMeasureMode.fromInt(widthMode),
|
||||
height,
|
||||
YogaMeasureMode.fromInt(heightMode));
|
||||
}
|
||||
|
||||
private native void jni_YGNodeSetHasBaselineFunc(long nativePointer, boolean hasMeasureFunc);
|
||||
|
@ -337,13 +337,15 @@ struct JYogaValue : public JavaClass<JYogaValue> {
|
||||
}
|
||||
};
|
||||
|
||||
#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \
|
||||
javatype jni_YGNodeStyleGet##name(alias_ref<jobject>, jlong nativePointer) { \
|
||||
return (javatype) YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \
|
||||
} \
|
||||
\
|
||||
void jni_YGNodeStyleSet##name(alias_ref<jobject>, jlong nativePointer, javatype value) { \
|
||||
YGNodeStyleSet##name(_jlong2YGNodeRef(nativePointer), static_cast<type>(value)); \
|
||||
#define YG_NODE_JNI_STYLE_PROP(javatype, type, name) \
|
||||
javatype jni_YGNodeStyleGet##name(alias_ref<jobject>, jlong nativePointer) { \
|
||||
return (javatype)YGNodeStyleGet##name(_jlong2YGNodeRef(nativePointer)); \
|
||||
} \
|
||||
\
|
||||
void jni_YGNodeStyleSet##name( \
|
||||
alias_ref<jobject>, jlong nativePointer, javatype value) { \
|
||||
YGNodeStyleSet##name( \
|
||||
_jlong2YGNodeRef(nativePointer), static_cast<type>(value)); \
|
||||
}
|
||||
|
||||
#define YG_NODE_JNI_STYLE_UNIT_PROP(name) \
|
||||
|
@ -15,15 +15,37 @@ YGFlexDirection YGFlexDirectionCross(
|
||||
: YGFlexDirectionColumn;
|
||||
}
|
||||
|
||||
float YGFloatMax(const float a, const float b) {
|
||||
if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
|
||||
return fmaxf(a, b);
|
||||
}
|
||||
return YGFloatIsUndefined(a) ? b : a;
|
||||
}
|
||||
|
||||
float YGFloatMin(const float a, const float b) {
|
||||
if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
|
||||
return fminf(a, b);
|
||||
}
|
||||
|
||||
return YGFloatIsUndefined(a) ? b : a;
|
||||
}
|
||||
|
||||
bool YGValueEqual(const YGValue a, const YGValue b) {
|
||||
if (a.unit != b.unit) {
|
||||
return false;
|
||||
}
|
||||
|
||||
if (a.unit == YGUnitUndefined ||
|
||||
(std::isnan(a.value) && std::isnan(b.value))) {
|
||||
(YGFloatIsUndefined(a.value) && YGFloatIsUndefined(b.value))) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return fabs(a.value - b.value) < 0.0001f;
|
||||
}
|
||||
|
||||
bool YGFloatsEqual(const float a, const float b) {
|
||||
if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
|
||||
return fabs(a - b) < 0.0001f;
|
||||
}
|
||||
return YGFloatIsUndefined(a) && YGFloatIsUndefined(b);
|
||||
}
|
||||
|
@ -54,6 +54,38 @@ struct YGCollectFlexItemsRowValues {
|
||||
|
||||
bool YGValueEqual(const YGValue a, const YGValue b);
|
||||
|
||||
// This custom float equality function returns true if either absolute
|
||||
// difference between two floats is less than 0.0001f or both are undefined.
|
||||
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);
|
||||
|
||||
// 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);
|
||||
|
||||
// This custom float comparision function compares the array of float with
|
||||
// YGFloatsEqual, as the default float comparision operator will not work(Look
|
||||
// at the comments of YGFloatsEqual function).
|
||||
template <std::size_t size>
|
||||
bool YGFloatArrayEqual(
|
||||
const std::array<float, size>& val1,
|
||||
const std::array<float, size>& val2) {
|
||||
bool areEqual = true;
|
||||
for (std::size_t i = 0; i < size && areEqual; ++i) {
|
||||
areEqual = YGFloatsEqual(val1[i], val2[i]);
|
||||
}
|
||||
return areEqual;
|
||||
}
|
||||
|
||||
YGFlexDirection YGFlexDirectionCross(
|
||||
const YGFlexDirection flexDirection,
|
||||
const YGDirection direction);
|
||||
@ -71,7 +103,7 @@ inline float YGResolveValue(const YGValue value, const float parentSize) {
|
||||
case YGUnitPoint:
|
||||
return value.value;
|
||||
case YGUnitPercent:
|
||||
return value.value * parentSize / 100.0f;
|
||||
return value.value * parentSize * 0.01;
|
||||
}
|
||||
return YGUndefined;
|
||||
}
|
||||
|
@ -7,6 +7,7 @@
|
||||
* of patent rights can be found in the PATENTS file in the same directory.
|
||||
*/
|
||||
#include "YGLayout.h"
|
||||
#include "Utils.h"
|
||||
|
||||
const std::array<float, 2> kYGDefaultDimensionValues = {
|
||||
{YGUndefined, YGUndefined}};
|
||||
@ -31,9 +32,11 @@ YGLayout::YGLayout()
|
||||
doesLegacyStretchFlagAffectsLayout(false) {}
|
||||
|
||||
bool YGLayout::operator==(YGLayout layout) const {
|
||||
bool isEqual = position == layout.position &&
|
||||
dimensions == layout.dimensions && margin == layout.margin &&
|
||||
border == layout.border && padding == layout.padding &&
|
||||
bool isEqual = YGFloatArrayEqual(position, layout.position) &&
|
||||
YGFloatArrayEqual(dimensions, layout.dimensions) &&
|
||||
YGFloatArrayEqual(margin, layout.margin) &&
|
||||
YGFloatArrayEqual(border, layout.border) &&
|
||||
YGFloatArrayEqual(padding, layout.padding) &&
|
||||
direction == layout.direction && hadOverflow == layout.hadOverflow &&
|
||||
lastParentDirection == layout.lastParentDirection &&
|
||||
nextCachedMeasurementsIndex == layout.nextCachedMeasurementsIndex &&
|
||||
|
@ -624,26 +624,28 @@ bool YGNode::isNodeFlexible() {
|
||||
float YGNode::getLeadingBorder(const YGFlexDirection axis) {
|
||||
if (YGFlexDirectionIsRow(axis) &&
|
||||
style_.border[YGEdgeStart].unit != YGUnitUndefined &&
|
||||
!YGFloatIsUndefined(style_.border[YGEdgeStart].value) &&
|
||||
style_.border[YGEdgeStart].value >= 0.0f) {
|
||||
return style_.border[YGEdgeStart].value;
|
||||
}
|
||||
|
||||
return fmaxf(
|
||||
YGComputedEdgeValue(style_.border, leading[axis], &YGValueZero)->value,
|
||||
0.0f);
|
||||
float computedEdgeValue =
|
||||
YGComputedEdgeValue(style_.border, leading[axis], &YGValueZero)->value;
|
||||
return YGFloatMax(computedEdgeValue, 0.0f);
|
||||
}
|
||||
|
||||
float YGNode::getTrailingBorder(const YGFlexDirection flexDirection) {
|
||||
if (YGFlexDirectionIsRow(flexDirection) &&
|
||||
style_.border[YGEdgeEnd].unit != YGUnitUndefined &&
|
||||
!YGFloatIsUndefined(style_.border[YGEdgeEnd].value) &&
|
||||
style_.border[YGEdgeEnd].value >= 0.0f) {
|
||||
return style_.border[YGEdgeEnd].value;
|
||||
}
|
||||
|
||||
return fmaxf(
|
||||
float computedEdgeValue =
|
||||
YGComputedEdgeValue(style_.border, trailing[flexDirection], &YGValueZero)
|
||||
->value,
|
||||
0.0f);
|
||||
->value;
|
||||
return YGFloatMax(computedEdgeValue, 0.0f);
|
||||
}
|
||||
|
||||
float YGNode::getLeadingPadding(
|
||||
@ -651,14 +653,16 @@ float YGNode::getLeadingPadding(
|
||||
const float widthSize) {
|
||||
if (YGFlexDirectionIsRow(axis) &&
|
||||
style_.padding[YGEdgeStart].unit != YGUnitUndefined &&
|
||||
YGResolveValue(style_.padding[YGEdgeStart], widthSize) >= 0.0f) {
|
||||
!YGFloatIsUndefined(
|
||||
YGResolveValue(style_.padding[YGEdgeStart], widthSize)) &&
|
||||
YGResolveValue(style_.padding[YGEdgeStart], widthSize) > 0.0f) {
|
||||
return YGResolveValue(style_.padding[YGEdgeStart], widthSize);
|
||||
}
|
||||
return fmaxf(
|
||||
YGResolveValue(
|
||||
*YGComputedEdgeValue(style_.padding, leading[axis], &YGValueZero),
|
||||
widthSize),
|
||||
0.0f);
|
||||
|
||||
float resolvedValue = YGResolveValue(
|
||||
*YGComputedEdgeValue(style_.padding, leading[axis], &YGValueZero),
|
||||
widthSize);
|
||||
return YGFloatMax(resolvedValue, 0.0f);
|
||||
}
|
||||
|
||||
float YGNode::getTrailingPadding(
|
||||
@ -666,14 +670,17 @@ float YGNode::getTrailingPadding(
|
||||
const float widthSize) {
|
||||
if (YGFlexDirectionIsRow(axis) &&
|
||||
style_.padding[YGEdgeEnd].unit != YGUnitUndefined &&
|
||||
!YGFloatIsUndefined(
|
||||
YGResolveValue(style_.padding[YGEdgeEnd], widthSize)) &&
|
||||
YGResolveValue(style_.padding[YGEdgeEnd], widthSize) >= 0.0f) {
|
||||
return YGResolveValue(style_.padding[YGEdgeEnd], widthSize);
|
||||
}
|
||||
return fmaxf(
|
||||
YGResolveValue(
|
||||
*YGComputedEdgeValue(style_.padding, trailing[axis], &YGValueZero),
|
||||
widthSize),
|
||||
0.0f);
|
||||
|
||||
float resolvedValue = YGResolveValue(
|
||||
*YGComputedEdgeValue(style_.padding, trailing[axis], &YGValueZero),
|
||||
widthSize);
|
||||
|
||||
return YGFloatMax(resolvedValue, 0.0f);
|
||||
}
|
||||
|
||||
float YGNode::getLeadingPaddingAndBorder(
|
||||
|
@ -70,21 +70,23 @@ bool YGStyle::operator==(const YGStyle& style) {
|
||||
YGValueArrayEqual(minDimensions, style.minDimensions) &&
|
||||
YGValueArrayEqual(maxDimensions, style.maxDimensions);
|
||||
|
||||
if (!(std::isnan(flex) && std::isnan(style.flex))) {
|
||||
if (!(YGFloatIsUndefined(flex) && YGFloatIsUndefined(style.flex))) {
|
||||
areNonFloatValuesEqual = areNonFloatValuesEqual && flex == style.flex;
|
||||
}
|
||||
|
||||
if (!(std::isnan(flexGrow) && std::isnan(style.flexGrow))) {
|
||||
if (!(YGFloatIsUndefined(flexGrow) && YGFloatIsUndefined(style.flexGrow))) {
|
||||
areNonFloatValuesEqual =
|
||||
areNonFloatValuesEqual && flexGrow == style.flexGrow;
|
||||
}
|
||||
|
||||
if (!(std::isnan(flexShrink) && std::isnan(style.flexShrink))) {
|
||||
if (!(YGFloatIsUndefined(flexShrink) &&
|
||||
YGFloatIsUndefined(style.flexShrink))) {
|
||||
areNonFloatValuesEqual =
|
||||
areNonFloatValuesEqual && flexShrink == style.flexShrink;
|
||||
}
|
||||
|
||||
if (!(std::isnan(aspectRatio) && std::isnan(style.aspectRatio))) {
|
||||
if (!(YGFloatIsUndefined(aspectRatio) &&
|
||||
YGFloatIsUndefined(style.aspectRatio))) {
|
||||
areNonFloatValuesEqual =
|
||||
areNonFloatValuesEqual && aspectRatio == style.aspectRatio;
|
||||
}
|
||||
|
@ -62,19 +62,20 @@ struct YGCachedMeasurement {
|
||||
bool isEqual = widthMeasureMode == measurement.widthMeasureMode &&
|
||||
heightMeasureMode == measurement.heightMeasureMode;
|
||||
|
||||
if (!std::isnan(availableWidth) ||
|
||||
!std::isnan(measurement.availableWidth)) {
|
||||
if (!YGFloatIsUndefined(availableWidth) ||
|
||||
!YGFloatIsUndefined(measurement.availableWidth)) {
|
||||
isEqual = isEqual && availableWidth == measurement.availableWidth;
|
||||
}
|
||||
if (!std::isnan(availableHeight) ||
|
||||
!std::isnan(measurement.availableHeight)) {
|
||||
if (!YGFloatIsUndefined(availableHeight) ||
|
||||
!YGFloatIsUndefined(measurement.availableHeight)) {
|
||||
isEqual = isEqual && availableHeight == measurement.availableHeight;
|
||||
}
|
||||
if (!std::isnan(computedWidth) || !std::isnan(measurement.computedWidth)) {
|
||||
if (!YGFloatIsUndefined(computedWidth) ||
|
||||
!YGFloatIsUndefined(measurement.computedWidth)) {
|
||||
isEqual = isEqual && computedWidth == measurement.computedWidth;
|
||||
}
|
||||
if (!std::isnan(computedHeight) ||
|
||||
!std::isnan(measurement.computedHeight)) {
|
||||
if (!YGFloatIsUndefined(computedHeight) ||
|
||||
!YGFloatIsUndefined(measurement.computedHeight)) {
|
||||
isEqual = isEqual && computedHeight == measurement.computedHeight;
|
||||
}
|
||||
|
||||
|
@ -19,7 +19,10 @@
|
||||
/* define fmaxf if < VC12 */
|
||||
#if _MSC_VER < 1800
|
||||
__forceinline const float fmaxf(const float a, const float b) {
|
||||
return (a > b) ? a : b;
|
||||
if (!YGFloatIsUndefined(a) && !YGFloatIsUndefined(b)) {
|
||||
return (a > b) ? a : b;
|
||||
}
|
||||
return YGFloatIsUndefined(a) ? b : a;
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
@ -118,7 +121,15 @@ static int YGDefaultLog(const YGConfigRef config,
|
||||
#endif
|
||||
|
||||
bool YGFloatIsUndefined(const 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;
|
||||
}
|
||||
|
||||
const YGValue* YGComputedEdgeValue(
|
||||
@ -788,13 +799,6 @@ bool YGLayoutNodeInternal(const YGNodeRef node,
|
||||
const char *reason,
|
||||
const YGConfigRef config);
|
||||
|
||||
bool YGFloatsEqual(const float a, const float b) {
|
||||
if (YGFloatIsUndefined(a)) {
|
||||
return YGFloatIsUndefined(b);
|
||||
}
|
||||
return fabs(a - b) < 0.0001f;
|
||||
}
|
||||
|
||||
static void YGNodePrintInternal(const YGNodeRef node,
|
||||
const YGPrintOptions options) {
|
||||
std::string str;
|
||||
@ -909,12 +913,15 @@ static inline float YGNodeDimWithMargin(const YGNodeRef node,
|
||||
static inline bool YGNodeIsStyleDimDefined(const YGNodeRef node,
|
||||
const YGFlexDirection axis,
|
||||
const float parentSize) {
|
||||
bool isUndefined =
|
||||
YGFloatIsUndefined(node->getResolvedDimension(dim[axis]).value);
|
||||
return !(
|
||||
node->getResolvedDimension(dim[axis]).unit == YGUnitAuto ||
|
||||
node->getResolvedDimension(dim[axis]).unit == YGUnitUndefined ||
|
||||
(node->getResolvedDimension(dim[axis]).unit == YGUnitPoint &&
|
||||
node->getResolvedDimension(dim[axis]).value < 0.0f) ||
|
||||
!isUndefined && node->getResolvedDimension(dim[axis]).value < 0.0f) ||
|
||||
(node->getResolvedDimension(dim[axis]).unit == YGUnitPercent &&
|
||||
!isUndefined &&
|
||||
(node->getResolvedDimension(dim[axis]).value < 0.0f ||
|
||||
YGFloatIsUndefined(parentSize))));
|
||||
}
|
||||
@ -964,8 +971,9 @@ static inline float YGNodeBoundAxis(const YGNodeRef node,
|
||||
const float value,
|
||||
const float axisSize,
|
||||
const float widthSize) {
|
||||
return fmaxf(YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize),
|
||||
YGNodePaddingAndBorderForAxis(node, axis, widthSize));
|
||||
return YGFloatMax(
|
||||
YGNodeBoundAxisWithinMinAndMax(node, axis, value, axisSize),
|
||||
YGNodePaddingAndBorderForAxis(node, axis, widthSize));
|
||||
}
|
||||
|
||||
static void YGNodeSetChildTrailingPosition(const YGNodeRef node,
|
||||
@ -1035,19 +1043,19 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node,
|
||||
child->getConfig(), YGExperimentalFeatureWebFlexBasis) &&
|
||||
child->getLayout().computedFlexBasisGeneration !=
|
||||
gCurrentGenerationCount)) {
|
||||
child->setLayoutComputedFlexBasis(fmaxf(
|
||||
child->setLayoutComputedFlexBasis(YGFloatMax(
|
||||
resolvedFlexBasis,
|
||||
YGNodePaddingAndBorderForAxis(child, mainAxis, parentWidth)));
|
||||
}
|
||||
} else if (isMainAxisRow && isRowStyleDimDefined) {
|
||||
// The width is definite, so use that as the flex basis.
|
||||
child->setLayoutComputedFlexBasis(fmaxf(
|
||||
child->setLayoutComputedFlexBasis(YGFloatMax(
|
||||
YGResolveValue(
|
||||
child->getResolvedDimension(YGDimensionWidth), parentWidth),
|
||||
YGNodePaddingAndBorderForAxis(child, YGFlexDirectionRow, parentWidth)));
|
||||
} else if (!isMainAxisRow && isColumnStyleDimDefined) {
|
||||
// The height is definite, so use that as the flex basis.
|
||||
child->setLayoutComputedFlexBasis(fmaxf(
|
||||
child->setLayoutComputedFlexBasis(YGFloatMax(
|
||||
YGResolveValue(
|
||||
child->getResolvedDimension(YGDimensionHeight), parentHeight),
|
||||
YGNodePaddingAndBorderForAxis(
|
||||
@ -1162,7 +1170,7 @@ static void YGNodeComputeFlexBasisForChild(const YGNodeRef node,
|
||||
"measure",
|
||||
config);
|
||||
|
||||
child->setLayoutComputedFlexBasis(fmaxf(
|
||||
child->setLayoutComputedFlexBasis(YGFloatMax(
|
||||
child->getLayout().measuredDimensions[dim[mainAxis]],
|
||||
YGNodePaddingAndBorderForAxis(child, mainAxis, parentWidth)));
|
||||
}
|
||||
@ -1252,7 +1260,8 @@ static void YGNodeAbsoluteLayoutChild(const YGNodeRef node,
|
||||
// If the size of the parent is defined then try to constrain the absolute child to that size
|
||||
// as well. This allows text within the absolute child to wrap to the size of its parent.
|
||||
// This is the same behavior as many browsers implement.
|
||||
if (!isMainAxisRow && YGFloatIsUndefined(childWidth) && widthMode != YGMeasureModeUndefined &&
|
||||
if (!isMainAxisRow && YGFloatIsUndefined(childWidth) &&
|
||||
widthMode != YGMeasureModeUndefined && !YGFloatIsUndefined(width) &&
|
||||
width > 0) {
|
||||
childWidth = width;
|
||||
childWidthMeasureMode = YGMeasureModeAtMost;
|
||||
@ -1368,10 +1377,10 @@ static void YGNodeWithMeasureFuncSetMeasuredDimensions(const YGNodeRef node,
|
||||
// We want to make sure we don't call measure with negative size
|
||||
const float innerWidth = YGFloatIsUndefined(availableWidth)
|
||||
? availableWidth
|
||||
: fmaxf(0, availableWidth - marginAxisRow - paddingAndBorderAxisRow);
|
||||
: YGFloatMax(0, availableWidth - marginAxisRow - paddingAndBorderAxisRow);
|
||||
const float innerHeight = YGFloatIsUndefined(availableHeight)
|
||||
? availableHeight
|
||||
: fmaxf(
|
||||
: YGFloatMax(
|
||||
0, availableHeight - marginAxisColumn - paddingAndBorderAxisColumn);
|
||||
|
||||
if (widthMeasureMode == YGMeasureModeExactly &&
|
||||
@ -1474,9 +1483,12 @@ static bool YGNodeFixedSizeSetMeasuredDimensions(const YGNodeRef node,
|
||||
const YGMeasureMode heightMeasureMode,
|
||||
const float parentWidth,
|
||||
const float parentHeight) {
|
||||
if ((widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0.0f) ||
|
||||
(heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) ||
|
||||
(widthMeasureMode == YGMeasureModeExactly && heightMeasureMode == YGMeasureModeExactly)) {
|
||||
if ((!YGFloatIsUndefined(availableWidth) &&
|
||||
widthMeasureMode == YGMeasureModeAtMost && availableWidth <= 0.0f) ||
|
||||
(!YGFloatIsUndefined(availableHeight) &&
|
||||
heightMeasureMode == YGMeasureModeAtMost && availableHeight <= 0.0f) ||
|
||||
(widthMeasureMode == YGMeasureModeExactly &&
|
||||
heightMeasureMode == YGMeasureModeExactly)) {
|
||||
const float marginAxisColumn =
|
||||
node->getMarginForAxis(YGFlexDirectionColumn, parentWidth);
|
||||
const float marginAxisRow =
|
||||
@ -1545,13 +1557,16 @@ static float YGNodeCalculateAvailableInnerDim(
|
||||
// We want to make sure our available height does not violate min and max
|
||||
// constraints
|
||||
const float minInnerDim =
|
||||
YGResolveValue(node->getStyle().minDimensions[dimension], parentDim) -
|
||||
paddingAndBorder;
|
||||
YGFloatIsUndefined(YGResolveValue(
|
||||
node->getStyle().minDimensions[dimension], parentDim))
|
||||
? 0.0f
|
||||
: YGResolveValue(node->getStyle().minDimensions[dimension], parentDim) -
|
||||
paddingAndBorder;
|
||||
const float maxInnerDim =
|
||||
YGResolveValue(node->getStyle().maxDimensions[dimension], parentDim) -
|
||||
paddingAndBorder;
|
||||
availableInnerDim =
|
||||
fmaxf(fminf(availableInnerDim, maxInnerDim), minInnerDim);
|
||||
YGFloatMax(YGFloatMin(availableInnerDim, maxInnerDim), minInnerDim);
|
||||
}
|
||||
|
||||
return availableInnerDim;
|
||||
@ -1752,14 +1767,17 @@ static float YGDistributeFreeSpaceSecondPass(
|
||||
mainAxisParentSize);
|
||||
float updatedMainSize = childFlexBasis;
|
||||
|
||||
if (collectedFlexItemsValues.remainingFreeSpace < 0) {
|
||||
if (!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) &&
|
||||
collectedFlexItemsValues.remainingFreeSpace < 0) {
|
||||
flexShrinkScaledFactor =
|
||||
-currentRelativeChild->resolveFlexShrink() * childFlexBasis;
|
||||
// Is this child able to shrink?
|
||||
if (flexShrinkScaledFactor != 0) {
|
||||
float childSize;
|
||||
|
||||
if (collectedFlexItemsValues.totalFlexShrinkScaledFactors == 0) {
|
||||
if (!YGFloatIsUndefined(
|
||||
collectedFlexItemsValues.totalFlexShrinkScaledFactors) &&
|
||||
collectedFlexItemsValues.totalFlexShrinkScaledFactors == 0) {
|
||||
childSize = childFlexBasis + flexShrinkScaledFactor;
|
||||
} else {
|
||||
childSize = childFlexBasis +
|
||||
@ -1775,11 +1793,13 @@ static float YGDistributeFreeSpaceSecondPass(
|
||||
availableInnerMainDim,
|
||||
availableInnerWidth);
|
||||
}
|
||||
} else if (collectedFlexItemsValues.remainingFreeSpace > 0) {
|
||||
} else if (
|
||||
!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) &&
|
||||
collectedFlexItemsValues.remainingFreeSpace > 0) {
|
||||
flexGrowFactor = currentRelativeChild->resolveFlexGrow();
|
||||
|
||||
// Is this child able to grow?
|
||||
if (flexGrowFactor != 0) {
|
||||
if (!YGFloatIsUndefined(flexGrowFactor) && flexGrowFactor != 0) {
|
||||
updatedMainSize = YGNodeBoundAxis(
|
||||
currentRelativeChild,
|
||||
mainAxis,
|
||||
@ -1926,7 +1946,8 @@ static void YGDistributeFreeSpaceFirstPass(
|
||||
-currentRelativeChild->resolveFlexShrink() * childFlexBasis;
|
||||
|
||||
// Is this child able to shrink?
|
||||
if (flexShrinkScaledFactor != 0) {
|
||||
if (!YGFloatIsUndefined(flexShrinkScaledFactor) &&
|
||||
flexShrinkScaledFactor != 0) {
|
||||
baseMainSize = childFlexBasis +
|
||||
collectedFlexItemsValues.remainingFreeSpace /
|
||||
collectedFlexItemsValues.totalFlexShrinkScaledFactors *
|
||||
@ -1937,7 +1958,9 @@ static void YGDistributeFreeSpaceFirstPass(
|
||||
baseMainSize,
|
||||
availableInnerMainDim,
|
||||
availableInnerWidth);
|
||||
if (baseMainSize != boundMainSize) {
|
||||
if (!YGFloatIsUndefined(baseMainSize) &&
|
||||
!YGFloatIsUndefined(boundMainSize) &&
|
||||
baseMainSize != boundMainSize) {
|
||||
// By excluding this item's size and flex factor from remaining,
|
||||
// this item's
|
||||
// min/max constraints should also trigger in the second pass
|
||||
@ -1949,11 +1972,13 @@ static void YGDistributeFreeSpaceFirstPass(
|
||||
flexShrinkScaledFactor;
|
||||
}
|
||||
}
|
||||
} else if (collectedFlexItemsValues.remainingFreeSpace > 0) {
|
||||
} else if (
|
||||
!YGFloatIsUndefined(collectedFlexItemsValues.remainingFreeSpace) &&
|
||||
collectedFlexItemsValues.remainingFreeSpace > 0) {
|
||||
flexGrowFactor = currentRelativeChild->resolveFlexGrow();
|
||||
|
||||
// Is this child able to grow?
|
||||
if (flexGrowFactor != 0) {
|
||||
if (!YGFloatIsUndefined(flexGrowFactor) && flexGrowFactor != 0) {
|
||||
baseMainSize = childFlexBasis +
|
||||
collectedFlexItemsValues.remainingFreeSpace /
|
||||
collectedFlexItemsValues.totalFlexGrowFactors * flexGrowFactor;
|
||||
@ -1964,7 +1989,9 @@ static void YGDistributeFreeSpaceFirstPass(
|
||||
availableInnerMainDim,
|
||||
availableInnerWidth);
|
||||
|
||||
if (baseMainSize != boundMainSize) {
|
||||
if (!YGFloatIsUndefined(baseMainSize) &&
|
||||
!YGFloatIsUndefined(boundMainSize) &&
|
||||
baseMainSize != boundMainSize) {
|
||||
// By excluding this item's size and flex factor from remaining,
|
||||
// this item's
|
||||
// min/max constraints should also trigger in the second pass
|
||||
@ -2069,9 +2096,9 @@ static void YGJustifyMainAxis(
|
||||
if (measureModeMainDim == YGMeasureModeAtMost &&
|
||||
collectedFlexItemsValues.remainingFreeSpace > 0) {
|
||||
if (style.minDimensions[dim[mainAxis]].unit != YGUnitUndefined &&
|
||||
YGResolveValue(
|
||||
style.minDimensions[dim[mainAxis]], mainAxisParentSize) >= 0) {
|
||||
collectedFlexItemsValues.remainingFreeSpace = fmaxf(
|
||||
!YGFloatIsUndefined(YGResolveValue(
|
||||
style.minDimensions[dim[mainAxis]], mainAxisParentSize))) {
|
||||
collectedFlexItemsValues.remainingFreeSpace = YGFloatMax(
|
||||
0,
|
||||
YGResolveValue(
|
||||
style.minDimensions[dim[mainAxis]], mainAxisParentSize) -
|
||||
@ -2115,7 +2142,7 @@ static void YGJustifyMainAxis(
|
||||
case YGJustifySpaceBetween:
|
||||
if (collectedFlexItemsValues.itemsOnLine > 1) {
|
||||
betweenMainDim =
|
||||
fmaxf(collectedFlexItemsValues.remainingFreeSpace, 0) /
|
||||
YGFloatMax(collectedFlexItemsValues.remainingFreeSpace, 0) /
|
||||
(collectedFlexItemsValues.itemsOnLine - 1);
|
||||
} else {
|
||||
betweenMainDim = 0;
|
||||
@ -2207,7 +2234,7 @@ static void YGJustifyMainAxis(
|
||||
|
||||
// The cross dimension is the max of the elements dimension since
|
||||
// there can only be one element in that cross dimension.
|
||||
collectedFlexItemsValues.crossDim = fmaxf(
|
||||
collectedFlexItemsValues.crossDim = YGFloatMax(
|
||||
collectedFlexItemsValues.crossDim,
|
||||
YGNodeDimWithMargin(child, crossAxis, availableInnerWidth));
|
||||
}
|
||||
@ -2537,8 +2564,11 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
availableInnerMainDim = maxInnerMainDim;
|
||||
} else {
|
||||
if (!node->getConfig()->useLegacyStretchBehaviour &&
|
||||
(collectedFlexItemsValues.totalFlexGrowFactors == 0 ||
|
||||
node->resolveFlexGrow() == 0)) {
|
||||
((YGFloatIsUndefined(
|
||||
collectedFlexItemsValues.totalFlexGrowFactors) &&
|
||||
collectedFlexItemsValues.totalFlexGrowFactors == 0) ||
|
||||
(YGFloatIsUndefined(node->resolveFlexGrow()) &&
|
||||
node->resolveFlexGrow() == 0))) {
|
||||
// If we don't have any children to flex or we can't flex the node
|
||||
// itself, space we've used is all space we need. Root node also
|
||||
// should be shrunk to minimum
|
||||
@ -2743,13 +2773,13 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
|
||||
if (child->marginLeadingValue(crossAxis).unit == YGUnitAuto &&
|
||||
child->marginTrailingValue(crossAxis).unit == YGUnitAuto) {
|
||||
leadingCrossDim += fmaxf(0.0f, remainingCrossDim / 2);
|
||||
leadingCrossDim += YGFloatMax(0.0f, remainingCrossDim / 2);
|
||||
} else if (
|
||||
child->marginTrailingValue(crossAxis).unit == YGUnitAuto) {
|
||||
// No-Op
|
||||
} else if (
|
||||
child->marginLeadingValue(crossAxis).unit == YGUnitAuto) {
|
||||
leadingCrossDim += fmaxf(0.0f, remainingCrossDim);
|
||||
leadingCrossDim += YGFloatMax(0.0f, remainingCrossDim);
|
||||
} else if (alignItem == YGAlignFlexStart) {
|
||||
// No-Op
|
||||
} else if (alignItem == YGAlignCenter) {
|
||||
@ -2768,7 +2798,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
}
|
||||
|
||||
totalLineCrossDim += collectedFlexItemsValues.crossDim;
|
||||
maxLineMainDim = fmaxf(maxLineMainDim, collectedFlexItemsValues.mainDim);
|
||||
maxLineMainDim =
|
||||
YGFloatMax(maxLineMainDim, collectedFlexItemsValues.mainDim);
|
||||
}
|
||||
|
||||
// STEP 8: MULTI-LINE CONTENT ALIGNMENT
|
||||
@ -2831,7 +2862,7 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
break;
|
||||
}
|
||||
if (YGNodeIsLayoutDimDefined(child, crossAxis)) {
|
||||
lineHeight = fmaxf(
|
||||
lineHeight = YGFloatMax(
|
||||
lineHeight,
|
||||
child->getLayout().measuredDimensions[dim[crossAxis]] +
|
||||
child->getMarginForAxis(crossAxis, availableInnerWidth));
|
||||
@ -2845,9 +2876,12 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
child->getMarginForAxis(
|
||||
YGFlexDirectionColumn, availableInnerWidth) -
|
||||
ascent;
|
||||
maxAscentForCurrentLine = fmaxf(maxAscentForCurrentLine, ascent);
|
||||
maxDescentForCurrentLine = fmaxf(maxDescentForCurrentLine, descent);
|
||||
lineHeight = fmaxf(lineHeight, maxAscentForCurrentLine + maxDescentForCurrentLine);
|
||||
maxAscentForCurrentLine =
|
||||
YGFloatMax(maxAscentForCurrentLine, ascent);
|
||||
maxDescentForCurrentLine =
|
||||
YGFloatMax(maxDescentForCurrentLine, descent);
|
||||
lineHeight = YGFloatMax(
|
||||
lineHeight, maxAscentForCurrentLine + maxDescentForCurrentLine);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2990,8 +3024,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
measureModeMainDim == YGMeasureModeAtMost &&
|
||||
node->getStyle().overflow == YGOverflowScroll) {
|
||||
node->setLayoutMeasuredDimension(
|
||||
fmaxf(
|
||||
fminf(
|
||||
YGFloatMax(
|
||||
YGFloatMin(
|
||||
availableInnerMainDim + paddingAndBorderAxisMain,
|
||||
YGNodeBoundAxisWithinMinAndMax(
|
||||
node, mainAxis, maxLineMainDim, mainAxisParentSize)),
|
||||
@ -3018,8 +3052,8 @@ static void YGNodelayoutImpl(const YGNodeRef node,
|
||||
measureModeCrossDim == YGMeasureModeAtMost &&
|
||||
node->getStyle().overflow == YGOverflowScroll) {
|
||||
node->setLayoutMeasuredDimension(
|
||||
fmaxf(
|
||||
fminf(
|
||||
YGFloatMax(
|
||||
YGFloatMin(
|
||||
availableInnerCrossDim + paddingAndBorderAxisCross,
|
||||
YGNodeBoundAxisWithinMinAndMax(
|
||||
node,
|
||||
@ -3134,8 +3168,11 @@ static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureM
|
||||
YGMeasureMode lastSizeMode,
|
||||
float lastSize,
|
||||
float lastComputedSize) {
|
||||
return lastSizeMode == YGMeasureModeAtMost && sizeMode == YGMeasureModeAtMost &&
|
||||
lastSize > size && (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize));
|
||||
return lastSizeMode == YGMeasureModeAtMost &&
|
||||
sizeMode == YGMeasureModeAtMost && !YGFloatIsUndefined(lastSize) &&
|
||||
!YGFloatIsUndefined(size) && !YGFloatIsUndefined(lastComputedSize) &&
|
||||
lastSize > size &&
|
||||
(lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize));
|
||||
}
|
||||
|
||||
float YGRoundValueToPixelGrid(const float value,
|
||||
@ -3157,9 +3194,15 @@ float YGRoundValueToPixelGrid(const float value,
|
||||
} else {
|
||||
// Finally we just round the value
|
||||
scaledValue = scaledValue - fractial +
|
||||
(fractial > 0.5f || YGFloatsEqual(fractial, 0.5f) ? 1.0f : 0.0f);
|
||||
(!YGFloatIsUndefined(fractial) &&
|
||||
(fractial > 0.5f || YGFloatsEqual(fractial, 0.5f))
|
||||
? 1.0f
|
||||
: 0.0f);
|
||||
}
|
||||
return scaledValue / pointScaleFactor;
|
||||
return (YGFloatIsUndefined(scaledValue) ||
|
||||
YGFloatIsUndefined(pointScaleFactor))
|
||||
? YGUndefined
|
||||
: scaledValue / pointScaleFactor;
|
||||
}
|
||||
|
||||
bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode,
|
||||
@ -3175,7 +3218,8 @@ bool YGNodeCanUseCachedMeasurement(const YGMeasureMode widthMode,
|
||||
const float marginRow,
|
||||
const float marginColumn,
|
||||
const YGConfigRef config) {
|
||||
if (lastComputedHeight < 0 || lastComputedWidth < 0) {
|
||||
if ((!YGFloatIsUndefined(lastComputedHeight) && lastComputedHeight < 0) ||
|
||||
(!YGFloatIsUndefined(lastComputedWidth) && lastComputedWidth < 0)) {
|
||||
return false;
|
||||
}
|
||||
bool useRoundedComparison =
|
||||
@ -3533,14 +3577,19 @@ static void YGRoundToPixelGrid(const YGNodeRef node,
|
||||
|
||||
const uint32_t childCount = YGNodeGetChildCount(node);
|
||||
for (uint32_t i = 0; i < childCount; i++) {
|
||||
YGRoundToPixelGrid(YGNodeGetChild(node, i), pointScaleFactor, absoluteNodeLeft, absoluteNodeTop);
|
||||
YGRoundToPixelGrid(
|
||||
YGNodeGetChild(node, i),
|
||||
pointScaleFactor,
|
||||
absoluteNodeLeft,
|
||||
absoluteNodeTop);
|
||||
}
|
||||
}
|
||||
|
||||
void YGNodeCalculateLayout(const YGNodeRef node,
|
||||
const float parentWidth,
|
||||
const float parentHeight,
|
||||
const YGDirection parentDirection) {
|
||||
void YGNodeCalculateLayout(
|
||||
const YGNodeRef node,
|
||||
const float parentWidth,
|
||||
const float parentHeight,
|
||||
const YGDirection parentDirection) {
|
||||
// Increment the generation count. This will force the recursive routine to
|
||||
// visit
|
||||
// all dirty nodes at least once. Subsequent visits will be skipped if the
|
||||
@ -3556,16 +3605,16 @@ void YGNodeCalculateLayout(const YGNodeRef node,
|
||||
node->getResolvedDimension(dim[YGFlexDirectionRow]), parentWidth) +
|
||||
node->getMarginForAxis(YGFlexDirectionRow, parentWidth);
|
||||
widthMeasureMode = YGMeasureModeExactly;
|
||||
} else if (
|
||||
YGResolveValue(
|
||||
node->getStyle().maxDimensions[YGDimensionWidth], parentWidth) >=
|
||||
0.0f) {
|
||||
} else if (!YGFloatIsUndefined(YGResolveValue(
|
||||
node->getStyle().maxDimensions[YGDimensionWidth],
|
||||
parentWidth))) {
|
||||
width = YGResolveValue(
|
||||
node->getStyle().maxDimensions[YGDimensionWidth], parentWidth);
|
||||
widthMeasureMode = YGMeasureModeAtMost;
|
||||
} else {
|
||||
width = parentWidth;
|
||||
widthMeasureMode = YGFloatIsUndefined(width) ? YGMeasureModeUndefined : YGMeasureModeExactly;
|
||||
widthMeasureMode = YGFloatIsUndefined(width) ? YGMeasureModeUndefined
|
||||
: YGMeasureModeExactly;
|
||||
}
|
||||
|
||||
float height = YGUndefined;
|
||||
@ -3576,18 +3625,17 @@ void YGNodeCalculateLayout(const YGNodeRef node,
|
||||
parentHeight) +
|
||||
node->getMarginForAxis(YGFlexDirectionColumn, parentWidth);
|
||||
heightMeasureMode = YGMeasureModeExactly;
|
||||
} else if (
|
||||
YGResolveValue(
|
||||
node->getStyle().maxDimensions[YGDimensionHeight], parentHeight) >=
|
||||
0.0f) {
|
||||
} else if (!YGFloatIsUndefined(YGResolveValue(
|
||||
node->getStyle().maxDimensions[YGDimensionHeight],
|
||||
parentHeight))) {
|
||||
height = YGResolveValue(
|
||||
node->getStyle().maxDimensions[YGDimensionHeight], parentHeight);
|
||||
heightMeasureMode = YGMeasureModeAtMost;
|
||||
} else {
|
||||
height = parentHeight;
|
||||
heightMeasureMode = YGFloatIsUndefined(height) ? YGMeasureModeUndefined : YGMeasureModeExactly;
|
||||
heightMeasureMode = YGFloatIsUndefined(height) ? YGMeasureModeUndefined
|
||||
: YGMeasureModeExactly;
|
||||
}
|
||||
|
||||
if (YGLayoutNodeInternal(
|
||||
node,
|
||||
width,
|
||||
|
@ -18,13 +18,14 @@
|
||||
#include <stdbool.h>
|
||||
#endif
|
||||
|
||||
// Not defined in MSVC++
|
||||
#ifndef NAN
|
||||
static const unsigned long __nan[2] = {0xffffffff, 0x7fffffff};
|
||||
#define NAN (*(const float *) __nan)
|
||||
#endif
|
||||
|
||||
#define YGUndefined 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
|
||||
**/
|
||||
#define YGUndefined 10E20F
|
||||
|
||||
#include "YGEnums.h"
|
||||
#include "YGMacros.h"
|
||||
|
Loading…
x
Reference in New Issue
Block a user