| OLD | NEW |
| (Empty) | |
| 1 // Copyright (c) 2009 The Chromium Authors. All rights reserved. |
| 2 // Use of this source code is governed by a BSD-style license that can be |
| 3 // found in the LICENSE file. |
| 4 |
| 5 #include "chrome/renderer/paint_aggregator.h" |
| 6 |
| 7 #include "base/logging.h" |
| 8 |
| 9 // We implement a very simple algorithm: |
| 10 // |
| 11 // - Multiple repaints are unioned to form the smallest bounding box. |
| 12 // - If a scroll intersects a repaint, then the scroll is downgraded |
| 13 // to a repaint and then unioned with the existing repaint. |
| 14 // |
| 15 // This allows for a scroll to exist in parallel to a repaint provided the two |
| 16 // do not intersect. |
| 17 |
| 18 gfx::Rect PaintAggregator::PendingUpdate::GetScrollDamage() const { |
| 19 // Should only be scrolling in one direction at a time. |
| 20 DCHECK(!(scroll_delta.x() && scroll_delta.y())); |
| 21 |
| 22 gfx::Rect damaged_rect; |
| 23 |
| 24 // Compute the region we will expose by scrolling, and paint that into a |
| 25 // shared memory section. |
| 26 if (scroll_delta.x()) { |
| 27 int dx = scroll_delta.x(); |
| 28 damaged_rect.set_y(scroll_rect.y()); |
| 29 damaged_rect.set_height(scroll_rect.height()); |
| 30 if (dx > 0) { |
| 31 damaged_rect.set_x(scroll_rect.x()); |
| 32 damaged_rect.set_width(dx); |
| 33 } else { |
| 34 damaged_rect.set_x(scroll_rect.right() + dx); |
| 35 damaged_rect.set_width(-dx); |
| 36 } |
| 37 } else { |
| 38 int dy = scroll_delta.y(); |
| 39 damaged_rect.set_x(scroll_rect.x()); |
| 40 damaged_rect.set_width(scroll_rect.width()); |
| 41 if (dy > 0) { |
| 42 damaged_rect.set_y(scroll_rect.y()); |
| 43 damaged_rect.set_height(dy); |
| 44 } else { |
| 45 damaged_rect.set_y(scroll_rect.bottom() + dy); |
| 46 damaged_rect.set_height(-dy); |
| 47 } |
| 48 } |
| 49 |
| 50 // In case the scroll offset exceeds the width/height of the scroll rect |
| 51 return scroll_rect.Intersect(damaged_rect); |
| 52 } |
| 53 |
| 54 bool PaintAggregator::HasPendingUpdate() const { |
| 55 return !update_.scroll_rect.IsEmpty() || !update_.paint_rect.IsEmpty(); |
| 56 } |
| 57 |
| 58 void PaintAggregator::ClearPendingUpdate() { |
| 59 update_ = PendingUpdate(); |
| 60 } |
| 61 |
| 62 void PaintAggregator::InvalidateRect(const gfx::Rect& rect) { |
| 63 // If this invalidate overlaps with a pending scroll, then we have to |
| 64 // downgrade to invalidating the scroll rect. |
| 65 if (rect.Intersects(update_.scroll_rect)) { |
| 66 update_.paint_rect = update_.paint_rect.Union(update_.scroll_rect); |
| 67 update_.scroll_rect = gfx::Rect(); |
| 68 update_.scroll_delta = gfx::Point(); |
| 69 } |
| 70 |
| 71 update_.paint_rect = update_.paint_rect.Union(rect); |
| 72 } |
| 73 |
| 74 void PaintAggregator::ScrollRect(int dx, int dy, const gfx::Rect& clip_rect) { |
| 75 if (dx != 0 && dy != 0) { |
| 76 // We only support scrolling along one axis at a time. |
| 77 ScrollRect(0, dy, clip_rect); |
| 78 dy = 0; |
| 79 } |
| 80 |
| 81 bool intersects_with_painting = update_.paint_rect.Intersects(clip_rect); |
| 82 |
| 83 // If we already have a pending scroll operation or if this scroll operation |
| 84 // intersects the existing paint region, then just failover to invalidating. |
| 85 if (!update_.scroll_rect.IsEmpty() || intersects_with_painting) { |
| 86 if (!intersects_with_painting && update_.scroll_rect == clip_rect) { |
| 87 // OK, we can just update the scroll delta (requires same scrolling axis) |
| 88 if (!dx && !update_.scroll_delta.x()) { |
| 89 update_.scroll_delta.set_y(update_.scroll_delta.y() + dy); |
| 90 return; |
| 91 } |
| 92 if (!dy && !update_.scroll_delta.y()) { |
| 93 update_.scroll_delta.set_x(update_.scroll_delta.x() + dx); |
| 94 return; |
| 95 } |
| 96 } |
| 97 InvalidateRect(update_.scroll_rect); |
| 98 DCHECK(update_.scroll_rect.IsEmpty()); |
| 99 InvalidateRect(clip_rect); |
| 100 return; |
| 101 } |
| 102 |
| 103 update_.scroll_rect = clip_rect; |
| 104 update_.scroll_delta = gfx::Point(dx, dy); |
| 105 } |
| OLD | NEW |