• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2010 Google Inc. All rights reserved.
3  *
4  * Redistribution and use in source and binary forms, with or without
5  * modification, are permitted provided that the following conditions are
6  * met:
7  *
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
13  * distribution.
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.
17  *
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.
29  */
30 
31 #include "config.h"
32 #include "web/painting/PaintAggregator.h"
33 
34 #include <gtest/gtest.h>
35 
36 using namespace blink;
37 
38 namespace {
39 
TEST(PaintAggregator,InitialState)40 TEST(PaintAggregator, InitialState)
41 {
42     PaintAggregator greg;
43     EXPECT_FALSE(greg.hasPendingUpdate());
44 }
45 
TEST(PaintAggregator,SingleInvalidation)46 TEST(PaintAggregator, SingleInvalidation)
47 {
48     PaintAggregator greg;
49 
50     IntRect rect(2, 4, 10, 16);
51     greg.invalidateRect(rect);
52 
53     EXPECT_TRUE(greg.hasPendingUpdate());
54     PaintAggregator::PendingUpdate update;
55     greg.popPendingUpdate(&update);
56 
57     EXPECT_TRUE(update.scrollRect.isEmpty());
58     ASSERT_EQ(1U, update.paintRects.size());
59 
60     EXPECT_EQ(rect, update.paintRects[0]);
61 }
62 
TEST(PaintAggregator,DoubleDisjointInvalidation)63 TEST(PaintAggregator, DoubleDisjointInvalidation)
64 {
65     PaintAggregator greg;
66 
67     IntRect r1(2, 4, 2, 40);
68     IntRect r2(4, 2, 40, 2);
69 
70     greg.invalidateRect(r1);
71     greg.invalidateRect(r2);
72 
73     IntRect expectedBounds = unionRect(r1, r2);
74 
75     EXPECT_TRUE(greg.hasPendingUpdate());
76     PaintAggregator::PendingUpdate update;
77     greg.popPendingUpdate(&update);
78 
79     EXPECT_TRUE(update.scrollRect.isEmpty());
80     EXPECT_EQ(2U, update.paintRects.size());
81 
82     EXPECT_EQ(expectedBounds, update.calculatePaintBounds());
83 }
84 
TEST(PaintAggregator,DisjointInvalidationsCombined)85 TEST(PaintAggregator, DisjointInvalidationsCombined)
86 {
87     PaintAggregator greg;
88 
89     // Make the rectangles such that they don't overlap but cover a very large
90     // percentage of the area of covered by their union. This is so we're not
91     // very sensitive to the combining heuristic in the paint aggregator.
92     IntRect r1(2, 4, 2, 1000);
93     IntRect r2(5, 2, 2, 1000);
94 
95     greg.invalidateRect(r1);
96     greg.invalidateRect(r2);
97 
98     IntRect expectedBounds = unionRect(r1, r2);
99 
100     EXPECT_TRUE(greg.hasPendingUpdate());
101     PaintAggregator::PendingUpdate update;
102     greg.popPendingUpdate(&update);
103 
104     EXPECT_TRUE(update.scrollRect.isEmpty());
105     ASSERT_EQ(1U, update.paintRects.size());
106 
107     EXPECT_EQ(expectedBounds, update.paintRects[0]);
108 }
109 
TEST(PaintAggregator,SingleScroll)110 TEST(PaintAggregator, SingleScroll)
111 {
112     PaintAggregator greg;
113 
114     IntRect rect(1, 2, 3, 4);
115     IntPoint delta(1, 0);
116     greg.scrollRect(delta.x(), delta.y(), rect);
117 
118     EXPECT_TRUE(greg.hasPendingUpdate());
119     PaintAggregator::PendingUpdate update;
120     greg.popPendingUpdate(&update);
121 
122     EXPECT_TRUE(update.paintRects.isEmpty());
123     EXPECT_FALSE(update.scrollRect.isEmpty());
124 
125     EXPECT_EQ(rect, update.scrollRect);
126 
127     EXPECT_EQ(delta.x(), update.scrollDelta.x());
128     EXPECT_EQ(delta.y(), update.scrollDelta.y());
129 
130     IntRect resultingDamage = update.calculateScrollDamage();
131     IntRect expectedDamage(1, 2, 1, 4);
132     EXPECT_EQ(expectedDamage, resultingDamage);
133 }
134 
TEST(PaintAggregator,DoubleOverlappingScroll)135 TEST(PaintAggregator, DoubleOverlappingScroll)
136 {
137     PaintAggregator greg;
138 
139     IntRect rect(1, 2, 3, 4);
140     IntPoint delta1(1, 0);
141     IntPoint delta2(1, 0);
142     greg.scrollRect(delta1.x(), delta1.y(), rect);
143     greg.scrollRect(delta2.x(), delta2.y(), rect);
144 
145     EXPECT_TRUE(greg.hasPendingUpdate());
146     PaintAggregator::PendingUpdate update;
147     greg.popPendingUpdate(&update);
148 
149     EXPECT_TRUE(update.paintRects.isEmpty());
150     EXPECT_FALSE(update.scrollRect.isEmpty());
151 
152     EXPECT_EQ(rect, update.scrollRect);
153 
154     IntPoint expectedDelta(delta1.x() + delta2.x(),
155                            delta1.y() + delta2.y());
156     EXPECT_EQ(expectedDelta.x(), update.scrollDelta.x());
157     EXPECT_EQ(expectedDelta.y(), update.scrollDelta.y());
158 
159     IntRect resultingDamage = update.calculateScrollDamage();
160     IntRect expectedDamage(1, 2, 2, 4);
161     EXPECT_EQ(expectedDamage, resultingDamage);
162 }
163 
TEST(PaintAggregator,NegatingScroll)164 TEST(PaintAggregator, NegatingScroll)
165 {
166     PaintAggregator greg;
167 
168     // Scroll twice in opposite directions by equal amounts. The result
169     // should be no scrolling.
170 
171     IntRect rect(1, 2, 3, 4);
172     IntPoint delta1(1, 0);
173     IntPoint delta2(-1, 0);
174     greg.scrollRect(delta1.x(), delta1.y(), rect);
175     greg.scrollRect(delta2.x(), delta2.y(), rect);
176 
177     EXPECT_FALSE(greg.hasPendingUpdate());
178 }
179 
TEST(PaintAggregator,DiagonalScroll)180 TEST(PaintAggregator, DiagonalScroll)
181 {
182     PaintAggregator greg;
183 
184     // We don't support optimized diagonal scrolling, so this should result in
185     // repainting.
186 
187     IntRect rect(1, 2, 3, 4);
188     IntPoint delta(1, 1);
189     greg.scrollRect(delta.x(), delta.y(), rect);
190 
191     EXPECT_TRUE(greg.hasPendingUpdate());
192     PaintAggregator::PendingUpdate update;
193     greg.popPendingUpdate(&update);
194 
195     EXPECT_TRUE(update.scrollRect.isEmpty());
196     ASSERT_EQ(1U, update.paintRects.size());
197 
198     EXPECT_EQ(rect, update.paintRects[0]);
199 }
200 
TEST(PaintAggregator,ContainedPaintAfterScroll)201 TEST(PaintAggregator, ContainedPaintAfterScroll)
202 {
203     PaintAggregator greg;
204 
205     IntRect scrollRect(0, 0, 10, 10);
206     greg.scrollRect(2, 0, scrollRect);
207 
208     IntRect paintRect(4, 4, 2, 2);
209     greg.invalidateRect(paintRect);
210 
211     EXPECT_TRUE(greg.hasPendingUpdate());
212     PaintAggregator::PendingUpdate update;
213     greg.popPendingUpdate(&update);
214 
215     // expecting a paint rect inside the scroll rect
216     EXPECT_FALSE(update.scrollRect.isEmpty());
217     EXPECT_EQ(1U, update.paintRects.size());
218 
219     EXPECT_EQ(scrollRect, update.scrollRect);
220     EXPECT_EQ(paintRect, update.paintRects[0]);
221 }
222 
TEST(PaintAggregator,ContainedPaintBeforeScroll)223 TEST(PaintAggregator, ContainedPaintBeforeScroll)
224 {
225     PaintAggregator greg;
226 
227     IntRect paintRect(4, 4, 2, 2);
228     greg.invalidateRect(paintRect);
229 
230     IntRect scrollRect(0, 0, 10, 10);
231     greg.scrollRect(2, 0, scrollRect);
232 
233     EXPECT_TRUE(greg.hasPendingUpdate());
234     PaintAggregator::PendingUpdate update;
235     greg.popPendingUpdate(&update);
236 
237     // Expecting a paint rect inside the scroll rect
238     EXPECT_FALSE(update.scrollRect.isEmpty());
239     EXPECT_EQ(1U, update.paintRects.size());
240 
241     paintRect.move(2, 0);
242 
243     EXPECT_EQ(scrollRect, update.scrollRect);
244     EXPECT_EQ(paintRect, update.paintRects[0]);
245 }
246 
TEST(PaintAggregator,ContainedPaintsBeforeAndAfterScroll)247 TEST(PaintAggregator, ContainedPaintsBeforeAndAfterScroll)
248 {
249     PaintAggregator greg;
250 
251     IntRect paintRect1(4, 4, 2, 2);
252     greg.invalidateRect(paintRect1);
253 
254     IntRect scrollRect(0, 0, 10, 10);
255     greg.scrollRect(2, 0, scrollRect);
256 
257     IntRect paintRect2(6, 4, 2, 2);
258     greg.invalidateRect(paintRect2);
259 
260     IntRect expectedPaintRect = paintRect2;
261 
262     EXPECT_TRUE(greg.hasPendingUpdate());
263     PaintAggregator::PendingUpdate update;
264     greg.popPendingUpdate(&update);
265 
266     // Expecting a paint rect inside the scroll rect
267     EXPECT_FALSE(update.scrollRect.isEmpty());
268     EXPECT_EQ(1U, update.paintRects.size());
269 
270     EXPECT_EQ(scrollRect, update.scrollRect);
271     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
272 }
273 
TEST(PaintAggregator,LargeContainedPaintAfterScroll)274 TEST(PaintAggregator, LargeContainedPaintAfterScroll)
275 {
276     PaintAggregator greg;
277 
278     IntRect scrollRect(0, 0, 10, 10);
279     greg.scrollRect(0, 1, scrollRect);
280 
281     IntRect paintRect(0, 0, 10, 9); // Repaint 90%
282     greg.invalidateRect(paintRect);
283 
284     EXPECT_TRUE(greg.hasPendingUpdate());
285     PaintAggregator::PendingUpdate update;
286     greg.popPendingUpdate(&update);
287 
288     EXPECT_TRUE(update.scrollRect.isEmpty());
289     EXPECT_EQ(1U, update.paintRects.size());
290 
291     EXPECT_EQ(scrollRect, update.paintRects[0]);
292 }
293 
TEST(PaintAggregator,LargeContainedPaintBeforeScroll)294 TEST(PaintAggregator, LargeContainedPaintBeforeScroll)
295 {
296     PaintAggregator greg;
297 
298     IntRect paintRect(0, 0, 10, 9); // Repaint 90%
299     greg.invalidateRect(paintRect);
300 
301     IntRect scrollRect(0, 0, 10, 10);
302     greg.scrollRect(0, 1, scrollRect);
303 
304     EXPECT_TRUE(greg.hasPendingUpdate());
305     PaintAggregator::PendingUpdate update;
306     greg.popPendingUpdate(&update);
307 
308     EXPECT_TRUE(update.scrollRect.isEmpty());
309     EXPECT_EQ(1U, update.paintRects.size());
310 
311     EXPECT_EQ(scrollRect, update.paintRects[0]);
312 }
313 
TEST(PaintAggregator,OverlappingPaintBeforeScroll)314 TEST(PaintAggregator, OverlappingPaintBeforeScroll)
315 {
316     PaintAggregator greg;
317 
318     IntRect paintRect(4, 4, 10, 2);
319     greg.invalidateRect(paintRect);
320 
321     IntRect scrollRect(0, 0, 10, 10);
322     greg.scrollRect(2, 0, scrollRect);
323 
324     IntRect expectedPaintRect = unionRect(scrollRect, paintRect);
325 
326     EXPECT_TRUE(greg.hasPendingUpdate());
327     PaintAggregator::PendingUpdate update;
328     greg.popPendingUpdate(&update);
329 
330     EXPECT_TRUE(update.scrollRect.isEmpty());
331     EXPECT_EQ(1U, update.paintRects.size());
332 
333     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
334 }
335 
TEST(PaintAggregator,OverlappingPaintAfterScroll)336 TEST(PaintAggregator, OverlappingPaintAfterScroll)
337 {
338     PaintAggregator greg;
339 
340     IntRect scrollRect(0, 0, 10, 10);
341     greg.scrollRect(2, 0, scrollRect);
342 
343     IntRect paintRect(4, 4, 10, 2);
344     greg.invalidateRect(paintRect);
345 
346     IntRect expectedPaintRect = unionRect(scrollRect, paintRect);
347 
348     EXPECT_TRUE(greg.hasPendingUpdate());
349     PaintAggregator::PendingUpdate update;
350     greg.popPendingUpdate(&update);
351 
352     EXPECT_TRUE(update.scrollRect.isEmpty());
353     EXPECT_EQ(1U, update.paintRects.size());
354 
355     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
356 }
357 
TEST(PaintAggregator,DisjointPaintBeforeScroll)358 TEST(PaintAggregator, DisjointPaintBeforeScroll)
359 {
360     PaintAggregator greg;
361 
362     IntRect paintRect(4, 4, 10, 2);
363     greg.invalidateRect(paintRect);
364 
365     IntRect scrollRect(0, 0, 2, 10);
366     greg.scrollRect(2, 0, scrollRect);
367 
368     EXPECT_TRUE(greg.hasPendingUpdate());
369     PaintAggregator::PendingUpdate update;
370     greg.popPendingUpdate(&update);
371 
372     EXPECT_FALSE(update.scrollRect.isEmpty());
373     EXPECT_EQ(1U, update.paintRects.size());
374 
375     EXPECT_EQ(paintRect, update.paintRects[0]);
376     EXPECT_EQ(scrollRect, update.scrollRect);
377 }
378 
TEST(PaintAggregator,DisjointPaintAfterScroll)379 TEST(PaintAggregator, DisjointPaintAfterScroll)
380 {
381     PaintAggregator greg;
382 
383     IntRect scrollRect(0, 0, 2, 10);
384     greg.scrollRect(2, 0, scrollRect);
385 
386     IntRect paintRect(4, 4, 10, 2);
387     greg.invalidateRect(paintRect);
388 
389     EXPECT_TRUE(greg.hasPendingUpdate());
390     PaintAggregator::PendingUpdate update;
391     greg.popPendingUpdate(&update);
392 
393     EXPECT_FALSE(update.scrollRect.isEmpty());
394     EXPECT_EQ(1U, update.paintRects.size());
395 
396     EXPECT_EQ(paintRect, update.paintRects[0]);
397     EXPECT_EQ(scrollRect, update.scrollRect);
398 }
399 
TEST(PaintAggregator,ContainedPaintTrimmedByScroll)400 TEST(PaintAggregator, ContainedPaintTrimmedByScroll)
401 {
402     PaintAggregator greg;
403 
404     IntRect paintRect(4, 4, 6, 6);
405     greg.invalidateRect(paintRect);
406 
407     IntRect scrollRect(0, 0, 10, 10);
408     greg.scrollRect(2, 0, scrollRect);
409 
410     // The paint rect should have become narrower.
411     IntRect expectedPaintRect(6, 4, 4, 6);
412 
413     EXPECT_TRUE(greg.hasPendingUpdate());
414     PaintAggregator::PendingUpdate update;
415     greg.popPendingUpdate(&update);
416 
417     EXPECT_FALSE(update.scrollRect.isEmpty());
418     EXPECT_EQ(1U, update.paintRects.size());
419 
420     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
421     EXPECT_EQ(scrollRect, update.scrollRect);
422 }
423 
TEST(PaintAggregator,ContainedPaintEliminatedByScroll)424 TEST(PaintAggregator, ContainedPaintEliminatedByScroll)
425 {
426     PaintAggregator greg;
427 
428     IntRect paintRect(4, 4, 6, 6);
429     greg.invalidateRect(paintRect);
430 
431     IntRect scrollRect(0, 0, 10, 10);
432     greg.scrollRect(6, 0, scrollRect);
433 
434     EXPECT_TRUE(greg.hasPendingUpdate());
435     PaintAggregator::PendingUpdate update;
436     greg.popPendingUpdate(&update);
437 
438     EXPECT_FALSE(update.scrollRect.isEmpty());
439     EXPECT_TRUE(update.paintRects.isEmpty());
440 
441     EXPECT_EQ(scrollRect, update.scrollRect);
442 }
443 
TEST(PaintAggregator,ContainedPaintAfterScrollTrimmedByScrollDamage)444 TEST(PaintAggregator, ContainedPaintAfterScrollTrimmedByScrollDamage)
445 {
446     PaintAggregator greg;
447 
448     IntRect scrollRect(0, 0, 10, 10);
449     greg.scrollRect(4, 0, scrollRect);
450 
451     IntRect paintRect(2, 0, 4, 10);
452     greg.invalidateRect(paintRect);
453 
454     IntRect expectedScrollDamage(0, 0, 4, 10);
455     IntRect expectedPaintRect(4, 0, 2, 10);
456 
457     EXPECT_TRUE(greg.hasPendingUpdate());
458     PaintAggregator::PendingUpdate update;
459     greg.popPendingUpdate(&update);
460 
461     EXPECT_FALSE(update.scrollRect.isEmpty());
462     EXPECT_EQ(1U, update.paintRects.size());
463 
464     EXPECT_EQ(scrollRect, update.scrollRect);
465     EXPECT_EQ(expectedScrollDamage, update.calculateScrollDamage());
466     EXPECT_EQ(expectedPaintRect, update.paintRects[0]);
467 }
468 
TEST(PaintAggregator,ContainedPaintAfterScrollEliminatedByScrollDamage)469 TEST(PaintAggregator, ContainedPaintAfterScrollEliminatedByScrollDamage)
470 {
471     PaintAggregator greg;
472 
473     IntRect scrollRect(0, 0, 10, 10);
474     greg.scrollRect(4, 0, scrollRect);
475 
476     IntRect paintRect(2, 0, 2, 10);
477     greg.invalidateRect(paintRect);
478 
479     IntRect expectedScrollDamage(0, 0, 4, 10);
480 
481     EXPECT_TRUE(greg.hasPendingUpdate());
482     PaintAggregator::PendingUpdate update;
483     greg.popPendingUpdate(&update);
484 
485     EXPECT_FALSE(update.scrollRect.isEmpty());
486     EXPECT_TRUE(update.paintRects.isEmpty());
487 
488     EXPECT_EQ(scrollRect, update.scrollRect);
489     EXPECT_EQ(expectedScrollDamage, update.calculateScrollDamage());
490 }
491 
492 } // namespace
493