Commit 7f5b0b1d authored by Peter Kasting's avatar Peter Kasting Committed by Commit Bot

Use the corner instead of the size as a reference when animating rects.

This prevents error accumulation (rounded origin + rounded size) in intermediate
values, which can lead to cracks between adjacent rects as they're animated.
These can be visible in MD refresh if background tabs have a different color
from the frame.

BUG=none
TEST=none

Change-Id: I8f8dce1c8d2189014ac4bf4ab13598f935f30a24
Reviewed-on: https://chromium-review.googlesource.com/1107241Reviewed-by: default avatarRobert Flack <flackr@chromium.org>
Commit-Queue: Peter Kasting <pkasting@chromium.org>
Cr-Commit-Position: refs/heads/master@{#570187}
parent 744ac3c7
......@@ -179,11 +179,12 @@ int Tween::LinearIntValueBetween(double value, int start, int target) {
gfx::Rect Tween::RectValueBetween(double value,
const gfx::Rect& start,
const gfx::Rect& target) {
return gfx::Rect(
LinearIntValueBetween(value, start.x(), target.x()),
LinearIntValueBetween(value, start.y(), target.y()),
LinearIntValueBetween(value, start.width(), target.width()),
LinearIntValueBetween(value, start.height(), target.height()));
const int x = LinearIntValueBetween(value, start.x(), target.x());
const int y = LinearIntValueBetween(value, start.y(), target.y());
const int right = LinearIntValueBetween(value, start.right(), target.right());
const int bottom =
LinearIntValueBetween(value, start.bottom(), target.bottom());
return gfx::Rect(x, y, right - x, bottom - y);
}
// static
......
......@@ -66,12 +66,17 @@ class ANIMATION_EXPORT Tween {
// specified by www.w3.org/TR/css3-transitions.
static int LinearIntValueBetween(double value, int start, int target);
// Interpolates between |start| and |target| rects, animating the rect corners
// (as opposed to animating the rect origin and size) to minimize rounding
// error accumulation at intermediate stages.
static gfx::Rect RectValueBetween(double value,
const gfx::Rect& start,
const gfx::Rect& target);
static gfx::Transform TransformValueBetween(double value,
const gfx::Transform& start,
const gfx::Transform& target);
static gfx::SizeF SizeValueBetween(double value,
const gfx::SizeF& start,
const gfx::SizeF& target);
......
......@@ -155,6 +155,20 @@ TEST(TweenTest, ClampedFloatValueBetweenTimeTicks) {
EXPECT_EQ(v2, Tween::ClampedFloatValueBetween(t_after, from, v1, to, v2));
}
// Verifies the corners of the rect are animated, rather than the origin/size
// (which would result in different rounding).
TEST(TweenTest, RectValueBetween) {
constexpr gfx::Rect r1(0, 0, 10, 10);
constexpr gfx::Rect r2(10, 10, 30, 30);
// TODO(pkasting): Move the geometry test helpers from
// cc/test/geometry_test_utils.h to ui/gfx/test/gfx_util.h or similar and use
// a rect-comparison function here.
const gfx::Rect tweened = Tween::RectValueBetween(0.08, r1, r2);
EXPECT_EQ(11, tweened.width());
EXPECT_EQ(11, tweened.height());
}
TEST(TweenTest, SizeValueBetween) {
const gfx::SizeF s1(12.0f, 24.0f);
const gfx::SizeF s2(36.0f, 48.0f);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment