1cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Copyright (c) 2010 The Chromium Authors. All rights reserved.
2cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// Use of this source code is governed by a BSD-style license that can be
3cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// found in the LICENSE file.
4cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
5cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "pdf/paint_aggregator.h"
6cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
7cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include <algorithm>
8cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
9cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)#include "base/logging.h"
10cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
11cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// ----------------------------------------------------------------------------
12cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// ALGORITHM NOTES
13cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//
14cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// We attempt to maintain a scroll rect in the presence of invalidations that
15cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// are contained within the scroll rect.  If an invalidation crosses a scroll
16cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// rect, then we just treat the scroll rect as an invalidation rect.
17cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//
18cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// For invalidations performed prior to scrolling and contained within the
19cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// scroll rect, we offset the invalidation rects to account for the fact that
20cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// the consumer will perform scrolling before painting.
21cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)//
22cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// We only support scrolling along one axis at a time.  A diagonal scroll will
23cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// therefore be treated as an invalidation.
24cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)// ----------------------------------------------------------------------------
25cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
26cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PaintAggregator::PaintUpdate::PaintUpdate() {
27cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
28cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
29cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PaintAggregator::PaintUpdate::~PaintUpdate() {
30cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
31cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
32cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PaintAggregator::InternalPaintUpdate::InternalPaintUpdate() :
33cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    synthesized_scroll_damage_rect_(false) {
34cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
35cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
36cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PaintAggregator::InternalPaintUpdate::~InternalPaintUpdate() {
37cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
38cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
39cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)pp::Rect PaintAggregator::InternalPaintUpdate::GetScrollDamage() const {
40cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Should only be scrolling in one direction at a time.
41cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  DCHECK(!(scroll_delta.x() && scroll_delta.y()));
42cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
43cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pp::Rect damaged_rect;
44cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
45cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Compute the region we will expose by scrolling, and paint that into a
46cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // shared memory section.
47cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (scroll_delta.x()) {
48cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int32_t dx = scroll_delta.x();
49cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    damaged_rect.set_y(scroll_rect.y());
50cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    damaged_rect.set_height(scroll_rect.height());
51cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (dx > 0) {
52cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      damaged_rect.set_x(scroll_rect.x());
53cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      damaged_rect.set_width(dx);
54cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
55cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      damaged_rect.set_x(scroll_rect.right() + dx);
56cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      damaged_rect.set_width(-dx);
57cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
58cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  } else {
59cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    int32_t dy = scroll_delta.y();
60cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    damaged_rect.set_x(scroll_rect.x());
61cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    damaged_rect.set_width(scroll_rect.width());
62cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (dy > 0) {
63cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      damaged_rect.set_y(scroll_rect.y());
64cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      damaged_rect.set_height(dy);
65cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    } else {
66cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      damaged_rect.set_y(scroll_rect.bottom() + dy);
67cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      damaged_rect.set_height(-dy);
68cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
69cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
70cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
71cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // In case the scroll offset exceeds the width/height of the scroll rect
72cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return scroll_rect.Intersect(damaged_rect);
73cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
74cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
75cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PaintAggregator::PaintAggregator() {
76cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
77cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
78cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)bool PaintAggregator::HasPendingUpdate() const {
79cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return !update_.scroll_rect.IsEmpty() || !update_.paint_rects.empty();
80cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
81cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
82cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PaintAggregator::ClearPendingUpdate() {
83cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  update_ = InternalPaintUpdate();
84cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
85cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
86cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)PaintAggregator::PaintUpdate PaintAggregator::GetPendingUpdate() {
87cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Convert the internal paint update to the external one, which includes a
88cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // bit more precomputed info for the caller.
89cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  PaintUpdate ret;
90cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ret.scroll_delta = update_.scroll_delta;
91cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ret.scroll_rect = update_.scroll_rect;
92cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ret.has_scroll = ret.scroll_delta.x() != 0 || ret.scroll_delta.y() != 0;
93cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
94cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Include the scroll damage (if any) in the paint rects.
95cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Code invalidates damaged rect here, it pick it up from the list of paint
96cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // rects in the next block.
97cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (ret.has_scroll  && !update_.synthesized_scroll_damage_rect_) {
98cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    update_.synthesized_scroll_damage_rect_ = true;
99cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    pp::Rect scroll_damage = update_.GetScrollDamage();
100cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    InvalidateRectInternal(scroll_damage, false);
101cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
102cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
103cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  ret.paint_rects.reserve(update_.paint_rects.size() + 1);
104cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < update_.paint_rects.size(); i++)
105cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    ret.paint_rects.push_back(update_.paint_rects[i]);
106cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
107cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return ret;
108cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
109cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
110cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PaintAggregator::SetIntermediateResults(
111cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<ReadyRect>& ready,
112cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const std::vector<pp::Rect>& pending) {
113cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  update_.ready_rects.insert(
114cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      update_.ready_rects.end(), ready.begin(), ready.end());
115cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  update_.paint_rects = pending;
116cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
117cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
118cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)std::vector<PaintAggregator::ReadyRect> PaintAggregator::GetReadyRects() const {
119cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return update_.ready_rects;
120cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
121cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
122cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PaintAggregator::InvalidateRect(const pp::Rect& rect) {
123cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  InvalidateRectInternal(rect, true);
124cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
125cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
126cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PaintAggregator::ScrollRect(const pp::Rect& clip_rect,
127cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                 const pp::Point& amount) {
128cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We only support scrolling along one axis at a time.
129cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (amount.x() != 0 && amount.y() != 0) {
130cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    InvalidateRect(clip_rect);
131cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
132cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
133cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
134cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We can only scroll one rect at a time.
135cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (!update_.scroll_rect.IsEmpty() && update_.scroll_rect != clip_rect) {
136cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    InvalidateRect(clip_rect);
137cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
138cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
139cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
140cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Again, we only support scrolling along one axis at a time.  Make sure this
141cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // update doesn't scroll on a different axis than any existing one.
142cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if ((amount.x() && update_.scroll_delta.y()) ||
143cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      (amount.y() && update_.scroll_delta.x())) {
144cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    InvalidateRect(clip_rect);
145cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
146cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
147cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
148cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // The scroll rect is new or isn't changing (though the scroll amount may
149cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // be changing).
150cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  update_.scroll_rect = clip_rect;
151cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  update_.scroll_delta += amount;
152cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
153cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // We might have just wiped out a pre-existing scroll.
154cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (update_.scroll_delta == pp::Point()) {
155cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    update_.scroll_rect = pp::Rect();
156cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    return;
157cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
158cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
159cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Adjust any paint rects that intersect the scroll. For the portion of the
160cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // paint that is inside the scroll area, move it by the scroll amount and
161cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // replace the existing paint with it. For the portion (if any) that is
162cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // outside the scroll, just invalidate it.
163cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  std::vector<pp::Rect> leftover_rects;
164cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < update_.paint_rects.size(); ++i) {
165cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (!update_.scroll_rect.Intersects(update_.paint_rects[i]))
166cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      continue;
167cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
168cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    pp::Rect intersection =
169cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        update_.paint_rects[i].Intersect(update_.scroll_rect);
170cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    pp::Rect rect = update_.paint_rects[i];
171cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    while (!rect.IsEmpty()) {
172cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      pp::Rect leftover = rect.Subtract(intersection);
173cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      if (leftover.IsEmpty())
174cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)        break;
175cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Don't want to call InvalidateRectInternal now since it'll modify
176cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // update_.paint_rects, so keep track of this and do it below.
177cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      leftover_rects.push_back(leftover);
178cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      rect = rect.Subtract(leftover);
179cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
180cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
181cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    update_.paint_rects[i] = ScrollPaintRect(intersection, amount);
182cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
183cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // The rect may have been scrolled out of view.
184cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (update_.paint_rects[i].IsEmpty()) {
185cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      update_.paint_rects.erase(update_.paint_rects.begin() + i);
186cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      i--;
187cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
188cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
189cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
190cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < leftover_rects.size(); ++i)
191cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    InvalidateRectInternal(leftover_rects[i], false);
192cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
193cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < update_.ready_rects.size(); ++i) {
194cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (update_.scroll_rect.Contains(update_.ready_rects[i].rect)) {
195cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      update_.ready_rects[i].rect =
196cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)          ScrollPaintRect(update_.ready_rects[i].rect, amount);
197cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
198cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
199cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
200cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (update_.synthesized_scroll_damage_rect_) {
201cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    pp::Rect damage = update_.GetScrollDamage();
202cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    InvalidateRect(damage);
203cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
204cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
205cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
206cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)pp::Rect PaintAggregator::ScrollPaintRect(const pp::Rect& paint_rect,
207cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                          const pp::Point& amount) const {
208cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pp::Rect result = paint_rect;
209cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  result.Offset(amount);
210cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  result = update_.scroll_rect.Intersect(result);
211cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  return result;
212cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
213cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
214cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PaintAggregator::InvalidateScrollRect() {
215cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pp::Rect scroll_rect = update_.scroll_rect;
216cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  update_.scroll_rect = pp::Rect();
217cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  update_.scroll_delta = pp::Point();
218cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  InvalidateRect(scroll_rect);
219cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
220cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
221cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)void PaintAggregator::InvalidateRectInternal(const pp::Rect& rect_old,
222cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)                                             bool check_scroll) {
223cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  pp::Rect rect = rect_old;
224cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Check if any rects that are ready to be painted overlap.
225cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < update_.ready_rects.size(); ++i) {
226cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const pp::Rect& existing_rect = update_.ready_rects[i].rect;
227cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (rect.Intersects(existing_rect)) {
228cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Re-invalidate in case the union intersects other paint rects.
229cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      rect = existing_rect.Union(rect);
230cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      update_.ready_rects.erase(update_.ready_rects.begin() + i);
231cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      break;
232cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
233cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
234cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
235cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  bool add_paint = true;
236cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
237cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // Combine overlapping paints using smallest bounding box.
238cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  for (size_t i = 0; i < update_.paint_rects.size(); ++i) {
239cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    const pp::Rect& existing_rect = update_.paint_rects[i];
240cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (existing_rect.Contains(rect))  // Optimize out redundancy.
241cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      add_paint = false;
242cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    if (rect.Intersects(existing_rect) || rect.SharesEdgeWith(existing_rect)) {
243cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      // Re-invalidate in case the union intersects other paint rects.
244cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      pp::Rect combined_rect = existing_rect.Union(rect);
245cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      update_.paint_rects.erase(update_.paint_rects.begin() + i);
246cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      InvalidateRectInternal(combined_rect, check_scroll);
247cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      add_paint = false;
248cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    }
249cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
250cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
251cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (add_paint) {
252cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    // Add a non-overlapping paint.
253cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    update_.paint_rects.push_back(rect);
254cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
255cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)
256cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // If the new paint overlaps with a scroll, then also invalidate the rect in
257cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  // its new position.
258cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  if (check_scroll &&
259cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      !update_.scroll_rect.IsEmpty() &&
260cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)      update_.scroll_rect.Intersects(rect)) {
261cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)    InvalidateRectInternal(ScrollPaintRect(rect, update_.scroll_delta), false);
262cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)  }
263cedac228d2dd51db4b79ea1e72c7f249408ee061Torne (Richard Coles)}
264