Upstream version 11.40.277.0
[platform/framework/web/crosswalk.git] / src / third_party / WebKit / Source / platform / graphics / GraphicsContextTest.cpp
1 /*
2  * Copyright (C) 2012 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
6  * are met:
7  * 1.  Redistributions of source code must retain the above copyright
8  *     notice, this list of conditions and the following disclaimer.
9  * 2.  Redistributions in binary form must reproduce the above copyright
10  *     notice, this list of conditions and the following disclaimer in the
11  *     documentation and/or other materials provided with the distribution.
12  *
13  * THIS SOFTWARE IS PROVIDED BY APPLE INC. AND ITS CONTRIBUTORS ``AS IS'' AND ANY
14  * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
15  * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
16  * DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR ITS CONTRIBUTORS BE LIABLE FOR ANY
17  * DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
18  * (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
19  * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON
20  * ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
21  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
22  * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
23  */
24
25 #include "config.h"
26
27 #include "platform/graphics/GraphicsContext.h"
28
29 #include "platform/graphics/BitmapImage.h"
30 #include "platform/graphics/DisplayList.h"
31 #include "platform/graphics/ImageBuffer.h"
32 #include "platform/graphics/skia/NativeImageSkia.h"
33 #include "third_party/skia/include/core/SkBitmap.h"
34 #include "third_party/skia/include/core/SkCanvas.h"
35 #include "third_party/skia/include/core/SkPicture.h"
36 #include <gtest/gtest.h>
37
38 using namespace blink;
39
40 namespace {
41
42 #define EXPECT_EQ_RECT(a, b) \
43     EXPECT_EQ(a.x(), b.x()); \
44     EXPECT_EQ(a.y(), b.y()); \
45     EXPECT_EQ(a.width(), b.width()); \
46     EXPECT_EQ(a.height(), b.height());
47
48 #define EXPECT_PIXELS_MATCH(bitmap, opaqueRect) \
49 { \
50     SkAutoLockPixels locker(bitmap); \
51     for (int y = opaqueRect.y(); y < opaqueRect.maxY(); ++y) \
52         for (int x = opaqueRect.x(); x < opaqueRect.maxX(); ++x) { \
53             int alpha = *bitmap.getAddr32(x, y) >> 24; \
54             EXPECT_EQ(255, alpha); \
55         } \
56 }
57
58 #define EXPECT_PIXELS_MATCH_EXACT(bitmap, opaqueRect) \
59 { \
60     SkAutoLockPixels locker(bitmap); \
61     for (int y = 0; y < bitmap.height(); ++y) \
62         for (int x = 0; x < bitmap.width(); ++x) {     \
63             int alpha = *bitmap.getAddr32(x, y) >> 24; \
64             bool opaque = opaqueRect.contains(x, y); \
65             EXPECT_EQ(opaque, alpha == 255); \
66         } \
67 }
68
69 TEST(GraphicsContextTest, trackOpaqueTest)
70 {
71     SkBitmap bitmap;
72     bitmap.allocN32Pixels(400, 400);
73     bitmap.eraseColor(0);
74     SkCanvas canvas(bitmap);
75
76     GraphicsContext context(&canvas);
77     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
78
79     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
80     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
81
82     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
83     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
84     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
85
86     context.fillRect(FloatRect(10, 10, 90, 90), alpha, CompositeSourceOver);
87     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
88     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
89
90     context.fillRect(FloatRect(99, 13, 10, 90), opaque, CompositePlusLighter);
91     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
92     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
93
94     context.fillRect(FloatRect(99, 13, 10, 90), opaque, CompositeSourceIn);
95     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
96     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
97
98     context.fillRect(FloatRect(99, 13, 10, 90), alpha, CompositeSourceIn);
99     EXPECT_EQ_RECT(IntRect(10, 10, 89, 90), context.opaqueRegion().asRect());
100     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
101
102     context.fillRect(FloatRect(8, 8, 3, 90), opaque, CompositeSourceOut);
103     EXPECT_EQ_RECT(IntRect(11, 10, 88, 90), context.opaqueRegion().asRect());
104     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
105
106     context.fillRect(FloatRect(30, 30, 290, 290), opaque, CompositeSourceOver);
107     EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
108     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
109
110     context.fillRect(FloatRect(40, 20, 290, 50), opaque, CompositeSourceOver);
111     EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
112     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
113
114     context.fillRect(FloatRect(10, 10, 390, 50), opaque, CompositeSourceIn);
115     EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
116     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
117
118     context.fillRect(FloatRect(10, 10, 390, 50), alpha);
119     EXPECT_EQ_RECT(IntRect(30, 30, 290, 290), context.opaqueRegion().asRect());
120     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
121
122     context.fillRect(FloatRect(10, 10, 390, 50), opaque, CompositeSourceOver);
123     EXPECT_EQ_RECT(IntRect(30, 10, 290, 310), context.opaqueRegion().asRect());
124     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
125 }
126
127 TEST(GraphicsContextTest, trackOpaqueClipTest)
128 {
129     SkBitmap bitmap;
130     bitmap.allocN32Pixels(400, 400);
131     SkCanvas canvas(bitmap);
132
133     GraphicsContext context(&canvas);
134     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
135
136     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
137     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
138
139     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
140     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
141     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
142
143     context.clearRect(FloatRect(10, 10, 90, 90));
144     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
145
146     context.save();
147     context.clip(FloatRect(0, 0, 10, 10));
148     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
149     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
150     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
151     context.restore();
152
153     context.clearRect(FloatRect(10, 10, 90, 90));
154     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
155
156     context.save();
157     context.clip(FloatRect(20, 20, 10, 10));
158     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
159     EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
160     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
161
162     context.clearRect(FloatRect(10, 10, 90, 90));
163     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
164
165     // The intersection of the two clips becomes empty.
166     context.clip(FloatRect(30, 20, 10, 10));
167     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
168     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
169     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
170     context.restore();
171
172     context.clearRect(FloatRect(10, 10, 90, 90));
173     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
174
175     // The transform and the clip need to interact correctly (transform first)
176     context.save();
177     context.translate(10, 10);
178     context.clip(FloatRect(20, 20, 10, 10));
179     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
180     EXPECT_EQ_RECT(IntRect(30, 30, 10, 10), context.opaqueRegion().asRect());
181     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
182     context.restore();
183
184     context.clearRect(FloatRect(10, 10, 90, 90));
185     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
186
187     // The transform and the clip need to interact correctly (clip first)
188     context.save();
189     context.clip(FloatRect(20, 20, 10, 10));
190     context.translate(10, 10);
191     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
192     EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
193     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
194     context.restore();
195
196     context.clearRect(FloatRect(10, 10, 90, 90));
197     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
198
199     Path path;
200     path.moveTo(FloatPoint(0, 0));
201     path.addLineTo(FloatPoint(100, 0));
202
203     // Non-rectangular clips just cause the paint to be considered non-opaque.
204     context.save();
205     context.clipPath(path, RULE_EVENODD);
206     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
207     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
208     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
209     context.restore();
210
211     // Another non-rectangular clip.
212     context.save();
213     context.clip(IntRect(30, 30, 20, 20));
214     context.clipOut(IntRect(30, 30, 10, 10));
215     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
216     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
217     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
218     context.restore();
219 }
220
221 TEST(GraphicsContextTest, trackDisplayListRecording)
222 {
223     SkBitmap bitmap;
224     bitmap.allocN32Pixels(100, 100);
225     SkCanvas canvas(bitmap);
226
227     GraphicsContext context(&canvas);
228     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
229
230     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
231
232     context.fillRect(FloatRect(0, 0, 50, 50), opaque, CompositeSourceOver);
233     EXPECT_EQ_RECT(IntRect(0, 0, 50, 50), context.opaqueRegion().asRect());
234     FloatRect bounds(0, 0, 100, 100);
235     context.beginRecording(bounds);
236     context.fillRect(FloatRect(0, 0, 100, 100), opaque, CompositeSourceOver);
237     RefPtr<DisplayList> displayList = context.endRecording();
238
239     // Make sure the opaque region was unaffected by the rect drawn during DisplayList recording.
240     EXPECT_EQ_RECT(IntRect(0, 0, 50, 50), context.opaqueRegion().asRect());
241
242     // Make sure the opaque region *is* affected (reset) by drawing the DisplayList itself.
243     context.drawDisplayList(displayList.get());
244     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
245 }
246
247 TEST(GraphicsContextTest, trackImageMask)
248 {
249     SkBitmap bitmap;
250     bitmap.allocN32Pixels(400, 400);
251     bitmap.eraseColor(0);
252     SkCanvas canvas(bitmap);
253
254     GraphicsContext context(&canvas);
255     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
256
257     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
258     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
259
260     // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
261     // out a transparency layer below that is filled with the mask color. In the end this should
262     // not be marked opaque.
263
264     context.setCompositeOperation(CompositeSourceOver);
265     context.beginTransparencyLayer(1);
266     context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
267
268     context.setCompositeOperation(CompositeDestinationIn);
269     context.beginTransparencyLayer(1);
270
271     OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
272     EXPECT_FALSE(!alphaImage);
273     alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
274
275     context.setCompositeOperation(CompositeSourceOver);
276     context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
277
278     context.endLayer();
279     context.endLayer();
280
281     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
282     EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
283 }
284
285 TEST(GraphicsContextTest, trackImageMaskWithOpaqueRect)
286 {
287     SkBitmap bitmap;
288     bitmap.allocN32Pixels(400, 400);
289     bitmap.eraseColor(0);
290     SkCanvas canvas(bitmap);
291
292     GraphicsContext context(&canvas);
293     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
294
295     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
296     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
297
298     // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
299     // out a transparency layer below that is filled with the mask color. In the end this should
300     // not be marked opaque.
301
302     context.setCompositeOperation(CompositeSourceOver);
303     context.beginTransparencyLayer(1);
304     context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
305
306     context.setCompositeOperation(CompositeDestinationIn);
307     context.beginTransparencyLayer(1);
308
309     OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
310     EXPECT_FALSE(!alphaImage);
311     alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
312
313     context.setCompositeOperation(CompositeSourceOver);
314     context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
315
316     // We can't have an opaque mask actually, but we can pretend here like it would look if we did.
317     context.fillRect(FloatRect(12, 12, 3, 3), opaque, CompositeSourceOver);
318
319     context.endLayer();
320     context.endLayer();
321
322     EXPECT_EQ_RECT(IntRect(12, 12, 3, 3), context.opaqueRegion().asRect());
323     EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
324 }
325
326 TEST(GraphicsContextTest, trackOpaqueJoinTest)
327 {
328     SkBitmap bitmap;
329     bitmap.allocN32Pixels(400, 400);
330     SkCanvas canvas(bitmap);
331
332     GraphicsContext context(&canvas);
333     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
334
335     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
336     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
337
338     context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
339     EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
340     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
341
342     // Doesn't join
343     context.fillRect(FloatRect(31, 20, 10, 10), opaque, CompositeSourceOver);
344     EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
345     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
346
347     // Does join
348     context.fillRect(FloatRect(30, 20, 10, 10), opaque, CompositeSourceOver);
349     EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
350     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
351
352     // Doesn't join
353     context.fillRect(FloatRect(20, 31, 20, 10), opaque, CompositeSourceOver);
354     EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
355     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
356
357     // Does join
358     context.fillRect(FloatRect(20, 30, 20, 10), opaque, CompositeSourceOver);
359     EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
360     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
361
362     // Doesn't join
363     context.fillRect(FloatRect(9, 20, 10, 20), opaque, CompositeSourceOver);
364     EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
365     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
366
367     // Does join
368     context.fillRect(FloatRect(10, 20, 10, 20), opaque, CompositeSourceOver);
369     EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
370     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
371
372     // Doesn't join
373     context.fillRect(FloatRect(10, 9, 30, 10), opaque, CompositeSourceOver);
374     EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
375     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
376
377     // Does join
378     context.fillRect(FloatRect(10, 10, 30, 10), opaque, CompositeSourceOver);
379     EXPECT_EQ_RECT(IntRect(10, 10, 30, 30), context.opaqueRegion().asRect());
380     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
381 }
382
383 TEST(GraphicsContextTest, trackOpaqueLineTest)
384 {
385     SkBitmap bitmap;
386     bitmap.allocN32Pixels(200, 200);
387     bitmap.eraseColor(0);
388     SkCanvas canvas(bitmap);
389
390     GraphicsContext context(&canvas);
391     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
392
393     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
394     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
395
396     context.setShouldAntialias(false);
397     context.setMiterLimit(0);
398     context.setStrokeThickness(4);
399     context.setLineCap(SquareCap);
400     context.setStrokeStyle(SolidStroke);
401     context.setCompositeOperation(CompositeSourceOver);
402
403     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
404     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
405     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
406
407     context.setCompositeOperation(CompositeSourceIn);
408
409     context.save();
410     context.setStrokeColor(alpha);
411     context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
412     context.restore();
413     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
414     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
415
416     context.save();
417     context.setStrokeColor(opaque);
418     context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
419     context.restore();
420     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
421     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
422
423     context.save();
424     context.setStrokeColor(alpha);
425     context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
426     context.restore();
427     EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
428     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
429
430     context.save();
431     context.setStrokeColor(alpha);
432     context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
433     context.restore();
434     EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
435     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
436
437     context.setShouldAntialias(true);
438     context.setCompositeOperation(CompositeSourceOver);
439
440     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
441     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
442     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
443
444     context.setCompositeOperation(CompositeSourceIn);
445
446     context.save();
447     context.setStrokeColor(alpha);
448     context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
449     context.restore();
450     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
451     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
452
453     context.setShouldAntialias(false);
454     context.save();
455     context.setStrokeColor(opaque);
456     context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
457     context.restore();
458     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
459     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
460
461     context.setShouldAntialias(true);
462     context.save();
463     context.setStrokeColor(opaque);
464     context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
465     context.restore();
466     EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
467     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
468
469     context.save();
470     context.setStrokeColor(alpha);
471     context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
472     context.restore();
473     EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
474     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
475 }
476
477 TEST(GraphicsContextTest, trackOpaquePathTest)
478 {
479     SkBitmap bitmap;
480     bitmap.allocN32Pixels(200, 200);
481     SkCanvas canvas(bitmap);
482
483     GraphicsContext context(&canvas);
484     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
485
486     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
487     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
488
489     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
490     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
491     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
492
493     context.setShouldAntialias(false);
494     context.setMiterLimit(1);
495     context.setStrokeThickness(5);
496     context.setLineCap(SquareCap);
497     context.setStrokeStyle(SolidStroke);
498     context.setCompositeOperation(CompositeSourceIn);
499
500     Path path;
501
502     context.setFillColor(alpha);
503     path.moveTo(FloatPoint(0, 0));
504     path.addLineTo(FloatPoint(100, 0));
505     context.fillPath(path);
506     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
507     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
508     path.clear();
509
510     context.setFillColor(opaque);
511     path.moveTo(FloatPoint(0, 10));
512     path.addLineTo(FloatPoint(100, 13));
513     context.fillPath(path);
514     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
515     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
516     path.clear();
517
518     context.setFillColor(alpha);
519     path.moveTo(FloatPoint(0, 10));
520     path.addLineTo(FloatPoint(100, 13));
521     context.fillPath(path);
522     EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
523     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
524     path.clear();
525
526     context.setFillColor(alpha);
527     path.moveTo(FloatPoint(0, 14));
528     path.addLineTo(FloatPoint(100, 10));
529     context.fillPath(path);
530     EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
531     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
532     path.clear();
533 }
534
535 TEST(GraphicsContextTest, trackOpaqueImageTest)
536 {
537     SkBitmap bitmap;
538     bitmap.allocN32Pixels(200, 200);
539     SkCanvas canvas(bitmap);
540
541     GraphicsContext context(&canvas);
542     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
543
544     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
545     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
546
547     SkBitmap opaqueBitmap;
548     opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */);
549
550     for (int y = 0; y < opaqueBitmap.height(); ++y)
551         for (int x = 0; x < opaqueBitmap.width(); ++x)
552             *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
553     RefPtr<BitmapImage> opaqueImage = BitmapImage::create(NativeImageSkia::create(opaqueBitmap));
554     EXPECT_TRUE(opaqueImage->currentFrameKnownToBeOpaque());
555
556     SkBitmap alphaBitmap;
557     alphaBitmap.allocN32Pixels(10, 10);
558
559     for (int y = 0; y < alphaBitmap.height(); ++y)
560         for (int x = 0; x < alphaBitmap.width(); ++x)
561             *alphaBitmap.getAddr32(x, y) = 0x00000000;
562     RefPtr<BitmapImage> alphaImage = BitmapImage::create(NativeImageSkia::create(alphaBitmap));
563     EXPECT_FALSE(alphaImage->currentFrameKnownToBeOpaque());
564
565     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
566     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
567     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
568
569     context.drawImage(opaqueImage.get(), IntPoint(0, 0));
570     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
571     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
572     context.drawImage(alphaImage.get(), IntPoint(0, 0));
573     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
574     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
575
576     context.drawImage(opaqueImage.get(), IntPoint(5, 5));
577     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
578     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
579     context.drawImage(alphaImage.get(), IntPoint(5, 5));
580     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
581     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
582
583     context.drawImage(opaqueImage.get(), IntPoint(10, 10));
584     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
585     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
586     context.drawImage(alphaImage.get(), IntPoint(10, 10));
587     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
588     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
589
590     context.drawImage(alphaImage.get(), IntPoint(20, 10), CompositeSourceIn);
591     EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), context.opaqueRegion().asRect());
592     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
593
594     context.save();
595     context.setAlphaAsFloat(0.5);
596     context.drawImage(opaqueImage.get(), IntPoint(25, 15), CompositeSourceIn);
597     context.restore();
598     EXPECT_EQ_RECT(IntRect(10, 25, 90, 75), context.opaqueRegion().asRect());
599     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
600
601     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
602     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
603     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
604
605     context.drawImage(alphaImage.get(), IntPoint(10, 20), CompositeSourceIn);
606     EXPECT_EQ_RECT(IntRect(20, 10, 80, 90), context.opaqueRegion().asRect());
607     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
608
609     context.save();
610     context.setAlphaAsFloat(0.5);
611     context.drawImage(opaqueImage.get(), IntPoint(15, 25), CompositeSourceIn);
612     context.restore();
613     EXPECT_EQ_RECT(IntRect(25, 10, 75, 90), context.opaqueRegion().asRect());
614     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
615 }
616
617 TEST(GraphicsContextTest, trackOpaqueOvalTest)
618 {
619     SkBitmap bitmap;
620     bitmap.allocN32Pixels(200, 200);
621     bitmap.eraseColor(0);
622     SkCanvas canvas(bitmap);
623
624     GraphicsContext context(&canvas);
625     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
626
627     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
628     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
629
630     EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
631     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
632
633     context.fillEllipse(FloatRect(10, 10, 90, 90));
634     context.strokeEllipse(FloatRect(10, 10, 90, 90));
635     EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
636     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
637
638     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
639     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
640     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
641
642     context.setCompositeOperation(CompositeSourceIn);
643
644     context.setShouldAntialias(false);
645
646     context.setFillColor(opaque);
647     context.fillEllipse(FloatRect(10, 10, 50, 30));
648     context.strokeEllipse(FloatRect(10, 10, 50, 30));
649     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
650     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
651
652     context.setFillColor(alpha);
653     context.fillEllipse(FloatRect(10, 10, 30, 50));
654     context.strokeEllipse(FloatRect(10, 10, 30, 50));
655     EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
656     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
657
658     context.setShouldAntialias(true);
659
660     context.setFillColor(opaque);
661     context.fillEllipse(FloatRect(10, 10, 50, 30));
662     context.strokeEllipse(FloatRect(10, 10, 50, 30));
663     EXPECT_EQ_RECT(IntRect(40, 41, 60, 59), context.opaqueRegion().asRect());
664     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
665
666     context.setFillColor(alpha);
667     context.fillEllipse(FloatRect(20, 10, 30, 50));
668     context.strokeEllipse(FloatRect(20, 10, 30, 50));
669     EXPECT_EQ_RECT(IntRect(51, 41, 49, 59), context.opaqueRegion().asRect());
670     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
671 }
672
673 TEST(GraphicsContextTest, trackOpaqueRoundedRectTest)
674 {
675     SkBitmap bitmap;
676     bitmap.allocN32Pixels(200, 200);
677     SkCanvas canvas(bitmap);
678
679     GraphicsContext context(&canvas);
680     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
681
682     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
683     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
684     IntSize radii(10, 10);
685
686     EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
687     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
688
689     context.fillRoundedRect(IntRect(10, 10, 90, 90), radii, radii, radii, radii, opaque);
690     EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
691     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
692
693     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
694     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
695     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
696
697     context.setCompositeOperation(CompositeSourceIn);
698     context.setShouldAntialias(false);
699
700     context.fillRoundedRect(IntRect(10, 10, 50, 30), radii, radii, radii, radii, opaque);
701     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
702     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
703
704     context.fillRoundedRect(IntRect(10, 10, 30, 50), radii, radii, radii, radii, alpha);
705     EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
706     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
707
708     context.fillRoundedRect(IntRect(10, 0, 50, 30), radii, radii, radii, radii, alpha);
709     EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
710     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
711
712     context.fillRoundedRect(IntRect(30, 0, 70, 50), radii, radii, radii, radii, opaque);
713     EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
714     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
715 }
716
717 TEST(GraphicsContextTest, trackOpaqueTextTest)
718 {
719     int width = 200, height = 200;
720     SkBitmap bitmap;
721     bitmap.allocN32Pixels(width, height);
722     bitmap.eraseColor(0);
723     SkCanvas canvas(bitmap);
724     SkRect textRect = SkRect::MakeWH(width, height);
725
726     GraphicsContext context(&canvas);
727     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
728
729     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
730     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
731
732     SkPaint opaquePaint;
733     opaquePaint.setColor(opaque.rgb());
734     opaquePaint.setXfermodeMode(SkXfermode::kSrc_Mode);
735     SkPaint alphaPaint;
736     alphaPaint.setColor(alpha.rgb());
737     alphaPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
738
739     SkPoint point = SkPoint::Make(0, 0);
740
741     context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
742     EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
743     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
744
745     context.drawPosText("A", 1, &point, textRect, opaquePaint);
746     EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
747     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
748
749     context.drawPosText("A", 1, &point, textRect, alphaPaint);
750     EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
751     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
752
753     context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
754     EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
755     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
756
757     context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
758     EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
759     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
760 }
761
762 static inline void writePixels(GraphicsContext* context, const SkBitmap& bm, int x, int y)
763 {
764     SkAutoLockPixels locker(bm);
765     context->writePixels(bm.info(), bm.getPixels(), bm.rowBytes(), x, y);
766 }
767
768 TEST(GraphicsContextTest, trackOpaqueWritePixelsTest)
769 {
770     SkBitmap bitmap;
771     bitmap.allocN32Pixels(200, 200);
772     bitmap.eraseColor(0);
773     SkCanvas canvas(bitmap);
774
775     GraphicsContext context(&canvas);
776     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
777
778     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
779
780     SkBitmap opaqueBitmap;
781     opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */);
782     for (int y = 0; y < opaqueBitmap.height(); ++y)
783         for (int x = 0; x < opaqueBitmap.width(); ++x)
784             *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
785
786     SkBitmap alphaBitmap;
787     alphaBitmap.allocN32Pixels(10, 10);
788     for (int y = 0; y < alphaBitmap.height(); ++y)
789         for (int x = 0; x < alphaBitmap.width(); ++x)
790             *alphaBitmap.getAddr32(x, y) = 0x00000000;
791
792     SkPaint paint;
793     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
794
795     writePixels(&context, opaqueBitmap, 50, 50);
796     EXPECT_EQ_RECT(IntRect(50, 50, 10, 10), context.opaqueRegion().asRect());
797     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
798
799     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
800     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
801     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
802
803     writePixels(&context, alphaBitmap, 10, 0);
804     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
805     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
806
807     writePixels(&context, alphaBitmap, 10, 1);
808     EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
809     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
810
811     writePixels(&context, alphaBitmap, 0, 10);
812     EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
813     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
814
815     writePixels(&context, alphaBitmap, 1, 10);
816     EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
817     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
818 }
819
820 TEST(GraphicsContextTest, trackOpaqueDrawBitmapTest)
821 {
822     SkBitmap bitmap;
823     bitmap.allocN32Pixels(200, 200);
824     bitmap.eraseColor(0);
825     SkCanvas canvas(bitmap);
826
827     GraphicsContext context(&canvas);
828     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
829
830     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
831
832     SkBitmap opaqueBitmap;
833     opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */);
834     for (int y = 0; y < opaqueBitmap.height(); ++y)
835         for (int x = 0; x < opaqueBitmap.width(); ++x)
836             *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
837
838     SkBitmap alphaBitmap;
839     alphaBitmap.allocN32Pixels(10, 10);
840     for (int y = 0; y < alphaBitmap.height(); ++y)
841         for (int x = 0; x < alphaBitmap.width(); ++x)
842             *alphaBitmap.getAddr32(x, y) = 0x00000000;
843
844     SkPaint paint;
845     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
846
847     context.drawBitmap(opaqueBitmap, 10, 10, &paint);
848     EXPECT_EQ_RECT(IntRect(10, 10, 10, 10), context.opaqueRegion().asRect());
849     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
850
851     context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
852     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
853     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
854
855     context.drawBitmap(alphaBitmap, 10, 0, &paint);
856     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
857     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
858
859     context.drawBitmap(alphaBitmap, 10, 1, &paint);
860     EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
861     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
862
863     context.drawBitmap(alphaBitmap, 0, 10, &paint);
864     EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
865     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
866
867     context.drawBitmap(alphaBitmap, 1, 10, &paint);
868     EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
869     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
870 }
871
872 TEST(GraphicsContextTest, trackOpaqueDrawBitmapRectTest)
873 {
874     SkBitmap bitmap;
875     bitmap.allocN32Pixels(200, 200);
876     bitmap.eraseColor(0);
877     SkCanvas canvas(bitmap);
878
879     GraphicsContext context(&canvas);
880     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
881
882     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
883
884     SkBitmap opaqueBitmap;
885     opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */);
886     for (int y = 0; y < opaqueBitmap.height(); ++y)
887         for (int x = 0; x < opaqueBitmap.width(); ++x)
888             *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
889
890     SkBitmap alphaBitmap;
891     alphaBitmap.allocN32Pixels(10, 10);
892     for (int y = 0; y < alphaBitmap.height(); ++y)
893         for (int x = 0; x < alphaBitmap.width(); ++x)
894             *alphaBitmap.getAddr32(x, y) = 0x00000000;
895
896     SkPaint paint;
897     paint.setXfermodeMode(SkXfermode::kSrc_Mode);
898
899     context.drawBitmapRect(opaqueBitmap, 0, SkRect::MakeXYWH(10, 10, 90, 90), &paint);
900     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
901     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
902
903     context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 10), &paint);
904     EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
905     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
906
907     context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 11), &paint);
908     EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
909     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
910
911     context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 10, 10), &paint);
912     EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
913     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
914
915     context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 11, 10), &paint);
916     EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
917     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
918 }
919
920 TEST(GraphicsContextTest, contextTransparencyLayerTest)
921 {
922     SkBitmap bitmap;
923     bitmap.allocN32Pixels(400, 400);
924     bitmap.eraseColor(0);
925     SkCanvas canvas(bitmap);
926
927     GraphicsContext context(&canvas);
928     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
929
930     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
931     context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
932     EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
933     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
934
935     context.clearRect(FloatRect(20, 20, 10, 10));
936     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
937
938     context.beginTransparencyLayer(0.5);
939     context.save();
940     context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
941     context.restore();
942     context.endLayer();
943     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
944
945     context.clearRect(FloatRect(20, 20, 10, 10));
946     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
947
948     context.beginTransparencyLayer(0.5);
949     context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
950     context.endLayer();
951     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
952 }
953
954 TEST(GraphicsContextTest, UnboundedDrawsAreClipped)
955 {
956     SkBitmap bitmap;
957     bitmap.allocN32Pixels(400, 400);
958     bitmap.eraseColor(0);
959     SkCanvas canvas(bitmap);
960
961     GraphicsContext context(&canvas);
962     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
963
964     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
965     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
966
967     Path path;
968     context.setShouldAntialias(false);
969     context.setMiterLimit(1);
970     context.setStrokeThickness(5);
971     context.setLineCap(SquareCap);
972     context.setStrokeStyle(SolidStroke);
973
974     // Make skia unable to compute fast bounds for our paths.
975     DashArray dashArray;
976     dashArray.append(1);
977     dashArray.append(0);
978     context.setLineDash(dashArray, 0);
979
980     // Make the device opaque in 10,10 40x40.
981     context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
982     EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
983     EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
984
985     // Clip to the left edge of the opaque area.
986     context.clip(IntRect(10, 10, 10, 40));
987
988     // Draw a path that gets clipped. This should destroy the opaque area but only inside the clip.
989     context.setCompositeOperation(CompositeSourceOut);
990     context.setFillColor(alpha);
991     path.moveTo(FloatPoint(10, 10));
992     path.addLineTo(FloatPoint(40, 40));
993     context.strokePath(path);
994
995     EXPECT_EQ_RECT(IntRect(20, 10, 30, 40), context.opaqueRegion().asRect());
996     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
997 }
998
999 TEST(GraphicsContextTest, PreserveOpaqueOnlyMattersForFirstLayer)
1000 {
1001     SkBitmap bitmap;
1002     bitmap.allocN32Pixels(400, 400);
1003     bitmap.eraseColor(0);
1004     SkCanvas canvas(bitmap);
1005
1006     GraphicsContext context(&canvas);
1007     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
1008
1009     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
1010     Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
1011
1012     Path path;
1013     context.setShouldAntialias(false);
1014     context.setMiterLimit(1);
1015     context.setStrokeThickness(5);
1016     context.setLineCap(SquareCap);
1017     context.setStrokeStyle(SolidStroke);
1018
1019     // Make skia unable to compute fast bounds for our paths.
1020     DashArray dashArray;
1021     dashArray.append(1);
1022     dashArray.append(0);
1023     context.setLineDash(dashArray, 0);
1024
1025     // Make the device opaque in 10,10 40x40.
1026     context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
1027     EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
1028     EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1029
1030     // Begin a layer that preserves opaque.
1031     context.setCompositeOperation(CompositeSourceOver);
1032     context.beginTransparencyLayer(0.5);
1033
1034     // Begin a layer that does not preserve opaque.
1035     context.setCompositeOperation(CompositeSourceOut);
1036     context.beginTransparencyLayer(0.5);
1037
1038     // This should not destroy the device opaqueness.
1039     context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
1040
1041     // This should not destroy the device opaqueness either.
1042     context.setFillColor(opaque);
1043     path.moveTo(FloatPoint(10, 10));
1044     path.addLineTo(FloatPoint(40, 40));
1045     context.strokePath(path);
1046
1047     context.endLayer();
1048     context.endLayer();
1049     EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
1050     EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1051
1052     // Now begin a layer that does not preserve opaque and draw through it to the device.
1053     context.setCompositeOperation(CompositeSourceOut);
1054     context.beginTransparencyLayer(0.5);
1055
1056     // This should destroy the device opaqueness.
1057     context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
1058
1059     context.endLayer();
1060     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1061     EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1062
1063     // Now we draw with a path for which it cannot compute fast bounds. This should destroy the entire opaque region.
1064
1065     context.setCompositeOperation(CompositeSourceOut);
1066     context.beginTransparencyLayer(0.5);
1067
1068     // This should nuke the device opaqueness.
1069     context.setFillColor(opaque);
1070     path.moveTo(FloatPoint(10, 10));
1071     path.addLineTo(FloatPoint(40, 40));
1072     context.strokePath(path);
1073
1074     context.endLayer();
1075     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1076     EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1077 }
1078
1079 TEST(GraphicsContextTest, OpaqueRegionForLayerWithNonRectDeviceClip)
1080 {
1081     SkBitmap bitmap;
1082     bitmap.allocN32Pixels(100, 100);
1083     bitmap.eraseColor(0);
1084     SkCanvas canvas(bitmap);
1085
1086     GraphicsContext context(&canvas);
1087     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
1088     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
1089
1090     context.fillRect(FloatRect(30, 30, 90, 90), opaque, CompositeSourceOver);
1091
1092     context.setCompositeOperation(CompositeSourceOver);
1093     context.beginTransparencyLayer(0.5);
1094     context.endLayer();
1095     EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), context.opaqueRegion().asRect());
1096
1097     Path path;
1098     path.moveTo(FloatPoint(0, 0));
1099     path.addLineTo(FloatPoint(50, 50));
1100
1101     // For opaque preserving mode and deviceClip is not rect
1102     // we will not alter opaque rect.
1103     context.clipPath(path, RULE_EVENODD);
1104
1105     context.setCompositeOperation(CompositeSourceOver);
1106     context.beginTransparencyLayer(0.5);
1107     context.endLayer();
1108     EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), context.opaqueRegion().asRect());
1109
1110     // For non-opaque preserving mode and deviceClip is not rect
1111     // we will mark opaque rect as empty.
1112     context.setCompositeOperation(CompositeSourceOut);
1113     context.beginTransparencyLayer(0.5);
1114
1115     context.endLayer();
1116     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1117 }
1118
1119 TEST(GraphicsContextTest, OpaqueRegionForLayerWithRectDeviceClip)
1120 {
1121     SkBitmap bitmap;
1122     bitmap.allocN32Pixels(100, 100);
1123     bitmap.eraseColor(0);
1124     SkCanvas canvas(bitmap);
1125
1126     Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
1127
1128     GraphicsContext context(&canvas);
1129     context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
1130
1131     context.fillRect(FloatRect(30, 30, 90, 90), opaque, CompositeSourceOver);
1132     EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), context.opaqueRegion().asRect());
1133
1134     // For non-opaque preserving mode and deviceClip is rect
1135     // we will mark device clip rect as non opaque.
1136     context.setCompositeOperation(CompositeSourceOut);
1137     context.beginTransparencyLayer(0.5);
1138     context.endLayer();
1139     EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1140     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
1141
1142     context.clip(FloatRect(0, 0, 50, 50));
1143     context.fillRect(FloatRect(20, 20, 100, 100), opaque, CompositeSourceOver);
1144
1145     // For opaque preserving mode and deviceClip is rect
1146     // we will intersect device clip rect with src opaque rect.
1147     context.setCompositeOperation(CompositeSourceOver);
1148     context.beginTransparencyLayer(0.5);
1149     context.endLayer();
1150     EXPECT_EQ_RECT(IntRect(20, 20, 30, 30), context.opaqueRegion().asRect());
1151     EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
1152 }
1153
1154 #define DISPATCH1(c1, c2, op, param1) do { c1.op(param1); c2.op(param1); } while (0);
1155 #define DISPATCH2(c1, c2, op, param1, param2) do { c1.op(param1, param2); c2.op(param1, param2); } while (0);
1156
1157 TEST(GraphicsContextTest, RecordingTotalMatrix)
1158 {
1159     SkBitmap bitmap;
1160     bitmap.allocN32Pixels(400, 400);
1161     bitmap.eraseColor(0);
1162     SkCanvas canvas(bitmap);
1163     GraphicsContext context(&canvas);
1164
1165     SkCanvas controlCanvas(400, 400);
1166     GraphicsContext controlContext(&controlCanvas);
1167
1168     EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1169     DISPATCH2(context, controlContext, scale, 2, 2);
1170     EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1171
1172     controlContext.save();
1173     context.beginRecording(FloatRect(0, 0, 200, 200));
1174     DISPATCH2(context, controlContext, translate, 10, 10);
1175     EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1176
1177     controlContext.save();
1178     context.beginRecording(FloatRect(10, 10, 100, 100));
1179     DISPATCH1(context, controlContext, rotate, 45);
1180     EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1181
1182     controlContext.restore();
1183     context.endRecording();
1184     EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1185
1186     controlContext.restore();
1187     context.endRecording();
1188     EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1189 }
1190
1191 TEST(GraphicsContextTest, RecordingCanvas)
1192 {
1193     SkBitmap bitmap;
1194     bitmap.allocN32Pixels(1, 1);
1195     bitmap.eraseColor(0);
1196     SkCanvas canvas(bitmap);
1197     GraphicsContext context(&canvas);
1198
1199     FloatRect rect(0, 0, 1, 1);
1200
1201     // Two beginRecordings in a row generate two canvases.
1202     // Unfortunately the new one could be allocated in the same
1203     // spot as the old one so ref the first one to prolong its life.
1204     context.beginRecording(rect);
1205     SkCanvas* canvas1 = context.canvas();
1206     EXPECT_TRUE(canvas1);
1207     context.beginRecording(rect);
1208     SkCanvas* canvas2 = context.canvas();
1209     EXPECT_TRUE(canvas2);
1210
1211     EXPECT_NE(canvas1, canvas2);
1212     EXPECT_EQ(1, canvas1->getRefCnt());
1213
1214     // endRecording finally makes the picture accessible
1215     RefPtr<DisplayList> dl = context.endRecording();
1216     SkPicture* pic = dl->picture().get();
1217     EXPECT_TRUE(pic);
1218     EXPECT_EQ(1, pic->getRefCnt());
1219
1220     context.endRecording();
1221 }
1222
1223 } // namespace