diff options
author | vollick@chromium.org <vollick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-06 17:10:58 +0000 |
---|---|---|
committer | vollick@chromium.org <vollick@chromium.org@0039d316-1c4b-4281-b951-d872f2087c98> | 2011-10-06 17:10:58 +0000 |
commit | aaa1268aa6cd0a4cdce9d2d04d21f11910b1198a (patch) | |
tree | d4e832228fe4067d5c28053697a60ab490691a32 /ui | |
parent | 947c86a24a345cd22df3d458c6cdb1b4ec68566a (diff) | |
download | chromium_src-aaa1268aa6cd0a4cdce9d2d04d21f11910b1198a.zip chromium_src-aaa1268aa6cd0a4cdce9d2d04d21f11910b1198a.tar.gz chromium_src-aaa1268aa6cd0a4cdce9d2d04d21f11910b1198a.tar.bz2 |
Revert 104304 - Avoid overdraw in views desktop.
Make sure that we still allow a view to punch a hole in its parent if it is rotated by a multiple of 90 degrees.
BUG=None
TEST=None
Review URL: http://codereview.chromium.org/7941017
TBR=vollick@chromium.org
Review URL: http://codereview.chromium.org/8175008
git-svn-id: svn://svn.chromium.org/chrome/trunk/src@104311 0039d316-1c4b-4281-b951-d872f2087c98
Diffstat (limited to 'ui')
-rw-r--r-- | ui/gfx/compositor/layer.cc | 59 | ||||
-rw-r--r-- | ui/gfx/compositor/layer_unittest.cc | 56 |
2 files changed, 62 insertions, 53 deletions
diff --git a/ui/gfx/compositor/layer.cc b/ui/gfx/compositor/layer.cc index b9b1cd3..af3514fc 100644 --- a/ui/gfx/compositor/layer.cc +++ b/ui/gfx/compositor/layer.cc @@ -11,20 +11,8 @@ #include "ui/base/animation/animation.h" #include "ui/gfx/compositor/layer_animator.h" #include "ui/gfx/canvas_skia.h" -#include "ui/gfx/interpolated_transform.h" #include "ui/gfx/point3.h" -namespace { - -const float EPSILON = 1e-3f; - -bool IsApproximateMultilpleOf(float value, float base) { - float remainder = fmod(fabs(value), base); - return remainder < EPSILON || base - remainder < EPSILON; -} - -} // namespace - namespace ui { Layer::Layer(Compositor* compositor) @@ -315,33 +303,48 @@ void Layer::RecomputeHole() { // Reset to default. hole_rect_ = gfx::Rect(); - // Find the largest hole + // 1) We cannot do any hole punching if any child has a transform. + for (size_t i = 0; i < children_.size(); ++i) { + if (children_[i]->transform().HasChange() && children_[i]->visible_) + return; + } + + // 2) Find the largest hole. for (size_t i = 0; i < children_.size(); ++i) { // Ignore non-opaque and hidden children. if (!children_[i]->IsCompletelyOpaque() || !children_[i]->visible_) continue; - // Ignore children that aren't rotated by multiples of 90 degrees. - float degrees; - if (!InterpolatedTransform::FactorTRS(children_[i]->transform(), - NULL, °rees, NULL) || - !IsApproximateMultilpleOf(degrees, 90.0f)) + if (children_[i]->bounds().size().GetArea() > hole_rect_.size().GetArea()) { + hole_rect_ = children_[i]->bounds(); + } + } + + // 3) Make sure hole does not intersect with non-opaque children. + for (size_t i = 0; i < children_.size(); ++i) { + // Ignore opaque and hidden children. + if (children_[i]->IsCompletelyOpaque() || !children_[i]->visible_) continue; - gfx::Rect candidate_hole = children_[i]->bounds(); - children_[i]->transform().TransformRect(&candidate_hole); + // Ignore non-intersecting children. + if (!hole_rect_.Intersects(children_[i]->bounds())) + continue; - // This layer might not contain the child (e.g., a portion of the child may - // be offscreen). Only the portion of the child that overlaps this layer is - // of any importance, so take the intersection. - candidate_hole = bounds().Intersect(candidate_hole); + // Compute surrounding fragments. + std::vector<gfx::Rect> fragments; + PunchHole(hole_rect_, children_[i]->bounds(), &fragments); - // Ensure we have the largest hole. - if (candidate_hole.size().GetArea() > hole_rect_.size().GetArea()) - hole_rect_ = candidate_hole; + // Pick the largest surrounding fragment as the new hole. + hole_rect_ = fragments[0]; + for (size_t j = 1; j < fragments.size(); ++j) { + if (fragments[j].size().GetArea() > hole_rect_.size().GetArea()) { + hole_rect_ = fragments[j]; + } + } + DCHECK(!hole_rect_.IsEmpty()); } - // Free up texture memory if the hole fills bounds of layer. + // 4) Free up texture memory if the hole fills bounds of layer. if (!ShouldDraw() && !layer_updated_externally_) texture_ = NULL; } diff --git a/ui/gfx/compositor/layer_unittest.cc b/ui/gfx/compositor/layer_unittest.cc index 953eaba..59ccfdd 100644 --- a/ui/gfx/compositor/layer_unittest.cc +++ b/ui/gfx/compositor/layer_unittest.cc @@ -506,6 +506,36 @@ TEST_F(LayerWithNullDelegateTest, LayerTextureNonEmptySchedulePaint) { EXPECT_TRUE(layer->texture() != NULL); } +// Verifies that a hole in a layer does not intersect non completely-opaque +// layers. +TEST_F(LayerWithNullDelegateTest, HoleDoesNotIntersectNonOpaque) { + scoped_ptr<Layer> parent(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400))); + scoped_ptr<Layer> child1(CreateTextureLayer(gfx::Rect(50, 50, 100, 100))); + parent->Add(child1.get()); + + scoped_ptr<Layer> child2(CreateLayer(Layer::LAYER_HAS_NO_TEXTURE)); + child2->SetFillsBoundsOpaquely(false); + parent->Add(child2.get()); + Draw(); + + // Ensure largest non intersecting hole picked. + // largest fragment on bottom. + child2->SetBounds(gfx::Rect(20, 20, 60, 80)); + EXPECT_EQ(gfx::Rect(50, 100, 100, 50), parent->hole_rect()); + + // largest fragment on right. + child2->SetBounds(gfx::Rect(20, 20, 60, 200)); + EXPECT_EQ(gfx::Rect(80, 50, 70, 100), parent->hole_rect()); + + // largest fragment on top. + child2->SetBounds(gfx::Rect(130, 110, 50, 50)); + EXPECT_EQ(gfx::Rect(50, 50, 100, 60), parent->hole_rect()); + + // largest fragment on left. + child2->SetBounds(gfx::Rect(130, 20, 50, 200)); + EXPECT_EQ(gfx::Rect(50, 50, 80, 100), parent->hole_rect()); +} + // Verifies that when there are many potential holes, the largest one is picked. TEST_F(LayerWithNullDelegateTest, LargestHole) { scoped_ptr<Layer> parent(CreateTextureRootLayer(gfx::Rect(0, 0, 400, 400))); @@ -529,36 +559,12 @@ TEST_F(LayerWithNullDelegateTest, NoHoleWithTransform) { EXPECT_TRUE(!parent->hole_rect().IsEmpty()); ui::Transform t; - t.SetTranslate(-75, -75); - t.ConcatRotate(45.0f); - t.ConcatTranslate(75, 75); + t.SetRotate(90.0f); child->SetTransform(t); EXPECT_EQ(gfx::Rect(0, 0, 0, 0), parent->hole_rect()); } -// Verifies that if the child layer is rotated by a multiple of ninety degrees -// we punch a hole -TEST_F(LayerWithNullDelegateTest, HoleWithNinetyDegreeTransforms) { - scoped_ptr<Layer> parent(CreateTextureLayer(gfx::Rect(0, 0, 400, 400))); - scoped_ptr<Layer> child(CreateTextureLayer(gfx::Rect(50, 50, 50, 50))); - parent->Add(child.get()); - - EXPECT_TRUE(!parent->hole_rect().IsEmpty()); - - for (int i = -4; i <= 4; ++i) { - ui::Transform t; - t.SetTranslate(-75, -75); - t.ConcatRotate(90.0f * i); - t.ConcatTranslate(75, 75); - child->SetTransform(t); - - gfx::Rect target_rect = child->bounds(); - child->transform().TransformRect(&target_rect); - EXPECT_EQ(target_rect, parent->hole_rect()); - } -} - // Create this hierarchy: // L1 (no texture) // +- L11 (texture) |