Skip to content

Commit f45059e

Browse files
Georgiy Kassablifacebook-github-bot
authored andcommitted
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
1 parent c938476 commit f45059e

File tree

3 files changed

+57
-2
lines changed

3 files changed

+57
-2
lines changed

tests/YGRoundingFunctionTest.cpp

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
#include <gtest/gtest.h>
11+
12+
#include <yoga/Yoga.h>
13+
#include <yoga/Yoga-internal.h>
14+
15+
TEST(YogaTest, rounding_value) {
16+
// Test that whole numbers are rounded to whole despite ceil/floor flags
17+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, false, false));
18+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, true, false));
19+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.000001, 2.0, false, true));
20+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, false, false));
21+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, true, false));
22+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.999999, 2.0, false, true));
23+
24+
// Test that numbers with fraction are rounded correctly accounting for ceil/floor flags
25+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.01, 2.0, false, false));
26+
ASSERT_FLOAT_EQ(6.5, YGRoundValueToPixelGrid(6.01, 2.0, true, false));
27+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(6.01, 2.0, false, true));
28+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.99, 2.0, false, false));
29+
ASSERT_FLOAT_EQ(6.0, YGRoundValueToPixelGrid(5.99, 2.0, true, false));
30+
ASSERT_FLOAT_EQ(5.5, YGRoundValueToPixelGrid(5.99, 2.0, false, true));
31+
}

yoga/Yoga-internal.h

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,19 @@
1+
/**
2+
* Copyright (c) 2014-present, Facebook, Inc.
3+
* All rights reserved.
4+
*
5+
* This source code is licensed under the BSD-style license found in the
6+
* LICENSE file in the root directory of this source tree. An additional grant
7+
* of patent rights can be found in the PATENTS file in the same directory.
8+
*/
9+
10+
#pragma once
11+
12+
YG_EXTERN_C_BEGIN
13+
14+
WIN_EXPORT float YGRoundValueToPixelGrid(const float value,
15+
const float pointScaleFactor,
16+
const bool forceCeil,
17+
const bool forceFloor);
18+
19+
YG_EXTERN_C_END

yoga/Yoga.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111

1212
#include "YGNodeList.h"
1313
#include "Yoga.h"
14+
#include "Yoga-internal.h"
1415

1516
#ifdef _MSC_VER
1617
#include <float.h>
@@ -3158,20 +3159,24 @@ static inline bool YGMeasureModeNewMeasureSizeIsStricterAndStillValid(YGMeasureM
31583159
lastSize > size && (lastComputedSize <= size || YGFloatsEqual(size, lastComputedSize));
31593160
}
31603161

3161-
static float YGRoundValueToPixelGrid(const float value,
3162+
float YGRoundValueToPixelGrid(const float value,
31623163
const float pointScaleFactor,
31633164
const bool forceCeil,
31643165
const bool forceFloor) {
31653166
float scaledValue = value * pointScaleFactor;
31663167
float fractial = fmodf(scaledValue, 1.0);
31673168
if (YGFloatsEqual(fractial, 0)) {
3168-
// Still remove fractial as fractial could be extremely small.
3169+
// First we check if the value is already rounded
31693170
scaledValue = scaledValue - fractial;
3171+
} else if (YGFloatsEqual(fractial, 1.0)) {
3172+
scaledValue = scaledValue - fractial + 1.0;
31703173
} else if (forceCeil) {
3174+
// Next we check if we need to use forced rounding
31713175
scaledValue = scaledValue - fractial + 1.0;
31723176
} else if (forceFloor) {
31733177
scaledValue = scaledValue - fractial;
31743178
} else {
3179+
// Finally we just round the value
31753180
scaledValue = scaledValue - fractial + (fractial >= 0.5f ? 1.0 : 0);
31763181
}
31773182
return scaledValue / pointScaleFactor;

0 commit comments

Comments
 (0)