Fixing edge case issue in Yoga where text node was unnecessary rounded down
Summary: There was an uncovered edge case where number close to the whole was forced to round down because it was considered non-whole and had forced flooring. This diff covers that + adds a bunch of test cases to cover rounding function Reviewed By: emilsjolander Differential Revision: D5465632 fbshipit-source-id: 57e11092a97eba5dd76daad15fa8619535ff9c1b
This commit is contained in:
committed by
Facebook Github Bot
parent
c9384762ee
commit
f45059e1e6
31
tests/YGRoundingFunctionTest.cpp
Normal file
31
tests/YGRoundingFunctionTest.cpp
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include <gtest/gtest.h>
|
||||||
|
|
||||||
|
#include <yoga/Yoga.h>
|
||||||
|
#include <yoga/Yoga-internal.h>
|
||||||
|
|
||||||
|
TEST(YogaTest, rounding_value) {
|
||||||
|
// Test that whole numbers are rounded to whole despite ceil/floor flags
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, false, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, true, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, false, true));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, false, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, true, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, false, true));
|
||||||
|
|
||||||
|
// Test that numbers with fraction are rounded correctly accounting for ceil/floor flags
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.01, 2.0, false, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.5, YGRoundValueToPixelGrid(6.01, 2.0, true, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.01, 2.0, false, true));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.99, 2.0, false, false));
|
||||||
|
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.99, 2.0, true, false));
|
||||||
|
ASSERT_FLOAT_EQ(5.5, YGRoundValueToPixelGrid(5.99, 2.0, false, true));
|
||||||
|
}
|
19
yoga/Yoga-internal.h
Normal file
19
yoga/Yoga-internal.h
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/**
|
||||||
|
* Copyright (c) 2014-present, Facebook, Inc.
|
||||||
|
* All rights reserved.
|
||||||
|
*
|
||||||
|
* This source code is licensed under the BSD-style license found in the
|
||||||
|
* LICENSE file in the root directory of this source tree. An additional grant
|
||||||
|
* of patent rights can be found in the PATENTS file in the same directory.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
YG_EXTERN_C_BEGIN
|
||||||
|
|
||||||
|
WIN_EXPORT float YGRoundValueToPixelGrid(const float value,
|
||||||
|
const float pointScaleFactor,
|
||||||
|
const bool forceCeil,
|
||||||
|
const bool forceFloor);
|
||||||
|
|
||||||
|
YG_EXTERN_C_END
|
@@ -11,6 +11,7 @@
|
|||||||
|
|
||||||
#include "YGNodeList.h"
|
#include "YGNodeList.h"
|
||||||
#include "Yoga.h"
|
#include "Yoga.h"
|
||||||
|
#include "Yoga-internal.h"
|
||||||
|
|
||||||
#ifdef _MSC_VER
|
#ifdef _MSC_VER
|
||||||
#include <float.h>
|
#include <float.h>
|
||||||
@@ -3158,20 +3159,24 @@ static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureM
|
|||||||
lastSize > size && (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize));
|
lastSize > size && (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize));
|
||||||
}
|
}
|
||||||
|
|
||||||
static float YGRoundValueToPixelGrid(const float value,
|
float YGRoundValueToPixelGrid(const float value,
|
||||||
const float pointScaleFactor,
|
const float pointScaleFactor,
|
||||||
const bool forceCeil,
|
const bool forceCeil,
|
||||||
const bool forceFloor) {
|
const bool forceFloor) {
|
||||||
float scaledValue = value * pointScaleFactor;
|
float scaledValue = value * pointScaleFactor;
|
||||||
float fractial = fmodf(scaledValue, 1.0);
|
float fractial = fmodf(scaledValue, 1.0);
|
||||||
if (YGFloatsEqual(fractial, 0)) {
|
if (YGFloatsEqual(fractial, 0)) {
|
||||||
// Still remove fractial as fractial could be extremely small.
|
// First we check if the value is already rounded
|
||||||
scaledValue = scaledValue - fractial;
|
scaledValue = scaledValue - fractial;
|
||||||
|
} else if (YGFloatsEqual(fractial, 1.0)) {
|
||||||
|
scaledValue = scaledValue - fractial + 1.0;
|
||||||
} else if (forceCeil) {
|
} else if (forceCeil) {
|
||||||
|
// Next we check if we need to use forced rounding
|
||||||
scaledValue = scaledValue - fractial + 1.0;
|
scaledValue = scaledValue - fractial + 1.0;
|
||||||
} else if (forceFloor) {
|
} else if (forceFloor) {
|
||||||
scaledValue = scaledValue - fractial;
|
scaledValue = scaledValue - fractial;
|
||||||
} else {
|
} else {
|
||||||
|
// Finally we just round the value
|
||||||
scaledValue = scaledValue - fractial + (fractial >= 0.5f ? 1.0 : 0);
|
scaledValue = scaledValue - fractial + (fractial >= 0.5f ? 1.0 : 0);
|
||||||
}
|
}
|
||||||
return scaledValue / pointScaleFactor;
|
return scaledValue / pointScaleFactor;
|
||||||
|
Reference in New Issue
Block a user