2 * Copyright (C) 2010 Google Inc. All rights reserved.
4 * Redistribution and use in source and binary forms, with or without
5 * modification, are permitted provided that the following conditions are
8 * * Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * * Redistributions in binary form must reproduce the above
11 * copyright notice, this list of conditions and the following disclaimer
12 * in the documentation and/or other materials provided with the
14 * * Neither the name of Google Inc. nor the names of its
15 * contributors may be used to endorse or promote products derived from
16 * this software without specific prior written permission.
18 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
19 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
20 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
21 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
22 * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
23 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
24 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
25 * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
26 * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
27 * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
28 * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
32 #include "web/painting/PaintAggregator.h"
34 #include <gtest/gtest.h>
36 using namespace WebCore;
37 using namespace blink;
41 TEST(PaintAggregator, InitialState)
44 EXPECT_FALSE(greg.hasPendingUpdate());
47 TEST(PaintAggregator, SingleInvalidation)
51 IntRect rect(2, 4, 10, 16);
52 greg.invalidateRect(rect);
54 EXPECT_TRUE(greg.hasPendingUpdate());
55 PaintAggregator::PendingUpdate update;
56 greg.popPendingUpdate(&update);
58 EXPECT_TRUE(update.scrollRect.isEmpty());
59 ASSERT_EQ(1U, update.paintRects.size());
61 EXPECT_EQ(rect, update.paintRects[0]);
64 TEST(PaintAggregator, DoubleDisjointInvalidation)
68 IntRect r1(2, 4, 2, 40);
69 IntRect r2(4, 2, 40, 2);
71 greg.invalidateRect(r1);
72 greg.invalidateRect(r2);
74 IntRect expectedBounds = unionRect(r1, r2);
76 EXPECT_TRUE(greg.hasPendingUpdate());
77 PaintAggregator::PendingUpdate update;
78 greg.popPendingUpdate(&update);
80 EXPECT_TRUE(update.scrollRect.isEmpty());
81 EXPECT_EQ(2U, update.paintRects.size());
83 EXPECT_EQ(expectedBounds, update.calculatePaintBounds());
86 TEST(PaintAggregator, DisjointInvalidationsCombined)
90 // Make the rectangles such that they don't overlap but cover a very large
91 // percentage of the area of covered by their union. This is so we're not
92 // very sensitive to the combining heuristic in the paint aggregator.
93 IntRect r1(2, 4, 2, 1000);
94 IntRect r2(5, 2, 2, 1000);
96 greg.invalidateRect(r1);
97 greg.invalidateRect(r2);
99 IntRect expectedBounds = unionRect(r1, r2);
101 EXPECT_TRUE(greg.hasPendingUpdate());
102 PaintAggregator::PendingUpdate update;
103 greg.popPendingUpdate(&update);
105 EXPECT_TRUE(update.scrollRect.isEmpty());
106 ASSERT_EQ(1U, update.paintRects.size());
108 EXPECT_EQ(expectedBounds, update.paintRects[0]);
111 TEST(PaintAggregator, SingleScroll)
113 PaintAggregator greg;
115 IntRect rect(1, 2, 3, 4);
116 IntPoint delta(1, 0);
117 greg.scrollRect(delta.x(), delta.y(), rect);
119 EXPECT_TRUE(greg.hasPendingUpdate());
120 PaintAggregator::PendingUpdate update;
121 greg.popPendingUpdate(&update);
123 EXPECT_TRUE(update.paintRects.isEmpty());
124 EXPECT_FALSE(update.scrollRect.isEmpty());
126 EXPECT_EQ(rect, update.scrollRect);
128 EXPECT_EQ(delta.x(), update.scrollDelta.x());
129 EXPECT_EQ(delta.y(), update.scrollDelta.y());
131 IntRect resultingDamage = update.calculateScrollDamage();
132 IntRect expectedDamage(1, 2, 1, 4);
133 EXPECT_EQ(expectedDamage, resultingDamage);
136 TEST(PaintAggregator, DoubleOverlappingScroll)
138 PaintAggregator greg;
140 IntRect rect(1, 2, 3, 4);
141 IntPoint delta1(1, 0);
142 IntPoint delta2(1, 0);
143 greg.scrollRect(delta1.x(), delta1.y(), rect);
144 greg.scrollRect(delta2.x(), delta2.y(), rect);
146 EXPECT_TRUE(greg.hasPendingUpdate());
147 PaintAggregator::PendingUpdate update;
148 greg.popPendingUpdate(&update);
150 EXPECT_TRUE(update.paintRects.isEmpty());
151 EXPECT_FALSE(update.scrollRect.isEmpty());
153 EXPECT_EQ(rect, update.scrollRect);
155 IntPoint expectedDelta(delta1.x() + delta2.x(),
156 delta1.y() + delta2.y());
157 EXPECT_EQ(expectedDelta.x(), update.scrollDelta.x());
158 EXPECT_EQ(expectedDelta.y(), update.scrollDelta.y());
160 IntRect resultingDamage = update.calculateScrollDamage();
161 IntRect expectedDamage(1, 2, 2, 4);
162 EXPECT_EQ(expectedDamage, resultingDamage);
165 TEST(PaintAggregator, NegatingScroll)
167 PaintAggregator greg;
169 // Scroll twice in opposite directions by equal amounts. The result
170 // should be no scrolling.
172 IntRect rect(1, 2, 3, 4);
173 IntPoint delta1(1, 0);
174 IntPoint delta2(-1, 0);
175 greg.scrollRect(delta1.x(), delta1.y(), rect);
176 greg.scrollRect(delta2.x(), delta2.y(), rect);
178 EXPECT_FALSE(greg.hasPendingUpdate());
181 TEST(PaintAggregator, DiagonalScroll)
183 PaintAggregator greg;
185 // We don't support optimized diagonal scrolling, so this should result in
188 IntRect rect(1, 2, 3, 4);
189 IntPoint delta(1, 1);
190 greg.scrollRect(delta.x(), delta.y(), rect);
192 EXPECT_TRUE(greg.hasPendingUpdate());
193 PaintAggregator::PendingUpdate update;
194 greg.popPendingUpdate(&update);
196 EXPECT_TRUE(update.scrollRect.isEmpty());
197 ASSERT_EQ(1U, update.paintRects.size());
199 EXPECT_EQ(rect, update.paintRects[0]);
202 TEST(PaintAggregator, ContainedPaintAfterScroll)
204 PaintAggregator greg;
206 IntRect scrollRect(0, 0, 10, 10);
207 greg.scrollRect(2, 0, scrollRect);
209 IntRect paintRect(4, 4, 2, 2);
210 greg.invalidateRect(paintRect);
212 EXPECT_TRUE(greg.hasPendingUpdate());
213 PaintAggregator::PendingUpdate update;
214 greg.popPendingUpdate(&update);
216 // expecting a paint rect inside the scroll rect
217 EXPECT_FALSE(update.scrollRect.isEmpty());
218 EXPECT_EQ(1U, update.paintRects.size());
220 EXPECT_EQ(scrollRect, update.scrollRect);
221 EXPECT_EQ(paintRect, update.paintRects[0]);
224 TEST(PaintAggregator, ContainedPaintBeforeScroll)
226 PaintAggregator greg;
228 IntRect paintRect(4, 4, 2, 2);
229 greg.invalidateRect(paintRect);
231 IntRect scrollRect(0, 0, 10, 10);
232 greg.scrollRect(2, 0, scrollRect);
234 EXPECT_TRUE(greg.hasPendingUpdate());
235 PaintAggregator::PendingUpdate update;
236 greg.popPendingUpdate(&update);
238 // Expecting a paint rect inside the scroll rect
239 EXPECT_FALSE(update.scrollRect.isEmpty());
240 EXPECT_EQ(1U, update.paintRects.size());
242 paintRect.move(2, 0);
244 EXPECT_EQ(scrollRect, update.scrollRect);
245 EXPECT_EQ(paintRect, update.paintRects[0]);
248 TEST(PaintAggregator, ContainedPaintsBeforeAndAfterScroll)
250 PaintAggregator greg;
252 IntRect paintRect1(4, 4, 2, 2);
253 greg.invalidateRect(paintRect1);
255 IntRect scrollRect(0, 0, 10, 10);
256 greg.scrollRect(2, 0, scrollRect);
258 IntRect paintRect2(6, 4, 2, 2);
259 greg.invalidateRect(paintRect2);
261 IntRect expectedPaintRect = paintRect2;
263 EXPECT_TRUE(greg.hasPendingUpdate());
264 PaintAggregator::PendingUpdate update;
265 greg.popPendingUpdate(&update);
267 // Expecting a paint rect inside the scroll rect
268 EXPECT_FALSE(update.scrollRect.isEmpty());
269 EXPECT_EQ(1U, update.paintRects.size());
271 EXPECT_EQ(scrollRect, update.scrollRect);
272 EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
275 TEST(PaintAggregator, LargeContainedPaintAfterScroll)
277 PaintAggregator greg;
279 IntRect scrollRect(0, 0, 10, 10);
280 greg.scrollRect(0, 1, scrollRect);
282 IntRect paintRect(0, 0, 10, 9); // Repaint 90%
283 greg.invalidateRect(paintRect);
285 EXPECT_TRUE(greg.hasPendingUpdate());
286 PaintAggregator::PendingUpdate update;
287 greg.popPendingUpdate(&update);
289 EXPECT_TRUE(update.scrollRect.isEmpty());
290 EXPECT_EQ(1U, update.paintRects.size());
292 EXPECT_EQ(scrollRect, update.paintRects[0]);
295 TEST(PaintAggregator, LargeContainedPaintBeforeScroll)
297 PaintAggregator greg;
299 IntRect paintRect(0, 0, 10, 9); // Repaint 90%
300 greg.invalidateRect(paintRect);
302 IntRect scrollRect(0, 0, 10, 10);
303 greg.scrollRect(0, 1, scrollRect);
305 EXPECT_TRUE(greg.hasPendingUpdate());
306 PaintAggregator::PendingUpdate update;
307 greg.popPendingUpdate(&update);
309 EXPECT_TRUE(update.scrollRect.isEmpty());
310 EXPECT_EQ(1U, update.paintRects.size());
312 EXPECT_EQ(scrollRect, update.paintRects[0]);
315 TEST(PaintAggregator, OverlappingPaintBeforeScroll)
317 PaintAggregator greg;
319 IntRect paintRect(4, 4, 10, 2);
320 greg.invalidateRect(paintRect);
322 IntRect scrollRect(0, 0, 10, 10);
323 greg.scrollRect(2, 0, scrollRect);
325 IntRect expectedPaintRect = unionRect(scrollRect, paintRect);
327 EXPECT_TRUE(greg.hasPendingUpdate());
328 PaintAggregator::PendingUpdate update;
329 greg.popPendingUpdate(&update);
331 EXPECT_TRUE(update.scrollRect.isEmpty());
332 EXPECT_EQ(1U, update.paintRects.size());
334 EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
337 TEST(PaintAggregator, OverlappingPaintAfterScroll)
339 PaintAggregator greg;
341 IntRect scrollRect(0, 0, 10, 10);
342 greg.scrollRect(2, 0, scrollRect);
344 IntRect paintRect(4, 4, 10, 2);
345 greg.invalidateRect(paintRect);
347 IntRect expectedPaintRect = unionRect(scrollRect, paintRect);
349 EXPECT_TRUE(greg.hasPendingUpdate());
350 PaintAggregator::PendingUpdate update;
351 greg.popPendingUpdate(&update);
353 EXPECT_TRUE(update.scrollRect.isEmpty());
354 EXPECT_EQ(1U, update.paintRects.size());
356 EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
359 TEST(PaintAggregator, DisjointPaintBeforeScroll)
361 PaintAggregator greg;
363 IntRect paintRect(4, 4, 10, 2);
364 greg.invalidateRect(paintRect);
366 IntRect scrollRect(0, 0, 2, 10);
367 greg.scrollRect(2, 0, scrollRect);
369 EXPECT_TRUE(greg.hasPendingUpdate());
370 PaintAggregator::PendingUpdate update;
371 greg.popPendingUpdate(&update);
373 EXPECT_FALSE(update.scrollRect.isEmpty());
374 EXPECT_EQ(1U, update.paintRects.size());
376 EXPECT_EQ(paintRect, update.paintRects[0]);
377 EXPECT_EQ(scrollRect, update.scrollRect);
380 TEST(PaintAggregator, DisjointPaintAfterScroll)
382 PaintAggregator greg;
384 IntRect scrollRect(0, 0, 2, 10);
385 greg.scrollRect(2, 0, scrollRect);
387 IntRect paintRect(4, 4, 10, 2);
388 greg.invalidateRect(paintRect);
390 EXPECT_TRUE(greg.hasPendingUpdate());
391 PaintAggregator::PendingUpdate update;
392 greg.popPendingUpdate(&update);
394 EXPECT_FALSE(update.scrollRect.isEmpty());
395 EXPECT_EQ(1U, update.paintRects.size());
397 EXPECT_EQ(paintRect, update.paintRects[0]);
398 EXPECT_EQ(scrollRect, update.scrollRect);
401 TEST(PaintAggregator, ContainedPaintTrimmedByScroll)
403 PaintAggregator greg;
405 IntRect paintRect(4, 4, 6, 6);
406 greg.invalidateRect(paintRect);
408 IntRect scrollRect(0, 0, 10, 10);
409 greg.scrollRect(2, 0, scrollRect);
411 // The paint rect should have become narrower.
412 IntRect expectedPaintRect(6, 4, 4, 6);
414 EXPECT_TRUE(greg.hasPendingUpdate());
415 PaintAggregator::PendingUpdate update;
416 greg.popPendingUpdate(&update);
418 EXPECT_FALSE(update.scrollRect.isEmpty());
419 EXPECT_EQ(1U, update.paintRects.size());
421 EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
422 EXPECT_EQ(scrollRect, update.scrollRect);
425 TEST(PaintAggregator, ContainedPaintEliminatedByScroll)
427 PaintAggregator greg;
429 IntRect paintRect(4, 4, 6, 6);
430 greg.invalidateRect(paintRect);
432 IntRect scrollRect(0, 0, 10, 10);
433 greg.scrollRect(6, 0, scrollRect);
435 EXPECT_TRUE(greg.hasPendingUpdate());
436 PaintAggregator::PendingUpdate update;
437 greg.popPendingUpdate(&update);
439 EXPECT_FALSE(update.scrollRect.isEmpty());
440 EXPECT_TRUE(update.paintRects.isEmpty());
442 EXPECT_EQ(scrollRect, update.scrollRect);
445 TEST(PaintAggregator, ContainedPaintAfterScrollTrimmedByScrollDamage)
447 PaintAggregator greg;
449 IntRect scrollRect(0, 0, 10, 10);
450 greg.scrollRect(4, 0, scrollRect);
452 IntRect paintRect(2, 0, 4, 10);
453 greg.invalidateRect(paintRect);
455 IntRect expectedScrollDamage(0, 0, 4, 10);
456 IntRect expectedPaintRect(4, 0, 2, 10);
458 EXPECT_TRUE(greg.hasPendingUpdate());
459 PaintAggregator::PendingUpdate update;
460 greg.popPendingUpdate(&update);
462 EXPECT_FALSE(update.scrollRect.isEmpty());
463 EXPECT_EQ(1U, update.paintRects.size());
465 EXPECT_EQ(scrollRect, update.scrollRect);
466 EXPECT_EQ(expectedScrollDamage, update.calculateScrollDamage());
467 EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
470 TEST(PaintAggregator, ContainedPaintAfterScrollEliminatedByScrollDamage)
472 PaintAggregator greg;
474 IntRect scrollRect(0, 0, 10, 10);
475 greg.scrollRect(4, 0, scrollRect);
477 IntRect paintRect(2, 0, 2, 10);
478 greg.invalidateRect(paintRect);
480 IntRect expectedScrollDamage(0, 0, 4, 10);
482 EXPECT_TRUE(greg.hasPendingUpdate());
483 PaintAggregator::PendingUpdate update;
484 greg.popPendingUpdate(&update);
486 EXPECT_FALSE(update.scrollRect.isEmpty());
487 EXPECT_TRUE(update.paintRects.isEmpty());
489 EXPECT_EQ(scrollRect, update.scrollRect);
490 EXPECT_EQ(expectedScrollDamage, update.calculateScrollDamage());