Skip to content

Commit af8c69e

Browse files
Adam Comellafacebook-github-bot
Adam Comella
authored andcommitted
Fix rounding of negative numbers (#825)
Summary: `YGRoundValueToPixelGrid` currently rounds negative numbers incorrectly. For example: ``` YGRoundValueToPixelGrid(-2.2, 1.0, /* ceil */ false, /* floor */ true) = -2.0 ``` However, that operation is supposed to take the floor of the number so the result should acutally be `-3.0`. There's a detailed comment in `YGRoundValueToPixelGrid` about the fix and why it works. A symptom that manifested because of this bug is that text nodes could get smaller and smaller on each layout pass. For details see facebook/yoga#824. Fixes #824 Adam Comella Microsoft Corp. Pull Request resolved: facebook/yoga#825 Reviewed By: priteshrnandgaonkar Differential Revision: D10282064 Pulled By: shergin fbshipit-source-id: 16ca966e6cb0cfc88b1dbf4ba31e7b1dbe1f2049
1 parent 6b5b475 commit af8c69e

File tree

1 file changed

+21
-2
lines changed

1 file changed

+21
-2
lines changed

Diff for: ReactCommon/yoga/yoga/Yoga.cpp

+21-2
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
/*
2-
* Copyright (c) Facebook, Inc. and its affiliates.
2+
* Copyright (c) 2018-present, Facebook, Inc.
33
*
44
* This source code is licensed under the MIT license found in the LICENSE
55
* file in the root directory of this source tree.
66
*
77
*/
8-
98
#include "Yoga.h"
109
#include <float.h>
1110
#include <string.h>
@@ -3608,7 +3607,27 @@ float YGRoundValueToPixelGrid(
36083607
const bool forceCeil,
36093608
const bool forceFloor) {
36103609
float scaledValue = value * pointScaleFactor;
3610+
// We want to calculate `fractial` such that `floor(scaledValue) = scaledValue
3611+
// - fractial`.
36113612
float fractial = fmodf(scaledValue, 1.0f);
3613+
if (fractial < 0) {
3614+
// This branch is for handling negative numbers for `value`.
3615+
//
3616+
// Regarding `floor` and `ceil`. Note that for a number x, `floor(x) <= x <=
3617+
// ceil(x)` even for negative numbers. Here are a couple of examples:
3618+
// - x = 2.2: floor( 2.2) = 2, ceil( 2.2) = 3
3619+
// - x = -2.2: floor(-2.2) = -3, ceil(-2.2) = -2
3620+
//
3621+
// Regarding `fmodf`. For fractional negative numbers, `fmodf` returns a
3622+
// negative number. For example, `fmodf(-2.2) = -0.2`. However, we want
3623+
// `fractial` to be the number such that subtracting it from `value` will
3624+
// give us `floor(value)`. In the case of negative numbers, adding 1 to
3625+
// `fmodf(value)` gives us this. Let's continue the example from above:
3626+
// - fractial = fmodf(-2.2) = -0.2
3627+
// - Add 1 to the fraction: fractial2 = fractial + 1 = -0.2 + 1 = 0.8
3628+
// - Finding the `floor`: -2.2 - fractial2 = -2.2 - 0.8 = -3
3629+
++fractial;
3630+
}
36123631
if (YGFloatsEqual(fractial, 0)) {
36133632
// First we check if the value is already rounded
36143633
scaledValue = scaledValue - fractial;

0 commit comments

Comments
 (0)