Преглед изворни кода

Math: Round half up, instead of away from zero

See the table below for comparison of behavior. The old behavior creates a bias away from zero, which causes issues. For example, `SnapToPixelGrid` with offset -0.5 can result in the size increasing by one pixel, even when that size is integer. Furthermore, an element whose right side is at -0.5 px will after rounding be two pixels away from another element starting at 0.5 px. The new behavior should be closer to expected behavior in such cases.

The new behavior causes a bias towards positive infinity, however, that is considered less problematic for the purpose of layouting.

Round | Previous | New behavior
-0.5  | -1       | 0
+0.5  |  1       | 1
Michael Ragazzon пре 1 година
родитељ
комит
41209432e5
2 измењених фајлова са 30 додато и 2 уклоњено
  1. 2 2
      Source/Core/Math.cpp
  2. 28 0
      Tests/Source/UnitTests/Math.cpp

+ 2 - 2
Source/Core/Math.cpp

@@ -129,12 +129,12 @@ namespace Math {
 
 	RMLUICORE_API float Round(float value)
 	{
-		return roundf(value);
+		return floorf(value + 0.5f);
 	}
 
 	RMLUICORE_API double Round(double value)
 	{
-		return round(value);
+		return floor(value + 0.5);
 	}
 
 	RMLUICORE_API float RoundUp(float value)

+ 28 - 0
Tests/Source/UnitTests/Math.cpp

@@ -154,3 +154,31 @@ TEST_CASE("Math.Max")
 	CHECK(Math::Max<Vector2f>({2, 2}, {1, 1}) == Vector2f(2, 2));
 	CHECK(Math::Max<Vector2f>({2, 1}, {1, 2}) == Vector2f(2, 2));
 }
+
+TEST_CASE("Math.Round")
+{
+	CHECK(Math::Round(-1.0f) == -1.f);
+	CHECK(Math::Round(0.0f) == 0.f);
+	CHECK(Math::Round(1.0f) == 1.f);
+
+	CHECK(Math::Round(0.49f) == 0.f);
+	CHECK(Math::Round(0.50f) == 1.f);
+	CHECK(Math::Round(0.51f) == 1.f);
+	CHECK(Math::Round(-0.49f) == 0.f);
+	CHECK(Math::Round(-0.50f) == 0.f); // Always round half up, see commit message.
+	CHECK(Math::Round(-0.51f) == -1.f);
+
+	CHECK(Math::Round(1000.49f) == 1000.f);
+	CHECK(Math::Round(1000.50f) == 1001.f);
+	CHECK(Math::Round(1000.51f) == 1001.f);
+	CHECK(Math::Round(-1000.49f) == -1000.f);
+	CHECK(Math::Round(-1000.50f) == -1000.f);
+	CHECK(Math::Round(-1000.51f) == -1001.f);
+
+	CHECK(Math::Round(100000.49f) == 100000.f);
+	CHECK(Math::Round(100000.50f) == 100001.f);
+	CHECK(Math::Round(100000.51f) == 100001.f);
+	CHECK(Math::Round(-100000.49f) == -100000.f);
+	CHECK(Math::Round(-100000.50f) == -100000.f);
+	CHECK(Math::Round(-100000.51f) == -100001.f);
+}