Commit 41dd59f3 authored by Roger Johannesson's avatar Roger Johannesson Committed by Commit Bot

Take the layer transform scale into account when snapping to physical pixels

SnapLayerToPhysicalPixelBoundary calculates the sub pixel offset that is needed
for a layer to end up on a physical pixel boundary but it does not take into
account that a layer can have a scaling transform applied to it.

This showed up as a problem when https://chromium-review.googlesource.com/691338
landed since it made layers with scale transforms applied start triggering
DCHECKs in CheckSnapped. The reason there was no problem before that CL is that
ConvertPointToLayer used to return floored coordinates.

This patch attempts to fix this problem by applying the transform scale to the
offset vector, similar to how the device scale factor is applied.

Bug: 805425
Change-Id: I401de72a465b83b00762a92ad2634ac2fc40dff5
Reviewed-on: https://chromium-review.googlesource.com/883782
Commit-Queue: Antoine Labour <piman@chromium.org>
Reviewed-by: default avatarAntoine Labour <piman@chromium.org>
Reviewed-by: default avatarIan Vollick <vollick@chromium.org>
Cr-Commit-Position: refs/heads/master@{#531967}
parent d85e91cc
......@@ -93,6 +93,14 @@ void SnapLayerToPhysicalPixelBoundary(ui::Layer* snapped_layer,
gfx::Vector2dF fudge = view_offset_snapped - view_offset;
fudge.Scale(1.0 / scale_factor);
// Apply any scale originating from transforms to the fudge.
gfx::Transform transform;
layer_to_snap->parent()->GetTargetTransformRelativeTo(snapped_layer,
&transform);
gfx::Vector2dF transform_scale = transform.Scale2d();
fudge.Scale(1.0 / transform_scale.x(), 1.0 / transform_scale.y());
layer_to_snap->SetSubpixelPositionOffset(fudge);
#if DCHECK_IS_ON()
gfx::PointF layer_offset;
......@@ -105,6 +113,7 @@ void SnapLayerToPhysicalPixelBoundary(ui::Layer* snapped_layer,
} else {
origin = layer_to_snap->position();
}
origin.Scale(transform_scale.x(), transform_scale.y());
CheckSnapped((layer_offset.x() + origin.x()) * scale_factor);
CheckSnapped((layer_offset.y() + origin.y()) * scale_factor);
#endif
......
......@@ -2192,7 +2192,7 @@ TEST_F(LayerWithDelegateTest, NonAnimatingAnimatorsAreRemovedFromCollection) {
namespace {
std::string Vector2dFTo100thPercisionString(const gfx::Vector2dF& vector) {
std::string Vector2dFTo100thPrecisionString(const gfx::Vector2dF& vector) {
return base::StringPrintf("%.2f %0.2f", vector.x(), vector.y());
}
......@@ -2215,21 +2215,68 @@ TEST_F(LayerWithRealCompositorTest, SnapLayerToPixels) {
SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
// 0.5 at 1.25 scale : (1 - 0.25 + 0.25) / 1.25 = 0.4
EXPECT_EQ("0.40 0.40",
Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
Vector2dFTo100thPrecisionString(c11->subpixel_position_offset()));
GetCompositor()->SetScaleAndSize(1.5f, gfx::Size(100, 100),
viz::LocalSurfaceId());
SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
// c11 must already be aligned at 1.5 scale.
EXPECT_EQ("0.00 0.00",
Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
Vector2dFTo100thPrecisionString(c11->subpixel_position_offset()));
c11->SetBounds(gfx::Rect(2, 2, 10, 10));
SnapLayerToPhysicalPixelBoundary(root.get(), c11.get());
// c11 is now off the pixel.
// 0.5 / 1.5 = 0.333...
EXPECT_EQ("0.33 0.33",
Vector2dFTo100thPercisionString(c11->subpixel_position_offset()));
Vector2dFTo100thPrecisionString(c11->subpixel_position_offset()));
}
TEST_F(LayerWithRealCompositorTest, SnapLayerToPixelsWithScaleTransform) {
std::unique_ptr<Layer> root(CreateLayer(LAYER_TEXTURED));
std::unique_ptr<Layer> c1(CreateLayer(LAYER_TEXTURED));
std::unique_ptr<Layer> c11(CreateLayer(LAYER_TEXTURED));
std::unique_ptr<Layer> c111(CreateLayer(LAYER_TEXTURED));
GetCompositor()->SetScaleAndSize(1.0f, gfx::Size(100, 100),
viz::LocalSurfaceId());
GetCompositor()->SetRootLayer(root.get());
root->Add(c1.get());
c1->Add(c11.get());
c11->Add(c111.get());
root->SetBounds(gfx::Rect(0, 0, 100, 100));
c1->SetBounds(gfx::Rect(0, 0, 10, 10));
c11->SetBounds(gfx::Rect(0, 0, 10, 10));
c111->SetBounds(gfx::Rect(2, 2, 5, 5));
gfx::Transform transform;
transform.Scale(1.25f, 1.25f);
c1->SetTransform(transform);
SnapLayerToPhysicalPixelBoundary(root.get(), c111.get());
// c111 ends up at 2.5, and is supposed to be snapped to 3.0. So subpixel
// offset is expected to be:
// 0.5 / 1.25 = 0.40
EXPECT_EQ("0.40 0.40",
Vector2dFTo100thPrecisionString(c111->subpixel_position_offset()));
c11->SetTransform(transform);
SnapLayerToPhysicalPixelBoundary(root.get(), c111.get());
// c111 ends up at 3.125, and is supposed to be snapped to 3.0. So subpixel
// offset is expected to be:
// -0.125 / (1.25 * 1.25) = -0.08
EXPECT_EQ("-0.08 -0.08",
Vector2dFTo100thPrecisionString(c111->subpixel_position_offset()));
// A transform on c111 should not affect the subpixel offset so expect it to
// be the same as before.
c111->SetTransform(transform);
SnapLayerToPhysicalPixelBoundary(root.get(), c111.get());
EXPECT_EQ("-0.08 -0.08",
Vector2dFTo100thPrecisionString(c111->subpixel_position_offset()));
}
// Verify that LayerDelegate::OnLayerBoundsChanged() is called when the bounds
......
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