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
38using namespace blink;
39
40namespace {
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
69TEST(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
127TEST(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
221TEST(GraphicsContextTest, trackImageMask)
222{
223    SkBitmap bitmap;
224    bitmap.allocN32Pixels(400, 400);
225    bitmap.eraseColor(0);
226    SkCanvas canvas(bitmap);
227
228    GraphicsContext context(&canvas);
229    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
230
231    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
232    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
233
234    // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
235    // out a transparency layer below that is filled with the mask color. In the end this should
236    // not be marked opaque.
237
238    context.setCompositeOperation(CompositeSourceOver);
239    context.beginTransparencyLayer(1);
240    context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
241
242    context.setCompositeOperation(CompositeDestinationIn);
243    context.beginTransparencyLayer(1);
244
245    OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
246    EXPECT_FALSE(!alphaImage);
247    alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
248
249    context.setCompositeOperation(CompositeSourceOver);
250    context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
251
252    context.endLayer();
253    context.endLayer();
254
255    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
256    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
257}
258
259TEST(GraphicsContextTest, trackImageMaskWithOpaqueRect)
260{
261    SkBitmap bitmap;
262    bitmap.allocN32Pixels(400, 400);
263    bitmap.eraseColor(0);
264    SkCanvas canvas(bitmap);
265
266    GraphicsContext context(&canvas);
267    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
268
269    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
270    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
271
272    // Image masks are done by drawing a bitmap into a transparency layer that uses DstIn to mask
273    // out a transparency layer below that is filled with the mask color. In the end this should
274    // not be marked opaque.
275
276    context.setCompositeOperation(CompositeSourceOver);
277    context.beginTransparencyLayer(1);
278    context.fillRect(FloatRect(10, 10, 10, 10), opaque, CompositeSourceOver);
279
280    context.setCompositeOperation(CompositeDestinationIn);
281    context.beginTransparencyLayer(1);
282
283    OwnPtr<ImageBuffer> alphaImage = ImageBuffer::create(IntSize(100, 100));
284    EXPECT_FALSE(!alphaImage);
285    alphaImage->context()->fillRect(IntRect(0, 0, 100, 100), alpha);
286
287    context.setCompositeOperation(CompositeSourceOver);
288    context.drawImageBuffer(alphaImage.get(), FloatRect(10, 10, 10, 10));
289
290    // We can't have an opaque mask actually, but we can pretend here like it would look if we did.
291    context.fillRect(FloatRect(12, 12, 3, 3), opaque, CompositeSourceOver);
292
293    context.endLayer();
294    context.endLayer();
295
296    EXPECT_EQ_RECT(IntRect(12, 12, 3, 3), context.opaqueRegion().asRect());
297    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
298}
299
300TEST(GraphicsContextTest, trackOpaqueJoinTest)
301{
302    SkBitmap bitmap;
303    bitmap.allocN32Pixels(400, 400);
304    SkCanvas canvas(bitmap);
305
306    GraphicsContext context(&canvas);
307    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
308
309    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
310    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
311
312    context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
313    EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
314    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
315
316    // Doesn't join
317    context.fillRect(FloatRect(31, 20, 10, 10), opaque, CompositeSourceOver);
318    EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
319    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
320
321    // Does join
322    context.fillRect(FloatRect(30, 20, 10, 10), opaque, CompositeSourceOver);
323    EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
324    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
325
326    // Doesn't join
327    context.fillRect(FloatRect(20, 31, 20, 10), opaque, CompositeSourceOver);
328    EXPECT_EQ_RECT(IntRect(20, 20, 20, 10), context.opaqueRegion().asRect());
329    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
330
331    // Does join
332    context.fillRect(FloatRect(20, 30, 20, 10), opaque, CompositeSourceOver);
333    EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
334    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
335
336    // Doesn't join
337    context.fillRect(FloatRect(9, 20, 10, 20), opaque, CompositeSourceOver);
338    EXPECT_EQ_RECT(IntRect(20, 20, 20, 20), context.opaqueRegion().asRect());
339    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
340
341    // Does join
342    context.fillRect(FloatRect(10, 20, 10, 20), opaque, CompositeSourceOver);
343    EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
344    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
345
346    // Doesn't join
347    context.fillRect(FloatRect(10, 9, 30, 10), opaque, CompositeSourceOver);
348    EXPECT_EQ_RECT(IntRect(10, 20, 30, 20), context.opaqueRegion().asRect());
349    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
350
351    // Does join
352    context.fillRect(FloatRect(10, 10, 30, 10), opaque, CompositeSourceOver);
353    EXPECT_EQ_RECT(IntRect(10, 10, 30, 30), context.opaqueRegion().asRect());
354    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
355}
356
357TEST(GraphicsContextTest, trackOpaqueLineTest)
358{
359    SkBitmap bitmap;
360    bitmap.allocN32Pixels(200, 200);
361    bitmap.eraseColor(0);
362    SkCanvas canvas(bitmap);
363
364    GraphicsContext context(&canvas);
365    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
366
367    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
368    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
369
370    context.setShouldAntialias(false);
371    context.setMiterLimit(0);
372    context.setStrokeThickness(4);
373    context.setLineCap(SquareCap);
374    context.setStrokeStyle(SolidStroke);
375    context.setCompositeOperation(CompositeSourceOver);
376
377    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
378    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
379    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
380
381    context.setCompositeOperation(CompositeSourceIn);
382
383    context.save();
384    context.setStrokeColor(alpha);
385    context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
386    context.restore();
387    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
388    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
389
390    context.save();
391    context.setStrokeColor(opaque);
392    context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
393    context.restore();
394    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
395    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
396
397    context.save();
398    context.setStrokeColor(alpha);
399    context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
400    context.restore();
401    EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
402    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
403
404    context.save();
405    context.setStrokeColor(alpha);
406    context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
407    context.restore();
408    EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
409    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
410
411    context.setShouldAntialias(true);
412    context.setCompositeOperation(CompositeSourceOver);
413
414    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
415    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
416    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
417
418    context.setCompositeOperation(CompositeSourceIn);
419
420    context.save();
421    context.setStrokeColor(alpha);
422    context.drawLine(IntPoint(0, 0), IntPoint(100, 0));
423    context.restore();
424    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
425    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
426
427    context.setShouldAntialias(false);
428    context.save();
429    context.setStrokeColor(opaque);
430    context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
431    context.restore();
432    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
433    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
434
435    context.setShouldAntialias(true);
436    context.save();
437    context.setStrokeColor(opaque);
438    context.drawLine(IntPoint(0, 10), IntPoint(100, 10));
439    context.restore();
440    EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
441    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
442
443    context.save();
444    context.setStrokeColor(alpha);
445    context.drawLine(IntPoint(0, 11), IntPoint(100, 11));
446    context.restore();
447    EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
448    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
449}
450
451TEST(GraphicsContextTest, trackOpaquePathTest)
452{
453    SkBitmap bitmap;
454    bitmap.allocN32Pixels(200, 200);
455    SkCanvas canvas(bitmap);
456
457    GraphicsContext context(&canvas);
458    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
459
460    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
461    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
462
463    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
464    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
465    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
466
467    context.setShouldAntialias(false);
468    context.setMiterLimit(1);
469    context.setStrokeThickness(5);
470    context.setLineCap(SquareCap);
471    context.setStrokeStyle(SolidStroke);
472    context.setCompositeOperation(CompositeSourceIn);
473
474    Path path;
475
476    context.setFillColor(alpha);
477    path.moveTo(FloatPoint(0, 0));
478    path.addLineTo(FloatPoint(100, 0));
479    context.fillPath(path);
480    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
481    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
482    path.clear();
483
484    context.setFillColor(opaque);
485    path.moveTo(FloatPoint(0, 10));
486    path.addLineTo(FloatPoint(100, 13));
487    context.fillPath(path);
488    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
489    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
490    path.clear();
491
492    context.setFillColor(alpha);
493    path.moveTo(FloatPoint(0, 10));
494    path.addLineTo(FloatPoint(100, 13));
495    context.fillPath(path);
496    EXPECT_EQ_RECT(IntRect(10, 13, 90, 87), context.opaqueRegion().asRect());
497    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
498    path.clear();
499
500    context.setFillColor(alpha);
501    path.moveTo(FloatPoint(0, 14));
502    path.addLineTo(FloatPoint(100, 10));
503    context.fillPath(path);
504    EXPECT_EQ_RECT(IntRect(10, 14, 90, 86), context.opaqueRegion().asRect());
505    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
506    path.clear();
507}
508
509TEST(GraphicsContextTest, trackOpaqueImageTest)
510{
511    SkBitmap bitmap;
512    bitmap.allocN32Pixels(200, 200);
513    SkCanvas canvas(bitmap);
514
515    GraphicsContext context(&canvas);
516    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
517
518    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
519    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
520
521    SkBitmap opaqueBitmap;
522    opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */);
523
524    for (int y = 0; y < opaqueBitmap.height(); ++y)
525        for (int x = 0; x < opaqueBitmap.width(); ++x)
526            *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
527    RefPtr<BitmapImage> opaqueImage = BitmapImage::create(NativeImageSkia::create(opaqueBitmap));
528    EXPECT_TRUE(opaqueImage->currentFrameKnownToBeOpaque());
529
530    SkBitmap alphaBitmap;
531    alphaBitmap.allocN32Pixels(10, 10);
532
533    for (int y = 0; y < alphaBitmap.height(); ++y)
534        for (int x = 0; x < alphaBitmap.width(); ++x)
535            *alphaBitmap.getAddr32(x, y) = 0x00000000;
536    RefPtr<BitmapImage> alphaImage = BitmapImage::create(NativeImageSkia::create(alphaBitmap));
537    EXPECT_FALSE(alphaImage->currentFrameKnownToBeOpaque());
538
539    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
540    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
541    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
542
543    context.drawImage(opaqueImage.get(), IntPoint(0, 0));
544    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
545    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
546    context.drawImage(alphaImage.get(), IntPoint(0, 0));
547    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
548    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
549
550    context.drawImage(opaqueImage.get(), IntPoint(5, 5));
551    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
552    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
553    context.drawImage(alphaImage.get(), IntPoint(5, 5));
554    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
555    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
556
557    context.drawImage(opaqueImage.get(), IntPoint(10, 10));
558    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
559    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
560    context.drawImage(alphaImage.get(), IntPoint(10, 10));
561    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
562    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
563
564    context.drawImage(alphaImage.get(), IntPoint(20, 10), CompositeSourceIn);
565    EXPECT_EQ_RECT(IntRect(10, 20, 90, 80), context.opaqueRegion().asRect());
566    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
567
568    context.save();
569    context.setAlphaAsFloat(0.5);
570    context.drawImage(opaqueImage.get(), IntPoint(25, 15), CompositeSourceIn);
571    context.restore();
572    EXPECT_EQ_RECT(IntRect(10, 25, 90, 75), context.opaqueRegion().asRect());
573    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
574
575    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
576    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
577    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
578
579    context.drawImage(alphaImage.get(), IntPoint(10, 20), CompositeSourceIn);
580    EXPECT_EQ_RECT(IntRect(20, 10, 80, 90), context.opaqueRegion().asRect());
581    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
582
583    context.save();
584    context.setAlphaAsFloat(0.5);
585    context.drawImage(opaqueImage.get(), IntPoint(15, 25), CompositeSourceIn);
586    context.restore();
587    EXPECT_EQ_RECT(IntRect(25, 10, 75, 90), context.opaqueRegion().asRect());
588    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
589}
590
591TEST(GraphicsContextTest, trackOpaqueOvalTest)
592{
593    SkBitmap bitmap;
594    bitmap.allocN32Pixels(200, 200);
595    bitmap.eraseColor(0);
596    SkCanvas canvas(bitmap);
597
598    GraphicsContext context(&canvas);
599    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
600
601    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
602    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
603
604    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
605    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
606
607    context.fillEllipse(FloatRect(10, 10, 90, 90));
608    context.strokeEllipse(FloatRect(10, 10, 90, 90));
609    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
610    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
611
612    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
613    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
614    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
615
616    context.setCompositeOperation(CompositeSourceIn);
617
618    context.setShouldAntialias(false);
619
620    context.setFillColor(opaque);
621    context.fillEllipse(FloatRect(10, 10, 50, 30));
622    context.strokeEllipse(FloatRect(10, 10, 50, 30));
623    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
624    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
625
626    context.setFillColor(alpha);
627    context.fillEllipse(FloatRect(10, 10, 30, 50));
628    context.strokeEllipse(FloatRect(10, 10, 30, 50));
629    EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
630    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
631
632    context.setShouldAntialias(true);
633
634    context.setFillColor(opaque);
635    context.fillEllipse(FloatRect(10, 10, 50, 30));
636    context.strokeEllipse(FloatRect(10, 10, 50, 30));
637    EXPECT_EQ_RECT(IntRect(40, 41, 60, 59), context.opaqueRegion().asRect());
638    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
639
640    context.setFillColor(alpha);
641    context.fillEllipse(FloatRect(20, 10, 30, 50));
642    context.strokeEllipse(FloatRect(20, 10, 30, 50));
643    EXPECT_EQ_RECT(IntRect(51, 41, 49, 59), context.opaqueRegion().asRect());
644    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
645}
646
647TEST(GraphicsContextTest, trackOpaqueRoundedRectTest)
648{
649    SkBitmap bitmap;
650    bitmap.allocN32Pixels(200, 200);
651    SkCanvas canvas(bitmap);
652
653    GraphicsContext context(&canvas);
654    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
655
656    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
657    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
658    IntSize radii(10, 10);
659
660    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
661    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
662
663    context.fillRoundedRect(IntRect(10, 10, 90, 90), radii, radii, radii, radii, opaque);
664    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
665    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
666
667    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
668    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
669    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
670
671    context.setCompositeOperation(CompositeSourceIn);
672    context.setShouldAntialias(false);
673
674    context.fillRoundedRect(IntRect(10, 10, 50, 30), radii, radii, radii, radii, opaque);
675    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
676    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
677
678    context.fillRoundedRect(IntRect(10, 10, 30, 50), radii, radii, radii, radii, alpha);
679    EXPECT_EQ_RECT(IntRect(40, 10, 60, 90), context.opaqueRegion().asRect());
680    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
681
682    context.fillRoundedRect(IntRect(10, 0, 50, 30), radii, radii, radii, radii, alpha);
683    EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
684    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
685
686    context.fillRoundedRect(IntRect(30, 0, 70, 50), radii, radii, radii, radii, opaque);
687    EXPECT_EQ_RECT(IntRect(40, 30, 60, 70), context.opaqueRegion().asRect());
688    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
689}
690
691TEST(GraphicsContextTest, trackOpaqueTextTest)
692{
693    int width = 200, height = 200;
694    SkBitmap bitmap;
695    bitmap.allocN32Pixels(width, height);
696    bitmap.eraseColor(0);
697    SkCanvas canvas(bitmap);
698    SkRect textRect = SkRect::MakeWH(width, height);
699
700    GraphicsContext context(&canvas);
701    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
702
703    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
704    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
705
706    SkPaint opaquePaint;
707    opaquePaint.setColor(opaque.rgb());
708    opaquePaint.setXfermodeMode(SkXfermode::kSrc_Mode);
709    SkPaint alphaPaint;
710    alphaPaint.setColor(alpha.rgb());
711    alphaPaint.setXfermodeMode(SkXfermode::kSrc_Mode);
712
713    SkPoint point = SkPoint::Make(0, 0);
714
715    context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
716    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
717    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
718
719    context.drawPosText("A", 1, &point, textRect, opaquePaint);
720    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
721    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
722
723    context.drawPosText("A", 1, &point, textRect, alphaPaint);
724    EXPECT_EQ_RECT(IntRect(0, 0, 0, 0), context.opaqueRegion().asRect());
725    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
726
727    context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
728    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
729    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
730
731    context.fillRect(FloatRect(50, 50, 50, 50), opaque, CompositeSourceOver);
732    EXPECT_EQ_RECT(IntRect(50, 50, 50, 50), context.opaqueRegion().asRect());
733    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
734}
735
736TEST(GraphicsContextTest, trackOpaqueWritePixelsTest)
737{
738    SkBitmap bitmap;
739    bitmap.allocN32Pixels(200, 200);
740    bitmap.eraseColor(0);
741    SkCanvas canvas(bitmap);
742
743    GraphicsContext context(&canvas);
744    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
745
746    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
747
748    SkBitmap opaqueBitmap;
749    opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */);
750    for (int y = 0; y < opaqueBitmap.height(); ++y)
751        for (int x = 0; x < opaqueBitmap.width(); ++x)
752            *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
753
754    SkBitmap alphaBitmap;
755    alphaBitmap.allocN32Pixels(10, 10);
756    for (int y = 0; y < alphaBitmap.height(); ++y)
757        for (int x = 0; x < alphaBitmap.width(); ++x)
758            *alphaBitmap.getAddr32(x, y) = 0x00000000;
759
760    SkPaint paint;
761    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
762
763    context.writePixels(opaqueBitmap, 50, 50);
764    EXPECT_EQ_RECT(IntRect(50, 50, 10, 10), context.opaqueRegion().asRect());
765    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
766
767    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
768    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
769    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
770
771    context.writePixels(alphaBitmap, 10, 0);
772    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
773    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
774
775    context.writePixels(alphaBitmap, 10, 1);
776    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
777    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
778
779    context.writePixels(alphaBitmap, 0, 10);
780    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
781    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
782
783    context.writePixels(alphaBitmap, 1, 10);
784    EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
785    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
786}
787
788TEST(GraphicsContextTest, trackOpaqueDrawBitmapTest)
789{
790    SkBitmap bitmap;
791    bitmap.allocN32Pixels(200, 200);
792    bitmap.eraseColor(0);
793    SkCanvas canvas(bitmap);
794
795    GraphicsContext context(&canvas);
796    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
797
798    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
799
800    SkBitmap opaqueBitmap;
801    opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */);
802    for (int y = 0; y < opaqueBitmap.height(); ++y)
803        for (int x = 0; x < opaqueBitmap.width(); ++x)
804            *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
805
806    SkBitmap alphaBitmap;
807    alphaBitmap.allocN32Pixels(10, 10);
808    for (int y = 0; y < alphaBitmap.height(); ++y)
809        for (int x = 0; x < alphaBitmap.width(); ++x)
810            *alphaBitmap.getAddr32(x, y) = 0x00000000;
811
812    SkPaint paint;
813    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
814
815    context.drawBitmap(opaqueBitmap, 10, 10, &paint);
816    EXPECT_EQ_RECT(IntRect(10, 10, 10, 10), context.opaqueRegion().asRect());
817    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
818
819    context.fillRect(FloatRect(10, 10, 90, 90), opaque, CompositeSourceOver);
820    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
821    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
822
823    context.drawBitmap(alphaBitmap, 10, 0, &paint);
824    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
825    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
826
827    context.drawBitmap(alphaBitmap, 10, 1, &paint);
828    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
829    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
830
831    context.drawBitmap(alphaBitmap, 0, 10, &paint);
832    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
833    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
834
835    context.drawBitmap(alphaBitmap, 1, 10, &paint);
836    EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
837    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
838}
839
840TEST(GraphicsContextTest, trackOpaqueDrawBitmapRectTest)
841{
842    SkBitmap bitmap;
843    bitmap.allocN32Pixels(200, 200);
844    bitmap.eraseColor(0);
845    SkCanvas canvas(bitmap);
846
847    GraphicsContext context(&canvas);
848    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
849
850    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
851
852    SkBitmap opaqueBitmap;
853    opaqueBitmap.allocN32Pixels(10, 10, true /* opaque */);
854    for (int y = 0; y < opaqueBitmap.height(); ++y)
855        for (int x = 0; x < opaqueBitmap.width(); ++x)
856            *opaqueBitmap.getAddr32(x, y) = 0xFFFFFFFF;
857
858    SkBitmap alphaBitmap;
859    alphaBitmap.allocN32Pixels(10, 10);
860    for (int y = 0; y < alphaBitmap.height(); ++y)
861        for (int x = 0; x < alphaBitmap.width(); ++x)
862            *alphaBitmap.getAddr32(x, y) = 0x00000000;
863
864    SkPaint paint;
865    paint.setXfermodeMode(SkXfermode::kSrc_Mode);
866
867    context.drawBitmapRect(opaqueBitmap, 0, SkRect::MakeXYWH(10, 10, 90, 90), &paint);
868    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
869    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
870
871    context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 10), &paint);
872    EXPECT_EQ_RECT(IntRect(10, 10, 90, 90), context.opaqueRegion().asRect());
873    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
874
875    context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(10, 0, 10, 11), &paint);
876    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
877    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
878
879    context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 10, 10), &paint);
880    EXPECT_EQ_RECT(IntRect(10, 11, 90, 89), context.opaqueRegion().asRect());
881    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
882
883    context.drawBitmapRect(alphaBitmap, 0, SkRect::MakeXYWH(0, 10, 11, 10), &paint);
884    EXPECT_EQ_RECT(IntRect(11, 11, 89, 89), context.opaqueRegion().asRect());
885    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
886}
887
888TEST(GraphicsContextTest, contextTransparencyLayerTest)
889{
890    SkBitmap bitmap;
891    bitmap.allocN32Pixels(400, 400);
892    bitmap.eraseColor(0);
893    SkCanvas canvas(bitmap);
894
895    GraphicsContext context(&canvas);
896    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
897
898    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
899    context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
900    EXPECT_EQ_RECT(IntRect(20, 20, 10, 10), context.opaqueRegion().asRect());
901    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
902
903    context.clearRect(FloatRect(20, 20, 10, 10));
904    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
905
906    context.beginTransparencyLayer(0.5);
907    context.save();
908    context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
909    context.restore();
910    context.endLayer();
911    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
912
913    context.clearRect(FloatRect(20, 20, 10, 10));
914    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
915
916    context.beginTransparencyLayer(0.5);
917    context.fillRect(FloatRect(20, 20, 10, 10), opaque, CompositeSourceOver);
918    context.endLayer();
919    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
920}
921
922TEST(GraphicsContextTest, UnboundedDrawsAreClipped)
923{
924    SkBitmap bitmap;
925    bitmap.allocN32Pixels(400, 400);
926    bitmap.eraseColor(0);
927    SkCanvas canvas(bitmap);
928
929    GraphicsContext context(&canvas);
930    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
931
932    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
933    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
934
935    Path path;
936    context.setShouldAntialias(false);
937    context.setMiterLimit(1);
938    context.setStrokeThickness(5);
939    context.setLineCap(SquareCap);
940    context.setStrokeStyle(SolidStroke);
941
942    // Make skia unable to compute fast bounds for our paths.
943    DashArray dashArray;
944    dashArray.append(1);
945    dashArray.append(0);
946    context.setLineDash(dashArray, 0);
947
948    // Make the device opaque in 10,10 40x40.
949    context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
950    EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
951    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
952
953    // Clip to the left edge of the opaque area.
954    context.clip(IntRect(10, 10, 10, 40));
955
956    // Draw a path that gets clipped. This should destroy the opaque area but only inside the clip.
957    context.setCompositeOperation(CompositeSourceOut);
958    context.setFillColor(alpha);
959    path.moveTo(FloatPoint(10, 10));
960    path.addLineTo(FloatPoint(40, 40));
961    context.strokePath(path);
962
963    EXPECT_EQ_RECT(IntRect(20, 10, 30, 40), context.opaqueRegion().asRect());
964    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
965}
966
967TEST(GraphicsContextTest, PreserveOpaqueOnlyMattersForFirstLayer)
968{
969    SkBitmap bitmap;
970    bitmap.allocN32Pixels(400, 400);
971    bitmap.eraseColor(0);
972    SkCanvas canvas(bitmap);
973
974    GraphicsContext context(&canvas);
975    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
976
977    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
978    Color alpha(0.0f, 0.0f, 0.0f, 0.0f);
979
980    Path path;
981    context.setShouldAntialias(false);
982    context.setMiterLimit(1);
983    context.setStrokeThickness(5);
984    context.setLineCap(SquareCap);
985    context.setStrokeStyle(SolidStroke);
986
987    // Make skia unable to compute fast bounds for our paths.
988    DashArray dashArray;
989    dashArray.append(1);
990    dashArray.append(0);
991    context.setLineDash(dashArray, 0);
992
993    // Make the device opaque in 10,10 40x40.
994    context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
995    EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
996    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
997
998    // Begin a layer that preserves opaque.
999    context.setCompositeOperation(CompositeSourceOver);
1000    context.beginTransparencyLayer(0.5);
1001
1002    // Begin a layer that does not preserve opaque.
1003    context.setCompositeOperation(CompositeSourceOut);
1004    context.beginTransparencyLayer(0.5);
1005
1006    // This should not destroy the device opaqueness.
1007    context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
1008
1009    // This should not destroy the device opaqueness either.
1010    context.setFillColor(opaque);
1011    path.moveTo(FloatPoint(10, 10));
1012    path.addLineTo(FloatPoint(40, 40));
1013    context.strokePath(path);
1014
1015    context.endLayer();
1016    context.endLayer();
1017    EXPECT_EQ_RECT(IntRect(10, 10, 40, 40), context.opaqueRegion().asRect());
1018    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1019
1020    // Now begin a layer that does not preserve opaque and draw through it to the device.
1021    context.setCompositeOperation(CompositeSourceOut);
1022    context.beginTransparencyLayer(0.5);
1023
1024    // This should destroy the device opaqueness.
1025    context.fillRect(FloatRect(10, 10, 40, 40), opaque, CompositeSourceOver);
1026
1027    context.endLayer();
1028    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1029    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1030
1031    // Now we draw with a path for which it cannot compute fast bounds. This should destroy the entire opaque region.
1032
1033    context.setCompositeOperation(CompositeSourceOut);
1034    context.beginTransparencyLayer(0.5);
1035
1036    // This should nuke the device opaqueness.
1037    context.setFillColor(opaque);
1038    path.moveTo(FloatPoint(10, 10));
1039    path.addLineTo(FloatPoint(40, 40));
1040    context.strokePath(path);
1041
1042    context.endLayer();
1043    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1044    EXPECT_PIXELS_MATCH_EXACT(bitmap, context.opaqueRegion().asRect());
1045}
1046
1047TEST(GraphicsContextTest, OpaqueRegionForLayerWithNonRectDeviceClip)
1048{
1049    SkBitmap bitmap;
1050    bitmap.allocN32Pixels(100, 100);
1051    bitmap.eraseColor(0);
1052    SkCanvas canvas(bitmap);
1053
1054    GraphicsContext context(&canvas);
1055    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
1056    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
1057
1058    context.fillRect(FloatRect(30, 30, 90, 90), opaque, CompositeSourceOver);
1059
1060    context.setCompositeOperation(CompositeSourceOver);
1061    context.beginTransparencyLayer(0.5);
1062    context.endLayer();
1063    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), context.opaqueRegion().asRect());
1064
1065    Path path;
1066    path.moveTo(FloatPoint(0, 0));
1067    path.addLineTo(FloatPoint(50, 50));
1068
1069    // For opaque preserving mode and deviceClip is not rect
1070    // we will not alter opaque rect.
1071    context.clipPath(path, RULE_EVENODD);
1072
1073    context.setCompositeOperation(CompositeSourceOver);
1074    context.beginTransparencyLayer(0.5);
1075    context.endLayer();
1076    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), context.opaqueRegion().asRect());
1077
1078    // For non-opaque preserving mode and deviceClip is not rect
1079    // we will mark opaque rect as empty.
1080    context.setCompositeOperation(CompositeSourceOut);
1081    context.beginTransparencyLayer(0.5);
1082
1083    context.endLayer();
1084    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1085}
1086
1087TEST(GraphicsContextTest, OpaqueRegionForLayerWithRectDeviceClip)
1088{
1089    SkBitmap bitmap;
1090    bitmap.allocN32Pixels(100, 100);
1091    bitmap.eraseColor(0);
1092    SkCanvas canvas(bitmap);
1093
1094    Color opaque(1.0f, 0.0f, 0.0f, 1.0f);
1095
1096    GraphicsContext context(&canvas);
1097    context.setRegionTrackingMode(GraphicsContext::RegionTrackingOpaque);
1098
1099    context.fillRect(FloatRect(30, 30, 90, 90), opaque, CompositeSourceOver);
1100    EXPECT_EQ_RECT(IntRect(30, 30, 70, 70), context.opaqueRegion().asRect());
1101
1102    // For non-opaque preserving mode and deviceClip is rect
1103    // we will mark device clip rect as non opaque.
1104    context.setCompositeOperation(CompositeSourceOut);
1105    context.beginTransparencyLayer(0.5);
1106    context.endLayer();
1107    EXPECT_EQ_RECT(IntRect(), context.opaqueRegion().asRect());
1108    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
1109
1110    context.clip(FloatRect(0, 0, 50, 50));
1111    context.fillRect(FloatRect(20, 20, 100, 100), opaque, CompositeSourceOver);
1112
1113    // For opaque preserving mode and deviceClip is rect
1114    // we will intersect device clip rect with src opaque rect.
1115    context.setCompositeOperation(CompositeSourceOver);
1116    context.beginTransparencyLayer(0.5);
1117    context.endLayer();
1118    EXPECT_EQ_RECT(IntRect(20, 20, 30, 30), context.opaqueRegion().asRect());
1119    EXPECT_PIXELS_MATCH(bitmap, context.opaqueRegion().asRect());
1120}
1121
1122#define DISPATCH1(c1, c2, op, param1) do { c1.op(param1); c2.op(param1); } while (0);
1123#define DISPATCH2(c1, c2, op, param1, param2) do { c1.op(param1, param2); c2.op(param1, param2); } while (0);
1124
1125TEST(GraphicsContextTest, RecordingTotalMatrix)
1126{
1127    SkBitmap bitmap;
1128    bitmap.allocN32Pixels(400, 400);
1129    bitmap.eraseColor(0);
1130    SkCanvas canvas(bitmap);
1131    GraphicsContext context(&canvas);
1132
1133    SkCanvas controlCanvas(400, 400);
1134    GraphicsContext controlContext(&controlCanvas);
1135
1136    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1137    DISPATCH2(context, controlContext, scale, 2, 2);
1138    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1139
1140    controlContext.save();
1141    context.beginRecording(FloatRect(0, 0, 200, 200));
1142    DISPATCH2(context, controlContext, translate, 10, 10);
1143    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1144
1145    controlContext.save();
1146    context.beginRecording(FloatRect(10, 10, 100, 100));
1147    DISPATCH1(context, controlContext, rotate, 45);
1148    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1149
1150    controlContext.restore();
1151    context.endRecording();
1152    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1153
1154    controlContext.restore();
1155    context.endRecording();
1156    EXPECT_EQ(context.getCTM(), controlContext.getCTM());
1157}
1158
1159TEST(GraphicsContextTest, RecordingCanvas)
1160{
1161    SkBitmap bitmap;
1162    bitmap.allocN32Pixels(1, 1);
1163    bitmap.eraseColor(0);
1164    SkCanvas canvas(bitmap);
1165    GraphicsContext context(&canvas);
1166
1167    FloatRect rect(0, 0, 1, 1);
1168
1169    // Two beginRecordings in a row generate two canvases.
1170    // Unfortunately the new one could be allocated in the same
1171    // spot as the old one so ref the first one to prolong its life.
1172    context.beginRecording(rect);
1173    SkCanvas* canvas1 = context.canvas();
1174    EXPECT_TRUE(canvas1);
1175    context.beginRecording(rect);
1176    SkCanvas* canvas2 = context.canvas();
1177    EXPECT_TRUE(canvas2);
1178
1179    EXPECT_NE(canvas1, canvas2);
1180    EXPECT_EQ(1, canvas1->getRefCnt());
1181
1182    // endRecording finally makes the picture accessible
1183    RefPtr<DisplayList> dl = context.endRecording();
1184    SkPicture* pic = dl->picture();
1185    EXPECT_TRUE(pic);
1186    EXPECT_EQ(1, pic->getRefCnt());
1187
1188    context.endRecording();
1189}
1190
1191} // namespace
1192